From 93fa7636dfdc059b25df148f230c0991096afdef Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Tue, 8 Apr 2008 11:01:58 +0200 Subject: [PATCH 0001/5416] x86, ptrace: PEBS support Polish the ds.h interface and add support for PEBS. Ds.c is meant to be the resource allocator for per-thread and per-cpu BTS and PEBS recording. It is used by ptrace/utrace to provide execution tracing of debugged tasks. It will be used by profilers (e.g. perfmon2). It may be used by kernel debuggers to provide a kernel execution trace. Changes in detail: - guard DS and ptrace by CONFIG macros - separate DS and BTS more clearly - simplify field accesses - add functions to manage PEBS buffers - add simple protection/allocation mechanism - added support for Atom Opens: - buffer overflow handling Currently, only circular buffers are supported. This is all we need for debugging. Profilers would want an overflow notification. This is planned to be added when perfmon2 is made to use the ds.h interface. - utrace intermediate layer Signed-off-by: Markus Metzger Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig.cpu | 18 + arch/x86/kernel/cpu/intel.c | 3 +- arch/x86/kernel/ds.c | 953 +++++++++++++++++++++++++---------- arch/x86/kernel/process_32.c | 25 +- arch/x86/kernel/process_64.c | 25 +- arch/x86/kernel/ptrace.c | 444 +++++++++------- arch/x86/kernel/setup_64.c | 3 +- include/asm-x86/ds.h | 258 ++++++++-- include/asm-x86/processor.h | 12 +- include/asm-x86/ptrace-abi.h | 14 +- include/asm-x86/ptrace.h | 38 +- 11 files changed, 1274 insertions(+), 519 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2ad6301849a..13f3f8bebfd 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -415,3 +415,21 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y depends on !(M586MMX || M586TSC || M586 || M486 || M386) + +config X86_DS + bool "Debug Store support" + default y + help + Add support for Debug Store. + This allows the kernel to provide a memory buffer to the hardware + to store various profiling and tracing events. + +config X86_PTRACE_BTS + bool "ptrace interface to Branch Trace Store" + default y + depends on (X86_DS && X86_DEBUGCTLMSR) + help + Add a ptrace interface to allow collecting an execution trace + of the traced task. + This collects control flow changes in a (cyclic) buffer and allows + debuggers to fill in the gaps and show an execution trace of the debuggee. diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index fe9224c51d3..cbffa2a25a1 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -222,10 +222,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); } if (cpu_has_bts) - ds_init_intel(c); + ptrace_bts_init_intel(c); } static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 11c11b8ec48..5b32b6d062b 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -2,26 +2,48 @@ * Debug Store support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger , Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger , 2007-2008 */ + +#ifdef CONFIG_X86_DS + #include #include #include #include +#include + + +/* + * The configuration for a particular DS hardware implementation. + */ +struct ds_configuration { + /* the size of the DS structure in bytes */ + unsigned char sizeof_ds; + /* the size of one pointer-typed field in the DS structure in bytes; + this covers the first 8 fields related to buffer management. */ + unsigned char sizeof_field; + /* the size of a BTS/PEBS record in bytes */ + unsigned char sizeof_rec[2]; +}; +static struct ds_configuration ds_cfg; /* @@ -44,378 +66,747 @@ * (interrupt occurs when write pointer passes interrupt pointer) * - value to which counter is reset following counter overflow * - * On later architectures, the last branch recording hardware uses - * 64bit pointers even in 32bit mode. - * - * - * Branch Trace Store (BTS) records store information about control - * flow changes. They at least provide the following information: - * - source linear address - * - destination linear address + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. * - * Netburst supported a predicated bit that had been dropped in later - * architectures. We do not suppor it. * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * - an offset giving the start of the respective region * - * In order to abstract from the actual DS and BTS layout, we describe - * the access to the relevant fields. - * Thanks to Andi Kleen for proposing this design. + * This offset is further used to index various arrays holding + * information for BTS and PEBS at the respective index. * - * The implementation, however, is not as general as it might seem. In - * order to stay somewhat simple and efficient, we assume an - * underlying unsigned type (mostly a pointer type) and we expect the - * field to be at least as big as that type. + * On later 32bit processors, we only access the lower 32bit of the + * 64bit pointer fields. The upper halves will be zeroed out. */ -/* - * A special from_ip address to indicate that the BTS record is an - * info record that needs to be interpreted or skipped. - */ -#define BTS_ESCAPE_ADDRESS (-1) +enum ds_field { + ds_buffer_base = 0, + ds_index, + ds_absolute_maximum, + ds_interrupt_threshold, +}; -/* - * A field access descriptor - */ -struct access_desc { - unsigned char offset; - unsigned char size; +enum ds_qualifier { + ds_bts = 0, + ds_pebs }; +static inline unsigned long ds_get(const unsigned char *base, + enum ds_qualifier qual, enum ds_field field) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + return *(unsigned long *)base; +} + +static inline void ds_set(unsigned char *base, enum ds_qualifier qual, + enum ds_field field, unsigned long value) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + (*(unsigned long *)base) = value; +} + + /* - * The configuration for a particular DS/BTS hardware implementation. + * Locking is done only for allocating BTS or PEBS resources and for + * guarding context and buffer memory allocation. + * + * Most functions require the current task to own the ds context part + * they are going to access. All the locking is done when validating + * access to the context. */ -struct ds_configuration { - /* the DS configuration */ - unsigned char sizeof_ds; - struct access_desc bts_buffer_base; - struct access_desc bts_index; - struct access_desc bts_absolute_maximum; - struct access_desc bts_interrupt_threshold; - /* the BTS configuration */ - unsigned char sizeof_bts; - struct access_desc from_ip; - struct access_desc to_ip; - /* BTS variants used to store additional information like - timestamps */ - struct access_desc info_type; - struct access_desc info_data; - unsigned long debugctl_mask; -}; +static spinlock_t ds_lock = __SPIN_LOCK_UNLOCKED(ds_lock); /* - * The global configuration used by the below accessor functions + * Validate that the current task is allowed to access the BTS/PEBS + * buffer of the parameter task. + * + * Returns 0, if access is granted; -Eerrno, otherwise. */ -static struct ds_configuration ds_cfg; +static inline int ds_validate_access(struct ds_context *context, + enum ds_qualifier qual) +{ + if (!context) + return -EPERM; + + if (context->owner[qual] == current) + return 0; + + return -EPERM; +} + /* - * Accessor functions for some DS and BTS fields using the above - * global ptrace_bts_cfg. + * We either support (system-wide) per-cpu or per-thread allocation. + * We distinguish the two based on the task_struct pointer, where a + * NULL pointer indicates per-cpu allocation for the current cpu. + * + * Allocations are use-counted. As soon as resources are allocated, + * further allocations must be of the same type (per-cpu or + * per-thread). We model this by counting allocations (i.e. the number + * of tracers of a certain type) for one type negatively: + * =0 no tracers + * >0 number of per-thread tracers + * <0 number of per-cpu tracers + * + * The below functions to get and put tracers and to check the + * allocation type require the ds_lock to be held by the caller. + * + * Tracers essentially gives the number of ds contexts for a certain + * type of allocation. */ -static inline unsigned long get_bts_buffer_base(char *base) +static long tracers; + +static inline void get_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_buffer_base.offset); + tracers += (task ? 1 : -1); } -static inline void set_bts_buffer_base(char *base, unsigned long value) + +static inline void put_tracer(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_buffer_base.offset)) = value; + tracers -= (task ? 1 : -1); } -static inline unsigned long get_bts_index(char *base) + +static inline int check_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_index.offset); + return (task ? (tracers >= 0) : (tracers <= 0)); } -static inline void set_bts_index(char *base, unsigned long value) + + +/* + * The DS context is either attached to a thread or to a cpu: + * - in the former case, the thread_struct contains a pointer to the + * attached context. + * - in the latter case, we use a static array of per-cpu context + * pointers. + * + * Contexts are use-counted. They are allocated on first access and + * deallocated when the last user puts the context. + * + * We distinguish between an allocating and a non-allocating get of a + * context: + * - the allocating get is used for requesting BTS/PEBS resources. It + * requires the caller to hold the global ds_lock. + * - the non-allocating get is used for all other cases. A + * non-existing context indicates an error. It acquires and releases + * the ds_lock itself for obtaining the context. + * + * A context and its DS configuration are allocated and deallocated + * together. A context always has a DS configuration of the + * appropriate size. + */ +static DEFINE_PER_CPU(struct ds_context *, system_context); + +#define this_system_context per_cpu(system_context, smp_processor_id()) + +/* + * Returns the pointer to the parameter task's context or to the + * system-wide context, if task is NULL. + * + * Increases the use count of the returned context, if not NULL. + */ +static inline struct ds_context *ds_get_context(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_index.offset)) = value; + struct ds_context *context; + + spin_lock(&ds_lock); + + context = (task ? task->thread.ds_ctx : this_system_context); + if (context) + context->count++; + + spin_unlock(&ds_lock); + + return context; } -static inline unsigned long get_bts_absolute_maximum(char *base) + +/* + * Same as ds_get_context, but allocates the context and it's DS + * structure, if necessary; returns NULL; if out of memory. + * + * pre: requires ds_lock to be held + */ +static inline struct ds_context *ds_alloc_context(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset); + struct ds_context **p_context = + (task ? &task->thread.ds_ctx : &this_system_context); + struct ds_context *context = *p_context; + + if (!context) { + context = kzalloc(sizeof(*context), GFP_KERNEL); + + if (!context) + return 0; + + context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + if (!context->ds) { + kfree(context); + return 0; + } + + *p_context = context; + + context->this = p_context; + context->task = task; + + if (task) + set_tsk_thread_flag(task, TIF_DS_AREA_MSR); + + if (!task || (task == current)) + wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0); + + get_tracer(task); + } + + context->count++; + + return context; } -static inline void set_bts_absolute_maximum(char *base, unsigned long value) + +/* + * Decreases the use count of the parameter context, if not NULL. + * Deallocates the context, if the use count reaches zero. + */ +static inline void ds_put_context(struct ds_context *context) { - (*(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset)) = value; + if (!context) + return; + + spin_lock(&ds_lock); + + if (--context->count) + goto out; + + *(context->this) = 0; + + if (context->task) + clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); + + if (!context->task || (context->task == current)) + wrmsrl(MSR_IA32_DS_AREA, 0); + + put_tracer(context->task); + + /* free any leftover buffers from tracers that did not + * deallocate them properly. */ + kfree(context->buffer[ds_bts]); + kfree(context->buffer[ds_pebs]); + kfree(context->ds); + kfree(context); + out: + spin_unlock(&ds_lock); } -static inline unsigned long get_bts_interrupt_threshold(char *base) + + +/* + * Handle a buffer overflow + * + * task: the task whose buffers are overflowing; + * NULL for a buffer overflow on the current cpu + * context: the ds context + * qual: the buffer type + */ +static void ds_overflow(struct task_struct *task, struct ds_context *context, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset); + if (!context) + return; + + if (context->callback[qual]) + (*context->callback[qual])(task); + + /* todo: do some more overflow handling */ } -static inline void set_bts_interrupt_threshold(char *base, unsigned long value) + + +/* + * Allocate a non-pageable buffer of the parameter size. + * Checks the memory and the locked memory rlimit. + * + * Returns the buffer, if successful; + * NULL, if out of memory or rlimit exceeded. + * + * size: the requested buffer size in bytes + * pages (out): if not NULL, contains the number of pages reserved + */ +static inline void *ds_allocate_buffer(size_t size, unsigned int *pages) { - (*(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset)) = value; + unsigned long rlim, vm, pgsz; + void *buffer; + + pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + pgsz; + if (rlim < vm) + return 0; + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + pgsz; + if (rlim < vm) + return 0; + + buffer = kzalloc(size, GFP_KERNEL); + if (!buffer) + return 0; + + current->mm->total_vm += pgsz; + current->mm->locked_vm += pgsz; + + if (pages) + *pages = pgsz; + + return buffer; } -static inline unsigned long get_from_ip(char *base) + +static int ds_request(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl, enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.from_ip.offset); + struct ds_context *context; + unsigned long buffer, adj; + const unsigned long alignment = (1 << 3); + int error = 0; + + if (!ds_cfg.sizeof_ds) + return -EOPNOTSUPP; + + /* we require some space to do alignment adjustments below */ + if (size < (alignment + ds_cfg.sizeof_rec[qual])) + return -EINVAL; + + /* buffer overflow notification is not yet implemented */ + if (ovfl) + return -EOPNOTSUPP; + + + spin_lock(&ds_lock); + + if (!check_tracer(task)) + return -EPERM; + + error = -ENOMEM; + context = ds_alloc_context(task); + if (!context) + goto out_unlock; + + error = -EALREADY; + if (context->owner[qual] == current) + goto out_unlock; + error = -EPERM; + if (context->owner[qual] != 0) + goto out_unlock; + context->owner[qual] = current; + + spin_unlock(&ds_lock); + + + error = -ENOMEM; + if (!base) { + base = ds_allocate_buffer(size, &context->pages[qual]); + if (!base) + goto out_release; + + context->buffer[qual] = base; + } + error = 0; + + context->callback[qual] = ovfl; + + /* adjust the buffer address and size to meet alignment + * constraints: + * - buffer is double-word aligned + * - size is multiple of record size + * + * We checked the size at the very beginning; we have enough + * space to do the adjustment. + */ + buffer = (unsigned long)base; + + adj = ALIGN(buffer, alignment) - buffer; + buffer += adj; + size -= adj; + + size /= ds_cfg.sizeof_rec[qual]; + size *= ds_cfg.sizeof_rec[qual]; + + ds_set(context->ds, qual, ds_buffer_base, buffer); + ds_set(context->ds, qual, ds_index, buffer); + ds_set(context->ds, qual, ds_absolute_maximum, buffer + size); + + if (ovfl) { + /* todo: select a suitable interrupt threshold */ + } else + ds_set(context->ds, qual, + ds_interrupt_threshold, buffer + size + 1); + + /* we keep the context until ds_release */ + return error; + + out_release: + context->owner[qual] = 0; + ds_put_context(context); + return error; + + out_unlock: + spin_unlock(&ds_lock); + ds_put_context(context); + return error; } -static inline void set_from_ip(char *base, unsigned long value) + +int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - (*(unsigned long *)(base + ds_cfg.from_ip.offset)) = value; + return ds_request(task, base, size, ovfl, ds_bts); } -static inline unsigned long get_to_ip(char *base) + +int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - return *(unsigned long *)(base + ds_cfg.to_ip.offset); + return ds_request(task, base, size, ovfl, ds_pebs); } -static inline void set_to_ip(char *base, unsigned long value) + +static int ds_release(struct task_struct *task, enum ds_qualifier qual) { - (*(unsigned long *)(base + ds_cfg.to_ip.offset)) = value; + struct ds_context *context; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + kfree(context->buffer[qual]); + context->buffer[qual] = 0; + + current->mm->total_vm -= context->pages[qual]; + current->mm->locked_vm -= context->pages[qual]; + context->pages[qual] = 0; + context->owner[qual] = 0; + + /* + * we put the context twice: + * once for the ds_get_context + * once for the corresponding ds_request + */ + ds_put_context(context); + out: + ds_put_context(context); + return error; } -static inline unsigned char get_info_type(char *base) + +int ds_release_bts(struct task_struct *task) { - return *(unsigned char *)(base + ds_cfg.info_type.offset); + return ds_release(task, ds_bts); } -static inline void set_info_type(char *base, unsigned char value) + +int ds_release_pebs(struct task_struct *task) { - (*(unsigned char *)(base + ds_cfg.info_type.offset)) = value; + return ds_release(task, ds_pebs); } -static inline unsigned long get_info_data(char *base) + +static int ds_get_index(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.info_data.offset); + struct ds_context *context; + unsigned long base, index; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + + error = ((index - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; } -static inline void set_info_data(char *base, unsigned long value) + +int ds_get_bts_index(struct task_struct *task, size_t *pos) { - (*(unsigned long *)(base + ds_cfg.info_data.offset)) = value; + return ds_get_index(task, pos, ds_bts); } +int ds_get_pebs_index(struct task_struct *task, size_t *pos) +{ + return ds_get_index(task, pos, ds_pebs); +} -int ds_allocate(void **dsp, size_t bts_size_in_bytes) +static int ds_get_end(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - size_t bts_size_in_records; - unsigned long bts; - void *ds; + struct ds_context *context; + unsigned long base, end; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); + + error = ((end - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +int ds_get_bts_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_bts); +} - if (bts_size_in_bytes < 0) - return -EINVAL; +int ds_get_pebs_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_pebs); +} - bts_size_in_records = - bts_size_in_bytes / ds_cfg.sizeof_bts; - bts_size_in_bytes = - bts_size_in_records * ds_cfg.sizeof_bts; +static int ds_access(struct task_struct *task, size_t index, + const void **record, enum ds_qualifier qual) +{ + struct ds_context *context; + unsigned long base, idx; + int error; - if (bts_size_in_bytes <= 0) + if (!record) return -EINVAL; - bts = (unsigned long)kzalloc(bts_size_in_bytes, GFP_KERNEL); + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - if (!bts) - return -ENOMEM; + base = ds_get(context->ds, qual, ds_buffer_base); + idx = base + (index * ds_cfg.sizeof_rec[qual]); - ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + error = -EINVAL; + if (idx > ds_get(context->ds, qual, ds_absolute_maximum)) + goto out; - if (!ds) { - kfree((void *)bts); - return -ENOMEM; - } - - set_bts_buffer_base(ds, bts); - set_bts_index(ds, bts); - set_bts_absolute_maximum(ds, bts + bts_size_in_bytes); - set_bts_interrupt_threshold(ds, bts + bts_size_in_bytes + 1); - - *dsp = ds; - return 0; + *record = (const void *)idx; + error = ds_cfg.sizeof_rec[qual]; + out: + ds_put_context(context); + return error; } -int ds_free(void **dsp) +int ds_access_bts(struct task_struct *task, size_t index, const void **record) { - if (*dsp) { - kfree((void *)get_bts_buffer_base(*dsp)); - kfree(*dsp); - *dsp = NULL; - } - return 0; + return ds_access(task, index, record, ds_bts); } -int ds_get_bts_size(void *ds) +int ds_access_pebs(struct task_struct *task, size_t index, const void **record) { - int size_in_bytes; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (!ds) - return 0; - - size_in_bytes = - get_bts_absolute_maximum(ds) - - get_bts_buffer_base(ds); - return size_in_bytes; + return ds_access(task, index, record, ds_pebs); } -int ds_get_bts_end(void *ds) +static int ds_write(struct task_struct *task, const void *record, size_t size, + enum ds_qualifier qual, int force) { - int size_in_bytes = ds_get_bts_size(ds); - - if (size_in_bytes <= 0) - return size_in_bytes; + struct ds_context *context; + int error; - return size_in_bytes / ds_cfg.sizeof_bts; -} + if (!record) + return -EINVAL; -int ds_get_bts_index(void *ds) -{ - int index_offset_in_bytes; + error = -EPERM; + context = ds_get_context(task); + if (!context) + goto out; - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; + if (!force) { + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + } - index_offset_in_bytes = - get_bts_index(ds) - - get_bts_buffer_base(ds); + error = 0; + while (size) { + unsigned long base, index, end, write_end, int_th; + unsigned long write_size, adj_write_size; + + /* + * write as much as possible without producing an + * overflow interrupt. + * + * interrupt_threshold must either be + * - bigger than absolute_maximum or + * - point to a record between buffer_base and absolute_maximum + * + * index points to a valid record. + */ + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + end = ds_get(context->ds, qual, ds_absolute_maximum); + int_th = ds_get(context->ds, qual, ds_interrupt_threshold); + + write_end = min(end, int_th); + + /* if we are already beyond the interrupt threshold, + * we fill the entire buffer */ + if (write_end <= index) + write_end = end; + + if (write_end <= index) + goto out; + + write_size = min((unsigned long) size, write_end - index); + memcpy((void *)index, record, write_size); + + record = (const char *)record + write_size; + size -= write_size; + error += write_size; + + adj_write_size = write_size / ds_cfg.sizeof_rec[qual]; + adj_write_size *= ds_cfg.sizeof_rec[qual]; + + /* zero out trailing bytes */ + memset((char *)index + write_size, 0, + adj_write_size - write_size); + index += adj_write_size; + + if (index >= end) + index = base; + ds_set(context->ds, qual, ds_index, index); + + if (index >= int_th) + ds_overflow(task, context, qual); + } - return index_offset_in_bytes / ds_cfg.sizeof_bts; + out: + ds_put_context(context); + return error; } -int ds_set_overflow(void *ds, int method) +int ds_write_bts(struct task_struct *task, const void *record, size_t size) { - switch (method) { - case DS_O_SIGNAL: - return -EOPNOTSUPP; - case DS_O_WRAP: - return 0; - default: - return -EINVAL; - } + return ds_write(task, record, size, ds_bts, /* force = */ 0); } -int ds_get_overflow(void *ds) +int ds_write_pebs(struct task_struct *task, const void *record, size_t size) { - return DS_O_WRAP; + return ds_write(task, record, size, ds_pebs, /* force = */ 0); } -int ds_clear(void *ds) +int ds_unchecked_write_bts(struct task_struct *task, + const void *record, size_t size) { - int bts_size = ds_get_bts_size(ds); - unsigned long bts_base; - - if (bts_size <= 0) - return bts_size; - - bts_base = get_bts_buffer_base(ds); - memset((void *)bts_base, 0, bts_size); - - set_bts_index(ds, bts_base); - return 0; + return ds_write(task, record, size, ds_bts, /* force = */ 1); } -int ds_read_bts(void *ds, int index, struct bts_struct *out) +int ds_unchecked_write_pebs(struct task_struct *task, + const void *record, size_t size) { - void *bts; + return ds_write(task, record, size, ds_pebs, /* force = */ 1); +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +static int ds_reset_or_clear(struct task_struct *task, + enum ds_qualifier qual, int clear) +{ + struct ds_context *context; + unsigned long base, end; + int error; - if (index < 0) - return -EINVAL; + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - if (index >= ds_get_bts_size(ds)) - return -EINVAL; + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); - bts = (void *)(get_bts_buffer_base(ds) + (index * ds_cfg.sizeof_bts)); + if (clear) + memset((void *)base, 0, end - base); - memset(out, 0, sizeof(*out)); - if (get_from_ip(bts) == BTS_ESCAPE_ADDRESS) { - out->qualifier = get_info_type(bts); - out->variant.jiffies = get_info_data(bts); - } else { - out->qualifier = BTS_BRANCH; - out->variant.lbr.from_ip = get_from_ip(bts); - out->variant.lbr.to_ip = get_to_ip(bts); - } + ds_set(context->ds, qual, ds_index, base); - return sizeof(*out);; + error = 0; + out: + ds_put_context(context); + return error; } -int ds_write_bts(void *ds, const struct bts_struct *in) +int ds_reset_bts(struct task_struct *task) { - unsigned long bts; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (ds_get_bts_size(ds) <= 0) - return -ENXIO; + return ds_reset_or_clear(task, ds_bts, /* clear = */ 0); +} - bts = get_bts_index(ds); +int ds_reset_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0); +} - memset((void *)bts, 0, ds_cfg.sizeof_bts); - switch (in->qualifier) { - case BTS_INVALID: - break; +int ds_clear_bts(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_bts, /* clear = */ 1); +} - case BTS_BRANCH: - set_from_ip((void *)bts, in->variant.lbr.from_ip); - set_to_ip((void *)bts, in->variant.lbr.to_ip); - break; +int ds_clear_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 1); +} - case BTS_TASK_ARRIVES: - case BTS_TASK_DEPARTS: - set_from_ip((void *)bts, BTS_ESCAPE_ADDRESS); - set_info_type((void *)bts, in->qualifier); - set_info_data((void *)bts, in->variant.jiffies); - break; +int ds_get_pebs_reset(struct task_struct *task, u64 *value) +{ + struct ds_context *context; + int error; - default: + if (!value) return -EINVAL; - } - bts = bts + ds_cfg.sizeof_bts; - if (bts >= get_bts_absolute_maximum(ds)) - bts = get_bts_buffer_base(ds); - set_bts_index(ds, bts); + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; - return ds_cfg.sizeof_bts; + *value = *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)); + + error = 0; + out: + ds_put_context(context); + return error; } -unsigned long ds_debugctl_mask(void) +int ds_set_pebs_reset(struct task_struct *task, u64 value) { - return ds_cfg.debugctl_mask; -} + struct ds_context *context; + int error; -#ifdef __i386__ -static const struct ds_configuration ds_cfg_netburst = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<2)|(1<<3) -}; + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; -static const struct ds_configuration ds_cfg_pentium_m = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<6)|(1<<7) + *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)) = value; + + error = 0; + out: + ds_put_context(context); + return error; +} + +static const struct ds_configuration ds_cfg_var = { + .sizeof_ds = sizeof(long) * 12, + .sizeof_field = sizeof(long), + .sizeof_rec[ds_bts] = sizeof(long) * 3, + .sizeof_rec[ds_pebs] = sizeof(long) * 10 }; -#endif /* _i386_ */ - -static const struct ds_configuration ds_cfg_core2 = { - .sizeof_ds = 9 * 8, - .bts_buffer_base = { 0, 8 }, - .bts_index = { 8, 8 }, - .bts_absolute_maximum = { 16, 8 }, - .bts_interrupt_threshold = { 24, 8 }, - .sizeof_bts = 3 * 8, - .from_ip = { 0, 8 }, - .to_ip = { 8, 8 }, - .info_type = { 8, 1 }, - .info_data = { 16, 8 }, - .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +static const struct ds_configuration ds_cfg_64 = { + .sizeof_ds = 8 * 12, + .sizeof_field = 8, + .sizeof_rec[ds_bts] = 8 * 3, + .sizeof_rec[ds_pebs] = 8 * 10 }; static inline void @@ -429,14 +820,13 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) switch (c->x86) { case 0x6: switch (c->x86_model) { -#ifdef __i386__ case 0xD: case 0xE: /* Pentium M */ - ds_configure(&ds_cfg_pentium_m); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ case 0xF: /* Core2 */ - ds_configure(&ds_cfg_core2); + case 0x1C: /* Atom */ + ds_configure(&ds_cfg_64); break; default: /* sorry, don't know about them */ @@ -445,13 +835,11 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; case 0xF: switch (c->x86_model) { -#ifdef __i386__ case 0x0: case 0x1: case 0x2: /* Netburst */ - ds_configure(&ds_cfg_netburst); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ default: /* sorry, don't know about them */ break; @@ -462,3 +850,14 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; } } + +void ds_free(struct ds_context *context) +{ + /* This is called when the task owning the parameter context + * is dying. There should not be any user of that context left + * to disturb us, anymore. */ + unsigned long leftovers = context->count; + while (leftovers--) + ds_put_context(context); +} +#endif /* CONFIG_X86_DS */ diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index f8476dfbb60..5cec8a75a4e 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -316,6 +316,14 @@ void exit_thread(void) tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(current->thread.ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(current->thread.ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -482,18 +490,27 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, { struct thread_struct *prev, *next; unsigned long debugctl; + unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread; next = &next_p->thread; debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { + +#ifdef CONFIG_X86_DS + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { /* we clear debugctl to make sure DS * is not in use when we change it */ debugctl = 0; update_debugctlmsr(0); - wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0); + wrmsr(MSR_IA32_DS_AREA, ds_next, 0); } +#endif /* CONFIG_X86_DS */ if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -517,13 +534,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, hard_enable_TSC(); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e2319f39988..ad213494a22 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -267,6 +267,14 @@ void exit_thread(void) t->io_bitmap_max = 0; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(t->ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(t->ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -492,18 +500,27 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, { struct thread_struct *prev, *next; unsigned long debugctl; + unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread, next = &next_p->thread; debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { + +#ifdef CONFIG_X86_DS + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { /* we clear debugctl to make sure DS * is not in use when we change it */ debugctl = 0; update_debugctlmsr(0); - wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr); + wrmsrl(MSR_IA32_DS_AREA, ds_next); } +#endif /* CONFIG_X86_DS */ if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -541,13 +558,13 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ } /* diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index fb03ef380f0..b7ff783dc5f 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -554,45 +554,115 @@ static int ptrace_set_debugreg(struct task_struct *child, return 0; } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS +/* + * The configuration for a particular BTS hardware implementation. + */ +struct bts_configuration { + /* the size of a BTS record in bytes; at most BTS_MAX_RECORD_SIZE */ + unsigned char sizeof_bts; + /* the size of a field in the BTS record in bytes */ + unsigned char sizeof_field; + /* a bitmask to enable/disable BTS in DEBUGCTL MSR */ + unsigned long debugctl_mask; +}; +static struct bts_configuration bts_cfg; + +#define BTS_MAX_RECORD_SIZE (8 * 3) + + +/* + * Branch Trace Store (BTS) uses the following format. Different + * architectures vary in the size of those fields. + * - source linear address + * - destination linear address + * - flags + * + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. + * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * + * In order to store additional information in the BTS buffer, we use + * a special source address to indicate that the record requires + * special interpretation. + * + * Netburst indicated via a bit in the flags field whether the branch + * was predicted; this is ignored. + */ -static int ptrace_bts_get_size(struct task_struct *child) +enum bts_field { + bts_from = 0, + bts_to, + bts_flags, + + bts_escape = (unsigned long)-1, + bts_qual = bts_to, + bts_jiffies = bts_flags +}; + +static inline unsigned long bts_get(const char *base, enum bts_field field) { - if (!child->thread.ds_area_msr) - return -ENXIO; + base += (bts_cfg.sizeof_field * field); + return *(unsigned long *)base; +} - return ds_get_bts_index((void *)child->thread.ds_area_msr); +static inline void bts_set(char *base, enum bts_field field, unsigned long val) +{ + base += (bts_cfg.sizeof_field * field);; + (*(unsigned long *)base) = val; } -static int ptrace_bts_read_record(struct task_struct *child, - long index, +/* + * Translate a BTS record from the raw format into the bts_struct format + * + * out (out): bts_struct interpretation + * raw: raw BTS record + */ +static void ptrace_bts_translate_record(struct bts_struct *out, const void *raw) +{ + memset(out, 0, sizeof(*out)); + if (bts_get(raw, bts_from) == bts_escape) { + out->qualifier = bts_get(raw, bts_qual); + out->variant.jiffies = bts_get(raw, bts_jiffies); + } else { + out->qualifier = BTS_BRANCH; + out->variant.lbr.from_ip = bts_get(raw, bts_from); + out->variant.lbr.to_ip = bts_get(raw, bts_to); + } +} + +static int ptrace_bts_read_record(struct task_struct *child, size_t index, struct bts_struct __user *out) { struct bts_struct ret; - int retval; - int bts_end; - int bts_index; - - if (!child->thread.ds_area_msr) - return -ENXIO; + const void *bts_record; + size_t bts_index, bts_end; + int error; - if (index < 0) - return -EINVAL; + error = ds_get_bts_end(child, &bts_end); + if (error < 0) + return error; - bts_end = ds_get_bts_end((void *)child->thread.ds_area_msr); if (bts_end <= index) return -EINVAL; + error = ds_get_bts_index(child, &bts_index); + if (error < 0) + return error; + /* translate the ptrace bts index into the ds bts index */ - bts_index = ds_get_bts_index((void *)child->thread.ds_area_msr); - bts_index -= (index + 1); - if (bts_index < 0) - bts_index += bts_end; + bts_index += bts_end - (index + 1); + if (bts_end <= bts_index) + bts_index -= bts_end; - retval = ds_read_bts((void *)child->thread.ds_area_msr, - bts_index, &ret); - if (retval < 0) - return retval; + error = ds_access_bts(child, bts_index, &bts_record); + if (error < 0) + return error; + + ptrace_bts_translate_record(&ret, bts_record); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; @@ -600,101 +670,106 @@ static int ptrace_bts_read_record(struct task_struct *child, return sizeof(ret); } -static int ptrace_bts_clear(struct task_struct *child) -{ - if (!child->thread.ds_area_msr) - return -ENXIO; - - return ds_clear((void *)child->thread.ds_area_msr); -} - static int ptrace_bts_drain(struct task_struct *child, long size, struct bts_struct __user *out) { - int end, i; - void *ds = (void *)child->thread.ds_area_msr; - - if (!ds) - return -ENXIO; + struct bts_struct ret; + const unsigned char *raw; + size_t end, i; + int error; - end = ds_get_bts_index(ds); - if (end <= 0) - return end; + error = ds_get_bts_index(child, &end); + if (error < 0) + return error; if (size < (end * sizeof(struct bts_struct))) return -EIO; - for (i = 0; i < end; i++, out++) { - struct bts_struct ret; - int retval; + error = ds_access_bts(child, 0, (const void **)&raw); + if (error < 0) + return error; - retval = ds_read_bts(ds, i, &ret); - if (retval < 0) - return retval; + for (i = 0; i < end; i++, out++, raw += bts_cfg.sizeof_bts) { + ptrace_bts_translate_record(&ret, raw); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; } - ds_clear(ds); + error = ds_clear_bts(child); + if (error < 0) + return error; return end; } +static void ptrace_bts_ovfl(struct task_struct *child) +{ + send_sig(child->thread.bts_ovfl_signal, child, 0); +} + static int ptrace_bts_config(struct task_struct *child, long cfg_size, const struct ptrace_bts_config __user *ucfg) { struct ptrace_bts_config cfg; - int bts_size, ret = 0; - void *ds; + int error = 0; + + error = -EOPNOTSUPP; + if (!bts_cfg.sizeof_bts) + goto errout; + error = -EIO; if (cfg_size < sizeof(cfg)) - return -EIO; + goto errout; + error = -EFAULT; if (copy_from_user(&cfg, ucfg, sizeof(cfg))) - return -EFAULT; + goto errout; - if ((int)cfg.size < 0) - return -EINVAL; + error = -EINVAL; + if ((cfg.flags & PTRACE_BTS_O_SIGNAL) && + !(cfg.flags & PTRACE_BTS_O_ALLOC)) + goto errout; - bts_size = 0; - ds = (void *)child->thread.ds_area_msr; - if (ds) { - bts_size = ds_get_bts_size(ds); - if (bts_size < 0) - return bts_size; - } - cfg.size = PAGE_ALIGN(cfg.size); + if (cfg.flags & PTRACE_BTS_O_ALLOC) { + ds_ovfl_callback_t ovfl = 0; + unsigned int sig = 0; - if (bts_size != cfg.size) { - ret = ptrace_bts_realloc(child, cfg.size, - cfg.flags & PTRACE_BTS_O_CUT_SIZE); - if (ret < 0) + /* we ignore the error in case we were not tracing child */ + (void)ds_release_bts(child); + + if (cfg.flags & PTRACE_BTS_O_SIGNAL) { + if (!cfg.signal) + goto errout; + + sig = cfg.signal; + ovfl = ptrace_bts_ovfl; + } + + error = ds_request_bts(child, /* base = */ 0, cfg.size, ovfl); + if (error < 0) goto errout; - ds = (void *)child->thread.ds_area_msr; + child->thread.bts_ovfl_signal = sig; } - if (cfg.flags & PTRACE_BTS_O_SIGNAL) - ret = ds_set_overflow(ds, DS_O_SIGNAL); - else - ret = ds_set_overflow(ds, DS_O_WRAP); - if (ret < 0) + error = -EINVAL; + if (!child->thread.ds_ctx && cfg.flags) goto errout; if (cfg.flags & PTRACE_BTS_O_TRACE) - child->thread.debugctlmsr |= ds_debugctl_mask(); + child->thread.debugctlmsr |= bts_cfg.debugctl_mask; else - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; if (cfg.flags & PTRACE_BTS_O_SCHED) set_tsk_thread_flag(child, TIF_BTS_TRACE_TS); else clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - ret = sizeof(cfg); + error = sizeof(cfg); out: if (child->thread.debugctlmsr) @@ -702,10 +777,10 @@ out: else clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - return ret; + return error; errout: - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); goto out; } @@ -714,29 +789,40 @@ static int ptrace_bts_status(struct task_struct *child, long cfg_size, struct ptrace_bts_config __user *ucfg) { - void *ds = (void *)child->thread.ds_area_msr; struct ptrace_bts_config cfg; + size_t end; + const void *base, *max; + int error; if (cfg_size < sizeof(cfg)) return -EIO; - memset(&cfg, 0, sizeof(cfg)); + error = ds_get_bts_end(child, &end); + if (error < 0) + return error; - if (ds) { - cfg.size = ds_get_bts_size(ds); + error = ds_access_bts(child, /* index = */ 0, &base); + if (error < 0) + return error; - if (ds_get_overflow(ds) == DS_O_SIGNAL) - cfg.flags |= PTRACE_BTS_O_SIGNAL; + error = ds_access_bts(child, /* index = */ end, &max); + if (error < 0) + return error; - if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && - child->thread.debugctlmsr & ds_debugctl_mask()) - cfg.flags |= PTRACE_BTS_O_TRACE; + memset(&cfg, 0, sizeof(cfg)); + cfg.size = (max - base); + cfg.signal = child->thread.bts_ovfl_signal; + cfg.bts_size = sizeof(struct bts_struct); - if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) - cfg.flags |= PTRACE_BTS_O_SCHED; - } + if (cfg.signal) + cfg.flags |= PTRACE_BTS_O_SIGNAL; - cfg.bts_size = sizeof(struct bts_struct); + if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && + child->thread.debugctlmsr & bts_cfg.debugctl_mask) + cfg.flags |= PTRACE_BTS_O_TRACE; + + if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) + cfg.flags |= PTRACE_BTS_O_SCHED; if (copy_to_user(ucfg, &cfg, sizeof(cfg))) return -EFAULT; @@ -744,89 +830,38 @@ static int ptrace_bts_status(struct task_struct *child, return sizeof(cfg); } - static int ptrace_bts_write_record(struct task_struct *child, const struct bts_struct *in) { - int retval; + unsigned char bts_record[BTS_MAX_RECORD_SIZE]; - if (!child->thread.ds_area_msr) - return -ENXIO; + BUG_ON(BTS_MAX_RECORD_SIZE < bts_cfg.sizeof_bts); - retval = ds_write_bts((void *)child->thread.ds_area_msr, in); - if (retval) - return retval; + memset(bts_record, 0, bts_cfg.sizeof_bts); + switch (in->qualifier) { + case BTS_INVALID: + break; - return sizeof(*in); -} + case BTS_BRANCH: + bts_set(bts_record, bts_from, in->variant.lbr.from_ip); + bts_set(bts_record, bts_to, in->variant.lbr.to_ip); + break; -static int ptrace_bts_realloc(struct task_struct *child, - int size, int reduce_size) -{ - unsigned long rlim, vm; - int ret, old_size; + case BTS_TASK_ARRIVES: + case BTS_TASK_DEPARTS: + bts_set(bts_record, bts_from, bts_escape); + bts_set(bts_record, bts_qual, in->qualifier); + bts_set(bts_record, bts_jiffies, in->variant.jiffies); + break; - if (size < 0) + default: return -EINVAL; - - old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); - if (old_size < 0) - return old_size; - - ret = ds_free((void **)&child->thread.ds_area_msr); - if (ret < 0) - goto out; - - size >>= PAGE_SHIFT; - old_size >>= PAGE_SHIFT; - - current->mm->total_vm -= old_size; - current->mm->locked_vm -= old_size; - - if (size == 0) - goto out; - - rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; - vm = current->mm->total_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->total_vm; - if (size <= 0) - goto out; } - rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - vm = current->mm->locked_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->locked_vm; - if (size <= 0) - goto out; - } - - ret = ds_allocate((void **)&child->thread.ds_area_msr, - size << PAGE_SHIFT); - if (ret < 0) - goto out; - - current->mm->total_vm += size; - current->mm->locked_vm += size; - -out: - if (child->thread.ds_area_msr) - set_tsk_thread_flag(child, TIF_DS_AREA_MSR); - else - clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); - - return ret; + /* The writing task will be the switched-to task on a context + * switch. It needs to write into the switched-from task's BTS + * buffer. */ + return ds_unchecked_write_bts(child, bts_record, bts_cfg.sizeof_bts); } void ptrace_bts_take_timestamp(struct task_struct *tsk, @@ -839,7 +874,66 @@ void ptrace_bts_take_timestamp(struct task_struct *tsk, ptrace_bts_write_record(tsk, &rec); } -#endif /* X86_BTS */ + +static const struct bts_configuration bts_cfg_netburst = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<2)|(1<<3)|(1<<5) +}; + +static const struct bts_configuration bts_cfg_pentium_m = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<6)|(1<<7) +}; + +static const struct bts_configuration bts_cfg_core2 = { + .sizeof_bts = 8 * 3, + .sizeof_field = 8, + .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +}; + +static inline void bts_configure(const struct bts_configuration *cfg) +{ + bts_cfg = *cfg; +} + +void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *c) +{ + switch (c->x86) { + case 0x6: + switch (c->x86_model) { + case 0xD: + case 0xE: /* Pentium M */ + bts_configure(&bts_cfg_pentium_m); + break; + case 0xF: /* Core2 */ + case 0x1C: /* Atom */ + bts_configure(&bts_cfg_core2); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + case 0xF: + switch (c->x86_model) { + case 0x0: + case 0x1: + case 0x2: /* Netburst */ + bts_configure(&bts_cfg_netburst); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + default: + /* sorry, don't know about them */ + break; + } +} +#endif /* CONFIG_X86_PTRACE_BTS */ /* * Called by kernel/ptrace.c when detaching.. @@ -852,15 +946,15 @@ void ptrace_disable(struct task_struct *child) #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); #endif - if (child->thread.ds_area_msr) { -#ifdef X86_BTS - ptrace_bts_realloc(child, 0, 0); -#endif - child->thread.debugctlmsr &= ~ds_debugctl_mask(); - if (!child->thread.debugctlmsr) - clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - } +#ifdef CONFIG_X86_PTRACE_BTS + (void)ds_release_bts(child); + + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; + if (!child->thread.debugctlmsr) + clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); + + clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); +#endif /* CONFIG_X86_PTRACE_BTS */ } #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION @@ -980,7 +1074,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* * These bits need more cooking - not enabled yet: */ -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS case PTRACE_BTS_CONFIG: ret = ptrace_bts_config (child, data, (struct ptrace_bts_config __user *)addr); @@ -992,7 +1086,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_SIZE: - ret = ptrace_bts_get_size(child); + ret = ds_get_bts_index(child, /* pos = */ 0); break; case PTRACE_BTS_GET: @@ -1001,14 +1095,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_CLEAR: - ret = ptrace_bts_clear(child); + ret = ds_clear_bts(child); break; case PTRACE_BTS_DRAIN: ret = ptrace_bts_drain (child, data, (struct bts_struct __user *) addr); break; -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ default: ret = ptrace_request(child, request, addr, data); diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index f2fc8feb727..f7aebe13c99 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -920,11 +920,12 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); } if (cpu_has_bts) - ds_init_intel(c); + ptrace_bts_init_intel(c); n = c->extended_cpuid_level; if (n >= 0x80000008) { diff --git a/include/asm-x86/ds.h b/include/asm-x86/ds.h index 7881368142f..72c5a190bf4 100644 --- a/include/asm-x86/ds.h +++ b/include/asm-x86/ds.h @@ -2,71 +2,237 @@ * Debug Store (DS) support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger , Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger , 2007-2008 */ #ifndef _ASM_X86_DS_H #define _ASM_X86_DS_H +#ifdef CONFIG_X86_DS + #include #include -struct cpuinfo_x86; +struct task_struct; -/* a branch trace record entry +/* + * Request BTS or PEBS + * + * Due to alignement constraints, the actual buffer may be slightly + * smaller than the requested or provided buffer. * - * In order to unify the interface between various processor versions, - * we use the below data structure for all processors. + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to request recording for; + * NULL for per-cpu recording on the current cpu + * base: the base pointer for the (non-pageable) buffer; + * NULL if buffer allocation requested + * size: the size of the requested or provided buffer + * ovfl: pointer to a function to be called on buffer overflow; + * NULL if cyclic buffer requested */ -enum bts_qualifier { - BTS_INVALID = 0, - BTS_BRANCH, - BTS_TASK_ARRIVES, - BTS_TASK_DEPARTS -}; +typedef void (*ds_ovfl_callback_t)(struct task_struct *); +extern int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); +extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); + +/* + * Release BTS or PEBS resources + * + * Frees buffers allocated on ds_request. + * + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to release resources for; + * NULL to release resources for the current cpu + */ +extern int ds_release_bts(struct task_struct *task); +extern int ds_release_pebs(struct task_struct *task); + +/* + * Return the (array) index of the write pointer. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ +extern int ds_get_bts_index(struct task_struct *task, size_t *pos); +extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); + +/* + * Return the (array) index one record beyond the end of the array. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ +extern int ds_get_bts_end(struct task_struct *task, size_t *pos); +extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); + +/* + * Provide a pointer to the BTS/PEBS record at parameter index. + * (assuming an array of BTS/PEBS records) + * + * The pointer points directly into the buffer. The user is + * responsible for copying the record. + * + * Returns the size of a single record on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * index: the index of the requested record + * record (out): pointer to the requested record + */ +extern int ds_access_bts(struct task_struct *task, + size_t index, const void **record); +extern int ds_access_pebs(struct task_struct *task, + size_t index, const void **record); + +/* + * Write one or more BTS/PEBS records at the write pointer index and + * advance the write pointer. + * + * If size is not a multiple of the record size, trailing bytes are + * zeroed out. + * + * May result in one or more overflow notifications. + * + * If called during overflow handling, that is, with index >= + * interrupt threshold, the write will wrap around. + * + * An overflow notification is given if and when the interrupt + * threshold is reached during or after the write. + * + * Returns the number of bytes written or -Eerrno. + * + * task: the task to access; + * NULL to access the current cpu + * buffer: the buffer to write + * size: the size of the buffer + */ +extern int ds_write_bts(struct task_struct *task, + const void *buffer, size_t size); +extern int ds_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + +/* + * Same as ds_write_bts/pebs, but omit ownership checks. + * + * This is needed to have some other task than the owner of the + * BTS/PEBS buffer or the parameter task itself write into the + * respective buffer. + */ +extern int ds_unchecked_write_bts(struct task_struct *task, + const void *buffer, size_t size); +extern int ds_unchecked_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + +/* + * Reset the write pointer of the BTS/PEBS buffer. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ +extern int ds_reset_bts(struct task_struct *task); +extern int ds_reset_pebs(struct task_struct *task); + +/* + * Clear the BTS/PEBS buffer and reset the write pointer. + * The entire buffer will be zeroed out. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ +extern int ds_clear_bts(struct task_struct *task); +extern int ds_clear_pebs(struct task_struct *task); + +/* + * Provide the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value (out): the counter reset value + */ +extern int ds_get_pebs_reset(struct task_struct *task, u64 *value); + +/* + * Set the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value: the new counter reset value + */ +extern int ds_set_pebs_reset(struct task_struct *task, u64 value); + +/* + * Initialization + */ +struct cpuinfo_x86; +extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); + + -struct bts_struct { - u64 qualifier; - union { - /* BTS_BRANCH */ - struct { - u64 from_ip; - u64 to_ip; - } lbr; - /* BTS_TASK_ARRIVES or - BTS_TASK_DEPARTS */ - u64 jiffies; - } variant; +/* + * The DS context - part of struct thread_struct. + */ +struct ds_context { + /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ + unsigned char *ds; + /* the owner of the BTS and PEBS configuration, respectively */ + struct task_struct *owner[2]; + /* buffer overflow notification function for BTS and PEBS */ + ds_ovfl_callback_t callback[2]; + /* the original buffer address */ + void *buffer[2]; + /* the number of allocated pages for on-request allocated buffers */ + unsigned int pages[2]; + /* use count */ + unsigned long count; + /* a pointer to the context location inside the thread_struct + * or the per_cpu context array */ + struct ds_context **this; + /* a pointer to the task owning this context, or NULL, if the + * context is owned by a cpu */ + struct task_struct *task; }; -/* Overflow handling mechanisms */ -#define DS_O_SIGNAL 1 /* send overflow signal */ -#define DS_O_WRAP 2 /* wrap around */ - -extern int ds_allocate(void **, size_t); -extern int ds_free(void **); -extern int ds_get_bts_size(void *); -extern int ds_get_bts_end(void *); -extern int ds_get_bts_index(void *); -extern int ds_set_overflow(void *, int); -extern int ds_get_overflow(void *); -extern int ds_clear(void *); -extern int ds_read_bts(void *, int, struct bts_struct *); -extern int ds_write_bts(void *, const struct bts_struct *); -extern unsigned long ds_debugctl_mask(void); -extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *c); +/* called by exit_thread() to free leftover contexts */ +extern void ds_free(struct ds_context *context); + +#else /* CONFIG_X86_DS */ + +#define ds_init_intel(config) do {} while (0) +#endif /* CONFIG_X86_DS */ #endif /* _ASM_X86_DS_H */ diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 559105220a4..beaccb71628 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -20,6 +20,7 @@ struct mm_struct; #include #include #include +#include #include #include @@ -415,9 +416,14 @@ struct thread_struct { unsigned io_bitmap_max; /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */ unsigned long debugctlmsr; -/* Debug Store - if not 0 points to a DS Save Area configuration; - * goes into MSR_IA32_DS_AREA */ - unsigned long ds_area_msr; +#ifdef CONFIG_X86_DS +/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */ + struct ds_context *ds_ctx; +#endif /* CONFIG_X86_DS */ +#ifdef CONFIG_X86_PTRACE_BTS +/* the signal to send on a bts buffer overflow */ + unsigned int bts_ovfl_signal; +#endif /* CONFIG_X86_PTRACE_BTS */ }; static inline unsigned long native_get_debugreg(int regno) diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h index f224eb3c315..9bcaa75cbca 100644 --- a/include/asm-x86/ptrace-abi.h +++ b/include/asm-x86/ptrace-abi.h @@ -80,8 +80,9 @@ #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ -#ifndef __ASSEMBLY__ +#ifdef CONFIG_X86_PTRACE_BTS +#ifndef __ASSEMBLY__ #include /* configuration/status structure used in PTRACE_BTS_CONFIG and @@ -97,20 +98,20 @@ struct ptrace_bts_config { /* actual size of bts_struct in bytes */ __u32 bts_size; }; -#endif +#endif /* __ASSEMBLY__ */ #define PTRACE_BTS_O_TRACE 0x1 /* branch trace */ #define PTRACE_BTS_O_SCHED 0x2 /* scheduling events w/ jiffies */ #define PTRACE_BTS_O_SIGNAL 0x4 /* send SIG on buffer overflow instead of wrapping around */ -#define PTRACE_BTS_O_CUT_SIZE 0x8 /* cut requested size to max available - instead of failing */ +#define PTRACE_BTS_O_ALLOC 0x8 /* (re)allocate buffer */ #define PTRACE_BTS_CONFIG 40 /* Configure branch trace recording. ADDR points to a struct ptrace_bts_config. DATA gives the size of that buffer. - A new buffer is allocated, iff the size changes. + A new buffer is allocated, if requested in the flags. + An overflow signal may only be requested for new buffers. Returns the number of bytes read. */ #define PTRACE_BTS_STATUS 41 @@ -119,7 +120,7 @@ struct ptrace_bts_config { Returns the number of bytes written. */ #define PTRACE_BTS_SIZE 42 -/* Return the number of available BTS records. +/* Return the number of available BTS records for draining. DATA and ADDR are ignored. */ #define PTRACE_BTS_GET 43 @@ -139,5 +140,6 @@ struct ptrace_bts_config { BTS records are read from oldest to newest. Returns number of BTS records drained. */ +#endif /* CONFIG_X86_PTRACE_BTS */ #endif diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 9f922b0b95d..6303701d18e 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -125,14 +125,48 @@ struct pt_regs { #endif /* __KERNEL__ */ #endif /* !__i386__ */ + +#ifdef CONFIG_X86_PTRACE_BTS +/* a branch trace record entry + * + * In order to unify the interface between various processor versions, + * we use the below data structure for all processors. + */ +enum bts_qualifier { + BTS_INVALID = 0, + BTS_BRANCH, + BTS_TASK_ARRIVES, + BTS_TASK_DEPARTS +}; + +struct bts_struct { + __u64 qualifier; + union { + /* BTS_BRANCH */ + struct { + __u64 from_ip; + __u64 to_ip; + } lbr; + /* BTS_TASK_ARRIVES or + BTS_TASK_DEPARTS */ + __u64 jiffies; + } variant; +}; +#endif /* CONFIG_X86_PTRACE_BTS */ + #ifdef __KERNEL__ -/* the DS BTS struct is used for ptrace as well */ -#include +#include +struct cpuinfo_x86; struct task_struct; +#ifdef CONFIG_X86_PTRACE_BTS +extern void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *); extern void ptrace_bts_take_timestamp(struct task_struct *, enum bts_qualifier); +#else +#define ptrace_bts_init_intel(config) do {} while (0) +#endif /* CONFIG_X86_PTRACE_BTS */ extern unsigned long profile_pc(struct pt_regs *regs); -- GitLab From 970e725098a6da5a9c1f8128102c812e31a0444c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 16 Apr 2008 16:40:17 -0700 Subject: [PATCH 0002/5416] x86, ptrace: PEBS support, warning fix arch/x86/kernel/process_32.c:566: warning: unused variable 'ds_next' arch/x86/kernel/process_32.c:566: warning: unused variable 'ds_prev' Cc: Markus Metzger Cc: Andi Kleen Cc: "H. Peter Anvin" Cc: "Siddha, Suresh B" Cc: Roland McGrath Cc: Michael Kerrisk Cc: Cc: stephane eranian Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_32.c | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 5cec8a75a4e..496ea3110aa 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -484,20 +484,13 @@ int set_tsc_mode(unsigned int val) return 0; } -static noinline void -__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, - struct tss_struct *tss) +#ifdef CONFIG_X86_DS +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) { - struct thread_struct *prev, *next; - unsigned long debugctl; - unsigned long ds_prev = 0, ds_next = 0; + unsigned long ds_prev = 0; + unsigned long ds_next = 0; - prev = &prev_p->thread; - next = &next_p->thread; - - debugctl = prev->debugctlmsr; - -#ifdef CONFIG_X86_DS if (prev->ds_ctx) ds_prev = (unsigned long)prev->ds_ctx->ds; if (next->ds_ctx) @@ -510,8 +503,28 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, update_debugctlmsr(0); wrmsr(MSR_IA32_DS_AREA, ds_next, 0); } + return debugctl; +} +#else +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) +{ + return debugctl; +} #endif /* CONFIG_X86_DS */ +static noinline void +__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, + struct tss_struct *tss) +{ + struct thread_struct *prev, *next; + unsigned long debugctl; + + prev = &prev_p->thread; + next = &next_p->thread; + + debugctl = update_debugctl(prev, next, prev->debugctlmsr); + if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); -- GitLab From 573da4224e8c3800e613d715e909c3179a7e3cb2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 28 Apr 2008 23:15:04 +0400 Subject: [PATCH 0003/5416] x86: DS cleanup - dont treat 0 as NULL Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/ds.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 5b32b6d062b..24a323c9599 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -238,12 +238,12 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task) context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) - return 0; + return NULL; context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); if (!context->ds) { kfree(context); - return 0; + return NULL; } *p_context = context; @@ -279,7 +279,7 @@ static inline void ds_put_context(struct ds_context *context) if (--context->count) goto out; - *(context->this) = 0; + *(context->this) = NULL; if (context->task) clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); @@ -341,16 +341,16 @@ static inline void *ds_allocate_buffer(size_t size, unsigned int *pages) rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; vm = current->mm->total_vm + pgsz; if (rlim < vm) - return 0; + return NULL; rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; vm = current->mm->locked_vm + pgsz; if (rlim < vm) - return 0; + return NULL; buffer = kzalloc(size, GFP_KERNEL); if (!buffer) - return 0; + return NULL; current->mm->total_vm += pgsz; current->mm->locked_vm += pgsz; @@ -395,7 +395,7 @@ static int ds_request(struct task_struct *task, void *base, size_t size, if (context->owner[qual] == current) goto out_unlock; error = -EPERM; - if (context->owner[qual] != 0) + if (context->owner[qual] != NULL) goto out_unlock; context->owner[qual] = current; @@ -445,7 +445,7 @@ static int ds_request(struct task_struct *task, void *base, size_t size, return error; out_release: - context->owner[qual] = 0; + context->owner[qual] = NULL; ds_put_context(context); return error; @@ -825,7 +825,7 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) ds_configure(&ds_cfg_var); break; case 0xF: /* Core2 */ - case 0x1C: /* Atom */ + case 0x1C: /* Atom */ ds_configure(&ds_cfg_64); break; default: -- GitLab From 34b2cd5b688b012975fcfc3b3970fc3508fa82c4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 17 May 2008 08:30:07 +0200 Subject: [PATCH 0004/5416] x86: PEBS cleanup Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ad213494a22..4a93c98a60a 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -500,7 +500,6 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, { struct thread_struct *prev, *next; unsigned long debugctl; - unsigned long ds_prev = 0, ds_next = 0; prev = &prev_p->thread, next = &next_p->thread; @@ -508,17 +507,23 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, debugctl = prev->debugctlmsr; #ifdef CONFIG_X86_DS - if (prev->ds_ctx) - ds_prev = (unsigned long)prev->ds_ctx->ds; - if (next->ds_ctx) - ds_next = (unsigned long)next->ds_ctx->ds; - - if (ds_next != ds_prev) { - /* we clear debugctl to make sure DS - * is not in use when we change it */ - debugctl = 0; - update_debugctlmsr(0); - wrmsrl(MSR_IA32_DS_AREA, ds_next); + { + unsigned long ds_prev = 0, ds_next = 0; + + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { + /* + * We clear debugctl to make sure DS + * is not in use when we change it: + */ + debugctl = 0; + update_debugctlmsr(0); + wrmsrl(MSR_IA32_DS_AREA, ds_next); + } } #endif /* CONFIG_X86_DS */ -- GitLab From 63cc8c75156462d4b42cbdd76c293b7eee7ddbfe Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 12 May 2008 15:44:40 +0200 Subject: [PATCH 0005/5416] percpu: introduce DEFINE_PER_CPU_PAGE_ALIGNED() macro While examining holes in percpu section I found this : c05f5000 D per_cpu__current_task c05f5000 D __per_cpu_start c05f5004 D per_cpu__cpu_number c05f5008 D per_cpu__irq_regs c05f500c d per_cpu__cpu_devices c05f5040 D per_cpu__cyc2ns c05f6000 d per_cpu__cpuid4_info c05f6004 d per_cpu__cache_kobject c05f6008 d per_cpu__index_kobject c05f7000 D per_cpu__gdt_page This is because gdt_page is a percpu variable, defined with a page alignement, and linker is doing its job, two times because of .o nesting in the build process. I introduced a new macro DEFINE_PER_CPU_PAGE_ALIGNED() to avoid wasting this space. All page aligned variables (only one at this time) are put in a separate subsection .data.percpu.page_aligned, at the very begining of percpu zone. Before patch , on a x86_32 machine : .data.percpu 30232 3227471872 .data.percpu 22168 3227471872 Thats 8064 bytes saved for each CPU. Signed-off-by: Eric Dumazet Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/vmlinux_32.lds.S | 1 + include/asm-generic/vmlinux.lds.h | 1 + include/linux/percpu.h | 7 +++++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d0463a94624..b2f54fafb8b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -21,7 +21,7 @@ #include "cpu.h" -DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { +DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index ce5ed083a1e..0f7c29a8c4e 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S @@ -189,6 +189,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { __per_cpu_start = .; + *(.data.percpu.page_aligned) *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f054778e916..69e5c1182fd 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -348,6 +348,7 @@ . = ALIGN(align); \ __per_cpu_start = .; \ .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { \ + *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ } \ diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 4cdd393e71e..2edacc8e6b8 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -23,12 +23,19 @@ __attribute__((__section__(SHARED_ALIGNED_SECTION))) \ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name \ ____cacheline_aligned_in_smp + +#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ + __attribute__((__section__(".data.percpu.page_aligned"))) \ + PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name #else #define DEFINE_PER_CPU(type, name) \ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ DEFINE_PER_CPU(type, name) + +#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ + DEFINE_PER_CPU(type, name) #endif #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) -- GitLab From 70ef6d595b6e51618a0cbe44b848d8c9db11a010 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Thu, 29 May 2008 18:41:04 +0800 Subject: [PATCH 0006/5416] x86: get irq for hpet timer HPET timer's IRQ is 0 by default. So we have to select which irq will be used by these timers. We wait to set the timer's irq until we really open it in order to reduce the chance of conflicting with other device. Signed-off-by: Kevin Hao Signed-off-by: Ingo Molnar --- drivers/char/hpet.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/hpet.h | 3 ++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index e7fb0bca366..c9bf5d44402 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -184,6 +184,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data) return IRQ_HANDLED; } +static void hpet_timer_set_irq(struct hpet_dev *devp) +{ + unsigned long v; + int irq, gsi; + struct hpet_timer __iomem *timer; + + spin_lock_irq(&hpet_lock); + if (devp->hd_hdwirq) { + spin_unlock_irq(&hpet_lock); + return; + } + + timer = devp->hd_timer; + + /* we prefer level triggered mode */ + v = readl(&timer->hpet_config); + if (!(v & Tn_INT_TYPE_CNF_MASK)) { + v |= Tn_INT_TYPE_CNF_MASK; + writel(v, &timer->hpet_config); + } + spin_unlock_irq(&hpet_lock); + + v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >> + Tn_INT_ROUTE_CAP_SHIFT; + + /* + * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by + * legacy device. In IO APIC mode, we skip all the legacy IRQS. + */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) + v &= ~0xf3df; + else + v &= ~0xffff; + + for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ; + irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) { + + if (irq >= NR_IRQS) { + irq = HPET_MAX_IRQ; + break; + } + + gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE, + ACPI_ACTIVE_LOW); + if (gsi > 0) + break; + + /* FIXME: Setup interrupt source table */ + } + + if (irq < HPET_MAX_IRQ) { + spin_lock_irq(&hpet_lock); + v = readl(&timer->hpet_config); + v |= irq << Tn_INT_ROUTE_CNF_SHIFT; + writel(v, &timer->hpet_config); + devp->hd_hdwirq = gsi; + spin_unlock_irq(&hpet_lock); + } + return; +} + static int hpet_open(struct inode *inode, struct file *file) { struct hpet_dev *devp; @@ -215,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file) devp->hd_flags |= HPET_OPEN; spin_unlock_irq(&hpet_lock); + hpet_timer_set_irq(devp); + return 0; } diff --git a/include/linux/hpet.h b/include/linux/hpet.h index 2dc29ce6c8e..6d2626b63a9 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h @@ -37,6 +37,7 @@ struct hpet { #define hpet_compare _u1._hpet_compare #define HPET_MAX_TIMERS (32) +#define HPET_MAX_IRQ (32) /* * HPET general capabilities register @@ -64,7 +65,7 @@ struct hpet { */ #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) -#define Tn_INI_ROUTE_CAP_SHIFT (32UL) +#define Tn_INT_ROUTE_CAP_SHIFT (32UL) #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) #define Tn_FSB_INT_DELCAP_SHIFT (15) #define Tn_FSB_EN_CNF_MASK (0x4000UL) -- GitLab From 3243b4ed817fad04e56e7b7dc78ec28dc8322ff2 Mon Sep 17 00:00:00 2001 From: Krzysztof Oledzki Date: Wed, 4 Jun 2008 03:40:17 +0200 Subject: [PATCH 0007/5416] x86: add another PCI ID for ICH6 force-hpet Tested on Asus P5GDC-V $ lspci -n -n |grep ISA 00:1f.0 ISA bridge [0601]: Intel Corporation 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge [8086:2640] (rev 03) Force enabled HPET at base address 0xfed00000 hpet clockevent registered hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 hpet0: 3 64-bit timers, 14318180 Hz Signed-off-by: Krzysztof Piotr Oledzki Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d89a648fe71..06e1fd6be83 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -158,6 +158,8 @@ static void ich_force_enable_hpet(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, ich_force_enable_hpet); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, -- GitLab From 59ea746337c69f6a5f1bc4d5e8544b3cbf12f801 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 12 Jun 2008 13:56:40 +0200 Subject: [PATCH 0008/5416] MM: virtual address debug Add some (configurable) expensive sanity checking to catch wrong address translations on x86. - create linux/mmdebug.h file to be able include this file in asm headers to not get unsolvable loops in header files - __phys_addr on x86_32 became a function in ioremap.c since PAGE_OFFSET, is_vmalloc_addr and VMALLOC_* non-constasts are undefined if declared in page_32.h - add __phys_addr_const for initializing doublefault_tss.__cr3 Tested on 386, 386pae, x86_64 and x86_64 numa=fake=2. Contains Andi's enable numa virtual address debug patch. Signed-off-by: Jiri Slaby Cc: Andi Kleen Signed-off-by: Ingo Molnar --- arch/x86/kernel/doublefault_32.c | 2 +- arch/x86/mm/ioremap.c | 31 ++++++++++++++++++++++++------- include/asm-x86/mmzone_64.h | 2 +- include/asm-x86/page_32.h | 3 ++- include/linux/mm.h | 7 +------ include/linux/mmdebug.h | 18 ++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ mm/vmalloc.c | 5 +++++ 8 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 include/linux/mmdebug.h diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index a47798b59f0..395acb12b0d 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = { .ds = __USER_DS, .fs = __KERNEL_PERCPU, - .__cr3 = __pa(swapper_pg_dir) + .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir) } }; diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 2b2bb3f9b68..a78ffef62a2 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -23,18 +23,26 @@ #ifdef CONFIG_X86_64 -unsigned long __phys_addr(unsigned long x) +static inline int phys_addr_valid(unsigned long addr) { - if (x >= __START_KERNEL_map) - return x - __START_KERNEL_map + phys_base; - return x - PAGE_OFFSET; + return addr < (1UL << boot_cpu_data.x86_phys_bits); } -EXPORT_SYMBOL(__phys_addr); -static inline int phys_addr_valid(unsigned long addr) +unsigned long __phys_addr(unsigned long x) { - return addr < (1UL << boot_cpu_data.x86_phys_bits); + if (x >= __START_KERNEL_map) { + x -= __START_KERNEL_map; + VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE); + x += phys_base; + } else { + VIRTUAL_BUG_ON(x < PAGE_OFFSET); + x -= PAGE_OFFSET; + VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM : + !phys_addr_valid(x)); + } + return x; } +EXPORT_SYMBOL(__phys_addr); #else @@ -43,6 +51,15 @@ static inline int phys_addr_valid(unsigned long addr) return 1; } +unsigned long __phys_addr(unsigned long x) +{ + /* VMALLOC_* aren't constants; not available at the boot time */ + VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING && + is_vmalloc_addr((void *)x))); + return x - PAGE_OFFSET; +} +EXPORT_SYMBOL(__phys_addr); + #endif int page_is_ram(unsigned long pagenr) diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h index 594bd0dc1d0..facde3e5314 100644 --- a/include/asm-x86/mmzone_64.h +++ b/include/asm-x86/mmzone_64.h @@ -7,7 +7,7 @@ #ifdef CONFIG_NUMA -#define VIRTUAL_BUG_ON(x) +#include #include diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index 424e82f8ae2..9159bfb9dcf 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h @@ -64,7 +64,8 @@ typedef struct page *pgtable_t; #endif #ifndef __ASSEMBLY__ -#define __phys_addr(x) ((x) - PAGE_OFFSET) +#define __phys_addr_const(x) ((x) - PAGE_OFFSET) +extern unsigned long __phys_addr(unsigned long); #define __phys_reloc_hide(x) RELOC_HIDE((x), 0) #ifdef CONFIG_FLATMEM diff --git a/include/linux/mm.h b/include/linux/mm.h index 586a943cab0..3414a8813e9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -210,12 +211,6 @@ struct inode; */ #include -#ifdef CONFIG_DEBUG_VM -#define VM_BUG_ON(cond) BUG_ON(cond) -#else -#define VM_BUG_ON(condition) do { } while(0) -#endif - /* * Methods to modify the page usage count. * diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h new file mode 100644 index 00000000000..860ed1a71bb --- /dev/null +++ b/include/linux/mmdebug.h @@ -0,0 +1,18 @@ +#ifndef LINUX_MM_DEBUG_H +#define LINUX_MM_DEBUG_H 1 + +#include + +#ifdef CONFIG_DEBUG_VM +#define VM_BUG_ON(cond) BUG_ON(cond) +#else +#define VM_BUG_ON(cond) do { } while(0) +#endif + +#ifdef CONFIG_DEBUG_VIRTUAL +#define VIRTUAL_BUG_ON(cond) BUG_ON(cond) +#else +#define VIRTUAL_BUG_ON(cond) do { } while(0) +#endif + +#endif diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index d2099f41aa1..9d9dc0ddf13 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -469,6 +469,15 @@ config DEBUG_VM If unsure, say N. +config DEBUG_VIRTUAL + bool "Debug VM translations" + depends on DEBUG_KERNEL && X86 + help + Enable some costly sanity checks in virtual to page code. This can + catch mistakes with virt_to_page() and friends. + + If unsure, say N. + config DEBUG_WRITECOUNT bool "Debug filesystem writers count" depends on DEBUG_KERNEL diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6e45b0f3d12..dc41e9c8ca6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -180,6 +180,11 @@ struct page *vmalloc_to_page(const void *vmalloc_addr) pmd_t *pmd; pte_t *ptep, pte; + /* XXX we might need to change this if we add VIRTUAL_BUG_ON for + * architectures that do not vmalloc module space */ + VIRTUAL_BUG_ON(!is_vmalloc_addr(vmalloc_addr) && + !is_module_address(addr)); + if (!pgd_none(*pgd)) { pud = pud_offset(pgd, addr); if (!pud_none(*pud)) { -- GitLab From a1bf9631be7332ce0641e299ddafad2d8223100f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 12 Jun 2008 13:56:40 +0200 Subject: [PATCH 0009/5416] x86, MM: virtual address debug, v2 I've removed the test from phys_to_nid and made a function from __phys_addr only when the debugging is enabled (on x86_32). Signed-off-by: Jiri Slaby Cc: tglx@linutronix.de Cc: hpa@zytor.com Cc: Mike Travis Cc: Nick Piggin Cc: Cc: linux-mm@kvack.org Cc: Jiri Slaby Cc: Andi Kleen Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 2 ++ include/asm-x86/mmzone_64.h | 1 - include/asm-x86/page_32.h | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index a78ffef62a2..9dd3cb90597 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -51,6 +51,7 @@ static inline int phys_addr_valid(unsigned long addr) return 1; } +#ifdef CONFIG_DEBUG_VIRTUAL unsigned long __phys_addr(unsigned long x) { /* VMALLOC_* aren't constants; not available at the boot time */ @@ -59,6 +60,7 @@ unsigned long __phys_addr(unsigned long x) return x - PAGE_OFFSET; } EXPORT_SYMBOL(__phys_addr); +#endif #endif diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h index facde3e5314..5e3a6cbddb4 100644 --- a/include/asm-x86/mmzone_64.h +++ b/include/asm-x86/mmzone_64.h @@ -29,7 +29,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) { unsigned nid; VIRTUAL_BUG_ON(!memnodemap); - VIRTUAL_BUG_ON((addr >> memnode_shift) >= memnodemapsize); nid = memnodemap[addr >> memnode_shift]; VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); return nid; diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index 9159bfb9dcf..71a2e424e58 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h @@ -65,7 +65,11 @@ typedef struct page *pgtable_t; #ifndef __ASSEMBLY__ #define __phys_addr_const(x) ((x) - PAGE_OFFSET) +#ifdef CONFIG_DEBUG_VIRTUAL extern unsigned long __phys_addr(unsigned long); +#else +#define __phys_addr(x) ((x) - PAGE_OFFSET) +#endif #define __phys_reloc_hide(x) RELOC_HIDE((x), 0) #ifdef CONFIG_FLATMEM -- GitLab From 7aa413def76146f7b3784228556d9e4bc562eab3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 19 Jun 2008 13:28:11 +0200 Subject: [PATCH 0010/5416] x86, MM: virtual address debug, cleanups Signed-off-by: Ingo Molnar --- include/linux/mmdebug.h | 4 ++-- mm/vmalloc.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h index 860ed1a71bb..8a550987719 100644 --- a/include/linux/mmdebug.h +++ b/include/linux/mmdebug.h @@ -6,13 +6,13 @@ #ifdef CONFIG_DEBUG_VM #define VM_BUG_ON(cond) BUG_ON(cond) #else -#define VM_BUG_ON(cond) do { } while(0) +#define VM_BUG_ON(cond) do { } while (0) #endif #ifdef CONFIG_DEBUG_VIRTUAL #define VIRTUAL_BUG_ON(cond) BUG_ON(cond) #else -#define VIRTUAL_BUG_ON(cond) do { } while(0) +#define VIRTUAL_BUG_ON(cond) do { } while (0) #endif #endif diff --git a/mm/vmalloc.c b/mm/vmalloc.c index dc41e9c8ca6..830a5580c5d 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -180,8 +180,10 @@ struct page *vmalloc_to_page(const void *vmalloc_addr) pmd_t *pmd; pte_t *ptep, pte; - /* XXX we might need to change this if we add VIRTUAL_BUG_ON for - * architectures that do not vmalloc module space */ + /* + * XXX we might need to change this if we add VIRTUAL_BUG_ON for + * architectures that do not vmalloc module space + */ VIRTUAL_BUG_ON(!is_vmalloc_addr(vmalloc_addr) && !is_module_address(addr)); -- GitLab From f3561810b163aca5388ad550abbbc82ae5323189 Mon Sep 17 00:00:00 2001 From: Joe Buehler Date: Mon, 9 Jun 2008 08:55:20 -0400 Subject: [PATCH 0011/5416] x86: add PCI ID for 6300ESB force hpet 00:1f.0 ISA bridge: Intel Corporation 6300ESB LPC Interface Controller (rev 02) 00:1f.0 Class 0601: 8086:25a1 (rev 02) kernel: pci 0000:00:1f.0: Force enabled HPET at 0xfed00000 kernel: hpet clockevent registered kernel: hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 kernel: hpet0: 3 64-bit timers, 14318180 Hz Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 06e1fd6be83..f327abafe3e 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -257,6 +257,8 @@ static void old_ich_force_enable_hpet_user(struct pci_dev *dev) old_ich_force_enable_hpet(dev); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, + old_ich_force_enable_hpet_user); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, old_ich_force_enable_hpet_user); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, -- GitLab From e61d98d8dad0048619bb138b0ff996422ffae53b Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:35 -0700 Subject: [PATCH 0012/5416] x64, x2apic/intr-remap: Intel vt-d, IOMMU code reorganization code reorganization of the generic Intel vt-d parsing related routines and linux iommu routines specific to Intel vt-d. drivers/pci/dmar.c now contains the generic vt-d parsing related routines drivers/pci/intel_iommu.c contains the iommu routines specific to vt-d Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dma_remapping.h | 155 ++++++++++++++++++++++++++++++++++ drivers/pci/dmar.c | 90 +++++++++++++++++++- drivers/pci/intel-iommu.c | 92 ++------------------ drivers/pci/intel-iommu.h | 163 +++--------------------------------- 4 files changed, 264 insertions(+), 236 deletions(-) create mode 100644 drivers/pci/dma_remapping.h diff --git a/drivers/pci/dma_remapping.h b/drivers/pci/dma_remapping.h new file mode 100644 index 00000000000..05aac8ef96c --- /dev/null +++ b/drivers/pci/dma_remapping.h @@ -0,0 +1,155 @@ +#ifndef _DMA_REMAPPING_H +#define _DMA_REMAPPING_H + +/* + * We need a fixed PAGE_SIZE of 4K irrespective of + * arch PAGE_SIZE for IOMMU page tables. + */ +#define PAGE_SHIFT_4K (12) +#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) +#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) +#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) + +#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) +#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) +#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) + + +/* + * 0: Present + * 1-11: Reserved + * 12-63: Context Ptr (12 - (haw-1)) + * 64-127: Reserved + */ +struct root_entry { + u64 val; + u64 rsvd1; +}; +#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry)) +static inline bool root_present(struct root_entry *root) +{ + return (root->val & 1); +} +static inline void set_root_present(struct root_entry *root) +{ + root->val |= 1; +} +static inline void set_root_value(struct root_entry *root, unsigned long value) +{ + root->val |= value & PAGE_MASK_4K; +} + +struct context_entry; +static inline struct context_entry * +get_context_addr_from_root(struct root_entry *root) +{ + return (struct context_entry *) + (root_present(root)?phys_to_virt( + root->val & PAGE_MASK_4K): + NULL); +} + +/* + * low 64 bits: + * 0: present + * 1: fault processing disable + * 2-3: translation type + * 12-63: address space root + * high 64 bits: + * 0-2: address width + * 3-6: aval + * 8-23: domain id + */ +struct context_entry { + u64 lo; + u64 hi; +}; +#define context_present(c) ((c).lo & 1) +#define context_fault_disable(c) (((c).lo >> 1) & 1) +#define context_translation_type(c) (((c).lo >> 2) & 3) +#define context_address_root(c) ((c).lo & PAGE_MASK_4K) +#define context_address_width(c) ((c).hi & 7) +#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1)) + +#define context_set_present(c) do {(c).lo |= 1;} while (0) +#define context_set_fault_enable(c) \ + do {(c).lo &= (((u64)-1) << 2) | 1;} while (0) +#define context_set_translation_type(c, val) \ + do { \ + (c).lo &= (((u64)-1) << 4) | 3; \ + (c).lo |= ((val) & 3) << 2; \ + } while (0) +#define CONTEXT_TT_MULTI_LEVEL 0 +#define context_set_address_root(c, val) \ + do {(c).lo |= (val) & PAGE_MASK_4K;} while (0) +#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0) +#define context_set_domain_id(c, val) \ + do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0) +#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0) + +/* + * 0: readable + * 1: writable + * 2-6: reserved + * 7: super page + * 8-11: available + * 12-63: Host physcial address + */ +struct dma_pte { + u64 val; +}; +#define dma_clear_pte(p) do {(p).val = 0;} while (0) + +#define DMA_PTE_READ (1) +#define DMA_PTE_WRITE (2) + +#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0) +#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0) +#define dma_set_pte_prot(p, prot) \ + do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0) +#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K) +#define dma_set_pte_addr(p, addr) do {\ + (p).val |= ((addr) & PAGE_MASK_4K); } while (0) +#define dma_pte_present(p) (((p).val & 3) != 0) + +struct intel_iommu; + +struct dmar_domain { + int id; /* domain id */ + struct intel_iommu *iommu; /* back pointer to owning iommu */ + + struct list_head devices; /* all devices' list */ + struct iova_domain iovad; /* iova's that belong to this domain */ + + struct dma_pte *pgd; /* virtual address */ + spinlock_t mapping_lock; /* page table lock */ + int gaw; /* max guest address width */ + + /* adjusted guest address width, 0 is level 2 30-bit */ + int agaw; + +#define DOMAIN_FLAG_MULTIPLE_DEVICES 1 + int flags; +}; + +/* PCI domain-device relationship */ +struct device_domain_info { + struct list_head link; /* link to domain siblings */ + struct list_head global; /* link to global list */ + u8 bus; /* PCI bus numer */ + u8 devfn; /* PCI devfn number */ + struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ + struct dmar_domain *domain; /* pointer to domain */ +}; + +extern int init_dmars(void); +extern void free_dmar_iommu(struct intel_iommu *iommu); + +#ifndef CONFIG_DMAR_GFX_WA +static inline void iommu_prepare_gfx_mapping(void) +{ + return; +} +#endif /* !CONFIG_DMAR_GFX_WA */ + +#endif diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index f941f609dbf..c00e387f5b7 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -19,9 +19,11 @@ * Author: Shaohua Li * Author: Anil S Keshavamurthy * - * This file implements early detection/parsing of DMA Remapping Devices + * This file implements early detection/parsing of Remapping Devices * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI * tables. + * + * These routines are used by both DMA-remapping and Interrupt-remapping */ #include @@ -300,6 +302,37 @@ parse_dmar_table(void) return ret; } +int dmar_pci_device_match(struct pci_dev *devices[], int cnt, + struct pci_dev *dev) +{ + int index; + + while (dev) { + for (index = 0; index < cnt; index++) + if (dev == devices[index]) + return 1; + + /* Check our parent */ + dev = dev->bus->self; + } + + return 0; +} + +struct dmar_drhd_unit * +dmar_find_matched_drhd_unit(struct pci_dev *dev) +{ + struct dmar_drhd_unit *drhd = NULL; + + list_for_each_entry(drhd, &dmar_drhd_units, list) { + if (drhd->include_all || dmar_pci_device_match(drhd->devices, + drhd->devices_cnt, dev)) + return drhd; + } + + return NULL; +} + int __init dmar_table_init(void) { @@ -343,3 +376,58 @@ int __init early_dmar_detect(void) return (ACPI_SUCCESS(status) ? 1 : 0); } + +struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, + struct dmar_drhd_unit *drhd) +{ + int map_size; + u32 ver; + + iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); + if (!iommu->reg) { + printk(KERN_ERR "IOMMU: can't map the region\n"); + goto error; + } + iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); + iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); + + /* the registers might be more than one page */ + map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), + cap_max_fault_reg_offset(iommu->cap)); + map_size = PAGE_ALIGN_4K(map_size); + if (map_size > PAGE_SIZE_4K) { + iounmap(iommu->reg); + iommu->reg = ioremap(drhd->reg_base_addr, map_size); + if (!iommu->reg) { + printk(KERN_ERR "IOMMU: can't map the region\n"); + goto error; + } + } + + ver = readl(iommu->reg + DMAR_VER_REG); + pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", + drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), + iommu->cap, iommu->ecap); + + spin_lock_init(&iommu->register_lock); + + drhd->iommu = iommu; + return iommu; +error: + kfree(iommu); + return NULL; +} + +void free_iommu(struct intel_iommu *iommu) +{ + if (!iommu) + return; + +#ifdef CONFIG_DMAR + free_dmar_iommu(iommu); +#endif + + if (iommu->reg) + iounmap(iommu->reg); + kfree(iommu); +} diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index bb0642318a9..1c0270d3e2e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -990,6 +990,8 @@ static int iommu_init_domains(struct intel_iommu *iommu) return -ENOMEM; } + spin_lock_init(&iommu->lock); + /* * if Caching mode is set, then invalid translations are tagged * with domainid 0. Hence we need to pre-allocate it. @@ -998,62 +1000,15 @@ static int iommu_init_domains(struct intel_iommu *iommu) set_bit(0, iommu->domain_ids); return 0; } -static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, - struct dmar_drhd_unit *drhd) -{ - int ret; - int map_size; - u32 ver; - - iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); - if (!iommu->reg) { - printk(KERN_ERR "IOMMU: can't map the region\n"); - goto error; - } - iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); - iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); - - /* the registers might be more than one page */ - map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), - cap_max_fault_reg_offset(iommu->cap)); - map_size = PAGE_ALIGN_4K(map_size); - if (map_size > PAGE_SIZE_4K) { - iounmap(iommu->reg); - iommu->reg = ioremap(drhd->reg_base_addr, map_size); - if (!iommu->reg) { - printk(KERN_ERR "IOMMU: can't map the region\n"); - goto error; - } - } - ver = readl(iommu->reg + DMAR_VER_REG); - pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", - drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), - iommu->cap, iommu->ecap); - ret = iommu_init_domains(iommu); - if (ret) - goto error_unmap; - spin_lock_init(&iommu->lock); - spin_lock_init(&iommu->register_lock); - - drhd->iommu = iommu; - return iommu; -error_unmap: - iounmap(iommu->reg); -error: - kfree(iommu); - return NULL; -} static void domain_exit(struct dmar_domain *domain); -static void free_iommu(struct intel_iommu *iommu) + +void free_dmar_iommu(struct intel_iommu *iommu) { struct dmar_domain *domain; int i; - if (!iommu) - return; - i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); for (; i < cap_ndoms(iommu->cap); ) { domain = iommu->domains[i]; @@ -1078,10 +1033,6 @@ static void free_iommu(struct intel_iommu *iommu) /* free context mapping */ free_context_table(iommu); - - if (iommu->reg) - iounmap(iommu->reg); - kfree(iommu); } static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu) @@ -1426,37 +1377,6 @@ find_domain(struct pci_dev *pdev) return NULL; } -static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, - struct pci_dev *dev) -{ - int index; - - while (dev) { - for (index = 0; index < cnt; index++) - if (dev == devices[index]) - return 1; - - /* Check our parent */ - dev = dev->bus->self; - } - - return 0; -} - -static struct dmar_drhd_unit * -dmar_find_matched_drhd_unit(struct pci_dev *dev) -{ - struct dmar_drhd_unit *drhd = NULL; - - list_for_each_entry(drhd, &dmar_drhd_units, list) { - if (drhd->include_all || dmar_pci_device_match(drhd->devices, - drhd->devices_cnt, dev)) - return drhd; - } - - return NULL; -} - /* domain is initialized */ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) { @@ -1764,6 +1684,10 @@ int __init init_dmars(void) goto error; } + ret = iommu_init_domains(iommu); + if (ret) + goto error; + /* * TBD: * we could share the same root & context tables diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index afc0ad96122..9e5e98c76c0 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -27,19 +27,7 @@ #include #include "iova.h" #include - -/* - * We need a fixed PAGE_SIZE of 4K irrespective of - * arch PAGE_SIZE for IOMMU page tables. - */ -#define PAGE_SHIFT_4K (12) -#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) -#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) -#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) - -#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) -#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) -#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) +#include "dma_remapping.h" /* * Intel IOMMU register specification per version 1.0 public spec. @@ -187,158 +175,31 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define dma_frcd_source_id(c) (c & 0xffff) #define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */ -/* - * 0: Present - * 1-11: Reserved - * 12-63: Context Ptr (12 - (haw-1)) - * 64-127: Reserved - */ -struct root_entry { - u64 val; - u64 rsvd1; -}; -#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry)) -static inline bool root_present(struct root_entry *root) -{ - return (root->val & 1); -} -static inline void set_root_present(struct root_entry *root) -{ - root->val |= 1; -} -static inline void set_root_value(struct root_entry *root, unsigned long value) -{ - root->val |= value & PAGE_MASK_4K; -} - -struct context_entry; -static inline struct context_entry * -get_context_addr_from_root(struct root_entry *root) -{ - return (struct context_entry *) - (root_present(root)?phys_to_virt( - root->val & PAGE_MASK_4K): - NULL); -} - -/* - * low 64 bits: - * 0: present - * 1: fault processing disable - * 2-3: translation type - * 12-63: address space root - * high 64 bits: - * 0-2: address width - * 3-6: aval - * 8-23: domain id - */ -struct context_entry { - u64 lo; - u64 hi; -}; -#define context_present(c) ((c).lo & 1) -#define context_fault_disable(c) (((c).lo >> 1) & 1) -#define context_translation_type(c) (((c).lo >> 2) & 3) -#define context_address_root(c) ((c).lo & PAGE_MASK_4K) -#define context_address_width(c) ((c).hi & 7) -#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1)) - -#define context_set_present(c) do {(c).lo |= 1;} while (0) -#define context_set_fault_enable(c) \ - do {(c).lo &= (((u64)-1) << 2) | 1;} while (0) -#define context_set_translation_type(c, val) \ - do { \ - (c).lo &= (((u64)-1) << 4) | 3; \ - (c).lo |= ((val) & 3) << 2; \ - } while (0) -#define CONTEXT_TT_MULTI_LEVEL 0 -#define context_set_address_root(c, val) \ - do {(c).lo |= (val) & PAGE_MASK_4K;} while (0) -#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0) -#define context_set_domain_id(c, val) \ - do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0) -#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0) - -/* - * 0: readable - * 1: writable - * 2-6: reserved - * 7: super page - * 8-11: available - * 12-63: Host physcial address - */ -struct dma_pte { - u64 val; -}; -#define dma_clear_pte(p) do {(p).val = 0;} while (0) - -#define DMA_PTE_READ (1) -#define DMA_PTE_WRITE (2) - -#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0) -#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0) -#define dma_set_pte_prot(p, prot) \ - do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0) -#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K) -#define dma_set_pte_addr(p, addr) do {\ - (p).val |= ((addr) & PAGE_MASK_4K); } while (0) -#define dma_pte_present(p) (((p).val & 3) != 0) - -struct intel_iommu; - -struct dmar_domain { - int id; /* domain id */ - struct intel_iommu *iommu; /* back pointer to owning iommu */ - - struct list_head devices; /* all devices' list */ - struct iova_domain iovad; /* iova's that belong to this domain */ - - struct dma_pte *pgd; /* virtual address */ - spinlock_t mapping_lock; /* page table lock */ - int gaw; /* max guest address width */ - - /* adjusted guest address width, 0 is level 2 30-bit */ - int agaw; - -#define DOMAIN_FLAG_MULTIPLE_DEVICES 1 - int flags; -}; - -/* PCI domain-device relationship */ -struct device_domain_info { - struct list_head link; /* link to domain siblings */ - struct list_head global; /* link to global list */ - u8 bus; /* PCI bus numer */ - u8 devfn; /* PCI devfn number */ - struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ - struct dmar_domain *domain; /* pointer to domain */ -}; - -extern int init_dmars(void); - struct intel_iommu { void __iomem *reg; /* Pointer to hardware regs, virtual addr */ u64 cap; u64 ecap; - unsigned long *domain_ids; /* bitmap of domains */ - struct dmar_domain **domains; /* ptr to domains */ int seg; u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ - spinlock_t lock; /* protect context, domain ids */ spinlock_t register_lock; /* protect register handling */ + +#ifdef CONFIG_DMAR + unsigned long *domain_ids; /* bitmap of domains */ + struct dmar_domain **domains; /* ptr to domains */ + spinlock_t lock; /* protect context, domain ids */ struct root_entry *root_entry; /* virtual address */ unsigned int irq; unsigned char name[7]; /* Device Name */ struct msi_msg saved_msg; struct sys_device sysdev; +#endif }; -#ifndef CONFIG_DMAR_GFX_WA -static inline void iommu_prepare_gfx_mapping(void) -{ - return; -} -#endif /* !CONFIG_DMAR_GFX_WA */ +extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); + +extern struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, + struct dmar_drhd_unit *drhd); +extern void free_iommu(struct intel_iommu *iommu); #endif -- GitLab From c42d9f32443397aed2d37d37df161392e6a5862f Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:36 -0700 Subject: [PATCH 0013/5416] x64, x2apic/intr-remap: fix the need for sequential array allocation of iommus Clean up the intel-iommu code related to deferred iommu flush logic. There is no need to allocate all the iommu's as a sequential array. This will be used later in the interrupt-remapping patch series to allocate iommu much early and individually for each device remapping hardware unit. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 11 +++++++++-- drivers/pci/intel-iommu.c | 24 +++++++----------------- drivers/pci/intel-iommu.h | 4 ++-- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index c00e387f5b7..1a59423a8ed 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -377,11 +377,18 @@ int __init early_dmar_detect(void) return (ACPI_SUCCESS(status) ? 1 : 0); } -struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, - struct dmar_drhd_unit *drhd) +struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) { + struct intel_iommu *iommu; int map_size; u32 ver; + static int iommu_allocated = 0; + + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + if (!iommu) + return NULL; + + iommu->seq_id = iommu_allocated++; iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); if (!iommu->reg) { diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1c0270d3e2e..4d59a6a1f4d 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -58,8 +58,6 @@ static void flush_unmaps_timeout(unsigned long data); DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0); -static struct intel_iommu *g_iommus; - #define HIGH_WATER_MARK 250 struct deferred_flush_tables { int next; @@ -1649,8 +1647,6 @@ int __init init_dmars(void) * endfor */ for_each_drhd_unit(drhd) { - if (drhd->ignored) - continue; g_num_of_iommus++; /* * lock not needed as this is only incremented in the single @@ -1659,26 +1655,17 @@ int __init init_dmars(void) */ } - g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL); - if (!g_iommus) { - ret = -ENOMEM; - goto error; - } - deferred_flush = kzalloc(g_num_of_iommus * sizeof(struct deferred_flush_tables), GFP_KERNEL); if (!deferred_flush) { - kfree(g_iommus); ret = -ENOMEM; goto error; } - i = 0; for_each_drhd_unit(drhd) { if (drhd->ignored) continue; - iommu = alloc_iommu(&g_iommus[i], drhd); - i++; + iommu = alloc_iommu(drhd); if (!iommu) { ret = -ENOMEM; goto error; @@ -1770,7 +1757,6 @@ error: iommu = drhd->iommu; free_iommu(iommu); } - kfree(g_iommus); return ret; } @@ -1927,7 +1913,10 @@ static void flush_unmaps(void) /* just flush them all */ for (i = 0; i < g_num_of_iommus; i++) { if (deferred_flush[i].next) { - iommu_flush_iotlb_global(&g_iommus[i], 0); + struct intel_iommu *iommu = + deferred_flush[i].domain[0]->iommu; + + iommu_flush_iotlb_global(iommu, 0); for (j = 0; j < deferred_flush[i].next; j++) { __free_iova(&deferred_flush[i].domain[j]->iovad, deferred_flush[i].iova[j]); @@ -1957,7 +1946,8 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova) if (list_size == HIGH_WATER_MARK) flush_unmaps(); - iommu_id = dom->iommu - g_iommus; + iommu_id = dom->iommu->seq_id; + next = deferred_flush[iommu_id].next; deferred_flush[iommu_id].domain[next] = dom; deferred_flush[iommu_id].iova[next] = iova; diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 9e5e98c76c0..75c63f65b3f 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -182,6 +182,7 @@ struct intel_iommu { int seg; u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ spinlock_t register_lock; /* protect register handling */ + int seq_id; /* sequence id of the iommu */ #ifdef CONFIG_DMAR unsigned long *domain_ids; /* bitmap of domains */ @@ -198,8 +199,7 @@ struct intel_iommu { extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); -extern struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, - struct dmar_drhd_unit *drhd); +extern struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd); extern void free_iommu(struct intel_iommu *iommu); #endif -- GitLab From 1886e8a90a580f3ad343f2065c84c1b9e1dac9ef Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:37 -0700 Subject: [PATCH 0014/5416] x64, x2apic/intr-remap: code re-structuring, to be used by both DMA and Interrupt remapping Allocate the iommu during the parse of DMA remapping hardware definition structures. And also, introduce routines for device scope initialization which will be explicitly called during dma-remapping initialization. These will be used for enabling interrupt remapping separately from the existing DMA-remapping enabling sequence. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 89 ++++++++++++++++++++++++++++++++------- drivers/pci/intel-iommu.c | 10 ++--- drivers/pci/intel-iommu.h | 2 +- include/linux/dmar.h | 10 ++++- 4 files changed, 88 insertions(+), 23 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 1a59423a8ed..158bc5bfcf7 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -174,19 +174,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) struct acpi_dmar_hardware_unit *drhd; struct dmar_drhd_unit *dmaru; int ret = 0; - static int include_all; dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); if (!dmaru) return -ENOMEM; + dmaru->hdr = header; drhd = (struct acpi_dmar_hardware_unit *)header; dmaru->reg_base_addr = drhd->address; dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ + ret = alloc_iommu(dmaru); + if (ret) { + kfree(dmaru); + return ret; + } + dmar_register_drhd_unit(dmaru); + return 0; +} + +static int __init +dmar_parse_dev(struct dmar_drhd_unit *dmaru) +{ + struct acpi_dmar_hardware_unit *drhd; + static int include_all; + int ret; + + drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr; + if (!dmaru->include_all) ret = dmar_parse_dev_scope((void *)(drhd + 1), - ((void *)drhd) + header->length, + ((void *)drhd) + drhd->header.length, &dmaru->devices_cnt, &dmaru->devices, drhd->segment); else { @@ -199,10 +217,10 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) include_all = 1; } - if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) + if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) { + list_del(&dmaru->list); kfree(dmaru); - else - dmar_register_drhd_unit(dmaru); + } return ret; } @@ -211,23 +229,35 @@ dmar_parse_one_rmrr(struct acpi_dmar_header *header) { struct acpi_dmar_reserved_memory *rmrr; struct dmar_rmrr_unit *rmrru; - int ret = 0; rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); if (!rmrru) return -ENOMEM; + rmrru->hdr = header; rmrr = (struct acpi_dmar_reserved_memory *)header; rmrru->base_address = rmrr->base_address; rmrru->end_address = rmrr->end_address; + + dmar_register_rmrr_unit(rmrru); + return 0; +} + +static int __init +rmrr_parse_dev(struct dmar_rmrr_unit *rmrru) +{ + struct acpi_dmar_reserved_memory *rmrr; + int ret; + + rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr; ret = dmar_parse_dev_scope((void *)(rmrr + 1), - ((void *)rmrr) + header->length, + ((void *)rmrr) + rmrr->header.length, &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); - if (ret || (rmrru->devices_cnt == 0)) + if (ret || (rmrru->devices_cnt == 0)) { + list_del(&rmrru->list); kfree(rmrru); - else - dmar_register_rmrr_unit(rmrru); + } return ret; } @@ -333,15 +363,42 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) return NULL; } +int __init dmar_dev_scope_init(void) +{ + struct dmar_drhd_unit *drhd; + struct dmar_rmrr_unit *rmrr; + int ret = -ENODEV; + + for_each_drhd_unit(drhd) { + ret = dmar_parse_dev(drhd); + if (ret) + return ret; + } + + for_each_rmrr_units(rmrr) { + ret = rmrr_parse_dev(rmrr); + if (ret) + return ret; + } + + return ret; +} + int __init dmar_table_init(void) { - + static int dmar_table_initialized; int ret; + if (dmar_table_initialized) + return 0; + + dmar_table_initialized = 1; + ret = parse_dmar_table(); if (ret) { - printk(KERN_INFO PREFIX "parse DMAR table failure.\n"); + if (ret != -ENODEV) + printk(KERN_INFO PREFIX "parse DMAR table failure.\n"); return ret; } @@ -377,7 +434,7 @@ int __init early_dmar_detect(void) return (ACPI_SUCCESS(status) ? 1 : 0); } -struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) +int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; int map_size; @@ -386,7 +443,7 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) - return NULL; + return -ENOMEM; iommu->seq_id = iommu_allocated++; @@ -419,10 +476,10 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) spin_lock_init(&iommu->register_lock); drhd->iommu = iommu; - return iommu; + return 0; error: kfree(iommu); - return NULL; + return -1; } void free_iommu(struct intel_iommu *iommu) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4d59a6a1f4d..218a1f357b4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1665,11 +1665,8 @@ int __init init_dmars(void) for_each_drhd_unit(drhd) { if (drhd->ignored) continue; - iommu = alloc_iommu(drhd); - if (!iommu) { - ret = -ENOMEM; - goto error; - } + + iommu = drhd->iommu; ret = iommu_init_domains(iommu); if (ret) @@ -2324,6 +2321,9 @@ int __init intel_iommu_init(void) if (dmar_table_init()) return -ENODEV; + if (dmar_dev_scope_init()) + return -ENODEV; + iommu_init_mempool(); dmar_init_reserved_ranges(); diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 75c63f65b3f..371e3b9caf3 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -199,7 +199,7 @@ struct intel_iommu { extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); -extern struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd); +extern int alloc_iommu(struct dmar_drhd_unit *drhd); extern void free_iommu(struct intel_iommu *iommu); #endif diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 56c73b84755..3ab07e42558 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -46,12 +46,14 @@ extern int intel_iommu_init(void); extern int dmar_table_init(void); extern int early_dmar_detect(void); +extern int dmar_dev_scope_init(void); extern struct list_head dmar_drhd_units; extern struct list_head dmar_rmrr_units; struct dmar_drhd_unit { struct list_head list; /* list of drhd units */ + struct acpi_dmar_header *hdr; /* ACPI header */ u64 reg_base_addr; /* register base address*/ struct pci_dev **devices; /* target device array */ int devices_cnt; /* target device count */ @@ -62,6 +64,7 @@ struct dmar_drhd_unit { struct dmar_rmrr_unit { struct list_head list; /* list of rmrr units */ + struct acpi_dmar_header *hdr; /* ACPI header */ u64 base_address; /* reserved base address*/ u64 end_address; /* reserved end address */ struct pci_dev **devices; /* target devices */ @@ -72,6 +75,8 @@ struct dmar_rmrr_unit { list_for_each_entry(drhd, &dmar_drhd_units, list) #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, &dmar_rmrr_units, list) + +extern int alloc_iommu(struct dmar_drhd_unit *); #else static inline void detect_intel_iommu(void) { @@ -81,6 +86,9 @@ static inline int intel_iommu_init(void) { return -ENODEV; } - +static inline int dmar_table_init(void) +{ + return -ENODEV; +} #endif /* !CONFIG_DMAR */ #endif /* __DMAR_H__ */ -- GitLab From aaa9d1dd63bf89b62f4ea9f46de376ab1a3fbc6c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:38 -0700 Subject: [PATCH 0015/5416] x64, x2apic/intr-remap: use CONFIG_DMAR for DMA-remapping specific code DMA remapping specific code covered with CONFIG_DMAR in the generic code which will also be used later for enabling Interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 158bc5bfcf7..5c99f997398 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -39,7 +39,6 @@ * these units are not supported by the architecture. */ LIST_HEAD(dmar_drhd_units); -LIST_HEAD(dmar_rmrr_units); static struct acpi_table_header * __initdata dmar_tbl; @@ -55,11 +54,6 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) list_add(&drhd->list, &dmar_drhd_units); } -static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr) -{ - list_add(&rmrr->list, &dmar_rmrr_units); -} - static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, struct pci_dev **dev, u16 segment) { @@ -224,6 +218,15 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru) return ret; } +#ifdef CONFIG_DMAR +LIST_HEAD(dmar_rmrr_units); + +static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr) +{ + list_add(&rmrr->list, &dmar_rmrr_units); +} + + static int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header) { @@ -260,6 +263,7 @@ rmrr_parse_dev(struct dmar_rmrr_unit *rmrru) } return ret; } +#endif static void __init dmar_table_print_dmar_entry(struct acpi_dmar_header *header) @@ -284,6 +288,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header) } } + /** * parse_dmar_table - parses the DMA reporting table */ @@ -316,7 +321,9 @@ parse_dmar_table(void) ret = dmar_parse_one_drhd(entry_header); break; case ACPI_DMAR_TYPE_RESERVED_MEMORY: +#ifdef CONFIG_DMAR ret = dmar_parse_one_rmrr(entry_header); +#endif break; default: printk(KERN_WARNING PREFIX @@ -366,7 +373,6 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) int __init dmar_dev_scope_init(void) { struct dmar_drhd_unit *drhd; - struct dmar_rmrr_unit *rmrr; int ret = -ENODEV; for_each_drhd_unit(drhd) { @@ -375,11 +381,16 @@ int __init dmar_dev_scope_init(void) return ret; } - for_each_rmrr_units(rmrr) { - ret = rmrr_parse_dev(rmrr); - if (ret) - return ret; +#ifdef CONFIG_DMAR + { + struct dmar_rmrr_unit *rmrr; + for_each_rmrr_units(rmrr) { + ret = rmrr_parse_dev(rmrr); + if (ret) + return ret; + } } +#endif return ret; } @@ -407,10 +418,12 @@ int __init dmar_table_init(void) return -ENODEV; } +#ifdef CONFIG_DMAR if (list_empty(&dmar_rmrr_units)) { printk(KERN_INFO PREFIX "No RMRR found\n"); return -ENODEV; } +#endif return 0; } -- GitLab From 2d6b5f85bb4ca919d8ab0f30311309b53fb93bc3 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:39 -0700 Subject: [PATCH 0016/5416] x64, x2apic/intr-remap: Fix the need for RMRR in the DMA-remapping detection Presence of RMRR structures is not compulsory for enabling DMA-remapping. Signed-off-by: Suresh Siddha Signed-off-by: Yong Y Wang Cc: Yong Y Wang Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 5c99f997398..903f1701edf 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -419,10 +419,8 @@ int __init dmar_table_init(void) } #ifdef CONFIG_DMAR - if (list_empty(&dmar_rmrr_units)) { + if (list_empty(&dmar_rmrr_units)) printk(KERN_INFO PREFIX "No RMRR found\n"); - return -ENODEV; - } #endif return 0; -- GitLab From ad3ad3f6a2caebf56869b83b69e23eb9fa5e0ab6 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:40 -0700 Subject: [PATCH 0017/5416] x64, x2apic/intr-remap: parse ioapic scope under vt-d structures Parse the vt-d device scope structures to find the mapping between IO-APICs and the interrupt remapping hardware units. This will be used later for enabling Interrupt-remapping for IOAPIC devices. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/Makefile | 2 ++ drivers/pci/dmar.c | 3 ++ drivers/pci/intel-iommu.h | 2 ++ drivers/pci/intr_remapping.c | 70 ++++++++++++++++++++++++++++++++++++ drivers/pci/intr_remapping.h | 6 ++++ include/linux/dmar.h | 1 + 6 files changed, 84 insertions(+) create mode 100644 drivers/pci/intr_remapping.c create mode 100644 drivers/pci/intr_remapping.h diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4d1ce2e7361..1c409c7b0d5 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o # Build Intel IOMMU support obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o +obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o + # # Some architectures use the generic PCI setup functions # diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 903f1701edf..127764cfbe2 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -423,6 +423,9 @@ int __init dmar_table_init(void) printk(KERN_INFO PREFIX "No RMRR found\n"); #endif +#ifdef CONFIG_INTR_REMAP + parse_ioapics_under_ir(); +#endif return 0; } diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 371e3b9caf3..eb167e39b46 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -114,6 +114,8 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define ecap_max_iotlb_offset(e) \ (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16) #define ecap_coherent(e) ((e) & 0x1) +#define ecap_eim_support(e) ((e >> 4) & 0x1) +#define ecap_ir_support(e) ((e >> 3) & 0x1) /* IOTLB_REG */ diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c new file mode 100644 index 00000000000..a80b87921c6 --- /dev/null +++ b/drivers/pci/intr_remapping.c @@ -0,0 +1,70 @@ +#include +#include +#include "intel-iommu.h" +#include "intr_remapping.h" + +static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; +static int ir_ioapic_num; + +static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, + struct intel_iommu *iommu) +{ + struct acpi_dmar_hardware_unit *drhd; + struct acpi_dmar_device_scope *scope; + void *start, *end; + + drhd = (struct acpi_dmar_hardware_unit *)header; + + start = (void *)(drhd + 1); + end = ((void *)drhd) + header->length; + + while (start < end) { + scope = start; + if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) { + if (ir_ioapic_num == MAX_IO_APICS) { + printk(KERN_WARNING "Exceeded Max IO APICS\n"); + return -1; + } + + printk(KERN_INFO "IOAPIC id %d under DRHD base" + " 0x%Lx\n", scope->enumeration_id, + drhd->address); + + ir_ioapic[ir_ioapic_num].iommu = iommu; + ir_ioapic[ir_ioapic_num].id = scope->enumeration_id; + ir_ioapic_num++; + } + start += scope->length; + } + + return 0; +} + +/* + * Finds the assocaition between IOAPIC's and its Interrupt-remapping + * hardware unit. + */ +int __init parse_ioapics_under_ir(void) +{ + struct dmar_drhd_unit *drhd; + int ir_supported = 0; + + for_each_drhd_unit(drhd) { + struct intel_iommu *iommu = drhd->iommu; + + if (ecap_ir_support(iommu->ecap)) { + if (ir_parse_ioapic_scope(drhd->hdr, iommu)) + return -1; + + ir_supported = 1; + } + } + + if (ir_supported && ir_ioapic_num != nr_ioapics) { + printk(KERN_WARNING + "Not all IO-APIC's listed under remapping hardware\n"); + return -1; + } + + return ir_supported; +} diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h new file mode 100644 index 00000000000..c4a40b2f33f --- /dev/null +++ b/drivers/pci/intr_remapping.h @@ -0,0 +1,6 @@ +#include "intel-iommu.h" + +struct ioapic_scope { + struct intel_iommu *iommu; + unsigned int id; +}; diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 3ab07e42558..c4e96eb2961 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -47,6 +47,7 @@ extern int intel_iommu_init(void); extern int dmar_table_init(void); extern int early_dmar_detect(void); extern int dmar_dev_scope_init(void); +extern int parse_ioapics_under_ir(void); extern struct list_head dmar_drhd_units; extern struct list_head dmar_rmrr_units; -- GitLab From cf1337f0447e5be8e66daa944f0ea3bcac2b6179 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:41 -0700 Subject: [PATCH 0018/5416] x64, x2apic/intr-remap: move IOMMU_WAIT_OP() macro to intel-iommu.h move IOMMU_WAIT_OP() macro to header file. This will be used by both DMA-remapping and Intr-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/intel-iommu.c | 15 --------------- drivers/pci/intel-iommu.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 218a1f357b4..fb701d9dd8c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -49,8 +49,6 @@ #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 -#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */ - #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) @@ -486,19 +484,6 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) return 0; } -#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ -{\ - cycles_t start_time = get_cycles();\ - while (1) {\ - sts = op (iommu->reg + offset);\ - if (cond)\ - break;\ - if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\ - panic("DMAR hardware is malfunctioning\n");\ - cpu_relax();\ - }\ -} - static void iommu_set_root_entry(struct intel_iommu *iommu) { void *addr; diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index eb167e39b46..3a650e8cba3 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -177,6 +177,21 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define dma_frcd_source_id(c) (c & 0xffff) #define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */ +#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */ + +#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ +{\ + cycles_t start_time = get_cycles();\ + while (1) {\ + sts = op (iommu->reg + offset);\ + if (cond)\ + break;\ + if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\ + panic("DMAR hardware is malfunctioning\n");\ + cpu_relax();\ + }\ +} + struct intel_iommu { void __iomem *reg; /* Pointer to hardware regs, virtual addr */ u64 cap; -- GitLab From fe962e90cb17a8426e144dee970e77ed789d98ee Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:42 -0700 Subject: [PATCH 0019/5416] x64, x2apic/intr-remap: Queued invalidation infrastructure (part of VT-d) Queued invalidation (part of Intel Virtualization Technology for Directed I/O architecture) infrastructure. This will be used for invalidating the interrupt entry cache in the case of Interrupt-remapping and IOTLB invalidation in the case of DMA-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 150 ++++++++++++++++++++++++++++++++++++++ drivers/pci/intel-iommu.c | 7 -- drivers/pci/intel-iommu.h | 61 ++++++++++++++++ 3 files changed, 211 insertions(+), 7 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 127764cfbe2..aba151ca6d2 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -28,6 +28,7 @@ #include #include +#include #include "iova.h" #include "intel-iommu.h" @@ -509,3 +510,152 @@ void free_iommu(struct intel_iommu *iommu) iounmap(iommu->reg); kfree(iommu); } + +/* + * Reclaim all the submitted descriptors which have completed its work. + */ +static inline void reclaim_free_desc(struct q_inval *qi) +{ + while (qi->desc_status[qi->free_tail] == QI_DONE) { + qi->desc_status[qi->free_tail] = QI_FREE; + qi->free_tail = (qi->free_tail + 1) % QI_LENGTH; + qi->free_cnt++; + } +} + +/* + * Submit the queued invalidation descriptor to the remapping + * hardware unit and wait for its completion. + */ +void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) +{ + struct q_inval *qi = iommu->qi; + struct qi_desc *hw, wait_desc; + int wait_index, index; + unsigned long flags; + + if (!qi) + return; + + hw = qi->desc; + + spin_lock(&qi->q_lock); + while (qi->free_cnt < 3) { + spin_unlock(&qi->q_lock); + cpu_relax(); + spin_lock(&qi->q_lock); + } + + index = qi->free_head; + wait_index = (index + 1) % QI_LENGTH; + + qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE; + + hw[index] = *desc; + + wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; + wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]); + + hw[wait_index] = wait_desc; + + __iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc)); + __iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc)); + + qi->free_head = (qi->free_head + 2) % QI_LENGTH; + qi->free_cnt -= 2; + + spin_lock_irqsave(&iommu->register_lock, flags); + /* + * update the HW tail register indicating the presence of + * new descriptors. + */ + writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG); + spin_unlock_irqrestore(&iommu->register_lock, flags); + + while (qi->desc_status[wait_index] != QI_DONE) { + spin_unlock(&qi->q_lock); + cpu_relax(); + spin_lock(&qi->q_lock); + } + + qi->desc_status[index] = QI_DONE; + + reclaim_free_desc(qi); + spin_unlock(&qi->q_lock); +} + +/* + * Flush the global interrupt entry cache. + */ +void qi_global_iec(struct intel_iommu *iommu) +{ + struct qi_desc desc; + + desc.low = QI_IEC_TYPE; + desc.high = 0; + + qi_submit_sync(&desc, iommu); +} + +/* + * Enable Queued Invalidation interface. This is a must to support + * interrupt-remapping. Also used by DMA-remapping, which replaces + * register based IOTLB invalidation. + */ +int dmar_enable_qi(struct intel_iommu *iommu) +{ + u32 cmd, sts; + unsigned long flags; + struct q_inval *qi; + + if (!ecap_qis(iommu->ecap)) + return -ENOENT; + + /* + * queued invalidation is already setup and enabled. + */ + if (iommu->qi) + return 0; + + iommu->qi = kmalloc(sizeof(*qi), GFP_KERNEL); + if (!iommu->qi) + return -ENOMEM; + + qi = iommu->qi; + + qi->desc = (void *)(get_zeroed_page(GFP_KERNEL)); + if (!qi->desc) { + kfree(qi); + iommu->qi = 0; + return -ENOMEM; + } + + qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_KERNEL); + if (!qi->desc_status) { + free_page((unsigned long) qi->desc); + kfree(qi); + iommu->qi = 0; + return -ENOMEM; + } + + qi->free_head = qi->free_tail = 0; + qi->free_cnt = QI_LENGTH; + + spin_lock_init(&qi->q_lock); + + spin_lock_irqsave(&iommu->register_lock, flags); + /* write zero to the tail reg */ + writel(0, iommu->reg + DMAR_IQT_REG); + + dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc)); + + cmd = iommu->gcmd | DMA_GCMD_QIE; + iommu->gcmd |= DMA_GCMD_QIE; + writel(cmd, iommu->reg + DMAR_GCMD_REG); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts); + spin_unlock_irqrestore(&iommu->register_lock, flags); + + return 0; +} diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fb701d9dd8c..347bf2e4716 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -181,13 +181,6 @@ void free_iova_mem(struct iova *iova) kmem_cache_free(iommu_iova_cache, iova); } -static inline void __iommu_flush_cache( - struct intel_iommu *iommu, void *addr, int size) -{ - if (!ecap_coherent(iommu->ecap)) - clflush_cache_range(addr, size); -} - /* Gets context entry for a given bus and devfn */ static struct context_entry * device_to_context_entry(struct intel_iommu *iommu, u8 bus, u8 devfn) diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 3a650e8cba3..2983ce89535 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -27,6 +27,7 @@ #include #include "iova.h" #include +#include #include "dma_remapping.h" /* @@ -51,6 +52,10 @@ #define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */ #define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */ #define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */ +#define DMAR_IQH_REG 0x80 /* Invalidation queue head register */ +#define DMAR_IQT_REG 0x88 /* Invalidation queue tail register */ +#define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */ +#define DMAR_ICS_REG 0x98 /* Invalidation complete status register */ #define OFFSET_STRIDE (9) /* @@ -114,6 +119,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define ecap_max_iotlb_offset(e) \ (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16) #define ecap_coherent(e) ((e) & 0x1) +#define ecap_qis(e) ((e) & 0x2) #define ecap_eim_support(e) ((e >> 4) & 0x1) #define ecap_ir_support(e) ((e >> 3) & 0x1) @@ -131,6 +137,17 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define DMA_TLB_IH_NONLEAF (((u64)1) << 6) #define DMA_TLB_MAX_SIZE (0x3f) +/* INVALID_DESC */ +#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 3) +#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 3) +#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 3) +#define DMA_ID_TLB_READ_DRAIN (((u64)1) << 7) +#define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6) +#define DMA_ID_TLB_DID(id) (((u64)((id & 0xffff) << 16))) +#define DMA_ID_TLB_IH_NONLEAF (((u64)1) << 6) +#define DMA_ID_TLB_ADDR(addr) (addr) +#define DMA_ID_TLB_ADDR_MASK(mask) (mask) + /* PMEN_REG */ #define DMA_PMEN_EPM (((u32)1)<<31) #define DMA_PMEN_PRS (((u32)1)<<0) @@ -140,6 +157,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define DMA_GCMD_SRTP (((u32)1) << 30) #define DMA_GCMD_SFL (((u32)1) << 29) #define DMA_GCMD_EAFL (((u32)1) << 28) +#define DMA_GCMD_QIE (((u32)1) << 26) #define DMA_GCMD_WBF (((u32)1) << 27) /* GSTS_REG */ @@ -147,6 +165,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define DMA_GSTS_RTPS (((u32)1) << 30) #define DMA_GSTS_FLS (((u32)1) << 29) #define DMA_GSTS_AFLS (((u32)1) << 28) +#define DMA_GSTS_QIES (((u32)1) << 26) #define DMA_GSTS_WBFS (((u32)1) << 27) /* CCMD_REG */ @@ -192,6 +211,40 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) }\ } +#define QI_LENGTH 256 /* queue length */ + +enum { + QI_FREE, + QI_IN_USE, + QI_DONE +}; + +#define QI_CC_TYPE 0x1 +#define QI_IOTLB_TYPE 0x2 +#define QI_DIOTLB_TYPE 0x3 +#define QI_IEC_TYPE 0x4 +#define QI_IWD_TYPE 0x5 + +#define QI_IEC_SELECTIVE (((u64)1) << 4) +#define QI_IEC_IIDEX(idx) (((u64)(idx & 0xffff) << 32)) +#define QI_IEC_IM(m) (((u64)(m & 0x1f) << 27)) + +#define QI_IWD_STATUS_DATA(d) (((u64)d) << 32) +#define QI_IWD_STATUS_WRITE (((u64)1) << 5) + +struct qi_desc { + u64 low, high; +}; + +struct q_inval { + spinlock_t q_lock; + struct qi_desc *desc; /* invalidation queue */ + int *desc_status; /* desc status */ + int free_head; /* first free entry */ + int free_tail; /* last free entry */ + int free_cnt; +}; + struct intel_iommu { void __iomem *reg; /* Pointer to hardware regs, virtual addr */ u64 cap; @@ -212,8 +265,16 @@ struct intel_iommu { struct msi_msg saved_msg; struct sys_device sysdev; #endif + struct q_inval *qi; /* Queued invalidation info */ }; +static inline void __iommu_flush_cache( + struct intel_iommu *iommu, void *addr, int size) +{ + if (!ecap_coherent(iommu->ecap)) + clflush_cache_range(addr, size); +} + extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); extern int alloc_iommu(struct dmar_drhd_unit *drhd); -- GitLab From 2ae21010694e56461a63bfc80e960090ce0a5ed9 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:43 -0700 Subject: [PATCH 0020/5416] x64, x2apic/intr-remap: Interrupt remapping infrastructure Interrupt remapping (part of Intel Virtualization Tech for directed I/O) infrastructure. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dma_remapping.h | 2 + drivers/pci/dmar.c | 16 ++++ drivers/pci/intel-iommu.c | 21 ++---- drivers/pci/intel-iommu.h | 24 +++++- drivers/pci/intr_remapping.c | 137 +++++++++++++++++++++++++++++++++++ drivers/pci/intr_remapping.h | 2 + include/linux/dmar.h | 120 +++++++++++++++++++++--------- 7 files changed, 272 insertions(+), 50 deletions(-) diff --git a/drivers/pci/dma_remapping.h b/drivers/pci/dma_remapping.h index 05aac8ef96c..bff5c65f81d 100644 --- a/drivers/pci/dma_remapping.h +++ b/drivers/pci/dma_remapping.h @@ -145,6 +145,8 @@ struct device_domain_info { extern int init_dmars(void); extern void free_dmar_iommu(struct intel_iommu *iommu); +extern int dmar_disabled; + #ifndef CONFIG_DMAR_GFX_WA static inline void iommu_prepare_gfx_mapping(void) { diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index aba151ca6d2..23a119e6485 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -449,6 +449,22 @@ int __init early_dmar_detect(void) return (ACPI_SUCCESS(status) ? 1 : 0); } +void __init detect_intel_iommu(void) +{ + int ret; + + ret = early_dmar_detect(); + +#ifdef CONFIG_DMAR + { + if (ret && !no_iommu && !iommu_detected && !swiotlb && + !dmar_disabled) + iommu_detected = 1; + } +#endif +} + + int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 347bf2e4716..ffccf2341b9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -76,7 +76,7 @@ static long list_size; static void domain_remove_dev_info(struct dmar_domain *domain); -static int dmar_disabled; +int dmar_disabled; static int __initdata dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -2238,15 +2238,6 @@ static void __init iommu_exit_mempool(void) } -void __init detect_intel_iommu(void) -{ - if (swiotlb || no_iommu || iommu_detected || dmar_disabled) - return; - if (early_dmar_detect()) { - iommu_detected = 1; - } -} - static void __init init_no_remapping_devices(void) { struct dmar_drhd_unit *drhd; @@ -2293,15 +2284,19 @@ int __init intel_iommu_init(void) { int ret = 0; - if (no_iommu || swiotlb || dmar_disabled) - return -ENODEV; - if (dmar_table_init()) return -ENODEV; if (dmar_dev_scope_init()) return -ENODEV; + /* + * Check the need for DMA-remapping initialization now. + * Above initialization will also be used by Interrupt-remapping. + */ + if (no_iommu || swiotlb || dmar_disabled) + return -ENODEV; + iommu_init_mempool(); dmar_init_reserved_ranges(); diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 2983ce89535..a81a74e2bd9 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -56,6 +56,7 @@ #define DMAR_IQT_REG 0x88 /* Invalidation queue tail register */ #define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */ #define DMAR_ICS_REG 0x98 /* Invalidation complete status register */ +#define DMAR_IRTA_REG 0xb8 /* Interrupt remapping table addr register */ #define OFFSET_STRIDE (9) /* @@ -157,16 +158,20 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define DMA_GCMD_SRTP (((u32)1) << 30) #define DMA_GCMD_SFL (((u32)1) << 29) #define DMA_GCMD_EAFL (((u32)1) << 28) -#define DMA_GCMD_QIE (((u32)1) << 26) #define DMA_GCMD_WBF (((u32)1) << 27) +#define DMA_GCMD_QIE (((u32)1) << 26) +#define DMA_GCMD_SIRTP (((u32)1) << 24) +#define DMA_GCMD_IRE (((u32) 1) << 25) /* GSTS_REG */ #define DMA_GSTS_TES (((u32)1) << 31) #define DMA_GSTS_RTPS (((u32)1) << 30) #define DMA_GSTS_FLS (((u32)1) << 29) #define DMA_GSTS_AFLS (((u32)1) << 28) -#define DMA_GSTS_QIES (((u32)1) << 26) #define DMA_GSTS_WBFS (((u32)1) << 27) +#define DMA_GSTS_QIES (((u32)1) << 26) +#define DMA_GSTS_IRTPS (((u32)1) << 24) +#define DMA_GSTS_IRES (((u32)1) << 25) /* CCMD_REG */ #define DMA_CCMD_ICC (((u64)1) << 63) @@ -245,6 +250,16 @@ struct q_inval { int free_cnt; }; +#ifdef CONFIG_INTR_REMAP +/* 1MB - maximum possible interrupt remapping table size */ +#define INTR_REMAP_PAGE_ORDER 8 +#define INTR_REMAP_TABLE_REG_SIZE 0xf + +struct ir_table { + struct irte *base; +}; +#endif + struct intel_iommu { void __iomem *reg; /* Pointer to hardware regs, virtual addr */ u64 cap; @@ -266,6 +281,9 @@ struct intel_iommu { struct sys_device sysdev; #endif struct q_inval *qi; /* Queued invalidation info */ +#ifdef CONFIG_INTR_REMAP + struct ir_table *ir_table; /* Interrupt remapping info */ +#endif }; static inline void __iommu_flush_cache( @@ -279,5 +297,7 @@ extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); extern int alloc_iommu(struct dmar_drhd_unit *drhd); extern void free_iommu(struct intel_iommu *iommu); +extern int dmar_enable_qi(struct intel_iommu *iommu); +extern void qi_global_iec(struct intel_iommu *iommu); #endif diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index a80b87921c6..3d10cdc9031 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -1,10 +1,147 @@ #include +#include +#include +#include #include #include "intel-iommu.h" #include "intr_remapping.h" static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; static int ir_ioapic_num; +int intr_remapping_enabled; + +static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) +{ + u64 addr; + u32 cmd, sts; + unsigned long flags; + + addr = virt_to_phys((void *)iommu->ir_table->base); + + spin_lock_irqsave(&iommu->register_lock, flags); + + dmar_writeq(iommu->reg + DMAR_IRTA_REG, + (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE); + + /* Set interrupt-remapping table pointer */ + cmd = iommu->gcmd | DMA_GCMD_SIRTP; + writel(cmd, iommu->reg + DMAR_GCMD_REG); + + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (sts & DMA_GSTS_IRTPS), sts); + spin_unlock_irqrestore(&iommu->register_lock, flags); + + /* + * global invalidation of interrupt entry cache before enabling + * interrupt-remapping. + */ + qi_global_iec(iommu); + + spin_lock_irqsave(&iommu->register_lock, flags); + + /* Enable interrupt-remapping */ + cmd = iommu->gcmd | DMA_GCMD_IRE; + iommu->gcmd |= DMA_GCMD_IRE; + writel(cmd, iommu->reg + DMAR_GCMD_REG); + + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (sts & DMA_GSTS_IRES), sts); + + spin_unlock_irqrestore(&iommu->register_lock, flags); +} + + +static int setup_intr_remapping(struct intel_iommu *iommu, int mode) +{ + struct ir_table *ir_table; + struct page *pages; + + ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table), + GFP_KERNEL); + + if (!iommu->ir_table) + return -ENOMEM; + + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER); + + if (!pages) { + printk(KERN_ERR "failed to allocate pages of order %d\n", + INTR_REMAP_PAGE_ORDER); + kfree(iommu->ir_table); + return -ENOMEM; + } + + ir_table->base = page_address(pages); + + iommu_set_intr_remapping(iommu, mode); + return 0; +} + +int __init enable_intr_remapping(int eim) +{ + struct dmar_drhd_unit *drhd; + int setup = 0; + + /* + * check for the Interrupt-remapping support + */ + for_each_drhd_unit(drhd) { + struct intel_iommu *iommu = drhd->iommu; + + if (!ecap_ir_support(iommu->ecap)) + continue; + + if (eim && !ecap_eim_support(iommu->ecap)) { + printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " + " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); + return -1; + } + } + + /* + * Enable queued invalidation for all the DRHD's. + */ + for_each_drhd_unit(drhd) { + int ret; + struct intel_iommu *iommu = drhd->iommu; + ret = dmar_enable_qi(iommu); + + if (ret) { + printk(KERN_ERR "DRHD %Lx: failed to enable queued, " + " invalidation, ecap %Lx, ret %d\n", + drhd->reg_base_addr, iommu->ecap, ret); + return -1; + } + } + + /* + * Setup Interrupt-remapping for all the DRHD's now. + */ + for_each_drhd_unit(drhd) { + struct intel_iommu *iommu = drhd->iommu; + + if (!ecap_ir_support(iommu->ecap)) + continue; + + if (setup_intr_remapping(iommu, eim)) + goto error; + + setup = 1; + } + + if (!setup) + goto error; + + intr_remapping_enabled = 1; + + return 0; + +error: + /* + * handle error condition gracefully here! + */ + return -1; +} static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, struct intel_iommu *iommu) diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h index c4a40b2f33f..05f2635bbe4 100644 --- a/drivers/pci/intr_remapping.h +++ b/drivers/pci/intr_remapping.h @@ -4,3 +4,5 @@ struct ioapic_scope { struct intel_iommu *iommu; unsigned int id; }; + +#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index c4e96eb2961..8a0238dd2c1 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -25,9 +25,85 @@ #include #include -#ifdef CONFIG_DMAR +#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) struct intel_iommu; +struct dmar_drhd_unit { + struct list_head list; /* list of drhd units */ + struct acpi_dmar_header *hdr; /* ACPI header */ + u64 reg_base_addr; /* register base address*/ + struct pci_dev **devices; /* target device array */ + int devices_cnt; /* target device count */ + u8 ignored:1; /* ignore drhd */ + u8 include_all:1; + struct intel_iommu *iommu; +}; + +extern struct list_head dmar_drhd_units; + +#define for_each_drhd_unit(drhd) \ + list_for_each_entry(drhd, &dmar_drhd_units, list) + +extern int dmar_table_init(void); +extern int early_dmar_detect(void); +extern int dmar_dev_scope_init(void); + +/* Intel IOMMU detection */ +extern void detect_intel_iommu(void); + + +extern int parse_ioapics_under_ir(void); +extern int alloc_iommu(struct dmar_drhd_unit *); +#else +static inline void detect_intel_iommu(void) +{ + return; +} + +static inline int dmar_table_init(void) +{ + return -ENODEV; +} +#endif /* !CONFIG_DMAR && !CONFIG_INTR_REMAP */ + +#ifdef CONFIG_INTR_REMAP +extern int intr_remapping_enabled; +extern int enable_intr_remapping(int); + +struct irte { + union { + struct { + __u64 present : 1, + fpd : 1, + dst_mode : 1, + redir_hint : 1, + trigger_mode : 1, + dlvry_mode : 3, + avail : 4, + __reserved_1 : 4, + vector : 8, + __reserved_2 : 8, + dest_id : 32; + }; + __u64 low; + }; + + union { + struct { + __u64 sid : 16, + sq : 2, + svt : 2, + __reserved_3 : 44; + }; + __u64 high; + }; +}; +#else +#define enable_intr_remapping(mode) (-1) +#define intr_remapping_enabled (0) +#endif + +#ifdef CONFIG_DMAR extern const char *dmar_get_fault_reason(u8 fault_reason); /* Can't use the common MSI interrupt functions @@ -40,29 +116,8 @@ extern void dmar_msi_write(int irq, struct msi_msg *msg); extern int dmar_set_interrupt(struct intel_iommu *iommu); extern int arch_setup_dmar_msi(unsigned int irq); -/* Intel IOMMU detection and initialization functions */ -extern void detect_intel_iommu(void); -extern int intel_iommu_init(void); - -extern int dmar_table_init(void); -extern int early_dmar_detect(void); -extern int dmar_dev_scope_init(void); -extern int parse_ioapics_under_ir(void); - -extern struct list_head dmar_drhd_units; +extern int iommu_detected, no_iommu; extern struct list_head dmar_rmrr_units; - -struct dmar_drhd_unit { - struct list_head list; /* list of drhd units */ - struct acpi_dmar_header *hdr; /* ACPI header */ - u64 reg_base_addr; /* register base address*/ - struct pci_dev **devices; /* target device array */ - int devices_cnt; /* target device count */ - u8 ignored:1; /* ignore drhd */ - u8 include_all:1; - struct intel_iommu *iommu; -}; - struct dmar_rmrr_unit { struct list_head list; /* list of rmrr units */ struct acpi_dmar_header *hdr; /* ACPI header */ @@ -72,24 +127,19 @@ struct dmar_rmrr_unit { int devices_cnt; /* target device count */ }; -#define for_each_drhd_unit(drhd) \ - list_for_each_entry(drhd, &dmar_drhd_units, list) #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, &dmar_rmrr_units, list) - -extern int alloc_iommu(struct dmar_drhd_unit *); +/* Intel DMAR initialization functions */ +extern int intel_iommu_init(void); +extern int dmar_disabled; #else -static inline void detect_intel_iommu(void) -{ - return; -} static inline int intel_iommu_init(void) { +#ifdef CONFIG_INTR_REMAP + return dmar_dev_scope_init(); +#else return -ENODEV; -} -static inline int dmar_table_init(void) -{ - return -ENODEV; +#endif } #endif /* !CONFIG_DMAR */ #endif /* __DMAR_H__ */ -- GitLab From b6fcb33ad6c05f152a672f7c96c1fab006527b80 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:44 -0700 Subject: [PATCH 0021/5416] x64, x2apic/intr-remap: routines managing Interrupt remapping table entries. Routines handling the management of interrupt remapping table entries. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/intel-iommu.h | 4 + drivers/pci/intr_remapping.c | 243 +++++++++++++++++++++++++++++++++++ include/linux/dmar.h | 12 ++ 3 files changed, 259 insertions(+) diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index a81a74e2bd9..2142c01e014 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h @@ -123,6 +123,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) #define ecap_qis(e) ((e) & 0x2) #define ecap_eim_support(e) ((e >> 4) & 0x1) #define ecap_ir_support(e) ((e >> 3) & 0x1) +#define ecap_max_handle_mask(e) ((e >> 20) & 0xf) /* IOTLB_REG */ @@ -255,6 +256,8 @@ struct q_inval { #define INTR_REMAP_PAGE_ORDER 8 #define INTR_REMAP_TABLE_REG_SIZE 0xf +#define INTR_REMAP_TABLE_ENTRIES 65536 + struct ir_table { struct irte *base; }; @@ -300,4 +303,5 @@ extern void free_iommu(struct intel_iommu *iommu); extern int dmar_enable_qi(struct intel_iommu *iommu); extern void qi_global_iec(struct intel_iommu *iommu); +extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); #endif diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 3d10cdc9031..bddb4b19b6c 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "intel-iommu.h" #include "intr_remapping.h" @@ -10,6 +11,248 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; static int ir_ioapic_num; int intr_remapping_enabled; +static struct { + struct intel_iommu *iommu; + u16 irte_index; + u16 sub_handle; + u8 irte_mask; +} irq_2_iommu[NR_IRQS]; + +static DEFINE_SPINLOCK(irq_2_ir_lock); + +int irq_remapped(int irq) +{ + if (irq > NR_IRQS) + return 0; + + if (!irq_2_iommu[irq].iommu) + return 0; + + return 1; +} + +int get_irte(int irq, struct irte *entry) +{ + int index; + + if (!entry || irq > NR_IRQS) + return -1; + + spin_lock(&irq_2_ir_lock); + if (!irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle; + *entry = *(irq_2_iommu[irq].iommu->ir_table->base + index); + + spin_unlock(&irq_2_ir_lock); + return 0; +} + +int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) +{ + struct ir_table *table = iommu->ir_table; + u16 index, start_index; + unsigned int mask = 0; + int i; + + if (!count) + return -1; + + /* + * start the IRTE search from index 0. + */ + index = start_index = 0; + + if (count > 1) { + count = __roundup_pow_of_two(count); + mask = ilog2(count); + } + + if (mask > ecap_max_handle_mask(iommu->ecap)) { + printk(KERN_ERR + "Requested mask %x exceeds the max invalidation handle" + " mask value %Lx\n", mask, + ecap_max_handle_mask(iommu->ecap)); + return -1; + } + + spin_lock(&irq_2_ir_lock); + do { + for (i = index; i < index + count; i++) + if (table->base[i].present) + break; + /* empty index found */ + if (i == index + count) + break; + + index = (index + count) % INTR_REMAP_TABLE_ENTRIES; + + if (index == start_index) { + spin_unlock(&irq_2_ir_lock); + printk(KERN_ERR "can't allocate an IRTE\n"); + return -1; + } + } while (1); + + for (i = index; i < index + count; i++) + table->base[i].present = 1; + + irq_2_iommu[irq].iommu = iommu; + irq_2_iommu[irq].irte_index = index; + irq_2_iommu[irq].sub_handle = 0; + irq_2_iommu[irq].irte_mask = mask; + + spin_unlock(&irq_2_ir_lock); + + return index; +} + +static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask) +{ + struct qi_desc desc; + + desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask) + | QI_IEC_SELECTIVE; + desc.high = 0; + + qi_submit_sync(&desc, iommu); +} + +int map_irq_to_irte_handle(int irq, u16 *sub_handle) +{ + int index; + + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + *sub_handle = irq_2_iommu[irq].sub_handle; + index = irq_2_iommu[irq].irte_index; + spin_unlock(&irq_2_ir_lock); + return index; +} + +int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) +{ + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + irq_2_iommu[irq].iommu = iommu; + irq_2_iommu[irq].irte_index = index; + irq_2_iommu[irq].sub_handle = subhandle; + irq_2_iommu[irq].irte_mask = 0; + + spin_unlock(&irq_2_ir_lock); + + return 0; +} + +int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index) +{ + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + irq_2_iommu[irq].iommu = NULL; + irq_2_iommu[irq].irte_index = 0; + irq_2_iommu[irq].sub_handle = 0; + irq_2_iommu[irq].irte_mask = 0; + + spin_unlock(&irq_2_ir_lock); + + return 0; +} + +int modify_irte(int irq, struct irte *irte_modified) +{ + int index; + struct irte *irte; + struct intel_iommu *iommu; + + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + iommu = irq_2_iommu[irq].iommu; + + index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle; + irte = &iommu->ir_table->base[index]; + + set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); + __iommu_flush_cache(iommu, irte, sizeof(*irte)); + + qi_flush_iec(iommu, index, 0); + + spin_unlock(&irq_2_ir_lock); + return 0; +} + +int flush_irte(int irq) +{ + int index; + struct intel_iommu *iommu; + + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + iommu = irq_2_iommu[irq].iommu; + + index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle; + + qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask); + spin_unlock(&irq_2_ir_lock); + + return 0; +} + +int free_irte(int irq) +{ + int index, i; + struct irte *irte; + struct intel_iommu *iommu; + + spin_lock(&irq_2_ir_lock); + if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) { + spin_unlock(&irq_2_ir_lock); + return -1; + } + + iommu = irq_2_iommu[irq].iommu; + + index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle; + irte = &iommu->ir_table->base[index]; + + if (!irq_2_iommu[irq].sub_handle) { + for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++) + set_64bit((unsigned long *)irte, 0); + qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask); + } + + irq_2_iommu[irq].iommu = NULL; + irq_2_iommu[irq].irte_index = 0; + irq_2_iommu[irq].sub_handle = 0; + irq_2_iommu[irq].irte_mask = 0; + + spin_unlock(&irq_2_ir_lock); + + return 0; +} + static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) { u64 addr; diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 8a0238dd2c1..324bbca85a2 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -98,7 +98,19 @@ struct irte { __u64 high; }; }; +extern int get_irte(int irq, struct irte *entry); +extern int modify_irte(int irq, struct irte *irte_modified); +extern int alloc_irte(struct intel_iommu *iommu, int irq, u16 count); +extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, + u16 sub_handle); +extern int map_irq_to_irte_handle(int irq, u16 *sub_handle); +extern int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index); +extern int flush_irte(int irq); +extern int free_irte(int irq); + +extern int irq_remapped(int irq); #else +#define irq_remapped(irq) (0) #define enable_intr_remapping(mode) (-1) #define intr_remapping_enabled (0) #endif -- GitLab From 72b1e22dfcad1daca6906148fd956ffe404bb0bc Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:45 -0700 Subject: [PATCH 0022/5416] x64, x2apic/intr-remap: generic irq migration support from process context Generic infrastructure for migrating the irq from the process context in the presence of CONFIG_GENERIC_PENDING_IRQ. This will be used later for migrating irq in the presence of interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- include/linux/irq.h | 1 + kernel/irq/manage.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 552e0ec269c..c211984b55e 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -62,6 +62,7 @@ typedef void (*irq_flow_handler_t)(unsigned int irq, #define IRQ_MOVE_PENDING 0x00200000 /* need to re-target IRQ destination */ #define IRQ_NO_BALANCING 0x00400000 /* IRQ is excluded from balancing */ #define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */ +#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */ #ifdef CONFIG_IRQ_PER_CPU # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 46d6611a33b..628b5572a7c 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -87,7 +87,14 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask) set_balance_irq_affinity(irq, cpumask); #ifdef CONFIG_GENERIC_PENDING_IRQ - set_pending_irq(irq, cpumask); + if (desc->status & IRQ_MOVE_PCNTXT) { + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + desc->chip->set_affinity(irq, cpumask); + spin_unlock_irqrestore(&desc->lock, flags); + } else + set_pending_irq(irq, cpumask); #else desc->affinity = cpumask; desc->chip->set_affinity(irq, cpumask); -- GitLab From d94d93ca5cc36cd78c532def62772c98fe8ba5d7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:46 -0700 Subject: [PATCH 0023/5416] x64, x2apic/intr-remap: 8259 specific mask/unmask routines 8259 specific mask/unmask routines which be used later while enabling interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/i8259.c | 24 ++++++++++++++++++++++++ include/asm-x86/i8259.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index dc92b49d920..4b8a53d841f 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -282,6 +282,30 @@ static int __init i8259A_init_sysfs(void) device_initcall(i8259A_init_sysfs); +void mask_8259A(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +void unmask_8259A(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ + outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + void init_8259A(int auto_eoi) { unsigned long flags; diff --git a/include/asm-x86/i8259.h b/include/asm-x86/i8259.h index 2f98df91f1f..31112b6c595 100644 --- a/include/asm-x86/i8259.h +++ b/include/asm-x86/i8259.h @@ -57,4 +57,7 @@ static inline void outb_pic(unsigned char value, unsigned int port) extern struct irq_chip i8259A_chip; +extern void mask_8259A(void); +extern void unmask_8259A(void); + #endif /* __ASM_I8259_H__ */ -- GitLab From 4dc2f96cacd1e74c688f94348a3bfd0a980817d5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:47 -0700 Subject: [PATCH 0024/5416] x64, x2apic/intr-remap: ioapic routines which deal with initial io-apic RTE setup Generic ioapic specific routines which be used later during enabling interrupt-remapping. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 66 ++++++++++++++++++++++++++++++++++++ include/asm-x86/io_apic.h | 6 ++++ 2 files changed, 72 insertions(+) diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 9e645cba11c..84dd63c13d6 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -114,6 +114,9 @@ DEFINE_SPINLOCK(vector_lock); */ int nr_ioapic_registers[MAX_IO_APICS]; +/* I/O APIC RTE contents at the OS boot up */ +struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; + /* I/O APIC entries */ struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; int nr_ioapics; @@ -446,6 +449,69 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } +/* + * Saves and masks all the unmasked IO-APIC RTE's + */ +int save_mask_IO_APIC_setup(void) +{ + union IO_APIC_reg_01 reg_01; + unsigned long flags; + int apic, pin; + + /* + * The number of IO-APIC IRQ registers (== #pins): + */ + for (apic = 0; apic < nr_ioapics; apic++) { + spin_lock_irqsave(&ioapic_lock, flags); + reg_01.raw = io_apic_read(apic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + nr_ioapic_registers[apic] = reg_01.bits.entries+1; + } + + for (apic = 0; apic < nr_ioapics; apic++) { + early_ioapic_entries[apic] = + kzalloc(sizeof(struct IO_APIC_route_entry) * + nr_ioapic_registers[apic], GFP_KERNEL); + if (!early_ioapic_entries[apic]) + return -ENOMEM; + } + + for (apic = 0; apic < nr_ioapics; apic++) + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { + struct IO_APIC_route_entry entry; + + entry = early_ioapic_entries[apic][pin] = + ioapic_read_entry(apic, pin); + if (!entry.mask) { + entry.mask = 1; + ioapic_write_entry(apic, pin, entry); + } + } + return 0; +} + +void restore_IO_APIC_setup(void) +{ + int apic, pin; + + for (apic = 0; apic < nr_ioapics; apic++) + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) + ioapic_write_entry(apic, pin, + early_ioapic_entries[apic][pin]); +} + +void reinit_intr_remapped_IO_APIC(int intr_remapping) +{ + /* + * for now plain restore of previous settings. + * TBD: In the case of OS enabling interrupt-remapping, + * IO-APIC RTE's need to be setup to point to interrupt-remapping + * table entries. for now, do a plain restore, and wait for + * the setup_IO_APIC_irqs() to do proper initialization. + */ + restore_IO_APIC_setup(); +} + int skip_ioapic_setup; int ioapic_force; diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h index 14f82bbcb5f..1c4a99d882f 100644 --- a/include/asm-x86/io_apic.h +++ b/include/asm-x86/io_apic.h @@ -183,6 +183,12 @@ extern int io_apic_set_pci_routing(int ioapic, int pin, int irq, extern int (*ioapic_renumber_irq)(int ioapic, int irq); extern void ioapic_init_mappings(void); +#ifdef CONFIG_X86_64 +extern int save_mask_IO_APIC_setup(void); +extern void restore_IO_APIC_setup(void); +extern void reinit_intr_remapped_IO_APIC(int); +#endif + #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 static const int timer_through_8259 = 0; -- GitLab From 0c81c746f9bdbfaafe64322d540c8b7b59c27314 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:48 -0700 Subject: [PATCH 0025/5416] x64, x2apic/intr-remap: introduce read_apic_id() to genapic routines Move the read_apic_id() to genapic routines. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 5 +++++ arch/x86/kernel/genapic_64.c | 11 ----------- arch/x86/kernel/genapic_flat_64.c | 14 +++++++++++++- arch/x86/kernel/genx2apic_uv_x.c | 14 +++++++++++++- include/asm-x86/genapic_64.h | 1 + include/asm-x86/mach-default/mach_apic.h | 1 + include/asm-x86/mach-default/mach_apicdef.h | 3 ++- include/asm-x86/smp.h | 4 +--- 8 files changed, 36 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 1e3d32e27c1..9dd4ee4735f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1096,6 +1096,11 @@ void __cpuinit generic_processor_info(int apicid, int version) cpu_set(cpu, cpu_present_map); } +int hard_smp_processor_id(void) +{ + return read_apic_id(); +} + /* * Power management */ diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 1fa8be5bd21..7414871751a 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -79,17 +79,6 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } -unsigned int read_apic_id(void) -{ - unsigned int id; - - WARN_ON(preemptible() && num_online_cpus() > 1); - id = apic_read(APIC_ID); - if (uv_system_type >= UV_X2APIC) - id |= __get_cpu_var(x2apic_extra_bits); - return id; -} - enum uv_system_type get_uv_system_type(void) { return uv_system_type; diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 1a9c68845ee..400ed8df8b4 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include static cpumask_t flat_target_cpus(void) { @@ -95,9 +97,17 @@ static void flat_send_IPI_all(int vector) __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } +static unsigned int read_xapic_id(void) +{ + unsigned int id; + + id = GET_XAPIC_ID(apic_read(APIC_ID)); + return id; +} + static int flat_apic_id_registered(void) { - return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map); + return physid_isset(read_xapic_id(), phys_cpu_present_map); } static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask) @@ -123,6 +133,7 @@ struct genapic apic_flat = { .send_IPI_mask = flat_send_IPI_mask, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, + .read_apic_id = read_xapic_id, }; /* @@ -187,4 +198,5 @@ struct genapic apic_physflat = { .send_IPI_mask = physflat_send_IPI_mask, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, + .read_apic_id = read_xapic_id, }; diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 711f11c30b0..1ef99be1848 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -134,9 +135,19 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int uv_read_apic_id(void) +{ + unsigned int id; + + WARN_ON(preemptible() && num_online_cpus() > 1); + id = apic_read(APIC_ID) | __get_cpu_var(x2apic_extra_bits); + + return id; +} + static unsigned int phys_pkg_id(int index_msb) { - return GET_APIC_ID(read_apic_id()) >> index_msb; + return uv_read_apic_id() >> index_msb; } #ifdef ZZZ /* Needs x2apic patch */ @@ -159,6 +170,7 @@ struct genapic apic_x2apic_uv_x = { /* ZZZ.send_IPI_self = uv_send_IPI_self, */ .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ + .read_apic_id = uv_read_apic_id, }; static __cpuinit void set_x2apic_extra_bits(int pnode) diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 647e4e5c258..d567abc347a 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -27,6 +27,7 @@ struct genapic { /* */ unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); unsigned int (*phys_pkg_id)(int index_msb); + unsigned int (*read_apic_id)(void); }; extern struct genapic *genapic; diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index 0b2cde5e1b7..d172c554ab9 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -30,6 +30,7 @@ static inline cpumask_t target_cpus(void) #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) #define phys_pkg_id (genapic->phys_pkg_id) #define vector_allocation_domain (genapic->vector_allocation_domain) +#define read_apic_id (genapic->read_apic_id) extern void setup_apic_routing(void); #else #define INT_DELIVERY_MODE dest_LowestPrio diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h index e4b29ba37de..453b58a67e2 100644 --- a/include/asm-x86/mach-default/mach_apicdef.h +++ b/include/asm-x86/mach-default/mach_apicdef.h @@ -5,8 +5,9 @@ #ifdef CONFIG_X86_64 #define APIC_ID_MASK (0xFFu<<24) -#define GET_APIC_ID(x) (((x)>>24)&0xFFu) +#define GET_APIC_ID(x) (x) #define SET_APIC_ID(x) (((x)<<24)) +#define GET_XAPIC_ID(x) (((x) >> 24) & 0xFFu) #else #define APIC_ID_MASK (0xF<<24) static inline unsigned get_apic_id(unsigned long x) diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 2e221f1ce0b..9848715fbd9 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -169,12 +169,10 @@ static inline unsigned int read_apic_id(void) { return *(u32 *)(APIC_BASE + APIC_ID); } -#else -extern unsigned int read_apic_id(void); #endif -# ifdef APIC_DEFINITION +# if defined(APIC_DEFINITION) || defined(CONFIG_X86_64) extern int hard_smp_processor_id(void); # else # include -- GitLab From 2d7a66d02e11af9ab8e16c76d22767e622b4e3d7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 14:24:19 -0700 Subject: [PATCH 0026/5416] x64, x2apic/intr-remap: Interrupt-remapping and x2apic support, fix Yinghai Lu wrote: > Setting APIC routing to physical flat > Kernel panic - not syncing: Boot APIC ID in local APIC unexpected (0 vs 4) > Pid: 1, comm: swapper Not tainted 2.6.26-rc9-tip-01763-g74f94b1-dirty #320 > > Call Trace: > [] ? set_cpu_sibling_map+0x38c/0x3bd > [] ? read_xapic_id+0x25/0x3e > [] ? verify_local_APIC+0x139/0x1b9 > [] ? read_xapic_id+0x25/0x3e > [] ? native_smp_prepare_cpus+0x224/0x2e9 > [] ? kernel_init+0x64/0x341 > [] ? child_rip+0xa/0x11 > [] ? kernel_init+0x0/0x341 > [] ? child_rip+0x0/0x11 > > > guess read_apic_id changing cuase some problem... genapic's read_apic_id() returns the actual apic id extracted from the APIC_ID register. And in some cases like UV, read_apic_id() returns completely different values from APIC ID register. Use the native apic register read, rather than genapic read_apic_id() in verify_local_APIC() And also, lapic_suspend() should also use native apic register read. Reported-by: Yinghai Lu Signed-off-by: Suresh Siddha Cc: "akpm@linux-foundation.org" Cc: "arjan@linux.intel.com" Cc: "andi@firstfloor.org" Cc: "ebiederm@xmission.com" Cc: "jbarnes@virtuousgeek.org" Cc: "steiner@sgi.com" Cc: "jeremy@goop.org" Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 9dd4ee4735f..3963f590c3d 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -626,10 +626,10 @@ int __init verify_local_APIC(void) /* * The ID register is read/write in a real APIC. */ - reg0 = read_apic_id(); + reg0 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); - reg1 = read_apic_id(); + reg1 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); apic_write(APIC_ID, reg0); if (reg1 != (reg0 ^ APIC_ID_MASK)) @@ -1137,7 +1137,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) maxlvt = lapic_get_maxlvt(); - apic_pm_state.apic_id = read_apic_id(); + apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); apic_pm_state.apic_ldr = apic_read(APIC_LDR); apic_pm_state.apic_dfr = apic_read(APIC_DFR); -- GitLab From 1b374e4d6f8b3eb2fcd034fcc24ea8ba1dfde7aa Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:49 -0700 Subject: [PATCH 0027/5416] x64, x2apic/intr-remap: basic apic ops support Introduce basic apic operations which handle the apic programming. This will be used later to introduce another specific operations for x2apic. For the perfomance critial accesses like IPI's, EOI etc, we use the native operations as they are already referenced by different indirections like genapic, irq_chip etc. 64bit Paravirt ops can also define their apic operations accordingly. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 +++++ arch/x86/kernel/apic_64.c | 34 ++++++++++++++++++++++++++-- arch/x86/kernel/io_apic_64.c | 8 +++---- arch/x86/kernel/paravirt.c | 8 ++++--- arch/x86/kernel/smpboot.c | 28 +++++++++-------------- include/asm-x86/apic.h | 43 +++++++++++++++++++++++++++++++----- include/asm-x86/ipi.h | 16 +++++++++----- include/asm-x86/paravirt.h | 2 ++ include/asm-x86/smp.h | 2 +- 9 files changed, 109 insertions(+), 38 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3e58b676d23..2a83c07bd88 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,6 +145,12 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +void apic_icr_write(u32 low, u32 id) +{ + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write_around(APIC_ICR, low); +} + void apic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 3963f590c3d..9bb040689b3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -119,13 +119,13 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } -void apic_wait_icr_idle(void) +void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) cpu_relax(); } -u32 safe_apic_wait_icr_idle(void) +u32 safe_xapic_wait_icr_idle(void) { u32 send_status; int timeout; @@ -141,6 +141,36 @@ u32 safe_apic_wait_icr_idle(void) return send_status; } +void xapic_icr_write(u32 low, u32 id) +{ + apic_write(APIC_ICR2, id << 24); + apic_write(APIC_ICR, low); +} + +u64 xapic_icr_read(void) +{ + u32 icr1, icr2; + + icr2 = apic_read(APIC_ICR2); + icr1 = apic_read(APIC_ICR); + + return (icr1 | ((u64)icr2 << 32)); +} + +static struct apic_ops xapic_ops = { + .read = native_apic_mem_read, + .write = native_apic_mem_write, + .write_atomic = native_apic_mem_write_atomic, + .icr_read = xapic_icr_read, + .icr_write = xapic_icr_write, + .wait_icr_idle = xapic_wait_icr_idle, + .safe_wait_icr_idle = safe_xapic_wait_icr_idle, +}; + +struct apic_ops __read_mostly *apic_ops = &xapic_ops; + +EXPORT_SYMBOL_GPL(apic_ops); + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 84dd63c13d6..b62d42ef928 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1157,6 +1157,7 @@ static __apicdebuginit void print_APIC_bitfield (int base) void __apicdebuginit print_local_APIC(void * dummy) { unsigned int v, ver, maxlvt; + unsigned long icr; if (apic_verbosity == APIC_QUIET) return; @@ -1200,10 +1201,9 @@ void __apicdebuginit print_local_APIC(void * dummy) v = apic_read(APIC_ESR); printk(KERN_DEBUG "... APIC ESR: %08x\n", v); - v = apic_read(APIC_ICR); - printk(KERN_DEBUG "... APIC ICR: %08x\n", v); - v = apic_read(APIC_ICR2); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); + icr = apic_icr_read(); + printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index e0f571d58c1..b80105a0f47 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,9 +360,11 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC - .apic_write = native_apic_write, - .apic_write_atomic = native_apic_write_atomic, - .apic_read = native_apic_read, +#ifnded CONFIG_X86_64 + .apic_write = native_apic_mem_write, + .apic_write_atomic = native_apic_mem_write_atomic, + .apic_read = native_apic_mem_read, +#endif .setup_boot_clock = setup_boot_APIC_clock, .setup_secondary_clock = setup_secondary_APIC_clock, .startup_ipi_hook = paravirt_nop, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f35c2d8016a..c55263b3df0 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); static atomic_t init_deasserted; -static int boot_cpu_logical_apicid; /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu) #endif #ifdef CONFIG_X86_32 +static int boot_cpu_logical_apicid; + u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; @@ -546,8 +547,7 @@ static inline void __inquire_remote_apic(int apicid) printk(KERN_CONT "a previous APIC delivery may have failed\n"); - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); + apic_icr_write(APIC_DM_REMRD | regs[i], apicid); timeout = 0; do { @@ -579,11 +579,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) int maxlvt; /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); - /* Boot on the stack */ /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); + apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -639,13 +637,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) /* * Turn INIT on target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* * Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT - | APIC_DM_INIT); + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, + phys_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -655,10 +651,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) Dprintk("Deasserting INIT.\n"); /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); Dprintk("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); @@ -703,12 +697,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) */ /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); - /* Boot on the stack */ /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_STARTUP - | (start_eip >> 12)); + apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), + phys_apicid); /* * Give the other CPU some time to accept the IPI. @@ -1147,7 +1139,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) * Setup boot CPU information */ smp_store_cpu_info(0); /* Final full version of the data */ +#ifdef CONFIG_X86_32 boot_cpu_logical_apicid = logical_smp_processor_id(); +#endif current_thread_info()->cpu = 0; /* needed? */ set_cpu_sibling_map(0); diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 4e2c1e517f0..6fda195337c 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -47,32 +47,59 @@ extern int disable_apic; #ifdef CONFIG_PARAVIRT #include #else -#define apic_write native_apic_write -#define apic_write_atomic native_apic_write_atomic -#define apic_read native_apic_read +#ifndef CONFIG_X86_64 +#define apic_write native_apic_mem_write +#define apic_write_atomic native_apic_mem_write_atomic +#define apic_read native_apic_mem_read +#endif #define setup_boot_clock setup_boot_APIC_clock #define setup_secondary_clock setup_secondary_APIC_clock #endif extern int is_vsmp_box(void); -static inline void native_apic_write(unsigned long reg, u32 v) +static inline void native_apic_mem_write(u32 reg, u32 v) { *((volatile u32 *)(APIC_BASE + reg)) = v; } -static inline void native_apic_write_atomic(unsigned long reg, u32 v) +static inline void native_apic_mem_write_atomic(u32 reg, u32 v) { (void)xchg((u32 *)(APIC_BASE + reg), v); } -static inline u32 native_apic_read(unsigned long reg) +static inline u32 native_apic_mem_read(u32 reg) { return *((volatile u32 *)(APIC_BASE + reg)); } +#ifdef CONFIG_X86_32 extern void apic_wait_icr_idle(void); extern u32 safe_apic_wait_icr_idle(void); +extern void apic_icr_write(u32 low, u32 id); +#else + +struct apic_ops { + u32 (*read)(u32 reg); + void (*write)(u32 reg, u32 v); + void (*write_atomic)(u32 reg, u32 v); + u64 (*icr_read)(void); + void (*icr_write)(u32 low, u32 high); + void (*wait_icr_idle)(void); + u32 (*safe_wait_icr_idle)(void); +}; + +extern struct apic_ops *apic_ops; + +#define apic_read (apic_ops->read) +#define apic_write (apic_ops->write) +#define apic_write_atomic (apic_ops->write_atomic) +#define apic_icr_read (apic_ops->icr_read) +#define apic_icr_write (apic_ops->icr_write) +#define apic_wait_icr_idle (apic_ops->wait_icr_idle) +#define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle) +#endif + extern int get_physical_broadcast(void); #ifdef CONFIG_X86_GOOD_APIC @@ -95,7 +122,11 @@ static inline void ack_APIC_irq(void) */ /* Docs say use 0 for future compatibility */ +#ifdef CONFIG_X86_32 apic_write_around(APIC_EOI, 0); +#else + native_apic_mem_write(APIC_EOI, 0); +#endif } extern int lapic_get_maxlvt(void); diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h index 196d63c28aa..3d8d6a6c1f8 100644 --- a/include/asm-x86/ipi.h +++ b/include/asm-x86/ipi.h @@ -49,6 +49,12 @@ static inline int __prepare_ICR2(unsigned int mask) return SET_APIC_DEST_FIELD(mask); } +static inline void __xapic_wait_icr_idle(void) +{ + while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY) + cpu_relax(); +} + static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) { @@ -64,7 +70,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, /* * Wait for idle. */ - apic_wait_icr_idle(); + __xapic_wait_icr_idle(); /* * No need to touch the target chip field @@ -74,7 +80,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, /* * Send the IPI. The write to APIC_ICR fires this off. */ - apic_write(APIC_ICR, cfg); + native_apic_mem_write(APIC_ICR, cfg); } /* @@ -92,13 +98,13 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector, if (unlikely(vector == NMI_VECTOR)) safe_apic_wait_icr_idle(); else - apic_wait_icr_idle(); + __xapic_wait_icr_idle(); /* * prepare target chip field */ cfg = __prepare_ICR2(mask); - apic_write(APIC_ICR2, cfg); + native_apic_mem_write(APIC_ICR2, cfg); /* * program the ICR @@ -108,7 +114,7 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector, /* * Send the IPI. The write to APIC_ICR fires this off. */ - apic_write(APIC_ICR, cfg); + native_apic_mem_write(APIC_ICR, cfg); } static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index ef5e8ec6a6a..10adac02e6d 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -891,6 +891,7 @@ static inline void slow_down_io(void) /* * Basic functions accessing APICs. */ +#ifndef CONFIG_X86_64 static inline void apic_write(unsigned long reg, u32 v) { PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); @@ -905,6 +906,7 @@ static inline u32 apic_read(unsigned long reg) { return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); } +#endif static inline void setup_boot_clock(void) { diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 9848715fbd9..d9d007d2278 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -158,13 +158,13 @@ extern int safe_smp_processor_id(void); #ifdef CONFIG_X86_LOCAL_APIC +#ifndef CONFIG_X86_64 static inline int logical_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR)); } -#ifndef CONFIG_X86_64 static inline unsigned int read_apic_id(void) { return *(u32 *)(APIC_BASE + APIC_ID); -- GitLab From 32e1d0a0651004f5fe47f85a2a5c725ad579a90c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:50 -0700 Subject: [PATCH 0028/5416] x64, x2apic/intr-remap: cpuid bits for x2apic feature cpuid feature for x2apic. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/feature_names.c | 2 +- include/asm-x86/cpufeature.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4ad4cb..0bf4d37a048 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -45,7 +45,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = { /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt", + NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 75ef959db32..5be9510ee01 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -90,6 +90,7 @@ #define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ @@ -188,6 +189,7 @@ extern const char * const x86_power_flags[32]; #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) +#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 -- GitLab From 1cb11583a6c4ceda7426eb36f7bf0419da8dfbc2 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:51 -0700 Subject: [PATCH 0029/5416] x64, x2apic/intr-remap: disable DMA-remapping if Interrupt-remapping is detected (temporary quirk) Interrupt-remapping enables queued invalidation. And once queued invalidation is enabled, IOTLB invalidation also needs to use the queued invalidation mechanism and the register based IOTLB invalidation doesn't work. For now, Support for IOTLB invalidation using queued invalidation is missing. Meanwhile, disable DMA-remapping, if Interrupt-remapping support is detected. For the meanwhile, if someone wants to really enable DMA-remapping, they can use nox2apic, which will disable interrupt-remapping and as such doesn't enable queued invalidation. And given that none of the release platforms support intr-remapping yet, we should be ok for this temporary hack. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- drivers/pci/dmar.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 23a119e6485..bd2c01674f5 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -457,6 +457,31 @@ void __init detect_intel_iommu(void) #ifdef CONFIG_DMAR { + struct acpi_table_dmar *dmar; + /* + * for now we will disable dma-remapping when interrupt + * remapping is enabled. + * When support for queued invalidation for IOTLB invalidation + * is added, we will not need this any more. + */ + dmar = (struct acpi_table_dmar *) dmar_tbl; + if (ret && cpu_has_x2apic && dmar->flags & 0x1) { + printk(KERN_INFO + "Queued invalidation will be enabled to support " + "x2apic and Intr-remapping.\n"); + printk(KERN_INFO + "Disabling IOMMU detection, because of missing " + "queued invalidation support for IOTLB " + "invalidation\n"); + printk(KERN_INFO + "Use \"nox2apic\", if you want to use Intel " + " IOMMU for DMA-remapping and don't care about " + " x2apic support\n"); + + dmar_disabled = 1; + return; + } + if (ret && !no_iommu && !iommu_detected && !swiotlb && !dmar_disabled) iommu_detected = 1; -- GitLab From 13c88fb58d0112d47f7839f24a755715c6218822 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:52 -0700 Subject: [PATCH 0030/5416] x64, x2apic/intr-remap: x2apic ops for x2apic mode support x2apic ops for x2apic mode support. This uses MSR interface and differs slightly from the xapic register layout. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 35 +++++++++++++++++++++++++++++++++++ include/asm-x86/apic.h | 22 ++++++++++++++++++++++ include/asm-x86/apicdef.h | 3 +++ 3 files changed, 60 insertions(+) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 9bb040689b3..a969ef78e12 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -171,6 +171,41 @@ struct apic_ops __read_mostly *apic_ops = &xapic_ops; EXPORT_SYMBOL_GPL(apic_ops); +static void x2apic_wait_icr_idle(void) +{ + /* no need to wait for icr idle in x2apic */ + return; +} + +static u32 safe_x2apic_wait_icr_idle(void) +{ + /* no need to wait for icr idle in x2apic */ + return 0; +} + +void x2apic_icr_write(u32 low, u32 id) +{ + wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low); +} + +u64 x2apic_icr_read(void) +{ + unsigned long val; + + rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val); + return val; +} + +static struct apic_ops x2apic_ops = { + .read = native_apic_msr_read, + .write = native_apic_msr_write, + .write_atomic = native_apic_msr_write, + .icr_read = x2apic_icr_read, + .icr_write = x2apic_icr_write, + .wait_icr_idle = x2apic_wait_icr_idle, + .safe_wait_icr_idle = safe_x2apic_wait_icr_idle, +}; + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 6fda195337c..bb54928373c 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include #define ARCH_APICTIMER_STOPS_ON_C3 1 @@ -73,6 +75,26 @@ static inline u32 native_apic_mem_read(u32 reg) return *((volatile u32 *)(APIC_BASE + reg)); } +static inline void native_apic_msr_write(u32 reg, u32 v) +{ + if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR || + reg == APIC_LVR) + return; + + wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0); +} + +static inline u32 native_apic_msr_read(u32 reg) +{ + u32 low, high; + + if (reg == APIC_DFR) + return -1; + + rdmsr(APIC_BASE_MSR + (reg >> 4), low, high); + return low; +} + #ifdef CONFIG_X86_32 extern void apic_wait_icr_idle(void); extern u32 safe_apic_wait_icr_idle(void); diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h index 6b9008c7873..bcae297b30b 100644 --- a/include/asm-x86/apicdef.h +++ b/include/asm-x86/apicdef.h @@ -105,6 +105,7 @@ #define APIC_TMICT 0x380 #define APIC_TMCCT 0x390 #define APIC_TDCR 0x3E0 +#define APIC_SELF_IPI 0x3F0 #define APIC_TDR_DIV_TMBASE (1 << 2) #define APIC_TDR_DIV_1 0xB #define APIC_TDR_DIV_2 0x0 @@ -128,6 +129,8 @@ #define APIC_EILVT3 0x530 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) +#define APIC_BASE_MSR 0x800 +#define X2APIC_ENABLE (1UL << 10) #ifdef CONFIG_X86_32 # define MAX_IO_APICS 64 -- GitLab From cff73a6ffaed726780b001937d2a42efde553922 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:53 -0700 Subject: [PATCH 0031/5416] x64, x2apic/intr-remap: introcude self IPI to genapic routines Introduce self IPI op for genapic. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 2 +- arch/x86/kernel/genapic_flat_64.c | 2 ++ include/asm-x86/genapic_64.h | 2 ++ include/asm-x86/hw_irq.h | 2 ++ include/asm-x86/mach-default/mach_apic.h | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 7414871751a..6657de609dc 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -61,7 +61,7 @@ void __init setup_apic_routing(void) /* Same for both flat and physical. */ -void send_IPI_self(int vector) +void apic_send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 400ed8df8b4..73558682213 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -131,6 +131,7 @@ struct genapic apic_flat = { .send_IPI_all = flat_send_IPI_all, .send_IPI_allbutself = flat_send_IPI_allbutself, .send_IPI_mask = flat_send_IPI_mask, + .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, .read_apic_id = read_xapic_id, @@ -196,6 +197,7 @@ struct genapic apic_physflat = { .send_IPI_all = physflat_send_IPI_all, .send_IPI_allbutself = physflat_send_IPI_allbutself, .send_IPI_mask = physflat_send_IPI_mask, + .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, .read_apic_id = read_xapic_id, diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index d567abc347a..6777d71aabc 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -24,6 +24,7 @@ struct genapic { void (*send_IPI_mask)(cpumask_t mask, int vector); void (*send_IPI_allbutself)(int vector); void (*send_IPI_all)(int vector); + void (*send_IPI_self)(int vector); /* */ unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); unsigned int (*phys_pkg_id)(int index_msb); @@ -36,6 +37,7 @@ extern struct genapic apic_flat; extern struct genapic apic_physflat; extern int acpi_madt_oem_check(char *, char *); +extern void apic_send_IPI_self(int vector); enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; extern enum uv_system_type get_uv_system_type(void); extern int is_uv_system(void); diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 18f067c310f..2ae47e7c106 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -72,7 +72,9 @@ extern void enable_IO_APIC(void); #endif /* IPI functions */ +#ifdef CONFIG_X86_32 extern void send_IPI_self(int vector); +#endif extern void send_IPI(int dest, int vector); /* Statistics */ diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index d172c554ab9..e06d23975d6 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -31,6 +31,7 @@ static inline cpumask_t target_cpus(void) #define phys_pkg_id (genapic->phys_pkg_id) #define vector_allocation_domain (genapic->vector_allocation_domain) #define read_apic_id (genapic->read_apic_id) +#define send_IPI_self (genapic->send_IPI_self) extern void setup_apic_routing(void); #else #define INT_DELIVERY_MODE dest_LowestPrio -- GitLab From 12a67cf6851871ca8df42025c94f140c303d0f7f Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:54 -0700 Subject: [PATCH 0032/5416] x64, x2apic/intr-remap: x2apic cluster mode support x2apic cluster mode support. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/genapic_64.c | 2 + arch/x86/kernel/genx2apic_cluster.c | 135 ++++++++++++++++++++++++++++ include/asm-x86/genapic_64.h | 1 + 4 files changed, 139 insertions(+) create mode 100644 arch/x86/kernel/genx2apic_cluster.c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 55ff016e9f6..bde3e9b6fec 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_OLPC) += olpc.o # 64 bit specific files ifeq ($(CONFIG_X86_64),y) obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o + obj-y += genx2apic_cluster.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o obj-$(CONFIG_AUDIT) += audit_64.o diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 6657de609dc..1029e178cdf 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -38,6 +38,8 @@ void __init setup_apic_routing(void) { if (uv_system_type == UV_NON_UNIQUE_APIC) genapic = &apic_x2apic_uv_x; + else if (cpu_has_x2apic && intr_remapping_enabled) + genapic = &apic_x2apic_cluster; else #ifdef CONFIG_ACPI /* diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c new file mode 100644 index 00000000000..ed0fdede800 --- /dev/null +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); + +/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ + +static cpumask_t x2apic_target_cpus(void) +{ + return cpumask_of_cpu(0); +} + +/* + * for now each logical cpu is in its own vector allocation domain. + */ +static cpumask_t x2apic_vector_allocation_domain(int cpu) +{ + cpumask_t domain = CPU_MASK_NONE; + cpu_set(cpu, domain); + return domain; +} + +static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, + unsigned int dest) +{ + unsigned long cfg; + + cfg = __prepare_ICR(0, vector, dest); + + /* + * send the IPI. + */ + x2apic_icr_write(cfg, apicid); +} + +/* + * for now, we send the IPI's one by one in the cpumask. + * TBD: Based on the cpu mask, we can send the IPI's to the cluster group + * at once. We have 16 cpu's in a cluster. This will minimize IPI register + * writes. + */ +static void x2apic_send_IPI_mask(cpumask_t mask, int vector) +{ + unsigned long flags; + unsigned long query_cpu; + + local_irq_save(flags); + for_each_cpu_mask(query_cpu, mask) { + __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_logical_apicid, query_cpu), + vector, APIC_DEST_LOGICAL); + } + local_irq_restore(flags); +} + +static void x2apic_send_IPI_allbutself(int vector) +{ + cpumask_t mask = cpu_online_map; + + cpu_clear(smp_processor_id(), mask); + + if (!cpus_empty(mask)) + x2apic_send_IPI_mask(mask, vector); +} + +static void x2apic_send_IPI_all(int vector) +{ + x2apic_send_IPI_mask(cpu_online_map, vector); +} + +static int x2apic_apic_id_registered(void) +{ + return 1; +} + +static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = first_cpu(cpumask); + if ((unsigned)cpu < NR_CPUS) + return per_cpu(x86_cpu_to_logical_apicid, cpu); + else + return BAD_APICID; +} + +static unsigned int x2apic_read_id(void) +{ + return apic_read(APIC_ID); +} + +static unsigned int phys_pkg_id(int index_msb) +{ + return x2apic_read_id() >> index_msb; +} + +static void x2apic_send_IPI_self(int vector) +{ + apic_write(APIC_SELF_IPI, vector); +} + +static void init_x2apic_ldr(void) +{ + int cpu = smp_processor_id(); + + per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR); + return; +} + +struct genapic apic_x2apic_cluster = { + .name = "cluster x2apic", + .int_delivery_mode = dest_LowestPrio, + .int_dest_mode = (APIC_DEST_LOGICAL != 0), + .target_cpus = x2apic_target_cpus, + .vector_allocation_domain = x2apic_vector_allocation_domain, + .apic_id_registered = x2apic_apic_id_registered, + .init_apic_ldr = init_x2apic_ldr, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_self = x2apic_send_IPI_self, + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .phys_pkg_id = phys_pkg_id, + .read_apic_id = x2apic_read_id, +}; diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 6777d71aabc..23246030587 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -35,6 +35,7 @@ extern struct genapic *genapic; extern struct genapic apic_flat; extern struct genapic apic_physflat; +extern struct genapic apic_x2apic_cluster; extern int acpi_madt_oem_check(char *, char *); extern void apic_send_IPI_self(int vector); -- GitLab From 5c520a6724e912a7e6153b7597192edad6752750 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:55 -0700 Subject: [PATCH 0033/5416] x64, x2apic/intr-remap: setup init_apic_ldr for UV Signed-off-by: Suresh Siddha Signed-off-by: Jack Steiner Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 1ef99be1848..dcd4fb219da 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -120,6 +120,10 @@ static int uv_apic_id_registered(void) return 1; } +static inline void uv_init_apic_ldr(void) +{ +} + static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) { int cpu; @@ -164,6 +168,7 @@ struct genapic apic_x2apic_uv_x = { .target_cpus = uv_target_cpus, .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */ .apic_id_registered = uv_apic_id_registered, + .init_apic_ldr = uv_init_apic_ldr, .send_IPI_all = uv_send_IPI_all, .send_IPI_allbutself = uv_send_IPI_allbutself, .send_IPI_mask = uv_send_IPI_mask, -- GitLab From 89027d35aa5b8f45ce0f7fa0911db85b46563da0 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:56 -0700 Subject: [PATCH 0034/5416] x64, x2apic/intr-remap: IO-APIC support for interrupt-remapping IO-APIC support in the presence of interrupt-remapping infrastructure. IO-APIC RTE will be programmed with interrupt-remapping table entry(IRTE) index and the IRTE will contain information about the vector, cpu destination, trigger mode etc, which traditionally was present in the IO-APIC RTE. Introduce a new irq_chip for cleaner irq migration (in the process context as opposed to the current irq migration in the context of an interrupt. interrupt-remapping infrastructure will help us achieve this cleanly). For edge triggered, irq migration is a simple atomic update(of vector and cpu destination) of IRTE and flush the hardware cache. For level triggered, we need to modify the io-apic RTE aswell with the update vector information, along with modifying IRTE with vector and cpu destination. So irq migration for level triggered is little bit more complex compared to edge triggered migration. But the good news is, we use the same algorithm for level triggered migration as we have today, only difference being, we now initiate the irq migration from process context instead of the interrupt context. In future, when we do a directed EOI (combined with cpu EOI broadcast suppression) to the IO-APIC, level triggered irq migration will also be as simple as edge triggered migration and we can do the irq migration with a simple atomic update to IO-APIC RTE. TBD: some tests/changes needed in the presence of fixup_irqs() for level triggered irq migration. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 1 + arch/x86/kernel/io_apic_64.c | 300 +++++++++++++++++++++++++++++--- drivers/pci/intr_remapping.c | 10 ++ include/asm-x86/apic.h | 9 + include/asm-x86/io_apic.h | 14 ++ include/asm-x86/irq_remapping.h | 8 + include/linux/dmar.h | 1 + 7 files changed, 321 insertions(+), 22 deletions(-) create mode 100644 include/asm-x86/irq_remapping.h diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index a969ef78e12..d5c06917b5b 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -46,6 +46,7 @@ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; +int x2apic; /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index b62d42ef928..9bd02ef049a 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -37,6 +37,7 @@ #include #endif #include +#include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include @@ -312,7 +314,12 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) pin = entry->pin; if (pin == -1) break; - io_apic_write(apic, 0x11 + pin*2, dest); + /* + * With interrupt-remapping, destination information comes + * from interrupt-remapping table entry. + */ + if (!irq_remapped(irq)) + io_apic_write(apic, 0x11 + pin*2, dest); reg = io_apic_read(apic, 0x10 + pin*2); reg &= ~IO_APIC_REDIR_VECTOR_MASK; reg |= vector; @@ -906,18 +913,98 @@ void setup_vector_irq(int cpu) static struct irq_chip ioapic_chip; +#ifdef CONFIG_INTR_REMAP +static struct irq_chip ir_ioapic_chip; +#endif static void ioapic_register_intr(int irq, unsigned long trigger) { - if (trigger) { + if (trigger) irq_desc[irq].status |= IRQ_LEVEL; - set_irq_chip_and_handler_name(irq, &ioapic_chip, - handle_fasteoi_irq, "fasteoi"); - } else { + else irq_desc[irq].status &= ~IRQ_LEVEL; + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + irq_desc[irq].status |= IRQ_MOVE_PCNTXT; + if (trigger) + set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, + handle_fasteoi_irq, + "fasteoi"); + else + set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, + handle_edge_irq, "edge"); + return; + } +#endif + if (trigger) + set_irq_chip_and_handler_name(irq, &ioapic_chip, + handle_fasteoi_irq, + "fasteoi"); + else set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge"); +} + +static int setup_ioapic_entry(int apic, int irq, + struct IO_APIC_route_entry *entry, + unsigned int destination, int trigger, + int polarity, int vector) +{ + /* + * add it to the IO-APIC irq-routing table: + */ + memset(entry,0,sizeof(*entry)); + +#ifdef CONFIG_INTR_REMAP + if (intr_remapping_enabled) { + struct intel_iommu *iommu = map_ioapic_to_ir(apic); + struct irte irte; + struct IR_IO_APIC_route_entry *ir_entry = + (struct IR_IO_APIC_route_entry *) entry; + int index; + + if (!iommu) + panic("No mapping iommu for ioapic %d\n", apic); + + index = alloc_irte(iommu, irq, 1); + if (index < 0) + panic("Failed to allocate IRTE for ioapic %d\n", apic); + + memset(&irte, 0, sizeof(irte)); + + irte.present = 1; + irte.dst_mode = INT_DEST_MODE; + irte.trigger_mode = trigger; + irte.dlvry_mode = INT_DELIVERY_MODE; + irte.vector = vector; + irte.dest_id = IRTE_DEST(destination); + + modify_irte(irq, &irte); + + ir_entry->index2 = (index >> 15) & 0x1; + ir_entry->zero = 0; + ir_entry->format = 1; + ir_entry->index = (index & 0x7fff); + } else +#endif + { + entry->delivery_mode = INT_DELIVERY_MODE; + entry->dest_mode = INT_DEST_MODE; + entry->dest = destination; } + + entry->mask = 0; /* enable IRQ */ + entry->trigger = trigger; + entry->polarity = polarity; + entry->vector = vector; + + /* Mask level triggered irqs. + * Use IRQ_DELAYED_DISABLE for edge triggered irqs. + */ + if (trigger) + entry->mask = 1; + return 0; } static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, @@ -942,24 +1029,15 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector, irq, trigger, polarity); - /* - * add it to the IO-APIC irq-routing table: - */ - memset(&entry,0,sizeof(entry)); - - entry.delivery_mode = INT_DELIVERY_MODE; - entry.dest_mode = INT_DEST_MODE; - entry.dest = cpu_mask_to_apicid(mask); - entry.mask = 0; /* enable IRQ */ - entry.trigger = trigger; - entry.polarity = polarity; - entry.vector = cfg->vector; - /* Mask level triggered irqs. - * Use IRQ_DELAYED_DISABLE for edge triggered irqs. - */ - if (trigger) - entry.mask = 1; + if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry, + cpu_mask_to_apicid(mask), trigger, polarity, + cfg->vector)) { + printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", + mp_ioapics[apic].mp_apicid, pin); + __clear_irq_vector(irq); + return; + } ioapic_register_intr(irq, trigger); if (irq < 16) @@ -1011,6 +1089,9 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, { struct IO_APIC_route_entry entry; + if (intr_remapping_enabled) + return; + memset(&entry, 0, sizeof(entry)); /* @@ -1466,6 +1547,147 @@ static int ioapic_retrigger_irq(unsigned int irq) */ #ifdef CONFIG_SMP + +#ifdef CONFIG_INTR_REMAP +static void ir_irq_migration(struct work_struct *work); + +static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration); + +/* + * Migrate the IO-APIC irq in the presence of intr-remapping. + * + * For edge triggered, irq migration is a simple atomic update(of vector + * and cpu destination) of IRTE and flush the hardware cache. + * + * For level triggered, we need to modify the io-apic RTE aswell with the update + * vector information, along with modifying IRTE with vector and destination. + * So irq migration for level triggered is little bit more complex compared to + * edge triggered migration. But the good news is, we use the same algorithm + * for level triggered migration as we have today, only difference being, + * we now initiate the irq migration from process context instead of the + * interrupt context. + * + * In future, when we do a directed EOI (combined with cpu EOI broadcast + * suppression) to the IO-APIC, level triggered irq migration will also be + * as simple as edge triggered migration and we can do the irq migration + * with a simple atomic update to IO-APIC RTE. + */ +static void migrate_ioapic_irq(int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + struct irq_desc *desc = irq_desc + irq; + cpumask_t tmp, cleanup_mask; + struct irte irte; + int modify_ioapic_rte = desc->status & IRQ_LEVEL; + unsigned int dest; + unsigned long flags; + + cpus_and(tmp, mask, cpu_online_map); + if (cpus_empty(tmp)) + return; + + if (get_irte(irq, &irte)) + return; + + if (assign_irq_vector(irq, mask)) + return; + + cpus_and(tmp, cfg->domain, mask); + dest = cpu_mask_to_apicid(tmp); + + if (modify_ioapic_rte) { + spin_lock_irqsave(&ioapic_lock, flags); + __target_IO_APIC_irq(irq, dest, cfg->vector); + spin_unlock_irqrestore(&ioapic_lock, flags); + } + + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + /* + * Modified the IRTE and flushes the Interrupt entry cache. + */ + modify_irte(irq, &irte); + + if (cfg->move_in_progress) { + cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map); + cfg->move_cleanup_count = cpus_weight(cleanup_mask); + send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); + cfg->move_in_progress = 0; + } + + irq_desc[irq].affinity = mask; +} + +static int migrate_irq_remapped_level(int irq) +{ + int ret = -1; + + mask_IO_APIC_irq(irq); + + if (io_apic_level_ack_pending(irq)) { + /* + * Interrupt in progress. Migrating irq now will change the + * vector information in the IO-APIC RTE and that will confuse + * the EOI broadcast performed by cpu. + * So, delay the irq migration to the next instance. + */ + schedule_delayed_work(&ir_migration_work, 1); + goto unmask; + } + + /* everthing is clear. we have right of way */ + migrate_ioapic_irq(irq, irq_desc[irq].pending_mask); + + ret = 0; + irq_desc[irq].status &= ~IRQ_MOVE_PENDING; + cpus_clear(irq_desc[irq].pending_mask); + +unmask: + unmask_IO_APIC_irq(irq); + return ret; +} + +static void ir_irq_migration(struct work_struct *work) +{ + int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_desc + irq; + if (desc->status & IRQ_MOVE_PENDING) { + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->chip->set_affinity || + !(desc->status & IRQ_MOVE_PENDING)) { + desc->status &= ~IRQ_MOVE_PENDING; + spin_unlock_irqrestore(&desc->lock, flags); + continue; + } + + desc->chip->set_affinity(irq, + irq_desc[irq].pending_mask); + spin_unlock_irqrestore(&desc->lock, flags); + } + } +} + +/* + * Migrates the IRQ destination in the process context. + */ +static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) +{ + if (irq_desc[irq].status & IRQ_LEVEL) { + irq_desc[irq].status |= IRQ_MOVE_PENDING; + irq_desc[irq].pending_mask = mask; + migrate_irq_remapped_level(irq); + return; + } + + migrate_ioapic_irq(irq, mask); +} +#endif + asmlinkage void smp_irq_move_cleanup_interrupt(void) { unsigned vector, me; @@ -1522,6 +1744,17 @@ static void irq_complete_move(unsigned int irq) #else static inline void irq_complete_move(unsigned int irq) {} #endif +#ifdef CONFIG_INTR_REMAP +static void ack_x2apic_level(unsigned int irq) +{ + ack_x2APIC_irq(); +} + +static void ack_x2apic_edge(unsigned int irq) +{ + ack_x2APIC_irq(); +} +#endif static void ack_apic_edge(unsigned int irq) { @@ -1596,6 +1829,21 @@ static struct irq_chip ioapic_chip __read_mostly = { .retrigger = ioapic_retrigger_irq, }; +#ifdef CONFIG_INTR_REMAP +static struct irq_chip ir_ioapic_chip __read_mostly = { + .name = "IR-IO-APIC", + .startup = startup_ioapic_irq, + .mask = mask_IO_APIC_irq, + .unmask = unmask_IO_APIC_irq, + .ack = ack_x2apic_edge, + .eoi = ack_x2apic_level, +#ifdef CONFIG_SMP + .set_affinity = set_ir_ioapic_affinity_irq, +#endif + .retrigger = ioapic_retrigger_irq, +}; +#endif + static inline void init_IO_APIC_traps(void) { int irq; @@ -1783,6 +2031,8 @@ static inline void __init check_timer(void) * 8259A. */ if (pin1 == -1) { + if (intr_remapping_enabled) + panic("BIOS bug: timer not connected to IO-APIC"); pin1 = pin2; apic1 = apic2; no_pin1 = 1; @@ -1809,6 +2059,8 @@ static inline void __init check_timer(void) clear_IO_APIC_pin(0, pin1); goto out; } + if (intr_remapping_enabled) + panic("timer doesn't work through Interrupt-remapped IO-APIC"); clear_IO_APIC_pin(apic1, pin1); if (!no_pin1) apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: " @@ -2401,6 +2653,10 @@ void __init setup_ioapic_dest(void) setup_IO_APIC_irq(ioapic, pin, irq, irq_trigger(irq_entry), irq_polarity(irq_entry)); +#ifdef CONFIG_INTR_REMAP + else if (intr_remapping_enabled) + set_ir_ioapic_affinity_irq(irq, TARGET_CPUS); +#endif else set_ioapic_affinity_irq(irq, TARGET_CPUS); } diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index bddb4b19b6c..32e55c7a980 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -220,6 +220,16 @@ int flush_irte(int irq) return 0; } +struct intel_iommu *map_ioapic_to_ir(int apic) +{ + int i; + + for (i = 0; i < MAX_IO_APICS; i++) + if (ir_ioapic[i].id == apic) + return ir_ioapic[i].iommu; + return NULL; +} + int free_irte(int irq) { int index, i; diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index bb54928373c..aa746704a5c 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -134,6 +134,15 @@ extern int get_physical_broadcast(void); # define apic_write_around(x, y) apic_write_atomic((x), (y)) #endif +#ifdef CONFIG_X86_64 +static inline void ack_x2APIC_irq(void) +{ + /* Docs say use 0 for future compatibility */ + native_apic_msr_write(APIC_EOI, 0); +} +#endif + + static inline void ack_APIC_irq(void) { /* diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h index 1c4a99d882f..8dc2622714c 100644 --- a/include/asm-x86/io_apic.h +++ b/include/asm-x86/io_apic.h @@ -107,6 +107,20 @@ struct IO_APIC_route_entry { } __attribute__ ((packed)); +struct IR_IO_APIC_route_entry { + __u64 vector : 8, + zero : 3, + index2 : 1, + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, + mask : 1, + reserved : 31, + format : 1, + index : 15; +} __attribute__ ((packed)); + #ifdef CONFIG_X86_IO_APIC /* diff --git a/include/asm-x86/irq_remapping.h b/include/asm-x86/irq_remapping.h new file mode 100644 index 00000000000..78242c6ffa5 --- /dev/null +++ b/include/asm-x86/irq_remapping.h @@ -0,0 +1,8 @@ +#ifndef _ASM_IRQ_REMAPPING_H +#define _ASM_IRQ_REMAPPING_H + +extern int x2apic; + +#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8) + +#endif diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 324bbca85a2..bf41ffa7470 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -109,6 +109,7 @@ extern int flush_irte(int irq); extern int free_irte(int irq); extern int irq_remapped(int irq); +extern struct intel_iommu *map_ioapic_to_ir(int apic); #else #define irq_remapped(irq) (0) #define enable_intr_remapping(mode) (-1) -- GitLab From 75c46fa61bc5b4ccd20a168ff325c58771248fcd Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:57 -0700 Subject: [PATCH 0035/5416] x64, x2apic/intr-remap: MSI and MSI-X support for interrupt remapping infrastructure MSI and MSI-X support for interrupt remapping infrastructure. MSI address register will be programmed with interrupt-remapping table entry(IRTE) index and the IRTE will contain information about the vector, cpu destination, etc. For MSI-X, all the IRTE's will be consecutively allocated in the table, and the address registers will contain the starting index to the block and the data register will contain the subindex with in that block. This also introduces a new irq_chip for cleaner irq migration (in the process context as opposed to the current irq migration in the context of an interrupt. interrupt-remapping infrastructure will help us achieve this). As MSI is edge triggered, irq migration is a simple atomic update(of vector and cpu destination) of IRTE and flushing the hardware cache. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 230 +++++++++++++++++++++++++++++++++-- drivers/pci/intr_remapping.c | 11 ++ include/asm-x86/msidef.h | 4 + include/linux/dmar.h | 1 + 4 files changed, 238 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 9bd02ef049a..877aa2e9d7e 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -2297,6 +2297,9 @@ void destroy_irq(unsigned int irq) dynamic_irq_cleanup(irq); +#ifdef CONFIG_INTR_REMAP + free_irte(irq); +#endif spin_lock_irqsave(&vector_lock, flags); __clear_irq_vector(irq); spin_unlock_irqrestore(&vector_lock, flags); @@ -2315,10 +2318,41 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms tmp = TARGET_CPUS; err = assign_irq_vector(irq, tmp); - if (!err) { - cpus_and(tmp, cfg->domain, tmp); - dest = cpu_mask_to_apicid(tmp); + if (err) + return err; + + cpus_and(tmp, cfg->domain, tmp); + dest = cpu_mask_to_apicid(tmp); + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + struct irte irte; + int ir_index; + u16 sub_handle; + + ir_index = map_irq_to_irte_handle(irq, &sub_handle); + BUG_ON(ir_index == -1); + + memset (&irte, 0, sizeof(irte)); + + irte.present = 1; + irte.dst_mode = INT_DEST_MODE; + irte.trigger_mode = 0; /* edge */ + irte.dlvry_mode = INT_DELIVERY_MODE; + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + modify_irte(irq, &irte); + msg->address_hi = MSI_ADDR_BASE_HI; + msg->data = sub_handle; + msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT | + MSI_ADDR_IR_SHV | + MSI_ADDR_IR_INDEX1(ir_index) | + MSI_ADDR_IR_INDEX2(ir_index); + } else +#endif + { msg->address_hi = MSI_ADDR_BASE_HI; msg->address_lo = MSI_ADDR_BASE_LO | @@ -2369,6 +2403,55 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) write_msi_msg(irq, &msg); irq_desc[irq].affinity = mask; } + +#ifdef CONFIG_INTR_REMAP +/* + * Migrate the MSI irq to another cpumask. This migration is + * done in the process context using interrupt-remapping hardware. + */ +static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + unsigned int dest; + cpumask_t tmp, cleanup_mask; + struct irte irte; + + cpus_and(tmp, mask, cpu_online_map); + if (cpus_empty(tmp)) + return; + + if (get_irte(irq, &irte)) + return; + + if (assign_irq_vector(irq, mask)) + return; + + cpus_and(tmp, cfg->domain, mask); + dest = cpu_mask_to_apicid(tmp); + + irte.vector = cfg->vector; + irte.dest_id = IRTE_DEST(dest); + + /* + * atomically update the IRTE with the new destination and vector. + */ + modify_irte(irq, &irte); + + /* + * After this point, all the interrupts will start arriving + * at the new destination. So, time to cleanup the previous + * vector allocation. + */ + if (cfg->move_in_progress) { + cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map); + cfg->move_cleanup_count = cpus_weight(cleanup_mask); + send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); + cfg->move_in_progress = 0; + } + + irq_desc[irq].affinity = mask; +} +#endif #endif /* CONFIG_SMP */ /* @@ -2386,26 +2469,157 @@ static struct irq_chip msi_chip = { .retrigger = ioapic_retrigger_irq, }; -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +#ifdef CONFIG_INTR_REMAP +static struct irq_chip msi_ir_chip = { + .name = "IR-PCI-MSI", + .unmask = unmask_msi_irq, + .mask = mask_msi_irq, + .ack = ack_x2apic_edge, +#ifdef CONFIG_SMP + .set_affinity = ir_set_msi_irq_affinity, +#endif + .retrigger = ioapic_retrigger_irq, +}; + +/* + * Map the PCI dev to the corresponding remapping hardware unit + * and allocate 'nvec' consecutive interrupt-remapping table entries + * in it. + */ +static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) +{ + struct intel_iommu *iommu; + int index; + + iommu = map_dev_to_ir(dev); + if (!iommu) { + printk(KERN_ERR + "Unable to map PCI %s to iommu\n", pci_name(dev)); + return -ENOENT; + } + + index = alloc_irte(iommu, irq, nvec); + if (index < 0) { + printk(KERN_ERR + "Unable to allocate %d IRTE for PCI %s\n", nvec, + pci_name(dev)); + return -ENOSPC; + } + return index; +} +#endif + +static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) { + int ret; struct msi_msg msg; + + ret = msi_compose_msg(dev, irq, &msg); + if (ret < 0) + return ret; + + set_irq_msi(irq, desc); + write_msi_msg(irq, &msg); + +#ifdef CONFIG_INTR_REMAP + if (irq_remapped(irq)) { + struct irq_desc *desc = irq_desc + irq; + /* + * irq migration in process context + */ + desc->status |= IRQ_MOVE_PCNTXT; + set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge"); + } else +#endif + set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); + + return 0; +} + +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ int irq, ret; + irq = create_irq(); if (irq < 0) return irq; - ret = msi_compose_msg(dev, irq, &msg); +#ifdef CONFIG_INTR_REMAP + if (!intr_remapping_enabled) + goto no_ir; + + ret = msi_alloc_irte(dev, irq, 1); + if (ret < 0) + goto error; +no_ir: +#endif + ret = setup_msi_irq(dev, desc, irq); if (ret < 0) { destroy_irq(irq); return ret; } + return 0; - set_irq_msi(irq, desc); - write_msi_msg(irq, &msg); +#ifdef CONFIG_INTR_REMAP +error: + destroy_irq(irq); + return ret; +#endif +} - set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + int irq, ret, sub_handle; + struct msi_desc *desc; +#ifdef CONFIG_INTR_REMAP + struct intel_iommu *iommu = 0; + int index = 0; +#endif + sub_handle = 0; + list_for_each_entry(desc, &dev->msi_list, list) { + irq = create_irq(); + if (irq < 0) + return irq; +#ifdef CONFIG_INTR_REMAP + if (!intr_remapping_enabled) + goto no_ir; + + if (!sub_handle) { + /* + * allocate the consecutive block of IRTE's + * for 'nvec' + */ + index = msi_alloc_irte(dev, irq, nvec); + if (index < 0) { + ret = index; + goto error; + } + } else { + iommu = map_dev_to_ir(dev); + if (!iommu) { + ret = -ENOENT; + goto error; + } + /* + * setup the mapping between the irq and the IRTE + * base index, the sub_handle pointing to the + * appropriate interrupt remap table entry. + */ + set_irte_irq(irq, iommu, index, sub_handle); + } +no_ir: +#endif + ret = setup_msi_irq(dev, desc, irq); + if (ret < 0) + goto error; + sub_handle++; + } return 0; + +error: + destroy_irq(irq); + return ret; } void arch_teardown_msi_irq(unsigned int irq) diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 32e55c7a980..bb642cc5e18 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -230,6 +230,17 @@ struct intel_iommu *map_ioapic_to_ir(int apic) return NULL; } +struct intel_iommu *map_dev_to_ir(struct pci_dev *dev) +{ + struct dmar_drhd_unit *drhd; + + drhd = dmar_find_matched_drhd_unit(dev); + if (!drhd) + return NULL; + + return drhd->iommu; +} + int free_irte(int irq) { int index, i; diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h index 296f29ce426..57fd85935e5 100644 --- a/include/asm-x86/msidef.h +++ b/include/asm-x86/msidef.h @@ -48,4 +48,8 @@ #define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ MSI_ADDR_DEST_ID_MASK) +#define MSI_ADDR_IR_EXT_INT (1 << 4) +#define MSI_ADDR_IR_SHV (1 << 3) +#define MSI_ADDR_IR_INDEX1(index) ((index & 0x8000) >> 13) +#define MSI_ADDR_IR_INDEX2(index) ((index & 0x7fff) << 5) #endif /* ASM_MSIDEF_H */ diff --git a/include/linux/dmar.h b/include/linux/dmar.h index bf41ffa7470..c360c558e59 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -109,6 +109,7 @@ extern int flush_irte(int irq); extern int free_irte(int irq); extern int irq_remapped(int irq); +extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev); extern struct intel_iommu *map_ioapic_to_ir(int apic); #else #define irq_remapped(irq) (0) -- GitLab From 6e1cb38a2aef7680975e71f23de187859ee8b158 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:58 -0700 Subject: [PATCH 0036/5416] x64, x2apic/intr-remap: add x2apic support, including enabling interrupt-remapping x2apic support. Interrupt-remapping must be enabled before enabling x2apic, this is needed to ensure that IO interrupts continue to work properly after the cpu mode is changed to x2apic(which uses 32bit extended physical/cluster apic id). On systems where apicid's are > 255, BIOS can handover the control to OS in x2apic mode. Or if the OS handover was in legacy xapic mode, check if it is capable of x2apic mode. And if we succeed in enabling Interrupt-remapping, then we can enable x2apic mode in the CPU. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 2 + arch/x86/kernel/acpi/boot.c | 2 + arch/x86/kernel/apic_64.c | 154 +++++++++++++++++++++++++++- arch/x86/kernel/cpu/common_64.c | 2 + arch/x86/kernel/genapic_64.c | 1 + arch/x86/kernel/mpparse.c | 2 + arch/x86/kernel/setup.c | 2 + arch/x86/kernel/smpboot.c | 5 + include/asm-x86/apic.h | 5 + 9 files changed, 171 insertions(+), 4 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 795c487af8e..56689ef1a15 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1377,6 +1377,8 @@ and is between 256 and 4096 characters. It is defined in the file nolapic_timer [X86-32,APIC] Do not use the local APIC timer. + nox2apic [X86-64,APIC] Do not enable x2APIC mode. + noltlbs [PPC] Do not use large page/tlb entries for kernel lowmem mapping on PPC40x. diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 785700a08e9..8705262ddcd 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1337,7 +1337,9 @@ static void __init acpi_process_madt(void) acpi_ioapic = 1; smp_found_config = 1; +#ifdef CONFIG_X86_32 setup_apic_routing(); +#endif } } if (error == -EINVAL) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d5c06917b5b..dd0501039f0 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -46,8 +48,12 @@ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; +int disable_x2apic; int x2apic; +/* x2apic enabled before OS handover */ +int x2apic_preenabled; + /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); @@ -896,6 +902,125 @@ void __cpuinit end_local_APIC_setup(void) apic_pm_activate(); } +void check_x2apic(void) +{ + int msr, msr2; + + rdmsr(MSR_IA32_APICBASE, msr, msr2); + + if (msr & X2APIC_ENABLE) { + printk("x2apic enabled by BIOS, switching to x2apic ops\n"); + x2apic_preenabled = x2apic = 1; + apic_ops = &x2apic_ops; + } +} + +void enable_x2apic(void) +{ + int msr, msr2; + + rdmsr(MSR_IA32_APICBASE, msr, msr2); + if (!(msr & X2APIC_ENABLE)) { + printk("Enabling x2apic\n"); + wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); + } +} + +void enable_IR_x2apic(void) +{ +#ifdef CONFIG_INTR_REMAP + int ret; + unsigned long flags; + + if (!cpu_has_x2apic) + return; + + if (!x2apic_preenabled && disable_x2apic) { + printk(KERN_INFO + "Skipped enabling x2apic and Interrupt-remapping " + "because of nox2apic\n"); + return; + } + + if (x2apic_preenabled && disable_x2apic) + panic("Bios already enabled x2apic, can't enforce nox2apic"); + + if (!x2apic_preenabled && skip_ioapic_setup) { + printk(KERN_INFO + "Skipped enabling x2apic and Interrupt-remapping " + "because of skipping io-apic setup\n"); + return; + } + + ret = dmar_table_init(); + if (ret) { + printk(KERN_INFO + "dmar_table_init() failed with %d:\n", ret); + + if (x2apic_preenabled) + panic("x2apic enabled by bios. But IR enabling failed"); + else + printk(KERN_INFO + "Not enabling x2apic,Intr-remapping\n"); + return; + } + + local_irq_save(flags); + mask_8259A(); + save_mask_IO_APIC_setup(); + + ret = enable_intr_remapping(1); + + if (ret && x2apic_preenabled) { + local_irq_restore(flags); + panic("x2apic enabled by bios. But IR enabling failed"); + } + + if (ret) + goto end; + + if (!x2apic) { + x2apic = 1; + apic_ops = &x2apic_ops; + enable_x2apic(); + } +end: + if (ret) + /* + * IR enabling failed + */ + restore_IO_APIC_setup(); + else + reinit_intr_remapped_IO_APIC(x2apic_preenabled); + + unmask_8259A(); + local_irq_restore(flags); + + if (!ret) { + if (!x2apic_preenabled) + printk(KERN_INFO + "Enabled x2apic and interrupt-remapping\n"); + else + printk(KERN_INFO + "Enabled Interrupt-remapping\n"); + } else + printk(KERN_ERR + "Failed to enable Interrupt-remapping and x2apic\n"); +#else + if (!cpu_has_x2apic) + return; + + if (x2apic_preenabled) + panic("x2apic enabled prior OS handover," + " enable CONFIG_INTR_REMAP"); + + printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping " + " and x2apic\n"); +#endif + + return; +} + /* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. @@ -943,6 +1068,11 @@ void __init early_init_lapic_mapping(void) */ void __init init_apic_mappings(void) { + if (x2apic) { + boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + return; + } + /* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another @@ -981,6 +1111,9 @@ int __init APIC_init_uniprocessor(void) return -1; } + enable_IR_x2apic(); + setup_apic_routing(); + verify_local_APIC(); connect_bsp_APIC(); @@ -1238,10 +1371,14 @@ static int lapic_resume(struct sys_device *dev) maxlvt = lapic_get_maxlvt(); local_irq_save(flags); - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; - wrmsr(MSR_IA32_APICBASE, l, h); + if (!x2apic) { + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + wrmsr(MSR_IA32_APICBASE, l, h); + } else + enable_x2apic(); + apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); apic_write(APIC_DFR, apic_pm_state.apic_dfr); @@ -1381,6 +1518,15 @@ __cpuinit int apic_is_clustered_box(void) return (clusters > 2); } +static __init int setup_nox2apic(char *str) +{ + disable_x2apic = 1; + clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC); + return 0; +} +early_param("nox2apic", setup_nox2apic); + + /* * APIC command line parameters */ diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 36537ab9e56..e7bf3c2dc5f 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -606,6 +606,8 @@ void __cpuinit cpu_init(void) barrier(); check_efer(); + if (cpu != 0 && x2apic) + enable_x2apic(); /* * set up and load the per-CPU TSS diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 1029e178cdf..792e21ba1a8 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 3b25e49380c..70e1f3e287f 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -545,7 +545,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) generic_bigsmp_probe(); #endif +#ifdef CONFIG_X86_32 setup_apic_routing(); +#endif if (!num_processors) printk(KERN_ERR "MPTABLE: no processors registered!\n"); return num_processors; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 987b6fde3a9..2e78a143dec 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -730,6 +730,8 @@ void __init setup_arch(char **cmdline_p) num_physpages = max_pfn; check_efer(); + if (cpu_has_x2apic) + check_x2apic(); /* How many end-of-memory variables you have, grandma! */ /* need this before calling reserve_initrd */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c55263b3df0..0c43e1f2e7d 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1145,6 +1145,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) current_thread_info()->cpu = 0; /* needed? */ set_cpu_sibling_map(0); +#ifdef CONFIG_X86_64 + enable_IR_x2apic(); + setup_apic_routing(); +#endif + if (smp_sanity_check(max_cpus) < 0) { printk(KERN_INFO "SMP disabled\n"); disable_smp(); diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index aa746704a5c..129752dd252 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -100,6 +100,11 @@ extern void apic_wait_icr_idle(void); extern u32 safe_apic_wait_icr_idle(void); extern void apic_icr_write(u32 low, u32 id); #else +extern int x2apic, x2apic_preenabled; +extern void check_x2apic(void); +extern void enable_x2apic(void); +extern void enable_IR_x2apic(void); +extern void x2apic_icr_write(u32 low, u32 id); struct apic_ops { u32 (*read)(u32 reg); -- GitLab From 2d9579a124d746a3e0e0ba45e57d80800ee80807 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:16:59 -0700 Subject: [PATCH 0037/5416] x64, x2apic/intr-remap: support for x2apic physical mode support x2apic Physical mode support. By default we will use x2apic cluster mode. x2apic physical mode can be selected using "x2apic_phys" boot parameter. Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/genapic_64.c | 18 ++++- arch/x86/kernel/genx2apic_phys.c | 122 +++++++++++++++++++++++++++++++ include/asm-x86/genapic_64.h | 1 + 4 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 arch/x86/kernel/genx2apic_phys.c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index bde3e9b6fec..81280e93e79 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_OLPC) += olpc.o ifeq ($(CONFIG_X86_64),y) obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o obj-y += genx2apic_cluster.o + obj-y += genx2apic_phys.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o obj-$(CONFIG_AUDIT) += audit_64.o diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 792e21ba1a8..3940d8161f8 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -30,6 +30,15 @@ DEFINE_PER_CPU(int, x2apic_extra_bits); struct genapic __read_mostly *genapic = &apic_flat; +static int x2apic_phys = 0; + +static int set_x2apic_phys_mode(char *arg) +{ + x2apic_phys = 1; + return 0; +} +early_param("x2apic_phys", set_x2apic_phys_mode); + static enum uv_system_type uv_system_type; /* @@ -39,9 +48,12 @@ void __init setup_apic_routing(void) { if (uv_system_type == UV_NON_UNIQUE_APIC) genapic = &apic_x2apic_uv_x; - else if (cpu_has_x2apic && intr_remapping_enabled) - genapic = &apic_x2apic_cluster; - else + else if (cpu_has_x2apic && intr_remapping_enabled) { + if (x2apic_phys) + genapic = &apic_x2apic_phys; + else + genapic = &apic_x2apic_cluster; + } else #ifdef CONFIG_ACPI /* * Quirk: some x86_64 machines can only use physical APIC mode diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c new file mode 100644 index 00000000000..3c70b9d692b --- /dev/null +++ b/arch/x86/kernel/genx2apic_phys.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ + +static cpumask_t x2apic_target_cpus(void) +{ + return cpumask_of_cpu(0); +} + +static cpumask_t x2apic_vector_allocation_domain(int cpu) +{ + cpumask_t domain = CPU_MASK_NONE; + cpu_set(cpu, domain); + return domain; +} + +static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, + unsigned int dest) +{ + unsigned long cfg; + + cfg = __prepare_ICR(0, vector, dest); + + /* + * send the IPI. + */ + x2apic_icr_write(cfg, apicid); +} + +static void x2apic_send_IPI_mask(cpumask_t mask, int vector) +{ + unsigned long flags; + unsigned long query_cpu; + + local_irq_save(flags); + for_each_cpu_mask(query_cpu, mask) { + __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), + vector, APIC_DEST_PHYSICAL); + } + local_irq_restore(flags); +} + +static void x2apic_send_IPI_allbutself(int vector) +{ + cpumask_t mask = cpu_online_map; + + cpu_clear(smp_processor_id(), mask); + + if (!cpus_empty(mask)) + x2apic_send_IPI_mask(mask, vector); +} + +static void x2apic_send_IPI_all(int vector) +{ + x2apic_send_IPI_mask(cpu_online_map, vector); +} + +static int x2apic_apic_id_registered(void) +{ + return 1; +} + +static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = first_cpu(cpumask); + if ((unsigned)cpu < NR_CPUS) + return per_cpu(x86_cpu_to_apicid, cpu); + else + return BAD_APICID; +} + +static unsigned int x2apic_read_id(void) +{ + return apic_read(APIC_ID); +} + +static unsigned int phys_pkg_id(int index_msb) +{ + return x2apic_read_id() >> index_msb; +} + +void x2apic_send_IPI_self(int vector) +{ + apic_write(APIC_SELF_IPI, vector); +} + +void init_x2apic_ldr(void) +{ + return; +} + +struct genapic apic_x2apic_phys = { + .name = "physical x2apic", + .int_delivery_mode = dest_Fixed, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .target_cpus = x2apic_target_cpus, + .vector_allocation_domain = x2apic_vector_allocation_domain, + .apic_id_registered = x2apic_apic_id_registered, + .init_apic_ldr = init_x2apic_ldr, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_self = x2apic_send_IPI_self, + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .phys_pkg_id = phys_pkg_id, + .read_apic_id = x2apic_read_id, +}; diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 23246030587..122b9242a40 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -36,6 +36,7 @@ extern struct genapic *genapic; extern struct genapic apic_flat; extern struct genapic apic_physflat; extern struct genapic apic_x2apic_cluster; +extern struct genapic apic_x2apic_phys; extern int acpi_madt_oem_check(char *, char *); extern void apic_send_IPI_self(int vector); -- GitLab From 9fa8c481b55e80edd8c637573f87853bb6b600f5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 11:17:00 -0700 Subject: [PATCH 0038/5416] x64, x2apic/intr-remap: introduce CONFIG_INTR_REMAP Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2cfccc987a2..0bf8391a7f2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1651,6 +1651,14 @@ config DMAR_FLOPPY_WA workaround will setup a 1:1 mapping for the first 16M to make floppy (an ISA device) work. +config INTR_REMAP + bool "Support for Interrupt Remapping (EXPERIMENTAL)" + depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL + help + Supports Interrupt remapping for IO-APIC and MSI devices. + To use x2apic mode in the CPU's which support x2APIC enhancements or + to support platforms with CPU's having > 8 bit APIC ID, say Y. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" -- GitLab From 372e92d8b3e433888bf76c36f1c7e1405eae1584 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 10 Jul 2008 14:56:18 -0700 Subject: [PATCH 0039/5416] x64, x2apic/intr-remap: Interrupt-remapping and x2apic support On Thu, Jul 10, 2008 at 12:53:20PM -0700, Ingo Molnar wrote: > > Btw., i threw it at the -tip test-cluster and got back a quick build > bugreport: > > arch/x86/xen/enlighten.c: In function 'xen_patch': > arch/x86/xen/enlighten.c:1084: warning: label 'patch_site' defined but not used > arch/x86/xen/enlighten.c: At top level: > arch/x86/xen/enlighten.c:1272: error: expected identifier before '(' token > arch/x86/xen/enlighten.c:1273: error: expected '}' before '.' token > arch/x86/kernel/paravirt.c:376:2: error: invalid preprocessing directive > #ifndedarch/x86/kernel/paravirt.c:384:2: error: #endif without #if > > with this config: > > http://redhat.com/~mingo/misc/config-Thu_Jul_10_21_43_28_CEST_2008.bad fix the typo. Signed-off-by: Suresh Siddha Cc: "Siddha Cc: Suresh B" Cc: "akpm@linux-foundation.org" Cc: "arjan@linux.intel.com" Cc: "andi@firstfloor.org" Cc: "ebiederm@xmission.com" Cc: "jbarnes@virtuousgeek.org" Cc: "steiner@sgi.com" Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index b80105a0f47..4f29ff847eb 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,7 +360,7 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC -#ifnded CONFIG_X86_64 +#ifndef CONFIG_X86_64 .apic_write = native_apic_mem_write, .apic_write_atomic = native_apic_mem_write_atomic, .apic_read = native_apic_mem_read, -- GitLab From 277d1f5846d84e16760131a93b7a67ebfa8eded4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 13:11:55 -0700 Subject: [PATCH 0040/5416] x2apic: uninline uv_init_apic_ldr() Andrew says: > There's no point in declaring it inline if it's always called indirectly. And point taken! Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index dcd4fb219da..c915f750241 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -120,7 +120,7 @@ static int uv_apic_id_registered(void) return 1; } -static inline void uv_init_apic_ldr(void) +static void uv_init_apic_ldr(void) { } -- GitLab From ad66dd340f561bdde2285992314d9e4fd9b6191e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 13:11:56 -0700 Subject: [PATCH 0041/5416] x2apic: xen64 paravirt basic apic ops Define the Xen specific basic apic ops, in additon to paravirt apic ops, with some misc warning fixes. Signed-off-by: Suresh Siddha Cc: Jeremy Fitzhardinge Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 4 ++-- arch/x86/xen/enlighten.c | 41 ++++++++++++++++++++++++++++++++++++-- include/asm-x86/paravirt.h | 14 +++++++------ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 50dad44fb54..0c45df20e2b 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -783,11 +783,11 @@ static void lguest_wbinvd(void) * code qualifies for Advanced. It will also never interrupt anything. It * does, however, allow us to get through the Linux boot code. */ #ifdef CONFIG_X86_LOCAL_APIC -static void lguest_apic_write(unsigned long reg, u32 v) +static void lguest_apic_write(u32 reg, u32 v) { } -static u32 lguest_apic_read(unsigned long reg) +static u32 lguest_apic_read(u32 reg) { return 0; } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index dcd4e51f2f1..54e25566753 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -548,16 +548,45 @@ static void xen_io_delay(void) } #ifdef CONFIG_X86_LOCAL_APIC -static u32 xen_apic_read(unsigned long reg) +static u32 xen_apic_read(u32 reg) { return 0; } -static void xen_apic_write(unsigned long reg, u32 val) +static void xen_apic_write(u32 reg, u32 val) { /* Warn to see if there's any stray references */ WARN_ON(1); } + +#ifdef CONFIG_X86_64 +static u64 xen_apic_icr_read(void) +{ + return 0; +} + +static void xen_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void xen_apic_wait_icr_idle(void) +{ + return; +} + +static struct apic_ops xen_basic_apic_ops = { + .read = xen_apic_read, + .write = xen_apic_write, + .write_atomic = xen_apic_write, + .icr_read = xen_apic_icr_read, + .icr_write = xen_apic_icr_write, + .wait_icr_idle = xen_apic_wait_icr_idle, + .safe_wait_icr_idle = xen_apic_wait_icr_idle, +}; +#endif + #endif static void xen_flush_tlb(void) @@ -1130,9 +1159,11 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC +#ifndef CONFIG_X86_64 .apic_write = xen_apic_write, .apic_write_atomic = xen_apic_write, .apic_read = xen_apic_read, +#endif .setup_boot_clock = paravirt_nop, .setup_secondary_clock = paravirt_nop, .startup_ipi_hook = paravirt_nop, @@ -1291,6 +1322,12 @@ asmlinkage void __init xen_start_kernel(void) pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; +#ifdef CONFIG_X86_64 + /* + * for 64bit, set up the basic apic ops aswell. + */ + apic_ops = &xen_basic_apic_ops; +#endif if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 10adac02e6d..5e34d26aa3b 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -200,13 +200,15 @@ struct pv_irq_ops { struct pv_apic_ops { #ifdef CONFIG_X86_LOCAL_APIC +#ifndef CONFIG_X86_64 /* * Direct APIC operations, principally for VMI. Ideally * these shouldn't be in this interface. */ - void (*apic_write)(unsigned long reg, u32 v); - void (*apic_write_atomic)(unsigned long reg, u32 v); - u32 (*apic_read)(unsigned long reg); + void (*apic_write)(u32 reg, u32 v); + void (*apic_write_atomic)(u32 reg, u32 v); + u32 (*apic_read)(u32 reg); +#endif void (*setup_boot_clock)(void); void (*setup_secondary_clock)(void); @@ -892,17 +894,17 @@ static inline void slow_down_io(void) * Basic functions accessing APICs. */ #ifndef CONFIG_X86_64 -static inline void apic_write(unsigned long reg, u32 v) +static inline void apic_write(u32 reg, u32 v) { PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); } -static inline void apic_write_atomic(unsigned long reg, u32 v) +static inline void apic_write_atomic(u32 reg, u32 v) { PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v); } -static inline u32 apic_read(unsigned long reg) +static inline u32 apic_read(u32 reg) { return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); } -- GitLab From af9d13887f9e3699bbc852c39b076d30bb9dff2f Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 11 Jul 2008 13:11:57 -0700 Subject: [PATCH 0042/5416] x2apic: kernel-parameter documentation for "x2apic_phys" Signed-off-by: Suresh Siddha Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 56689ef1a15..88b08acf2ff 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1379,6 +1379,10 @@ and is between 256 and 4096 characters. It is defined in the file nox2apic [X86-64,APIC] Do not enable x2APIC mode. + x2apic_phys [X86-64,APIC] Use x2apic physical mode instead of + default x2apic cluster mode on platforms + supporting x2apic. + noltlbs [PPC] Do not use large page/tlb entries for kernel lowmem mapping on PPC40x. -- GitLab From c535b6a1a685eb23f96e2c221777d6c1e05080d5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:41:54 -0700 Subject: [PATCH 0043/5416] x86: let 32bit use apic_ops too Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 39 +++++++++++++++++++++++++++++++-------- include/asm-x86/apic.h | 13 ++----------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 2a83c07bd88..7413354c9ff 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,19 +145,13 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } -void apic_icr_write(u32 low, u32 id) -{ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, low); -} - -void apic_wait_icr_idle(void) +void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) cpu_relax(); } -u32 safe_apic_wait_icr_idle(void) +u32 safe_xapic_wait_icr_idle(void) { u32 send_status; int timeout; @@ -173,6 +167,35 @@ u32 safe_apic_wait_icr_idle(void) return send_status; } +void xapic_icr_write(u32 low, u32 id) +{ + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write_around(APIC_ICR, low); +} + +u64 xapic_icr_read(void) +{ + u32 icr1, icr2; + + icr2 = apic_read(APIC_ICR2); + icr1 = apic_read(APIC_ICR); + + return icr1 | ((u64)icr2 << 32); +} + +static struct apic_ops xapic_ops = { + .read = native_apic_mem_read, + .write = native_apic_mem_write, + .write_atomic = native_apic_mem_write_atomic, + .icr_read = xapic_icr_read, + .icr_write = xapic_icr_write, + .wait_icr_idle = xapic_wait_icr_idle, + .safe_wait_icr_idle = safe_xapic_wait_icr_idle, +}; + +struct apic_ops __read_mostly *apic_ops = &xapic_ops; +EXPORT_SYMBOL_GPL(apic_ops); + /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */ diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 129752dd252..fcd2f01277b 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -49,11 +49,6 @@ extern int disable_apic; #ifdef CONFIG_PARAVIRT #include #else -#ifndef CONFIG_X86_64 -#define apic_write native_apic_mem_write -#define apic_write_atomic native_apic_mem_write_atomic -#define apic_read native_apic_mem_read -#endif #define setup_boot_clock setup_boot_APIC_clock #define setup_secondary_clock setup_secondary_APIC_clock #endif @@ -95,16 +90,13 @@ static inline u32 native_apic_msr_read(u32 reg) return low; } -#ifdef CONFIG_X86_32 -extern void apic_wait_icr_idle(void); -extern u32 safe_apic_wait_icr_idle(void); -extern void apic_icr_write(u32 low, u32 id); -#else +#ifndef CONFIG_X86_32 extern int x2apic, x2apic_preenabled; extern void check_x2apic(void); extern void enable_x2apic(void); extern void enable_IR_x2apic(void); extern void x2apic_icr_write(u32 low, u32 id); +#endif struct apic_ops { u32 (*read)(u32 reg); @@ -125,7 +117,6 @@ extern struct apic_ops *apic_ops; #define apic_icr_write (apic_ops->icr_write) #define apic_wait_icr_idle (apic_ops->wait_icr_idle) #define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle) -#endif extern int get_physical_broadcast(void); -- GitLab From 4696ca5bfd2697f5686f96d59cf0b6de14869b4e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:43:10 -0700 Subject: [PATCH 0044/5416] x86: mach_apicdef.h need to include before smp.h smp.h internal has include, so need to include that at first when genericarch use them need to have different apicdef.h Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/bigsmp.c | 5 ++--- arch/x86/mach-generic/es7000.c | 3 +-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 5 ++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 59d77171455..b31f2800638 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -5,17 +5,16 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include -#include #include #include -#include #include +#include +#include #include #include diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 4742626f08c..9b30547d746 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -4,16 +4,15 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include #include -#include #include #include +#include #include #include #include diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 8091e68764c..95c07efff6b 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -4,7 +4,6 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include @@ -12,8 +11,9 @@ #include #include #include -#include #include +#include +#include #include #include #include diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index a97ea0f35b1..752edd96b1b 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -4,17 +4,16 @@ #define APIC_DEFINITION 1 #include #include -#include #include #include #include #include #include #include -#include #include -#include #include +#include +#include #include #include -- GitLab From 4c9961d56ec20c27ec5d02e49fd7427748312741 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 11 Jul 2008 18:44:16 -0700 Subject: [PATCH 0045/5416] x86: make read_apic_id return final apicid also remove GET_APIC_ID when read_apic_id is used. need to apply after [PATCH] x86: mach_apicdef.h need to include before smp.h Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 2 +- arch/x86/kernel/apic_32.c | 4 ++-- arch/x86/kernel/apic_64.c | 6 +++--- arch/x86/kernel/genapic_flat_64.c | 2 +- arch/x86/kernel/io_apic_32.c | 5 ++--- arch/x86/kernel/io_apic_64.c | 4 ++-- arch/x86/kernel/smpboot.c | 6 +++--- include/asm-x86/mach-default/mach_apic.h | 2 +- include/asm-x86/mach-default/mach_apicdef.h | 3 +-- include/asm-x86/mach-es7000/mach_apic.h | 2 +- include/asm-x86/smp.h | 11 ++++++++--- 11 files changed, 25 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8705262ddcd..b314bcd0840 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -761,7 +761,7 @@ static void __init acpi_register_lapic_address(unsigned long address) set_fixmap_nocache(FIX_APIC_BASE, address); if (boot_cpu_physical_apicid == -1U) { - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); #ifdef CONFIG_X86_32 apic_version[boot_cpu_physical_apicid] = GET_APIC_VERSION(apic_read(APIC_LVR)); diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7413354c9ff..47ff978aecf 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1230,7 +1230,7 @@ void __init init_apic_mappings(void) * default configuration (or the MP table is broken). */ if (boot_cpu_physical_apicid == -1U) - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } @@ -1270,7 +1270,7 @@ int __init APIC_init_uniprocessor(void) * might be zero if read from MP tables. Get it from LAPIC. */ #ifdef CONFIG_CRASH_DUMP - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); #endif physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index dd0501039f0..c75f58a66d8 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1060,7 +1060,7 @@ void __init early_init_lapic_mapping(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } /** @@ -1069,7 +1069,7 @@ void __init early_init_lapic_mapping(void) void __init init_apic_mappings(void) { if (x2apic) { - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); return; } @@ -1092,7 +1092,7 @@ void __init init_apic_mappings(void) * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); } /* diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 73558682213..7dac2f275fa 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -101,7 +101,7 @@ static unsigned int read_xapic_id(void) { unsigned int id; - id = GET_XAPIC_ID(apic_read(APIC_ID)); + id = GET_APIC_ID(apic_read(APIC_ID)); return id; } diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index c50adb84ea6..382208d11f8 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -1501,7 +1501,7 @@ void /*__init*/ print_local_APIC(void *dummy) smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, - GET_APIC_ID(read_apic_id())); + GET_APIC_ID(v)); v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); @@ -1709,8 +1709,7 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = - GET_APIC_ID(read_apic_id()); + entry.dest.physical.physical_dest = read_apic_id(); /* * Add it to the IO-APIC irq-routing table: diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 877aa2e9d7e..2db0f98e2af 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1246,7 +1246,7 @@ void __apicdebuginit print_local_APIC(void * dummy) printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); - printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id())); + printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, read_apic_id()); v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); @@ -1439,7 +1439,7 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest = GET_APIC_ID(read_apic_id()); + entry.dest = read_apic_id(); /* * Add it to the IO-APIC irq-routing table: diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0c43e1f2e7d..6cd002f3e20 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -211,7 +211,7 @@ static void __cpuinit smp_callin(void) /* * (This works even if the APIC is not enabled.) */ - phys_id = GET_APIC_ID(read_apic_id()); + phys_id = read_apic_id(); cpuid = smp_processor_id(); if (cpu_isset(cpuid, cpu_callin_map)) { panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, @@ -1157,9 +1157,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) } preempt_disable(); - if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) { + if (read_apic_id() != boot_cpu_physical_apicid) { panic("Boot APIC ID in local APIC unexpected (%d vs %d)", - GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid); + read_apic_id(), boot_cpu_physical_apicid); /* Or can we switch back to PIC here? */ } preempt_enable(); diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index e06d23975d6..925b797e2a2 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -56,7 +56,7 @@ static inline void init_apic_ldr(void) static inline int apic_id_registered(void) { - return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map); + return physid_isset(read_apic_id(), phys_cpu_present_map); } static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h index 453b58a67e2..3e1be6c99b3 100644 --- a/include/asm-x86/mach-default/mach_apicdef.h +++ b/include/asm-x86/mach-default/mach_apicdef.h @@ -5,9 +5,8 @@ #ifdef CONFIG_X86_64 #define APIC_ID_MASK (0xFFu<<24) -#define GET_APIC_ID(x) (x) +#define GET_APIC_ID(x) (((x)>>24) & 0xFFu) #define SET_APIC_ID(x) (((x)<<24)) -#define GET_XAPIC_ID(x) (((x) >> 24) & 0xFFu) #else #define APIC_ID_MASK (0xF<<24) static inline unsigned get_apic_id(unsigned long x) diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h index fbc8ad256f5..b3556ec3bca 100644 --- a/include/asm-x86/mach-es7000/mach_apic.h +++ b/include/asm-x86/mach-es7000/mach_apic.h @@ -141,7 +141,7 @@ static inline void setup_portio_remap(void) extern unsigned int boot_cpu_physical_apicid; static inline int check_phys_apicid_present(int cpu_physical_apicid) { - boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); + boot_cpu_physical_apicid = read_apic_id(); return (1); } diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index d9d007d2278..3b43ca202c3 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -165,9 +165,14 @@ static inline int logical_smp_processor_id(void) return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR)); } +#include static inline unsigned int read_apic_id(void) { - return *(u32 *)(APIC_BASE + APIC_ID); + unsigned int reg; + + reg = *(u32 *)(APIC_BASE + APIC_ID); + + return GET_APIC_ID(reg); } #endif @@ -175,11 +180,11 @@ static inline unsigned int read_apic_id(void) # if defined(APIC_DEFINITION) || defined(CONFIG_X86_64) extern int hard_smp_processor_id(void); # else -# include +#include static inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ - return GET_APIC_ID(read_apic_id()); + return read_apic_id(); } # endif /* APIC_DEFINITION */ -- GitLab From f910a9dc7c865896815e2a95fe33363e9522f277 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 12 Jul 2008 01:01:20 -0700 Subject: [PATCH 0046/5416] x86: make 64bit have get_apic_id generalize the x2apic code some more. let read_apic_id become a macro (later on a function/inline) GET_APIC_ID(apic_read(APIC_ID)) +#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) instead of this weird construct: -#define read_apic_id (genapic->read_apic_id) Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_flat_64.c | 26 ++++++++++++++++++--- arch/x86/kernel/genx2apic_cluster.c | 20 +++++++++++++++- arch/x86/kernel/genx2apic_phys.c | 20 +++++++++++++++- arch/x86/kernel/genx2apic_uv_x.c | 23 +++++++++++++++--- include/asm-x86/genapic_64.h | 4 +++- include/asm-x86/mach-default/mach_apic.h | 2 +- include/asm-x86/mach-default/mach_apicdef.h | 6 ++--- 7 files changed, 88 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 7dac2f275fa..2c973cbf054 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -97,11 +97,27 @@ static void flat_send_IPI_all(int vector) __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = (((x)>>24) & 0xFFu); + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = ((id & 0xFFu)<<24); + return x; +} + static unsigned int read_xapic_id(void) { unsigned int id; - id = GET_APIC_ID(apic_read(APIC_ID)); + id = get_apic_id(apic_read(APIC_ID)); return id; } @@ -134,7 +150,9 @@ struct genapic apic_flat = { .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = read_xapic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFu<<24), }; /* @@ -200,5 +218,7 @@ struct genapic apic_physflat = { .send_IPI_self = apic_send_IPI_self, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = read_xapic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFu<<24), }; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index ed0fdede800..40bc0140d89 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -94,6 +94,22 @@ static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = x; + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = id; + return x; +} + static unsigned int x2apic_read_id(void) { return apic_read(APIC_ID); @@ -131,5 +147,7 @@ struct genapic apic_x2apic_cluster = { .send_IPI_self = x2apic_send_IPI_self, .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = x2apic_read_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3c70b9d692b..2f3c6ca19de 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -84,6 +84,22 @@ static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } +static unsigned int get_apic_id(unsigned long x) +{ + unsigned int id; + + id = x; + return id; +} + +static unsigned long set_apic_id(unsigned int id) +{ + unsigned long x; + + x = id; + return x; +} + static unsigned int x2apic_read_id(void) { return apic_read(APIC_ID); @@ -118,5 +134,7 @@ struct genapic apic_x2apic_phys = { .send_IPI_self = x2apic_send_IPI_self, .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, - .read_apic_id = x2apic_read_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index c915f750241..3ca29cd8c23 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -139,16 +139,31 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask) return BAD_APICID; } -static unsigned int uv_read_apic_id(void) +static unsigned int get_apic_id(unsigned long x) { unsigned int id; WARN_ON(preemptible() && num_online_cpus() > 1); - id = apic_read(APIC_ID) | __get_cpu_var(x2apic_extra_bits); + id = x | __get_cpu_var(x2apic_extra_bits); return id; } +static long set_apic_id(unsigned int id) +{ + unsigned long x; + + /* maskout x2apic_extra_bits ? */ + x = id; + return x; +} + +static unsigned int uv_read_apic_id(void) +{ + + return get_apic_id(apic_read(APIC_ID)); +} + static unsigned int phys_pkg_id(int index_msb) { return uv_read_apic_id() >> index_msb; @@ -175,7 +190,9 @@ struct genapic apic_x2apic_uv_x = { /* ZZZ.send_IPI_self = uv_send_IPI_self, */ .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ - .read_apic_id = uv_read_apic_id, + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = (0xFFFFFFFFu), }; static __cpuinit void set_x2apic_extra_bits(int pnode) diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 122b9242a40..8ff2589da93 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -28,7 +28,9 @@ struct genapic { /* */ unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); unsigned int (*phys_pkg_id)(int index_msb); - unsigned int (*read_apic_id)(void); + unsigned int (*get_apic_id)(unsigned long x); + unsigned long (*set_apic_id)(unsigned int id); + unsigned long apic_id_mask; }; extern struct genapic *genapic; diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index 925b797e2a2..3d2b455581e 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -30,7 +30,7 @@ static inline cpumask_t target_cpus(void) #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) #define phys_pkg_id (genapic->phys_pkg_id) #define vector_allocation_domain (genapic->vector_allocation_domain) -#define read_apic_id (genapic->read_apic_id) +#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) #define send_IPI_self (genapic->send_IPI_self) extern void setup_apic_routing(void); #else diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h index 3e1be6c99b3..a55518aa5a2 100644 --- a/include/asm-x86/mach-default/mach_apicdef.h +++ b/include/asm-x86/mach-default/mach_apicdef.h @@ -4,9 +4,9 @@ #include #ifdef CONFIG_X86_64 -#define APIC_ID_MASK (0xFFu<<24) -#define GET_APIC_ID(x) (((x)>>24) & 0xFFu) -#define SET_APIC_ID(x) (((x)<<24)) +#define APIC_ID_MASK (genapic->apic_id_mask) +#define GET_APIC_ID(x) (genapic->get_apic_id(x)) +#define SET_APIC_ID(x) (genapic->set_apic_id(x)) #else #define APIC_ID_MASK (0xF<<24) static inline unsigned get_apic_id(unsigned long x) -- GitLab From 94a8c3c2437c8946f1b6c8e0b2c560a7db8ed3c6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 13 Jul 2008 22:19:35 -0700 Subject: [PATCH 0047/5416] x86: let 32bit use apic_ops too - fix fix for pv - clean up the namespace there too. Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt.c | 5 ---- arch/x86/kernel/vmi_32.c | 51 +++++++++++++++++++++++++++++++++++--- arch/x86/xen/enlighten.c | 19 +++++++------- include/asm-x86/paravirt.h | 29 ---------------------- 4 files changed, 57 insertions(+), 47 deletions(-) diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 4f29ff847eb..e0f139106c7 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -360,11 +360,6 @@ struct pv_cpu_ops pv_cpu_ops = { struct pv_apic_ops pv_apic_ops = { #ifdef CONFIG_X86_LOCAL_APIC -#ifndef CONFIG_X86_64 - .apic_write = native_apic_mem_write, - .apic_write_atomic = native_apic_mem_write_atomic, - .apic_read = native_apic_mem_read, -#endif .setup_boot_clock = setup_boot_APIC_clock, .setup_secondary_clock = setup_secondary_APIC_clock, .startup_ipi_hook = paravirt_nop, diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index b15346092b7..cf307435455 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -676,6 +676,50 @@ static inline int __init probe_vmi_rom(void) return 0; } +#ifdef CONFIG_X86_LOCAL_APIC +static u32 vmi_apic_read(u32 reg) +{ + return 0; +} + +static void vmi_apic_write(u32 reg, u32 val) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static u64 vmi_apic_icr_read(void) +{ + return 0; +} + +static void vmi_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void vmi_apic_wait_icr_idle(void) +{ + return; +} + +static u32 vmi_safe_apic_wait_icr_idle(void) +{ + return 0; +} + +static struct apic_ops vmi_basic_apic_ops = { + .read = vmi_apic_read, + .write = vmi_apic_write, + .write_atomic = vmi_apic_write, + .icr_read = vmi_apic_icr_read, + .icr_write = vmi_apic_icr_write, + .wait_icr_idle = vmi_apic_wait_icr_idle, + .safe_wait_icr_idle = vmi_safe_apic_wait_icr_idle, +}; +#endif + /* * VMI setup common to all processors */ @@ -904,9 +948,10 @@ static inline int __init activate_vmi(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - para_fill(pv_apic_ops.apic_read, APICRead); - para_fill(pv_apic_ops.apic_write, APICWrite); - para_fill(pv_apic_ops.apic_write_atomic, APICWrite); + para_fill(vmi_basic_apic_ops.read, APICRead); + para_fill(vmi_basic_apic_ops.write, APICWrite); + para_fill(vmi_basic_apic_ops.write_atomic, APICWrite); + apic_ops = &vmi_basic_apic_ops; #endif /* diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 54e25566753..d11dda7ebd7 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -559,7 +559,6 @@ static void xen_apic_write(u32 reg, u32 val) WARN_ON(1); } -#ifdef CONFIG_X86_64 static u64 xen_apic_icr_read(void) { return 0; @@ -576,6 +575,11 @@ static void xen_apic_wait_icr_idle(void) return; } +static u32 xen_safe_apic_wait_icr_idle(void) +{ + return 0; +} + static struct apic_ops xen_basic_apic_ops = { .read = xen_apic_read, .write = xen_apic_write, @@ -583,9 +587,8 @@ static struct apic_ops xen_basic_apic_ops = { .icr_read = xen_apic_icr_read, .icr_write = xen_apic_icr_write, .wait_icr_idle = xen_apic_wait_icr_idle, - .safe_wait_icr_idle = xen_apic_wait_icr_idle, + .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle, }; -#endif #endif @@ -1159,11 +1162,6 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC -#ifndef CONFIG_X86_64 - .apic_write = xen_apic_write, - .apic_write_atomic = xen_apic_write, - .apic_read = xen_apic_read, -#endif .setup_boot_clock = paravirt_nop, .setup_secondary_clock = paravirt_nop, .startup_ipi_hook = paravirt_nop, @@ -1322,9 +1320,10 @@ asmlinkage void __init xen_start_kernel(void) pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; -#ifdef CONFIG_X86_64 + +#ifdef CONFIG_X86_LOCAL_APIC /* - * for 64bit, set up the basic apic ops aswell. + * set up the basic apic ops. */ apic_ops = &xen_basic_apic_ops; #endif diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 5e34d26aa3b..08f89e385a9 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -200,15 +200,6 @@ struct pv_irq_ops { struct pv_apic_ops { #ifdef CONFIG_X86_LOCAL_APIC -#ifndef CONFIG_X86_64 - /* - * Direct APIC operations, principally for VMI. Ideally - * these shouldn't be in this interface. - */ - void (*apic_write)(u32 reg, u32 v); - void (*apic_write_atomic)(u32 reg, u32 v); - u32 (*apic_read)(u32 reg); -#endif void (*setup_boot_clock)(void); void (*setup_secondary_clock)(void); @@ -890,26 +881,6 @@ static inline void slow_down_io(void) } #ifdef CONFIG_X86_LOCAL_APIC -/* - * Basic functions accessing APICs. - */ -#ifndef CONFIG_X86_64 -static inline void apic_write(u32 reg, u32 v) -{ - PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); -} - -static inline void apic_write_atomic(u32 reg, u32 v) -{ - PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v); -} - -static inline u32 apic_read(u32 reg) -{ - return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); -} -#endif - static inline void setup_boot_clock(void) { PVOP_VCALL0(pv_apic_ops.setup_boot_clock); -- GitLab From 3cac97cbb14aed00d83eb33d4613b0fe3aaea863 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 6 Jul 2008 17:23:55 +0800 Subject: [PATCH 0048/5416] rcu classic: simplify the next pending batch use a batch number(rcp->pending) instead of a flag(rcp->next_pending) rcu_start_batch() need to change this flag, so mb()s is needed for memory-access safe. but(after this patch applied) rcu_start_batch() do not change this batch number(rcp->pending), rcp->pending is managed by __rcu_process_callbacks only, and troublesome mb()s are eliminated. And codes look simpler and clearer. Signed-off-by: Lai Jiangshan Cc: "Paul E. McKenney" Cc: Dipankar Sarma Cc: Gautham Shenoy Cc: Dhaval Giani Cc: Peter Zijlstra Signed-off-by: Ingo Molnar --- include/linux/rcuclassic.h | 2 +- kernel/rcuclassic.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index 8c774905dcf..c847e59c600 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h @@ -45,7 +45,7 @@ struct rcu_ctrlblk { long cur; /* Current batch number. */ long completed; /* Number of the last completed batch */ - int next_pending; /* Is the next batch already waiting? */ + long pending; /* Number of the last pending batch */ int signaled; diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index 16eeeaa9d61..03726eb9519 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -60,12 +60,14 @@ EXPORT_SYMBOL_GPL(rcu_lock_map); static struct rcu_ctrlblk rcu_ctrlblk = { .cur = -300, .completed = -300, + .pending = -300, .lock = __SPIN_LOCK_UNLOCKED(&rcu_ctrlblk.lock), .cpumask = CPU_MASK_NONE, }; static struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur = -300, .completed = -300, + .pending = -300, .lock = __SPIN_LOCK_UNLOCKED(&rcu_bh_ctrlblk.lock), .cpumask = CPU_MASK_NONE, }; @@ -276,14 +278,8 @@ static void rcu_do_batch(struct rcu_data *rdp) */ static void rcu_start_batch(struct rcu_ctrlblk *rcp) { - if (rcp->next_pending && + if (rcp->cur != rcp->pending && rcp->completed == rcp->cur) { - rcp->next_pending = 0; - /* - * next_pending == 0 must be visible in - * __rcu_process_callbacks() before it can see new value of cur. - */ - smp_wmb(); rcp->cur++; /* @@ -441,16 +437,14 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, /* determine batch number */ rdp->batch = rcp->cur + 1; - /* see the comment and corresponding wmb() in - * the rcu_start_batch() - */ - smp_rmb(); - if (!rcp->next_pending) { + if (rcu_batch_after(rdp->batch, rcp->pending)) { /* and start it/schedule start if it's a new batch */ spin_lock(&rcp->lock); - rcp->next_pending = 1; - rcu_start_batch(rcp); + if (rcu_batch_after(rdp->batch, rcp->pending)) { + rcp->pending = rdp->batch; + rcu_start_batch(rcp); + } spin_unlock(&rcp->lock); } } -- GitLab From 5127bed588a2f8f3a1f732de2a8a190b7df5dce3 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 6 Jul 2008 17:23:59 +0800 Subject: [PATCH 0049/5416] rcu classic: new algorithm for callbacks-processing(v2) This is v2, it's a little deference from v1 that I had send to lkml. use ACCESS_ONCE use rcu_batch_after/rcu_batch_before for batch # comparison. rcutorture test result: (hotplugs: do cpu-online/offline once per second) No CONFIG_NO_HZ: OK, 12hours No CONFIG_NO_HZ, hotplugs: OK, 12hours CONFIG_NO_HZ=y: OK, 24hours CONFIG_NO_HZ=y, hotplugs: Failed. (Failed also without my patch applied, exactly the same bug occurred, http://lkml.org/lkml/2008/7/3/24) v1's email thread: http://lkml.org/lkml/2008/6/2/539 v1's description: The code/algorithm of the implement of current callbacks-processing is very efficient and technical. But when I studied it and I found a disadvantage: In multi-CPU systems, when a new RCU callback is being queued(call_rcu[_bh]), this callback will be invoked after the grace period for the batch with batch number = rcp->cur+2 has completed very very likely in current implement. Actually, this callback can be invoked after the grace period for the batch with batch number = rcp->cur+1 has completed. The delay of invocation means that latency of synchronize_rcu() is extended. But more important thing is that the callbacks usually free memory, and these works are delayed too! it's necessary for reclaimer to free memory as soon as possible when left memory is few. A very simple way can solve this problem: a field(struct rcu_head::batch) is added to record the batch number for the RCU callback. And when a new RCU callback is being queued, we determine the batch number for this callback(head->batch = rcp->cur+1) and we move this callback to rdp->donelist if we find that head->batch <= rcp->completed when we process callbacks. This simple way reduces the wait time for invocation a lot. (about 2.5Grace Period -> 1.5Grace Period in average in multi-CPU systems) This is my algorithm. But I do not add any field for struct rcu_head in my implement. We just need to memorize the last 2 batches and their batch number, because these 2 batches include all entries that for whom the grace period hasn't completed. So we use a special linked-list rather than add a field. Please see the comment of struct rcu_data. Signed-off-by: Lai Jiangshan Cc: "Paul E. McKenney" Cc: Dipankar Sarma Cc: Gautham Shenoy Cc: Dhaval Giani Cc: Peter Zijlstra Signed-off-by: Ingo Molnar --- include/linux/rcuclassic.h | 26 +++--- kernel/rcuclassic.c | 157 +++++++++++++++++++++++-------------- 2 files changed, 114 insertions(+), 69 deletions(-) diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index c847e59c600..04c728147be 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h @@ -66,11 +66,7 @@ static inline int rcu_batch_after(long a, long b) return (a - b) > 0; } -/* - * Per-CPU data for Read-Copy UPdate. - * nxtlist - new callbacks are added here - * curlist - current batch for which quiescent cycle started if any - */ +/* Per-CPU data for Read-Copy UPdate. */ struct rcu_data { /* 1) quiescent state handling : */ long quiescbatch; /* Batch # for grace period */ @@ -78,12 +74,24 @@ struct rcu_data { int qs_pending; /* core waits for quiesc state */ /* 2) batch handling */ - long batch; /* Batch # for current RCU batch */ + /* + * if nxtlist is not NULL, then: + * batch: + * The batch # for the last entry of nxtlist + * [*nxttail[1], NULL = *nxttail[2]): + * Entries that batch # <= batch + * [*nxttail[0], *nxttail[1]): + * Entries that batch # <= batch - 1 + * [nxtlist, *nxttail[0]): + * Entries that batch # <= batch - 2 + * The grace period for these entries has completed, and + * the other grace-period-completed entries may be moved + * here temporarily in rcu_process_callbacks(). + */ + long batch; struct rcu_head *nxtlist; - struct rcu_head **nxttail; + struct rcu_head **nxttail[3]; long qlen; /* # of queued callbacks */ - struct rcu_head *curlist; - struct rcu_head **curtail; struct rcu_head *donelist; struct rcu_head **donetail; long blimit; /* Upper limit on a processed batch */ diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index 03726eb9519..d3553ee55f6 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -120,6 +120,43 @@ static inline void force_quiescent_state(struct rcu_data *rdp, } #endif +static void __call_rcu(struct rcu_head *head, struct rcu_ctrlblk *rcp, + struct rcu_data *rdp) +{ + long batch; + smp_mb(); /* reads the most recently updated value of rcu->cur. */ + + /* + * Determine the batch number of this callback. + * + * Using ACCESS_ONCE to avoid the following error when gcc eliminates + * local variable "batch" and emits codes like this: + * 1) rdp->batch = rcp->cur + 1 # gets old value + * ...... + * 2)rcu_batch_after(rcp->cur + 1, rdp->batch) # gets new value + * then [*nxttail[0], *nxttail[1]) may contain callbacks + * that batch# = rdp->batch, see the comment of struct rcu_data. + */ + batch = ACCESS_ONCE(rcp->cur) + 1; + + if (rdp->nxtlist && rcu_batch_after(batch, rdp->batch)) { + /* process callbacks */ + rdp->nxttail[0] = rdp->nxttail[1]; + rdp->nxttail[1] = rdp->nxttail[2]; + if (rcu_batch_after(batch - 1, rdp->batch)) + rdp->nxttail[0] = rdp->nxttail[2]; + } + + rdp->batch = batch; + *rdp->nxttail[2] = head; + rdp->nxttail[2] = &head->next; + + if (unlikely(++rdp->qlen > qhimark)) { + rdp->blimit = INT_MAX; + force_quiescent_state(rdp, &rcu_ctrlblk); + } +} + /** * call_rcu - Queue an RCU callback for invocation after a grace period. * @head: structure to be used for queueing the RCU updates. @@ -135,18 +172,11 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { unsigned long flags; - struct rcu_data *rdp; head->func = func; head->next = NULL; local_irq_save(flags); - rdp = &__get_cpu_var(rcu_data); - *rdp->nxttail = head; - rdp->nxttail = &head->next; - if (unlikely(++rdp->qlen > qhimark)) { - rdp->blimit = INT_MAX; - force_quiescent_state(rdp, &rcu_ctrlblk); - } + __call_rcu(head, &rcu_ctrlblk, &__get_cpu_var(rcu_data)); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(call_rcu); @@ -171,20 +201,11 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { unsigned long flags; - struct rcu_data *rdp; head->func = func; head->next = NULL; local_irq_save(flags); - rdp = &__get_cpu_var(rcu_bh_data); - *rdp->nxttail = head; - rdp->nxttail = &head->next; - - if (unlikely(++rdp->qlen > qhimark)) { - rdp->blimit = INT_MAX; - force_quiescent_state(rdp, &rcu_bh_ctrlblk); - } - + __call_rcu(head, &rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(call_rcu_bh); @@ -213,12 +234,6 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); static inline void raise_rcu_softirq(void) { raise_softirq(RCU_SOFTIRQ); - /* - * The smp_mb() here is required to ensure that this cpu's - * __rcu_process_callbacks() reads the most recently updated - * value of rcu->cur. - */ - smp_mb(); } /* @@ -360,13 +375,15 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, * which is dead and hence not processing interrupts. */ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list, - struct rcu_head **tail) + struct rcu_head **tail, long batch) { - local_irq_disable(); - *this_rdp->nxttail = list; - if (list) - this_rdp->nxttail = tail; - local_irq_enable(); + if (list) { + local_irq_disable(); + this_rdp->batch = batch; + *this_rdp->nxttail[2] = list; + this_rdp->nxttail[2] = tail; + local_irq_enable(); + } } static void __rcu_offline_cpu(struct rcu_data *this_rdp, @@ -380,9 +397,9 @@ static void __rcu_offline_cpu(struct rcu_data *this_rdp, if (rcp->cur != rcp->completed) cpu_quiet(rdp->cpu, rcp); spin_unlock_bh(&rcp->lock); - rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail); - rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail); - rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail); + /* spin_lock implies smp_mb() */ + rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail, rcp->cur + 1); + rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail[2], rcp->cur + 1); local_irq_disable(); this_rdp->qlen += rdp->qlen; @@ -416,27 +433,37 @@ static void rcu_offline_cpu(int cpu) static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) { - *rdp->donetail = rdp->curlist; - rdp->donetail = rdp->curtail; - rdp->curlist = NULL; - rdp->curtail = &rdp->curlist; - } - - if (rdp->nxtlist && !rdp->curlist) { + if (rdp->nxtlist) { local_irq_disable(); - rdp->curlist = rdp->nxtlist; - rdp->curtail = rdp->nxttail; - rdp->nxtlist = NULL; - rdp->nxttail = &rdp->nxtlist; - local_irq_enable(); /* - * start the next batch of callbacks + * move the other grace-period-completed entries to + * [rdp->nxtlist, *rdp->nxttail[0]) temporarily + */ + if (!rcu_batch_before(rcp->completed, rdp->batch)) + rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2]; + else if (!rcu_batch_before(rcp->completed, rdp->batch - 1)) + rdp->nxttail[0] = rdp->nxttail[1]; + + /* + * the grace period for entries in + * [rdp->nxtlist, *rdp->nxttail[0]) has completed and + * move these entries to donelist */ + if (rdp->nxttail[0] != &rdp->nxtlist) { + *rdp->donetail = rdp->nxtlist; + rdp->donetail = rdp->nxttail[0]; + rdp->nxtlist = *rdp->nxttail[0]; + *rdp->donetail = NULL; + + if (rdp->nxttail[1] == rdp->nxttail[0]) + rdp->nxttail[1] = &rdp->nxtlist; + if (rdp->nxttail[2] == rdp->nxttail[0]) + rdp->nxttail[2] = &rdp->nxtlist; + rdp->nxttail[0] = &rdp->nxtlist; + } - /* determine batch number */ - rdp->batch = rcp->cur + 1; + local_irq_enable(); if (rcu_batch_after(rdp->batch, rcp->pending)) { /* and start it/schedule start if it's a new batch */ @@ -462,15 +489,26 @@ static void rcu_process_callbacks(struct softirq_action *unused) static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - /* This cpu has pending rcu entries and the grace period - * for them has completed. - */ - if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) - return 1; + if (rdp->nxtlist) { + /* + * This cpu has pending rcu entries and the grace period + * for them has completed. + */ + if (!rcu_batch_before(rcp->completed, rdp->batch)) + return 1; + if (!rcu_batch_before(rcp->completed, rdp->batch - 1) && + rdp->nxttail[0] != rdp->nxttail[1]) + return 1; + if (rdp->nxttail[0] != &rdp->nxtlist) + return 1; - /* This cpu has no pending entries, but there are new entries */ - if (!rdp->curlist && rdp->nxtlist) - return 1; + /* + * This cpu has pending rcu entries and the new batch + * for then hasn't been started nor scheduled start + */ + if (rcu_batch_after(rdp->batch, rcp->pending)) + return 1; + } /* This cpu has finished callbacks to invoke */ if (rdp->donelist) @@ -506,7 +544,7 @@ int rcu_needs_cpu(int cpu) struct rcu_data *rdp = &per_cpu(rcu_data, cpu); struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu); - return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu)); + return !!rdp->nxtlist || !!rdp_bh->nxtlist || rcu_pending(cpu); } void rcu_check_callbacks(int cpu, int user) @@ -553,8 +591,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { memset(rdp, 0, sizeof(*rdp)); - rdp->curtail = &rdp->curlist; - rdp->nxttail = &rdp->nxtlist; + rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2] = &rdp->nxtlist; rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending = 0; -- GitLab From 9a8f0e6b5dfe3b4f330fc82b16a4000f5688fce8 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 18 Jul 2008 09:59:40 -0700 Subject: [PATCH 0050/5416] x86: let 32bit use apic_ops too - fix Fix VMI apic_ops. Signed-off-by: Suresh Siddha Acked-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 5 ++++ arch/x86/kernel/vmi_32.c | 51 +++------------------------------------ 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 47ff978aecf..cb54d9e20f9 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -145,6 +145,11 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +/* + * Paravirt kernels also might be using these below ops. So we still + * use generic apic_read()/apic_write(), which might be pointing to different + * ops in PARAVIRT case. + */ void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index cf307435455..237082833c1 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -676,50 +676,6 @@ static inline int __init probe_vmi_rom(void) return 0; } -#ifdef CONFIG_X86_LOCAL_APIC -static u32 vmi_apic_read(u32 reg) -{ - return 0; -} - -static void vmi_apic_write(u32 reg, u32 val) -{ - /* Warn to see if there's any stray references */ - WARN_ON(1); -} - -static u64 vmi_apic_icr_read(void) -{ - return 0; -} - -static void vmi_apic_icr_write(u32 low, u32 id) -{ - /* Warn to see if there's any stray references */ - WARN_ON(1); -} - -static void vmi_apic_wait_icr_idle(void) -{ - return; -} - -static u32 vmi_safe_apic_wait_icr_idle(void) -{ - return 0; -} - -static struct apic_ops vmi_basic_apic_ops = { - .read = vmi_apic_read, - .write = vmi_apic_write, - .write_atomic = vmi_apic_write, - .icr_read = vmi_apic_icr_read, - .icr_write = vmi_apic_icr_write, - .wait_icr_idle = vmi_apic_wait_icr_idle, - .safe_wait_icr_idle = vmi_safe_apic_wait_icr_idle, -}; -#endif - /* * VMI setup common to all processors */ @@ -948,10 +904,9 @@ static inline int __init activate_vmi(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - para_fill(vmi_basic_apic_ops.read, APICRead); - para_fill(vmi_basic_apic_ops.write, APICWrite); - para_fill(vmi_basic_apic_ops.write_atomic, APICWrite); - apic_ops = &vmi_basic_apic_ops; + para_fill(apic_ops->read, APICRead); + para_fill(apic_ops->write, APICWrite); + para_fill(apic_ops->write_atomic, APICWrite); #endif /* -- GitLab From 511d9d34183662aada3890883e860b151d707e22 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 14 Jul 2008 09:49:14 -0700 Subject: [PATCH 0051/5416] x86: apic_ops for lguest apic_ops for lguest. Signed-off-by: Suresh Siddha Acked-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 0c45df20e2b..675ee7a6475 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -791,6 +791,37 @@ static u32 lguest_apic_read(u32 reg) { return 0; } + +static u64 lguest_apic_icr_read(void) +{ + return 0; +} + +static void lguest_apic_icr_write(u32 low, u32 id) +{ + /* Warn to see if there's any stray references */ + WARN_ON(1); +} + +static void lguest_apic_wait_icr_idle(void) +{ + return; +} + +static u32 lguest_apic_safe_wait_icr_idle(void) +{ + return 0; +} + +static struct apic_ops lguest_basic_apic_ops = { + .read = lguest_apic_read, + .write = lguest_apic_write, + .write_atomic = lguest_apic_write, + .icr_read = lguest_apic_icr_read, + .icr_write = lguest_apic_icr_write, + .wait_icr_idle = lguest_apic_wait_icr_idle, + .safe_wait_icr_idle = lguest_apic_safe_wait_icr_idle, +}; #endif /* STOP! Until an interrupt comes in. */ @@ -990,9 +1021,7 @@ __init void lguest_init(void) #ifdef CONFIG_X86_LOCAL_APIC /* apic read/write intercepts */ - pv_apic_ops.apic_write = lguest_apic_write; - pv_apic_ops.apic_write_atomic = lguest_apic_write; - pv_apic_ops.apic_read = lguest_apic_read; + apic_ops = &lguest_basic_apic_ops; #endif /* time operations */ -- GitLab From f586bf7df9acc26b68b0feefc0dd32fa63516d3a Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Fri, 18 Jul 2008 15:58:35 -0700 Subject: [PATCH 0052/5416] x86: APIC: Remove apic_write_around(); use alternatives, merge fix On Fri, Jul 18, 2008 at 02:03:48PM -0700, Ingo Molnar wrote: > > * Yinghai Lu wrote: > > > > git merge tip/x86/x2apic > > CONFLICT (content): Merge conflict in arch/x86/kernel/Makefile > > CONFLICT (content): Merge conflict in arch/x86/kernel/paravirt.c > > CONFLICT (content): Merge conflict in arch/x86/kernel/smpboot.c > > CONFLICT (content): Merge conflict in arch/x86/kernel/vmi_32.c > > CONFLICT (content): Merge conflict in arch/x86/xen/enlighten.c > > CONFLICT (content): Merge conflict in include/asm-x86/apic.h > > CONFLICT (content): Merge conflict in include/asm-x86/paravirt.h > > that's due to the changes in tip/x86/apic and in tip/x86/uv. > > ok, i've just merged x86/apic into x86/x2apic and x86/uv as well, and > pushed out the result. > > Note: it's a first raw merge and completely untested. It will now merge > cleanly into tip/master. There are probably a few details missing. Ingo, thanks for doing this. While I was testing my merge changes, you posted yours... anyhow we need this piece, which is missing from your merge. Signed-off-by: Suresh Siddha Cc: Yinghai Lu Cc: "Maciej W. Rozycki" Cc: Jeremy Fitzhardinge Cc: Zachary Amsden Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 5 ++--- arch/x86/kernel/apic_64.c | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index dcb897f22aa..8728f54a93d 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -174,8 +174,8 @@ u32 safe_xapic_wait_icr_idle(void) void xapic_icr_write(u32 low, u32 id) { - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, low); + apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write(APIC_ICR, low); } u64 xapic_icr_read(void) @@ -191,7 +191,6 @@ u64 xapic_icr_read(void) static struct apic_ops xapic_ops = { .read = native_apic_mem_read, .write = native_apic_mem_write, - .write_atomic = native_apic_mem_write_atomic, .icr_read = xapic_icr_read, .icr_write = xapic_icr_write, .wait_icr_idle = xapic_wait_icr_idle, diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46e612408ac..a850bc63fb1 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -167,7 +167,6 @@ u64 xapic_icr_read(void) static struct apic_ops xapic_ops = { .read = native_apic_mem_read, .write = native_apic_mem_write, - .write_atomic = native_apic_mem_write_atomic, .icr_read = xapic_icr_read, .icr_write = xapic_icr_write, .wait_icr_idle = xapic_wait_icr_idle, @@ -206,7 +205,6 @@ u64 x2apic_icr_read(void) static struct apic_ops x2apic_ops = { .read = native_apic_msr_read, .write = native_apic_msr_write, - .write_atomic = native_apic_msr_write, .icr_read = x2apic_icr_read, .icr_write = x2apic_icr_write, .wait_icr_idle = x2apic_wait_icr_idle, -- GitLab From caf43bf7c6a55e89b6df5179df434d67e24aa32e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 20 Jul 2008 14:06:50 +0200 Subject: [PATCH 0053/5416] x86, xen: fix apic_ops build on UP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/xen/enlighten.c:615: error: variable ‘xen_basic_apic_ops’ has initializer but incomplete type arch/x86/xen/enlighten.c:616: error: unknown field ‘read’ specified in initializer [...] Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 008b7b69581..e4d1459a63d 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include -- GitLab From 7be42004065ce4df193aeef5befd26805267d0d9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 20 Jul 2008 17:04:57 +0200 Subject: [PATCH 0054/5416] x86, lguest: fix apic_ops build on UP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/lguest/boot.c:816: error: variable ‘lguest_basic_apic_ops’ has initializer but incomplete type arch/x86/lguest/boot.c:817: error: unknown field ‘read’ specified in initializer [...] Signed-off-by: Ingo Molnar --- arch/x86/lguest/boot.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 35c4349cd66..756fc489652 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include -- GitLab From 68c072388d2339af504c033a51886ea7c6b8d806 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Tue, 15 Jul 2008 16:24:50 +0200 Subject: [PATCH 0055/5416] ALSA: re-order AC97 codec ID table. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ac97/ac97_codec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 8c49a00a5e3..f6a7d721649 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -67,8 +67,8 @@ struct ac97_codec_id { }; static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { -{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, { 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL }, +{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, { 0x414c4300, 0xffffff00, "Realtek", NULL, NULL }, { 0x414c4700, 0xffffff00, "Realtek", NULL, NULL }, { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL }, @@ -94,11 +94,6 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { }; static const struct ac97_codec_id snd_ac97_codec_ids[] = { -{ 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL }, -{ 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL }, -{ 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL }, -{ 0x414b4d06, 0xffffffff, "AK4544A", NULL, NULL }, -{ 0x414b4d07, 0xffffffff, "AK4545", NULL, NULL }, { 0x41445303, 0xffffffff, "AD1819", patch_ad1819, NULL }, { 0x41445340, 0xffffffff, "AD1881", patch_ad1881, NULL }, { 0x41445348, 0xffffffff, "AD1881A", patch_ad1881, NULL }, @@ -112,20 +107,25 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL }, { 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, { 0x41445378, 0xffffffff, "AD1986", patch_ad1986, NULL }, +{ 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL }, +{ 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL }, +{ 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL }, +{ 0x414b4d06, 0xffffffff, "AK4544A", NULL, NULL }, +{ 0x414b4d07, 0xffffffff, "AK4545", NULL, NULL }, { 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL }, { 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL }, { 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */ { 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */ { 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */ { 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL }, -{ 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, -{ 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ -{ 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, -{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, { 0x414c4730, 0xffffffff, "ALC101", NULL, NULL }, { 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL }, { 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL }, +{ 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, { 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL }, +{ 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ +{ 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, +{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, -- GitLab From 1cd2224cd01898a13138f4ab476932cfb689839e Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Fri, 18 Jul 2008 18:20:52 +0200 Subject: [PATCH 0056/5416] ALSA: hda: digital pc-beep support hd-audio codecs Added digital pc-beep support using linear tone generation for hd-codecs along with initial support for several IDT codecs. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/Kconfig | 8 ++ sound/pci/hda/Makefile | 1 + sound/pci/hda/hda_beep.c | 134 +++++++++++++++++++++++++++++++++ sound/pci/hda/hda_beep.h | 44 +++++++++++ sound/pci/hda/hda_codec.h | 4 + sound/pci/hda/patch_sigmatel.c | 63 ++++++++++++++++ 6 files changed, 254 insertions(+) create mode 100644 sound/pci/hda/hda_beep.c create mode 100644 sound/pci/hda/hda_beep.h diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 31f52d3fc21..db9e31fd061 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -517,6 +517,14 @@ config SND_HDA_HWDEP This interface can be used for out-of-band communication with codecs for debugging purposes. +config SND_HDA_INPUT_BEEP + bool "Support digital beep via input layer" + depends on SND_HDA_INTEL + depends on INPUT=y || INPUT=SND_HDA_INTEL + help + Say Y here to build a digital beep interface for HD-audio + driver. This interface is used to generate digital beeps. + config SND_HDA_CODEC_REALTEK bool "Build Realtek HD-audio codec support" depends on SND_HDA_INTEL diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index ab0c726d648..6db92fd954d 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -5,6 +5,7 @@ snd-hda-intel-y := hda_intel.o snd-hda-intel-y += hda_codec.o snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o +snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c new file mode 100644 index 00000000000..5a764c48139 --- /dev/null +++ b/sound/pci/hda/hda_beep.c @@ -0,0 +1,134 @@ +/* + * Digital Beep Input Interface for HD-audio codec + * + * Author: Matthew Ranostay + * Copyright (c) 2008 Embedded Alley Solutions Inc + * + * This driver 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 driver 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 "hda_beep.h" + +enum { + DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */ + DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */ + DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ +}; + +static void snd_hda_generate_beep(struct work_struct *work) +{ + struct hda_beep *beep = + container_of(work, struct hda_beep, beep_work); + struct hda_codec *codec = beep->codec; + + /* generate tone */ + snd_hda_codec_write_cache(codec, beep->nid, 0, + AC_VERB_SET_BEEP_CONTROL, beep->tone); +} + +static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, + unsigned int code, int hz) +{ + struct hda_beep *beep = input_get_drvdata(dev); + + switch (code) { + case SND_BELL: + if (hz) + hz = 1000; + case SND_TONE: + hz *= 1000; /* fixed point */ + hz = hz - DIGBEEP_HZ_MIN; + if (hz < 0) + hz = 0; /* turn off PC beep*/ + else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) + hz = 0xff; + else { + hz /= DIGBEEP_HZ_STEP; + hz++; + } + break; + default: + return -1; + } + beep->tone = hz; + + /* schedule beep event */ + schedule_work(&beep->beep_work); + return 0; +} + +int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) +{ + struct input_dev *input_dev; + struct hda_beep *beep; + int err; + + beep = kzalloc(sizeof(*beep), GFP_KERNEL); + if (beep == NULL) + return -ENOMEM; + snprintf(beep->phys, sizeof(beep->phys), + "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); + input_dev = input_allocate_device(); + + /* setup digital beep device */ + input_dev->name = "HDA Digital PCBeep"; + input_dev->phys = beep->phys; + input_dev->id.bustype = BUS_PCI; + + input_dev->id.vendor = codec->vendor_id >> 16; + input_dev->id.product = codec->vendor_id & 0xffff; + input_dev->id.version = 0x01; + + input_dev->evbit[0] = BIT_MASK(EV_SND); + input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); + input_dev->event = snd_hda_beep_event; + input_dev->dev.parent = &codec->bus->pci->dev; + input_set_drvdata(input_dev, beep); + + err = input_register_device(input_dev); + if (err < 0) { + kfree(input_dev); + kfree(beep); + return err; + } + + /* enable linear scale */ + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_DIGI_CONVERT_2, 0x01); + + beep->nid = nid; + beep->dev = input_dev; + beep->codec = codec; + codec->beep = beep; + + INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); + return 0; +} + +void snd_hda_detach_beep_device(struct hda_codec *codec) +{ + struct hda_beep *beep = codec->beep; + if (beep) { + cancel_work_sync(&beep->beep_work); + flush_scheduled_work(); + + input_unregister_device(beep->dev); + kfree(beep); + } +} diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h new file mode 100644 index 00000000000..de4036e6e71 --- /dev/null +++ b/sound/pci/hda/hda_beep.h @@ -0,0 +1,44 @@ +/* + * Digital Beep Input Interface for HD-audio codec + * + * Author: Matthew Ranostay + * Copyright (c) 2008 Embedded Alley Solutions Inc + * + * This driver 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 driver 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 + */ + +#ifndef __SOUND_HDA_BEEP_H +#define __SOUND_HDA_BEEP_H + +#include "hda_codec.h" + +/* beep information */ +struct hda_beep { + struct input_dev *dev; + struct hda_codec *codec; + char phys[32]; + int tone; + int nid; + struct work_struct beep_work; /* scheduled task for beep event */ +}; + +#ifdef CONFIG_SND_HDA_INPUT_BEEP +int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); +void snd_hda_detach_beep_device(struct hda_codec *codec); +#else +#define snd_hda_attach_beep_device(...) +#define snd_hda_detach_beep_device(...) +#endif +#endif diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index efc682888b3..3a63c445d36 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -449,6 +449,7 @@ enum { */ struct hda_bus; +struct hda_beep; struct hda_codec; struct hda_pcm; struct hda_pcm_stream; @@ -634,6 +635,9 @@ struct hda_codec { /* codec specific info */ void *spec; + /* beep device */ + struct hda_beep *beep; + /* widget capabilities cache */ unsigned int num_nodes; hda_nid_t start_nid; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3da621f25c..6ee73ed23dd 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -33,6 +33,7 @@ #include "hda_codec.h" #include "hda_local.h" #include "hda_patch.h" +#include "hda_beep.h" #define NUM_CONTROL_ALLOC 32 #define STAC_PWR_EVENT 0x20 @@ -164,6 +165,8 @@ struct sigmatel_spec { unsigned int num_dmuxes; hda_nid_t dig_in_nid; hda_nid_t mono_nid; + hda_nid_t anabeep_nid; + hda_nid_t digbeep_nid; /* pin widgets */ hda_nid_t *pin_nids; @@ -690,6 +693,8 @@ static struct hda_verb d965_core_init[] = { static struct hda_verb stac927x_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + /* enable analog pc beep path */ + { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, {} }; @@ -829,8 +834,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), + /* analog pc-beep replaced with digital beep support */ + /* HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT), HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT), + */ HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT), HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT), @@ -2609,6 +2617,34 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) "Mono Mux", spec->mono_nid); } +/* create PC beep volume controls */ +static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, + hda_nid_t nid) +{ + struct sigmatel_spec *spec = codec->spec; + u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); + int err; + + /* check for mute support for the the amp */ + if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { + err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, + "PC Beep Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); + if (err < 0) + return err; + } + + /* check to see if there is volume support for the amp */ + if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { + err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, + "PC Beep Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); + if (err < 0) + return err; + } + return 0; +} + /* labels for dmic mux inputs */ static const char *stac92xx_dmic_labels[5] = { "Analog Inputs", "Digital Mic 1", "Digital Mic 2", @@ -2844,6 +2880,28 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if (err < 0) return err; + /* setup analog beep controls */ + if (spec->anabeep_nid > 0) { + err = stac92xx_auto_create_beep_ctls(codec, + spec->anabeep_nid); + if (err < 0) + return err; + } + + /* setup digital beep controls and input device */ +#ifdef CONFIG_SND_HDA_INPUT_BEEP + if (spec->digbeep_nid > 0) { + hda_nid_t nid = spec->digbeep_nid; + + err = stac92xx_auto_create_beep_ctls(codec, nid); + if (err < 0) + return err; + err = snd_hda_attach_beep_device(codec, nid); + if (err < 0) + return err; + } +#endif + if (hp_speaker_swap == 1) { /* Restore the hp_outs and line_outs */ memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, @@ -3158,6 +3216,7 @@ static void stac92xx_free(struct hda_codec *codec) kfree(spec->bios_pin_configs); kfree(spec); + snd_hda_detach_beep_device(codec); } static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, @@ -3546,6 +3605,7 @@ again: spec->aloopback_mask = 0x01; spec->aloopback_shift = 8; + spec->digbeep_nid = 0x1c; spec->mux_nids = stac92hd73xx_mux_nids; spec->adc_nids = stac92hd73xx_adc_nids; spec->dmic_nids = stac92hd73xx_dmic_nids; @@ -3680,6 +3740,7 @@ again: spec->gpio_dir = 0x01; spec->gpio_data = 0x01; + spec->digbeep_nid = 0x26; spec->mux_nids = stac92hd71bxx_mux_nids; spec->adc_nids = stac92hd71bxx_adc_nids; spec->dmic_nids = stac92hd71bxx_dmic_nids; @@ -3854,6 +3915,7 @@ static int patch_stac927x(struct hda_codec *codec) stac92xx_set_config_regs(codec); } + spec->digbeep_nid = 0x23; spec->adc_nids = stac927x_adc_nids; spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); spec->mux_nids = stac927x_mux_nids; @@ -3974,6 +4036,7 @@ static int patch_stac9205(struct hda_codec *codec) stac92xx_set_config_regs(codec); } + spec->digbeep_nid = 0x23; spec->adc_nids = stac9205_adc_nids; spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); spec->mux_nids = stac9205_mux_nids; -- GitLab From 1b9b89e7f163336ad84200b66a17284dbf26aced Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 21 Jul 2008 22:08:21 -0700 Subject: [PATCH 0057/5416] x86: add apic probe for genapic 64bit, v2 introducing an APIC handling probing abstraction: static struct genapic *apic_probe[] __initdata = { &apic_x2apic_uv_x, &apic_x2apic_phys, &apic_x2apic_cluster, &apic_physflat, NULL, }; This way we can remove UV, x2apic specific code from genapic_64.c and move them to their specific genapic files. [ v2: fix compiling when CONFIG_ACPI is not set ] Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 85 +++++++++-------------------- arch/x86/kernel/genapic_flat_64.c | 26 +++++++++ arch/x86/kernel/genx2apic_cluster.c | 11 ++++ arch/x86/kernel/genx2apic_phys.c | 21 +++++++ arch/x86/kernel/genx2apic_uv_x.c | 32 ++++++++++- include/asm-x86/genapic_64.h | 1 + 6 files changed, 116 insertions(+), 60 deletions(-) diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 3940d8161f8..b3ba969c50d 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,62 +16,37 @@ #include #include #include -#include #include #include #include -#ifdef CONFIG_ACPI -#include -#endif - -DEFINE_PER_CPU(int, x2apic_extra_bits); +extern struct genapic apic_flat; +extern struct genapic apic_physflat; +extern struct genapic apic_x2xpic_uv_x; +extern struct genapic apic_x2apic_phys; +extern struct genapic apic_x2apic_cluster; struct genapic __read_mostly *genapic = &apic_flat; -static int x2apic_phys = 0; - -static int set_x2apic_phys_mode(char *arg) -{ - x2apic_phys = 1; - return 0; -} -early_param("x2apic_phys", set_x2apic_phys_mode); - -static enum uv_system_type uv_system_type; +static struct genapic *apic_probe[] __initdata = { + &apic_x2apic_uv_x, + &apic_x2apic_phys, + &apic_x2apic_cluster, + &apic_physflat, + NULL, +}; /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. */ void __init setup_apic_routing(void) { - if (uv_system_type == UV_NON_UNIQUE_APIC) - genapic = &apic_x2apic_uv_x; - else if (cpu_has_x2apic && intr_remapping_enabled) { - if (x2apic_phys) - genapic = &apic_x2apic_phys; - else - genapic = &apic_x2apic_cluster; - } else -#ifdef CONFIG_ACPI - /* - * Quirk: some x86_64 machines can only use physical APIC mode - * regardless of how many processors are present (x86_64 ES7000 - * is an example). - */ - if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) - genapic = &apic_physflat; - else -#endif - - if (max_physical_apicid < 8) - genapic = &apic_flat; - else - genapic = &apic_physflat; - - printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); + if (genapic == &apic_flat) { + if (max_physical_apicid >= 8) + genapic = &apic_physflat; + printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); + } } /* Same for both flat and physical. */ @@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector) int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (!strcmp(oem_id, "SGI")) { - if (!strcmp(oem_table_id, "UVL")) - uv_system_type = UV_LEGACY_APIC; - else if (!strcmp(oem_table_id, "UVX")) - uv_system_type = UV_X2APIC; - else if (!strcmp(oem_table_id, "UVH")) - uv_system_type = UV_NON_UNIQUE_APIC; + int i; + + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Setting APIC routing to %s.\n", + genapic->name); + return 1; + } } return 0; } - -enum uv_system_type get_uv_system_type(void) -{ - return uv_system_type; -} - -int is_uv_system(void) -{ - return uv_system_type != UV_NONE; -} diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 2c973cbf054..1740b83329f 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -21,6 +21,15 @@ #include #include +#ifdef CONFIG_ACPI +#include +#endif + +static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 1; +} + static cpumask_t flat_target_cpus(void) { return cpu_online_map; @@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb) struct genapic apic_flat = { .name = "flat", + .acpi_madt_oem_check = flat_acpi_madt_oem_check, .int_delivery_mode = dest_LowestPrio, .int_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = flat_target_cpus, @@ -160,6 +170,21 @@ struct genapic apic_flat = { * We cannot use logical delivery in this case because the mask * overflows, so use physical mode. */ +static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ +#ifdef CONFIG_ACPI + /* + * Quirk: some x86_64 machines can only use physical APIC mode + * regardless of how many processors are present (x86_64 ES7000 + * is an example). + */ + if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && + (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) + return 1; +#endif + + return 0; +} static cpumask_t physflat_target_cpus(void) { @@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask) struct genapic apic_physflat = { .name = "physical flat", + .acpi_madt_oem_check = physflat_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = physflat_target_cpus, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 40bc0140d89..ef3f3182d50 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -4,12 +4,22 @@ #include #include #include +#include + #include #include #include DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (cpu_has_x2apic && intr_remapping_enabled) + return 1; + + return 0; +} + /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ static cpumask_t x2apic_target_cpus(void) @@ -135,6 +145,7 @@ static void init_x2apic_ldr(void) struct genapic apic_x2apic_cluster = { .name = "cluster x2apic", + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .int_delivery_mode = dest_LowestPrio, .int_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = x2apic_target_cpus, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 2f3c6ca19de..f35a3bf3a9e 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -4,10 +4,30 @@ #include #include #include +#include + #include #include #include +DEFINE_PER_CPU(int, x2apic_extra_bits); + +static int x2apic_phys; + +static int set_x2apic_phys_mode(char *arg) +{ + x2apic_phys = 1; + return 0; +} +early_param("x2apic_phys", set_x2apic_phys_mode); + +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys) + return 1; + + return 0; +} /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ @@ -122,6 +142,7 @@ void init_x2apic_ldr(void) struct genapic apic_x2apic_phys = { .name = "physical x2apic", + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = x2apic_target_cpus, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index a8e5cb4c4d4..a882bc3a2ce 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -27,6 +27,33 @@ #include #include +static enum uv_system_type uv_system_type; + +static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (!strcmp(oem_id, "SGI")) { + if (!strcmp(oem_table_id, "UVL")) + uv_system_type = UV_LEGACY_APIC; + else if (!strcmp(oem_table_id, "UVX")) + uv_system_type = UV_X2APIC; + else if (!strcmp(oem_table_id, "UVH")) { + uv_system_type = UV_NON_UNIQUE_APIC; + return 1; + } + } + return 0; +} + +enum uv_system_type get_uv_system_type(void) +{ + return uv_system_type; +} + +int is_uv_system(void) +{ + return uv_system_type != UV_NONE; +} + DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); @@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x) return id; } -static long set_apic_id(unsigned int id) +static unsigned long set_apic_id(unsigned int id) { unsigned long x; @@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector) struct genapic apic_x2apic_uv_x = { .name = "UV large system", + .acpi_madt_oem_check = uv_acpi_madt_oem_check, .int_delivery_mode = dest_Fixed, .int_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = uv_target_cpus, @@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void) if (get_uv_system_type() == UV_NON_UNIQUE_APIC) set_x2apic_extra_bits(uv_hub_info->pnode); } + + diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 2871b3fccb2..1e832e49f54 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -14,6 +14,7 @@ struct genapic { char *name; + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); u32 int_delivery_mode; u32 int_dest_mode; int (*apic_id_registered)(void); -- GitLab From 026e2c05ef58ef413e2d52696f125d5ea1aa8bce Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 22 Jul 2008 11:58:14 +0200 Subject: [PATCH 0058/5416] x86, cyrix: debug Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/cyrix.c | 20 ++++++++++---------- include/asm-x86/processor-cyrix.h | 8 ++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 3fd7a67bb06..db5868cd244 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -116,7 +116,7 @@ static void __cpuinit set_cx86_reorder(void) setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* Load/Store Serialize to mem access disable (=reorder it) */ - setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80); + setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) & ~0x80); /* set load/store serialize from 1GB to 4GB */ ccr3 |= 0xe0; setCx86(CX86_CCR3, ccr3); @@ -127,11 +127,11 @@ static void __cpuinit set_cx86_memwb(void) printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); /* CCR2 bit 2: unlock NW bit */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) & ~0x04); /* set 'Not Write-through' */ write_cr0(read_cr0() | X86_CR0_NW); /* CCR2 bit 2: lock NW bit and set WT1 */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x14); } static void __cpuinit set_cx86_inc(void) @@ -144,10 +144,10 @@ static void __cpuinit set_cx86_inc(void) setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* PCR1 -- Performance Control */ /* Incrementor on, whatever that is */ - setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02); + setCx86_old(CX86_PCR1, getCx86_old(CX86_PCR1) | 0x02); /* PCR0 -- Performance Control */ /* Incrementor Margin 10 */ - setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); + setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) | 0x04); setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ } @@ -162,14 +162,14 @@ static void __cpuinit geode_configure(void) local_irq_save(flags); /* Suspend on halt power saving and enable #SUSP pin */ - setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88); + setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x88); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ /* FPU fast, DTE cache, Mem bypass */ - setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38); + setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x38); setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ set_cx86_memwb(); @@ -286,7 +286,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { /* Enable cxMMX extensions (GX1 Datasheet 54) */ - setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1); + setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7) | 1); /* * GXm : 0x30 ... 0x5f GXm datasheet 51 @@ -309,7 +309,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) if (dir1 > 7) { dir0_msn++; /* M II */ /* Enable MMX extensions (App note 108) */ - setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1); + setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7)|1); } else { c->coma_bug = 1; /* 6x86MX, it has the bug. */ } @@ -424,7 +424,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ - setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80); /* enable cpuid */ + setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x80); /* enable cpuid */ setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ local_irq_restore(flags); } diff --git a/include/asm-x86/processor-cyrix.h b/include/asm-x86/processor-cyrix.h index 97568ada1f9..1198f2a0e42 100644 --- a/include/asm-x86/processor-cyrix.h +++ b/include/asm-x86/processor-cyrix.h @@ -28,3 +28,11 @@ static inline void setCx86(u8 reg, u8 data) outb(reg, 0x22); outb(data, 0x23); } + +#define getCx86_old(reg) ({ outb((reg), 0x22); inb(0x23); }) + +#define setCx86_old(reg, data) do { \ + outb((reg), 0x22); \ + outb((data), 0x23); \ +} while (0) + -- GitLab From bbc1f698a508927d21324b57500e863f9bd562b9 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:34:13 +0530 Subject: [PATCH 0059/5416] x86: Introducing asm/syscalls.h Declaring arch-dependent syscalls for x86 architecture Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ioport.c | 1 + arch/x86/kernel/ldt.c | 1 + arch/x86/kernel/process_32.c | 1 + arch/x86/kernel/process_64.c | 1 + arch/x86/kernel/signal_32.c | 1 + arch/x86/kernel/signal_64.c | 1 + arch/x86/kernel/sys_i386_32.c | 2 + arch/x86/kernel/sys_x86_64.c | 1 + arch/x86/kernel/tls.c | 1 + arch/x86/kernel/vm86_32.c | 1 + include/asm-x86/syscalls.h | 90 +++++++++++++++++++++++++++++++++++ 11 files changed, 101 insertions(+) create mode 100644 include/asm-x86/syscalls.h diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 50e5e4a31c8..19191430274 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, unsigned int base, diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index a8449571858..c49ff2dc8f8 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP static void flush_ldt(void *current_mm) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 0c3927accb0..6490e498126 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -55,6 +55,7 @@ #include #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e8a8e1b9981..c78090dd0c5 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -51,6 +51,7 @@ #include #include #include +#include asmlinkage extern void ret_from_fork(void); diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 07faaa5109c..5cede1045ce 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sigframe.h" diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index bf87684474f..b95a0a60905 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sigframe.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 7066cb855a6..1884a8d12bf 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -22,6 +22,8 @@ #include #include +#include + asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 3b360ef3381..c9288c883e2 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -16,6 +16,7 @@ #include #include +#include asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index ab6bf375a30..6bb7b8579e7 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "tls.h" diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 38f566fa27d..4eeb5cf9720 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -46,6 +46,7 @@ #include #include #include +#include /* * Known problems: diff --git a/include/asm-x86/syscalls.h b/include/asm-x86/syscalls.h new file mode 100644 index 00000000000..170fcb132f5 --- /dev/null +++ b/include/asm-x86/syscalls.h @@ -0,0 +1,90 @@ +/* + * syscalls.h - Linux syscall interfaces (arch-specific) + * + * Copyright (c) 2008 Jaswinder Singh + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + * + * Please do not call me directly, include linux/syscalls.h + */ + +#ifndef _ASM_X86_SYSCALLS_H +#define _ASM_X86_SYSCALLS_H + +#include +#include +#include +#include + +/* Common in X86_32 and X86_64 */ +/* kernel/ioport.c */ +asmlinkage long sys_ioperm(unsigned long, unsigned long, int); + +/* X86_32 only */ +#ifdef CONFIG_X86_32 +/* kernel/process_32.c */ +asmlinkage int sys_fork(struct pt_regs); +asmlinkage int sys_clone(struct pt_regs); +asmlinkage int sys_vfork(struct pt_regs); +asmlinkage int sys_execve(struct pt_regs); + +/* kernel/signal_32.c */ +asmlinkage int sys_sigsuspend(int, int, old_sigset_t); +asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, + struct old_sigaction __user *); +asmlinkage int sys_sigaltstack(unsigned long); +asmlinkage unsigned long sys_sigreturn(unsigned long); +asmlinkage int sys_rt_sigreturn(unsigned long); + +/* kernel/ioport.c */ +asmlinkage long sys_iopl(unsigned long); + +/* kernel/ldt.c */ +asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); + +/* kernel/sys_i386_32.c */ +asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long); +struct mmap_arg_struct; +asmlinkage int old_mmap(struct mmap_arg_struct __user *); +struct sel_arg_struct; +asmlinkage int old_select(struct sel_arg_struct __user *); +asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); +struct old_utsname; +asmlinkage int sys_uname(struct old_utsname __user *); +struct oldold_utsname; +asmlinkage int sys_olduname(struct oldold_utsname __user *); + +/* kernel/tls.c */ +asmlinkage int sys_set_thread_area(struct user_desc __user *); +asmlinkage int sys_get_thread_area(struct user_desc __user *); + +#else /* CONFIG_X86_32 */ + +/* X86_64 only */ +/* kernel/process_64.c */ +asmlinkage long sys_fork(struct pt_regs *); +asmlinkage long sys_clone(unsigned long, unsigned long, + void __user *, void __user *, + struct pt_regs *); +asmlinkage long sys_vfork(struct pt_regs *); +asmlinkage long sys_execve(char __user *, char __user * __user *, + char __user * __user *, + struct pt_regs *); + +/* kernel/ioport.c */ +asmlinkage long sys_iopl(unsigned int, struct pt_regs *); + +/* kernel/signal_64.c */ +asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, + struct pt_regs *); +asmlinkage long sys_rt_sigreturn(struct pt_regs *); + +/* kernel/sys_x86_64.c */ +asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long); +asmlinkage long sys_uname(struct new_utsname __user *); + +#endif /* CONFIG_X86_32 */ +#endif /* _ASM_X86_SYSCALLS_H */ -- GitLab From fb26132b441e75d6ba9996efc29b42081aee0abd Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:36:40 +0530 Subject: [PATCH 0060/5416] x86: process_32.c declare cpu_number before they get used Moved DECLARE_PER_CPU(int, cpu_number) from CONFIG_X86_32_SMP to CONFIG_X86_32 because cpu_number is required for both. And include asm/smp.h in process_32.c Signed-off-by: Jaswinder Singh --- arch/x86/kernel/process_32.c | 1 + include/asm-x86/smp.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 6490e498126..7218bccd176 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -56,6 +56,7 @@ #include #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 3c877f74f27..3a1480648f6 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -34,6 +34,9 @@ extern cpumask_t cpu_initialized; DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); DECLARE_PER_CPU(cpumask_t, cpu_core_map); DECLARE_PER_CPU(u16, cpu_llc_id); +#ifdef CONFIG_X86_32 +DECLARE_PER_CPU(int, cpu_number); +#endif DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); @@ -142,7 +145,6 @@ extern unsigned disabled_cpus __cpuinitdata; * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ -DECLARE_PER_CPU(int, cpu_number); #define raw_smp_processor_id() (x86_read_percpu(cpu_number)) extern int safe_smp_processor_id(void); -- GitLab From b994b6c0332a5499b33880855dadad04d74cde54 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:37:52 +0530 Subject: [PATCH 0061/5416] x86: signal_XX.c declare do_notify_resume before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/signal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h index 6dac49364e9..5e4a1b0d8dc 100644 --- a/include/asm-x86/signal.h +++ b/include/asm-x86/signal.h @@ -140,6 +140,9 @@ struct sigaction { struct k_sigaction { struct sigaction sa; }; + +extern void do_notify_resume(struct pt_regs *, void *, __u32); + # else /* __KERNEL__ */ /* Here we must cater to libcs that poke about in kernel headers. */ -- GitLab From cc0384917bf69079088701a0725c5fc6b554bf35 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 21:52:51 +0530 Subject: [PATCH 0062/5416] x86: time_XX.c declare functions before they get used Declare time_init() in asm-x86/time.h Also did cleanup in asm-x86/timer.h : timer_ack is only required for X86_32 int recalibrate_cpu_khz(void) is for X86_32 Signed-off-by: Jaswinder Singh --- arch/x86/kernel/time_32.c | 1 + include/asm-x86/time.h | 2 ++ include/asm-x86/timer.h | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index ffe3c664afc..bbecf8b6bf9 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "do_timer.h" diff --git a/include/asm-x86/time.h b/include/asm-x86/time.h index a17fa473e91..5f4fc3e0238 100644 --- a/include/asm-x86/time.h +++ b/include/asm-x86/time.h @@ -46,6 +46,8 @@ static inline int native_set_wallclock(unsigned long nowtime) #endif +extern void time_init(void); + #ifdef CONFIG_PARAVIRT #include #else /* !CONFIG_PARAVIRT */ diff --git a/include/asm-x86/timer.h b/include/asm-x86/timer.h index fb2a4ddddf3..2a8a92d5787 100644 --- a/include/asm-x86/timer.h +++ b/include/asm-x86/timer.h @@ -9,9 +9,12 @@ unsigned long long native_sched_clock(void); unsigned long native_calibrate_tsc(void); +#ifdef CONFIG_X86_32 extern int timer_ack; -extern int no_timer_check; extern int recalibrate_cpu_khz(void); +#endif /* CONFIG_X86_32 */ + +extern int no_timer_check; #ifndef CONFIG_PARAVIRT #define calibrate_tsc() native_calibrate_tsc() -- GitLab From 5314d48ed54c1a0111c597d1510f77850a1b3232 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:12:23 +0530 Subject: [PATCH 0063/5416] x86: setup.c declare saved_video_mode before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/setup.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h index a07c6f1c01e..946f8f20e91 100644 --- a/include/asm-x86/setup.h +++ b/include/asm-x86/setup.h @@ -41,6 +41,7 @@ struct x86_quirks { }; extern struct x86_quirks *x86_quirks; +extern unsigned long saved_video_mode; #ifndef CONFIG_PARAVIRT #define paravirt_post_allocator_init() do {} while (0) -- GitLab From a7b7511ac1404eaf0e7b6c445a7c61b48ccfcf0b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:19:29 +0530 Subject: [PATCH 0064/5416] x86: e820.c declare pci_mem_start before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/e820.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index 16a31e2c7c5..213d1ed3d41 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h @@ -64,6 +64,7 @@ struct e820map { extern struct e820map e820; extern struct e820map e820_saved; +extern unsigned long pci_mem_start; extern int e820_any_mapped(u64 start, u64 end, unsigned type); extern int e820_all_mapped(u64 start, u64 end, unsigned type); extern void e820_add_region(u64 start, u64 size, int type); -- GitLab From 9321b8cbbbf3a8dbd4748e3722facaeb8401bd13 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:24:29 +0530 Subject: [PATCH 0065/5416] x86: pci-dma.c declare iommu_bio_merge before they get used moved iommu_bio_merge from io_64.h to io.h because it is required for both. Signed-off-by: Jaswinder Singh --- include/asm-x86/io.h | 2 ++ include/asm-x86/io_64.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h index bf5d629b3a3..a145210ac16 100644 --- a/include/asm-x86/io.h +++ b/include/asm-x86/io.h @@ -73,6 +73,8 @@ build_mmio_write(__writeq, "q", unsigned long, "r", ) #define writeq writeq #endif +extern int iommu_bio_merge; + #ifdef CONFIG_X86_32 # include "io_32.h" #else diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index ddd8058a502..1e271378afa 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -233,7 +233,6 @@ void memset_io(volatile void __iomem *a, int b, size_t c); #define flush_write_buffers() -extern int iommu_bio_merge; #define BIO_VMERGE_BOUNDARY iommu_bio_merge /* -- GitLab From 791b897ccd1a2c6c184b88ca6d1aaf053499c3df Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:28:22 +0530 Subject: [PATCH 0066/5416] x86: pci-nommu.c declare nommu_dma_ops before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/dma-mapping.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index c2ddd3d1b88..f14b04d8bae 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h @@ -57,6 +57,7 @@ struct dma_mapping_ops { }; extern const struct dma_mapping_ops *dma_ops; +extern const struct dma_mapping_ops nommu_dma_ops; static inline int dma_mapping_error(dma_addr_t dma_addr) { -- GitLab From 36454936c00c700ae86b5ff376d3c1c1a862c4f5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:31:57 +0530 Subject: [PATCH 0067/5416] x86: i387.c declare dump_fpu() before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/i387.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 37672f79dcc..48789892383 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -24,6 +24,7 @@ extern void mxcsr_feature_mask_init(void); extern int init_fpu(struct task_struct *child); extern asmlinkage void math_state_restore(void); extern void init_thread_xstate(void); +extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); extern user_regset_active_fn fpregs_active, xfpregs_active; extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; -- GitLab From c1686aeaf0780055ffcd4b224b73d5ada77630e8 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:35:38 +0530 Subject: [PATCH 0068/5416] x86: ptrace.c declare functions before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/ptrace.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 8a71db803da..48c1d5a890d 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -148,6 +148,9 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, void signal_fault(struct pt_regs *regs, void __user *frame, char *where); #endif +extern long syscall_trace_enter(struct pt_regs *); +extern void syscall_trace_leave(struct pt_regs *); + static inline unsigned long regs_return_value(struct pt_regs *regs) { return regs->ax; -- GitLab From 1c6c727d9c12c84a612abe31b60948f06fc2ab2d Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:40:37 +0530 Subject: [PATCH 0069/5416] x86: proc.c declare cpuinfo_op before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/processor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 15cb82a44e8..93b6adc72ad 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -140,6 +140,8 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info); #define current_cpu_data boot_cpu_data #endif +extern const struct seq_operations cpuinfo_op; + static inline int hlt_works(int cpu) { #ifdef CONFIG_X86_32 -- GitLab From 8fd329a1ac696973ba5467c510302ae1248cc11a Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:54:56 +0530 Subject: [PATCH 0070/5416] x86: common.c declare idle_regs before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/processor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 93b6adc72ad..a2fb5a43641 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -155,6 +155,8 @@ static inline int hlt_works(int cpu) extern void cpu_detect(struct cpuinfo_x86 *c); +extern struct pt_regs *idle_regs(struct pt_regs *); + extern void early_cpu_init(void); extern void identify_boot_cpu(void); extern void identify_secondary_cpu(struct cpuinfo_x86 *); -- GitLab From 1e84911c6c37fd1080ef07039e19c346628b31db Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 21 Jul 2008 22:58:29 +0530 Subject: [PATCH 0071/5416] x86: mtrr/main.c declare range_state as static Signed-off-by: Jaswinder Singh --- arch/x86/kernel/cpu/mtrr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 6f23969c8fa..b5ade28ca8f 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -729,7 +729,7 @@ struct var_mtrr_range_state { mtrr_type type; }; -struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; +static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; static int __initdata debug_print; static int __init -- GitLab From df1be4372eae5f104b7fb4991bc4b35f00b11a11 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 22 Jul 2008 10:13:11 -0400 Subject: [PATCH 0072/5416] x64, apic: use generic apic_write() for ack_APIC_irq() I tested tip/master and found an issue (patch attached) for x2apic support. This is not because of the recent merges we had, but because of something(where we still access memory based interface after enabling x2apic mode) that slipped through my earlier tests. Probably it is a good idea to unmap the memory mapped interface, once we switch to x2apic mode. That will catch the issues much earlier. I will post another patch for this. ack_APIC_irq() is used at too many generic places (and not just during irq_chip handling!) to use the native_apic_mem_write(). For ex, this will break x2apic based systems. Fix ack_APIC_irq() to use the generic apic_write() even for 64-bit. Signed-off-by: Suresh Siddha Cc: suresh.b.siddha@intel.com Cc: yong.y.wang@linux.intel.com Signed-off-by: Ingo Molnar --- include/asm-x86/apic.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 51339910fdc..502ca6594b1 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -136,11 +136,7 @@ static inline void ack_APIC_irq(void) */ /* Docs say use 0 for future compatibility */ -#ifdef CONFIG_X86_32 apic_write(APIC_EOI, 0); -#else - native_apic_mem_write(APIC_EOI, 0); -#endif } extern int lapic_get_maxlvt(void); -- GitLab From a656c8efb40a8700046df20da2195f8aa39ce38a Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 22 Jul 2008 21:27:11 +0200 Subject: [PATCH 0073/5416] x86: fix spurious '#' in kvm header Signed-off-by: Vegard Nossum --- include/asm-x86/kvm_host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index fdde0bedaa9..924e1bfe3a6 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -1,4 +1,4 @@ -#/* +/* * Kernel-based Virtual Machine driver for Linux * * This header defines architecture specific interfaces, x86 version -- GitLab From 77ef50a522717fa040636ee1017179ceba12ff62 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 18 Jun 2008 17:08:48 +0200 Subject: [PATCH 0074/5416] x86: consolidate header guards This patch is the result of an automatic script that consolidates the format of all the headers in include/asm-x86/. The format: 1. No leading underscore. Names with leading underscores are reserved. 2. Pathname components are separated by two underscores. So we can distinguish between mm_types.h and mm/types.h. 3. Everything except letters and numbers are turned into single underscores. Signed-off-by: Vegard Nossum --- include/asm-x86/a.out-core.h | 6 +++--- include/asm-x86/a.out.h | 6 +++--- include/asm-x86/acpi.h | 6 +++--- include/asm-x86/agp.h | 6 +++--- include/asm-x86/alternative.h | 6 +++--- include/asm-x86/amd_iommu.h | 6 +++--- include/asm-x86/amd_iommu_types.h | 6 +++--- include/asm-x86/apic.h | 6 +++--- include/asm-x86/apicdef.h | 6 +++--- include/asm-x86/arch_hooks.h | 6 +++--- include/asm-x86/asm.h | 6 +++--- include/asm-x86/atomic_32.h | 6 +++--- include/asm-x86/atomic_64.h | 6 +++--- include/asm-x86/auxvec.h | 6 +++--- include/asm-x86/bios_ebda.h | 6 +++--- include/asm-x86/bitops.h | 6 +++--- include/asm-x86/boot.h | 6 +++--- include/asm-x86/bootparam.h | 6 +++--- include/asm-x86/bug.h | 6 +++--- include/asm-x86/bugs.h | 6 +++--- include/asm-x86/byteorder.h | 6 +++--- include/asm-x86/cache.h | 6 +++--- include/asm-x86/cacheflush.h | 6 +++--- include/asm-x86/calgary.h | 6 +++--- include/asm-x86/checksum_32.h | 6 +++--- include/asm-x86/checksum_64.h | 6 +++--- include/asm-x86/cmpxchg_32.h | 6 +++--- include/asm-x86/cmpxchg_64.h | 6 +++--- include/asm-x86/compat.h | 6 +++--- include/asm-x86/cpu.h | 6 +++--- include/asm-x86/cpufeature.h | 6 +++--- include/asm-x86/current.h | 6 +++--- include/asm-x86/debugreg.h | 6 +++--- include/asm-x86/delay.h | 6 +++--- include/asm-x86/desc_defs.h | 6 +++--- include/asm-x86/device.h | 6 +++--- include/asm-x86/div64.h | 6 +++--- include/asm-x86/dma-mapping.h | 6 +++--- include/asm-x86/dma.h | 6 +++--- include/asm-x86/dmi.h | 6 +++--- include/asm-x86/ds.h | 6 +++--- include/asm-x86/dwarf2.h | 6 +++--- include/asm-x86/e820.h | 6 +++--- include/asm-x86/edac.h | 6 +++--- include/asm-x86/efi.h | 6 +++--- include/asm-x86/elf.h | 6 +++--- include/asm-x86/emergency-restart.h | 6 +++--- include/asm-x86/fb.h | 6 +++--- include/asm-x86/fixmap.h | 6 +++--- include/asm-x86/fixmap_32.h | 6 +++--- include/asm-x86/fixmap_64.h | 6 +++--- include/asm-x86/floppy.h | 6 +++--- include/asm-x86/ftrace.h | 6 +++--- include/asm-x86/futex.h | 6 +++--- include/asm-x86/gart.h | 6 +++--- include/asm-x86/genapic_32.h | 6 +++--- include/asm-x86/genapic_64.h | 6 +++--- include/asm-x86/geode.h | 6 +++--- include/asm-x86/gpio.h | 6 +++--- include/asm-x86/hardirq_32.h | 6 +++--- include/asm-x86/hardirq_64.h | 6 +++--- include/asm-x86/highmem.h | 6 +++--- include/asm-x86/hpet.h | 6 +++--- include/asm-x86/hugetlb.h | 6 +++--- include/asm-x86/hw_irq.h | 6 +++--- include/asm-x86/hypertransport.h | 6 +++--- include/asm-x86/i387.h | 6 +++--- include/asm-x86/i8253.h | 6 +++--- include/asm-x86/i8259.h | 6 +++--- include/asm-x86/ia32.h | 6 +++--- include/asm-x86/ia32_unistd.h | 6 +++--- include/asm-x86/ide.h | 6 +++--- include/asm-x86/idle.h | 6 +++--- include/asm-x86/intel_arch_perfmon.h | 6 +++--- include/asm-x86/io.h | 6 +++--- include/asm-x86/io_32.h | 6 +++--- include/asm-x86/io_64.h | 6 +++--- include/asm-x86/io_apic.h | 6 +++--- include/asm-x86/ioctls.h | 6 +++--- include/asm-x86/iommu.h | 6 +++--- include/asm-x86/ipcbuf.h | 6 +++--- include/asm-x86/ipi.h | 6 +++--- include/asm-x86/irq.h | 6 +++--- include/asm-x86/irq_regs_32.h | 6 +++--- include/asm-x86/irq_vectors.h | 6 +++--- include/asm-x86/ist.h | 6 +++--- include/asm-x86/k8.h | 6 +++--- include/asm-x86/kdebug.h | 6 +++--- include/asm-x86/kexec.h | 6 +++--- include/asm-x86/kgdb.h | 6 +++--- include/asm-x86/kmap_types.h | 6 +++--- include/asm-x86/kprobes.h | 6 +++--- include/asm-x86/kvm.h | 6 +++--- include/asm-x86/kvm_host.h | 6 +++--- include/asm-x86/kvm_para.h | 6 +++--- include/asm-x86/kvm_x86_emulate.h | 6 +++--- include/asm-x86/ldt.h | 6 +++--- include/asm-x86/lguest.h | 6 +++--- include/asm-x86/lguest_hcall.h | 6 +++--- include/asm-x86/linkage.h | 6 +++--- include/asm-x86/local.h | 6 +++--- include/asm-x86/mach-bigsmp/mach_apic.h | 6 +++--- include/asm-x86/mach-bigsmp/mach_apicdef.h | 6 +++--- include/asm-x86/mach-bigsmp/mach_ipi.h | 6 +++--- include/asm-x86/mach-default/apm.h | 6 +++--- include/asm-x86/mach-default/mach_apic.h | 6 +++--- include/asm-x86/mach-default/mach_apicdef.h | 6 +++--- include/asm-x86/mach-default/mach_ipi.h | 6 +++--- include/asm-x86/mach-default/mach_mpparse.h | 6 +++--- include/asm-x86/mach-default/mach_mpspec.h | 6 +++--- include/asm-x86/mach-default/mach_timer.h | 6 +++--- include/asm-x86/mach-default/mach_traps.h | 6 +++--- include/asm-x86/mach-default/mach_wakecpu.h | 6 +++--- include/asm-x86/mach-es7000/mach_apic.h | 6 +++--- include/asm-x86/mach-es7000/mach_apicdef.h | 6 +++--- include/asm-x86/mach-es7000/mach_ipi.h | 6 +++--- include/asm-x86/mach-es7000/mach_mpparse.h | 6 +++--- include/asm-x86/mach-es7000/mach_wakecpu.h | 6 +++--- include/asm-x86/mach-generic/gpio.h | 6 +++--- include/asm-x86/mach-generic/irq_vectors_limits.h | 6 +++--- include/asm-x86/mach-generic/mach_apic.h | 6 +++--- include/asm-x86/mach-generic/mach_apicdef.h | 6 +++--- include/asm-x86/mach-generic/mach_ipi.h | 6 +++--- include/asm-x86/mach-generic/mach_mpparse.h | 6 +++--- include/asm-x86/mach-generic/mach_mpspec.h | 6 +++--- include/asm-x86/mach-numaq/mach_apic.h | 6 +++--- include/asm-x86/mach-numaq/mach_apicdef.h | 6 +++--- include/asm-x86/mach-numaq/mach_ipi.h | 6 +++--- include/asm-x86/mach-numaq/mach_mpparse.h | 6 +++--- include/asm-x86/mach-numaq/mach_wakecpu.h | 6 +++--- include/asm-x86/mach-rdc321x/gpio.h | 6 +++--- include/asm-x86/mach-summit/irq_vectors_limits.h | 6 +++--- include/asm-x86/mach-summit/mach_apic.h | 6 +++--- include/asm-x86/mach-summit/mach_apicdef.h | 6 +++--- include/asm-x86/mach-summit/mach_ipi.h | 6 +++--- include/asm-x86/mach-summit/mach_mpparse.h | 6 +++--- include/asm-x86/math_emu.h | 6 +++--- include/asm-x86/mc146818rtc.h | 6 +++--- include/asm-x86/mca.h | 6 +++--- include/asm-x86/mca_dma.h | 6 +++--- include/asm-x86/mce.h | 6 +++--- include/asm-x86/mman.h | 6 +++--- include/asm-x86/mmconfig.h | 6 +++--- include/asm-x86/mmu.h | 6 +++--- include/asm-x86/mmu_context.h | 6 +++--- include/asm-x86/mmu_context_32.h | 6 +++--- include/asm-x86/mmu_context_64.h | 6 +++--- include/asm-x86/mmx.h | 6 +++--- include/asm-x86/mmzone_32.h | 6 +++--- include/asm-x86/mmzone_64.h | 6 +++--- include/asm-x86/module.h | 6 +++--- include/asm-x86/mpspec.h | 6 +++--- include/asm-x86/mpspec_def.h | 6 +++--- include/asm-x86/msgbuf.h | 6 +++--- include/asm-x86/msidef.h | 6 +++--- include/asm-x86/msr-index.h | 6 +++--- include/asm-x86/msr.h | 6 +++--- include/asm-x86/mtrr.h | 6 +++--- include/asm-x86/mutex_32.h | 6 +++--- include/asm-x86/mutex_64.h | 6 +++--- include/asm-x86/namei.h | 6 +++--- include/asm-x86/nmi.h | 6 +++--- include/asm-x86/nops.h | 6 +++--- include/asm-x86/numa_32.h | 6 +++--- include/asm-x86/numa_64.h | 6 +++--- include/asm-x86/numaq.h | 6 +++--- include/asm-x86/olpc.h | 6 +++--- include/asm-x86/page.h | 6 +++--- include/asm-x86/page_32.h | 6 +++--- include/asm-x86/page_64.h | 6 +++--- include/asm-x86/param.h | 6 +++--- include/asm-x86/paravirt.h | 6 +++--- include/asm-x86/parport.h | 6 +++--- include/asm-x86/pat.h | 6 +++--- include/asm-x86/pci-direct.h | 6 +++--- include/asm-x86/pci.h | 6 +++--- include/asm-x86/pci_32.h | 6 +++--- include/asm-x86/pci_64.h | 6 +++--- include/asm-x86/pda.h | 6 +++--- include/asm-x86/percpu.h | 6 +++--- include/asm-x86/pgalloc.h | 6 +++--- include/asm-x86/pgtable-2level-defs.h | 6 +++--- include/asm-x86/pgtable-2level.h | 6 +++--- include/asm-x86/pgtable-3level-defs.h | 6 +++--- include/asm-x86/pgtable-3level.h | 6 +++--- include/asm-x86/pgtable.h | 6 +++--- include/asm-x86/pgtable_32.h | 6 +++--- include/asm-x86/pgtable_64.h | 6 +++--- include/asm-x86/posix_types_32.h | 6 +++--- include/asm-x86/posix_types_64.h | 6 +++--- include/asm-x86/prctl.h | 6 +++--- include/asm-x86/processor-flags.h | 6 +++--- include/asm-x86/processor.h | 6 +++--- include/asm-x86/proto.h | 6 +++--- include/asm-x86/ptrace-abi.h | 6 +++--- include/asm-x86/ptrace.h | 6 +++--- include/asm-x86/pvclock-abi.h | 6 +++--- include/asm-x86/pvclock.h | 6 +++--- include/asm-x86/reboot.h | 6 +++--- include/asm-x86/reboot_fixups.h | 6 +++--- include/asm-x86/required-features.h | 6 +++--- include/asm-x86/resume-trace.h | 6 +++--- include/asm-x86/rio.h | 6 +++--- include/asm-x86/rwlock.h | 6 +++--- include/asm-x86/rwsem.h | 6 +++--- include/asm-x86/scatterlist.h | 6 +++--- include/asm-x86/seccomp_32.h | 6 +++--- include/asm-x86/seccomp_64.h | 6 +++--- include/asm-x86/segment.h | 6 +++--- include/asm-x86/sembuf.h | 6 +++--- include/asm-x86/serial.h | 6 +++--- include/asm-x86/setup.h | 6 +++--- include/asm-x86/shmbuf.h | 6 +++--- include/asm-x86/shmparam.h | 6 +++--- include/asm-x86/sigcontext.h | 6 +++--- include/asm-x86/sigcontext32.h | 6 +++--- include/asm-x86/siginfo.h | 6 +++--- include/asm-x86/signal.h | 6 +++--- include/asm-x86/smp.h | 6 +++--- include/asm-x86/socket.h | 6 +++--- include/asm-x86/sockios.h | 6 +++--- include/asm-x86/sparsemem.h | 6 +++--- include/asm-x86/spinlock.h | 6 +++--- include/asm-x86/spinlock_types.h | 6 +++--- include/asm-x86/srat.h | 6 +++--- include/asm-x86/stacktrace.h | 6 +++--- include/asm-x86/stat.h | 6 +++--- include/asm-x86/statfs.h | 6 +++--- include/asm-x86/string_32.h | 6 +++--- include/asm-x86/string_64.h | 6 +++--- include/asm-x86/suspend_32.h | 6 +++--- include/asm-x86/suspend_64.h | 6 +++--- include/asm-x86/swiotlb.h | 6 +++--- include/asm-x86/sync_bitops.h | 6 +++--- include/asm-x86/system.h | 6 +++--- include/asm-x86/system_64.h | 6 +++--- include/asm-x86/tce.h | 6 +++--- include/asm-x86/termbits.h | 6 +++--- include/asm-x86/termios.h | 6 +++--- include/asm-x86/therm_throt.h | 6 +++--- include/asm-x86/thread_info.h | 6 +++--- include/asm-x86/time.h | 6 +++--- include/asm-x86/timer.h | 6 +++--- include/asm-x86/timex.h | 6 +++--- include/asm-x86/tlb.h | 6 +++--- include/asm-x86/tlbflush.h | 6 +++--- include/asm-x86/topology.h | 6 +++--- include/asm-x86/trampoline.h | 6 +++--- include/asm-x86/traps.h | 6 +++--- include/asm-x86/tsc.h | 6 +++--- include/asm-x86/types.h | 6 +++--- include/asm-x86/uaccess.h | 6 +++--- include/asm-x86/uaccess_32.h | 6 +++--- include/asm-x86/uaccess_64.h | 6 +++--- include/asm-x86/ucontext.h | 6 +++--- include/asm-x86/unaligned.h | 6 +++--- include/asm-x86/unistd_32.h | 6 +++--- include/asm-x86/unwind.h | 6 +++--- include/asm-x86/user32.h | 6 +++--- include/asm-x86/user_32.h | 6 +++--- include/asm-x86/user_64.h | 6 +++--- include/asm-x86/uv/bios.h | 6 +++--- include/asm-x86/uv/uv_bau.h | 6 +++--- include/asm-x86/uv/uv_hub.h | 6 +++--- include/asm-x86/uv/uv_mmrs.h | 6 +++--- include/asm-x86/vdso.h | 6 +++--- include/asm-x86/vga.h | 6 +++--- include/asm-x86/vgtod.h | 6 +++--- include/asm-x86/visws/cobalt.h | 6 +++--- include/asm-x86/visws/lithium.h | 6 +++--- include/asm-x86/visws/piix4.h | 6 +++--- include/asm-x86/vm86.h | 6 +++--- include/asm-x86/vmi_time.h | 6 +++--- include/asm-x86/vsyscall.h | 6 +++--- include/asm-x86/xen/events.h | 6 +++--- include/asm-x86/xen/grant_table.h | 6 +++--- include/asm-x86/xen/hypercall.h | 6 +++--- include/asm-x86/xen/hypervisor.h | 6 +++--- include/asm-x86/xen/interface.h | 6 +++--- include/asm-x86/xen/interface_32.h | 6 +++--- include/asm-x86/xen/interface_64.h | 6 +++--- include/asm-x86/xen/page.h | 6 +++--- 282 files changed, 846 insertions(+), 846 deletions(-) diff --git a/include/asm-x86/a.out-core.h b/include/asm-x86/a.out-core.h index 714207a1c38..f5705761a37 100644 --- a/include/asm-x86/a.out-core.h +++ b/include/asm-x86/a.out-core.h @@ -9,8 +9,8 @@ * 2 of the Licence, or (at your option) any later version. */ -#ifndef _ASM_A_OUT_CORE_H -#define _ASM_A_OUT_CORE_H +#ifndef ASM_X86__A_OUT_CORE_H +#define ASM_X86__A_OUT_CORE_H #ifdef __KERNEL__ #ifdef CONFIG_X86_32 @@ -70,4 +70,4 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) #endif /* CONFIG_X86_32 */ #endif /* __KERNEL__ */ -#endif /* _ASM_A_OUT_CORE_H */ +#endif /* ASM_X86__A_OUT_CORE_H */ diff --git a/include/asm-x86/a.out.h b/include/asm-x86/a.out.h index 4684f97a5bb..0948748bc69 100644 --- a/include/asm-x86/a.out.h +++ b/include/asm-x86/a.out.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_A_OUT_H -#define _ASM_X86_A_OUT_H +#ifndef ASM_X86__A_OUT_H +#define ASM_X86__A_OUT_H struct exec { @@ -17,4 +17,4 @@ struct exec #define N_DRSIZE(a) ((a).a_drsize) #define N_SYMSIZE(a) ((a).a_syms) -#endif /* _ASM_X86_A_OUT_H */ +#endif /* ASM_X86__A_OUT_H */ diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h index 635d764dc13..bd76299586b 100644 --- a/include/asm-x86/acpi.h +++ b/include/asm-x86/acpi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ACPI_H -#define _ASM_X86_ACPI_H +#ifndef ASM_X86__ACPI_H +#define ASM_X86__ACPI_H /* * Copyright (C) 2001 Paul Diefenbaugh @@ -173,4 +173,4 @@ static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, #define acpi_unlazy_tlb(x) leave_mm(x) -#endif /*__X86_ASM_ACPI_H*/ +#endif /* ASM_X86__ACPI_H */ diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index e4004a9f6a9..3617fd4fcdf 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_AGP_H -#define _ASM_X86_AGP_H +#ifndef ASM_X86__AGP_H +#define ASM_X86__AGP_H #include #include @@ -32,4 +32,4 @@ #define free_gatt_pages(table, order) \ free_pages((unsigned long)(table), (order)) -#endif +#endif /* ASM_X86__AGP_H */ diff --git a/include/asm-x86/alternative.h b/include/asm-x86/alternative.h index f6aa18eadf7..22d3c9862bf 100644 --- a/include/asm-x86/alternative.h +++ b/include/asm-x86/alternative.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ALTERNATIVE_H -#define _ASM_X86_ALTERNATIVE_H +#ifndef ASM_X86__ALTERNATIVE_H +#define ASM_X86__ALTERNATIVE_H #include #include @@ -180,4 +180,4 @@ extern void add_nops(void *insns, unsigned int len); extern void *text_poke(void *addr, const void *opcode, size_t len); extern void *text_poke_early(void *addr, const void *opcode, size_t len); -#endif /* _ASM_X86_ALTERNATIVE_H */ +#endif /* ASM_X86__ALTERNATIVE_H */ diff --git a/include/asm-x86/amd_iommu.h b/include/asm-x86/amd_iommu.h index 30a12049353..783f43e5805 100644 --- a/include/asm-x86/amd_iommu.h +++ b/include/asm-x86/amd_iommu.h @@ -17,8 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_AMD_IOMMU_H -#define _ASM_X86_AMD_IOMMU_H +#ifndef ASM_X86__AMD_IOMMU_H +#define ASM_X86__AMD_IOMMU_H #ifdef CONFIG_AMD_IOMMU extern int amd_iommu_init(void); @@ -29,4 +29,4 @@ static inline int amd_iommu_init(void) { return -ENODEV; } static inline void amd_iommu_detect(void) { } #endif -#endif +#endif /* ASM_X86__AMD_IOMMU_H */ diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index 22aa58ca199..e6b4d5b0837 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -17,8 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __AMD_IOMMU_TYPES_H__ -#define __AMD_IOMMU_TYPES_H__ +#ifndef ASM_X86__AMD_IOMMU_TYPES_H +#define ASM_X86__AMD_IOMMU_TYPES_H #include #include @@ -339,4 +339,4 @@ static inline u16 calc_devid(u8 bus, u8 devfn) return (((u16)bus) << 8) | devfn; } -#endif +#endif /* ASM_X86__AMD_IOMMU_TYPES_H */ diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 133c998161c..d0ace3d63a2 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_APIC_H -#define _ASM_X86_APIC_H +#ifndef ASM_X86__APIC_H +#define ASM_X86__APIC_H #include #include @@ -128,4 +128,4 @@ static inline void init_apic_mappings(void) { } #endif /* !CONFIG_X86_LOCAL_APIC */ -#endif /* __ASM_APIC_H */ +#endif /* ASM_X86__APIC_H */ diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h index 6b9008c7873..c40687da20f 100644 --- a/include/asm-x86/apicdef.h +++ b/include/asm-x86/apicdef.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_APICDEF_H -#define _ASM_X86_APICDEF_H +#ifndef ASM_X86__APICDEF_H +#define ASM_X86__APICDEF_H /* * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) @@ -411,4 +411,4 @@ struct local_apic { #else #define BAD_APICID 0xFFFFu #endif -#endif +#endif /* ASM_X86__APICDEF_H */ diff --git a/include/asm-x86/arch_hooks.h b/include/asm-x86/arch_hooks.h index 8411750ceb6..72adc3a109c 100644 --- a/include/asm-x86/arch_hooks.h +++ b/include/asm-x86/arch_hooks.h @@ -1,5 +1,5 @@ -#ifndef _ASM_ARCH_HOOKS_H -#define _ASM_ARCH_HOOKS_H +#ifndef ASM_X86__ARCH_HOOKS_H +#define ASM_X86__ARCH_HOOKS_H #include @@ -25,4 +25,4 @@ extern void pre_time_init_hook(void); extern void time_init_hook(void); extern void mca_nmi_hook(void); -#endif +#endif /* ASM_X86__ARCH_HOOKS_H */ diff --git a/include/asm-x86/asm.h b/include/asm-x86/asm.h index 97220321f39..2439ae49e8a 100644 --- a/include/asm-x86/asm.h +++ b/include/asm-x86/asm.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ASM_H -#define _ASM_X86_ASM_H +#ifndef ASM_X86__ASM_H +#define ASM_X86__ASM_H #ifdef __ASSEMBLY__ # define __ASM_FORM(x) x @@ -39,4 +39,4 @@ _ASM_PTR #from "," #to "\n" \ " .previous\n" -#endif /* _ASM_X86_ASM_H */ +#endif /* ASM_X86__ASM_H */ diff --git a/include/asm-x86/atomic_32.h b/include/asm-x86/atomic_32.h index 21a4825148c..14d3f0beb88 100644 --- a/include/asm-x86/atomic_32.h +++ b/include/asm-x86/atomic_32.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_I386_ATOMIC__ -#define __ARCH_I386_ATOMIC__ +#ifndef ASM_X86__ATOMIC_32_H +#define ASM_X86__ATOMIC_32_H #include #include @@ -256,4 +256,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define smp_mb__after_atomic_inc() barrier() #include -#endif +#endif /* ASM_X86__ATOMIC_32_H */ diff --git a/include/asm-x86/atomic_64.h b/include/asm-x86/atomic_64.h index a0095191c02..ebbc753af6a 100644 --- a/include/asm-x86/atomic_64.h +++ b/include/asm-x86/atomic_64.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_X86_64_ATOMIC__ -#define __ARCH_X86_64_ATOMIC__ +#ifndef ASM_X86__ATOMIC_64_H +#define ASM_X86__ATOMIC_64_H #include #include @@ -470,4 +470,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2) #define smp_mb__after_atomic_inc() barrier() #include -#endif +#endif /* ASM_X86__ATOMIC_64_H */ diff --git a/include/asm-x86/auxvec.h b/include/asm-x86/auxvec.h index 87f5e6d5a02..12c7cac7420 100644 --- a/include/asm-x86/auxvec.h +++ b/include/asm-x86/auxvec.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_AUXVEC_H -#define _ASM_X86_AUXVEC_H +#ifndef ASM_X86__AUXVEC_H +#define ASM_X86__AUXVEC_H /* * Architecture-neutral AT_ values in 0-17, leave some room * for more of them, start the x86-specific ones at 32. @@ -9,4 +9,4 @@ #endif #define AT_SYSINFO_EHDR 33 -#endif +#endif /* ASM_X86__AUXVEC_H */ diff --git a/include/asm-x86/bios_ebda.h b/include/asm-x86/bios_ebda.h index 0033e50c13b..ec42ed87459 100644 --- a/include/asm-x86/bios_ebda.h +++ b/include/asm-x86/bios_ebda.h @@ -1,5 +1,5 @@ -#ifndef _MACH_BIOS_EBDA_H -#define _MACH_BIOS_EBDA_H +#ifndef ASM_X86__BIOS_EBDA_H +#define ASM_X86__BIOS_EBDA_H #include @@ -16,4 +16,4 @@ static inline unsigned int get_bios_ebda(void) void reserve_ebda_region(void); -#endif /* _MACH_BIOS_EBDA_H */ +#endif /* ASM_X86__BIOS_EBDA_H */ diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h index cfb2b64f76e..61989b93b47 100644 --- a/include/asm-x86/bitops.h +++ b/include/asm-x86/bitops.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BITOPS_H -#define _ASM_X86_BITOPS_H +#ifndef ASM_X86__BITOPS_H +#define ASM_X86__BITOPS_H /* * Copyright 1992, Linus Torvalds. @@ -458,4 +458,4 @@ static inline void set_bit_string(unsigned long *bitmap, #include #endif /* __KERNEL__ */ -#endif /* _ASM_X86_BITOPS_H */ +#endif /* ASM_X86__BITOPS_H */ diff --git a/include/asm-x86/boot.h b/include/asm-x86/boot.h index 2faed7ecb09..825de5dc867 100644 --- a/include/asm-x86/boot.h +++ b/include/asm-x86/boot.h @@ -1,5 +1,5 @@ -#ifndef _ASM_BOOT_H -#define _ASM_BOOT_H +#ifndef ASM_X86__BOOT_H +#define ASM_X86__BOOT_H /* Don't touch these, unless you really know what you're doing. */ #define DEF_INITSEG 0x9000 @@ -25,4 +25,4 @@ #define BOOT_STACK_SIZE 0x1000 #endif -#endif /* _ASM_BOOT_H */ +#endif /* ASM_X86__BOOT_H */ diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h index ae22bdf0ab1..ccf027e2d97 100644 --- a/include/asm-x86/bootparam.h +++ b/include/asm-x86/bootparam.h @@ -1,5 +1,5 @@ -#ifndef _ASM_BOOTPARAM_H -#define _ASM_BOOTPARAM_H +#ifndef ASM_X86__BOOTPARAM_H +#define ASM_X86__BOOTPARAM_H #include #include @@ -108,4 +108,4 @@ struct boot_params { __u8 _pad9[276]; /* 0xeec */ } __attribute__((packed)); -#endif /* _ASM_BOOTPARAM_H */ +#endif /* ASM_X86__BOOTPARAM_H */ diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h index b69aa64b82a..91ad43a54c4 100644 --- a/include/asm-x86/bug.h +++ b/include/asm-x86/bug.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BUG_H -#define _ASM_X86_BUG_H +#ifndef ASM_X86__BUG_H +#define ASM_X86__BUG_H #ifdef CONFIG_BUG #define HAVE_ARCH_BUG @@ -36,4 +36,4 @@ do { \ #endif /* !CONFIG_BUG */ #include -#endif +#endif /* ASM_X86__BUG_H */ diff --git a/include/asm-x86/bugs.h b/include/asm-x86/bugs.h index 021cbdd5f25..4761c461d23 100644 --- a/include/asm-x86/bugs.h +++ b/include/asm-x86/bugs.h @@ -1,7 +1,7 @@ -#ifndef _ASM_X86_BUGS_H -#define _ASM_X86_BUGS_H +#ifndef ASM_X86__BUGS_H +#define ASM_X86__BUGS_H extern void check_bugs(void); int ppro_with_ram_bug(void); -#endif /* _ASM_X86_BUGS_H */ +#endif /* ASM_X86__BUGS_H */ diff --git a/include/asm-x86/byteorder.h b/include/asm-x86/byteorder.h index e02ae2d89ac..722f27d6810 100644 --- a/include/asm-x86/byteorder.h +++ b/include/asm-x86/byteorder.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BYTEORDER_H -#define _ASM_X86_BYTEORDER_H +#ifndef ASM_X86__BYTEORDER_H +#define ASM_X86__BYTEORDER_H #include #include @@ -78,4 +78,4 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) #include -#endif /* _ASM_X86_BYTEORDER_H */ +#endif /* ASM_X86__BYTEORDER_H */ diff --git a/include/asm-x86/cache.h b/include/asm-x86/cache.h index 1e0bac86f38..ea3f1cc06a9 100644 --- a/include/asm-x86/cache.h +++ b/include/asm-x86/cache.h @@ -1,5 +1,5 @@ -#ifndef _ARCH_X86_CACHE_H -#define _ARCH_X86_CACHE_H +#ifndef ASM_X86__CACHE_H +#define ASM_X86__CACHE_H /* L1 cache line size */ #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) @@ -17,4 +17,4 @@ #endif #endif -#endif +#endif /* ASM_X86__CACHE_H */ diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index f4c0ab50d2c..59859cb28a3 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_CACHEFLUSH_H -#define _ASM_X86_CACHEFLUSH_H +#ifndef ASM_X86__CACHEFLUSH_H +#define ASM_X86__CACHEFLUSH_H /* Keep includes the same across arches. */ #include @@ -112,4 +112,4 @@ static inline int rodata_test(void) } #endif -#endif +#endif /* ASM_X86__CACHEFLUSH_H */ diff --git a/include/asm-x86/calgary.h b/include/asm-x86/calgary.h index 67f60406e2d..933fd272f82 100644 --- a/include/asm-x86/calgary.h +++ b/include/asm-x86/calgary.h @@ -21,8 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_64_CALGARY_H -#define _ASM_X86_64_CALGARY_H +#ifndef ASM_X86__CALGARY_H +#define ASM_X86__CALGARY_H #include #include @@ -69,4 +69,4 @@ static inline int calgary_iommu_init(void) { return 1; } static inline void detect_calgary(void) { return; } #endif -#endif /* _ASM_X86_64_CALGARY_H */ +#endif /* ASM_X86__CALGARY_H */ diff --git a/include/asm-x86/checksum_32.h b/include/asm-x86/checksum_32.h index 52bbb0d8c4c..d041e8cda22 100644 --- a/include/asm-x86/checksum_32.h +++ b/include/asm-x86/checksum_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_CHECKSUM_H -#define _I386_CHECKSUM_H +#ifndef ASM_X86__CHECKSUM_32_H +#define ASM_X86__CHECKSUM_32_H #include @@ -186,4 +186,4 @@ static inline __wsum csum_and_copy_to_user(const void *src, return (__force __wsum)-1; /* invalid checksum */ } -#endif +#endif /* ASM_X86__CHECKSUM_32_H */ diff --git a/include/asm-x86/checksum_64.h b/include/asm-x86/checksum_64.h index 8bd861cc526..110f403beb8 100644 --- a/include/asm-x86/checksum_64.h +++ b/include/asm-x86/checksum_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_CHECKSUM_H -#define _X86_64_CHECKSUM_H +#ifndef ASM_X86__CHECKSUM_64_H +#define ASM_X86__CHECKSUM_64_H /* * Checksums for x86-64 @@ -188,4 +188,4 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b) return a; } -#endif +#endif /* ASM_X86__CHECKSUM_64_H */ diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h index bf5a69d1329..0622e45cdf7 100644 --- a/include/asm-x86/cmpxchg_32.h +++ b/include/asm-x86/cmpxchg_32.h @@ -1,5 +1,5 @@ -#ifndef __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H +#ifndef ASM_X86__CMPXCHG_32_H +#define ASM_X86__CMPXCHG_32_H #include /* for LOCK_PREFIX */ @@ -341,4 +341,4 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); #endif -#endif +#endif /* ASM_X86__CMPXCHG_32_H */ diff --git a/include/asm-x86/cmpxchg_64.h b/include/asm-x86/cmpxchg_64.h index 17463ccf816..63c1a5e61b9 100644 --- a/include/asm-x86/cmpxchg_64.h +++ b/include/asm-x86/cmpxchg_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H +#ifndef ASM_X86__CMPXCHG_64_H +#define ASM_X86__CMPXCHG_64_H #include /* Provides LOCK_PREFIX */ @@ -182,4 +182,4 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, cmpxchg_local((ptr), (o), (n)); \ }) -#endif +#endif /* ASM_X86__CMPXCHG_64_H */ diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h index 1793ac317a3..6732b150949 100644 --- a/include/asm-x86/compat.h +++ b/include/asm-x86/compat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_COMPAT_H -#define _ASM_X86_64_COMPAT_H +#ifndef ASM_X86__COMPAT_H +#define ASM_X86__COMPAT_H /* * Architecture specific compatibility types @@ -215,4 +215,4 @@ static inline int is_compat_task(void) return current_thread_info()->status & TS_COMPAT; } -#endif /* _ASM_X86_64_COMPAT_H */ +#endif /* ASM_X86__COMPAT_H */ diff --git a/include/asm-x86/cpu.h b/include/asm-x86/cpu.h index 73f2ea84fd7..83a115083f0 100644 --- a/include/asm-x86/cpu.h +++ b/include/asm-x86/cpu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_I386_CPU_H_ -#define _ASM_I386_CPU_H_ +#ifndef ASM_X86__CPU_H +#define ASM_X86__CPU_H #include #include @@ -17,4 +17,4 @@ extern void arch_unregister_cpu(int); #endif DECLARE_PER_CPU(int, cpu_state); -#endif /* _ASM_I386_CPU_H_ */ +#endif /* ASM_X86__CPU_H */ diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 2f5a792b0ac..2f3143e4514 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -1,8 +1,8 @@ /* * Defines x86 CPU feature bits */ -#ifndef _ASM_X86_CPUFEATURE_H -#define _ASM_X86_CPUFEATURE_H +#ifndef ASM_X86__CPUFEATURE_H +#define ASM_X86__CPUFEATURE_H #include @@ -220,4 +220,4 @@ extern const char * const x86_power_flags[32]; #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ -#endif /* _ASM_X86_CPUFEATURE_H */ +#endif /* ASM_X86__CPUFEATURE_H */ diff --git a/include/asm-x86/current.h b/include/asm-x86/current.h index 7515c19d498..a863ead856f 100644 --- a/include/asm-x86/current.h +++ b/include/asm-x86/current.h @@ -1,5 +1,5 @@ -#ifndef _X86_CURRENT_H -#define _X86_CURRENT_H +#ifndef ASM_X86__CURRENT_H +#define ASM_X86__CURRENT_H #ifdef CONFIG_X86_32 #include @@ -36,4 +36,4 @@ static __always_inline struct task_struct *get_current(void) #define current get_current() -#endif /* X86_CURRENT_H */ +#endif /* ASM_X86__CURRENT_H */ diff --git a/include/asm-x86/debugreg.h b/include/asm-x86/debugreg.h index c6344d572b0..ecb6907c3ea 100644 --- a/include/asm-x86/debugreg.h +++ b/include/asm-x86/debugreg.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DEBUGREG_H -#define _ASM_X86_DEBUGREG_H +#ifndef ASM_X86__DEBUGREG_H +#define ASM_X86__DEBUGREG_H /* Indicate the register numbers for a number of the specific @@ -67,4 +67,4 @@ #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ -#endif +#endif /* ASM_X86__DEBUGREG_H */ diff --git a/include/asm-x86/delay.h b/include/asm-x86/delay.h index 409a649204a..8a0da95b4fc 100644 --- a/include/asm-x86/delay.h +++ b/include/asm-x86/delay.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DELAY_H -#define _ASM_X86_DELAY_H +#ifndef ASM_X86__DELAY_H +#define ASM_X86__DELAY_H /* * Copyright (C) 1993 Linus Torvalds @@ -28,4 +28,4 @@ extern void __delay(unsigned long loops); void use_tsc_delay(void); -#endif /* _ASM_X86_DELAY_H */ +#endif /* ASM_X86__DELAY_H */ diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h index f7bacf357da..b881db664b4 100644 --- a/include/asm-x86/desc_defs.h +++ b/include/asm-x86/desc_defs.h @@ -1,6 +1,6 @@ /* Written 2000 by Andi Kleen */ -#ifndef __ARCH_DESC_DEFS_H -#define __ARCH_DESC_DEFS_H +#ifndef ASM_X86__DESC_DEFS_H +#define ASM_X86__DESC_DEFS_H /* * Segment descriptor structure definitions, usable from both x86_64 and i386 @@ -92,4 +92,4 @@ struct desc_ptr { #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__DESC_DEFS_H */ diff --git a/include/asm-x86/device.h b/include/asm-x86/device.h index 87a715367a1..dbe88554389 100644 --- a/include/asm-x86/device.h +++ b/include/asm-x86/device.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DEVICE_H -#define _ASM_X86_DEVICE_H +#ifndef ASM_X86__DEVICE_H +#define ASM_X86__DEVICE_H struct dev_archdata { #ifdef CONFIG_ACPI @@ -10,4 +10,4 @@ struct dev_archdata { #endif }; -#endif /* _ASM_X86_DEVICE_H */ +#endif /* ASM_X86__DEVICE_H */ diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h index 9a2d644c08e..f9530f23f1d 100644 --- a/include/asm-x86/div64.h +++ b/include/asm-x86/div64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DIV64_H -#define _ASM_X86_DIV64_H +#ifndef ASM_X86__DIV64_H +#define ASM_X86__DIV64_H #ifdef CONFIG_X86_32 @@ -57,4 +57,4 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) # include #endif /* CONFIG_X86_32 */ -#endif /* _ASM_X86_DIV64_H */ +#endif /* ASM_X86__DIV64_H */ diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index c2ddd3d1b88..71b6f7d22e9 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h @@ -1,5 +1,5 @@ -#ifndef _ASM_DMA_MAPPING_H_ -#define _ASM_DMA_MAPPING_H_ +#ifndef ASM_X86__DMA_MAPPING_H +#define ASM_X86__DMA_MAPPING_H /* * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for @@ -233,4 +233,4 @@ extern void * dma_mark_declared_memory_occupied(struct device *dev, dma_addr_t device_addr, size_t size); #endif /* CONFIG_X86_32 */ -#endif +#endif /* ASM_X86__DMA_MAPPING_H */ diff --git a/include/asm-x86/dma.h b/include/asm-x86/dma.h index ca1098a7e58..c9f7a4eec55 100644 --- a/include/asm-x86/dma.h +++ b/include/asm-x86/dma.h @@ -5,8 +5,8 @@ * and John Boyd, Nov. 1992. */ -#ifndef _ASM_X86_DMA_H -#define _ASM_X86_DMA_H +#ifndef ASM_X86__DMA_H +#define ASM_X86__DMA_H #include /* And spinlocks */ #include /* need byte IO */ @@ -315,4 +315,4 @@ extern int isa_dma_bridge_buggy; #define isa_dma_bridge_buggy (0) #endif -#endif /* _ASM_X86_DMA_H */ +#endif /* ASM_X86__DMA_H */ diff --git a/include/asm-x86/dmi.h b/include/asm-x86/dmi.h index 58a86571fe0..1cff6fe81fa 100644 --- a/include/asm-x86/dmi.h +++ b/include/asm-x86/dmi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DMI_H -#define _ASM_X86_DMI_H +#ifndef ASM_X86__DMI_H +#define ASM_X86__DMI_H #include @@ -23,4 +23,4 @@ static inline void *dmi_alloc(unsigned len) #define dmi_ioremap early_ioremap #define dmi_iounmap early_iounmap -#endif +#endif /* ASM_X86__DMI_H */ diff --git a/include/asm-x86/ds.h b/include/asm-x86/ds.h index 7881368142f..6b27c686fa1 100644 --- a/include/asm-x86/ds.h +++ b/include/asm-x86/ds.h @@ -17,8 +17,8 @@ * Markus Metzger , Dec 2007 */ -#ifndef _ASM_X86_DS_H -#define _ASM_X86_DS_H +#ifndef ASM_X86__DS_H +#define ASM_X86__DS_H #include #include @@ -69,4 +69,4 @@ extern int ds_write_bts(void *, const struct bts_struct *); extern unsigned long ds_debugctl_mask(void); extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *c); -#endif /* _ASM_X86_DS_H */ +#endif /* ASM_X86__DS_H */ diff --git a/include/asm-x86/dwarf2.h b/include/asm-x86/dwarf2.h index 738bb9fb3e5..21d1bc32ad7 100644 --- a/include/asm-x86/dwarf2.h +++ b/include/asm-x86/dwarf2.h @@ -1,5 +1,5 @@ -#ifndef _DWARF2_H -#define _DWARF2_H +#ifndef ASM_X86__DWARF2_H +#define ASM_X86__DWARF2_H #ifndef __ASSEMBLY__ #warning "asm/dwarf2.h should be only included in pure assembly files" @@ -58,4 +58,4 @@ #endif -#endif +#endif /* ASM_X86__DWARF2_H */ diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index 16a31e2c7c5..38741ac7690 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h @@ -1,5 +1,5 @@ -#ifndef __ASM_E820_H -#define __ASM_E820_H +#ifndef ASM_X86__E820_H +#define ASM_X86__E820_H #define E820MAP 0x2d0 /* our map */ #define E820MAX 128 /* number of entries in E820MAP */ @@ -140,4 +140,4 @@ extern char *memory_setup(void); #define HIGH_MEMORY (1024*1024) #endif /* __KERNEL__ */ -#endif /* __ASM_E820_H */ +#endif /* ASM_X86__E820_H */ diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h index a8088f63a30..9493c5b27bb 100644 --- a/include/asm-x86/edac.h +++ b/include/asm-x86/edac.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_EDAC_H -#define _ASM_X86_EDAC_H +#ifndef ASM_X86__EDAC_H +#define ASM_X86__EDAC_H /* ECC atomic, DMA, SMP and interrupt safe scrub function */ @@ -15,4 +15,4 @@ static inline void atomic_scrub(void *va, u32 size) asm volatile("lock; addl $0, %0"::"m" (*virt_addr)); } -#endif +#endif /* ASM_X86__EDAC_H */ diff --git a/include/asm-x86/efi.h b/include/asm-x86/efi.h index 7ed2bd7a7f5..69c7b7ab43e 100644 --- a/include/asm-x86/efi.h +++ b/include/asm-x86/efi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_EFI_H -#define _ASM_X86_EFI_H +#ifndef ASM_X86__EFI_H +#define ASM_X86__EFI_H #ifdef CONFIG_X86_32 @@ -94,4 +94,4 @@ extern void efi_reserve_early(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); -#endif +#endif /* ASM_X86__EFI_H */ diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h index 7be4733c793..cd678b2d6a7 100644 --- a/include/asm-x86/elf.h +++ b/include/asm-x86/elf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ELF_H -#define _ASM_X86_ELF_H +#ifndef ASM_X86__ELF_H +#define ASM_X86__ELF_H /* * ELF register definitions.. @@ -332,4 +332,4 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack); extern unsigned long arch_randomize_brk(struct mm_struct *mm); #define arch_randomize_brk arch_randomize_brk -#endif +#endif /* ASM_X86__ELF_H */ diff --git a/include/asm-x86/emergency-restart.h b/include/asm-x86/emergency-restart.h index 8e6aef19f8f..190d0d8b71e 100644 --- a/include/asm-x86/emergency-restart.h +++ b/include/asm-x86/emergency-restart.h @@ -1,5 +1,5 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H +#ifndef ASM_X86__EMERGENCY_RESTART_H +#define ASM_X86__EMERGENCY_RESTART_H enum reboot_type { BOOT_TRIPLE = 't', @@ -15,4 +15,4 @@ extern enum reboot_type reboot_type; extern void machine_emergency_restart(void); -#endif /* _ASM_EMERGENCY_RESTART_H */ +#endif /* ASM_X86__EMERGENCY_RESTART_H */ diff --git a/include/asm-x86/fb.h b/include/asm-x86/fb.h index 53018464aea..aca38dbd9a6 100644 --- a/include/asm-x86/fb.h +++ b/include/asm-x86/fb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FB_H -#define _ASM_X86_FB_H +#ifndef ASM_X86__FB_H +#define ASM_X86__FB_H #include #include @@ -18,4 +18,4 @@ extern int fb_is_primary_device(struct fb_info *info); static inline int fb_is_primary_device(struct fb_info *info) { return 0; } #endif -#endif /* _ASM_X86_FB_H */ +#endif /* ASM_X86__FB_H */ diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h index 44d4f821734..78e33a1bc59 100644 --- a/include/asm-x86/fixmap.h +++ b/include/asm-x86/fixmap.h @@ -1,5 +1,5 @@ -#ifndef _ASM_FIXMAP_H -#define _ASM_FIXMAP_H +#ifndef ASM_X86__FIXMAP_H +#define ASM_X86__FIXMAP_H #ifdef CONFIG_X86_32 # include "fixmap_32.h" @@ -65,4 +65,4 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr) BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); return __virt_to_fix(vaddr); } -#endif +#endif /* ASM_X86__FIXMAP_H */ diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h index f1ac2b2167d..784e3e75986 100644 --- a/include/asm-x86/fixmap_32.h +++ b/include/asm-x86/fixmap_32.h @@ -10,8 +10,8 @@ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 */ -#ifndef _ASM_FIXMAP_32_H -#define _ASM_FIXMAP_32_H +#ifndef ASM_X86__FIXMAP_32_H +#define ASM_X86__FIXMAP_32_H /* used by vmalloc.c, vsyscall.lds.S. @@ -120,4 +120,4 @@ extern void reserve_top_address(unsigned long reserve); #define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE) #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__FIXMAP_32_H */ diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h index 00f3d74a052..dafb24bc042 100644 --- a/include/asm-x86/fixmap_64.h +++ b/include/asm-x86/fixmap_64.h @@ -8,8 +8,8 @@ * Copyright (C) 1998 Ingo Molnar */ -#ifndef _ASM_FIXMAP_64_H -#define _ASM_FIXMAP_64_H +#ifndef ASM_X86__FIXMAP_64_H +#define ASM_X86__FIXMAP_64_H #include #include @@ -80,4 +80,4 @@ enum fixed_addresses { #define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) #define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) -#endif +#endif /* ASM_X86__FIXMAP_64_H */ diff --git a/include/asm-x86/floppy.h b/include/asm-x86/floppy.h index dbe82a5c5ea..7d83a3a83e3 100644 --- a/include/asm-x86/floppy.h +++ b/include/asm-x86/floppy.h @@ -7,8 +7,8 @@ * * Copyright (C) 1995 */ -#ifndef _ASM_X86_FLOPPY_H -#define _ASM_X86_FLOPPY_H +#ifndef ASM_X86__FLOPPY_H +#define ASM_X86__FLOPPY_H #include @@ -278,4 +278,4 @@ static int FDC2 = -1; #define EXTRA_FLOPPY_PARAMS -#endif /* _ASM_X86_FLOPPY_H */ +#endif /* ASM_X86__FLOPPY_H */ diff --git a/include/asm-x86/ftrace.h b/include/asm-x86/ftrace.h index 5c68b32ee1c..be0e004ad14 100644 --- a/include/asm-x86/ftrace.h +++ b/include/asm-x86/ftrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FTRACE -#define _ASM_X86_FTRACE +#ifndef ASM_X86__FTRACE_H +#define ASM_X86__FTRACE_H #ifdef CONFIG_FTRACE #define MCOUNT_ADDR ((long)(mcount)) @@ -11,4 +11,4 @@ extern void mcount(void); #endif /* CONFIG_FTRACE */ -#endif /* _ASM_X86_FTRACE */ +#endif /* ASM_X86__FTRACE_H */ diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h index e7a76b37b33..45dc24d8418 100644 --- a/include/asm-x86/futex.h +++ b/include/asm-x86/futex.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FUTEX_H -#define _ASM_X86_FUTEX_H +#ifndef ASM_X86__FUTEX_H +#define ASM_X86__FUTEX_H #ifdef __KERNEL__ @@ -137,4 +137,4 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, } #endif -#endif +#endif /* ASM_X86__FUTEX_H */ diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h index 3f62a83887f..07f44584414 100644 --- a/include/asm-x86/gart.h +++ b/include/asm-x86/gart.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_GART_H -#define _ASM_X8664_GART_H 1 +#ifndef ASM_X86__GART_H +#define ASM_X86__GART_H #include @@ -68,4 +68,4 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) return 1; } -#endif +#endif /* ASM_X86__GART_H */ diff --git a/include/asm-x86/genapic_32.h b/include/asm-x86/genapic_32.h index b02ea6e17de..4904c672e4f 100644 --- a/include/asm-x86/genapic_32.h +++ b/include/asm-x86/genapic_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_GENAPIC_H -#define _ASM_GENAPIC_H 1 +#ifndef ASM_X86__GENAPIC_32_H +#define ASM_X86__GENAPIC_32_H #include @@ -120,4 +120,4 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; #define uv_wakeup_secondary(a, b) 1 -#endif +#endif /* ASM_X86__GENAPIC_32_H */ diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 0f8504627c4..381a09d19d5 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_GENAPIC_H -#define _ASM_GENAPIC_H 1 +#ifndef ASM_X86__GENAPIC_64_H +#define ASM_X86__GENAPIC_64_H /* * Copyright 2004 James Cleverdon, IBM. @@ -46,4 +46,4 @@ extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); extern void setup_apic_routing(void); -#endif +#endif /* ASM_X86__GENAPIC_64_H */ diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h index bb06027fc83..1ef738e01a0 100644 --- a/include/asm-x86/geode.h +++ b/include/asm-x86/geode.h @@ -7,8 +7,8 @@ * as published by the Free Software Foundation. */ -#ifndef _ASM_GEODE_H_ -#define _ASM_GEODE_H_ +#ifndef ASM_X86__GEODE_H +#define ASM_X86__GEODE_H #include #include @@ -249,4 +249,4 @@ extern int __init mfgpt_timer_setup(void); static inline int mfgpt_timer_setup(void) { return 0; } #endif -#endif +#endif /* ASM_X86__GEODE_H */ diff --git a/include/asm-x86/gpio.h b/include/asm-x86/gpio.h index ff87fca0caf..f269ff9cd40 100644 --- a/include/asm-x86/gpio.h +++ b/include/asm-x86/gpio.h @@ -1,6 +1,6 @@ -#ifndef _ASM_I386_GPIO_H -#define _ASM_I386_GPIO_H +#ifndef ASM_X86__GPIO_H +#define ASM_X86__GPIO_H #include -#endif /* _ASM_I386_GPIO_H */ +#endif /* ASM_X86__GPIO_H */ diff --git a/include/asm-x86/hardirq_32.h b/include/asm-x86/hardirq_32.h index 4f85f0f4b56..700fe230d91 100644 --- a/include/asm-x86/hardirq_32.h +++ b/include/asm-x86/hardirq_32.h @@ -1,5 +1,5 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H +#ifndef ASM_X86__HARDIRQ_32_H +#define ASM_X86__HARDIRQ_32_H #include #include @@ -25,4 +25,4 @@ DECLARE_PER_CPU(irq_cpustat_t, irq_stat); void ack_bad_irq(unsigned int irq); #include -#endif /* __ASM_HARDIRQ_H */ +#endif /* ASM_X86__HARDIRQ_32_H */ diff --git a/include/asm-x86/hardirq_64.h b/include/asm-x86/hardirq_64.h index 95d5e090ed8..f8bd2919a8c 100644 --- a/include/asm-x86/hardirq_64.h +++ b/include/asm-x86/hardirq_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H +#ifndef ASM_X86__HARDIRQ_64_H +#define ASM_X86__HARDIRQ_64_H #include #include @@ -20,4 +20,4 @@ extern void ack_bad_irq(unsigned int irq); -#endif /* __ASM_HARDIRQ_H */ +#endif /* ASM_X86__HARDIRQ_64_H */ diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h index 4514b16cc72..bc3f6a28031 100644 --- a/include/asm-x86/highmem.h +++ b/include/asm-x86/highmem.h @@ -15,8 +15,8 @@ * Copyright (C) 1999 Ingo Molnar */ -#ifndef _ASM_HIGHMEM_H -#define _ASM_HIGHMEM_H +#ifndef ASM_X86__HIGHMEM_H +#define ASM_X86__HIGHMEM_H #ifdef __KERNEL__ @@ -79,4 +79,4 @@ extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn, #endif /* __KERNEL__ */ -#endif /* _ASM_HIGHMEM_H */ +#endif /* ASM_X86__HIGHMEM_H */ diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index 82f1ac641bd..cbbbb6d4dd3 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86_HPET_H -#define ASM_X86_HPET_H +#ifndef ASM_X86__HPET_H +#define ASM_X86__HPET_H #ifdef CONFIG_HPET_TIMER @@ -90,4 +90,4 @@ static inline int is_hpet_enabled(void) { return 0; } #define hpet_readl(a) 0 #endif -#endif /* ASM_X86_HPET_H */ +#endif /* ASM_X86__HPET_H */ diff --git a/include/asm-x86/hugetlb.h b/include/asm-x86/hugetlb.h index 14171a4924f..0e0a0828182 100644 --- a/include/asm-x86/hugetlb.h +++ b/include/asm-x86/hugetlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_HUGETLB_H -#define _ASM_X86_HUGETLB_H +#ifndef ASM_X86__HUGETLB_H +#define ASM_X86__HUGETLB_H #include @@ -88,4 +88,4 @@ static inline void arch_release_hugepage(struct page *page) { } -#endif /* _ASM_X86_HUGETLB_H */ +#endif /* ASM_X86__HUGETLB_H */ diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 77ba51df566..3f3c465b915 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -1,5 +1,5 @@ -#ifndef _ASM_HW_IRQ_H -#define _ASM_HW_IRQ_H +#ifndef ASM_X86__HW_IRQ_H +#define ASM_X86__HW_IRQ_H /* * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar @@ -104,4 +104,4 @@ extern void setup_vector_irq(int cpu); #endif /* !ASSEMBLY_ */ -#endif +#endif /* ASM_X86__HW_IRQ_H */ diff --git a/include/asm-x86/hypertransport.h b/include/asm-x86/hypertransport.h index d2bbd238b3e..cc011a3bc1c 100644 --- a/include/asm-x86/hypertransport.h +++ b/include/asm-x86/hypertransport.h @@ -1,5 +1,5 @@ -#ifndef ASM_HYPERTRANSPORT_H -#define ASM_HYPERTRANSPORT_H +#ifndef ASM_X86__HYPERTRANSPORT_H +#define ASM_X86__HYPERTRANSPORT_H /* * Constants for x86 Hypertransport Interrupts. @@ -42,4 +42,4 @@ #define HT_IRQ_HIGH_DEST_ID(v) \ ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) -#endif /* ASM_HYPERTRANSPORT_H */ +#endif /* ASM_X86__HYPERTRANSPORT_H */ diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 37672f79dcc..3e83cbb728a 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -7,8 +7,8 @@ * x86-64 work by Andi Kleen 2002 */ -#ifndef _ASM_X86_I387_H -#define _ASM_X86_I387_H +#ifndef ASM_X86__I387_H +#define ASM_X86__I387_H #include #include @@ -360,4 +360,4 @@ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) } } -#endif /* _ASM_X86_I387_H */ +#endif /* ASM_X86__I387_H */ diff --git a/include/asm-x86/i8253.h b/include/asm-x86/i8253.h index b51c0487fc4..15a5b530044 100644 --- a/include/asm-x86/i8253.h +++ b/include/asm-x86/i8253.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I8253_H__ -#define __ASM_I8253_H__ +#ifndef ASM_X86__I8253_H +#define ASM_X86__I8253_H /* i8253A PIT registers */ #define PIT_MODE 0x43 @@ -15,4 +15,4 @@ extern void setup_pit_timer(void); #define inb_pit inb_p #define outb_pit outb_p -#endif /* __ASM_I8253_H__ */ +#endif /* ASM_X86__I8253_H */ diff --git a/include/asm-x86/i8259.h b/include/asm-x86/i8259.h index 2f98df91f1f..c586559a695 100644 --- a/include/asm-x86/i8259.h +++ b/include/asm-x86/i8259.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I8259_H__ -#define __ASM_I8259_H__ +#ifndef ASM_X86__I8259_H +#define ASM_X86__I8259_H #include @@ -57,4 +57,4 @@ static inline void outb_pic(unsigned char value, unsigned int port) extern struct irq_chip i8259A_chip; -#endif /* __ASM_I8259_H__ */ +#endif /* ASM_X86__I8259_H */ diff --git a/include/asm-x86/ia32.h b/include/asm-x86/ia32.h index 55d3abe5276..f932f7ad51d 100644 --- a/include/asm-x86/ia32.h +++ b/include/asm-x86/ia32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IA32_H -#define _ASM_X86_64_IA32_H +#ifndef ASM_X86__IA32_H +#define ASM_X86__IA32_H #ifdef CONFIG_IA32_EMULATION @@ -167,4 +167,4 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm); #endif /* !CONFIG_IA32_SUPPORT */ -#endif +#endif /* ASM_X86__IA32_H */ diff --git a/include/asm-x86/ia32_unistd.h b/include/asm-x86/ia32_unistd.h index 61cea9e7c5c..dbd887d8a5a 100644 --- a/include/asm-x86/ia32_unistd.h +++ b/include/asm-x86/ia32_unistd.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IA32_UNISTD_H_ -#define _ASM_X86_64_IA32_UNISTD_H_ +#ifndef ASM_X86__IA32_UNISTD_H +#define ASM_X86__IA32_UNISTD_H /* * This file contains the system call numbers of the ia32 port, @@ -15,4 +15,4 @@ #define __NR_ia32_sigreturn 119 #define __NR_ia32_rt_sigreturn 173 -#endif /* _ASM_X86_64_IA32_UNISTD_H_ */ +#endif /* ASM_X86__IA32_UNISTD_H */ diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h index cf9c98e5bdb..8bf3cdc6bb4 100644 --- a/include/asm-x86/ide.h +++ b/include/asm-x86/ide.h @@ -6,8 +6,8 @@ * This file contains the i386 architecture specific IDE code. */ -#ifndef __ASMi386_IDE_H -#define __ASMi386_IDE_H +#ifndef ASM_X86__IDE_H +#define ASM_X86__IDE_H #ifdef __KERNEL__ @@ -62,4 +62,4 @@ static __inline__ unsigned long ide_default_io_base(int index) #endif /* __KERNEL__ */ -#endif /* __ASMi386_IDE_H */ +#endif /* ASM_X86__IDE_H */ diff --git a/include/asm-x86/idle.h b/include/asm-x86/idle.h index d240e5b30a4..dc9c7944847 100644 --- a/include/asm-x86/idle.h +++ b/include/asm-x86/idle.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IDLE_H -#define _ASM_X86_64_IDLE_H 1 +#ifndef ASM_X86__IDLE_H +#define ASM_X86__IDLE_H #define IDLE_START 1 #define IDLE_END 2 @@ -10,4 +10,4 @@ void idle_notifier_register(struct notifier_block *n); void enter_idle(void); void exit_idle(void); -#endif +#endif /* ASM_X86__IDLE_H */ diff --git a/include/asm-x86/intel_arch_perfmon.h b/include/asm-x86/intel_arch_perfmon.h index fa0fd068bc2..07c03c6c9a1 100644 --- a/include/asm-x86/intel_arch_perfmon.h +++ b/include/asm-x86/intel_arch_perfmon.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_INTEL_ARCH_PERFMON_H -#define _ASM_X86_INTEL_ARCH_PERFMON_H +#ifndef ASM_X86__INTEL_ARCH_PERFMON_H +#define ASM_X86__INTEL_ARCH_PERFMON_H #define MSR_ARCH_PERFMON_PERFCTR0 0xc1 #define MSR_ARCH_PERFMON_PERFCTR1 0xc2 @@ -28,4 +28,4 @@ union cpuid10_eax { unsigned int full; }; -#endif /* _ASM_X86_INTEL_ARCH_PERFMON_H */ +#endif /* ASM_X86__INTEL_ARCH_PERFMON_H */ diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h index bf5d629b3a3..1b75a43bb6c 100644 --- a/include/asm-x86/io.h +++ b/include/asm-x86/io.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IO_H -#define _ASM_X86_IO_H +#ifndef ASM_X86__IO_H +#define ASM_X86__IO_H #define ARCH_HAS_IOREMAP_WC @@ -99,4 +99,4 @@ extern void early_iounmap(void *addr, unsigned long size); extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); -#endif /* _ASM_X86_IO_H */ +#endif /* ASM_X86__IO_H */ diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h index 4df44ed5407..d9d1e3f269a 100644 --- a/include/asm-x86/io_32.h +++ b/include/asm-x86/io_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IO_H -#define _ASM_IO_H +#ifndef ASM_X86__IO_32_H +#define ASM_X86__IO_32_H #include #include @@ -279,4 +279,4 @@ BUILDIO(b, b, char) BUILDIO(w, w, short) BUILDIO(l, , int) -#endif +#endif /* ASM_X86__IO_32_H */ diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index ddd8058a502..00ac4729e52 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IO_H -#define _ASM_IO_H +#ifndef ASM_X86__IO_64_H +#define ASM_X86__IO_64_H /* @@ -243,4 +243,4 @@ extern int iommu_bio_merge; #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__IO_64_H */ diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h index 14f82bbcb5f..be62847ab07 100644 --- a/include/asm-x86/io_apic.h +++ b/include/asm-x86/io_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_IO_APIC_H -#define __ASM_IO_APIC_H +#ifndef ASM_X86__IO_APIC_H +#define ASM_X86__IO_APIC_H #include #include @@ -189,4 +189,4 @@ static const int timer_through_8259 = 0; static inline void ioapic_init_mappings(void) { } #endif -#endif +#endif /* ASM_X86__IO_APIC_H */ diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h index c0c338bd406..33660351239 100644 --- a/include/asm-x86/ioctls.h +++ b/include/asm-x86/ioctls.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IOCTLS_H -#define _ASM_X86_IOCTLS_H +#ifndef ASM_X86__IOCTLS_H +#define ASM_X86__IOCTLS_H #include @@ -85,4 +85,4 @@ #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ -#endif +#endif /* ASM_X86__IOCTLS_H */ diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h index d63166fb3ab..4f3d212d827 100644 --- a/include/asm-x86/iommu.h +++ b/include/asm-x86/iommu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_IOMMU_H -#define _ASM_X8664_IOMMU_H 1 +#ifndef ASM_X86__IOMMU_H +#define ASM_X86__IOMMU_H extern void pci_iommu_shutdown(void); extern void no_iommu_init(void); @@ -39,4 +39,4 @@ static inline void gart_iommu_hole_init(void) } #endif -#endif +#endif /* ASM_X86__IOMMU_H */ diff --git a/include/asm-x86/ipcbuf.h b/include/asm-x86/ipcbuf.h index ee678fd5159..910304fbdc8 100644 --- a/include/asm-x86/ipcbuf.h +++ b/include/asm-x86/ipcbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IPCBUF_H -#define _ASM_X86_IPCBUF_H +#ifndef ASM_X86__IPCBUF_H +#define ASM_X86__IPCBUF_H /* * The ipc64_perm structure for x86 architecture. @@ -25,4 +25,4 @@ struct ipc64_perm { unsigned long __unused2; }; -#endif /* _ASM_X86_IPCBUF_H */ +#endif /* ASM_X86__IPCBUF_H */ diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h index 196d63c28aa..63390ea87d1 100644 --- a/include/asm-x86/ipi.h +++ b/include/asm-x86/ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_IPI_H -#define __ASM_IPI_H +#ifndef ASM_X86__IPI_H +#define ASM_X86__IPI_H /* * Copyright 2004 James Cleverdon, IBM. @@ -129,4 +129,4 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) local_irq_restore(flags); } -#endif /* __ASM_IPI_H */ +#endif /* ASM_X86__IPI_H */ diff --git a/include/asm-x86/irq.h b/include/asm-x86/irq.h index 1a292575731..1e5f2909c1d 100644 --- a/include/asm-x86/irq.h +++ b/include/asm-x86/irq.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_H -#define _ASM_IRQ_H +#ifndef ASM_X86__IRQ_H +#define ASM_X86__IRQ_H /* * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar * @@ -47,4 +47,4 @@ extern void native_init_IRQ(void); /* Interrupt vector management */ extern DECLARE_BITMAP(used_vectors, NR_VECTORS); -#endif /* _ASM_IRQ_H */ +#endif /* ASM_X86__IRQ_H */ diff --git a/include/asm-x86/irq_regs_32.h b/include/asm-x86/irq_regs_32.h index 3368b20c0b4..316a3b25887 100644 --- a/include/asm-x86/irq_regs_32.h +++ b/include/asm-x86/irq_regs_32.h @@ -4,8 +4,8 @@ * * Jeremy Fitzhardinge */ -#ifndef _ASM_I386_IRQ_REGS_H -#define _ASM_I386_IRQ_REGS_H +#ifndef ASM_X86__IRQ_REGS_32_H +#define ASM_X86__IRQ_REGS_32_H #include @@ -26,4 +26,4 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) return old_regs; } -#endif /* _ASM_I386_IRQ_REGS_H */ +#endif /* ASM_X86__IRQ_REGS_32_H */ diff --git a/include/asm-x86/irq_vectors.h b/include/asm-x86/irq_vectors.h index 90b1d1f12f0..646d59f5ebf 100644 --- a/include/asm-x86/irq_vectors.h +++ b/include/asm-x86/irq_vectors.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_H -#define _ASM_IRQ_VECTORS_H +#ifndef ASM_X86__IRQ_VECTORS_H +#define ASM_X86__IRQ_VECTORS_H #include @@ -170,4 +170,4 @@ #define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8) -#endif /* _ASM_IRQ_VECTORS_H */ +#endif /* ASM_X86__IRQ_VECTORS_H */ diff --git a/include/asm-x86/ist.h b/include/asm-x86/ist.h index 6ec6ceed95a..35a2fe9bc92 100644 --- a/include/asm-x86/ist.h +++ b/include/asm-x86/ist.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IST_H -#define _ASM_IST_H +#ifndef ASM_X86__IST_H +#define ASM_X86__IST_H /* * Include file for the interface to IST BIOS @@ -31,4 +31,4 @@ struct ist_info { extern struct ist_info ist_info; #endif /* __KERNEL__ */ -#endif /* _ASM_IST_H */ +#endif /* ASM_X86__IST_H */ diff --git a/include/asm-x86/k8.h b/include/asm-x86/k8.h index 452e2b696ff..2bbaf4370a5 100644 --- a/include/asm-x86/k8.h +++ b/include/asm-x86/k8.h @@ -1,5 +1,5 @@ -#ifndef _ASM_K8_H -#define _ASM_K8_H 1 +#ifndef ASM_X86__K8_H +#define ASM_X86__K8_H #include @@ -12,4 +12,4 @@ extern int cache_k8_northbridges(void); extern void k8_flush_garts(void); extern int k8_scan_nodes(unsigned long start, unsigned long end); -#endif +#endif /* ASM_X86__K8_H */ diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index 96651bb59ba..5ec3ad3e825 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_KDEBUG_H -#define _ASM_X86_KDEBUG_H +#ifndef ASM_X86__KDEBUG_H +#define ASM_X86__KDEBUG_H #include @@ -35,4 +35,4 @@ extern void show_regs(struct pt_regs *regs); extern unsigned long oops_begin(void); extern void oops_end(unsigned long, struct pt_regs *, int signr); -#endif +#endif /* ASM_X86__KDEBUG_H */ diff --git a/include/asm-x86/kexec.h b/include/asm-x86/kexec.h index 8f855a15f64..262b63ec911 100644 --- a/include/asm-x86/kexec.h +++ b/include/asm-x86/kexec.h @@ -1,5 +1,5 @@ -#ifndef _KEXEC_H -#define _KEXEC_H +#ifndef ASM_X86__KEXEC_H +#define ASM_X86__KEXEC_H #ifdef CONFIG_X86_32 # define PA_CONTROL_PAGE 0 @@ -166,4 +166,4 @@ relocate_kernel(unsigned long indirection_page, #endif /* __ASSEMBLY__ */ -#endif /* _KEXEC_H */ +#endif /* ASM_X86__KEXEC_H */ diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h index 484c47554f3..83a7ee228ab 100644 --- a/include/asm-x86/kgdb.h +++ b/include/asm-x86/kgdb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_KGDB_H_ -#define _ASM_KGDB_H_ +#ifndef ASM_X86__KGDB_H +#define ASM_X86__KGDB_H /* * Copyright (C) 2001-2004 Amit S. Kale @@ -78,4 +78,4 @@ static inline void arch_kgdb_breakpoint(void) #define BREAK_INSTR_SIZE 1 #define CACHE_FLUSH_IS_SAFE 1 -#endif /* _ASM_KGDB_H_ */ +#endif /* ASM_X86__KGDB_H */ diff --git a/include/asm-x86/kmap_types.h b/include/asm-x86/kmap_types.h index 5f4174132a2..89f44493e64 100644 --- a/include/asm-x86/kmap_types.h +++ b/include/asm-x86/kmap_types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_KMAP_TYPES_H -#define _ASM_X86_KMAP_TYPES_H +#ifndef ASM_X86__KMAP_TYPES_H +#define ASM_X86__KMAP_TYPES_H #if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM) # define D(n) __KM_FENCE_##n , @@ -26,4 +26,4 @@ D(13) KM_TYPE_NR #undef D -#endif +#endif /* ASM_X86__KMAP_TYPES_H */ diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h index 54980b0b389..bd8407863c1 100644 --- a/include/asm-x86/kprobes.h +++ b/include/asm-x86/kprobes.h @@ -1,5 +1,5 @@ -#ifndef _ASM_KPROBES_H -#define _ASM_KPROBES_H +#ifndef ASM_X86__KPROBES_H +#define ASM_X86__KPROBES_H /* * Kernel Probes (KProbes) * @@ -94,4 +94,4 @@ static inline void restore_interrupts(struct pt_regs *regs) extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -#endif /* _ASM_KPROBES_H */ +#endif /* ASM_X86__KPROBES_H */ diff --git a/include/asm-x86/kvm.h b/include/asm-x86/kvm.h index 6f1840812e5..78e954db1e7 100644 --- a/include/asm-x86/kvm.h +++ b/include/asm-x86/kvm.h @@ -1,5 +1,5 @@ -#ifndef __LINUX_KVM_X86_H -#define __LINUX_KVM_X86_H +#ifndef ASM_X86__KVM_H +#define ASM_X86__KVM_H /* * KVM x86 specific structures and definitions @@ -230,4 +230,4 @@ struct kvm_pit_state { #define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14) #define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15) -#endif +#endif /* ASM_X86__KVM_H */ diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 924e1bfe3a6..920823d53d6 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -8,8 +8,8 @@ * */ -#ifndef ASM_KVM_HOST_H -#define ASM_KVM_HOST_H +#ifndef ASM_X86__KVM_HOST_H +#define ASM_X86__KVM_HOST_H #include #include @@ -728,4 +728,4 @@ asmlinkage void kvm_handle_fault_on_reboot(void); KVM_EX_ENTRY " 666b, 667b \n\t" \ ".popsection" -#endif +#endif /* ASM_X86__KVM_HOST_H */ diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h index 76f392146da..30054fded4f 100644 --- a/include/asm-x86/kvm_para.h +++ b/include/asm-x86/kvm_para.h @@ -1,5 +1,5 @@ -#ifndef __X86_KVM_PARA_H -#define __X86_KVM_PARA_H +#ifndef ASM_X86__KVM_PARA_H +#define ASM_X86__KVM_PARA_H /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It * should be used to determine that a VM is running under KVM. @@ -144,4 +144,4 @@ static inline unsigned int kvm_arch_para_features(void) #endif -#endif +#endif /* ASM_X86__KVM_PARA_H */ diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h index 4e8c1e48d91..e2d9b030c1a 100644 --- a/include/asm-x86/kvm_x86_emulate.h +++ b/include/asm-x86/kvm_x86_emulate.h @@ -8,8 +8,8 @@ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 */ -#ifndef __X86_EMULATE_H__ -#define __X86_EMULATE_H__ +#ifndef ASM_X86__KVM_X86_EMULATE_H +#define ASM_X86__KVM_X86_EMULATE_H struct x86_emulate_ctxt; @@ -181,4 +181,4 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops); -#endif /* __X86_EMULATE_H__ */ +#endif /* ASM_X86__KVM_X86_EMULATE_H */ diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h index 20c597242b5..a5228504d86 100644 --- a/include/asm-x86/ldt.h +++ b/include/asm-x86/ldt.h @@ -3,8 +3,8 @@ * * Definitions of structures used with the modify_ldt system call. */ -#ifndef _ASM_X86_LDT_H -#define _ASM_X86_LDT_H +#ifndef ASM_X86__LDT_H +#define ASM_X86__LDT_H /* Maximum number of LDT entries supported. */ #define LDT_ENTRIES 8192 @@ -37,4 +37,4 @@ struct user_desc { #define MODIFY_LDT_CONTENTS_CODE 2 #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__LDT_H */ diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h index be4a7247fa2..7505e947ed2 100644 --- a/include/asm-x86/lguest.h +++ b/include/asm-x86/lguest.h @@ -1,5 +1,5 @@ -#ifndef _X86_LGUEST_H -#define _X86_LGUEST_H +#ifndef ASM_X86__LGUEST_H +#define ASM_X86__LGUEST_H #define GDT_ENTRY_LGUEST_CS 10 #define GDT_ENTRY_LGUEST_DS 11 @@ -91,4 +91,4 @@ static inline void lguest_set_ts(void) #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__LGUEST_H */ diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h index a3241f28e34..8f034ba4b53 100644 --- a/include/asm-x86/lguest_hcall.h +++ b/include/asm-x86/lguest_hcall.h @@ -1,6 +1,6 @@ /* Architecture specific portion of the lguest hypercalls */ -#ifndef _X86_LGUEST_HCALL_H -#define _X86_LGUEST_HCALL_H +#ifndef ASM_X86__LGUEST_HCALL_H +#define ASM_X86__LGUEST_HCALL_H #define LHCALL_FLUSH_ASYNC 0 #define LHCALL_LGUEST_INIT 1 @@ -68,4 +68,4 @@ struct hcall_args { }; #endif /* !__ASSEMBLY__ */ -#endif /* _I386_LGUEST_HCALL_H */ +#endif /* ASM_X86__LGUEST_HCALL_H */ diff --git a/include/asm-x86/linkage.h b/include/asm-x86/linkage.h index 64e444f8e85..42d8b62ee8a 100644 --- a/include/asm-x86/linkage.h +++ b/include/asm-x86/linkage.h @@ -1,5 +1,5 @@ -#ifndef __ASM_LINKAGE_H -#define __ASM_LINKAGE_H +#ifndef ASM_X86__LINKAGE_H +#define ASM_X86__LINKAGE_H #undef notrace #define notrace __attribute__((no_instrument_function)) @@ -57,5 +57,5 @@ #define __ALIGN_STR ".align 16,0x90" #endif -#endif +#endif /* ASM_X86__LINKAGE_H */ diff --git a/include/asm-x86/local.h b/include/asm-x86/local.h index 330a72496ab..ae91994fd6c 100644 --- a/include/asm-x86/local.h +++ b/include/asm-x86/local.h @@ -1,5 +1,5 @@ -#ifndef _ARCH_LOCAL_H -#define _ARCH_LOCAL_H +#ifndef ASM_X86__LOCAL_H +#define ASM_X86__LOCAL_H #include @@ -232,4 +232,4 @@ static inline long local_sub_return(long i, local_t *l) #define __cpu_local_add(i, l) cpu_local_add((i), (l)) #define __cpu_local_sub(i, l) cpu_local_sub((i), (l)) -#endif /* _ARCH_LOCAL_H */ +#endif /* ASM_X86__LOCAL_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/mach-bigsmp/mach_apic.h index c3b9dc6970c..05362d44a3e 100644 --- a/include/asm-x86/mach-bigsmp/mach_apic.h +++ b/include/asm-x86/mach-bigsmp/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_APIC_H +#define ASM_X86__MACH_BIGSMP__MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) #define esr_disable (1) @@ -141,4 +141,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_BIGSMP__MACH_APIC_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_apicdef.h b/include/asm-x86/mach-bigsmp/mach_apicdef.h index a58ab5a75c8..811935d9d49 100644 --- a/include/asm-x86/mach-bigsmp/mach_apicdef.h +++ b/include/asm-x86/mach-bigsmp/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_APICDEF_H +#define ASM_X86__MACH_BIGSMP__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_BIGSMP__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_ipi.h b/include/asm-x86/mach-bigsmp/mach_ipi.h index 9404c535b7e..b1b0f966a00 100644 --- a/include/asm-x86/mach-bigsmp/mach_ipi.h +++ b/include/asm-x86/mach-bigsmp/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_IPI_H +#define ASM_X86__MACH_BIGSMP__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_BIGSMP__MACH_IPI_H */ diff --git a/include/asm-x86/mach-default/apm.h b/include/asm-x86/mach-default/apm.h index 989f34c37d3..2aa61b54fbd 100644 --- a/include/asm-x86/mach-default/apm.h +++ b/include/asm-x86/mach-default/apm.h @@ -3,8 +3,8 @@ * Split out from apm.c by Osamu Tomita */ -#ifndef _ASM_APM_H -#define _ASM_APM_H +#ifndef ASM_X86__MACH_DEFAULT__APM_H +#define ASM_X86__MACH_DEFAULT__APM_H #ifdef APM_ZERO_SEGS # define APM_DO_ZERO_SEGS \ @@ -70,4 +70,4 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in, return error; } -#endif /* _ASM_APM_H */ +#endif /* ASM_X86__MACH_DEFAULT__APM_H */ diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index f3226b9a6b8..b615f40736b 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_APIC_H +#define ASM_X86__MACH_DEFAULT__MACH_APIC_H #ifdef CONFIG_X86_LOCAL_APIC @@ -138,4 +138,4 @@ static inline void enable_apic_mode(void) } #endif /* CONFIG_X86_LOCAL_APIC */ -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_APIC_H */ diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h index e4b29ba37de..936704f816d 100644 --- a/include/asm-x86/mach-default/mach_apicdef.h +++ b/include/asm-x86/mach-default/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_APICDEF_H +#define ASM_X86__MACH_DEFAULT__MACH_APICDEF_H #include @@ -21,4 +21,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) #endif -#endif +#endif /* ASM_X86__MACH_DEFAULT__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-default/mach_ipi.h b/include/asm-x86/mach-default/mach_ipi.h index be323364e68..674bc7e50c3 100644 --- a/include/asm-x86/mach-default/mach_ipi.h +++ b/include/asm-x86/mach-default/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_IPI_H +#define ASM_X86__MACH_DEFAULT__MACH_IPI_H /* Avoid include hell */ #define NMI_VECTOR 0x02 @@ -61,4 +61,4 @@ static inline void send_IPI_all(int vector) } #endif -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_IPI_H */ diff --git a/include/asm-x86/mach-default/mach_mpparse.h b/include/asm-x86/mach-default/mach_mpparse.h index d14108505bb..9c381f2815a 100644 --- a/include/asm-x86/mach-default/mach_mpparse.h +++ b/include/asm-x86/mach-default/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H +#define ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) @@ -14,4 +14,4 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) } -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-default/mach_mpspec.h b/include/asm-x86/mach-default/mach_mpspec.h index 51c9a977593..d77646f011f 100644 --- a/include/asm-x86/mach-default/mach_mpspec.h +++ b/include/asm-x86/mach-default/mach_mpspec.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPSPEC_H -#define __ASM_MACH_MPSPEC_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H +#define ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H #define MAX_IRQ_SOURCES 256 @@ -9,4 +9,4 @@ #define MAX_MP_BUSSES 32 #endif -#endif /* __ASM_MACH_MPSPEC_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H */ diff --git a/include/asm-x86/mach-default/mach_timer.h b/include/asm-x86/mach-default/mach_timer.h index 4b76e536cd9..990b1583383 100644 --- a/include/asm-x86/mach-default/mach_timer.h +++ b/include/asm-x86/mach-default/mach_timer.h @@ -10,8 +10,8 @@ * directly because of the awkward 8-bit access mechanism of the 82C54 * device. */ -#ifndef _MACH_TIMER_H -#define _MACH_TIMER_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_TIMER_H +#define ASM_X86__MACH_DEFAULT__MACH_TIMER_H #define CALIBRATE_TIME_MSEC 30 /* 30 msecs */ #define CALIBRATE_LATCH \ @@ -45,4 +45,4 @@ static inline void mach_countup(unsigned long *count_p) *count_p = count; } -#endif /* !_MACH_TIMER_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_TIMER_H */ diff --git a/include/asm-x86/mach-default/mach_traps.h b/include/asm-x86/mach-default/mach_traps.h index 2fe7705c048..de9ac3f5c4c 100644 --- a/include/asm-x86/mach-default/mach_traps.h +++ b/include/asm-x86/mach-default/mach_traps.h @@ -2,8 +2,8 @@ * Machine specific NMI handling for generic. * Split out from traps.c by Osamu Tomita */ -#ifndef _MACH_TRAPS_H -#define _MACH_TRAPS_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_TRAPS_H +#define ASM_X86__MACH_DEFAULT__MACH_TRAPS_H #include @@ -36,4 +36,4 @@ static inline void reassert_nmi(void) unlock_cmos(); } -#endif /* !_MACH_TRAPS_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_TRAPS_H */ diff --git a/include/asm-x86/mach-default/mach_wakecpu.h b/include/asm-x86/mach-default/mach_wakecpu.h index 3ebb17893aa..361b810f516 100644 --- a/include/asm-x86/mach-default/mach_wakecpu.h +++ b/include/asm-x86/mach-default/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H +#define ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H /* * This file copes with machines that wakeup secondary CPUs by the @@ -39,4 +39,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} #endif -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h index 0a3fdf93067..c1f6f682d61 100644 --- a/include/asm-x86/mach-es7000/mach_apic.h +++ b/include/asm-x86/mach-es7000/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_ES7000__MACH_APIC_H +#define ASM_X86__MACH_ES7000__MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) #define esr_disable (1) @@ -191,4 +191,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_APIC_H */ diff --git a/include/asm-x86/mach-es7000/mach_apicdef.h b/include/asm-x86/mach-es7000/mach_apicdef.h index a58ab5a75c8..a07e5674402 100644 --- a/include/asm-x86/mach-es7000/mach_apicdef.h +++ b/include/asm-x86/mach-es7000/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_ES7000__MACH_APICDEF_H +#define ASM_X86__MACH_ES7000__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_ES7000__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-es7000/mach_ipi.h b/include/asm-x86/mach-es7000/mach_ipi.h index 5e61bd220b0..3a21240e03d 100644 --- a/include/asm-x86/mach-es7000/mach_ipi.h +++ b/include/asm-x86/mach-es7000/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_ES7000__MACH_IPI_H +#define ASM_X86__MACH_ES7000__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -21,4 +21,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_IPI_H */ diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/mach-es7000/mach_mpparse.h index ef26d352362..befde24705b 100644 --- a/include/asm-x86/mach-es7000/mach_mpparse.h +++ b/include/asm-x86/mach-es7000/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_ES7000__MACH_MPPARSE_H +#define ASM_X86__MACH_ES7000__MACH_MPPARSE_H #include @@ -26,4 +26,4 @@ static inline int es7000_check_dsdt(void) } #endif -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-es7000/mach_wakecpu.h b/include/asm-x86/mach-es7000/mach_wakecpu.h index 84ff5831450..97c776ce13f 100644 --- a/include/asm-x86/mach-es7000/mach_wakecpu.h +++ b/include/asm-x86/mach-es7000/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_ES7000__MACH_WAKECPU_H +#define ASM_X86__MACH_ES7000__MACH_WAKECPU_H /* * This file copes with machines that wakeup secondary CPUs by the @@ -56,4 +56,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} #endif -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-generic/gpio.h b/include/asm-x86/mach-generic/gpio.h index 5305dcb96df..6ce0f7786ef 100644 --- a/include/asm-x86/mach-generic/gpio.h +++ b/include/asm-x86/mach-generic/gpio.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_GENERIC_GPIO_H -#define __ASM_MACH_GENERIC_GPIO_H +#ifndef ASM_X86__MACH_GENERIC__GPIO_H +#define ASM_X86__MACH_GENERIC__GPIO_H int gpio_request(unsigned gpio, const char *label); void gpio_free(unsigned gpio); @@ -12,4 +12,4 @@ int irq_to_gpio(unsigned irq); #include /* cansleep wrappers */ -#endif /* __ASM_MACH_GENERIC_GPIO_H */ +#endif /* ASM_X86__MACH_GENERIC__GPIO_H */ diff --git a/include/asm-x86/mach-generic/irq_vectors_limits.h b/include/asm-x86/mach-generic/irq_vectors_limits.h index 890ce3f5e09..f7870e1a220 100644 --- a/include/asm-x86/mach-generic/irq_vectors_limits.h +++ b/include/asm-x86/mach-generic/irq_vectors_limits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_LIMITS_H -#define _ASM_IRQ_VECTORS_LIMITS_H +#ifndef ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H +#define ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H /* * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs, @@ -11,4 +11,4 @@ #define NR_IRQS 224 #define NR_IRQ_VECTORS 1024 -#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ +#endif /* ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H */ diff --git a/include/asm-x86/mach-generic/mach_apic.h b/include/asm-x86/mach-generic/mach_apic.h index 6eff343e123..5d010c6881d 100644 --- a/include/asm-x86/mach-generic/mach_apic.h +++ b/include/asm-x86/mach-generic/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_GENERIC__MACH_APIC_H +#define ASM_X86__MACH_GENERIC__MACH_APIC_H #include @@ -29,4 +29,4 @@ extern void generic_bigsmp_probe(void); -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_GENERIC__MACH_APIC_H */ diff --git a/include/asm-x86/mach-generic/mach_apicdef.h b/include/asm-x86/mach-generic/mach_apicdef.h index 28ed98972ca..1657f38b8f2 100644 --- a/include/asm-x86/mach-generic/mach_apicdef.h +++ b/include/asm-x86/mach-generic/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef _GENAPIC_MACH_APICDEF_H -#define _GENAPIC_MACH_APICDEF_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_APICDEF_H +#define ASM_X86__MACH_GENERIC__MACH_APICDEF_H #ifndef APIC_DEFINITION #include @@ -8,4 +8,4 @@ #define APIC_ID_MASK (genapic->apic_id_mask) #endif -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-generic/mach_ipi.h b/include/asm-x86/mach-generic/mach_ipi.h index 441b0fe3ed1..f67433dbd65 100644 --- a/include/asm-x86/mach-generic/mach_ipi.h +++ b/include/asm-x86/mach-generic/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef _MACH_IPI_H -#define _MACH_IPI_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_IPI_H +#define ASM_X86__MACH_GENERIC__MACH_IPI_H #include @@ -7,4 +7,4 @@ #define send_IPI_allbutself (genapic->send_IPI_allbutself) #define send_IPI_all (genapic->send_IPI_all) -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_IPI_H */ diff --git a/include/asm-x86/mach-generic/mach_mpparse.h b/include/asm-x86/mach-generic/mach_mpparse.h index 586cadbf378..3115564e557 100644 --- a/include/asm-x86/mach-generic/mach_mpparse.h +++ b/include/asm-x86/mach-generic/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef _MACH_MPPARSE_H -#define _MACH_MPPARSE_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_MPPARSE_H +#define ASM_X86__MACH_GENERIC__MACH_MPPARSE_H extern int mps_oem_check(struct mp_config_table *mpc, char *oem, @@ -7,4 +7,4 @@ extern int mps_oem_check(struct mp_config_table *mpc, char *oem, extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id); -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-generic/mach_mpspec.h b/include/asm-x86/mach-generic/mach_mpspec.h index c83c120be53..6061b153613 100644 --- a/include/asm-x86/mach-generic/mach_mpspec.h +++ b/include/asm-x86/mach-generic/mach_mpspec.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPSPEC_H -#define __ASM_MACH_MPSPEC_H +#ifndef ASM_X86__MACH_GENERIC__MACH_MPSPEC_H +#define ASM_X86__MACH_GENERIC__MACH_MPSPEC_H #define MAX_IRQ_SOURCES 256 @@ -9,4 +9,4 @@ extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); -#endif /* __ASM_MACH_MPSPEC_H */ +#endif /* ASM_X86__MACH_GENERIC__MACH_MPSPEC_H */ diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/mach-numaq/mach_apic.h index d802465e026..7a0d39edfcf 100644 --- a/include/asm-x86/mach-numaq/mach_apic.h +++ b/include/asm-x86/mach-numaq/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_APIC_H +#define ASM_X86__MACH_NUMAQ__MACH_APIC_H #include #include @@ -135,4 +135,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_APIC_H */ diff --git a/include/asm-x86/mach-numaq/mach_apicdef.h b/include/asm-x86/mach-numaq/mach_apicdef.h index bf439d0690f..f870ec5f778 100644 --- a/include/asm-x86/mach-numaq/mach_apicdef.h +++ b/include/asm-x86/mach-numaq/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_APICDEF_H +#define ASM_X86__MACH_NUMAQ__MACH_APICDEF_H #define APIC_ID_MASK (0xF<<24) @@ -11,4 +11,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_NUMAQ__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-numaq/mach_ipi.h b/include/asm-x86/mach-numaq/mach_ipi.h index c6044488e9e..1e835823f4b 100644 --- a/include/asm-x86/mach-numaq/mach_ipi.h +++ b/include/asm-x86/mach-numaq/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_IPI_H +#define ASM_X86__MACH_NUMAQ__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_IPI_H */ diff --git a/include/asm-x86/mach-numaq/mach_mpparse.h b/include/asm-x86/mach-numaq/mach_mpparse.h index 626aef6b155..74ade184920 100644 --- a/include/asm-x86/mach-numaq/mach_mpparse.h +++ b/include/asm-x86/mach-numaq/mach_mpparse.h @@ -1,7 +1,7 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H +#define ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-numaq/mach_wakecpu.h b/include/asm-x86/mach-numaq/mach_wakecpu.h index 00530041a99..0db8cea643c 100644 --- a/include/asm-x86/mach-numaq/mach_wakecpu.h +++ b/include/asm-x86/mach-numaq/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H +#define ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H /* This file copes with machines that wakeup secondary CPUs by NMIs */ @@ -40,4 +40,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h index acce0b7d397..6184561980f 100644 --- a/include/asm-x86/mach-rdc321x/gpio.h +++ b/include/asm-x86/mach-rdc321x/gpio.h @@ -1,5 +1,5 @@ -#ifndef _RDC321X_GPIO_H -#define _RDC321X_GPIO_H +#ifndef ASM_X86__MACH_RDC321X__GPIO_H +#define ASM_X86__MACH_RDC321X__GPIO_H extern int rdc_gpio_get_value(unsigned gpio); extern void rdc_gpio_set_value(unsigned gpio, int value); @@ -54,4 +54,4 @@ static inline int irq_to_gpio(unsigned irq) /* For cansleep */ #include -#endif /* _RDC321X_GPIO_H_ */ +#endif /* ASM_X86__MACH_RDC321X__GPIO_H */ diff --git a/include/asm-x86/mach-summit/irq_vectors_limits.h b/include/asm-x86/mach-summit/irq_vectors_limits.h index 890ce3f5e09..22f376ad68e 100644 --- a/include/asm-x86/mach-summit/irq_vectors_limits.h +++ b/include/asm-x86/mach-summit/irq_vectors_limits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_LIMITS_H -#define _ASM_IRQ_VECTORS_LIMITS_H +#ifndef ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H +#define ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H /* * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs, @@ -11,4 +11,4 @@ #define NR_IRQS 224 #define NR_IRQ_VECTORS 1024 -#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ +#endif /* ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H */ diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/mach-summit/mach_apic.h index 75d2c95005d..ef77af36cc9 100644 --- a/include/asm-x86/mach-summit/mach_apic.h +++ b/include/asm-x86/mach-summit/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_APIC_H +#define ASM_X86__MACH_SUMMIT__MACH_APIC_H #include @@ -182,4 +182,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return hard_smp_processor_id() >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_APIC_H */ diff --git a/include/asm-x86/mach-summit/mach_apicdef.h b/include/asm-x86/mach-summit/mach_apicdef.h index a58ab5a75c8..d4bc8590c4f 100644 --- a/include/asm-x86/mach-summit/mach_apicdef.h +++ b/include/asm-x86/mach-summit/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_APICDEF_H +#define ASM_X86__MACH_SUMMIT__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_SUMMIT__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-summit/mach_ipi.h b/include/asm-x86/mach-summit/mach_ipi.h index 9404c535b7e..a3b31c528d9 100644 --- a/include/asm-x86/mach-summit/mach_ipi.h +++ b/include/asm-x86/mach-summit/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_IPI_H +#define ASM_X86__MACH_SUMMIT__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_IPI_H */ diff --git a/include/asm-x86/mach-summit/mach_mpparse.h b/include/asm-x86/mach-summit/mach_mpparse.h index fdf59170133..92396f28772 100644 --- a/include/asm-x86/mach-summit/mach_mpparse.h +++ b/include/asm-x86/mach-summit/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H +#define ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H #include #include @@ -107,4 +107,4 @@ static inline int is_WPEG(struct rio_detail *rio){ rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); } -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H */ diff --git a/include/asm-x86/math_emu.h b/include/asm-x86/math_emu.h index 9bf4ae93ab1..5768d8e95c8 100644 --- a/include/asm-x86/math_emu.h +++ b/include/asm-x86/math_emu.h @@ -1,5 +1,5 @@ -#ifndef _I386_MATH_EMU_H -#define _I386_MATH_EMU_H +#ifndef ASM_X86__MATH_EMU_H +#define ASM_X86__MATH_EMU_H /* This structure matches the layout of the data saved to the stack following a device-not-present interrupt, part of it saved @@ -28,4 +28,4 @@ struct info { long ___vm86_fs; long ___vm86_gs; }; -#endif +#endif /* ASM_X86__MATH_EMU_H */ diff --git a/include/asm-x86/mc146818rtc.h b/include/asm-x86/mc146818rtc.h index daf1ccde77a..a995f33176c 100644 --- a/include/asm-x86/mc146818rtc.h +++ b/include/asm-x86/mc146818rtc.h @@ -1,8 +1,8 @@ /* * Machine dependent access functions for RTC registers. */ -#ifndef _ASM_MC146818RTC_H -#define _ASM_MC146818RTC_H +#ifndef ASM_X86__MC146818RTC_H +#define ASM_X86__MC146818RTC_H #include #include @@ -101,4 +101,4 @@ extern unsigned long mach_get_cmos_time(void); #define RTC_IRQ 8 -#endif /* _ASM_MC146818RTC_H */ +#endif /* ASM_X86__MC146818RTC_H */ diff --git a/include/asm-x86/mca.h b/include/asm-x86/mca.h index 09adf2eac4d..60d1ed287b1 100644 --- a/include/asm-x86/mca.h +++ b/include/asm-x86/mca.h @@ -1,8 +1,8 @@ /* -*- mode: c; c-basic-offset: 8 -*- */ /* Platform specific MCA defines */ -#ifndef _ASM_MCA_H -#define _ASM_MCA_H +#ifndef ASM_X86__MCA_H +#define ASM_X86__MCA_H /* Maximal number of MCA slots - actually, some machines have less, but * they all have sufficient number of POS registers to cover 8. @@ -40,4 +40,4 @@ */ #define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3) -#endif +#endif /* ASM_X86__MCA_H */ diff --git a/include/asm-x86/mca_dma.h b/include/asm-x86/mca_dma.h index c3dca6edc6b..49f22be237d 100644 --- a/include/asm-x86/mca_dma.h +++ b/include/asm-x86/mca_dma.h @@ -1,5 +1,5 @@ -#ifndef MCA_DMA_H -#define MCA_DMA_H +#ifndef ASM_X86__MCA_DMA_H +#define ASM_X86__MCA_DMA_H #include #include @@ -198,4 +198,4 @@ static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode) outb(mode, MCA_DMA_REG_EXE); } -#endif /* MCA_DMA_H */ +#endif /* ASM_X86__MCA_DMA_H */ diff --git a/include/asm-x86/mce.h b/include/asm-x86/mce.h index 94f1fd79e22..6a580f24d4a 100644 --- a/include/asm-x86/mce.h +++ b/include/asm-x86/mce.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MCE_H -#define _ASM_X86_MCE_H +#ifndef ASM_X86__MCE_H +#define ASM_X86__MCE_H #ifdef __x86_64__ @@ -126,4 +126,4 @@ extern void restart_mce(void); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__MCE_H */ diff --git a/include/asm-x86/mman.h b/include/asm-x86/mman.h index c1682b542da..b6b41aa1cbc 100644 --- a/include/asm-x86/mman.h +++ b/include/asm-x86/mman.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MMAN_H -#define _ASM_X86_MMAN_H +#ifndef ASM_X86__MMAN_H +#define ASM_X86__MMAN_H #include @@ -16,4 +16,4 @@ #define MCL_CURRENT 1 /* lock all current mappings */ #define MCL_FUTURE 2 /* lock all future mappings */ -#endif /* _ASM_X86_MMAN_H */ +#endif /* ASM_X86__MMAN_H */ diff --git a/include/asm-x86/mmconfig.h b/include/asm-x86/mmconfig.h index 95beda07c6f..8689f1e7bc0 100644 --- a/include/asm-x86/mmconfig.h +++ b/include/asm-x86/mmconfig.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MMCONFIG_H -#define _ASM_MMCONFIG_H +#ifndef ASM_X86__MMCONFIG_H +#define ASM_X86__MMCONFIG_H #ifdef CONFIG_PCI_MMCONFIG extern void __cpuinit fam10h_check_enable_mmcfg(void); @@ -9,4 +9,4 @@ static inline void fam10h_check_enable_mmcfg(void) { } static inline void check_enable_amd_mmconf_dmi(void) { } #endif -#endif +#endif /* ASM_X86__MMCONFIG_H */ diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h index 00e88679e11..a30d7a9c829 100644 --- a/include/asm-x86/mmu.h +++ b/include/asm-x86/mmu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MMU_H -#define _ASM_X86_MMU_H +#ifndef ASM_X86__MMU_H +#define ASM_X86__MMU_H #include #include @@ -28,4 +28,4 @@ static inline void leave_mm(int cpu) } #endif -#endif /* _ASM_X86_MMU_H */ +#endif /* ASM_X86__MMU_H */ diff --git a/include/asm-x86/mmu_context.h b/include/asm-x86/mmu_context.h index fac57014e7c..8ec940bfd07 100644 --- a/include/asm-x86/mmu_context.h +++ b/include/asm-x86/mmu_context.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_MMU_CONTEXT_H -#define __ASM_X86_MMU_CONTEXT_H +#ifndef ASM_X86__MMU_CONTEXT_H +#define ASM_X86__MMU_CONTEXT_H #include #include @@ -34,4 +34,4 @@ do { \ } while (0); -#endif /* __ASM_X86_MMU_CONTEXT_H */ +#endif /* ASM_X86__MMU_CONTEXT_H */ diff --git a/include/asm-x86/mmu_context_32.h b/include/asm-x86/mmu_context_32.h index 824fc575c6d..cce6f6e4afd 100644 --- a/include/asm-x86/mmu_context_32.h +++ b/include/asm-x86/mmu_context_32.h @@ -1,5 +1,5 @@ -#ifndef __I386_SCHED_H -#define __I386_SCHED_H +#ifndef ASM_X86__MMU_CONTEXT_32_H +#define ASM_X86__MMU_CONTEXT_32_H static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { @@ -53,4 +53,4 @@ static inline void switch_mm(struct mm_struct *prev, #define deactivate_mm(tsk, mm) \ asm("movl %0,%%gs": :"r" (0)); -#endif +#endif /* ASM_X86__MMU_CONTEXT_32_H */ diff --git a/include/asm-x86/mmu_context_64.h b/include/asm-x86/mmu_context_64.h index c7000634cca..26758673c82 100644 --- a/include/asm-x86/mmu_context_64.h +++ b/include/asm-x86/mmu_context_64.h @@ -1,5 +1,5 @@ -#ifndef __X86_64_MMU_CONTEXT_H -#define __X86_64_MMU_CONTEXT_H +#ifndef ASM_X86__MMU_CONTEXT_64_H +#define ASM_X86__MMU_CONTEXT_64_H #include @@ -51,4 +51,4 @@ do { \ asm volatile("movl %0,%%fs"::"r"(0)); \ } while (0) -#endif +#endif /* ASM_X86__MMU_CONTEXT_64_H */ diff --git a/include/asm-x86/mmx.h b/include/asm-x86/mmx.h index 940881218ff..2e7299bb365 100644 --- a/include/asm-x86/mmx.h +++ b/include/asm-x86/mmx.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MMX_H -#define _ASM_MMX_H +#ifndef ASM_X86__MMX_H +#define ASM_X86__MMX_H /* * MMX 3Dnow! helper operations @@ -11,4 +11,4 @@ extern void *_mmx_memcpy(void *to, const void *from, size_t size); extern void mmx_clear_page(void *page); extern void mmx_copy_page(void *to, void *from); -#endif +#endif /* ASM_X86__MMX_H */ diff --git a/include/asm-x86/mmzone_32.h b/include/asm-x86/mmzone_32.h index b2298a22756..b98590fdc9e 100644 --- a/include/asm-x86/mmzone_32.h +++ b/include/asm-x86/mmzone_32.h @@ -3,8 +3,8 @@ * */ -#ifndef _ASM_MMZONE_H_ -#define _ASM_MMZONE_H_ +#ifndef ASM_X86__MMZONE_32_H +#define ASM_X86__MMZONE_32_H #include @@ -125,4 +125,4 @@ static inline int pfn_valid(int pfn) }) #endif /* CONFIG_NEED_MULTIPLE_NODES */ -#endif /* _ASM_MMZONE_H_ */ +#endif /* ASM_X86__MMZONE_32_H */ diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h index 594bd0dc1d0..626b03a1487 100644 --- a/include/asm-x86/mmzone_64.h +++ b/include/asm-x86/mmzone_64.h @@ -1,8 +1,8 @@ /* K8 NUMA support */ /* Copyright 2002,2003 by Andi Kleen, SuSE Labs */ /* 2.5 Version loosely based on the NUMAQ Code by Pat Gaughen. */ -#ifndef _ASM_X86_64_MMZONE_H -#define _ASM_X86_64_MMZONE_H 1 +#ifndef ASM_X86__MMZONE_64_H +#define ASM_X86__MMZONE_64_H #ifdef CONFIG_NUMA @@ -49,4 +49,4 @@ extern int early_pfn_to_nid(unsigned long pfn); #endif #endif -#endif +#endif /* ASM_X86__MMZONE_64_H */ diff --git a/include/asm-x86/module.h b/include/asm-x86/module.h index bfedb247871..48dc3e0c07d 100644 --- a/include/asm-x86/module.h +++ b/include/asm-x86/module.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MODULE_H -#define _ASM_MODULE_H +#ifndef ASM_X86__MODULE_H +#define ASM_X86__MODULE_H /* x86_32/64 are simple */ struct mod_arch_specific {}; @@ -79,4 +79,4 @@ struct mod_arch_specific {}; # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE #endif -#endif /* _ASM_MODULE_H */ +#endif /* ASM_X86__MODULE_H */ diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h index b6995e567fc..118da365e37 100644 --- a/include/asm-x86/mpspec.h +++ b/include/asm-x86/mpspec.h @@ -1,5 +1,5 @@ -#ifndef _AM_X86_MPSPEC_H -#define _AM_X86_MPSPEC_H +#ifndef ASM_X86__MPSPEC_H +#define ASM_X86__MPSPEC_H #include @@ -141,4 +141,4 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map) extern physid_mask_t phys_cpu_present_map; -#endif +#endif /* ASM_X86__MPSPEC_H */ diff --git a/include/asm-x86/mpspec_def.h b/include/asm-x86/mpspec_def.h index 38d1e73b49e..79166b04801 100644 --- a/include/asm-x86/mpspec_def.h +++ b/include/asm-x86/mpspec_def.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MPSPEC_DEF_H -#define __ASM_MPSPEC_DEF_H +#ifndef ASM_X86__MPSPEC_DEF_H +#define ASM_X86__MPSPEC_DEF_H /* * Structure definitions for SMP machines following the @@ -177,4 +177,4 @@ enum mp_bustype { MP_BUS_PCI, MP_BUS_MCA, }; -#endif +#endif /* ASM_X86__MPSPEC_DEF_H */ diff --git a/include/asm-x86/msgbuf.h b/include/asm-x86/msgbuf.h index 7e4e9481f51..1b538c907a3 100644 --- a/include/asm-x86/msgbuf.h +++ b/include/asm-x86/msgbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MSGBUF_H -#define _ASM_X86_MSGBUF_H +#ifndef ASM_X86__MSGBUF_H +#define ASM_X86__MSGBUF_H /* * The msqid64_ds structure for i386 architecture. @@ -36,4 +36,4 @@ struct msqid64_ds { unsigned long __unused5; }; -#endif /* _ASM_X86_MSGBUF_H */ +#endif /* ASM_X86__MSGBUF_H */ diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h index 296f29ce426..3139666a94f 100644 --- a/include/asm-x86/msidef.h +++ b/include/asm-x86/msidef.h @@ -1,5 +1,5 @@ -#ifndef ASM_MSIDEF_H -#define ASM_MSIDEF_H +#ifndef ASM_X86__MSIDEF_H +#define ASM_X86__MSIDEF_H /* * Constants for Intel APIC based MSI messages. @@ -48,4 +48,4 @@ #define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ MSI_ADDR_DEST_ID_MASK) -#endif /* ASM_MSIDEF_H */ +#endif /* ASM_X86__MSIDEF_H */ diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h index 44bce773012..3052f058ab0 100644 --- a/include/asm-x86/msr-index.h +++ b/include/asm-x86/msr-index.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MSR_INDEX_H -#define __ASM_MSR_INDEX_H +#ifndef ASM_X86__MSR_INDEX_H +#define ASM_X86__MSR_INDEX_H /* CPU model specific register (MSR) numbers */ @@ -310,4 +310,4 @@ /* Geode defined MSRs */ #define MSR_GEODE_BUSCONT_CONF0 0x00001900 -#endif /* __ASM_MSR_INDEX_H */ +#endif /* ASM_X86__MSR_INDEX_H */ diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index ca110ee73f0..032992035bd 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_MSR_H_ -#define __ASM_X86_MSR_H_ +#ifndef ASM_X86__MSR_H +#define ASM_X86__MSR_H #include @@ -220,4 +220,4 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__MSR_H */ diff --git a/include/asm-x86/mtrr.h b/include/asm-x86/mtrr.h index a69a01a5172..23a7f83da95 100644 --- a/include/asm-x86/mtrr.h +++ b/include/asm-x86/mtrr.h @@ -20,8 +20,8 @@ The postal address is: Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. */ -#ifndef _ASM_X86_MTRR_H -#define _ASM_X86_MTRR_H +#ifndef ASM_X86__MTRR_H +#define ASM_X86__MTRR_H #include #include @@ -170,4 +170,4 @@ struct mtrr_gentry32 { #endif /* __KERNEL__ */ -#endif /* _ASM_X86_MTRR_H */ +#endif /* ASM_X86__MTRR_H */ diff --git a/include/asm-x86/mutex_32.h b/include/asm-x86/mutex_32.h index 73e928ef5f0..25c16d8ba3c 100644 --- a/include/asm-x86/mutex_32.h +++ b/include/asm-x86/mutex_32.h @@ -6,8 +6,8 @@ * * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar */ -#ifndef _ASM_MUTEX_H -#define _ASM_MUTEX_H +#ifndef ASM_X86__MUTEX_32_H +#define ASM_X86__MUTEX_32_H #include @@ -122,4 +122,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, #endif } -#endif +#endif /* ASM_X86__MUTEX_32_H */ diff --git a/include/asm-x86/mutex_64.h b/include/asm-x86/mutex_64.h index f3fae9becb3..918ba21ab9d 100644 --- a/include/asm-x86/mutex_64.h +++ b/include/asm-x86/mutex_64.h @@ -6,8 +6,8 @@ * * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar */ -#ifndef _ASM_MUTEX_H -#define _ASM_MUTEX_H +#ifndef ASM_X86__MUTEX_64_H +#define ASM_X86__MUTEX_64_H /** * __mutex_fastpath_lock - decrement and call function if negative @@ -97,4 +97,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, return 0; } -#endif +#endif /* ASM_X86__MUTEX_64_H */ diff --git a/include/asm-x86/namei.h b/include/asm-x86/namei.h index 415ef5d9550..6e5de58c10c 100644 --- a/include/asm-x86/namei.h +++ b/include/asm-x86/namei.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_NAMEI_H -#define _ASM_X86_NAMEI_H +#ifndef ASM_X86__NAMEI_H +#define ASM_X86__NAMEI_H /* This dummy routine maybe changed to something useful * for /usr/gnemul/ emulation stuff. @@ -8,4 +8,4 @@ #define __emul_prefix() NULL -#endif /* _ASM_X86_NAMEI_H */ +#endif /* ASM_X86__NAMEI_H */ diff --git a/include/asm-x86/nmi.h b/include/asm-x86/nmi.h index 21f8d0202a8..f8b76f38390 100644 --- a/include/asm-x86/nmi.h +++ b/include/asm-x86/nmi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_NMI_H_ -#define _ASM_X86_NMI_H_ +#ifndef ASM_X86__NMI_H +#define ASM_X86__NMI_H #include #include @@ -81,4 +81,4 @@ void enable_lapic_nmi_watchdog(void); void stop_nmi(void); void restart_nmi(void); -#endif +#endif /* ASM_X86__NMI_H */ diff --git a/include/asm-x86/nops.h b/include/asm-x86/nops.h index ad0bedd10b8..ae742721ae7 100644 --- a/include/asm-x86/nops.h +++ b/include/asm-x86/nops.h @@ -1,5 +1,5 @@ -#ifndef _ASM_NOPS_H -#define _ASM_NOPS_H 1 +#ifndef ASM_X86__NOPS_H +#define ASM_X86__NOPS_H /* Define nops for use with alternative() */ @@ -115,4 +115,4 @@ #define ASM_NOP_MAX 8 -#endif +#endif /* ASM_X86__NOPS_H */ diff --git a/include/asm-x86/numa_32.h b/include/asm-x86/numa_32.h index 220d7b7707a..44cb07855c5 100644 --- a/include/asm-x86/numa_32.h +++ b/include/asm-x86/numa_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_32_NUMA_H -#define _ASM_X86_32_NUMA_H 1 +#ifndef ASM_X86__NUMA_32_H +#define ASM_X86__NUMA_32_H extern int pxm_to_nid(int pxm); extern void numa_remove_cpu(int cpu); @@ -8,4 +8,4 @@ extern void numa_remove_cpu(int cpu); extern void set_highmem_pages_init(void); #endif -#endif /* _ASM_X86_32_NUMA_H */ +#endif /* ASM_X86__NUMA_32_H */ diff --git a/include/asm-x86/numa_64.h b/include/asm-x86/numa_64.h index 3830094434a..15c990395b0 100644 --- a/include/asm-x86/numa_64.h +++ b/include/asm-x86/numa_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_NUMA_H -#define _ASM_X8664_NUMA_H 1 +#ifndef ASM_X86__NUMA_64_H +#define ASM_X86__NUMA_64_H #include #include @@ -40,4 +40,4 @@ static inline void numa_add_cpu(int cpu, int node) { } static inline void numa_remove_cpu(int cpu) { } #endif -#endif +#endif /* ASM_X86__NUMA_64_H */ diff --git a/include/asm-x86/numaq.h b/include/asm-x86/numaq.h index 34b92d581fa..124bf7d4b70 100644 --- a/include/asm-x86/numaq.h +++ b/include/asm-x86/numaq.h @@ -23,8 +23,8 @@ * Send feedback to */ -#ifndef NUMAQ_H -#define NUMAQ_H +#ifndef ASM_X86__NUMAQ_H +#define ASM_X86__NUMAQ_H #ifdef CONFIG_X86_NUMAQ @@ -165,5 +165,5 @@ static inline int get_memcfg_numaq(void) return 0; } #endif /* CONFIG_X86_NUMAQ */ -#endif /* NUMAQ_H */ +#endif /* ASM_X86__NUMAQ_H */ diff --git a/include/asm-x86/olpc.h b/include/asm-x86/olpc.h index 97d47133486..d7328b1a05c 100644 --- a/include/asm-x86/olpc.h +++ b/include/asm-x86/olpc.h @@ -1,7 +1,7 @@ /* OLPC machine specific definitions */ -#ifndef ASM_OLPC_H_ -#define ASM_OLPC_H_ +#ifndef ASM_X86__OLPC_H +#define ASM_X86__OLPC_H #include @@ -129,4 +129,4 @@ extern int olpc_ec_mask_unset(uint8_t bits); #define OLPC_GPIO_LID geode_gpio(26) #define OLPC_GPIO_ECSCI geode_gpio(27) -#endif +#endif /* ASM_X86__OLPC_H */ diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h index 28d7b4533b1..068a636e0bb 100644 --- a/include/asm-x86/page.h +++ b/include/asm-x86/page.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PAGE_H -#define _ASM_X86_PAGE_H +#ifndef ASM_X86__PAGE_H +#define ASM_X86__PAGE_H #include @@ -192,4 +192,4 @@ static inline pteval_t native_pte_val(pte_t pte) #define __HAVE_ARCH_GATE_AREA 1 #endif /* __KERNEL__ */ -#endif /* _ASM_X86_PAGE_H */ +#endif /* ASM_X86__PAGE_H */ diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index ab8528793f0..85ac2b8ec7c 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PAGE_32_H -#define _ASM_X86_PAGE_32_H +#ifndef ASM_X86__PAGE_32_H +#define ASM_X86__PAGE_32_H /* * This handles the memory map. @@ -126,4 +126,4 @@ static inline void copy_page(void *to, void *from) #endif /* CONFIG_X86_3DNOW */ #endif /* !__ASSEMBLY__ */ -#endif /* _ASM_X86_PAGE_32_H */ +#endif /* ASM_X86__PAGE_32_H */ diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h index c6916c83e6b..87aef3c48b5 100644 --- a/include/asm-x86/page_64.h +++ b/include/asm-x86/page_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_PAGE_H -#define _X86_64_PAGE_H +#ifndef ASM_X86__PAGE_64_H +#define ASM_X86__PAGE_64_H #define PAGETABLE_LEVELS 4 @@ -102,4 +102,4 @@ extern void init_extra_mapping_wb(unsigned long phys, unsigned long size); #endif -#endif /* _X86_64_PAGE_H */ +#endif /* ASM_X86__PAGE_64_H */ diff --git a/include/asm-x86/param.h b/include/asm-x86/param.h index 6f0d0422f4c..0009cfb11a5 100644 --- a/include/asm-x86/param.h +++ b/include/asm-x86/param.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PARAM_H -#define _ASM_X86_PARAM_H +#ifndef ASM_X86__PARAM_H +#define ASM_X86__PARAM_H #ifdef __KERNEL__ # define HZ CONFIG_HZ /* Internal kernel timer frequency */ @@ -19,4 +19,4 @@ #define MAXHOSTNAMELEN 64 /* max length of hostname */ -#endif /* _ASM_X86_PARAM_H */ +#endif /* ASM_X86__PARAM_H */ diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index aec9767836b..1b7eff0b41b 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -1,5 +1,5 @@ -#ifndef __ASM_PARAVIRT_H -#define __ASM_PARAVIRT_H +#ifndef ASM_X86__PARAVIRT_H +#define ASM_X86__PARAVIRT_H /* Various instructions on x86 need to be replaced for * para-virtualization: those hooks are defined here. */ @@ -1631,4 +1631,4 @@ static inline unsigned long __raw_local_irq_save(void) #endif /* __ASSEMBLY__ */ #endif /* CONFIG_PARAVIRT */ -#endif /* __ASM_PARAVIRT_H */ +#endif /* ASM_X86__PARAVIRT_H */ diff --git a/include/asm-x86/parport.h b/include/asm-x86/parport.h index 3c4ffeb467e..2e3dda4dc3d 100644 --- a/include/asm-x86/parport.h +++ b/include/asm-x86/parport.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PARPORT_H -#define _ASM_X86_PARPORT_H +#ifndef ASM_X86__PARPORT_H +#define ASM_X86__PARPORT_H static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma); static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma) @@ -7,4 +7,4 @@ static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma) return parport_pc_find_isa_ports(autoirq, autodma); } -#endif /* _ASM_X86_PARPORT_H */ +#endif /* ASM_X86__PARPORT_H */ diff --git a/include/asm-x86/pat.h b/include/asm-x86/pat.h index 7edc4730721..482c3e3f987 100644 --- a/include/asm-x86/pat.h +++ b/include/asm-x86/pat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_PAT_H -#define _ASM_PAT_H +#ifndef ASM_X86__PAT_H +#define ASM_X86__PAT_H #include @@ -19,4 +19,4 @@ extern int free_memtype(u64 start, u64 end); extern void pat_disable(char *reason); -#endif +#endif /* ASM_X86__PAT_H */ diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h index 80c775d9fe2..da42be07b69 100644 --- a/include/asm-x86/pci-direct.h +++ b/include/asm-x86/pci-direct.h @@ -1,5 +1,5 @@ -#ifndef ASM_PCI_DIRECT_H -#define ASM_PCI_DIRECT_H 1 +#ifndef ASM_X86__PCI_DIRECT_H +#define ASM_X86__PCI_DIRECT_H #include @@ -18,4 +18,4 @@ extern int early_pci_allowed(void); extern unsigned int pci_early_dump_regs; extern void early_dump_pci_device(u8 bus, u8 slot, u8 func); extern void early_dump_pci_devices(void); -#endif +#endif /* ASM_X86__PCI_DIRECT_H */ diff --git a/include/asm-x86/pci.h b/include/asm-x86/pci.h index 2db14cf17db..60258319299 100644 --- a/include/asm-x86/pci.h +++ b/include/asm-x86/pci.h @@ -1,5 +1,5 @@ -#ifndef __x86_PCI_H -#define __x86_PCI_H +#ifndef ASM_X86__PCI_H +#define ASM_X86__PCI_H #include /* for struct page */ #include @@ -111,4 +111,4 @@ static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus) } #endif -#endif +#endif /* ASM_X86__PCI_H */ diff --git a/include/asm-x86/pci_32.h b/include/asm-x86/pci_32.h index a50d4685128..3f2288207c0 100644 --- a/include/asm-x86/pci_32.h +++ b/include/asm-x86/pci_32.h @@ -1,5 +1,5 @@ -#ifndef __i386_PCI_H -#define __i386_PCI_H +#ifndef ASM_X86__PCI_32_H +#define ASM_X86__PCI_32_H #ifdef __KERNEL__ @@ -31,4 +31,4 @@ struct pci_dev; #endif /* __KERNEL__ */ -#endif /* __i386_PCI_H */ +#endif /* ASM_X86__PCI_32_H */ diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index f330234ffa5..f72e12d5770 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h @@ -1,5 +1,5 @@ -#ifndef __x8664_PCI_H -#define __x8664_PCI_H +#ifndef ASM_X86__PCI_64_H +#define ASM_X86__PCI_64_H #ifdef __KERNEL__ @@ -63,4 +63,4 @@ extern void pci_iommu_alloc(void); #endif /* __KERNEL__ */ -#endif /* __x8664_PCI_H */ +#endif /* ASM_X86__PCI_64_H */ diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h index b34e9a7cc80..80860afffbd 100644 --- a/include/asm-x86/pda.h +++ b/include/asm-x86/pda.h @@ -1,5 +1,5 @@ -#ifndef X86_64_PDA_H -#define X86_64_PDA_H +#ifndef ASM_X86__PDA_H +#define ASM_X86__PDA_H #ifndef __ASSEMBLY__ #include @@ -134,4 +134,4 @@ do { \ #define PDA_STACKOFFSET (5*8) -#endif +#endif /* ASM_X86__PDA_H */ diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h index 4e91ee1e37a..0afc8324807 100644 --- a/include/asm-x86/percpu.h +++ b/include/asm-x86/percpu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PERCPU_H_ -#define _ASM_X86_PERCPU_H_ +#ifndef ASM_X86__PERCPU_H +#define ASM_X86__PERCPU_H #ifdef CONFIG_X86_64 #include @@ -215,4 +215,4 @@ do { \ #endif /* !CONFIG_SMP */ -#endif /* _ASM_X86_PERCPU_H_ */ +#endif /* ASM_X86__PERCPU_H */ diff --git a/include/asm-x86/pgalloc.h b/include/asm-x86/pgalloc.h index d63ea431cb3..3cd23adedae 100644 --- a/include/asm-x86/pgalloc.h +++ b/include/asm-x86/pgalloc.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PGALLOC_H -#define _ASM_X86_PGALLOC_H +#ifndef ASM_X86__PGALLOC_H +#define ASM_X86__PGALLOC_H #include #include /* for struct page */ @@ -111,4 +111,4 @@ extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud); #endif /* PAGETABLE_LEVELS > 3 */ #endif /* PAGETABLE_LEVELS > 2 */ -#endif /* _ASM_X86_PGALLOC_H */ +#endif /* ASM_X86__PGALLOC_H */ diff --git a/include/asm-x86/pgtable-2level-defs.h b/include/asm-x86/pgtable-2level-defs.h index 0f71c9f13da..7ec48f4e534 100644 --- a/include/asm-x86/pgtable-2level-defs.h +++ b/include/asm-x86/pgtable-2level-defs.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_2LEVEL_DEFS_H -#define _I386_PGTABLE_2LEVEL_DEFS_H +#ifndef ASM_X86__PGTABLE_2LEVEL_DEFS_H +#define ASM_X86__PGTABLE_2LEVEL_DEFS_H #define SHARED_KERNEL_PMD 0 @@ -17,4 +17,4 @@ #define PTRS_PER_PTE 1024 -#endif /* _I386_PGTABLE_2LEVEL_DEFS_H */ +#endif /* ASM_X86__PGTABLE_2LEVEL_DEFS_H */ diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h index 46bc52c0eae..60440b19162 100644 --- a/include/asm-x86/pgtable-2level.h +++ b/include/asm-x86/pgtable-2level.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_2LEVEL_H -#define _I386_PGTABLE_2LEVEL_H +#ifndef ASM_X86__PGTABLE_2LEVEL_H +#define ASM_X86__PGTABLE_2LEVEL_H #define pte_ERROR(e) \ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low) @@ -78,4 +78,4 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) -#endif /* _I386_PGTABLE_2LEVEL_H */ +#endif /* ASM_X86__PGTABLE_2LEVEL_H */ diff --git a/include/asm-x86/pgtable-3level-defs.h b/include/asm-x86/pgtable-3level-defs.h index 448ac951631..c05fe6ff372 100644 --- a/include/asm-x86/pgtable-3level-defs.h +++ b/include/asm-x86/pgtable-3level-defs.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_3LEVEL_DEFS_H -#define _I386_PGTABLE_3LEVEL_DEFS_H +#ifndef ASM_X86__PGTABLE_3LEVEL_DEFS_H +#define ASM_X86__PGTABLE_3LEVEL_DEFS_H #ifdef CONFIG_PARAVIRT #define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd) @@ -25,4 +25,4 @@ */ #define PTRS_PER_PTE 512 -#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */ +#endif /* ASM_X86__PGTABLE_3LEVEL_DEFS_H */ diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h index c93dbb6c262..a9ad971a733 100644 --- a/include/asm-x86/pgtable-3level.h +++ b/include/asm-x86/pgtable-3level.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_3LEVEL_H -#define _I386_PGTABLE_3LEVEL_H +#ifndef ASM_X86__PGTABLE_3LEVEL_H +#define ASM_X86__PGTABLE_3LEVEL_H /* * Intel Physical Address Extension (PAE) Mode - three-level page @@ -179,4 +179,4 @@ static inline unsigned long pte_pfn(pte_t pte) #define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) #define __swp_entry_to_pte(x) ((pte_t){ { .pte_high = (x).val } }) -#endif /* _I386_PGTABLE_3LEVEL_H */ +#endif /* ASM_X86__PGTABLE_3LEVEL_H */ diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 96aa76e691d..b8d7c530054 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PGTABLE_H -#define _ASM_X86_PGTABLE_H +#ifndef ASM_X86__PGTABLE_H +#define ASM_X86__PGTABLE_H #define FIRST_USER_ADDRESS 0 @@ -518,4 +518,4 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) #include #endif /* __ASSEMBLY__ */ -#endif /* _ASM_X86_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_H */ diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h index 0611abf96a5..4fa3b046e1b 100644 --- a/include/asm-x86/pgtable_32.h +++ b/include/asm-x86/pgtable_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_H -#define _I386_PGTABLE_H +#ifndef ASM_X86__PGTABLE_32_H +#define ASM_X86__PGTABLE_32_H /* @@ -186,4 +186,4 @@ do { \ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot) -#endif /* _I386_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_32_H */ diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h index 805d3128bfc..b80c0d7658c 100644 --- a/include/asm-x86/pgtable_64.h +++ b/include/asm-x86/pgtable_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_PGTABLE_H -#define _X86_64_PGTABLE_H +#ifndef ASM_X86__PGTABLE_64_H +#define ASM_X86__PGTABLE_64_H #include #ifndef __ASSEMBLY__ @@ -284,4 +284,4 @@ extern void cleanup_highmap(void); #define __HAVE_ARCH_PTE_SAME #endif /* !__ASSEMBLY__ */ -#endif /* _X86_64_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_64_H */ diff --git a/include/asm-x86/posix_types_32.h b/include/asm-x86/posix_types_32.h index b031efda37e..70cf2bb0593 100644 --- a/include/asm-x86/posix_types_32.h +++ b/include/asm-x86/posix_types_32.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_I386_POSIX_TYPES_H -#define __ARCH_I386_POSIX_TYPES_H +#ifndef ASM_X86__POSIX_TYPES_32_H +#define ASM_X86__POSIX_TYPES_32_H /* * This file is generally used by user-level software, so you need to @@ -82,4 +82,4 @@ do { \ #endif /* defined(__KERNEL__) */ -#endif +#endif /* ASM_X86__POSIX_TYPES_32_H */ diff --git a/include/asm-x86/posix_types_64.h b/include/asm-x86/posix_types_64.h index d6624c95854..388b4e7f4a4 100644 --- a/include/asm-x86/posix_types_64.h +++ b/include/asm-x86/posix_types_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_POSIX_TYPES_H -#define _ASM_X86_64_POSIX_TYPES_H +#ifndef ASM_X86__POSIX_TYPES_64_H +#define ASM_X86__POSIX_TYPES_64_H /* * This file is generally used by user-level software, so you need to @@ -116,4 +116,4 @@ static inline void __FD_ZERO(__kernel_fd_set *p) #endif /* defined(__KERNEL__) */ -#endif +#endif /* ASM_X86__POSIX_TYPES_64_H */ diff --git a/include/asm-x86/prctl.h b/include/asm-x86/prctl.h index 52952adef1c..e7ae34eb410 100644 --- a/include/asm-x86/prctl.h +++ b/include/asm-x86/prctl.h @@ -1,5 +1,5 @@ -#ifndef X86_64_PRCTL_H -#define X86_64_PRCTL_H 1 +#ifndef ASM_X86__PRCTL_H +#define ASM_X86__PRCTL_H #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 @@ -7,4 +7,4 @@ #define ARCH_GET_GS 0x1004 -#endif +#endif /* ASM_X86__PRCTL_H */ diff --git a/include/asm-x86/processor-flags.h b/include/asm-x86/processor-flags.h index 092b39b3a7e..ae1d434f197 100644 --- a/include/asm-x86/processor-flags.h +++ b/include/asm-x86/processor-flags.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I386_PROCESSOR_FLAGS_H -#define __ASM_I386_PROCESSOR_FLAGS_H +#ifndef ASM_X86__PROCESSOR_FLAGS_H +#define ASM_X86__PROCESSOR_FLAGS_H /* Various flags defined: can be included from assembler. */ /* @@ -94,4 +94,4 @@ #define X86_VM_MASK 0 /* No VM86 support */ #endif -#endif /* __ASM_I386_PROCESSOR_FLAGS_H */ +#endif /* ASM_X86__PROCESSOR_FLAGS_H */ diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 15cb82a44e8..a9a28baef69 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_PROCESSOR_H -#define __ASM_X86_PROCESSOR_H +#ifndef ASM_X86__PROCESSOR_H +#define ASM_X86__PROCESSOR_H #include @@ -920,4 +920,4 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, extern int get_tsc_mode(unsigned long adr); extern int set_tsc_mode(unsigned int val); -#endif +#endif /* ASM_X86__PROCESSOR_H */ diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h index 3dd458c385c..6e89e8b4de0 100644 --- a/include/asm-x86/proto.h +++ b/include/asm-x86/proto.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_PROTO_H -#define _ASM_X8664_PROTO_H 1 +#ifndef ASM_X86__PROTO_H +#define ASM_X86__PROTO_H #include @@ -29,4 +29,4 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); #define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1)) #define round_down(x, y) ((x) & ~((y) - 1)) -#endif +#endif /* ASM_X86__PROTO_H */ diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h index 72e7b9db29b..d0cf3344a58 100644 --- a/include/asm-x86/ptrace-abi.h +++ b/include/asm-x86/ptrace-abi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PTRACE_ABI_H -#define _ASM_X86_PTRACE_ABI_H +#ifndef ASM_X86__PTRACE_ABI_H +#define ASM_X86__PTRACE_ABI_H #ifdef __i386__ @@ -140,4 +140,4 @@ struct ptrace_bts_config { Returns number of BTS records drained. */ -#endif +#endif /* ASM_X86__PTRACE_ABI_H */ diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 8a71db803da..d464f252edc 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PTRACE_H -#define _ASM_X86_PTRACE_H +#ifndef ASM_X86__PTRACE_H +#define ASM_X86__PTRACE_H #include /* For __user */ #include @@ -239,4 +239,4 @@ extern int do_set_thread_area(struct task_struct *p, int idx, #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__PTRACE_H */ diff --git a/include/asm-x86/pvclock-abi.h b/include/asm-x86/pvclock-abi.h index 6857f840b24..edb3b4ecfc8 100644 --- a/include/asm-x86/pvclock-abi.h +++ b/include/asm-x86/pvclock-abi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PVCLOCK_ABI_H_ -#define _ASM_X86_PVCLOCK_ABI_H_ +#ifndef ASM_X86__PVCLOCK_ABI_H +#define ASM_X86__PVCLOCK_ABI_H #ifndef __ASSEMBLY__ /* @@ -39,4 +39,4 @@ struct pvclock_wall_clock { } __attribute__((__packed__)); #endif /* __ASSEMBLY__ */ -#endif /* _ASM_X86_PVCLOCK_ABI_H_ */ +#endif /* ASM_X86__PVCLOCK_ABI_H */ diff --git a/include/asm-x86/pvclock.h b/include/asm-x86/pvclock.h index 85b1bba8e0a..1a38f683480 100644 --- a/include/asm-x86/pvclock.h +++ b/include/asm-x86/pvclock.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PVCLOCK_H_ -#define _ASM_X86_PVCLOCK_H_ +#ifndef ASM_X86__PVCLOCK_H +#define ASM_X86__PVCLOCK_H #include #include @@ -10,4 +10,4 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall, struct pvclock_vcpu_time_info *vcpu, struct timespec *ts); -#endif /* _ASM_X86_PVCLOCK_H_ */ +#endif /* ASM_X86__PVCLOCK_H */ diff --git a/include/asm-x86/reboot.h b/include/asm-x86/reboot.h index 206f355786d..1c2f0ce9e31 100644 --- a/include/asm-x86/reboot.h +++ b/include/asm-x86/reboot.h @@ -1,5 +1,5 @@ -#ifndef _ASM_REBOOT_H -#define _ASM_REBOOT_H +#ifndef ASM_X86__REBOOT_H +#define ASM_X86__REBOOT_H struct pt_regs; @@ -18,4 +18,4 @@ void native_machine_crash_shutdown(struct pt_regs *regs); void native_machine_shutdown(void); void machine_real_restart(const unsigned char *code, int length); -#endif /* _ASM_REBOOT_H */ +#endif /* ASM_X86__REBOOT_H */ diff --git a/include/asm-x86/reboot_fixups.h b/include/asm-x86/reboot_fixups.h index 0cb7d87c2b6..2c2987d9757 100644 --- a/include/asm-x86/reboot_fixups.h +++ b/include/asm-x86/reboot_fixups.h @@ -1,6 +1,6 @@ -#ifndef _LINUX_REBOOT_FIXUPS_H -#define _LINUX_REBOOT_FIXUPS_H +#ifndef ASM_X86__REBOOT_FIXUPS_H +#define ASM_X86__REBOOT_FIXUPS_H extern void mach_reboot_fixups(void); -#endif /* _LINUX_REBOOT_FIXUPS_H */ +#endif /* ASM_X86__REBOOT_FIXUPS_H */ diff --git a/include/asm-x86/required-features.h b/include/asm-x86/required-features.h index adec887dd7c..d6822e099c5 100644 --- a/include/asm-x86/required-features.h +++ b/include/asm-x86/required-features.h @@ -1,5 +1,5 @@ -#ifndef _ASM_REQUIRED_FEATURES_H -#define _ASM_REQUIRED_FEATURES_H 1 +#ifndef ASM_X86__REQUIRED_FEATURES_H +#define ASM_X86__REQUIRED_FEATURES_H /* Define minimum CPUID feature set for kernel These bits are checked really early to actually display a visible error message before the @@ -73,4 +73,4 @@ #define REQUIRED_MASK6 0 #define REQUIRED_MASK7 0 -#endif +#endif /* ASM_X86__REQUIRED_FEATURES_H */ diff --git a/include/asm-x86/resume-trace.h b/include/asm-x86/resume-trace.h index 8d9f0b41ee8..519a8ecbfc9 100644 --- a/include/asm-x86/resume-trace.h +++ b/include/asm-x86/resume-trace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_RESUME_TRACE_H -#define _ASM_X86_RESUME_TRACE_H +#ifndef ASM_X86__RESUME_TRACE_H +#define ASM_X86__RESUME_TRACE_H #include @@ -18,4 +18,4 @@ do { \ } \ } while (0) -#endif +#endif /* ASM_X86__RESUME_TRACE_H */ diff --git a/include/asm-x86/rio.h b/include/asm-x86/rio.h index c9448bd8968..5e1256bdee8 100644 --- a/include/asm-x86/rio.h +++ b/include/asm-x86/rio.h @@ -5,8 +5,8 @@ * Author: Laurent Vivier */ -#ifndef __ASM_RIO_H -#define __ASM_RIO_H +#ifndef ASM_X86__RIO_H +#define ASM_X86__RIO_H #define RIO_TABLE_VERSION 3 @@ -60,4 +60,4 @@ enum { ALT_CALGARY = 5, /* Second Planar Calgary */ }; -#endif /* __ASM_RIO_H */ +#endif /* ASM_X86__RIO_H */ diff --git a/include/asm-x86/rwlock.h b/include/asm-x86/rwlock.h index 6a8c0d64510..48a3109e1a7 100644 --- a/include/asm-x86/rwlock.h +++ b/include/asm-x86/rwlock.h @@ -1,8 +1,8 @@ -#ifndef _ASM_X86_RWLOCK_H -#define _ASM_X86_RWLOCK_H +#ifndef ASM_X86__RWLOCK_H +#define ASM_X86__RWLOCK_H #define RW_LOCK_BIAS 0x01000000 /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */ -#endif /* _ASM_X86_RWLOCK_H */ +#endif /* ASM_X86__RWLOCK_H */ diff --git a/include/asm-x86/rwsem.h b/include/asm-x86/rwsem.h index 750f2a3542b..3ff3015b71a 100644 --- a/include/asm-x86/rwsem.h +++ b/include/asm-x86/rwsem.h @@ -29,8 +29,8 @@ * front, then they'll all be woken up, but no other readers will be. */ -#ifndef _I386_RWSEM_H -#define _I386_RWSEM_H +#ifndef ASM_X86__RWSEM_H +#define ASM_X86__RWSEM_H #ifndef _LINUX_RWSEM_H #error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" @@ -262,4 +262,4 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) } #endif /* __KERNEL__ */ -#endif /* _I386_RWSEM_H */ +#endif /* ASM_X86__RWSEM_H */ diff --git a/include/asm-x86/scatterlist.h b/include/asm-x86/scatterlist.h index c0432061f81..ee48f880005 100644 --- a/include/asm-x86/scatterlist.h +++ b/include/asm-x86/scatterlist.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SCATTERLIST_H -#define _ASM_X86_SCATTERLIST_H +#ifndef ASM_X86__SCATTERLIST_H +#define ASM_X86__SCATTERLIST_H #include @@ -30,4 +30,4 @@ struct scatterlist { # define sg_dma_len(sg) ((sg)->dma_length) #endif -#endif +#endif /* ASM_X86__SCATTERLIST_H */ diff --git a/include/asm-x86/seccomp_32.h b/include/asm-x86/seccomp_32.h index 36e71c5f306..cf9ab2dbcef 100644 --- a/include/asm-x86/seccomp_32.h +++ b/include/asm-x86/seccomp_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SECCOMP_H -#define _ASM_SECCOMP_H +#ifndef ASM_X86__SECCOMP_32_H +#define ASM_X86__SECCOMP_32_H #include @@ -14,4 +14,4 @@ #define __NR_seccomp_exit __NR_exit #define __NR_seccomp_sigreturn __NR_sigreturn -#endif /* _ASM_SECCOMP_H */ +#endif /* ASM_X86__SECCOMP_32_H */ diff --git a/include/asm-x86/seccomp_64.h b/include/asm-x86/seccomp_64.h index 76cfe69aa63..03274cea751 100644 --- a/include/asm-x86/seccomp_64.h +++ b/include/asm-x86/seccomp_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SECCOMP_H -#define _ASM_SECCOMP_H +#ifndef ASM_X86__SECCOMP_64_H +#define ASM_X86__SECCOMP_64_H #include @@ -22,4 +22,4 @@ #define __NR_seccomp_exit_32 __NR_ia32_exit #define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn -#endif /* _ASM_SECCOMP_H */ +#endif /* ASM_X86__SECCOMP_64_H */ diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h index 646452ea9ea..ea5f0a8686f 100644 --- a/include/asm-x86/segment.h +++ b/include/asm-x86/segment.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SEGMENT_H_ -#define _ASM_X86_SEGMENT_H_ +#ifndef ASM_X86__SEGMENT_H +#define ASM_X86__SEGMENT_H /* Constructor for a conventional segment GDT (or LDT) entry */ /* This is a macro so it can be used in initializers */ @@ -212,4 +212,4 @@ extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10]; #endif #endif -#endif +#endif /* ASM_X86__SEGMENT_H */ diff --git a/include/asm-x86/sembuf.h b/include/asm-x86/sembuf.h index ee50c801f7b..81f06b7e5a3 100644 --- a/include/asm-x86/sembuf.h +++ b/include/asm-x86/sembuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SEMBUF_H -#define _ASM_X86_SEMBUF_H +#ifndef ASM_X86__SEMBUF_H +#define ASM_X86__SEMBUF_H /* * The semid64_ds structure for x86 architecture. @@ -21,4 +21,4 @@ struct semid64_ds { unsigned long __unused4; }; -#endif /* _ASM_X86_SEMBUF_H */ +#endif /* ASM_X86__SEMBUF_H */ diff --git a/include/asm-x86/serial.h b/include/asm-x86/serial.h index 628c801535e..303660b671e 100644 --- a/include/asm-x86/serial.h +++ b/include/asm-x86/serial.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SERIAL_H -#define _ASM_X86_SERIAL_H +#ifndef ASM_X86__SERIAL_H +#define ASM_X86__SERIAL_H /* * This assumes you have a 1.8432 MHz clock for your UART. @@ -26,4 +26,4 @@ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ -#endif /* _ASM_X86_SERIAL_H */ +#endif /* ASM_X86__SERIAL_H */ diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h index a07c6f1c01e..b7aeba94e43 100644 --- a/include/asm-x86/setup.h +++ b/include/asm-x86/setup.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SETUP_H -#define _ASM_X86_SETUP_H +#ifndef ASM_X86__SETUP_H +#define ASM_X86__SETUP_H #define COMMAND_LINE_SIZE 2048 @@ -100,4 +100,4 @@ void __init x86_64_start_reservations(char *real_mode_data); #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ -#endif /* _ASM_X86_SETUP_H */ +#endif /* ASM_X86__SETUP_H */ diff --git a/include/asm-x86/shmbuf.h b/include/asm-x86/shmbuf.h index b51413b7497..f51aec2298e 100644 --- a/include/asm-x86/shmbuf.h +++ b/include/asm-x86/shmbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SHMBUF_H -#define _ASM_X86_SHMBUF_H +#ifndef ASM_X86__SHMBUF_H +#define ASM_X86__SHMBUF_H /* * The shmid64_ds structure for x86 architecture. @@ -48,4 +48,4 @@ struct shminfo64 { unsigned long __unused4; }; -#endif /* _ASM_X86_SHMBUF_H */ +#endif /* ASM_X86__SHMBUF_H */ diff --git a/include/asm-x86/shmparam.h b/include/asm-x86/shmparam.h index 0880cf0917b..a83a1fd96a0 100644 --- a/include/asm-x86/shmparam.h +++ b/include/asm-x86/shmparam.h @@ -1,6 +1,6 @@ -#ifndef _ASM_X86_SHMPARAM_H -#define _ASM_X86_SHMPARAM_H +#ifndef ASM_X86__SHMPARAM_H +#define ASM_X86__SHMPARAM_H #define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ -#endif /* _ASM_X86_SHMPARAM_H */ +#endif /* ASM_X86__SHMPARAM_H */ diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h index 2f9c884d2c0..24879c85b29 100644 --- a/include/asm-x86/sigcontext.h +++ b/include/asm-x86/sigcontext.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGCONTEXT_H -#define _ASM_X86_SIGCONTEXT_H +#ifndef ASM_X86__SIGCONTEXT_H +#define ASM_X86__SIGCONTEXT_H #include #include @@ -202,4 +202,4 @@ struct sigcontext { #endif /* !__i386__ */ -#endif +#endif /* ASM_X86__SIGCONTEXT_H */ diff --git a/include/asm-x86/sigcontext32.h b/include/asm-x86/sigcontext32.h index 57a9686fb49..4e2ec732dd0 100644 --- a/include/asm-x86/sigcontext32.h +++ b/include/asm-x86/sigcontext32.h @@ -1,5 +1,5 @@ -#ifndef _SIGCONTEXT32_H -#define _SIGCONTEXT32_H 1 +#ifndef ASM_X86__SIGCONTEXT32_H +#define ASM_X86__SIGCONTEXT32_H /* signal context for 32bit programs. */ @@ -68,4 +68,4 @@ struct sigcontext_ia32 { unsigned int cr2; }; -#endif +#endif /* ASM_X86__SIGCONTEXT32_H */ diff --git a/include/asm-x86/siginfo.h b/include/asm-x86/siginfo.h index a477bea0c2a..808bdfb2958 100644 --- a/include/asm-x86/siginfo.h +++ b/include/asm-x86/siginfo.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGINFO_H -#define _ASM_X86_SIGINFO_H +#ifndef ASM_X86__SIGINFO_H +#define ASM_X86__SIGINFO_H #ifdef __x86_64__ # define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) @@ -7,4 +7,4 @@ #include -#endif +#endif /* ASM_X86__SIGINFO_H */ diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h index 6dac49364e9..6ee32822779 100644 --- a/include/asm-x86/signal.h +++ b/include/asm-x86/signal.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGNAL_H -#define _ASM_X86_SIGNAL_H +#ifndef ASM_X86__SIGNAL_H +#define ASM_X86__SIGNAL_H #ifndef __ASSEMBLY__ #include @@ -256,4 +256,4 @@ struct pt_regs; #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__SIGNAL_H */ diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 3c877f74f27..cd3c5f03fca 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SMP_H_ -#define _ASM_X86_SMP_H_ +#ifndef ASM_X86__SMP_H +#define ASM_X86__SMP_H #ifndef __ASSEMBLY__ #include #include @@ -205,4 +205,4 @@ extern void cpu_uninit(void); #endif #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__SMP_H */ diff --git a/include/asm-x86/socket.h b/include/asm-x86/socket.h index 80af9c4ccad..db73274c83c 100644 --- a/include/asm-x86/socket.h +++ b/include/asm-x86/socket.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H +#ifndef ASM_X86__SOCKET_H +#define ASM_X86__SOCKET_H #include @@ -54,4 +54,4 @@ #define SO_MARK 36 -#endif /* _ASM_SOCKET_H */ +#endif /* ASM_X86__SOCKET_H */ diff --git a/include/asm-x86/sockios.h b/include/asm-x86/sockios.h index 49cc72b5d3c..a006704fdc8 100644 --- a/include/asm-x86/sockios.h +++ b/include/asm-x86/sockios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SOCKIOS_H -#define _ASM_X86_SOCKIOS_H +#ifndef ASM_X86__SOCKIOS_H +#define ASM_X86__SOCKIOS_H /* Socket-level I/O control calls. */ #define FIOSETOWN 0x8901 @@ -10,4 +10,4 @@ #define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ #define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ -#endif /* _ASM_X86_SOCKIOS_H */ +#endif /* ASM_X86__SOCKIOS_H */ diff --git a/include/asm-x86/sparsemem.h b/include/asm-x86/sparsemem.h index 9bd48b0a534..38f8e6bc318 100644 --- a/include/asm-x86/sparsemem.h +++ b/include/asm-x86/sparsemem.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SPARSEMEM_H -#define _ASM_X86_SPARSEMEM_H +#ifndef ASM_X86__SPARSEMEM_H +#define ASM_X86__SPARSEMEM_H #ifdef CONFIG_SPARSEMEM /* @@ -31,4 +31,4 @@ #endif #endif /* CONFIG_SPARSEMEM */ -#endif +#endif /* ASM_X86__SPARSEMEM_H */ diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h index 4f9a9861799..cbe01086ba6 100644 --- a/include/asm-x86/spinlock.h +++ b/include/asm-x86/spinlock.h @@ -1,5 +1,5 @@ -#ifndef _X86_SPINLOCK_H_ -#define _X86_SPINLOCK_H_ +#ifndef ASM_X86__SPINLOCK_H +#define ASM_X86__SPINLOCK_H #include #include @@ -366,4 +366,4 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) #define _raw_read_relax(lock) cpu_relax() #define _raw_write_relax(lock) cpu_relax() -#endif +#endif /* ASM_X86__SPINLOCK_H */ diff --git a/include/asm-x86/spinlock_types.h b/include/asm-x86/spinlock_types.h index 06c071c9eee..6aa9b562c50 100644 --- a/include/asm-x86/spinlock_types.h +++ b/include/asm-x86/spinlock_types.h @@ -1,5 +1,5 @@ -#ifndef __ASM_SPINLOCK_TYPES_H -#define __ASM_SPINLOCK_TYPES_H +#ifndef ASM_X86__SPINLOCK_TYPES_H +#define ASM_X86__SPINLOCK_TYPES_H #ifndef __LINUX_SPINLOCK_TYPES_H # error "please don't include this file directly" @@ -17,4 +17,4 @@ typedef struct { #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } -#endif +#endif /* ASM_X86__SPINLOCK_TYPES_H */ diff --git a/include/asm-x86/srat.h b/include/asm-x86/srat.h index 774c919dc23..5363e4f7e1c 100644 --- a/include/asm-x86/srat.h +++ b/include/asm-x86/srat.h @@ -24,8 +24,8 @@ * Send feedback to Pat Gaughen */ -#ifndef _ASM_SRAT_H_ -#define _ASM_SRAT_H_ +#ifndef ASM_X86__SRAT_H +#define ASM_X86__SRAT_H #ifdef CONFIG_ACPI_NUMA extern int get_memcfg_from_srat(void); @@ -36,4 +36,4 @@ static inline int get_memcfg_from_srat(void) } #endif -#endif /* _ASM_SRAT_H_ */ +#endif /* ASM_X86__SRAT_H */ diff --git a/include/asm-x86/stacktrace.h b/include/asm-x86/stacktrace.h index 30f82526a8e..f43517e2853 100644 --- a/include/asm-x86/stacktrace.h +++ b/include/asm-x86/stacktrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_STACKTRACE_H -#define _ASM_STACKTRACE_H 1 +#ifndef ASM_X86__STACKTRACE_H +#define ASM_X86__STACKTRACE_H extern int kstack_depth_to_print; @@ -18,4 +18,4 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data); -#endif +#endif /* ASM_X86__STACKTRACE_H */ diff --git a/include/asm-x86/stat.h b/include/asm-x86/stat.h index 5c22dcb5d17..1e120f62890 100644 --- a/include/asm-x86/stat.h +++ b/include/asm-x86/stat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_STAT_H -#define _ASM_X86_STAT_H +#ifndef ASM_X86__STAT_H +#define ASM_X86__STAT_H #define STAT_HAVE_NSEC 1 @@ -111,4 +111,4 @@ struct __old_kernel_stat { #endif }; -#endif +#endif /* ASM_X86__STAT_H */ diff --git a/include/asm-x86/statfs.h b/include/asm-x86/statfs.h index 7c651aa9725..3f005bc3aa5 100644 --- a/include/asm-x86/statfs.h +++ b/include/asm-x86/statfs.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_STATFS_H -#define _ASM_X86_STATFS_H +#ifndef ASM_X86__STATFS_H +#define ASM_X86__STATFS_H #ifdef __i386__ #include @@ -60,4 +60,4 @@ struct compat_statfs64 { } __attribute__((packed)); #endif /* !__i386__ */ -#endif +#endif /* ASM_X86__STATFS_H */ diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h index 193578cd1fd..487843ed245 100644 --- a/include/asm-x86/string_32.h +++ b/include/asm-x86/string_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_STRING_H_ -#define _I386_STRING_H_ +#ifndef ASM_X86__STRING_32_H +#define ASM_X86__STRING_32_H #ifdef __KERNEL__ @@ -323,4 +323,4 @@ extern void *memscan(void *addr, int c, size_t size); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__STRING_32_H */ diff --git a/include/asm-x86/string_64.h b/include/asm-x86/string_64.h index 52b5ab38339..a2add11d3b6 100644 --- a/include/asm-x86/string_64.h +++ b/include/asm-x86/string_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_STRING_H_ -#define _X86_64_STRING_H_ +#ifndef ASM_X86__STRING_64_H +#define ASM_X86__STRING_64_H #ifdef __KERNEL__ @@ -57,4 +57,4 @@ int strcmp(const char *cs, const char *ct); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__STRING_64_H */ diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h index 8675c6782a7..acb6d4d491f 100644 --- a/include/asm-x86/suspend_32.h +++ b/include/asm-x86/suspend_32.h @@ -3,8 +3,8 @@ * Based on code * Copyright 2001 Patrick Mochel */ -#ifndef __ASM_X86_32_SUSPEND_H -#define __ASM_X86_32_SUSPEND_H +#ifndef ASM_X86__SUSPEND_32_H +#define ASM_X86__SUSPEND_32_H #include #include @@ -48,4 +48,4 @@ static inline void acpi_save_register_state(unsigned long return_point) extern int acpi_save_state_mem(void); #endif -#endif /* __ASM_X86_32_SUSPEND_H */ +#endif /* ASM_X86__SUSPEND_32_H */ diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h index dc3262b4307..cf821dd310e 100644 --- a/include/asm-x86/suspend_64.h +++ b/include/asm-x86/suspend_64.h @@ -3,8 +3,8 @@ * Based on code * Copyright 2001 Patrick Mochel */ -#ifndef __ASM_X86_64_SUSPEND_H -#define __ASM_X86_64_SUSPEND_H +#ifndef ASM_X86__SUSPEND_64_H +#define ASM_X86__SUSPEND_64_H #include #include @@ -49,4 +49,4 @@ extern int acpi_save_state_mem(void); extern char core_restore_code; extern char restore_registers; -#endif /* __ASM_X86_64_SUSPEND_H */ +#endif /* ASM_X86__SUSPEND_64_H */ diff --git a/include/asm-x86/swiotlb.h b/include/asm-x86/swiotlb.h index c706a744263..9486c400a71 100644 --- a/include/asm-x86/swiotlb.h +++ b/include/asm-x86/swiotlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SWIOTLB_H -#define _ASM_SWIOTLB_H 1 +#ifndef ASM_X86__SWIOTLB_H +#define ASM_X86__SWIOTLB_H #include @@ -55,4 +55,4 @@ static inline void pci_swiotlb_init(void) static inline void dma_mark_clean(void *addr, size_t size) {} -#endif /* _ASM_SWIOTLB_H */ +#endif /* ASM_X86__SWIOTLB_H */ diff --git a/include/asm-x86/sync_bitops.h b/include/asm-x86/sync_bitops.h index b47a1d0b8a8..b689bee7110 100644 --- a/include/asm-x86/sync_bitops.h +++ b/include/asm-x86/sync_bitops.h @@ -1,5 +1,5 @@ -#ifndef _I386_SYNC_BITOPS_H -#define _I386_SYNC_BITOPS_H +#ifndef ASM_X86__SYNC_BITOPS_H +#define ASM_X86__SYNC_BITOPS_H /* * Copyright 1992, Linus Torvalds. @@ -127,4 +127,4 @@ static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr) #undef ADDR -#endif /* _I386_SYNC_BITOPS_H */ +#endif /* ASM_X86__SYNC_BITOPS_H */ diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h index 983ce37c491..34505dd7b24 100644 --- a/include/asm-x86/system.h +++ b/include/asm-x86/system.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SYSTEM_H_ -#define _ASM_X86_SYSTEM_H_ +#ifndef ASM_X86__SYSTEM_H +#define ASM_X86__SYSTEM_H #include #include @@ -419,4 +419,4 @@ static inline void rdtsc_barrier(void) alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); } -#endif +#endif /* ASM_X86__SYSTEM_H */ diff --git a/include/asm-x86/system_64.h b/include/asm-x86/system_64.h index 97fa251ccb2..5aedb8bffc5 100644 --- a/include/asm-x86/system_64.h +++ b/include/asm-x86/system_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_SYSTEM_H -#define __ASM_SYSTEM_H +#ifndef ASM_X86__SYSTEM_64_H +#define ASM_X86__SYSTEM_64_H #include #include @@ -19,4 +19,4 @@ static inline void write_cr8(unsigned long val) #include -#endif +#endif /* ASM_X86__SYSTEM_64_H */ diff --git a/include/asm-x86/tce.h b/include/asm-x86/tce.h index b1a4ea00df7..e7932d7fbba 100644 --- a/include/asm-x86/tce.h +++ b/include/asm-x86/tce.h @@ -21,8 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_64_TCE_H -#define _ASM_X86_64_TCE_H +#ifndef ASM_X86__TCE_H +#define ASM_X86__TCE_H extern unsigned int specified_table_size; struct iommu_table; @@ -45,4 +45,4 @@ extern void * __init alloc_tce_table(void); extern void __init free_tce_table(void *tbl); extern int __init build_tce_table(struct pci_dev *dev, void __iomem *bbar); -#endif /* _ASM_X86_64_TCE_H */ +#endif /* ASM_X86__TCE_H */ diff --git a/include/asm-x86/termbits.h b/include/asm-x86/termbits.h index af1b70ea440..3d00dc5e0c7 100644 --- a/include/asm-x86/termbits.h +++ b/include/asm-x86/termbits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TERMBITS_H -#define _ASM_X86_TERMBITS_H +#ifndef ASM_X86__TERMBITS_H +#define ASM_X86__TERMBITS_H #include @@ -195,4 +195,4 @@ struct ktermios { #define TCSADRAIN 1 #define TCSAFLUSH 2 -#endif /* _ASM_X86_TERMBITS_H */ +#endif /* ASM_X86__TERMBITS_H */ diff --git a/include/asm-x86/termios.h b/include/asm-x86/termios.h index f72956331c4..e235db24807 100644 --- a/include/asm-x86/termios.h +++ b/include/asm-x86/termios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TERMIOS_H -#define _ASM_X86_TERMIOS_H +#ifndef ASM_X86__TERMIOS_H +#define ASM_X86__TERMIOS_H #include #include @@ -110,4 +110,4 @@ static inline int kernel_termios_to_user_termios_1(struct termios __user *u, #endif /* __KERNEL__ */ -#endif /* _ASM_X86_TERMIOS_H */ +#endif /* ASM_X86__TERMIOS_H */ diff --git a/include/asm-x86/therm_throt.h b/include/asm-x86/therm_throt.h index 399bf6026b1..1c7f57b6b66 100644 --- a/include/asm-x86/therm_throt.h +++ b/include/asm-x86/therm_throt.h @@ -1,9 +1,9 @@ -#ifndef __ASM_I386_THERM_THROT_H__ -#define __ASM_I386_THERM_THROT_H__ 1 +#ifndef ASM_X86__THERM_THROT_H +#define ASM_X86__THERM_THROT_H #include extern atomic_t therm_throt_en; int therm_throt_process(int curr); -#endif /* __ASM_I386_THERM_THROT_H__ */ +#endif /* ASM_X86__THERM_THROT_H */ diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h index 0a8f27d31d0..50315a5dd18 100644 --- a/include/asm-x86/thread_info.h +++ b/include/asm-x86/thread_info.h @@ -4,8 +4,8 @@ * - Incorporating suggestions made by Linus Torvalds and Dave Miller */ -#ifndef _ASM_X86_THREAD_INFO_H -#define _ASM_X86_THREAD_INFO_H +#ifndef ASM_X86__THREAD_INFO_H +#define ASM_X86__THREAD_INFO_H #include #include @@ -258,4 +258,4 @@ extern void free_thread_info(struct thread_info *ti); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); #define arch_task_cache_init arch_task_cache_init #endif -#endif /* _ASM_X86_THREAD_INFO_H */ +#endif /* ASM_X86__THREAD_INFO_H */ diff --git a/include/asm-x86/time.h b/include/asm-x86/time.h index a17fa473e91..7457a5d7b4a 100644 --- a/include/asm-x86/time.h +++ b/include/asm-x86/time.h @@ -1,5 +1,5 @@ -#ifndef _ASMX86_TIME_H -#define _ASMX86_TIME_H +#ifndef ASM_X86__TIME_H +#define ASM_X86__TIME_H extern void hpet_time_init(void); @@ -58,4 +58,4 @@ static inline int native_set_wallclock(unsigned long nowtime) extern unsigned long __init calibrate_cpu(void); -#endif +#endif /* ASM_X86__TIME_H */ diff --git a/include/asm-x86/timer.h b/include/asm-x86/timer.h index fb2a4ddddf3..b87123dec3d 100644 --- a/include/asm-x86/timer.h +++ b/include/asm-x86/timer.h @@ -1,5 +1,5 @@ -#ifndef _ASMi386_TIMER_H -#define _ASMi386_TIMER_H +#ifndef ASM_X86__TIMER_H +#define ASM_X86__TIMER_H #include #include #include @@ -60,4 +60,4 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) return ns; } -#endif +#endif /* ASM_X86__TIMER_H */ diff --git a/include/asm-x86/timex.h b/include/asm-x86/timex.h index 43e5a78500c..d1ce2416a5d 100644 --- a/include/asm-x86/timex.h +++ b/include/asm-x86/timex.h @@ -1,6 +1,6 @@ /* x86 architecture timex specifications */ -#ifndef _ASM_X86_TIMEX_H -#define _ASM_X86_TIMEX_H +#ifndef ASM_X86__TIMEX_H +#define ASM_X86__TIMEX_H #include #include @@ -16,4 +16,4 @@ #define ARCH_HAS_READ_CURRENT_TIMER -#endif +#endif /* ASM_X86__TIMEX_H */ diff --git a/include/asm-x86/tlb.h b/include/asm-x86/tlb.h index e4e9e2d07a9..db36e9e89e8 100644 --- a/include/asm-x86/tlb.h +++ b/include/asm-x86/tlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TLB_H -#define _ASM_X86_TLB_H +#ifndef ASM_X86__TLB_H +#define ASM_X86__TLB_H #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) @@ -8,4 +8,4 @@ #include -#endif +#endif /* ASM_X86__TLB_H */ diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h index 35c76ceb9f4..ef68b76dc3c 100644 --- a/include/asm-x86/tlbflush.h +++ b/include/asm-x86/tlbflush.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TLBFLUSH_H -#define _ASM_X86_TLBFLUSH_H +#ifndef ASM_X86__TLBFLUSH_H +#define ASM_X86__TLBFLUSH_H #include #include @@ -165,4 +165,4 @@ static inline void flush_tlb_kernel_range(unsigned long start, flush_tlb_all(); } -#endif /* _ASM_X86_TLBFLUSH_H */ +#endif /* ASM_X86__TLBFLUSH_H */ diff --git a/include/asm-x86/topology.h b/include/asm-x86/topology.h index 90ac7718469..7eca9bc022b 100644 --- a/include/asm-x86/topology.h +++ b/include/asm-x86/topology.h @@ -22,8 +22,8 @@ * * Send feedback to */ -#ifndef _ASM_X86_TOPOLOGY_H -#define _ASM_X86_TOPOLOGY_H +#ifndef ASM_X86__TOPOLOGY_H +#define ASM_X86__TOPOLOGY_H #ifdef CONFIG_X86_32 # ifdef CONFIG_X86_HT @@ -255,4 +255,4 @@ static inline void set_mp_bus_to_node(int busnum, int node) } #endif -#endif /* _ASM_X86_TOPOLOGY_H */ +#endif /* ASM_X86__TOPOLOGY_H */ diff --git a/include/asm-x86/trampoline.h b/include/asm-x86/trampoline.h index b156b08d013..0406bbd898a 100644 --- a/include/asm-x86/trampoline.h +++ b/include/asm-x86/trampoline.h @@ -1,5 +1,5 @@ -#ifndef __TRAMPOLINE_HEADER -#define __TRAMPOLINE_HEADER +#ifndef ASM_X86__TRAMPOLINE_H +#define ASM_X86__TRAMPOLINE_H #ifndef __ASSEMBLY__ @@ -18,4 +18,4 @@ extern unsigned long setup_trampoline(void); #endif /* __ASSEMBLY__ */ -#endif /* __TRAMPOLINE_HEADER */ +#endif /* ASM_X86__TRAMPOLINE_H */ diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h index a4b65a71bd6..2a891a70471 100644 --- a/include/asm-x86/traps.h +++ b/include/asm-x86/traps.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TRAPS_H -#define _ASM_X86_TRAPS_H +#ifndef ASM_X86__TRAPS_H +#define ASM_X86__TRAPS_H /* Common in X86_32 and X86_64 */ asmlinkage void divide_error(void); @@ -63,4 +63,4 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *); asmlinkage void do_spurious_interrupt_bug(struct pt_regs *); #endif /* CONFIG_X86_32 */ -#endif /* _ASM_X86_TRAPS_H */ +#endif /* ASM_X86__TRAPS_H */ diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h index cb6f6ee45b8..ad0f5c41e78 100644 --- a/include/asm-x86/tsc.h +++ b/include/asm-x86/tsc.h @@ -1,8 +1,8 @@ /* * x86 TSC related functions */ -#ifndef _ASM_X86_TSC_H -#define _ASM_X86_TSC_H +#ifndef ASM_X86__TSC_H +#define ASM_X86__TSC_H #include @@ -59,4 +59,4 @@ extern void check_tsc_sync_target(void); extern int notsc_setup(char *); -#endif +#endif /* ASM_X86__TSC_H */ diff --git a/include/asm-x86/types.h b/include/asm-x86/types.h index 1ac80cd9acf..e78b52e1744 100644 --- a/include/asm-x86/types.h +++ b/include/asm-x86/types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TYPES_H -#define _ASM_X86_TYPES_H +#ifndef ASM_X86__TYPES_H +#define ASM_X86__TYPES_H #include @@ -33,4 +33,4 @@ typedef u32 dma_addr_t; #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__TYPES_H */ diff --git a/include/asm-x86/uaccess.h b/include/asm-x86/uaccess.h index f6fa4d841bb..1838f3959a5 100644 --- a/include/asm-x86/uaccess.h +++ b/include/asm-x86/uaccess.h @@ -1,5 +1,5 @@ -#ifndef _ASM_UACCES_H_ -#define _ASM_UACCES_H_ +#ifndef ASM_X86__UACCESS_H +#define ASM_X86__UACCESS_H /* * User space memory access functions */ @@ -450,4 +450,4 @@ extern struct movsl_mask { # include "uaccess_64.h" #endif -#endif +#endif /* ASM_X86__UACCESS_H */ diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h index 6fdef39a0bc..6b5b57d9c6d 100644 --- a/include/asm-x86/uaccess_32.h +++ b/include/asm-x86/uaccess_32.h @@ -1,5 +1,5 @@ -#ifndef __i386_UACCESS_H -#define __i386_UACCESS_H +#ifndef ASM_X86__UACCESS_32_H +#define ASM_X86__UACCESS_32_H /* * User space memory access functions @@ -215,4 +215,4 @@ long strnlen_user(const char __user *str, long n); unsigned long __must_check clear_user(void __user *mem, unsigned long len); unsigned long __must_check __clear_user(void __user *mem, unsigned long len); -#endif /* __i386_UACCESS_H */ +#endif /* ASM_X86__UACCESS_32_H */ diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h index 515d4dce96b..5cfd2951c9e 100644 --- a/include/asm-x86/uaccess_64.h +++ b/include/asm-x86/uaccess_64.h @@ -1,5 +1,5 @@ -#ifndef __X86_64_UACCESS_H -#define __X86_64_UACCESS_H +#ifndef ASM_X86__UACCESS_64_H +#define ASM_X86__UACCESS_64_H /* * User space memory access functions @@ -198,4 +198,4 @@ static inline int __copy_from_user_inatomic_nocache(void *dst, unsigned long copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest); -#endif /* __X86_64_UACCESS_H */ +#endif /* ASM_X86__UACCESS_64_H */ diff --git a/include/asm-x86/ucontext.h b/include/asm-x86/ucontext.h index 50a79f7fcde..9948dd32808 100644 --- a/include/asm-x86/ucontext.h +++ b/include/asm-x86/ucontext.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UCONTEXT_H -#define _ASM_X86_UCONTEXT_H +#ifndef ASM_X86__UCONTEXT_H +#define ASM_X86__UCONTEXT_H struct ucontext { unsigned long uc_flags; @@ -9,4 +9,4 @@ struct ucontext { sigset_t uc_sigmask; /* mask last for extensibility */ }; -#endif /* _ASM_X86_UCONTEXT_H */ +#endif /* ASM_X86__UCONTEXT_H */ diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h index a7bd416b476..59dcdec3716 100644 --- a/include/asm-x86/unaligned.h +++ b/include/asm-x86/unaligned.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNALIGNED_H -#define _ASM_X86_UNALIGNED_H +#ifndef ASM_X86__UNALIGNED_H +#define ASM_X86__UNALIGNED_H /* * The x86 can do unaligned accesses itself. @@ -11,4 +11,4 @@ #define get_unaligned __get_unaligned_le #define put_unaligned __put_unaligned_le -#endif /* _ASM_X86_UNALIGNED_H */ +#endif /* ASM_X86__UNALIGNED_H */ diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h index 8317d94771d..602ddd88c68 100644 --- a/include/asm-x86/unistd_32.h +++ b/include/asm-x86/unistd_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_I386_UNISTD_H_ -#define _ASM_I386_UNISTD_H_ +#ifndef ASM_X86__UNISTD_32_H +#define ASM_X86__UNISTD_32_H /* * This file contains the system call numbers. @@ -370,4 +370,4 @@ #endif #endif /* __KERNEL__ */ -#endif /* _ASM_I386_UNISTD_H_ */ +#endif /* ASM_X86__UNISTD_32_H */ diff --git a/include/asm-x86/unwind.h b/include/asm-x86/unwind.h index 8b064bd9c55..a2151567db4 100644 --- a/include/asm-x86/unwind.h +++ b/include/asm-x86/unwind.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNWIND_H -#define _ASM_X86_UNWIND_H +#ifndef ASM_X86__UNWIND_H +#define ASM_X86__UNWIND_H #define UNW_PC(frame) ((void)(frame), 0UL) #define UNW_SP(frame) ((void)(frame), 0UL) @@ -10,4 +10,4 @@ static inline int arch_unw_user_mode(const void *info) return 0; } -#endif /* _ASM_X86_UNWIND_H */ +#endif /* ASM_X86__UNWIND_H */ diff --git a/include/asm-x86/user32.h b/include/asm-x86/user32.h index a3d91004787..aa66c1857f0 100644 --- a/include/asm-x86/user32.h +++ b/include/asm-x86/user32.h @@ -1,5 +1,5 @@ -#ifndef USER32_H -#define USER32_H 1 +#ifndef ASM_X86__USER32_H +#define ASM_X86__USER32_H /* IA32 compatible user structures for ptrace. * These should be used for 32bit coredumps too. */ @@ -67,4 +67,4 @@ struct user32 { }; -#endif +#endif /* ASM_X86__USER32_H */ diff --git a/include/asm-x86/user_32.h b/include/asm-x86/user_32.h index d6e51edc259..e0fe2f55f1a 100644 --- a/include/asm-x86/user_32.h +++ b/include/asm-x86/user_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_USER_H -#define _I386_USER_H +#ifndef ASM_X86__USER_32_H +#define ASM_X86__USER_32_H #include /* Core file format: The core file is written in such a way that gdb @@ -128,4 +128,4 @@ struct user{ #define HOST_TEXT_START_ADDR (u.start_code) #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) -#endif /* _I386_USER_H */ +#endif /* ASM_X86__USER_32_H */ diff --git a/include/asm-x86/user_64.h b/include/asm-x86/user_64.h index 6037b634c77..38b5799863b 100644 --- a/include/asm-x86/user_64.h +++ b/include/asm-x86/user_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_USER_H -#define _X86_64_USER_H +#ifndef ASM_X86__USER_64_H +#define ASM_X86__USER_64_H #include #include @@ -134,4 +134,4 @@ struct user { #define HOST_TEXT_START_ADDR (u.start_code) #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) -#endif /* _X86_64_USER_H */ +#endif /* ASM_X86__USER_64_H */ diff --git a/include/asm-x86/uv/bios.h b/include/asm-x86/uv/bios.h index aa73362ff5d..7cd6d7ec130 100644 --- a/include/asm-x86/uv/bios.h +++ b/include/asm-x86/uv/bios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BIOS_H -#define _ASM_X86_BIOS_H +#ifndef ASM_X86__UV__BIOS_H +#define ASM_X86__UV__BIOS_H /* * BIOS layer definitions. @@ -65,4 +65,4 @@ x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second, unsigned long *drift_info); extern const char *x86_bios_strerror(long status); -#endif /* _ASM_X86_BIOS_H */ +#endif /* ASM_X86__UV__BIOS_H */ diff --git a/include/asm-x86/uv/uv_bau.h b/include/asm-x86/uv/uv_bau.h index 91ac0dfb758..0950239acaf 100644 --- a/include/asm-x86/uv/uv_bau.h +++ b/include/asm-x86/uv/uv_bau.h @@ -8,8 +8,8 @@ * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_BAU__ -#define __ASM_X86_UV_BAU__ +#ifndef ASM_X86__UV__UV_BAU_H +#define ASM_X86__UV__UV_BAU_H #include #define BITSPERBYTE 8 @@ -334,4 +334,4 @@ extern int uv_flush_tlb_others(cpumask_t *, struct mm_struct *, unsigned long); extern void uv_bau_message_intr1(void); extern void uv_bau_timeout_intr1(void); -#endif /* __ASM_X86_UV_BAU__ */ +#endif /* ASM_X86__UV__UV_BAU_H */ diff --git a/include/asm-x86/uv/uv_hub.h b/include/asm-x86/uv/uv_hub.h index a4ef26e5850..bdb5b01afbf 100644 --- a/include/asm-x86/uv/uv_hub.h +++ b/include/asm-x86/uv/uv_hub.h @@ -8,8 +8,8 @@ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_HUB_H__ -#define __ASM_X86_UV_HUB_H__ +#ifndef ASM_X86__UV__UV_HUB_H +#define ASM_X86__UV__UV_HUB_H #include #include @@ -350,5 +350,5 @@ static inline int uv_num_possible_blades(void) return uv_possible_blades; } -#endif /* __ASM_X86_UV_HUB__ */ +#endif /* ASM_X86__UV__UV_HUB_H */ diff --git a/include/asm-x86/uv/uv_mmrs.h b/include/asm-x86/uv/uv_mmrs.h index 151fd7fcb80..8b03d89d245 100644 --- a/include/asm-x86/uv/uv_mmrs.h +++ b/include/asm-x86/uv/uv_mmrs.h @@ -8,8 +8,8 @@ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_MMRS__ -#define __ASM_X86_UV_MMRS__ +#ifndef ASM_X86__UV__UV_MMRS_H +#define ASM_X86__UV__UV_MMRS_H #define UV_MMR_ENABLE (1UL << 63) @@ -1292,4 +1292,4 @@ union uvh_si_alias2_overlay_config_u { }; -#endif /* __ASM_X86_UV_MMRS__ */ +#endif /* ASM_X86__UV__UV_MMRS_H */ diff --git a/include/asm-x86/vdso.h b/include/asm-x86/vdso.h index 8e18fb80f5e..4ab320913ea 100644 --- a/include/asm-x86/vdso.h +++ b/include/asm-x86/vdso.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_VDSO_H -#define _ASM_X86_VDSO_H 1 +#ifndef ASM_X86__VDSO_H +#define ASM_X86__VDSO_H #ifdef CONFIG_X86_64 extern const char VDSO64_PRELINK[]; @@ -44,4 +44,4 @@ extern const char vdso32_int80_start, vdso32_int80_end; extern const char vdso32_syscall_start, vdso32_syscall_end; extern const char vdso32_sysenter_start, vdso32_sysenter_end; -#endif /* asm-x86/vdso.h */ +#endif /* ASM_X86__VDSO_H */ diff --git a/include/asm-x86/vga.h b/include/asm-x86/vga.h index 0ccf804377e..b9e493d07d0 100644 --- a/include/asm-x86/vga.h +++ b/include/asm-x86/vga.h @@ -4,8 +4,8 @@ * (c) 1998 Martin Mares */ -#ifndef _LINUX_ASM_VGA_H_ -#define _LINUX_ASM_VGA_H_ +#ifndef ASM_X86__VGA_H +#define ASM_X86__VGA_H /* * On the PC, we can just recalculate addresses and then @@ -17,4 +17,4 @@ #define vga_readb(x) (*(x)) #define vga_writeb(x, y) (*(y) = (x)) -#endif +#endif /* ASM_X86__VGA_H */ diff --git a/include/asm-x86/vgtod.h b/include/asm-x86/vgtod.h index 3301f092934..38fd1336402 100644 --- a/include/asm-x86/vgtod.h +++ b/include/asm-x86/vgtod.h @@ -1,5 +1,5 @@ -#ifndef _ASM_VGTOD_H -#define _ASM_VGTOD_H 1 +#ifndef ASM_X86__VGTOD_H +#define ASM_X86__VGTOD_H #include #include @@ -26,4 +26,4 @@ extern struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data; extern struct vsyscall_gtod_data vsyscall_gtod_data; -#endif +#endif /* ASM_X86__VGTOD_H */ diff --git a/include/asm-x86/visws/cobalt.h b/include/asm-x86/visws/cobalt.h index 995258831b7..9627a8fe84e 100644 --- a/include/asm-x86/visws/cobalt.h +++ b/include/asm-x86/visws/cobalt.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_COBALT_H -#define __I386_SGI_COBALT_H +#ifndef ASM_X86__VISWS__COBALT_H +#define ASM_X86__VISWS__COBALT_H #include @@ -122,4 +122,4 @@ extern char visws_board_type; extern char visws_board_rev; -#endif /* __I386_SGI_COBALT_H */ +#endif /* ASM_X86__VISWS__COBALT_H */ diff --git a/include/asm-x86/visws/lithium.h b/include/asm-x86/visws/lithium.h index dfcd4f07ab8..b36d3b378c6 100644 --- a/include/asm-x86/visws/lithium.h +++ b/include/asm-x86/visws/lithium.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_LITHIUM_H -#define __I386_SGI_LITHIUM_H +#ifndef ASM_X86__VISWS__LITHIUM_H +#define ASM_X86__VISWS__LITHIUM_H #include @@ -49,5 +49,5 @@ static inline unsigned short li_pcib_read16(unsigned long reg) return *((volatile unsigned short *)(LI_PCIB_VADDR+reg)); } -#endif +#endif /* ASM_X86__VISWS__LITHIUM_H */ diff --git a/include/asm-x86/visws/piix4.h b/include/asm-x86/visws/piix4.h index 83ea4f46e41..61c938045ec 100644 --- a/include/asm-x86/visws/piix4.h +++ b/include/asm-x86/visws/piix4.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_PIIX_H -#define __I386_SGI_PIIX_H +#ifndef ASM_X86__VISWS__PIIX4_H +#define ASM_X86__VISWS__PIIX4_H /* * PIIX4 as used on SGI Visual Workstations @@ -104,4 +104,4 @@ */ #define PIIX_GPI_STPCLK 0x4 // STPCLK signal routed back in -#endif +#endif /* ASM_X86__VISWS__PIIX4_H */ diff --git a/include/asm-x86/vm86.h b/include/asm-x86/vm86.h index 5ce351325e0..998bd18eb73 100644 --- a/include/asm-x86/vm86.h +++ b/include/asm-x86/vm86.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_VM86_H -#define _LINUX_VM86_H +#ifndef ASM_X86__VM86_H +#define ASM_X86__VM86_H /* * I'm guessing at the VIF/VIP flag usage, but hope that this is how @@ -205,4 +205,4 @@ static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c) #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__VM86_H */ diff --git a/include/asm-x86/vmi_time.h b/include/asm-x86/vmi_time.h index c3118c38515..b2d39e6a08b 100644 --- a/include/asm-x86/vmi_time.h +++ b/include/asm-x86/vmi_time.h @@ -22,8 +22,8 @@ * */ -#ifndef __VMI_TIME_H -#define __VMI_TIME_H +#ifndef ASM_X86__VMI_TIME_H +#define ASM_X86__VMI_TIME_H /* * Raw VMI call indices for timer functions @@ -95,4 +95,4 @@ extern void __devinit vmi_time_ap_init(void); #define CONFIG_VMI_ALARM_HZ 100 -#endif +#endif /* ASM_X86__VMI_TIME_H */ diff --git a/include/asm-x86/vsyscall.h b/include/asm-x86/vsyscall.h index 6b66ff905af..dcd4682413d 100644 --- a/include/asm-x86/vsyscall.h +++ b/include/asm-x86/vsyscall.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_VSYSCALL_H_ -#define _ASM_X86_64_VSYSCALL_H_ +#ifndef ASM_X86__VSYSCALL_H +#define ASM_X86__VSYSCALL_H enum vsyscall_num { __NR_vgettimeofday, @@ -41,4 +41,4 @@ extern void map_vsyscall(void); #endif /* __KERNEL__ */ -#endif /* _ASM_X86_64_VSYSCALL_H_ */ +#endif /* ASM_X86__VSYSCALL_H */ diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h index 8ded7472002..8151f5b8b6c 100644 --- a/include/asm-x86/xen/events.h +++ b/include/asm-x86/xen/events.h @@ -1,5 +1,5 @@ -#ifndef __XEN_EVENTS_H -#define __XEN_EVENTS_H +#ifndef ASM_X86__XEN__EVENTS_H +#define ASM_X86__XEN__EVENTS_H enum ipi_vector { XEN_RESCHEDULE_VECTOR, @@ -21,4 +21,4 @@ static inline void xen_do_IRQ(int irq, struct pt_regs *regs) do_IRQ(regs); } -#endif /* __XEN_EVENTS_H */ +#endif /* ASM_X86__XEN__EVENTS_H */ diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h index 2444d4593a3..c4baab4d2b6 100644 --- a/include/asm-x86/xen/grant_table.h +++ b/include/asm-x86/xen/grant_table.h @@ -1,7 +1,7 @@ -#ifndef __XEN_GRANT_TABLE_H -#define __XEN_GRANT_TABLE_H +#ifndef ASM_X86__XEN__GRANT_TABLE_H +#define ASM_X86__XEN__GRANT_TABLE_H #define xen_alloc_vm_area(size) alloc_vm_area(size) #define xen_free_vm_area(area) free_vm_area(area) -#endif /* __XEN_GRANT_TABLE_H */ +#endif /* ASM_X86__XEN__GRANT_TABLE_H */ diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h index 91cb7fd5c12..44f4259bee3 100644 --- a/include/asm-x86/xen/hypercall.h +++ b/include/asm-x86/xen/hypercall.h @@ -30,8 +30,8 @@ * IN THE SOFTWARE. */ -#ifndef __HYPERCALL_H__ -#define __HYPERCALL_H__ +#ifndef ASM_X86__XEN__HYPERCALL_H +#define ASM_X86__XEN__HYPERCALL_H #include #include @@ -524,4 +524,4 @@ MULTI_stack_switch(struct multicall_entry *mcl, mcl->args[1] = esp; } -#endif /* __HYPERCALL_H__ */ +#endif /* ASM_X86__XEN__HYPERCALL_H */ diff --git a/include/asm-x86/xen/hypervisor.h b/include/asm-x86/xen/hypervisor.h index 8e15dd28c91..06c350452c5 100644 --- a/include/asm-x86/xen/hypervisor.h +++ b/include/asm-x86/xen/hypervisor.h @@ -30,8 +30,8 @@ * IN THE SOFTWARE. */ -#ifndef __HYPERVISOR_H__ -#define __HYPERVISOR_H__ +#ifndef ASM_X86__XEN__HYPERVISOR_H +#define ASM_X86__XEN__HYPERVISOR_H #include #include @@ -70,4 +70,4 @@ u64 jiffies_to_st(unsigned long jiffies); #define is_running_on_xen() (xen_start_info ? 1 : 0) -#endif /* __HYPERVISOR_H__ */ +#endif /* ASM_X86__XEN__HYPERVISOR_H */ diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h index 9d810f2538a..d077bba96da 100644 --- a/include/asm-x86/xen/interface.h +++ b/include/asm-x86/xen/interface.h @@ -6,8 +6,8 @@ * Copyright (c) 2004, K A Fraser */ -#ifndef __ASM_X86_XEN_INTERFACE_H -#define __ASM_X86_XEN_INTERFACE_H +#ifndef ASM_X86__XEN__INTERFACE_H +#define ASM_X86__XEN__INTERFACE_H #ifdef __XEN__ #define __DEFINE_GUEST_HANDLE(name, type) \ @@ -172,4 +172,4 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context); #define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" #endif -#endif /* __ASM_X86_XEN_INTERFACE_H */ +#endif /* ASM_X86__XEN__INTERFACE_H */ diff --git a/include/asm-x86/xen/interface_32.h b/include/asm-x86/xen/interface_32.h index d8ac41d5db8..08167e19fc6 100644 --- a/include/asm-x86/xen/interface_32.h +++ b/include/asm-x86/xen/interface_32.h @@ -6,8 +6,8 @@ * Copyright (c) 2004, K A Fraser */ -#ifndef __ASM_X86_XEN_INTERFACE_32_H -#define __ASM_X86_XEN_INTERFACE_32_H +#ifndef ASM_X86__XEN__INTERFACE_32_H +#define ASM_X86__XEN__INTERFACE_32_H /* @@ -94,4 +94,4 @@ typedef struct xen_callback xen_callback_t; #define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) #define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) -#endif /* __ASM_X86_XEN_INTERFACE_32_H */ +#endif /* ASM_X86__XEN__INTERFACE_32_H */ diff --git a/include/asm-x86/xen/interface_64.h b/include/asm-x86/xen/interface_64.h index 842266ce96e..046c0f1e01d 100644 --- a/include/asm-x86/xen/interface_64.h +++ b/include/asm-x86/xen/interface_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_XEN_INTERFACE_64_H -#define __ASM_X86_XEN_INTERFACE_64_H +#ifndef ASM_X86__XEN__INTERFACE_64_H +#define ASM_X86__XEN__INTERFACE_64_H /* * 64-bit segment selectors @@ -156,4 +156,4 @@ typedef unsigned long xen_callback_t; #endif /* !__ASSEMBLY__ */ -#endif /* __ASM_X86_XEN_INTERFACE_64_H */ +#endif /* ASM_X86__XEN__INTERFACE_64_H */ diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h index 05e678a8662..a17a86433c7 100644 --- a/include/asm-x86/xen/page.h +++ b/include/asm-x86/xen/page.h @@ -1,5 +1,5 @@ -#ifndef __XEN_PAGE_H -#define __XEN_PAGE_H +#ifndef ASM_X86__XEN__PAGE_H +#define ASM_X86__XEN__PAGE_H #include @@ -162,4 +162,4 @@ xmaddr_t arbitrary_virt_to_machine(void *address); void make_lowmem_page_readonly(void *vaddr); void make_lowmem_page_readwrite(void *vaddr); -#endif /* __XEN_PAGE_H */ +#endif /* ASM_X86__XEN__PAGE_H */ -- GitLab From 5616c23ad9cd3c50af674d408fef7b90abeee81c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 22 Jul 2008 15:32:38 -0400 Subject: [PATCH 0075/5416] x86: doc: move x86-generic documentation from Doc/x86/i386 The boot protocol, USB legacy support, and zero-page documentation is common to the x86 platform, not i386-specific. Signed-off-by: H. Peter Anvin --- Documentation/x86/{i386 => }/boot.txt | 0 Documentation/x86/{i386 => }/usb-legacy-support.txt | 0 Documentation/x86/{i386 => }/zero-page.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Documentation/x86/{i386 => }/boot.txt (100%) rename Documentation/x86/{i386 => }/usb-legacy-support.txt (100%) rename Documentation/x86/{i386 => }/zero-page.txt (100%) diff --git a/Documentation/x86/i386/boot.txt b/Documentation/x86/boot.txt similarity index 100% rename from Documentation/x86/i386/boot.txt rename to Documentation/x86/boot.txt diff --git a/Documentation/x86/i386/usb-legacy-support.txt b/Documentation/x86/usb-legacy-support.txt similarity index 100% rename from Documentation/x86/i386/usb-legacy-support.txt rename to Documentation/x86/usb-legacy-support.txt diff --git a/Documentation/x86/i386/zero-page.txt b/Documentation/x86/zero-page.txt similarity index 100% rename from Documentation/x86/i386/zero-page.txt rename to Documentation/x86/zero-page.txt -- GitLab From a021e5124a6c57325ffb02a60cd1d5f40342f8aa Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 22 Jul 2008 15:33:57 -0400 Subject: [PATCH 0076/5416] x86: doc: boot.txt: fix the size of the start_sys field The start_sys field is two bytes, not four. Signed-off-by: H. Peter Anvin --- Documentation/x86/boot.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 147bfe511cd..83c0033ee9e 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -308,7 +308,7 @@ Protocol: 2.00+ Field name: start_sys Type: read -Offset/size: 0x20c/4 +Offset/size: 0x20c/2 Protocol: 2.00+ The load low segment (0x1000). Obsolete. -- GitLab From a31863168660c6b6f6c7ffe05bb6a38e97803326 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 22 Jul 2008 21:53:53 +0200 Subject: [PATCH 0077/5416] x86: consolidate header guards This patch consolidates the header guard names which are also used externally, i.e. in .c files. Signed-off-by: Vegard Nossum --- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/kernel/asm-offsets_64.c | 2 +- arch/x86/kernel/syscall_64.c | 4 ++-- include/asm-x86/desc.h | 6 +++--- include/asm-x86/unistd_64.h | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index bc5553b496f..3ee338c7d1d 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -16,7 +16,7 @@ */ #undef CONFIG_PARAVIRT #ifdef CONFIG_X86_32 -#define _ASM_DESC_H_ 1 +#define ASM_X86__DESC_H 1 #endif #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index aa89387006f..505543a75a5 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -22,7 +22,7 @@ #define __NO_STUBS 1 #undef __SYSCALL -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #define __SYSCALL(nr, sym) [nr] = 1, static char syscalls[] = { #include diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c index 170d43c1748..3d1be4f0fac 100644 --- a/arch/x86/kernel/syscall_64.c +++ b/arch/x86/kernel/syscall_64.c @@ -8,12 +8,12 @@ #define __NO_STUBS #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #include #undef __SYSCALL #define __SYSCALL(nr, sym) [nr] = sym, -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H typedef void (*sys_call_ptr_t)(void); diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index a44c4dc7059..b73fea54def 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h @@ -1,5 +1,5 @@ -#ifndef _ASM_DESC_H_ -#define _ASM_DESC_H_ +#ifndef ASM_X86__DESC_H +#define ASM_X86__DESC_H #ifndef __ASSEMBLY__ #include @@ -397,4 +397,4 @@ static inline void set_system_gate_ist(int n, void *addr, unsigned ist) #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__DESC_H */ diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h index 9c1a4a3470d..1e10189ed6b 100644 --- a/include/asm-x86/unistd_64.h +++ b/include/asm-x86/unistd_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_UNISTD_H_ -#define _ASM_X86_64_UNISTD_H_ +#ifndef ASM_X86__UNISTD_64_H +#define ASM_X86__UNISTD_64_H #ifndef __SYSCALL #define __SYSCALL(a, b) @@ -676,4 +676,4 @@ __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") #endif /* __KERNEL__ */ -#endif /* _ASM_X86_64_UNISTD_H_ */ +#endif /* ASM_X86__UNISTD_64_H */ -- GitLab From 2b97df06ce44b1d145bd1299f50765803c2fabee Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:13:14 +0530 Subject: [PATCH 0078/5416] x86: apic_XX.c declare functions before they get used declared following smp interrupts in asm-x86/hw_irq.h: smp_apic_timer_interrupt, smp_spurious_interrupt, smp_error_interrupt Signed-off-by: Jaswinder Singh --- include/asm-x86/apic.h | 5 +++++ include/asm-x86/hw_irq.h | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 133c998161c..519ad65708e 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -54,6 +54,11 @@ extern int disable_apic; #endif extern int is_vsmp_box(void); +extern void xapic_wait_icr_idle(void); +extern u32 safe_xapic_wait_icr_idle(void); +extern u64 xapic_icr_read(void); +extern void xapic_icr_write(u32, u32); +extern int setup_profiling_timer(unsigned int); static inline void native_apic_write(unsigned long reg, u32 v) { diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 77ba51df566..40b941ac81c 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -93,6 +93,16 @@ extern asmlinkage void qic_reschedule_interrupt(void); extern asmlinkage void qic_enable_irq_interrupt(void); extern asmlinkage void qic_call_function_interrupt(void); +/* SMP */ +extern void smp_apic_timer_interrupt(struct pt_regs *); +#ifdef CONFIG_X86_32 +extern void smp_spurious_interrupt(struct pt_regs *); +extern void smp_error_interrupt(struct pt_regs *); +#else +extern asmlinkage void smp_spurious_interrupt(void); +extern asmlinkage void smp_error_interrupt(void); +#endif + #ifdef CONFIG_X86_32 extern void (*const interrupt[NR_IRQS])(void); #else -- GitLab From 8f7db5186cf126b56035d9a9735774d751090d66 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:31:02 +0530 Subject: [PATCH 0079/5416] x86: vm86_32.c declare functions before they get used declared following syscalls in asm-x86/syscalls.h: sys_vm86old, sys_vm86 Signed-off-by: Jaswinder Singh --- include/asm-x86/syscalls.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/asm-x86/syscalls.h b/include/asm-x86/syscalls.h index 170fcb132f5..3d6b159d348 100644 --- a/include/asm-x86/syscalls.h +++ b/include/asm-x86/syscalls.h @@ -6,7 +6,6 @@ * This file is released under the GPLv2. * See the file COPYING for more details. * - * Please do not call me directly, include linux/syscalls.h */ #ifndef _ASM_X86_SYSCALLS_H @@ -60,6 +59,10 @@ asmlinkage int sys_olduname(struct oldold_utsname __user *); asmlinkage int sys_set_thread_area(struct user_desc __user *); asmlinkage int sys_get_thread_area(struct user_desc __user *); +/* kernel/vm86_32.c */ +asmlinkage int sys_vm86old(struct pt_regs); +asmlinkage int sys_vm86(struct pt_regs); + #else /* CONFIG_X86_32 */ /* X86_64 only */ -- GitLab From a80495ec927e8ec2b1ff085592bbe9bed77ffb3b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:33:57 +0530 Subject: [PATCH 0080/5416] x86: mm/init_XX.c declare functions before they get used included in mm/init_32.c for zap_low_mappings() declared free_initmem() in asm-x86/page_XX.h Signed-off-by: Jaswinder Singh --- arch/x86/mm/init_32.c | 1 + include/asm-x86/page_32.h | 1 + include/asm-x86/page_64.h | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..4974e97dedf 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -47,6 +47,7 @@ #include #include #include +#include unsigned int __VMALLOC_RESERVE = 128 << 20; diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index ab8528793f0..c9dd069d4ef 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h @@ -96,6 +96,7 @@ extern void find_low_pfn_range(void); extern unsigned long init_memory_mapping(unsigned long start, unsigned long end); extern void initmem_init(unsigned long, unsigned long); +extern void free_initmem(void); extern void setup_bootmem_allocator(void); diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h index c6916c83e6b..e5a754e97f2 100644 --- a/include/asm-x86/page_64.h +++ b/include/asm-x86/page_64.h @@ -91,6 +91,7 @@ extern unsigned long init_memory_mapping(unsigned long start, unsigned long end); extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn); +extern void free_initmem(void); extern void init_extra_mapping_uc(unsigned long phys, unsigned long size); extern void init_extra_mapping_wb(unsigned long phys, unsigned long size); -- GitLab From 70ef56414ec7e01d787c8e959bb259845df4ee4f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:36:37 +0530 Subject: [PATCH 0081/5416] x86: mm/fault.c declare do_page_fault before they get used declared do_page_fault() in asm-x86/trap.h for both X86_32 and X86_64 removed do_invalid_op declaration from mm/fault.c as it is already declared in asm-x86/trap.h Signed-off-by: Jaswinder Singh --- arch/x86/mm/fault.c | 3 +-- include/asm-x86/traps.h | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 455f3fe67b4..8f92cac4e6d 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Page fault error code bits @@ -357,8 +358,6 @@ static int is_errata100(struct pt_regs *regs, unsigned long address) return 0; } -void do_invalid_op(struct pt_regs *, unsigned long); - static int is_f00f_bug(struct pt_regs *regs, unsigned long address) { #ifdef CONFIG_X86_F00F_BUG diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h index a4b65a71bd6..b60fab546da 100644 --- a/include/asm-x86/traps.h +++ b/include/asm-x86/traps.h @@ -51,6 +51,8 @@ void do_spurious_interrupt_bug(struct pt_regs *, long); unsigned long patch_espfix_desc(unsigned long, unsigned long); asmlinkage void math_emulate(long); +void do_page_fault(struct pt_regs *regs, unsigned long error_code); + #else /* CONFIG_X86_32 */ asmlinkage void double_fault(void); @@ -62,5 +64,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *); asmlinkage void do_simd_coprocessor_error(struct pt_regs *); asmlinkage void do_spurious_interrupt_bug(struct pt_regs *); +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code); + #endif /* CONFIG_X86_32 */ #endif /* _ASM_X86_TRAPS_H */ -- GitLab From 4b6e9f27d0034740e9cfa341b45c229ba30ec0c5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:39:16 +0530 Subject: [PATCH 0082/5416] x86: mm/ioremap.c declare early_ioremap_debug and early_ioremap_nested as static Signed-off-by: Jaswinder Singh --- arch/x86/mm/ioremap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 24c1d3c3018..19fd9a3c521 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -413,7 +413,7 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr) return; } -int __initdata early_ioremap_debug; +static int __initdata early_ioremap_debug; static int __init early_ioremap_debug_setup(char *str) { @@ -539,7 +539,7 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx) } -int __initdata early_ioremap_nested; +static int __initdata early_ioremap_nested; static int __init check_early_ioremap_leak(void) { -- GitLab From e0b7c8192ded4c2096388008d3ca6708caa8b601 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:40:34 +0530 Subject: [PATCH 0083/5416] x86: mm/pageattr.c declare arch_report_meminfo before they get used declared arch_report_meminfo() in asm-x86/pgtable.h as it will be also accessible by fs/proc/proc_misc.c Signed-off-by: Jaswinder Singh --- include/asm-x86/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 96aa76e691d..4fb22b9c528 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -310,6 +310,8 @@ static inline void native_pagetable_setup_start(pgd_t *base) {} static inline void native_pagetable_setup_done(pgd_t *base) {} #endif +extern int arch_report_meminfo(char *page); + #ifdef CONFIG_PARAVIRT #include #else /* !CONFIG_PARAVIRT */ -- GitLab From 01eb7858c017b1c63b962f8c2ad37133383ca560 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:41:59 +0530 Subject: [PATCH 0084/5416] x86: mm/pgtable_32.c declare set_pmd_pfn before they get used Signed-off-by: Jaswinder Singh --- include/asm-x86/pgtable_32.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h index 0611abf96a5..015fb4e19de 100644 --- a/include/asm-x86/pgtable_32.h +++ b/include/asm-x86/pgtable_32.h @@ -31,6 +31,7 @@ static inline void pgtable_cache_init(void) { } static inline void check_pgt_cache(void) { } void paging_init(void); +extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* * The Linux x86 paging architecture is 'compile-time dual-mode', it -- GitLab From 71e3b818431957371c7f69fa1c576d4a403c1478 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Wed, 23 Jul 2008 17:44:00 +0530 Subject: [PATCH 0085/5416] x86: mach-default/setup.c declare no_broadcast before they get used included mach_ipi.h for no_broadcast declaration fixed minor spacing for no_broadcast Signed-off-by: Jaswinder Singh --- arch/x86/mach-default/setup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index 3d317836be9..3f2cf11f201 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -10,13 +10,15 @@ #include #include +#include + #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) #else #define DEFAULT_SEND_IPI (0) #endif -int no_broadcast=DEFAULT_SEND_IPI; +int no_broadcast = DEFAULT_SEND_IPI; /** * pre_intr_init_hook - initialisation prior to setting up interrupt vectors -- GitLab From 05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 21 Jul 2008 10:15:22 -0400 Subject: [PATCH 0086/5416] x86, pci: iommu fix potential overflow in alloc_iommu() It is possible that alloc_iommu()'s boundary_size overflows as dma_get_seg_boundary can return 0xffffffff. In that case, further usage of boundary_size triggers a BUG_ON() in the iommu code. Signed-off-by: Prarit Bhargava Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index df5f142657d..1062dc1e639 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -93,7 +93,7 @@ static unsigned long alloc_iommu(struct device *dev, int size) base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), PAGE_SIZE) >> PAGE_SHIFT; - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, + boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; spin_lock_irqsave(&iommu_bitmap_lock, flags); -- GitLab From fd60b39f845aa7462453af8aed4f059b162f181f Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Wed, 23 Jul 2008 22:45:01 +0800 Subject: [PATCH 0087/5416] arch/x86/kernel/genx2apic_uv_x.c: Removed duplicated include Removed duplicated include file in arch/x86/kernel/genx2apic_uv_x.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index a882bc3a2ce..14a9772778e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include -- GitLab From a300bec952127d9a15e666b391bb35c9aecb3002 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 22 Jul 2008 09:46:13 -0700 Subject: [PATCH 0088/5416] documentation: move hpet.txt to timers/ subdirectory Move hpet.txt to Documentation/timers/ subdirectory. Add 00-INDEX to Documentation/timers/ subdirectory. Signed-off-by: Randy Dunlap Cc: tglx Signed-off-by: Thomas Gleixner --- Documentation/00-INDEX | 2 -- Documentation/timers/00-INDEX | 10 ++++++++++ Documentation/{ => timers}/hpet.txt | 0 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Documentation/timers/00-INDEX rename Documentation/{ => timers}/hpet.txt (100%) diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 1977fab3865..6c40c4c300d 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -161,8 +161,6 @@ hayes-esp.txt - info on using the Hayes ESP serial driver. highuid.txt - notes on the change from 16 bit to 32 bit user/group IDs. -hpet.txt - - High Precision Event Timer Driver for Linux. timers/ - info on the timer related topics hw_random.txt diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX new file mode 100644 index 00000000000..397dc35e132 --- /dev/null +++ b/Documentation/timers/00-INDEX @@ -0,0 +1,10 @@ +00-INDEX + - this file +highres.txt + - High resolution timers and dynamic ticks design notes +hpet.txt + - High Precision Event Timer Driver for Linux +hrtimers.txt + - subsystem for high-resolution kernel timers +timer_stats.txt + - timer usage statistics diff --git a/Documentation/hpet.txt b/Documentation/timers/hpet.txt similarity index 100% rename from Documentation/hpet.txt rename to Documentation/timers/hpet.txt -- GitLab From 38ffbe66d59051fd9cfcfc8545f164700e2fa3bc Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 23 Jul 2008 14:21:18 -0700 Subject: [PATCH 0089/5416] x86/paravirt/xen: properly fill out the ldt ops LTP testing showed that Xen does not properly implement sys_modify_ldt(). This patch does the final little bits needed to make the ldt work properly. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/ldt.c | 9 ++++++++- arch/x86/kernel/paravirt.c | 4 ++++ arch/x86/xen/enlighten.c | 23 +++++++++++++++++++++++ include/asm-x86/desc.h | 10 +++++++++- include/asm-x86/paravirt.h | 13 +++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 3fee2aa50f3..4895e0634d2 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -51,6 +51,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, (mincount - oldsize) * LDT_ENTRY_SIZE); + paravirt_alloc_ldt(newldt, mincount); + #ifdef CONFIG_X86_64 /* CHECKME: Do we really need this ? */ wmb(); @@ -75,6 +77,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) #endif } if (oldsize) { + paravirt_free_ldt(oldldt, oldsize); if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(oldldt); else @@ -86,10 +89,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) static inline int copy_ldt(mm_context_t *new, mm_context_t *old) { int err = alloc_ldt(new, old->size, 0); + int i; if (err < 0) return err; - memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); + + for(i = 0; i < old->size; i++) + write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE); return 0; } @@ -126,6 +132,7 @@ void destroy_context(struct mm_struct *mm) if (mm == current->active_mm) clear_LDT(); #endif + paravirt_free_ldt(mm->context.ldt, mm->context.size); if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 94da4d52d79..d8f2277be5a 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -348,6 +348,10 @@ struct pv_cpu_ops pv_cpu_ops = { .write_ldt_entry = native_write_ldt_entry, .write_gdt_entry = native_write_gdt_entry, .write_idt_entry = native_write_idt_entry, + + .alloc_ldt = paravirt_nop, + .free_ldt = paravirt_nop, + .load_sp0 = native_load_sp0, #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9ff6e3cbf08..06219e60e9c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -325,6 +325,26 @@ static unsigned long xen_store_tr(void) return 0; } +static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{ + unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); + void *v = ldt; + int i; + + for(i = 0; i < pages; i += PAGE_SIZE) + make_lowmem_page_readonly(v + i); +} + +static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) +{ + unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); + void *v = ldt; + int i; + + for(i = 0; i < pages; i += PAGE_SIZE) + make_lowmem_page_readwrite(v + i); +} + static void xen_set_ldt(const void *addr, unsigned entries) { struct mmuext_op *op; @@ -1220,6 +1240,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { .load_gs_index = xen_load_gs_index, #endif + .alloc_ldt = xen_alloc_ldt, + .free_ldt = xen_free_ldt, + .store_gdt = native_store_gdt, .store_idt = native_store_idt, .store_tr = xen_store_tr, diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index a44c4dc7059..24a524f5e1a 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h @@ -97,7 +97,15 @@ static inline int desc_empty(const void *ptr) native_write_gdt_entry(dt, entry, desc, type) #define write_idt_entry(dt, entry, g) \ native_write_idt_entry(dt, entry, g) -#endif + +static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{ +} + +static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) +{ +} +#endif /* CONFIG_PARAVIRT */ static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate) diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index fbbde93f12d..db9b0647b34 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -124,6 +124,9 @@ struct pv_cpu_ops { int entrynum, const void *desc, int size); void (*write_idt_entry)(gate_desc *, int entrynum, const gate_desc *gate); + void (*alloc_ldt)(struct desc_struct *ldt, unsigned entries); + void (*free_ldt)(struct desc_struct *ldt, unsigned entries); + void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t); void (*set_iopl_mask)(unsigned mask); @@ -824,6 +827,16 @@ do { \ (aux) = __aux; \ } while (0) +static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{ + PVOP_VCALL2(pv_cpu_ops.alloc_ldt, ldt, entries); +} + +static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) +{ + PVOP_VCALL2(pv_cpu_ops.free_ldt, ldt, entries); +} + static inline void load_TR_desc(void) { PVOP_VCALL0(pv_cpu_ops.load_tr_desc); -- GitLab From d5de8841355a48f7f634a04507185eaf1f9755e3 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 23 Jul 2008 13:28:58 -0700 Subject: [PATCH 0090/5416] x86: split spinlock implementations out into their own files ftrace requires certain low-level code, like spinlocks and timestamps, to be compiled without -pg in order to avoid infinite recursion. This patch splits out the core paravirt spinlocks and the Xen spinlocks into separate files which can be compiled without -pg. Also do xen/time.c while we're about it. As a result, we can now use ftrace within a Xen domain. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 4 +- arch/x86/kernel/paravirt-spinlocks.c | 31 +++++ arch/x86/kernel/paravirt.c | 23 ---- arch/x86/xen/Makefile | 8 +- arch/x86/xen/smp.c | 167 ------------------------ arch/x86/xen/spinlock.c | 183 +++++++++++++++++++++++++++ arch/x86/xen/xen-ops.h | 3 + 7 files changed, 226 insertions(+), 193 deletions(-) create mode 100644 arch/x86/kernel/paravirt-spinlocks.c create mode 100644 arch/x86/xen/spinlock.c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 3db651fc8ec..d679cb2c79b 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -10,7 +10,7 @@ ifdef CONFIG_FTRACE # Do not profile debug and lowlevel utilities CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg -CFLAGS_REMOVE_paravirt.o = -pg +CFLAGS_REMOVE_paravirt-spinlocks.o = -pg endif # @@ -89,7 +89,7 @@ obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o obj-$(CONFIG_KVM_GUEST) += kvm.o obj-$(CONFIG_KVM_CLOCK) += kvmclock.o -obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o +obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o paravirt-spinlocks.o obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c new file mode 100644 index 00000000000..38d7f7f1dbc --- /dev/null +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -0,0 +1,31 @@ +/* + * Split spinlock implementation out into its own file, so it can be + * compiled in a FTRACE-compatible way. + */ +#include +#include + +#include + +struct pv_lock_ops pv_lock_ops = { +#ifdef CONFIG_SMP + .spin_is_locked = __ticket_spin_is_locked, + .spin_is_contended = __ticket_spin_is_contended, + + .spin_lock = __ticket_spin_lock, + .spin_trylock = __ticket_spin_trylock, + .spin_unlock = __ticket_spin_unlock, +#endif +}; +EXPORT_SYMBOL_GPL(pv_lock_ops); + +void __init paravirt_use_bytelocks(void) +{ +#ifdef CONFIG_SMP + pv_lock_ops.spin_is_locked = __byte_spin_is_locked; + pv_lock_ops.spin_is_contended = __byte_spin_is_contended; + pv_lock_ops.spin_lock = __byte_spin_lock; + pv_lock_ops.spin_trylock = __byte_spin_trylock; + pv_lock_ops.spin_unlock = __byte_spin_unlock; +#endif +} diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 94da4d52d79..0d71de9ff56 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -268,17 +268,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) return __get_cpu_var(paravirt_lazy_mode); } -void __init paravirt_use_bytelocks(void) -{ -#ifdef CONFIG_SMP - pv_lock_ops.spin_is_locked = __byte_spin_is_locked; - pv_lock_ops.spin_is_contended = __byte_spin_is_contended; - pv_lock_ops.spin_lock = __byte_spin_lock; - pv_lock_ops.spin_trylock = __byte_spin_trylock; - pv_lock_ops.spin_unlock = __byte_spin_unlock; -#endif -} - struct pv_info pv_info = { .name = "bare hardware", .paravirt_enabled = 0, @@ -461,18 +450,6 @@ struct pv_mmu_ops pv_mmu_ops = { .set_fixmap = native_set_fixmap, }; -struct pv_lock_ops pv_lock_ops = { -#ifdef CONFIG_SMP - .spin_is_locked = __ticket_spin_is_locked, - .spin_is_contended = __ticket_spin_is_contended, - - .spin_lock = __ticket_spin_lock, - .spin_trylock = __ticket_spin_trylock, - .spin_unlock = __ticket_spin_unlock, -#endif -}; -EXPORT_SYMBOL_GPL(pv_lock_ops); - EXPORT_SYMBOL_GPL(pv_time_ops); EXPORT_SYMBOL (pv_cpu_ops); EXPORT_SYMBOL (pv_mmu_ops); diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 59c1e539aed..5bfee243cf9 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -1,4 +1,10 @@ +ifdef CONFIG_FTRACE +# Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_spinlock.o = -pg +CFLAGS_REMOVE_time.o = -pg +endif + obj-y := enlighten.o setup.o multicalls.o mmu.o \ time.o xen-asm_$(BITS).o grant-table.o suspend.o -obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smp.o spinlock.o diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index d8faf79a0a1..baca7f2fbd8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -15,7 +15,6 @@ * This does not handle HOTPLUG_CPU yet. */ #include -#include #include #include @@ -36,8 +35,6 @@ #include "xen-ops.h" #include "mmu.h" -static void __cpuinit xen_init_lock_cpu(int cpu); - cpumask_t xen_cpu_initialized_map; static DEFINE_PER_CPU(int, resched_irq); @@ -419,170 +416,6 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct xen_spinlock { - unsigned char lock; /* 0 -> free; 1 -> locked */ - unsigned short spinners; /* count of waiting cpus */ -}; - -static int xen_spin_is_locked(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - return xl->lock != 0; -} - -static int xen_spin_is_contended(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - /* Not strictly true; this is only the count of contended - lock-takers entering the slow path. */ - return xl->spinners != 0; -} - -static int xen_spin_trylock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - u8 old = 1; - - asm("xchgb %b0,%1" - : "+q" (old), "+m" (xl->lock) : : "memory"); - - return old == 0; -} - -static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; -static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners); - -static inline void spinning_lock(struct xen_spinlock *xl) -{ - __get_cpu_var(lock_spinners) = xl; - wmb(); /* set lock of interest before count */ - asm(LOCK_PREFIX " incw %0" - : "+m" (xl->spinners) : : "memory"); -} - -static inline void unspinning_lock(struct xen_spinlock *xl) -{ - asm(LOCK_PREFIX " decw %0" - : "+m" (xl->spinners) : : "memory"); - wmb(); /* decrement count before clearing lock */ - __get_cpu_var(lock_spinners) = NULL; -} - -static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - int irq = __get_cpu_var(lock_kicker_irq); - int ret; - - /* If kicker interrupts not initialized yet, just spin */ - if (irq == -1) - return 0; - - /* announce we're spinning */ - spinning_lock(xl); - - /* clear pending */ - xen_clear_irq_pending(irq); - - /* check again make sure it didn't become free while - we weren't looking */ - ret = xen_spin_trylock(lock); - if (ret) - goto out; - - /* block until irq becomes pending */ - xen_poll_irq(irq); - kstat_this_cpu.irqs[irq]++; - -out: - unspinning_lock(xl); - return ret; -} - -static void xen_spin_lock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - int timeout; - u8 oldval; - - do { - timeout = 1 << 10; - - asm("1: xchgb %1,%0\n" - " testb %1,%1\n" - " jz 3f\n" - "2: rep;nop\n" - " cmpb $0,%0\n" - " je 1b\n" - " dec %2\n" - " jnz 2b\n" - "3:\n" - : "+m" (xl->lock), "=q" (oldval), "+r" (timeout) - : "1" (1) - : "memory"); - - } while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock))); -} - -static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) -{ - int cpu; - - for_each_online_cpu(cpu) { - /* XXX should mix up next cpu selection */ - if (per_cpu(lock_spinners, cpu) == xl) { - xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); - break; - } - } -} - -static void xen_spin_unlock(struct raw_spinlock *lock) -{ - struct xen_spinlock *xl = (struct xen_spinlock *)lock; - - smp_wmb(); /* make sure no writes get moved after unlock */ - xl->lock = 0; /* release lock */ - - /* make sure unlock happens before kick */ - barrier(); - - if (unlikely(xl->spinners)) - xen_spin_unlock_slow(xl); -} - -static __cpuinit void xen_init_lock_cpu(int cpu) -{ - int irq; - const char *name; - - name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); - irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, - cpu, - xen_reschedule_interrupt, - IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, - name, - NULL); - - if (irq >= 0) { - disable_irq(irq); /* make sure it's never delivered */ - per_cpu(lock_kicker_irq, cpu) = irq; - } - - printk("cpu %d spinlock event irq %d\n", cpu, irq); -} - -static void __init xen_init_spinlocks(void) -{ - pv_lock_ops.spin_is_locked = xen_spin_is_locked; - pv_lock_ops.spin_is_contended = xen_spin_is_contended; - pv_lock_ops.spin_lock = xen_spin_lock; - pv_lock_ops.spin_trylock = xen_spin_trylock; - pv_lock_ops.spin_unlock = xen_spin_unlock; -} - static const struct smp_ops xen_smp_ops __initdata = { .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, .smp_prepare_cpus = xen_smp_prepare_cpus, diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c new file mode 100644 index 00000000000..8dc4d31da67 --- /dev/null +++ b/arch/x86/xen/spinlock.c @@ -0,0 +1,183 @@ +/* + * Split spinlock implementation out into its own file, so it can be + * compiled in a FTRACE-compatible way. + */ +#include +#include + +#include + +#include +#include + +#include "xen-ops.h" + +struct xen_spinlock { + unsigned char lock; /* 0 -> free; 1 -> locked */ + unsigned short spinners; /* count of waiting cpus */ +}; + +static int xen_spin_is_locked(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + return xl->lock != 0; +} + +static int xen_spin_is_contended(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + /* Not strictly true; this is only the count of contended + lock-takers entering the slow path. */ + return xl->spinners != 0; +} + +static int xen_spin_trylock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + u8 old = 1; + + asm("xchgb %b0,%1" + : "+q" (old), "+m" (xl->lock) : : "memory"); + + return old == 0; +} + +static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; +static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners); + +static inline void spinning_lock(struct xen_spinlock *xl) +{ + __get_cpu_var(lock_spinners) = xl; + wmb(); /* set lock of interest before count */ + asm(LOCK_PREFIX " incw %0" + : "+m" (xl->spinners) : : "memory"); +} + +static inline void unspinning_lock(struct xen_spinlock *xl) +{ + asm(LOCK_PREFIX " decw %0" + : "+m" (xl->spinners) : : "memory"); + wmb(); /* decrement count before clearing lock */ + __get_cpu_var(lock_spinners) = NULL; +} + +static noinline int xen_spin_lock_slow(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + int irq = __get_cpu_var(lock_kicker_irq); + int ret; + + /* If kicker interrupts not initialized yet, just spin */ + if (irq == -1) + return 0; + + /* announce we're spinning */ + spinning_lock(xl); + + /* clear pending */ + xen_clear_irq_pending(irq); + + /* check again make sure it didn't become free while + we weren't looking */ + ret = xen_spin_trylock(lock); + if (ret) + goto out; + + /* block until irq becomes pending */ + xen_poll_irq(irq); + kstat_this_cpu.irqs[irq]++; + +out: + unspinning_lock(xl); + return ret; +} + +static void xen_spin_lock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + int timeout; + u8 oldval; + + do { + timeout = 1 << 10; + + asm("1: xchgb %1,%0\n" + " testb %1,%1\n" + " jz 3f\n" + "2: rep;nop\n" + " cmpb $0,%0\n" + " je 1b\n" + " dec %2\n" + " jnz 2b\n" + "3:\n" + : "+m" (xl->lock), "=q" (oldval), "+r" (timeout) + : "1" (1) + : "memory"); + + } while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock))); +} + +static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) +{ + int cpu; + + for_each_online_cpu(cpu) { + /* XXX should mix up next cpu selection */ + if (per_cpu(lock_spinners, cpu) == xl) { + xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); + break; + } + } +} + +static void xen_spin_unlock(struct raw_spinlock *lock) +{ + struct xen_spinlock *xl = (struct xen_spinlock *)lock; + + smp_wmb(); /* make sure no writes get moved after unlock */ + xl->lock = 0; /* release lock */ + + /* make sure unlock happens before kick */ + barrier(); + + if (unlikely(xl->spinners)) + xen_spin_unlock_slow(xl); +} + +static irqreturn_t dummy_handler(int irq, void *dev_id) +{ + BUG(); + return IRQ_HANDLED; +} + +void __cpuinit xen_init_lock_cpu(int cpu) +{ + int irq; + const char *name; + + name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); + irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, + cpu, + dummy_handler, + IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, + name, + NULL); + + if (irq >= 0) { + disable_irq(irq); /* make sure it's never delivered */ + per_cpu(lock_kicker_irq, cpu) = irq; + } + + printk("cpu %d spinlock event irq %d\n", cpu, irq); +} + +void __init xen_init_spinlocks(void) +{ + pv_lock_ops.spin_is_locked = xen_spin_is_locked; + pv_lock_ops.spin_is_contended = xen_spin_is_contended; + pv_lock_ops.spin_lock = xen_spin_lock; + pv_lock_ops.spin_trylock = xen_spin_trylock; + pv_lock_ops.spin_unlock = xen_spin_unlock; +} diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index dd3c23152a2..8847fb34f17 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -50,6 +50,9 @@ void __init xen_setup_vcpu_info_placement(void); #ifdef CONFIG_SMP void xen_smp_init(void); +void __init xen_init_spinlocks(void); +__cpuinit void xen_init_lock_cpu(int cpu); + extern cpumask_t xen_cpu_initialized_map; #else static inline void xen_smp_init(void) {} -- GitLab From e0a5a5d9b006fd441e61685a051fa85d52fb172c Mon Sep 17 00:00:00 2001 From: Alexander van Heukelum Date: Tue, 22 Jul 2008 18:14:16 +0200 Subject: [PATCH 0091/5416] x86, 64-bit, dwarf2: push pushes 8 bytes and popf pops 8 The CFI_ADJUST_CFA_OFFSET dwarf2 annotation of a push/popf pair in ret_from_fork wrongly used a value of 4. It should have been 8. Fix that. Signed-off-by: Alexander van Heukelum Cc: Andi Kleen Cc: heukelum@fastmail.fm Signed-off-by: Ingo Molnar --- arch/x86/kernel/entry_64.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 89434d43960..cf3a0b2d005 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -275,9 +275,9 @@ ENTRY(native_usergs_sysret64) ENTRY(ret_from_fork) CFI_DEFAULT_STACK push kernel_eflags(%rip) - CFI_ADJUST_CFA_OFFSET 4 + CFI_ADJUST_CFA_OFFSET 8 popf # reset kernel eflags - CFI_ADJUST_CFA_OFFSET -4 + CFI_ADJUST_CFA_OFFSET -8 call schedule_tail GET_THREAD_INFO(%rcx) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx) -- GitLab From 32f71aff77b6470d272f80ac28f43f9601c4d140 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 21 Jul 2008 00:52:49 +0100 Subject: [PATCH 0092/5416] x86: PIC, L-APIC and I/O APIC debug information Dump all the PIC, local APIC and I/O APIC information at the fs_initcall() level, which is after ACPI (if used) has initialised PCI information, making the point of invocation consistent across MP-table and ACPI platforms. Remove explicit calls to print_IO_APIC() from elsewhere. Make the interface of all the functions involved consistent between 32-bit and 64-bit versions and make them all static by default by the means of a New-and-Improved(TM) __apicdebuginit() macro. Note that like print_IO_APIC() all these only output anything if "apic=debug" has been passed to the kernel through the command line. Signed-off-by: Maciej W. Rozycki Cc: Chuck Ebbert Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_32.c | 29 +++++++++++++++++++---------- arch/x86/kernel/io_apic_64.c | 31 +++++++++++++++++++------------ arch/x86/pci/acpi.c | 5 ----- include/asm-x86/hw_irq.h | 1 - 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index de9aa0e3a9c..d54455ec985 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -50,6 +50,8 @@ #include #include +#define __apicdebuginit(type) static type __init + int (*ioapic_renumber_irq)(int ioapic, int irq); atomic_t irq_mis_count; @@ -1345,7 +1347,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, ioapic_write_entry(apic, pin, entry); } -void __init print_IO_APIC(void) + +__apicdebuginit(void) print_IO_APIC(void) { int apic, i; union IO_APIC_reg_00 reg_00; @@ -1460,9 +1463,7 @@ void __init print_IO_APIC(void) return; } -#if 0 - -static void print_APIC_bitfield(int base) +__apicdebuginit(void) print_APIC_bitfield(int base) { unsigned int v; int i, j; @@ -1483,7 +1484,7 @@ static void print_APIC_bitfield(int base) } } -void /*__init*/ print_local_APIC(void *dummy) +__apicdebuginit(void) print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; @@ -1567,12 +1568,12 @@ void /*__init*/ print_local_APIC(void *dummy) printk("\n"); } -void print_all_local_APICs(void) +__apicdebuginit(void) print_all_local_APICs(void) { on_each_cpu(print_local_APIC, NULL, 1); } -void /*__init*/ print_PIC(void) +__apicdebuginit(void) print_PIC(void) { unsigned int v; unsigned long flags; @@ -1604,7 +1605,17 @@ void /*__init*/ print_PIC(void) printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } -#endif /* 0 */ +__apicdebuginit(int) print_all_ICs(void) +{ + print_PIC(); + print_all_local_APICs(); + print_IO_APIC(); + + return 0; +} + +fs_initcall(print_all_ICs); + static void __init enable_IO_APIC(void) { @@ -2333,8 +2344,6 @@ void __init setup_IO_APIC(void) setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - if (!acpi_ioapic) - print_IO_APIC(); } /* diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 8269434d170..8cdcc4f287c 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -53,6 +53,8 @@ #include #include +#define __apicdebuginit(type) static type __init + struct irq_cfg { cpumask_t domain; cpumask_t old_domain; @@ -87,8 +89,6 @@ int first_system_vector = 0xfe; char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE}; -#define __apicdebuginit __init - int sis_apic_bug; /* not actually supported, dummy for compile */ static int no_timer_check; @@ -965,7 +965,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, ioapic_write_entry(apic, pin, entry); } -void __apicdebuginit print_IO_APIC(void) + +__apicdebuginit(void) print_IO_APIC(void) { int apic, i; union IO_APIC_reg_00 reg_00; @@ -1059,9 +1060,7 @@ void __apicdebuginit print_IO_APIC(void) return; } -#if 0 - -static __apicdebuginit void print_APIC_bitfield (int base) +__apicdebuginit(void) print_APIC_bitfield(int base) { unsigned int v; int i, j; @@ -1082,7 +1081,7 @@ static __apicdebuginit void print_APIC_bitfield (int base) } } -void __apicdebuginit print_local_APIC(void * dummy) +__apicdebuginit(void) print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; @@ -1159,12 +1158,12 @@ void __apicdebuginit print_local_APIC(void * dummy) printk("\n"); } -void print_all_local_APICs (void) +__apicdebuginit(void) print_all_local_APICs(void) { on_each_cpu(print_local_APIC, NULL, 1); } -void __apicdebuginit print_PIC(void) +__apicdebuginit(void) print_PIC(void) { unsigned int v; unsigned long flags; @@ -1196,7 +1195,17 @@ void __apicdebuginit print_PIC(void) printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } -#endif /* 0 */ +__apicdebuginit(int) print_all_ICs(void) +{ + print_PIC(); + print_all_local_APICs(); + print_IO_APIC(); + + return 0; +} + +fs_initcall(print_all_ICs); + void __init enable_IO_APIC(void) { @@ -1849,8 +1858,6 @@ void __init setup_IO_APIC(void) setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); - if (!acpi_ioapic) - print_IO_APIC(); } struct sysfs_ioapic_data { diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 19af06927fb..1d88d2b3977 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -250,10 +250,5 @@ int __init pci_acpi_init(void) acpi_pci_irq_enable(dev); } -#ifdef CONFIG_X86_IO_APIC - if (acpi_ioapic) - print_IO_APIC(); -#endif - return 0; } diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 77ba51df566..83e0048dca7 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -64,7 +64,6 @@ extern unsigned long io_apic_irqs; extern void init_VISWS_APIC_irqs(void); extern void setup_IO_APIC(void); extern void disable_IO_APIC(void); -extern void print_IO_APIC(void); extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); extern void setup_ioapic_dest(void); -- GitLab From 0791e13fbb1ea4e1808d055922c3f116b924bdc9 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 21 Jul 2008 01:28:43 +0100 Subject: [PATCH 0093/5416] x86: fix up a comment in ack_APIC_irq() Adjust a comment in ack_APIC_irq() according to the recent removal of CONFIG_X86_GOOD_APIC. Signed-off-by: Maciej W. Rozycki Signed-off-by: Ingo Molnar --- include/asm-x86/apic.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 133c998161c..e9e09b2ee7c 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -76,9 +76,7 @@ extern int get_physical_broadcast(void); static inline void ack_APIC_irq(void) { /* - * ack_APIC_irq() actually gets compiled as a single instruction: - * - a single rmw on Pentium/82489DX - * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) + * ack_APIC_irq() actually gets compiled as a single instruction * ... yummie. */ -- GitLab From 510b37258dfd61693ca6c039865c78bd996e3718 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 22 Jul 2008 13:20:22 -0700 Subject: [PATCH 0094/5416] x86: move declaring x2apic_extra_bits it is for uv only Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_phys.c | 2 -- arch/x86/kernel/genx2apic_uv_x.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index f35a3bf3a9e..3229c68aedd 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -10,8 +10,6 @@ #include #include -DEFINE_PER_CPU(int, x2apic_extra_bits); - static int x2apic_phys; static int set_x2apic_phys_mode(char *arg) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 14a9772778e..169388c4cce 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -26,6 +26,8 @@ #include #include +DEFINE_PER_CPU(int, x2apic_extra_bits); + static enum uv_system_type uv_system_type; static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -- GitLab From 36a028de785c6e6f15ac84f8b3b087b89137ea26 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 24 Jul 2008 13:52:28 +0200 Subject: [PATCH 0095/5416] x86: apic unification - merge down lapic_get_maxlvt No code change on binary level. Signed-off-by: Cyrill Gorcunov Cc: macro@linux-mips.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 8 ++++++-- arch/x86/kernel/apic_64.c | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d6c89835837..447dd8c5c0e 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -193,9 +193,13 @@ int get_physical_broadcast(void) */ int lapic_get_maxlvt(void) { - unsigned int v = apic_read(APIC_LVR); + unsigned int v; - /* 82489DXs do not report # of LVT entries. */ + v = apic_read(APIC_LVR); + /* + * - we always have APIC integrated on 64bit mode + * - 82489DXs do not report # of LVT entries + */ return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7f1f030da7e..4fa2a8620c2 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -158,11 +158,14 @@ void __cpuinit enable_NMI_through_LVT0(void) */ int lapic_get_maxlvt(void) { - unsigned int v, maxlvt; + unsigned int v; v = apic_read(APIC_LVR); - maxlvt = GET_APIC_MAXLVT(v); - return maxlvt; + /* + * - we always have APIC integrated on 64bit mode + * - 82489DXs do not report # of LVT entries + */ + return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } /* -- GitLab From d4c63ec060f3315653c0ae5bc3a7fe2419a2282f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 24 Jul 2008 13:52:29 +0200 Subject: [PATCH 0096/5416] x86: apic unification - merge down enable_NMI_through_LVT0 No code change on binary level. Signed-off-by: Cyrill Gorcunov Cc: macro@linux-mips.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 8 ++++++-- arch/x86/kernel/apic_64.c | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 447dd8c5c0e..01708f128ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -172,11 +172,15 @@ u32 safe_apic_wait_icr_idle(void) */ void __cpuinit enable_NMI_through_LVT0(void) { - unsigned int v = APIC_DM_NMI; + unsigned int v; + + /* unmask and set to NMI */ + v = APIC_DM_NMI; - /* Level triggered for 82489DX */ + /* Level triggered for 82489DX (32bit mode) */ if (!lapic_is_integrated()) v |= APIC_LVT_LEVEL_TRIGGER; + apic_write(APIC_LVT0, v); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 4fa2a8620c2..7615b4b9c3f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -150,6 +150,11 @@ void __cpuinit enable_NMI_through_LVT0(void) /* unmask and set to NMI */ v = APIC_DM_NMI; + + /* Level triggered for 82489DX (32bit mode) */ + if (!lapic_is_integrated()) + v |= APIC_LVT_LEVEL_TRIGGER; + apic_write(APIC_LVT0, v); } -- GitLab From 461d159694d683c9e43ead07720a3a0f17f6f060 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 09:19:05 +0530 Subject: [PATCH 0097/5416] x86_64: Declare new_utsname in asm-x86/syscalls.h Signed-off-by: Jaswinder Singh --- include/asm-x86/syscalls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-x86/syscalls.h b/include/asm-x86/syscalls.h index 3d6b159d348..87803da4401 100644 --- a/include/asm-x86/syscalls.h +++ b/include/asm-x86/syscalls.h @@ -5,7 +5,6 @@ * * This file is released under the GPLv2. * See the file COPYING for more details. - * */ #ifndef _ASM_X86_SYSCALLS_H @@ -87,6 +86,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *); /* kernel/sys_x86_64.c */ asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); +struct new_utsname; asmlinkage long sys_uname(struct new_utsname __user *); #endif /* CONFIG_X86_32 */ -- GitLab From 4fe702c7e401f912c0edd294af6e37c02f451bbb Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 10:19:27 +0530 Subject: [PATCH 0098/5416] X86_32: declare pt_regs_access as unsigned long Fixed pt_regs_access to unsigned long as per X86_64 Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e37dccce85d..fc3e8dcd9da 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -69,7 +69,7 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 -static long *pt_regs_access(struct pt_regs *regs, unsigned long regno) +static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); regno >>= 2; -- GitLab From e7f08dfdaa82def3d685d16fdb99203cbb67ec95 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 10:42:26 +0530 Subject: [PATCH 0099/5416] X86_SMP: smp.c declare functions before they get used declared following smp interrupts in asm-x86/hw_irq.h: smp_reschedule_interrupt, smp_call_function_interrupt, smp_call_function_single_interrupt Signed-off-by: Jaswinder Singh --- include/asm-x86/hw_irq.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 40b941ac81c..08900eb90a9 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -102,6 +102,11 @@ extern void smp_error_interrupt(struct pt_regs *); extern asmlinkage void smp_spurious_interrupt(void); extern asmlinkage void smp_error_interrupt(void); #endif +#ifdef CONFIG_X86_SMP +extern void smp_reschedule_interrupt(struct pt_regs *); +extern void smp_call_function_interrupt(struct pt_regs *); +extern void smp_call_function_single_interrupt(struct pt_regs *); +#endif #ifdef CONFIG_X86_32 extern void (*const interrupt[NR_IRQS])(void); -- GitLab From f86c99853b22576ee8dc4fa27ff6f3c0c7ce0ef8 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 10:52:53 +0530 Subject: [PATCH 0100/5416] X86_SMP: smpboot.c declare idle_thread_array and smp_b_stepping as static Signed-off-by: Jaswinder Singh --- arch/x86/kernel/smpboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 4b53a647bc0..a9331a42f76 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -88,7 +88,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) #else -struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; +static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif @@ -129,7 +129,7 @@ static int boot_cpu_logical_apicid; static cpumask_t cpu_sibling_setup_map; /* Set if we find a B stepping CPU */ -int __cpuinitdata smp_b_stepping; +static int __cpuinitdata smp_b_stepping; #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) -- GitLab From 2907829cd0ffdef69083985ba28cf1cf3857c681 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 11:05:56 +0530 Subject: [PATCH 0101/5416] X86_SMP: ipi.c declare functions before they get used move upwards for __send_IPI_shortcut and send_IPI_mask_bitmask Signed-off-by: Jaswinder Singh --- arch/x86/kernel/ipi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 3f7537b669d..f1c688e46f3 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -20,6 +20,8 @@ #ifdef CONFIG_X86_32 #include +#include + /* * the following functions deal with sending IPIs between CPUs. * @@ -147,7 +149,6 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector) } /* must come after the send_IPI functions above for inlining */ -#include static int convert_apicid_to_cpu(int apic_id) { int i; -- GitLab From b2139aa0eec330c711c5a279db361e5ef1178e78 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Fri, 25 Jul 2008 11:32:38 +0530 Subject: [PATCH 0102/5416] X86_SMP: tlb_XX.c declare smp_invalidate_interrupt before they get used declare smp_invalidate_interrupt in asm-x86/hw_irq.h for X86_32 and X86_64 Signed-off-by: Jaswinder Singh --- include/asm-x86/hw_irq.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index 08900eb90a9..67685f1d318 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -106,6 +106,11 @@ extern asmlinkage void smp_error_interrupt(void); extern void smp_reschedule_interrupt(struct pt_regs *); extern void smp_call_function_interrupt(struct pt_regs *); extern void smp_call_function_single_interrupt(struct pt_regs *); +#ifdef CONFIG_X86_32 +extern void smp_invalidate_interrupt(struct pt_regs *); +#else +extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *); +#endif #endif #ifdef CONFIG_X86_32 -- GitLab From 3c9339049df5cc3a468c11de6c4101a1ea8c3d83 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 25 Jul 2008 11:32:36 +0200 Subject: [PATCH 0103/5416] x86: fix ds.c build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/ds.c: In function ‘ds_allocate_buffer': arch/x86/kernel/ds.c:339: error: implicit declaration of function ‘PAGE_ALIGN' Signed-off-by: Ingo Molnar --- arch/x86/kernel/ds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 24a323c9599..ab21c270bfa 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -29,6 +29,7 @@ #include #include #include +#include /* -- GitLab From 021f8b75e78f9da67421a2c2e320e8934a90914a Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:45 +0200 Subject: [PATCH 0104/5416] x86: add PCI IDs for AMD Barcelona PCI devices Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- include/linux/pci_ids.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c3b1761aba2..917d48e5ea0 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -497,6 +497,11 @@ #define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP 0x1101 #define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102 #define PCI_DEVICE_ID_AMD_K8_NB_MISC 0x1103 +#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200 +#define PCI_DEVICE_ID_AMD_10H_NB_MAP 0x1201 +#define PCI_DEVICE_ID_AMD_10H_NB_DRAM 0x1202 +#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203 +#define PCI_DEVICE_ID_AMD_10H_NB_LINK 0x1204 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 -- GitLab From 286f571837ba9d67625afd015366d79345abb414 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:46 +0200 Subject: [PATCH 0105/5416] x86: apic_*.c: add description to AMD's extended LVT functions Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 +++ arch/x86/kernel/apic_64.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d6c89835837..fad94b0decc 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -646,6 +646,9 @@ int setup_profiling_timer(unsigned int multiplier) * * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and * MCE interrupts are supported. Thus MCE offset must be set to 0. + * + * If mask=1, the LVT entry does not generate interrupts while mask=0 + * enables the vector. See also the BKDGs. */ #define APIC_EILVT_LVTOFF_MCE 0 diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7f1f030da7e..42bf69f8bc8 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -205,6 +205,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) * * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and * MCE interrupts are supported. Thus MCE offset must be set to 0. + * + * If mask=1, the LVT entry does not generate interrupts while mask=0 + * enables the vector. See also the BKDGs. */ #define APIC_EILVT_LVTOFF_MCE 0 -- GitLab From 12f2b2610e812627acf338aaf043fef20bb726ca Mon Sep 17 00:00:00 2001 From: Barry Kasindorf Date: Tue, 22 Jul 2008 21:08:47 +0200 Subject: [PATCH 0106/5416] oprofile: Add support for AMD Family 11h This patch add support for AMD Family 11h CPUs. Signed-off-by: Barry Kasindorf Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 3f90289410e..33db99ab90c 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -436,6 +436,10 @@ int __init op_nmi_init(struct oprofile_operations *ops) model = &op_athlon_spec; cpu_type = "x86-64/family10"; break; + case 0x11: + model = &op_athlon_spec; + cpu_type = "x86-64/family11h"; + break; } break; -- GitLab From adf5ec0bca553b763a6b9baed2677a4c7470025b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:48 +0200 Subject: [PATCH 0107/5416] x86/oprofile: introduce model specific init/exit functions This patch implements model specific OProfile init/exit functions for x86 CPUs. Though there is more rework needed at the initialization code, this new introduced functions allow it to keep model specific code in the corresponding op_model_*.c files. The function interface is the same as for oprofile_arch_init/exit(). Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 11 ++++++++++- arch/x86/oprofile/op_model_athlon.c | 18 +++++++++++++++--- arch/x86/oprofile/op_x86_model.h | 2 ++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 33db99ab90c..75e889156f2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -1,10 +1,11 @@ /** * @file nmi_int.c * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2008 OProfile authors * @remark Read the file COPYING * * @author John Levon + * @author Robert Richter */ #include @@ -411,6 +412,7 @@ int __init op_nmi_init(struct oprofile_operations *ops) __u8 vendor = boot_cpu_data.x86_vendor; __u8 family = boot_cpu_data.x86; char *cpu_type; + int ret = 0; if (!cpu_has_apic) return -ENODEV; @@ -466,6 +468,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } + if (model->init) + ret = model->init(ops); + if (ret) + return ret; + init_sysfs(); using_nmi = 1; ops->create_files = nmi_create_files; @@ -482,4 +489,6 @@ void op_nmi_exit(void) { if (using_nmi) exit_sysfs(); + if (model->exit) + model->exit(); } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 3d534879a9d..dd8b1dcd163 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -1,14 +1,15 @@ /* - * @file op_model_athlon.h + * @file op_model_athlon.c * athlon / K7 / K8 / Family 10h model-specific MSR operations * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2008 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Philippe Elie * @author Graydon Hoare - */ + * @author Robert Richter +*/ #include #include @@ -178,7 +179,18 @@ static void athlon_shutdown(struct op_msrs const * const msrs) } } +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) +{ +} + struct op_x86_model_spec const op_athlon_spec = { + .init = op_amd_init, + .exit = op_amd_exit, .num_counters = NUM_COUNTERS, .num_controls = NUM_CONTROLS, .fill_in_addresses = &athlon_fill_in_addresses, diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 45b605fa71d..ee9ca96253f 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -32,6 +32,8 @@ struct pt_regs; * various x86 CPU models' perfctr support. */ struct op_x86_model_spec { + int (*init)(struct oprofile_operations *ops); + void (*exit)(void); unsigned int const num_counters; unsigned int const num_controls; void (*fill_in_addresses)(struct op_msrs * const msrs); -- GitLab From dfa154289701ed315909b4e371a0381c52c8bdc9 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:49 +0200 Subject: [PATCH 0108/5416] x86/oprofile: Minor changes in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index dd8b1dcd163..d25d7f19503 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -45,6 +45,8 @@ static unsigned long reset_value[NUM_COUNTERS]; +/* functions for op_athlon_spec */ + static void athlon_fill_in_addresses(struct op_msrs * const msrs) { int i; -- GitLab From 6657fe4f5650ff7174d418d4bfa50c4640e81a2b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:50 +0200 Subject: [PATCH 0109/5416] x86/oprofile: renaming athlon_*() into op_amd_*() These functions contain code for all AMD CPUs. The new names fit better. Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 8 ++++---- arch/x86/oprofile/op_model_athlon.c | 28 ++++++++++++++-------------- arch/x86/oprofile/op_x86_model.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 75e889156f2..b29819313f2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -425,21 +425,21 @@ int __init op_nmi_init(struct oprofile_operations *ops) default: return -ENODEV; case 6: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "i386/athlon"; break; case 0xf: - model = &op_athlon_spec; + model = &op_amd_spec; /* Actually it could be i386/hammer too, but give user space an consistent name. */ cpu_type = "x86-64/hammer"; break; case 0x10: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "x86-64/family10"; break; case 0x11: - model = &op_athlon_spec; + model = &op_amd_spec; cpu_type = "x86-64/family11h"; break; } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index d25d7f19503..40ecb020c7d 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -45,9 +45,9 @@ static unsigned long reset_value[NUM_COUNTERS]; -/* functions for op_athlon_spec */ +/* functions for op_amd_spec */ -static void athlon_fill_in_addresses(struct op_msrs * const msrs) +static void op_amd_fill_in_addresses(struct op_msrs * const msrs) { int i; @@ -67,7 +67,7 @@ static void athlon_fill_in_addresses(struct op_msrs * const msrs) } -static void athlon_setup_ctrs(struct op_msrs const * const msrs) +static void op_amd_setup_ctrs(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -116,7 +116,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs) } -static int athlon_check_ctrs(struct pt_regs * const regs, +static int op_amd_check_ctrs(struct pt_regs * const regs, struct op_msrs const * const msrs) { unsigned int low, high; @@ -137,7 +137,7 @@ static int athlon_check_ctrs(struct pt_regs * const regs, } -static void athlon_start(struct op_msrs const * const msrs) +static void op_amd_start(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -151,7 +151,7 @@ static void athlon_start(struct op_msrs const * const msrs) } -static void athlon_stop(struct op_msrs const * const msrs) +static void op_amd_stop(struct op_msrs const * const msrs) { unsigned int low, high; int i; @@ -167,7 +167,7 @@ static void athlon_stop(struct op_msrs const * const msrs) } } -static void athlon_shutdown(struct op_msrs const * const msrs) +static void op_amd_shutdown(struct op_msrs const * const msrs) { int i; @@ -190,15 +190,15 @@ static void op_amd_exit(void) { } -struct op_x86_model_spec const op_athlon_spec = { +struct op_x86_model_spec const op_amd_spec = { .init = op_amd_init, .exit = op_amd_exit, .num_counters = NUM_COUNTERS, .num_controls = NUM_CONTROLS, - .fill_in_addresses = &athlon_fill_in_addresses, - .setup_ctrs = &athlon_setup_ctrs, - .check_ctrs = &athlon_check_ctrs, - .start = &athlon_start, - .stop = &athlon_stop, - .shutdown = &athlon_shutdown + .fill_in_addresses = &op_amd_fill_in_addresses, + .setup_ctrs = &op_amd_setup_ctrs, + .check_ctrs = &op_amd_check_ctrs, + .start = &op_amd_start, + .stop = &op_amd_stop, + .shutdown = &op_amd_shutdown }; diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index ee9ca96253f..05a0261ba0c 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -48,6 +48,6 @@ struct op_x86_model_spec { extern struct op_x86_model_spec const op_ppro_spec; extern struct op_x86_model_spec const op_p4_spec; extern struct op_x86_model_spec const op_p4_ht2_spec; -extern struct op_x86_model_spec const op_athlon_spec; +extern struct op_x86_model_spec const op_amd_spec; #endif /* OP_X86_MODEL_H */ -- GitLab From 73185e0a5d11d729d451692034fbe55a9eba7468 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:51 +0200 Subject: [PATCH 0110/5416] drivers/oprofile: coding style fixes in buffer_sync.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- drivers/oprofile/buffer_sync.c | 111 +++++++++++++++++---------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 9304c455507..69a732778ba 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -33,7 +33,7 @@ #include "event_buffer.h" #include "cpu_buffer.h" #include "buffer_sync.h" - + static LIST_HEAD(dying_tasks); static LIST_HEAD(dead_tasks); static cpumask_t marked_cpus = CPU_MASK_NONE; @@ -48,10 +48,11 @@ static void process_task_mortuary(void); * Can be invoked from softirq via RCU callback due to * call_rcu() of the task struct, hence the _irqsave. */ -static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) +static int +task_free_notify(struct notifier_block *self, unsigned long val, void *data) { unsigned long flags; - struct task_struct * task = data; + struct task_struct *task = data; spin_lock_irqsave(&task_mortuary, flags); list_add(&task->tasks, &dying_tasks); spin_unlock_irqrestore(&task_mortuary, flags); @@ -62,13 +63,14 @@ static int task_free_notify(struct notifier_block * self, unsigned long val, voi /* The task is on its way out. A sync of the buffer means we can catch * any remaining samples for this task. */ -static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data) +static int +task_exit_notify(struct notifier_block *self, unsigned long val, void *data) { /* To avoid latency problems, we only process the current CPU, * hoping that most samples for the task are on this CPU */ sync_buffer(raw_smp_processor_id()); - return 0; + return 0; } @@ -77,11 +79,12 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi * we don't lose any. This does not have to be exact, it's a QoI issue * only. */ -static int munmap_notify(struct notifier_block * self, unsigned long val, void * data) +static int +munmap_notify(struct notifier_block *self, unsigned long val, void *data) { unsigned long addr = (unsigned long)data; - struct mm_struct * mm = current->mm; - struct vm_area_struct * mpnt; + struct mm_struct *mm = current->mm; + struct vm_area_struct *mpnt; down_read(&mm->mmap_sem); @@ -99,11 +102,12 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void * return 0; } - + /* We need to be told about new modules so we don't attribute to a previously * loaded module, or drop the samples on the floor. */ -static int module_load_notify(struct notifier_block * self, unsigned long val, void * data) +static int +module_load_notify(struct notifier_block *self, unsigned long val, void *data) { #ifdef CONFIG_MODULES if (val != MODULE_STATE_COMING) @@ -118,7 +122,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v return 0; } - + static struct notifier_block task_free_nb = { .notifier_call = task_free_notify, }; @@ -135,7 +139,7 @@ static struct notifier_block module_load_nb = { .notifier_call = module_load_notify, }; - + static void end_sync(void) { end_cpu_work(); @@ -208,14 +212,14 @@ static inline unsigned long fast_get_dcookie(struct path *path) * not strictly necessary but allows oprofile to associate * shared-library samples with particular applications */ -static unsigned long get_exec_dcookie(struct mm_struct * mm) +static unsigned long get_exec_dcookie(struct mm_struct *mm) { unsigned long cookie = NO_COOKIE; - struct vm_area_struct * vma; - + struct vm_area_struct *vma; + if (!mm) goto out; - + for (vma = mm->mmap; vma; vma = vma->vm_next) { if (!vma->vm_file) continue; @@ -235,13 +239,14 @@ out: * sure to do this lookup before a mm->mmap modification happens so * we don't lose track. */ -static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset) +static unsigned long +lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) { unsigned long cookie = NO_COOKIE; - struct vm_area_struct * vma; + struct vm_area_struct *vma; for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { - + if (addr < vma->vm_start || addr >= vma->vm_end) continue; @@ -265,7 +270,7 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o static unsigned long last_cookie = INVALID_COOKIE; - + static void add_cpu_switch(int i) { add_event_entry(ESCAPE_CODE); @@ -278,16 +283,16 @@ static void add_kernel_ctx_switch(unsigned int in_kernel) { add_event_entry(ESCAPE_CODE); if (in_kernel) - add_event_entry(KERNEL_ENTER_SWITCH_CODE); + add_event_entry(KERNEL_ENTER_SWITCH_CODE); else - add_event_entry(KERNEL_EXIT_SWITCH_CODE); + add_event_entry(KERNEL_EXIT_SWITCH_CODE); } - + static void -add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) +add_user_ctx_switch(struct task_struct const *task, unsigned long cookie) { add_event_entry(ESCAPE_CODE); - add_event_entry(CTX_SWITCH_CODE); + add_event_entry(CTX_SWITCH_CODE); add_event_entry(task->pid); add_event_entry(cookie); /* Another code for daemon back-compat */ @@ -296,7 +301,7 @@ add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) add_event_entry(task->tgid); } - + static void add_cookie_switch(unsigned long cookie) { add_event_entry(ESCAPE_CODE); @@ -304,7 +309,7 @@ static void add_cookie_switch(unsigned long cookie) add_event_entry(cookie); } - + static void add_trace_begin(void) { add_event_entry(ESCAPE_CODE); @@ -319,13 +324,13 @@ static void add_sample_entry(unsigned long offset, unsigned long event) } -static int add_us_sample(struct mm_struct * mm, struct op_sample * s) +static int add_us_sample(struct mm_struct *mm, struct op_sample *s) { unsigned long cookie; off_t offset; - - cookie = lookup_dcookie(mm, s->eip, &offset); - + + cookie = lookup_dcookie(mm, s->eip, &offset); + if (cookie == INVALID_COOKIE) { atomic_inc(&oprofile_stats.sample_lost_no_mapping); return 0; @@ -341,13 +346,13 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s) return 1; } - + /* Add a sample to the global event buffer. If possible the * sample is converted into a persistent dentry/offset pair * for later lookup from userspace. */ static int -add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) +add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) { if (in_kernel) { add_sample_entry(s->eip, s->event); @@ -359,9 +364,9 @@ add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) } return 0; } - -static void release_mm(struct mm_struct * mm) + +static void release_mm(struct mm_struct *mm) { if (!mm) return; @@ -370,9 +375,9 @@ static void release_mm(struct mm_struct * mm) } -static struct mm_struct * take_tasks_mm(struct task_struct * task) +static struct mm_struct *take_tasks_mm(struct task_struct *task) { - struct mm_struct * mm = get_task_mm(task); + struct mm_struct *mm = get_task_mm(task); if (mm) down_read(&mm->mmap_sem); return mm; @@ -383,10 +388,10 @@ static inline int is_code(unsigned long val) { return val == ESCAPE_CODE; } - + /* "acquire" as many cpu buffer slots as we can */ -static unsigned long get_slots(struct oprofile_cpu_buffer * b) +static unsigned long get_slots(struct oprofile_cpu_buffer *b) { unsigned long head = b->head_pos; unsigned long tail = b->tail_pos; @@ -412,7 +417,7 @@ static unsigned long get_slots(struct oprofile_cpu_buffer * b) } -static void increment_tail(struct oprofile_cpu_buffer * b) +static void increment_tail(struct oprofile_cpu_buffer *b) { unsigned long new_tail = b->tail_pos + 1; @@ -435,8 +440,8 @@ static void process_task_mortuary(void) { unsigned long flags; LIST_HEAD(local_dead_tasks); - struct task_struct * task; - struct task_struct * ttask; + struct task_struct *task; + struct task_struct *ttask; spin_lock_irqsave(&task_mortuary, flags); @@ -493,7 +498,7 @@ void sync_buffer(int cpu) { struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); struct mm_struct *mm = NULL; - struct task_struct * new; + struct task_struct *new; unsigned long cookie = 0; int in_kernel = 1; unsigned int i; @@ -501,7 +506,7 @@ void sync_buffer(int cpu) unsigned long available; mutex_lock(&buffer_mutex); - + add_cpu_switch(cpu); /* Remember, only we can modify tail_pos */ @@ -509,8 +514,8 @@ void sync_buffer(int cpu) available = get_slots(cpu_buf); for (i = 0; i < available; ++i) { - struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; - + struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos]; + if (is_code(s->eip)) { if (s->event <= CPU_IS_KERNEL) { /* kernel/userspace switch */ @@ -522,7 +527,7 @@ void sync_buffer(int cpu) state = sb_bt_start; add_trace_begin(); } else { - struct mm_struct * oldmm = mm; + struct mm_struct *oldmm = mm; /* userspace context switch */ new = (struct task_struct *)s->event; @@ -533,13 +538,11 @@ void sync_buffer(int cpu) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); } - } else { - if (state >= sb_bt_start && - !add_sample(mm, s, in_kernel)) { - if (state == sb_bt_start) { - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); - } + } else if (state >= sb_bt_start && + !add_sample(mm, s, in_kernel)) { + if (state == sb_bt_start) { + state = sb_bt_ignore; + atomic_inc(&oprofile_stats.bt_lost_no_mapping); } } -- GitLab From 5e11f98dcebc40c9d67e8d21a5f47248444c17a8 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:52 +0200 Subject: [PATCH 0111/5416] OProfile: moving increment_tail() in buffer_sync.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- drivers/oprofile/buffer_sync.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 69a732778ba..615929f6f0c 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -268,6 +268,17 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) return cookie; } +static void increment_tail(struct oprofile_cpu_buffer *b) +{ + unsigned long new_tail = b->tail_pos + 1; + + rmb(); + + if (new_tail < b->buffer_size) + b->tail_pos = new_tail; + else + b->tail_pos = 0; +} static unsigned long last_cookie = INVALID_COOKIE; @@ -417,19 +428,6 @@ static unsigned long get_slots(struct oprofile_cpu_buffer *b) } -static void increment_tail(struct oprofile_cpu_buffer *b) -{ - unsigned long new_tail = b->tail_pos + 1; - - rmb(); - - if (new_tail < b->buffer_size) - b->tail_pos = new_tail; - else - b->tail_pos = 0; -} - - /* Move tasks along towards death. Any tasks on dead_tasks * will definitely have no remaining references in any * CPU buffers at this point, because we use two lists, -- GitLab From ee648bc77f11b57d15a68d336fc30e343198f893 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:53 +0200 Subject: [PATCH 0112/5416] OProfile: add IBS code macros Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- include/linux/oprofile.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 041bb31100f..bcb8f725427 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -36,6 +36,8 @@ #define XEN_ENTER_SWITCH_CODE 10 #define SPU_PROFILING_CODE 11 #define SPU_CTX_SWITCH_CODE 12 +#define IBS_FETCH_CODE 13 +#define IBS_OP_CODE 14 struct super_block; struct dentry; -- GitLab From 345c25730d085c45622ac779da4dbd97dc3a10fe Mon Sep 17 00:00:00 2001 From: Barry Kasindorf Date: Tue, 22 Jul 2008 21:08:54 +0200 Subject: [PATCH 0113/5416] x86/oprofile: add IBS support for AMD CPUs, IBS buffer handling routines This patchset supports the new profiling hardware available in the latest AMD CPUs in the oProfile driver. Signed-off-by: Barry Kasindorf Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- drivers/oprofile/buffer_sync.c | 72 +++++++++++++++++++++++++++++++++- drivers/oprofile/cpu_buffer.c | 68 +++++++++++++++++++++++++++++++- drivers/oprofile/cpu_buffer.h | 2 + 3 files changed, 140 insertions(+), 2 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 615929f6f0c..e1782d2df09 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -5,6 +5,7 @@ * @remark Read the file COPYING * * @author John Levon + * @author Barry Kasindorf * * This is the core of the buffer management. Each * CPU buffer is processed and entered into the @@ -272,7 +273,7 @@ static void increment_tail(struct oprofile_cpu_buffer *b) { unsigned long new_tail = b->tail_pos + 1; - rmb(); + rmb(); /* be sure fifo pointers are synchromized */ if (new_tail < b->buffer_size) b->tail_pos = new_tail; @@ -327,6 +328,67 @@ static void add_trace_begin(void) add_event_entry(TRACE_BEGIN_CODE); } +#define IBS_FETCH_CODE_SIZE 2 +#define IBS_OP_CODE_SIZE 5 +#define IBS_EIP(offset) \ + (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip) +#define IBS_EVENT(offset) \ + (((struct op_sample *)&cpu_buf->buffer[(offset)])->event) + +/* + * Add IBS fetch and op entries to event buffer + */ +static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, + int in_kernel, struct mm_struct *mm) +{ + unsigned long rip; + int i, count; + unsigned long ibs_cookie = 0; + off_t offset; + + increment_tail(cpu_buf); /* move to RIP entry */ + + rip = IBS_EIP(cpu_buf->tail_pos); + +#ifdef __LP64__ + rip += IBS_EVENT(cpu_buf->tail_pos) << 32; +#endif + + if (mm) { + ibs_cookie = lookup_dcookie(mm, rip, &offset); + + if (ibs_cookie == NO_COOKIE) + offset = rip; + if (ibs_cookie == INVALID_COOKIE) { + atomic_inc(&oprofile_stats.sample_lost_no_mapping); + offset = rip; + } + if (ibs_cookie != last_cookie) { + add_cookie_switch(ibs_cookie); + last_cookie = ibs_cookie; + } + } else + offset = rip; + + add_event_entry(ESCAPE_CODE); + add_event_entry(code); + add_event_entry(offset); /* Offset from Dcookie */ + + /* we send the Dcookie offset, but send the raw Linear Add also*/ + add_event_entry(IBS_EIP(cpu_buf->tail_pos)); + add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); + + if (code == IBS_FETCH_CODE) + count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ + else + count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ + + for (i = 0; i < count; i++) { + increment_tail(cpu_buf); + add_event_entry(IBS_EIP(cpu_buf->tail_pos)); + add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); + } +} static void add_sample_entry(unsigned long offset, unsigned long event) { @@ -524,6 +586,14 @@ void sync_buffer(int cpu) } else if (s->event == CPU_TRACE_BEGIN) { state = sb_bt_start; add_trace_begin(); + } else if (s->event == IBS_FETCH_BEGIN) { + state = sb_bt_start; + add_ibs_begin(cpu_buf, + IBS_FETCH_CODE, in_kernel, mm); + } else if (s->event == IBS_OP_BEGIN) { + state = sb_bt_start; + add_ibs_begin(cpu_buf, + IBS_OP_CODE, in_kernel, mm); } else { struct mm_struct *oldmm = mm; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 2450b3a393f..c9ac4e15691 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -5,6 +5,7 @@ * @remark Read the file COPYING * * @author John Levon + * @author Barry Kasindorf * * Each CPU has a local buffer that stores PC value/event * pairs. We also log context switches when we notice them. @@ -207,7 +208,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, return 1; } -static int oprofile_begin_trace(struct oprofile_cpu_buffer * cpu_buf) +static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) { if (nr_available_slots(cpu_buf) < 4) { cpu_buf->sample_lost_overflow++; @@ -252,6 +253,71 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) oprofile_add_ext_sample(pc, regs, event, is_kernel); } +#define MAX_IBS_SAMPLE_SIZE 14 +static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf, + unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code) +{ + struct task_struct *task; + + cpu_buf->sample_received++; + + if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) { + cpu_buf->sample_lost_overflow++; + return 0; + } + + is_kernel = !!is_kernel; + + /* notice a switch from user->kernel or vice versa */ + if (cpu_buf->last_is_kernel != is_kernel) { + cpu_buf->last_is_kernel = is_kernel; + add_code(cpu_buf, is_kernel); + } + + /* notice a task switch */ + if (!is_kernel) { + task = current; + + if (cpu_buf->last_task != task) { + cpu_buf->last_task = task; + add_code(cpu_buf, (unsigned long)task); + } + } + + add_code(cpu_buf, ibs_code); + add_sample(cpu_buf, ibs[0], ibs[1]); + add_sample(cpu_buf, ibs[2], ibs[3]); + add_sample(cpu_buf, ibs[4], ibs[5]); + + if (ibs_code == IBS_OP_BEGIN) { + add_sample(cpu_buf, ibs[6], ibs[7]); + add_sample(cpu_buf, ibs[8], ibs[9]); + add_sample(cpu_buf, ibs[10], ibs[11]); + } + + return 1; +} + +void oprofile_add_ibs_sample(struct pt_regs *const regs, + unsigned int * const ibs_sample, u8 code) +{ + int is_kernel = !user_mode(regs); + unsigned long pc = profile_pc(regs); + + struct oprofile_cpu_buffer *cpu_buf = + &per_cpu(cpu_buffer, smp_processor_id()); + + if (!backtrace_depth) { + log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code); + return; + } + + /* if log_sample() fails we can't backtrace since we lost the source + * of this event */ + if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code)) + oprofile_ops.backtrace(regs, backtrace_depth); +} + void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index c3e366b5226..9c44d004da6 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -55,5 +55,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); /* transient events for the CPU buffer -> event buffer */ #define CPU_IS_KERNEL 1 #define CPU_TRACE_BEGIN 2 +#define IBS_FETCH_BEGIN 3 +#define IBS_OP_BEGIN 4 #endif /* OPROFILE_CPU_BUFFER_H */ -- GitLab From 56784f11df473b4c1d9d0e37777fd7c0b77b6bca Mon Sep 17 00:00:00 2001 From: Barry Kasindorf Date: Tue, 22 Jul 2008 21:08:55 +0200 Subject: [PATCH 0114/5416] x86/oprofile: add IBS support for AMD CPUs, model specific code This patchset supports the new profiling hardware available in the latest AMD CPUs in the oProfile driver. Signed-off-by: Barry Kasindorf Signed-off-by: Robert Richter Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 257 ++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 40ecb020c7d..229e0b4e21e 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -9,9 +9,13 @@ * @author Philippe Elie * @author Graydon Hoare * @author Robert Richter + * @author Barry Kasindorf */ #include +#include +#include + #include #include #include @@ -43,7 +47,83 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) +#define IBS_FETCH_CTL_HIGH_MASK 0xFFFFFFFF +/* high dword bit IbsFetchCtl[bit 49] */ +#define IBS_FETCH_VALID_BIT (1UL << 17) +/* high dword bit IbsFetchCtl[bit 52] */ +#define IBS_FETCH_PHY_ADDR_VALID_BIT (1UL << 20) +/* high dword bit IbsFetchCtl[bit 48] */ +#define IBS_FETCH_ENABLE (1UL << 16) + +#define IBS_FETCH_CTL_CNT_MASK 0x00000000FFFF0000UL +#define IBS_FETCH_CTL_MAX_CNT_MASK 0x000000000000FFFFUL + +/*IbsOpCtl masks/bits */ +#define IBS_OP_VALID_BIT (1ULL<<18) /* IbsOpCtl[bit18] */ +#define IBS_OP_ENABLE (1ULL<<17) /* IBS_OP_ENABLE[bit17]*/ + +/* Codes used in cpu_buffer.c */ +#define IBS_FETCH_BEGIN 3 +#define IBS_OP_BEGIN 4 + +/*IbsOpData3 masks */ +#define IBS_CTL_LVT_OFFSET_VALID_BIT (1ULL<<8) + +/*PCI Extended Configuration Constants */ +/* MSR to set the IBS control register APIC LVT offset */ +#define IBS_LVT_OFFSET_PCI 0x1CC + +struct ibs_fetch_sample { + /* MSRC001_1031 IBS Fetch Linear Address Register */ + unsigned int ibs_fetch_lin_addr_low; + unsigned int ibs_fetch_lin_addr_high; + /* MSRC001_1030 IBS Fetch Control Register */ + unsigned int ibs_fetch_ctl_low; + unsigned int ibs_fetch_ctl_high; + /* MSRC001_1032 IBS Fetch Physical Address Register */ + unsigned int ibs_fetch_phys_addr_low; + unsigned int ibs_fetch_phys_addr_high; +}; + +struct ibs_op_sample { + /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ + unsigned int ibs_op_rip_low; + unsigned int ibs_op_rip_high; + /* MSRC001_1035 IBS Op Data Register */ + unsigned int ibs_op_data1_low; + unsigned int ibs_op_data1_high; + /* MSRC001_1036 IBS Op Data 2 Register */ + unsigned int ibs_op_data2_low; + unsigned int ibs_op_data2_high; + /* MSRC001_1037 IBS Op Data 3 Register */ + unsigned int ibs_op_data3_low; + unsigned int ibs_op_data3_high; + /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ + unsigned int ibs_dc_linear_low; + unsigned int ibs_dc_linear_high; + /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ + unsigned int ibs_dc_phys_low; + unsigned int ibs_dc_phys_high; +}; + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ +*/ +static void clear_ibs_nmi(void); + static unsigned long reset_value[NUM_COUNTERS]; +static int ibs_allowed; /* AMD Family10h and later */ + +struct op_ibs_config { + unsigned long op_enabled; + unsigned long fetch_enabled; + unsigned long max_cnt_fetch; + unsigned long max_cnt_op; + unsigned long rand_en; + unsigned long dispatched_ops; +}; + +static struct op_ibs_config ibs_config; /* functions for op_amd_spec */ @@ -121,6 +201,8 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, { unsigned int low, high; int i; + struct ibs_fetch_sample ibs_fetch; + struct ibs_op_sample ibs_op; for (i = 0 ; i < NUM_COUNTERS; ++i) { if (!reset_value[i]) @@ -132,6 +214,65 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } + /*If AMD and IBS is available */ + if (ibs_allowed && ibs_config.fetch_enabled) { + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + if (high & IBS_FETCH_VALID_BIT) { + ibs_fetch.ibs_fetch_ctl_high = high; + ibs_fetch.ibs_fetch_ctl_low = low; + rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); + ibs_fetch.ibs_fetch_lin_addr_high = high; + ibs_fetch.ibs_fetch_lin_addr_low = low; + rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); + ibs_fetch.ibs_fetch_phys_addr_high = high; + ibs_fetch.ibs_fetch_phys_addr_low = low; + + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_fetch, + IBS_FETCH_BEGIN); + + /*reenable the IRQ */ + rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); + high &= ~(IBS_FETCH_VALID_BIT); + high |= IBS_FETCH_ENABLE; + low &= IBS_FETCH_CTL_MAX_CNT_MASK; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + } + + if (ibs_allowed && ibs_config.op_enabled) { + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + if (low & IBS_OP_VALID_BIT) { + rdmsr(MSR_AMD64_IBSOPRIP, low, high); + ibs_op.ibs_op_rip_low = low; + ibs_op.ibs_op_rip_high = high; + rdmsr(MSR_AMD64_IBSOPDATA, low, high); + ibs_op.ibs_op_data1_low = low; + ibs_op.ibs_op_data1_high = high; + rdmsr(MSR_AMD64_IBSOPDATA2, low, high); + ibs_op.ibs_op_data2_low = low; + ibs_op.ibs_op_data2_high = high; + rdmsr(MSR_AMD64_IBSOPDATA3, low, high); + ibs_op.ibs_op_data3_low = low; + ibs_op.ibs_op_data3_high = high; + rdmsr(MSR_AMD64_IBSDCLINAD, low, high); + ibs_op.ibs_dc_linear_low = low; + ibs_op.ibs_dc_linear_high = high; + rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); + ibs_op.ibs_dc_phys_low = low; + ibs_op.ibs_dc_phys_high = high; + + /* reenable the IRQ */ + oprofile_add_ibs_sample(regs, + (unsigned int *)&ibs_op, + IBS_OP_BEGIN); + rdmsr(MSR_AMD64_IBSOPCTL, low, high); + low &= ~(IBS_OP_VALID_BIT); + low |= IBS_OP_ENABLE; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } + } + /* See op_model_ppro.c */ return 1; } @@ -148,6 +289,17 @@ static void op_amd_start(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } } + if (ibs_allowed && ibs_config.fetch_enabled) { + low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; + high = IBS_FETCH_ENABLE; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_ENABLE; + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } } @@ -165,6 +317,18 @@ static void op_amd_stop(struct op_msrs const * const msrs) CTRL_SET_INACTIVE(low); CTRL_WRITE(low, high, msrs, i); } + + if (ibs_allowed && ibs_config.fetch_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); + } + + if (ibs_allowed && ibs_config.op_enabled) { + low = 0; /* clear max count and enable */ + high = 0; + wrmsr(MSR_AMD64_IBSOPCTL, low, high); + } } static void op_amd_shutdown(struct op_msrs const * const msrs) @@ -181,6 +345,99 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +static inline void apic_init_ibs_nmi_per_cpu(void *arg) +{ + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); +} + +static inline void apic_clear_ibs_nmi_per_cpu(void *arg) +{ + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); +} + +/* + * initialize the APIC for the IBS interrupts + * if needed on AMD Family10h rev B0 and later + */ +static void setup_ibs(void) +{ + struct pci_dev *gh_device = NULL; + u32 low, high; + u8 vector; + + ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); + + if (!ibs_allowed) + return; + + /* This gets the APIC_EILVT_LVTOFF_IBS value */ + vector = setup_APIC_eilvt_ibs(0, 0, 1); + + /*see if the IBS control register is already set correctly*/ + /*remove this when we know for sure it is done + in the kernel init*/ + rdmsr(MSR_AMD64_IBSCTL, low, high); + if ((low & (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) != + (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) { + + /**** Be sure to run loop until NULL is returned to + decrement reference count on any pci_dev structures + returned ****/ + while ((gh_device = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, gh_device)) + != NULL) { + /* This code may change if we can find a proper + * way to get at the PCI extended config space */ + pci_write_config_dword( + gh_device, IBS_LVT_OFFSET_PCI, + (vector | IBS_CTL_LVT_OFFSET_VALID_BIT)); + } + } + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1, 1); +} + + +/* + * unitialize the APIC for the IBS interrupts if needed on AMD Family10h + * rev B0 and later */ +static void clear_ibs_nmi(void) +{ + if (ibs_allowed) + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1, 1); +} + +static void setup_ibs_files(struct super_block *sb, struct dentry *root) +{ + char buf[12]; + struct dentry *dir; + + if (!ibs_allowed) + return; + + /* setup some reasonable defaults */ + ibs_config.max_cnt_fetch = 250000; + ibs_config.fetch_enabled = 0; + ibs_config.max_cnt_op = 250000; + ibs_config.op_enabled = 0; + ibs_config.dispatched_ops = 1; + snprintf(buf, sizeof(buf), "ibs_fetch"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "rand_enable", + &ibs_config.rand_en); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.fetch_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_fetch); + snprintf(buf, sizeof(buf), "ibs_uops"); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "enable", + &ibs_config.op_enabled); + oprofilefs_create_ulong(sb, dir, "max_count", + &ibs_config.max_cnt_op); + oprofilefs_create_ulong(sb, dir, "dispatched_ops", + &ibs_config.dispatched_ops); +} + static int op_amd_init(struct oprofile_operations *ops) { return 0; -- GitLab From 7939d2bf7e30353d40d14f967b7fe2b2a7be5bd9 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:56 +0200 Subject: [PATCH 0115/5416] x86/oprofile: separating the IBS handler Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 45 ++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 229e0b4e21e..a2c8e2e372b 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -195,27 +195,18 @@ static void op_amd_setup_ctrs(struct op_msrs const * const msrs) } } - -static int op_amd_check_ctrs(struct pt_regs * const regs, - struct op_msrs const * const msrs) +static inline int +op_amd_handle_ibs(struct pt_regs * const regs, + struct op_msrs const * const msrs) { unsigned int low, high; - int i; struct ibs_fetch_sample ibs_fetch; struct ibs_op_sample ibs_op; - for (i = 0 ; i < NUM_COUNTERS; ++i) { - if (!reset_value[i]) - continue; - CTR_READ(low, high, msrs, i); - if (CTR_OVERFLOWED(low)) { - oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], msrs, i); - } - } + if (!ibs_allowed) + return 1; - /*If AMD and IBS is available */ - if (ibs_allowed && ibs_config.fetch_enabled) { + if (ibs_config.fetch_enabled) { rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); if (high & IBS_FETCH_VALID_BIT) { ibs_fetch.ibs_fetch_ctl_high = high; @@ -240,7 +231,7 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } - if (ibs_allowed && ibs_config.op_enabled) { + if (ibs_config.op_enabled) { rdmsr(MSR_AMD64_IBSOPCTL, low, high); if (low & IBS_OP_VALID_BIT) { rdmsr(MSR_AMD64_IBSOPRIP, low, high); @@ -273,10 +264,30 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } - /* See op_model_ppro.c */ return 1; } +static int op_amd_check_ctrs(struct pt_regs * const regs, + struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + if (!reset_value[i]) + continue; + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + oprofile_add_sample(regs, i); + CTR_WRITE(reset_value[i], msrs, i); + } + } + + op_amd_handle_ibs(regs, msrs); + + /* See op_model_ppro.c */ + return 1; +} static void op_amd_start(struct op_msrs const * const msrs) { -- GitLab From 7d77f2dcae37cf232950cd0181fb0a2cddb18130 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:57 +0200 Subject: [PATCH 0116/5416] OProfile: change IBS interrupt initialization Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 84 ++++++++++++++++++----------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index a2c8e2e372b..90193b1538a 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -356,9 +356,11 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +static u8 ibs_eilvt_off; + static inline void apic_init_ibs_nmi_per_cpu(void *arg) { - setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); + ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); } static inline void apic_clear_ibs_nmi_per_cpu(void *arg) @@ -366,45 +368,67 @@ static inline void apic_clear_ibs_nmi_per_cpu(void *arg) setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); } +static int pfm_amd64_setup_eilvt(void) +{ +#define IBSCTL_LVTOFFSETVAL (1 << 8) +#define IBSCTL 0x1cc + struct pci_dev *cpu_cfg; + int nodes; + u32 value = 0; + + /* per CPU setup */ + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 0, 1); + + nodes = 0; + cpu_cfg = NULL; + do { + cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, + cpu_cfg); + if (!cpu_cfg) + break; + ++nodes; + pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off + | IBSCTL_LVTOFFSETVAL); + pci_read_config_dword(cpu_cfg, IBSCTL, &value); + if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { + printk(KERN_DEBUG "Failed to setup IBS LVT offset, " + "IBSCTL = 0x%08x", value); + return 1; + } + } while (1); + + if (!nodes) { + printk(KERN_DEBUG "No CPU node configured for IBS"); + return 1; + } + +#ifdef CONFIG_NUMA + /* Sanity check */ + /* Works only for 64bit with proper numa implementation. */ + if (nodes != num_possible_nodes()) { + printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, " + "found: %d, expected %d", + nodes, num_possible_nodes()); + return 1; + } +#endif + return 0; +} + /* * initialize the APIC for the IBS interrupts - * if needed on AMD Family10h rev B0 and later + * if available (AMD Family10h rev B0 and later) */ static void setup_ibs(void) { - struct pci_dev *gh_device = NULL; - u32 low, high; - u8 vector; - ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); if (!ibs_allowed) return; - /* This gets the APIC_EILVT_LVTOFF_IBS value */ - vector = setup_APIC_eilvt_ibs(0, 0, 1); - - /*see if the IBS control register is already set correctly*/ - /*remove this when we know for sure it is done - in the kernel init*/ - rdmsr(MSR_AMD64_IBSCTL, low, high); - if ((low & (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) != - (IBS_CTL_LVT_OFFSET_VALID_BIT | vector)) { - - /**** Be sure to run loop until NULL is returned to - decrement reference count on any pci_dev structures - returned ****/ - while ((gh_device = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_10H_NB_MISC, gh_device)) - != NULL) { - /* This code may change if we can find a proper - * way to get at the PCI extended config space */ - pci_write_config_dword( - gh_device, IBS_LVT_OFFSET_PCI, - (vector | IBS_CTL_LVT_OFFSET_VALID_BIT)); - } - } - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1, 1); + if (pfm_amd64_setup_eilvt()) + ibs_allowed = 0; } -- GitLab From 90645700ef8393cd9cdc02d83da36726fc88f49e Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:58 +0200 Subject: [PATCH 0117/5416] OProfile: Fix build error in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 90193b1538a..284c45661ed 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -73,6 +73,11 @@ /* MSR to set the IBS control register APIC LVT offset */ #define IBS_LVT_OFFSET_PCI 0x1CC +/* The function interface needs to be fixed, something like add + data. Should then be added to linux/oprofile.h. */ +extern void oprofile_add_ibs_sample(struct pt_regs *const regs, + unsigned int * const ibs_sample, u8 code); + struct ibs_fetch_sample { /* MSRC001_1031 IBS Fetch Linear Address Register */ unsigned int ibs_fetch_lin_addr_low; -- GitLab From ebb535de267386f659e0348185b1e361dbba3b59 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:08:59 +0200 Subject: [PATCH 0118/5416] OProfile: on_each_cpu(): kill unused retry parameter Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 284c45661ed..ce732362dbb 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -382,7 +382,7 @@ static int pfm_amd64_setup_eilvt(void) u32 value = 0; /* per CPU setup */ - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 0, 1); + on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); nodes = 0; cpu_cfg = NULL; @@ -443,7 +443,7 @@ static void setup_ibs(void) static void clear_ibs_nmi(void) { if (ibs_allowed) - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1, 1); + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } static void setup_ibs_files(struct super_block *sb, struct dentry *root) -- GitLab From fc2bd7345b4e006a34c2ea3711d8c6b83cba50f7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:00 +0200 Subject: [PATCH 0119/5416] OProfile: fix setup_ibs_files() function interface Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index ce732362dbb..2650b12a0c5 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -446,13 +446,13 @@ static void clear_ibs_nmi(void) on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } -static void setup_ibs_files(struct super_block *sb, struct dentry *root) +static int setup_ibs_files(struct super_block * sb, struct dentry * root) { char buf[12]; struct dentry *dir; if (!ibs_allowed) - return; + return 0; /* setup some reasonable defaults */ ibs_config.max_cnt_fetch = 250000; @@ -476,6 +476,8 @@ static void setup_ibs_files(struct super_block *sb, struct dentry *root) &ibs_config.max_cnt_op); oprofilefs_create_ulong(sb, dir, "dispatched_ops", &ibs_config.dispatched_ops); + + return 0; } static int op_amd_init(struct oprofile_operations *ops) -- GitLab From 270d3e1a10e6ef85d5a085377e01d91dbcbe3726 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:01 +0200 Subject: [PATCH 0120/5416] OProfile: enable IBS for AMD CPUs Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 14 ++++++++------ arch/x86/oprofile/op_model_athlon.c | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b29819313f2..287513a0981 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -468,6 +468,14 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } + /* default values, can be overwritten by model */ + ops->create_files = nmi_create_files; + ops->setup = nmi_setup; + ops->shutdown = nmi_shutdown; + ops->start = nmi_start; + ops->stop = nmi_stop; + ops->cpu_type = cpu_type; + if (model->init) ret = model->init(ops); if (ret) @@ -475,12 +483,6 @@ int __init op_nmi_init(struct oprofile_operations *ops) init_sysfs(); using_nmi = 1; - ops->create_files = nmi_create_files; - ops->setup = nmi_setup; - ops->shutdown = nmi_shutdown; - ops->start = nmi_start; - ops->stop = nmi_stop; - ops->cpu_type = cpu_type; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; } diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 2650b12a0c5..0d839031979 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -446,13 +446,25 @@ static void clear_ibs_nmi(void) on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } +static int (*create_arch_files)(struct super_block * sb, struct dentry * root); + static int setup_ibs_files(struct super_block * sb, struct dentry * root) { char buf[12]; struct dentry *dir; + int ret = 0; + + /* architecture specific files */ + if (create_arch_files) + ret = create_arch_files(sb, root); + + if (ret) + return ret; if (!ibs_allowed) - return 0; + return ret; + + /* model specific files */ /* setup some reasonable defaults */ ibs_config.max_cnt_fetch = 250000; @@ -482,11 +494,15 @@ static int setup_ibs_files(struct super_block * sb, struct dentry * root) static int op_amd_init(struct oprofile_operations *ops) { + setup_ibs(); + create_arch_files = ops->create_files; + ops->create_files = setup_ibs_files; return 0; } static void op_amd_exit(void) { + clear_ibs_nmi(); } struct op_x86_model_spec const op_amd_spec = { -- GitLab From a4c408a41167949f820e2740e56a8f2f7bb6177c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:02 +0200 Subject: [PATCH 0121/5416] OProfile: fix IBS build error for UP Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 0d839031979..1acb067bd34 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -361,6 +361,26 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } +#ifndef CONFIG_SMP + +/* no IBS support */ + +static void setup_ibs(void) +{ + ibs_allowed = 0; +} + +static void clear_ibs_nmi(void) {} + +static int op_amd_init(struct oprofile_operations *ops) +{ + return 0; +} + +static void op_amd_exit(void) {} + +#else + static u8 ibs_eilvt_off; static inline void apic_init_ibs_nmi_per_cpu(void *arg) @@ -505,6 +525,8 @@ static void op_amd_exit(void) clear_ibs_nmi(); } +#endif + struct op_x86_model_spec const op_amd_spec = { .init = op_amd_init, .exit = op_amd_exit, -- GitLab From 87f0baccc2e4f194c931186d3c8499314494a484 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:03 +0200 Subject: [PATCH 0122/5416] x86/oprofile: macro definition cleanup in op_model_athlon.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 46 +++++++++++------------------ 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 1acb067bd34..a3a2058c372 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -47,32 +47,20 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) -#define IBS_FETCH_CTL_HIGH_MASK 0xFFFFFFFF -/* high dword bit IbsFetchCtl[bit 49] */ -#define IBS_FETCH_VALID_BIT (1UL << 17) -/* high dword bit IbsFetchCtl[bit 52] */ -#define IBS_FETCH_PHY_ADDR_VALID_BIT (1UL << 20) -/* high dword bit IbsFetchCtl[bit 48] */ -#define IBS_FETCH_ENABLE (1UL << 16) +/* IbsFetchCtl bits/masks */ +#define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ +#define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ +#define IBS_FETCH_LOW_MAX_CNT_MASK 0x0000FFFFUL /* MaxCnt mask */ -#define IBS_FETCH_CTL_CNT_MASK 0x00000000FFFF0000UL -#define IBS_FETCH_CTL_MAX_CNT_MASK 0x000000000000FFFFUL - -/*IbsOpCtl masks/bits */ -#define IBS_OP_VALID_BIT (1ULL<<18) /* IbsOpCtl[bit18] */ -#define IBS_OP_ENABLE (1ULL<<17) /* IBS_OP_ENABLE[bit17]*/ +/*IbsOpCtl bits */ +#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ +#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ /* Codes used in cpu_buffer.c */ +/* This produces duplicate code, need to be fixed */ #define IBS_FETCH_BEGIN 3 #define IBS_OP_BEGIN 4 -/*IbsOpData3 masks */ -#define IBS_CTL_LVT_OFFSET_VALID_BIT (1ULL<<8) - -/*PCI Extended Configuration Constants */ -/* MSR to set the IBS control register APIC LVT offset */ -#define IBS_LVT_OFFSET_PCI 0x1CC - /* The function interface needs to be fixed, something like add data. Should then be added to linux/oprofile.h. */ extern void oprofile_add_ibs_sample(struct pt_regs *const regs, @@ -213,7 +201,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, if (ibs_config.fetch_enabled) { rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - if (high & IBS_FETCH_VALID_BIT) { + if (high & IBS_FETCH_HIGH_VALID_BIT) { ibs_fetch.ibs_fetch_ctl_high = high; ibs_fetch.ibs_fetch_ctl_low = low; rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); @@ -229,16 +217,16 @@ op_amd_handle_ibs(struct pt_regs * const regs, /*reenable the IRQ */ rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); - high &= ~(IBS_FETCH_VALID_BIT); - high |= IBS_FETCH_ENABLE; - low &= IBS_FETCH_CTL_MAX_CNT_MASK; + high &= ~IBS_FETCH_HIGH_VALID_BIT; + high |= IBS_FETCH_HIGH_ENABLE; + low &= IBS_FETCH_LOW_MAX_CNT_MASK; wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); } } if (ibs_config.op_enabled) { rdmsr(MSR_AMD64_IBSOPCTL, low, high); - if (low & IBS_OP_VALID_BIT) { + if (low & IBS_OP_LOW_VALID_BIT) { rdmsr(MSR_AMD64_IBSOPRIP, low, high); ibs_op.ibs_op_rip_low = low; ibs_op.ibs_op_rip_high = high; @@ -263,8 +251,8 @@ op_amd_handle_ibs(struct pt_regs * const regs, (unsigned int *)&ibs_op, IBS_OP_BEGIN); rdmsr(MSR_AMD64_IBSOPCTL, low, high); - low &= ~(IBS_OP_VALID_BIT); - low |= IBS_OP_ENABLE; + low &= ~IBS_OP_LOW_VALID_BIT; + low |= IBS_OP_LOW_ENABLE; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } } @@ -307,12 +295,12 @@ static void op_amd_start(struct op_msrs const * const msrs) } if (ibs_allowed && ibs_config.fetch_enabled) { low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; - high = IBS_FETCH_ENABLE; + high = IBS_FETCH_HIGH_ENABLE; wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); } if (ibs_allowed && ibs_config.op_enabled) { - low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_ENABLE; + low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE; high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } -- GitLab From 543a157bbdfae8eb997506031c3b2d4d17957098 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:04 +0200 Subject: [PATCH 0123/5416] x86/oprofile: op_model_athlon.c: fix counter reset when reenabling IBS OP Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_athlon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index a3a2058c372..9c8c8c58313 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -251,6 +251,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, (unsigned int *)&ibs_op, IBS_OP_BEGIN); rdmsr(MSR_AMD64_IBSOPCTL, low, high); + high = 0; low &= ~IBS_OP_LOW_VALID_BIT; low |= IBS_OP_LOW_ENABLE; wrmsr(MSR_AMD64_IBSOPCTL, low, high); -- GitLab From 09691616850b3614dfb44790e1e1419b6a7f5d13 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:05 +0200 Subject: [PATCH 0124/5416] x86: apic: export symbols for extended interrupt LVT functions This patch adds EXPORT_SYMBOLs to allow OProfile to be built as module. Cc: Arjan van de Ven Signed-off-by: Robert Richter Cc: oprofile-list Cc: Arjan van de Ven Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 1 + arch/x86/kernel/apic_64.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index fad94b0decc..ed3a6d7e9de 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -672,6 +672,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } +EXPORT_SYMBOL(setup_APIC_eilvt_ibs); /* * Local APIC start and shutdown diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 42bf69f8bc8..45ec90e37b9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -232,6 +232,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } +EXPORT_SYMBOL(setup_APIC_eilvt_ibs); /* * Program the next event, relative to now -- GitLab From 6aa360e6c16c145edf1837690e0f7aaea6b86ef3 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 23 Jul 2008 15:28:14 +0200 Subject: [PATCH 0125/5416] x86: apic: changing export symbols to *_GPL This fits better here. Signed-off-by: Robert Richter Cc: Arjan van de Ven Cc: Barry Kasindorf Cc: oprofile-list Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 +- arch/x86/kernel/apic_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index ed3a6d7e9de..0059e7a8a9e 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -672,7 +672,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } -EXPORT_SYMBOL(setup_APIC_eilvt_ibs); +EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); /* * Local APIC start and shutdown diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 45ec90e37b9..e571351f2a9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -232,7 +232,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); return APIC_EILVT_LVTOFF_IBS; } -EXPORT_SYMBOL(setup_APIC_eilvt_ibs); +EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); /* * Program the next event, relative to now -- GitLab From 852402cc27bfa1200164e9e8dc7f6e5f0a4fbd46 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:06 +0200 Subject: [PATCH 0126/5416] x86/oprofile: add CONFIG_OPROFILE_IBS option Signed-off-by: Robert Richter Cc: oprofile-list Cc: Robert Richter Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/Kconfig | 14 ++++++++++++ arch/x86/oprofile/op_model_athlon.c | 33 ++++++++++++++++++++--------- drivers/oprofile/buffer_sync.c | 6 ++++++ drivers/oprofile/cpu_buffer.c | 4 ++++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index b0fabfa864f..2651af48b2e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -13,6 +13,20 @@ config OPROFILE If unsure, say N. +config OPROFILE_IBS + bool "OProfile AMD IBS support (EXPERIMENTAL)" + default n + depends on OPROFILE && SMP && X86 + help + Instruction-Based Sampling (IBS) is a new profiling + technique that provides rich, precise program performance + information. IBS is introduced by AMD Family10h processors + (AMD Opteron Quad-Core processor “Barcelonaâ€) to overcome + the limitations of conventional performance counter + sampling. + + If unsure, say N. + config HAVE_OPROFILE def_bool n diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c index 9c8c8c58313..fb6015c1132 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_athlon.c @@ -47,6 +47,10 @@ #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) +static unsigned long reset_value[NUM_COUNTERS]; + +#ifdef CONFIG_OPROFILE_IBS + /* IbsFetchCtl bits/masks */ #define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ #define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ @@ -104,7 +108,6 @@ struct ibs_op_sample { */ static void clear_ibs_nmi(void); -static unsigned long reset_value[NUM_COUNTERS]; static int ibs_allowed; /* AMD Family10h and later */ struct op_ibs_config { @@ -118,6 +121,8 @@ struct op_ibs_config { static struct op_ibs_config ibs_config; +#endif + /* functions for op_amd_spec */ static void op_amd_fill_in_addresses(struct op_msrs * const msrs) @@ -188,6 +193,8 @@ static void op_amd_setup_ctrs(struct op_msrs const * const msrs) } } +#ifdef CONFIG_OPROFILE_IBS + static inline int op_amd_handle_ibs(struct pt_regs * const regs, struct op_msrs const * const msrs) @@ -261,6 +268,8 @@ op_amd_handle_ibs(struct pt_regs * const regs, return 1; } +#endif + static int op_amd_check_ctrs(struct pt_regs * const regs, struct op_msrs const * const msrs) { @@ -277,7 +286,9 @@ static int op_amd_check_ctrs(struct pt_regs * const regs, } } +#ifdef CONFIG_OPROFILE_IBS op_amd_handle_ibs(regs, msrs); +#endif /* See op_model_ppro.c */ return 1; @@ -294,6 +305,8 @@ static void op_amd_start(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } } + +#ifdef CONFIG_OPROFILE_IBS if (ibs_allowed && ibs_config.fetch_enabled) { low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; high = IBS_FETCH_HIGH_ENABLE; @@ -305,6 +318,7 @@ static void op_amd_start(struct op_msrs const * const msrs) high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } +#endif } @@ -323,6 +337,7 @@ static void op_amd_stop(struct op_msrs const * const msrs) CTRL_WRITE(low, high, msrs, i); } +#ifdef CONFIG_OPROFILE_IBS if (ibs_allowed && ibs_config.fetch_enabled) { low = 0; /* clear max count and enable */ high = 0; @@ -334,6 +349,7 @@ static void op_amd_stop(struct op_msrs const * const msrs) high = 0; wrmsr(MSR_AMD64_IBSOPCTL, low, high); } +#endif } static void op_amd_shutdown(struct op_msrs const * const msrs) @@ -350,17 +366,10 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } -#ifndef CONFIG_SMP +#ifndef CONFIG_OPROFILE_IBS /* no IBS support */ -static void setup_ibs(void) -{ - ibs_allowed = 0; -} - -static void clear_ibs_nmi(void) {} - static int op_amd_init(struct oprofile_operations *ops) { return 0; @@ -441,8 +450,12 @@ static void setup_ibs(void) if (!ibs_allowed) return; - if (pfm_amd64_setup_eilvt()) + if (pfm_amd64_setup_eilvt()) { ibs_allowed = 0; + return; + } + + printk(KERN_INFO "oprofile: AMD IBS detected\n"); } diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index e1782d2df09..ed982273fb8 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -328,6 +328,8 @@ static void add_trace_begin(void) add_event_entry(TRACE_BEGIN_CODE); } +#ifdef CONFIG_OPROFILE_IBS + #define IBS_FETCH_CODE_SIZE 2 #define IBS_OP_CODE_SIZE 5 #define IBS_EIP(offset) \ @@ -390,6 +392,8 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, } } +#endif + static void add_sample_entry(unsigned long offset, unsigned long event) { add_event_entry(offset); @@ -586,6 +590,7 @@ void sync_buffer(int cpu) } else if (s->event == CPU_TRACE_BEGIN) { state = sb_bt_start; add_trace_begin(); +#ifdef CONFIG_OPROFILE_IBS } else if (s->event == IBS_FETCH_BEGIN) { state = sb_bt_start; add_ibs_begin(cpu_buf, @@ -594,6 +599,7 @@ void sync_buffer(int cpu) state = sb_bt_start; add_ibs_begin(cpu_buf, IBS_OP_CODE, in_kernel, mm); +#endif } else { struct mm_struct *oldmm = mm; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index c9ac4e15691..aba905b3afb 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -253,6 +253,8 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) oprofile_add_ext_sample(pc, regs, event, is_kernel); } +#ifdef CONFIG_OPROFILE_IBS + #define MAX_IBS_SAMPLE_SIZE 14 static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code) @@ -318,6 +320,8 @@ void oprofile_add_ibs_sample(struct pt_regs *const regs, oprofile_ops.backtrace(regs, backtrace_depth); } +#endif + void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); -- GitLab From bd17b625c09d1ed14c4d98604186b0bbb314f6b2 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:07 +0200 Subject: [PATCH 0127/5416] oprofile: fix printk in cpu_buffer.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Robert Richter Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- drivers/oprofile/cpu_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index aba905b3afb..4decab624e7 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -364,7 +364,7 @@ static void wq_sync_buffer(struct work_struct *work) struct oprofile_cpu_buffer * b = container_of(work, struct oprofile_cpu_buffer, work.work); if (b->cpu != smp_processor_id()) { - printk("WQ on CPU%d, prefer CPU%d\n", + printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n", smp_processor_id(), b->cpu); } sync_buffer(b->cpu); -- GitLab From 6852fd9b86d05063c6ef49d2e12e061cc7f6a105 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 22 Jul 2008 21:09:08 +0200 Subject: [PATCH 0128/5416] x86/oprofile: reanaming op_model_athlon.c to op_model_amd.c Signed-off-by: Robert Richter Cc: oprofile-list Cc: Barry Kasindorf Signed-off-by: Ingo Molnar --- arch/x86/oprofile/Makefile | 2 +- arch/x86/oprofile/{op_model_athlon.c => op_model_amd.c} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename arch/x86/oprofile/{op_model_athlon.c => op_model_amd.c} (99%) diff --git a/arch/x86/oprofile/Makefile b/arch/x86/oprofile/Makefile index 30f3eb36666..446902b2a6b 100644 --- a/arch/x86/oprofile/Makefile +++ b/arch/x86/oprofile/Makefile @@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) init.o backtrace.o -oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ +oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ op_model_ppro.o op_model_p4.o oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_amd.c similarity index 99% rename from arch/x86/oprofile/op_model_athlon.c rename to arch/x86/oprofile/op_model_amd.c index fb6015c1132..d9faf607b3a 100644 --- a/arch/x86/oprofile/op_model_athlon.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -1,5 +1,5 @@ /* - * @file op_model_athlon.c + * @file op_model_amd.c * athlon / K7 / K8 / Family 10h model-specific MSR operations * * @remark Copyright 2002-2008 OProfile authors -- GitLab From 1ddb5518052e4e28ab489237443f7443b3fd69ca Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:55 +0200 Subject: [PATCH 0129/5416] x86: convert pci-dma.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index cbecb05551b..88ddd04cfa9 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -82,7 +82,7 @@ void __init dma32_reserve_bootmem(void) * using 512M as goal */ align = 64ULL<<20; - size = round_up(dma32_bootmem_size, align); + size = roundup(dma32_bootmem_size, align); dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, 512ULL<<20); if (dma32_bootmem_ptr) -- GitLab From 15ae2d76ceb037a1e3fcd8fc9b4fe3177f9f3831 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:56 +0200 Subject: [PATCH 0130/5416] x86: convert pageattr.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 65c6e46bf05..0d254adcc82 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -78,7 +78,7 @@ static inline unsigned long highmap_start_pfn(void) static inline unsigned long highmap_end_pfn(void) { - return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; + return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; } #endif -- GitLab From d86bb0dac792c6a9c92944b6db2687980c808094 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:57 +0200 Subject: [PATCH 0131/5416] x86: convert init_64.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index ec37121f670..e4805771b5b 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -258,7 +258,7 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) void __init cleanup_highmap(void) { unsigned long vaddr = __START_KERNEL_map; - unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; + unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; pmd_t *pmd = level2_kernel_pgt; pmd_t *last_pmd = pmd + PTRS_PER_PMD; @@ -474,14 +474,14 @@ static void __init find_early_table_space(unsigned long end) unsigned long puds, pmds, ptes, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); if (direct_gbpages) { unsigned long extra; extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; } else pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); if (cpu_has_pse) { unsigned long extra; @@ -489,7 +489,7 @@ static void __init find_early_table_space(unsigned long end) ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; - tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); + tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); /* * RED-PEN putting page tables only on node 0 could -- GitLab From be3e89ee6df8607356f705901dd90bcf3836c86e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 25 Jul 2008 16:48:58 +0200 Subject: [PATCH 0132/5416] x86: convert numa_64.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/numa_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index a4dd793d600..cebcbf152d4 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -79,7 +79,7 @@ static int __init allocate_cachealigned_memnodemap(void) return 0; addr = 0x8000; - nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); + nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); nodemap_addr = find_e820_area(addr, max_pfn< Date: Fri, 25 Jul 2008 16:48:59 +0200 Subject: [PATCH 0133/5416] x86: convert discontig_32.c from round_up to roundup Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/mm/discontig_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index 62fa440678d..847c164725f 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -328,7 +328,7 @@ void __init initmem_init(unsigned long start_pfn, get_memcfg_numa(); - kva_pages = round_up(calculate_numa_remap_pages(), PTRS_PER_PTE); + kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE); kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE); do { -- GitLab From 0af36739af81f152cc24a0fdfa0754ef657afe3d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 24 Jul 2008 17:27:57 -0700 Subject: [PATCH 0134/5416] usb: move ehci reg def prepare x86: usb debug port early console move ehci struct def to linux/usrb/ehci_def.h from host/ehci.h Signed-off-by: Yinghai Lu Acked-by: David Brownell Cc: Andrew Morton Cc: Andi Kleen Cc: "Arjan van de Ven" Cc: "Eric W. Biederman" Cc: "Greg KH" Signed-off-by: Ingo Molnar --- drivers/usb/host/ehci.h | 138 +----------------------------- include/linux/usb/ehci_def.h | 160 +++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 137 deletions(-) create mode 100644 include/linux/usb/ehci_def.h diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 5799298364f..b697a13364e 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -210,143 +210,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) /*-------------------------------------------------------------------------*/ -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - */ - u32 hc_capbase; -#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#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*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute [8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - - /* USBCMD: offset 0x00 */ - u32 command; -/* 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_LRESET (1<<7) /* partial reset (no ports, etc) */ -#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 reserved [9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status [0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#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 | PORT_OCC) -} __attribute__ ((packed)); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1<<3) /* Stream disable */ -#define USBMODE_BE (1<<2) /* BE/LE endianness select */ -#define USBMODE_CM_HC (3<<0) /* host controller mode */ -#define USBMODE_CM_IDLE (0<<0) /* idle state */ - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_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)) -} __attribute__ ((packed)); +#include /*-------------------------------------------------------------------------*/ diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h new file mode 100644 index 00000000000..5b88e36c910 --- /dev/null +++ b/include/linux/usb/ehci_def.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_USB_EHCI_DEF_H +#define __LINUX_USB_EHCI_DEF_H + +/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ + +/* Section 2.2 Host Controller Capability Registers */ +struct ehci_caps { + /* these fields are specified as 8 and 16 bit registers, + * but some hosts can't perform 8 or 16 bit PCI accesses. + */ + u32 hc_capbase; +#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ +#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ + u32 hcs_params; /* HCSPARAMS - offset 0x4 */ +#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ +#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ +#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ +#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ +#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ +#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ +#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ + + u32 hcc_params; /* HCCPARAMS - offset 0x8 */ +#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ +#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ +#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ +#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*/ +#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ + u8 portroute [8]; /* nibbles for routing - offset 0xC */ +} __attribute__ ((packed)); + + +/* Section 2.3 Host Controller Operational Registers */ +struct ehci_regs { + + /* USBCMD: offset 0x00 */ + u32 command; +/* 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_LRESET (1<<7) /* partial reset (no ports, etc) */ +#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 reserved [9]; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ + + /* PORTSC: offset 0x44 */ + u32 port_status [0]; /* up to N_PORTS */ +/* 31:23 reserved */ +#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ +#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ +#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ +/* 19:16 for port testing */ +#define PORT_LED_OFF (0<<14) +#define PORT_LED_AMBER (1<<14) +#define PORT_LED_GREEN (2<<14) +#define PORT_LED_MASK (3<<14) +#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ +#define PORT_POWER (1<<12) /* true: has power (see PPC) */ +#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ +/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ +/* 9 reserved */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_OCC (1<<5) /* over current change */ +#define PORT_OC (1<<4) /* over current active */ +#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 | PORT_OCC) +} __attribute__ ((packed)); + +#define USBMODE 0x68 /* USB Device mode */ +#define USBMODE_SDIS (1<<3) /* Stream disable */ +#define USBMODE_BE (1<<2) /* BE/LE endianness select */ +#define USBMODE_CM_HC (3<<0) /* host controller mode */ +#define USBMODE_CM_IDLE (0<<0) /* idle state */ + +/* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) + */ +struct ehci_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)) +} __attribute__ ((packed)); + +#endif /* __LINUX_USB_EHCI_DEF_H */ -- GitLab From 5c05917e7fe313a187ad6ebb94c1c6cf42862a0b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 24 Jul 2008 17:29:40 -0700 Subject: [PATCH 0135/5416] x86: usb debug port early console, v4 based on work from Eric, and add some timeout so don't dead loop when debug device is not installed v2: fix checkpatch warning v3: move ehci struct def to linux/usrb/ehci_def.h from host/ehci.h also add CONFIG_EARLY_PRINTK_DBGP to disable it by default v4: address comments from Ingo, seperate ehci reg def moving to another patch also add auto detect port that connect to debug device for Nvidia southbridge Signed-off-by: Yinghai Lu Cc: Andrew Morton Cc: Andi Kleen Cc: "Arjan van de Ven" Cc: "Eric W. Biederman" Cc: "Greg KH" Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 3 +- arch/x86/Kconfig.debug | 13 + arch/x86/kernel/early_printk.c | 762 +++++++++++++++++++++++++++- 3 files changed, 774 insertions(+), 4 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e7bea3e8530..92ddd4afe17 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -657,11 +657,12 @@ and is between 256 and 4096 characters. It is defined in the file earlyprintk= [X86-32,X86-64,SH,BLACKFIN] earlyprintk=vga earlyprintk=serial[,ttySn[,baudrate]] + earlyprintk=dbgp Append ",keep" to not disable it when the real console takes over. - Only vga or serial at a time, not both. + Only vga or serial or usb debug port at a time. Currently only ttyS0 and ttyS1 are supported. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 092f019e033..93422d2ecf6 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -43,6 +43,19 @@ config EARLY_PRINTK with klogd/syslogd or the X server. You should normally N here, unless you want to debug such a crash. +config EARLY_PRINTK_DBGP + bool "Early printk via EHCI debug port" + default n + depends on EARLY_PRINTK + help + Write kernel log output directly into the EHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. You need usb debug device. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index ff9e7350da5..28155acf706 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -3,11 +3,19 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include /* Simple VGA output */ #define VGABASE (__ISA_IO_base + 0xb8000) @@ -78,6 +86,7 @@ static int early_serial_base = 0x3f8; /* ttyS0 */ static int early_serial_putc(unsigned char ch) { unsigned timeout = 0xffff; + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) cpu_relax(); outb(ch, early_serial_base + TXR); @@ -151,6 +160,721 @@ static struct console early_serial_console = { .index = -1, }; +#ifdef CONFIG_EARLY_PRINTK_DBGP + +static struct ehci_caps __iomem *ehci_caps; +static struct ehci_regs __iomem *ehci_regs; +static struct ehci_dbg_port __iomem *ehci_debug; +static unsigned int dbgp_endpoint_out; + +struct ehci_dev { + u32 bus; + u32 slot; + u32 func; +}; + +static struct ehci_dev ehci_dev; + +#define USB_DEBUG_DEVNUM 127 + +#define DBGP_DATA_TOGGLE 0x8800 + +static inline u32 dbgp_pid_update(u32 x, u32 tok) +{ + return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); +} + +static inline u32 dbgp_len_update(u32 x, u32 len) +{ + return (x & ~0x0f) | (len & 0x0f); +} + +/* + * USB Packet IDs (PIDs) + */ + +/* token */ +#define USB_PID_OUT 0xe1 +#define USB_PID_IN 0x69 +#define USB_PID_SOF 0xa5 +#define USB_PID_SETUP 0x2d +/* handshake */ +#define USB_PID_ACK 0xd2 +#define USB_PID_NAK 0x5a +#define USB_PID_STALL 0x1e +#define USB_PID_NYET 0x96 +/* data */ +#define USB_PID_DATA0 0xc3 +#define USB_PID_DATA1 0x4b +#define USB_PID_DATA2 0x87 +#define USB_PID_MDATA 0x0f +/* Special */ +#define USB_PID_PREAMBLE 0x3c +#define USB_PID_ERR 0x3c +#define USB_PID_SPLIT 0x78 +#define USB_PID_PING 0xb4 +#define USB_PID_UNDEF_0 0xf0 + +#define USB_PID_DATA_TOGGLE 0x88 +#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE) + +#define PCI_CAP_ID_EHCI_DEBUG 0xa + +#define HUB_ROOT_RESET_TIME 50 /* times are in msec */ +#define HUB_SHORT_RESET_TIME 10 +#define HUB_LONG_RESET_TIME 200 +#define HUB_RESET_TIMEOUT 500 + +#define DBGP_MAX_PACKET 8 + +static int dbgp_wait_until_complete(void) +{ + u32 ctrl; + int loop = 0x100000; + + do { + ctrl = readl(&ehci_debug->control); + /* Stop when the transaction is finished */ + if (ctrl & DBGP_DONE) + break; + } while (--loop > 0); + + if (!loop) + return -1; + + /* + * Now that we have observed the completed transaction, + * clear the done bit. + */ + writel(ctrl | DBGP_DONE, &ehci_debug->control); + return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl); +} + +static void dbgp_mdelay(int ms) +{ + int i; + + while (ms--) { + for (i = 0; i < 1000; i++) + outb(0x1, 0x80); + } +} + +static void dbgp_breath(void) +{ + /* Sleep to give the debug port a chance to breathe */ +} + +static int dbgp_wait_until_done(unsigned ctrl) +{ + u32 pids, lpid; + int ret; + int loop = 3; + +retry: + writel(ctrl | DBGP_GO, &ehci_debug->control); + ret = dbgp_wait_until_complete(); + pids = readl(&ehci_debug->pids); + lpid = DBGP_PID_GET(pids); + + if (ret < 0) + return ret; + + /* + * If the port is getting full or it has dropped data + * start pacing ourselves, not necessary but it's friendly. + */ + if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET)) + dbgp_breath(); + + /* If I get a NACK reissue the transmission */ + if (lpid == USB_PID_NAK) { + if (--loop > 0) + goto retry; + } + + return ret; +} + +static void dbgp_set_data(const void *buf, int size) +{ + const unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = hi = 0; + for (i = 0; i < 4 && i < size; i++) + lo |= bytes[i] << (8*i); + for (; i < 8 && i < size; i++) + hi |= bytes[i] << (8*(i - 4)); + writel(lo, &ehci_debug->data03); + writel(hi, &ehci_debug->data47); +} + +static void dbgp_get_data(void *buf, int size) +{ + unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = readl(&ehci_debug->data03); + hi = readl(&ehci_debug->data47); + for (i = 0; i < 4 && i < size; i++) + bytes[i] = (lo >> (8*i)) & 0xff; + for (; i < 8 && i < size; i++) + bytes[i] = (hi >> (8*(i - 4))) & 0xff; +} + +static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, + const char *bytes, int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_OUT); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + dbgp_set_data(bytes, size); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + return ret; +} + +static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, + int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_IN); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl &= ~DBGP_OUT; + ctrl |= DBGP_GO; + + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + if (size > ret) + size = ret; + dbgp_get_data(data, size); + return ret; +} + +static int dbgp_control_msg(unsigned devnum, int requesttype, int request, + int value, int index, void *data, int size) +{ + u32 pids, addr, ctrl; + struct usb_ctrlrequest req; + int read; + int ret; + + read = (requesttype & USB_DIR_IN) != 0; + if (size > (read ? DBGP_MAX_PACKET:0)) + return -1; + + /* Compute the control message */ + req.bRequestType = requesttype; + req.bRequest = request; + req.wValue = value; + req.wIndex = index; + req.wLength = size; + + pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); + addr = DBGP_EPADDR(devnum, 0); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, sizeof(req)); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + /* Send the setup message */ + dbgp_set_data(&req, sizeof(req)); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + /* Read the result */ + return dbgp_bulk_read(devnum, 0, data, size); +} + + +/* Find a PCI capability */ +static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) +{ + u8 pos; + int bytes; + + if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & + PCI_STATUS_CAP_LIST)) + return 0; + + pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); + for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { + u8 id; + + pos &= ~3; + id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); + if (id == 0xff) + break; + if (id == cap) + return pos; + + pos = read_pci_config_byte(num, slot, func, + pos+PCI_CAP_LIST_NEXT); + } + return 0; +} + +static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func) +{ + u32 class; + + class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); + if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI) + return 0; + + return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG); +} + +static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc) +{ + u32 bus, slot, func; + + for (bus = 0; bus < 256; bus++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + unsigned cap; + + cap = __find_dbgp(bus, slot, func); + + if (!cap) + continue; + if (ehci_num-- != 0) + continue; + *rbus = bus; + *rslot = slot; + *rfunc = func; + return cap; + } + } + } + return 0; +} + +static int ehci_reset_port(int port) +{ + u32 portsc; + u32 delay_time, delay; + int loop; + + /* Reset the usb debug port */ + portsc = readl(&ehci_regs->port_status[port - 1]); + portsc &= ~PORT_PE; + portsc |= PORT_RESET; + writel(portsc, &ehci_regs->port_status[port - 1]); + + delay = HUB_ROOT_RESET_TIME; + for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; + delay_time += delay) { + dbgp_mdelay(delay); + + portsc = readl(&ehci_regs->port_status[port - 1]); + if (portsc & PORT_RESET) { + /* force reset to complete */ + loop = 2; + writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), + &ehci_regs->port_status[port - 1]); + do { + portsc = readl(&ehci_regs->port_status[port-1]); + } while ((portsc & PORT_RESET) && (--loop > 0)); + } + + /* Device went away? */ + if (!(portsc & PORT_CONNECT)) + return -ENOTCONN; + + /* bomb out completely if something weird happend */ + if ((portsc & PORT_CSC)) + return -EINVAL; + + /* If we've finished resetting, then break out of the loop */ + if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) + return 0; + } + return -EBUSY; +} + +static int ehci_wait_for_port(int port) +{ + u32 status; + int ret, reps; + + for (reps = 0; reps < 3; reps++) { + dbgp_mdelay(100); + status = readl(&ehci_regs->status); + if (status & STS_PCD) { + ret = ehci_reset_port(port); + if (ret == 0) + return 0; + } + } + return -ENOTCONN; +} + +#ifdef DBGP_DEBUG +# define dbgp_printk early_printk +#else +static inline void dbgp_printk(const char *fmt, ...) { } +#endif + +typedef void (*set_debug_port_t)(int port); + +static void default_set_debug_port(int port) +{ +} + +static set_debug_port_t set_debug_port = default_set_debug_port; + +static void nvidia_set_debug_port(int port) +{ + u32 dword; + dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x74); + dword &= ~(0x0f<<12); + dword |= ((port & 0x0f)<<12); + write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74, + dword); + dbgp_printk("set debug port to %d\n", port); +} + +static void __init detect_set_debug_port(void) +{ + u32 vendorid; + + vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x00); + + if ((vendorid & 0xffff) == 0x10de) { + dbgp_printk("using nvidia set_debug_port\n"); + set_debug_port = nvidia_set_debug_port; + } +} + +static int __init ehci_setup(void) +{ + struct usb_debug_descriptor dbgp_desc; + u32 cmd, ctrl, status, portsc, hcs_params; + u32 debug_port, new_debug_port = 0, n_ports; + u32 devnum; + int ret, i; + int loop; + int port_map_tried; + int playtimes = 3; + +try_next_time: + port_map_tried = 0; + +try_next_port: + + hcs_params = readl(&ehci_caps->hcs_params); + debug_port = HCS_DEBUG_PORT(hcs_params); + n_ports = HCS_N_PORTS(hcs_params); + + dbgp_printk("debug_port: %d\n", debug_port); + dbgp_printk("n_ports: %d\n", n_ports); + + for (i = 1; i <= n_ports; i++) { + portsc = readl(&ehci_regs->port_status[i-1]); + dbgp_printk("portstatus%d: %08x\n", i, portsc); + } + + if (port_map_tried && (new_debug_port != debug_port)) { + if (--playtimes) { + set_debug_port(new_debug_port); + goto try_next_time; + } + return -1; + } + + loop = 10; + /* Reset the EHCI controller */ + cmd = readl(&ehci_regs->command); + cmd |= CMD_RESET; + writel(cmd, &ehci_regs->command); + do { + cmd = readl(&ehci_regs->command); + } while ((cmd & CMD_RESET) && (--loop > 0)); + + if (!loop) { + dbgp_printk("can not reset ehci\n"); + return -1; + } + dbgp_printk("ehci reset done\n"); + + /* Claim ownership, but do not enable yet */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_OWNER; + ctrl &= ~(DBGP_ENABLED | DBGP_INUSE); + writel(ctrl, &ehci_debug->control); + + /* Start the ehci running */ + cmd = readl(&ehci_regs->command); + cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET); + cmd |= CMD_RUN; + writel(cmd, &ehci_regs->command); + + /* Ensure everything is routed to the EHCI */ + writel(FLAG_CF, &ehci_regs->configured_flag); + + /* Wait until the controller is no longer halted */ + loop = 10; + do { + status = readl(&ehci_regs->status); + } while ((status & STS_HALT) && (--loop > 0)); + + if (!loop) { + dbgp_printk("ehci can be started\n"); + return -1; + } + dbgp_printk("ehci started\n"); + + /* Wait for a device to show up in the debug port */ + ret = ehci_wait_for_port(debug_port); + if (ret < 0) { + dbgp_printk("No device found in debug port\n"); + goto next_debug_port; + } + dbgp_printk("ehci wait for port done\n"); + + /* Enable the debug port */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_CLAIM; + writel(ctrl, &ehci_debug->control); + ctrl = readl(&ehci_debug->control); + if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) { + dbgp_printk("No device in debug port\n"); + writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control); + goto err; + } + dbgp_printk("debug ported enabled\n"); + + /* Completely transfer the debug device to the debug controller */ + portsc = readl(&ehci_regs->port_status[debug_port - 1]); + portsc &= ~PORT_PE; + writel(portsc, &ehci_regs->port_status[debug_port - 1]); + + dbgp_mdelay(100); + + /* Find the debug device and make it device number 127 */ + for (devnum = 0; devnum <= 127; devnum++) { + ret = dbgp_control_msg(devnum, + USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0, + &dbgp_desc, sizeof(dbgp_desc)); + if (ret > 0) + break; + } + if (devnum > 127) { + dbgp_printk("Could not find attached debug device\n"); + goto err; + } + if (ret < 0) { + dbgp_printk("Attached device is not a debug device\n"); + goto err; + } + dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; + + /* Move the device to 127 if it isn't already there */ + if (devnum != USB_DEBUG_DEVNUM) { + ret = dbgp_control_msg(devnum, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); + if (ret < 0) { + dbgp_printk("Could not move attached device to %d\n", + USB_DEBUG_DEVNUM); + goto err; + } + devnum = USB_DEBUG_DEVNUM; + dbgp_printk("debug device renamed to 127\n"); + } + + /* Enable the debug interface */ + ret = dbgp_control_msg(USB_DEBUG_DEVNUM, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0); + if (ret < 0) { + dbgp_printk(" Could not enable the debug device\n"); + goto err; + } + dbgp_printk("debug interface enabled\n"); + + /* Perform a small write to get the even/odd data state in sync + */ + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1); + if (ret < 0) { + dbgp_printk("dbgp_bulk_write failed: %d\n", ret); + goto err; + } + dbgp_printk("small write doned\n"); + + return 0; +err: + /* Things didn't work so remove my claim */ + ctrl = readl(&ehci_debug->control); + ctrl &= ~(DBGP_CLAIM | DBGP_OUT); + writel(ctrl, &ehci_debug->control); + return -1; + +next_debug_port: + port_map_tried |= (1<<(debug_port - 1)); + new_debug_port = ((debug_port-1+1)%n_ports) + 1; + if (port_map_tried != ((1<> 29) & 0x7; + bar = (bar * 4) + 0xc; + offset = (debug_port >> 16) & 0xfff; + dbgp_printk("bar: %02x offset: %03x\n", bar, offset); + if (bar != PCI_BASE_ADDRESS_0) { + dbgp_printk("only debug ports on bar 1 handled.\n"); + + return -1; + } + + bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); + dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset); + if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) { + dbgp_printk("only simple 32bit mmio bars supported\n"); + + return -1; + } + + /* double check if the mem space is enabled */ + byte = read_pci_config_byte(bus, slot, func, 0x04); + if (!(byte & 0x2)) { + byte |= 0x02; + write_pci_config_byte(bus, slot, func, 0x04, byte); + dbgp_printk("mmio for ehci enabled\n"); + } + + /* + * FIXME I don't have the bar size so just guess PAGE_SIZE is more + * than enough. 1K is the biggest I have seen. + */ + set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); + ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); + ehci_bar += bar_val & ~PAGE_MASK; + dbgp_printk("ehci_bar: %p\n", ehci_bar); + + ehci_caps = ehci_bar; + ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)); + ehci_debug = ehci_bar + offset; + ehci_dev.bus = bus; + ehci_dev.slot = slot; + ehci_dev.func = func; + + detect_set_debug_port(); + + ret = ehci_setup(); + if (ret < 0) { + dbgp_printk("ehci_setup failed\n"); + ehci_debug = 0; + + return -1; + } + + return 0; +} + +static void early_dbgp_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + + if (!ehci_debug) + return; + while (n > 0) { + chunk = n; + if (chunk > DBGP_MAX_PACKET) + chunk = DBGP_MAX_PACKET; + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, + dbgp_endpoint_out, str, chunk); + str += chunk; + n -= chunk; + } +} + +static struct console early_dbgp_console = { + .name = "earlydbg", + .write = early_dbgp_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; +#endif + /* Console interface to a host file on AMD's SimNow! */ static int simnow_fd; @@ -165,6 +889,7 @@ enum { static noinline long simnow(long cmd, long a, long b, long c) { long ret; + asm volatile("cpuid" : "=a" (ret) : "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2)); @@ -174,6 +899,7 @@ static noinline long simnow(long cmd, long a, long b, long c) static void __init simnow_init(char *str) { char *fn = "klog"; + if (*str == '=') fn = ++str; /* error ignored */ @@ -208,10 +934,11 @@ asmlinkage void early_printk(const char *fmt, ...) va_end(ap); } -static int __initdata keep_early; static int __init setup_early_printk(char *buf) { + int keep_early; + if (!buf) return 0; @@ -219,8 +946,7 @@ static int __init setup_early_printk(char *buf) return 0; early_console_initialized = 1; - if (strstr(buf, "keep")) - keep_early = 1; + keep_early = (strstr(buf, "keep") != NULL); if (!strncmp(buf, "serial", 6)) { early_serial_init(buf + 6); @@ -238,6 +964,17 @@ static int __init setup_early_printk(char *buf) simnow_init(buf + 6); early_console = &simnow_console; keep_early = 1; +#ifdef CONFIG_EARLY_PRINTK_DBGP + } else if (!strncmp(buf, "dbgp", 4)) { + if (early_dbgp_init(buf+4) < 0) + return 0; + early_console = &early_dbgp_console; + /* + * usb subsys will reset ehci controller, so don't keep + * that early console + */ + keep_early = 0; +#endif #ifdef CONFIG_HVC_XEN } else if (!strncmp(buf, "xen", 3)) { early_console = &xenboot_console; @@ -251,4 +988,23 @@ static int __init setup_early_printk(char *buf) register_console(early_console); return 0; } + +void __init enable_debug_console(char *buf) +{ +#ifdef DBGP_DEBUG + struct console *old_early_console = NULL; + + if (early_console_initialized && early_console) { + old_early_console = early_console; + unregister_console(early_console); + early_console_initialized = 0; + } + + setup_early_printk(buf); + + if (early_console == old_early_console && old_early_console) + register_console(old_early_console); +#endif +} + early_param("earlyprintk", setup_early_printk); -- GitLab From a4dbc34d181e87a0d724dee365921e9251f831d4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:14:28 -0700 Subject: [PATCH 0136/5416] x86: add setup_ioapic_ids for numaq in x86_quirks Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_32.c | 5 ++--- arch/x86/kernel/numaq_32.c | 7 +++++++ include/asm-x86/setup.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 98e4db5373f..72ba06314c7 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -1728,10 +1729,8 @@ static void __init setup_ioapic_ids_from_mpc(void) unsigned char old_id; unsigned long flags; -#ifdef CONFIG_X86_NUMAQ - if (found_numaq) + if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids()) return; -#endif /* * Don't check I/O APIC IDs for xAPIC systems. They have diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index b8c45610b20..2434467ddf7 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -229,6 +229,12 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, } } +static int __init numaq_setup_ioapic_ids(void) +{ + /* so can skip it */ + return 1; +} + static struct x86_quirks numaq_x86_quirks __initdata = { .arch_pre_time_init = numaq_pre_time_init, .arch_time_init = NULL, @@ -243,6 +249,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = { .mpc_oem_bus_info = mpc_oem_bus_info, .mpc_oem_pci_bus = mpc_oem_pci_bus, .smp_read_mpc_oem = smp_read_mpc_oem, + .setup_ioapic_ids = numaq_setup_ioapic_ids, }; void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h index b7aeba94e43..80fcc0de80b 100644 --- a/include/asm-x86/setup.h +++ b/include/asm-x86/setup.h @@ -38,6 +38,7 @@ struct x86_quirks { void (*mpc_oem_pci_bus)(struct mpc_config_bus *m); void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable, unsigned short oemsize); + int (*setup_ioapic_ids)(void); }; extern struct x86_quirks *x86_quirks; -- GitLab From 1176fa919292887aa738d317d61fe2bba4d764f2 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:21 -0700 Subject: [PATCH 0137/5416] x86: mach-bigsmp to bigsmp Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/bigsmp.c | 6 +++--- .../{mach-bigsmp/mach_apic.h => bigsmp/apic.h} | 10 +++++----- include/asm-x86/bigsmp/apicdef.h | 13 +++++++++++++ .../{mach-bigsmp/mach_ipi.h => bigsmp/ipi.h} | 6 +++--- include/asm-x86/mach-bigsmp/mach_apicdef.h | 13 ------------- 5 files changed, 24 insertions(+), 24 deletions(-) rename include/asm-x86/{mach-bigsmp/mach_apic.h => bigsmp/apic.h} (94%) create mode 100644 include/asm-x86/bigsmp/apicdef.h rename include/asm-x86/{mach-bigsmp/mach_ipi.h => bigsmp/ipi.h} (77%) delete mode 100644 include/asm-x86/mach-bigsmp/mach_apicdef.h diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index b31f2800638..df37fc9d6a2 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -12,10 +12,10 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include #include static int dmi_bigsmp; /* can be set by dmi scanners */ diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/bigsmp/apic.h similarity index 94% rename from include/asm-x86/mach-bigsmp/mach_apic.h rename to include/asm-x86/bigsmp/apic.h index 05362d44a3e..0a9cd7c5ca0 100644 --- a/include/asm-x86/mach-bigsmp/mach_apic.h +++ b/include/asm-x86/bigsmp/apic.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_BIGSMP__MACH_APIC_H -#define ASM_X86__MACH_BIGSMP__MACH_APIC_H +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) #define esr_disable (1) @@ -11,7 +11,7 @@ static inline int apic_id_registered(void) /* Round robin the irqs amoung the online cpus */ static inline cpumask_t target_cpus(void) -{ +{ static unsigned long cpu = NR_CPUS; do { if (cpu >= NR_CPUS) @@ -23,7 +23,7 @@ static inline cpumask_t target_cpus(void) } #undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0 +#define APIC_DEST_LOGICAL 0 #define TARGET_CPUS (target_cpus()) #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define INT_DELIVERY_MODE (dest_Fixed) @@ -141,4 +141,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* ASM_X86__MACH_BIGSMP__MACH_APIC_H */ +#endif /* __ASM_MACH_APIC_H */ diff --git a/include/asm-x86/bigsmp/apicdef.h b/include/asm-x86/bigsmp/apicdef.h new file mode 100644 index 00000000000..392c3f5ef2f --- /dev/null +++ b/include/asm-x86/bigsmp/apicdef.h @@ -0,0 +1,13 @@ +#ifndef __ASM_MACH_APICDEF_H +#define __ASM_MACH_APICDEF_H + +#define APIC_ID_MASK (0xFF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xFF); +} + +#define GET_APIC_ID(x) get_apic_id(x) + +#endif diff --git a/include/asm-x86/mach-bigsmp/mach_ipi.h b/include/asm-x86/bigsmp/ipi.h similarity index 77% rename from include/asm-x86/mach-bigsmp/mach_ipi.h rename to include/asm-x86/bigsmp/ipi.h index b1b0f966a00..9404c535b7e 100644 --- a/include/asm-x86/mach-bigsmp/mach_ipi.h +++ b/include/asm-x86/bigsmp/ipi.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_BIGSMP__MACH_IPI_H -#define ASM_X86__MACH_BIGSMP__MACH_IPI_H +#ifndef __ASM_MACH_IPI_H +#define __ASM_MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* ASM_X86__MACH_BIGSMP__MACH_IPI_H */ +#endif /* __ASM_MACH_IPI_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_apicdef.h b/include/asm-x86/mach-bigsmp/mach_apicdef.h deleted file mode 100644 index 811935d9d49..00000000000 --- a/include/asm-x86/mach-bigsmp/mach_apicdef.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ASM_X86__MACH_BIGSMP__MACH_APICDEF_H -#define ASM_X86__MACH_BIGSMP__MACH_APICDEF_H - -#define APIC_ID_MASK (0xFF<<24) - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif /* ASM_X86__MACH_BIGSMP__MACH_APICDEF_H */ -- GitLab From c7e7964c9828083aeb41c2664cbf5a32acbfa9d1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:33 -0700 Subject: [PATCH 0138/5416] x86: mach_es7000 to es7000 Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/{mach-es7000 => es7000}/Makefile | 0 arch/x86/{mach-es7000 => es7000}/es7000.h | 18 +++++------ arch/x86/{mach-es7000 => es7000}/es7000plat.c | 2 +- arch/x86/mach-generic/Makefile | 2 +- arch/x86/mach-generic/es7000.c | 10 +++---- .../mach_apic.h => es7000/apic.h} | 30 +++++++++---------- include/asm-x86/es7000/apicdef.h | 13 ++++++++ .../{mach-es7000/mach_ipi.h => es7000/ipi.h} | 6 ++-- .../mach_mpparse.h => es7000/mpparse.h} | 6 ++-- .../mach_wakecpu.h => es7000/wakecpu.h} | 8 ++--- include/asm-x86/mach-es7000/mach_apicdef.h | 13 -------- 11 files changed, 54 insertions(+), 54 deletions(-) rename arch/x86/{mach-es7000 => es7000}/Makefile (100%) rename arch/x86/{mach-es7000 => es7000}/es7000.h (89%) rename arch/x86/{mach-es7000 => es7000}/es7000plat.c (99%) rename include/asm-x86/{mach-es7000/mach_apic.h => es7000/apic.h} (92%) create mode 100644 include/asm-x86/es7000/apicdef.h rename include/asm-x86/{mach-es7000/mach_ipi.h => es7000/ipi.h} (77%) rename include/asm-x86/{mach-es7000/mach_mpparse.h => es7000/mpparse.h} (81%) rename include/asm-x86/{mach-es7000/mach_wakecpu.h => es7000/wakecpu.h} (89%) delete mode 100644 include/asm-x86/mach-es7000/mach_apicdef.h diff --git a/arch/x86/mach-es7000/Makefile b/arch/x86/es7000/Makefile similarity index 100% rename from arch/x86/mach-es7000/Makefile rename to arch/x86/es7000/Makefile diff --git a/arch/x86/mach-es7000/es7000.h b/arch/x86/es7000/es7000.h similarity index 89% rename from arch/x86/mach-es7000/es7000.h rename to arch/x86/es7000/es7000.h index c8d5aa132fa..4e62f6fa95b 100644 --- a/arch/x86/mach-es7000/es7000.h +++ b/arch/x86/es7000/es7000.h @@ -1,7 +1,7 @@ /* * Written by: Garry Forsgren, Unisys Corporation * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface + * This file contains the code to configure and interface * with Unisys ES7000 series hardware system manager. * * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. @@ -18,7 +18,7 @@ * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * Contact information: Unisys Corporation, Township Line & Union Meeting + * Contact information: Unisys Corporation, Township Line & Union Meeting * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: * * http://www.unisys.com @@ -41,7 +41,7 @@ #define MIP_VALID 0x0100000000000000ULL #define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) -#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) +#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) struct mip_reg_info { unsigned long long mip_info; @@ -51,11 +51,11 @@ struct mip_reg_info { }; struct part_info { - unsigned char type; + unsigned char type; unsigned char length; unsigned char part_id; unsigned char apic_mode; - unsigned long snum; + unsigned long snum; char ptype[16]; char sname[64]; char pname[64]; @@ -68,11 +68,11 @@ struct psai { }; struct es7000_mem_info { - unsigned char type; + unsigned char type; unsigned char length; unsigned char resv[6]; - unsigned long long start; - unsigned long long size; + unsigned long long start; + unsigned long long size; }; struct es7000_oem_table { @@ -106,7 +106,7 @@ struct mip_reg { }; #define MIP_SW_APIC 0x1020b -#define MIP_FUNC(VALUE) (VALUE & 0xff) +#define MIP_FUNC(VALUE) (VALUE & 0xff) extern int parse_unisys_oem (char *oemptr); extern void setup_unisys(void); diff --git a/arch/x86/mach-es7000/es7000plat.c b/arch/x86/es7000/es7000plat.c similarity index 99% rename from arch/x86/mach-es7000/es7000plat.c rename to arch/x86/es7000/es7000plat.c index 50189af14b8..7789fde13c3 100644 --- a/arch/x86/mach-es7000/es7000plat.c +++ b/arch/x86/es7000/es7000plat.c @@ -72,7 +72,7 @@ es7000_rename_gsi(int ioapic, int gsi) base += nr_ioapic_registers[i]; } - if (!ioapic && (gsi < 16)) + if (!ioapic && (gsi < 16)) gsi += base; return gsi; } diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 0dbd7803a1d..4706de7676b 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -9,4 +9,4 @@ obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT) += summit.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o obj-$(CONFIG_X86_ES7000) += es7000.o -obj-$(CONFIG_X86_ES7000) += ../../x86/mach-es7000/ +obj-$(CONFIG_X86_ES7000) += ../../x86/es7000/ diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 9b30547d746..520cca0ee04 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -11,12 +11,12 @@ #include #include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include static int probe_es7000(void) { diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/es7000/apic.h similarity index 92% rename from include/asm-x86/mach-es7000/mach_apic.h rename to include/asm-x86/es7000/apic.h index ae877ec267f..bd2c44d1f7a 100644 --- a/include/asm-x86/mach-es7000/mach_apic.h +++ b/include/asm-x86/es7000/apic.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_ES7000__MACH_APIC_H -#define ASM_X86__MACH_ES7000__MACH_APIC_H +#ifndef __ASM_ES7000_APIC_H +#define __ASM_ES7000_APIC_H #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) #define esr_disable (1) @@ -10,7 +10,7 @@ static inline int apic_id_registered(void) } static inline cpumask_t target_cpus(void) -{ +{ #if defined CONFIG_ES7000_CLUSTERED_APIC return CPU_MASK_ALL; #else @@ -23,24 +23,24 @@ static inline cpumask_t target_cpus(void) #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) #define INT_DELIVERY_MODE (dest_LowestPrio) #define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */ -#define NO_BALANCE_IRQ (1) +#define NO_BALANCE_IRQ (1) #undef WAKE_SECONDARY_VIA_INIT #define WAKE_SECONDARY_VIA_MIP #else #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define INT_DELIVERY_MODE (dest_Fixed) #define INT_DEST_MODE (0) /* phys delivery to target procs */ -#define NO_BALANCE_IRQ (0) +#define NO_BALANCE_IRQ (0) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0x0 #define WAKE_SECONDARY_VIA_INIT #endif static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ +{ return 0; -} -static inline unsigned long check_apicid_present(int bit) +} +static inline unsigned long check_apicid_present(int bit) { return physid_isset(bit, phys_cpu_present_map); } @@ -80,7 +80,7 @@ static inline void setup_apic_routing(void) { int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", - (apic_version[apic] == 0x14) ? + (apic_version[apic] == 0x14) ? "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]); } @@ -150,7 +150,7 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) int num_bits_set; int cpus_found = 0; int cpu; - int apicid; + int apicid; num_bits_set = cpus_weight(cpumask); /* Return id to all */ @@ -160,16 +160,16 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) #else return cpu_to_logical_apicid(0); #endif - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of TARGET_CPUS. */ cpu = first_cpu(cpumask); apicid = cpu_to_logical_apicid(cpu); while (cpus_found < num_bits_set) { if (cpu_isset(cpu, cpumask)) { int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != + if (apicid_cluster(apicid) != apicid_cluster(new_apicid)){ printk ("%s: Not a valid mask!\n",__FUNCTION__); #if defined CONFIG_ES7000_CLUSTERED_APIC @@ -191,4 +191,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* ASM_X86__MACH_ES7000__MACH_APIC_H */ +#endif /* __ASM_ES7000_APIC_H */ diff --git a/include/asm-x86/es7000/apicdef.h b/include/asm-x86/es7000/apicdef.h new file mode 100644 index 00000000000..8b234a3cb85 --- /dev/null +++ b/include/asm-x86/es7000/apicdef.h @@ -0,0 +1,13 @@ +#ifndef __ASM_ES7000_APICDEF_H +#define __ASM_ES7000_APICDEF_H + +#define APIC_ID_MASK (0xFF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xFF); +} + +#define GET_APIC_ID(x) get_apic_id(x) + +#endif diff --git a/include/asm-x86/mach-es7000/mach_ipi.h b/include/asm-x86/es7000/ipi.h similarity index 77% rename from include/asm-x86/mach-es7000/mach_ipi.h rename to include/asm-x86/es7000/ipi.h index 3a21240e03d..632a955fcc0 100644 --- a/include/asm-x86/mach-es7000/mach_ipi.h +++ b/include/asm-x86/es7000/ipi.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_ES7000__MACH_IPI_H -#define ASM_X86__MACH_ES7000__MACH_IPI_H +#ifndef __ASM_ES7000_IPI_H +#define __ASM_ES7000_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -21,4 +21,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* ASM_X86__MACH_ES7000__MACH_IPI_H */ +#endif /* __ASM_ES7000_IPI_H */ diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/es7000/mpparse.h similarity index 81% rename from include/asm-x86/mach-es7000/mach_mpparse.h rename to include/asm-x86/es7000/mpparse.h index befde24705b..7b5c889d8e7 100644 --- a/include/asm-x86/mach-es7000/mach_mpparse.h +++ b/include/asm-x86/es7000/mpparse.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_ES7000__MACH_MPPARSE_H -#define ASM_X86__MACH_ES7000__MACH_MPPARSE_H +#ifndef __ASM_ES7000_MPPARSE_H +#define __ASM_ES7000_MPPARSE_H #include @@ -26,4 +26,4 @@ static inline int es7000_check_dsdt(void) } #endif -#endif /* ASM_X86__MACH_ES7000__MACH_MPPARSE_H */ +#endif /* __ASM_MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-es7000/mach_wakecpu.h b/include/asm-x86/es7000/wakecpu.h similarity index 89% rename from include/asm-x86/mach-es7000/mach_wakecpu.h rename to include/asm-x86/es7000/wakecpu.h index 97c776ce13f..3ffc5a7bf66 100644 --- a/include/asm-x86/mach-es7000/mach_wakecpu.h +++ b/include/asm-x86/es7000/wakecpu.h @@ -1,7 +1,7 @@ -#ifndef ASM_X86__MACH_ES7000__MACH_WAKECPU_H -#define ASM_X86__MACH_ES7000__MACH_WAKECPU_H +#ifndef __ASM_ES7000_WAKECPU_H +#define __ASM_ES7000_WAKECPU_H -/* +/* * This file copes with machines that wakeup secondary CPUs by the * INIT, INIT, STARTUP sequence. */ @@ -56,4 +56,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} #endif -#endif /* ASM_X86__MACH_ES7000__MACH_WAKECPU_H */ +#endif /* __ASM_MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-es7000/mach_apicdef.h b/include/asm-x86/mach-es7000/mach_apicdef.h deleted file mode 100644 index a07e5674402..00000000000 --- a/include/asm-x86/mach-es7000/mach_apicdef.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ASM_X86__MACH_ES7000__MACH_APICDEF_H -#define ASM_X86__MACH_ES7000__MACH_APICDEF_H - -#define APIC_ID_MASK (0xFF<<24) - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif /* ASM_X86__MACH_ES7000__MACH_APICDEF_H */ -- GitLab From e8c48efdb971cfb1b043076cf68be535d461a20b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:44 -0700 Subject: [PATCH 0139/5416] x86: mach_summit to summit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/summit_32.c | 2 +- arch/x86/mach-generic/summit.c | 8 +++---- include/asm-x86/mach-summit/mach_apicdef.h | 13 ---------- .../mach_apic.h => summit/apic.h} | 24 +++++++++---------- include/asm-x86/summit/apicdef.h | 13 ++++++++++ .../{mach-summit/mach_ipi.h => summit/ipi.h} | 6 ++--- .../irq_vectors_limits.h | 6 ++--- .../mach_mpparse.h => summit/mpparse.h} | 13 +++++----- 8 files changed, 42 insertions(+), 43 deletions(-) delete mode 100644 include/asm-x86/mach-summit/mach_apicdef.h rename include/asm-x86/{mach-summit/mach_apic.h => summit/apic.h} (93%) create mode 100644 include/asm-x86/summit/apicdef.h rename include/asm-x86/{mach-summit/mach_ipi.h => summit/ipi.h} (77%) rename include/asm-x86/{mach-summit => summit}/irq_vectors_limits.h (65%) rename include/asm-x86/{mach-summit/mach_mpparse.h => summit/mpparse.h} (95%) diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index d67ce5f044b..7b987852e87 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include static struct rio_table_hdr *rio_table_hdr __initdata; static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 752edd96b1b..6ad6b67a723 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -11,11 +11,11 @@ #include #include #include -#include +#include #include -#include -#include -#include +#include +#include +#include static int probe_summit(void) { diff --git a/include/asm-x86/mach-summit/mach_apicdef.h b/include/asm-x86/mach-summit/mach_apicdef.h deleted file mode 100644 index d4bc8590c4f..00000000000 --- a/include/asm-x86/mach-summit/mach_apicdef.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ASM_X86__MACH_SUMMIT__MACH_APICDEF_H -#define ASM_X86__MACH_SUMMIT__MACH_APICDEF_H - -#define APIC_ID_MASK (0xFF<<24) - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif /* ASM_X86__MACH_SUMMIT__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/summit/apic.h similarity index 93% rename from include/asm-x86/mach-summit/mach_apic.h rename to include/asm-x86/summit/apic.h index 7a66758d701..c5b2e4b1035 100644 --- a/include/asm-x86/mach-summit/mach_apic.h +++ b/include/asm-x86/summit/apic.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_SUMMIT__MACH_APIC_H -#define ASM_X86__MACH_SUMMIT__MACH_APIC_H +#ifndef __ASM_SUMMIT_APIC_H +#define __ASM_SUMMIT_APIC_H #include @@ -21,7 +21,7 @@ static inline cpumask_t target_cpus(void) * Just start on cpu 0. IRQ balancing will spread load */ return cpumask_of_cpu(0); -} +} #define TARGET_CPUS (target_cpus()) #define INT_DELIVERY_MODE (dest_LowestPrio) @@ -30,10 +30,10 @@ static inline cpumask_t target_cpus(void) static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { return 0; -} +} /* we don't use the phys_cpu_present_map to indicate apicid presence */ -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long check_apicid_present(int bit) { return 1; } @@ -122,7 +122,7 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map) static inline physid_mask_t apicid_to_cpu_present(int apicid) { - return physid_mask_of_physid(apicid); + return physid_mask_of_physid(0); } static inline void setup_portio_remap(void) @@ -143,22 +143,22 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) int num_bits_set; int cpus_found = 0; int cpu; - int apicid; + int apicid; num_bits_set = cpus_weight(cpumask); /* Return id to all */ if (num_bits_set == NR_CPUS) return (int) 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of TARGET_CPUS. */ cpu = first_cpu(cpumask); apicid = cpu_to_logical_apicid(cpu); while (cpus_found < num_bits_set) { if (cpu_isset(cpu, cpumask)) { int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != + if (apicid_cluster(apicid) != apicid_cluster(new_apicid)){ printk ("%s: Not a valid mask!\n",__FUNCTION__); return 0xFF; @@ -182,4 +182,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return hard_smp_processor_id() >> index_msb; } -#endif /* ASM_X86__MACH_SUMMIT__MACH_APIC_H */ +#endif /* __ASM_SUMMIT_APIC_H */ diff --git a/include/asm-x86/summit/apicdef.h b/include/asm-x86/summit/apicdef.h new file mode 100644 index 00000000000..f3fbca1f61c --- /dev/null +++ b/include/asm-x86/summit/apicdef.h @@ -0,0 +1,13 @@ +#ifndef __ASM_SUMMIT_APICDEF_H +#define __ASM_SUMMIT_APICDEF_H + +#define APIC_ID_MASK (0xFF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (x>>24)&0xFF; +} + +#define GET_APIC_ID(x) get_apic_id(x) + +#endif diff --git a/include/asm-x86/mach-summit/mach_ipi.h b/include/asm-x86/summit/ipi.h similarity index 77% rename from include/asm-x86/mach-summit/mach_ipi.h rename to include/asm-x86/summit/ipi.h index a3b31c528d9..53bd1e7bd7b 100644 --- a/include/asm-x86/mach-summit/mach_ipi.h +++ b/include/asm-x86/summit/ipi.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_SUMMIT__MACH_IPI_H -#define ASM_X86__MACH_SUMMIT__MACH_IPI_H +#ifndef __ASM_SUMMIT_IPI_H +#define __ASM_SUMMIT_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* ASM_X86__MACH_SUMMIT__MACH_IPI_H */ +#endif /* __ASM_SUMMIT_IPI_H */ diff --git a/include/asm-x86/mach-summit/irq_vectors_limits.h b/include/asm-x86/summit/irq_vectors_limits.h similarity index 65% rename from include/asm-x86/mach-summit/irq_vectors_limits.h rename to include/asm-x86/summit/irq_vectors_limits.h index 22f376ad68e..890ce3f5e09 100644 --- a/include/asm-x86/mach-summit/irq_vectors_limits.h +++ b/include/asm-x86/summit/irq_vectors_limits.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H -#define ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H +#ifndef _ASM_IRQ_VECTORS_LIMITS_H +#define _ASM_IRQ_VECTORS_LIMITS_H /* * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs, @@ -11,4 +11,4 @@ #define NR_IRQS 224 #define NR_IRQ_VECTORS 1024 -#endif /* ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H */ +#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ diff --git a/include/asm-x86/mach-summit/mach_mpparse.h b/include/asm-x86/summit/mpparse.h similarity index 95% rename from include/asm-x86/mach-summit/mach_mpparse.h rename to include/asm-x86/summit/mpparse.h index 92396f28772..013ce6fab2d 100644 --- a/include/asm-x86/mach-summit/mach_mpparse.h +++ b/include/asm-x86/summit/mpparse.h @@ -1,7 +1,6 @@ -#ifndef ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H -#define ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H +#ifndef __ASM_SUMMIT_MPPARSE_H +#define __ASM_SUMMIT_MPPARSE_H -#include #include extern int use_cyclone; @@ -12,11 +11,11 @@ extern void setup_summit(void); #define setup_summit() {} #endif -static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, +static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) { - if (!strncmp(oem, "IBM ENSW", 8) && - (!strncmp(productid, "VIGIL SMP", 9) + if (!strncmp(oem, "IBM ENSW", 8) && + (!strncmp(productid, "VIGIL SMP", 9) || !strncmp(productid, "EXA", 3) || !strncmp(productid, "RUTHLESS SMP", 12))){ mark_tsc_unstable("Summit based system"); @@ -107,4 +106,4 @@ static inline int is_WPEG(struct rio_detail *rio){ rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); } -#endif /* ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H */ +#endif /* __ASM_SUMMIT_MPPARSE_H */ -- GitLab From edb181ac4b0c7c1240503da46349a3fb69af9ef6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 02:17:55 -0700 Subject: [PATCH 0140/5416] x86: mach-numaq to numaq Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/numaq.c | 10 +++++----- include/asm-x86/mach-numaq/mach_mpparse.h | 7 ------- .../asm-x86/{mach-numaq/mach_apic.h => numaq/apic.h} | 6 +++--- .../{mach-numaq/mach_apicdef.h => numaq/apicdef.h} | 6 +++--- include/asm-x86/{mach-numaq/mach_ipi.h => numaq/ipi.h} | 6 +++--- include/asm-x86/numaq/mpparse.h | 7 +++++++ .../{mach-numaq/mach_wakecpu.h => numaq/wakecpu.h} | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) delete mode 100644 include/asm-x86/mach-numaq/mach_mpparse.h rename include/asm-x86/{mach-numaq/mach_apic.h => numaq/apic.h} (96%) rename include/asm-x86/{mach-numaq/mach_apicdef.h => numaq/apicdef.h} (55%) rename include/asm-x86/{mach-numaq/mach_ipi.h => numaq/ipi.h} (77%) create mode 100644 include/asm-x86/numaq/mpparse.h rename include/asm-x86/{mach-numaq/mach_wakecpu.h => numaq/wakecpu.h} (88%) diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 95c07efff6b..8cf58394975 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -11,12 +11,12 @@ #include #include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include static int mps_oem_check(struct mp_config_table *mpc, char *oem, diff --git a/include/asm-x86/mach-numaq/mach_mpparse.h b/include/asm-x86/mach-numaq/mach_mpparse.h deleted file mode 100644 index 74ade184920..00000000000 --- a/include/asm-x86/mach-numaq/mach_mpparse.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H -#define ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H - -extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, - char *productid); - -#endif /* ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/numaq/apic.h similarity index 96% rename from include/asm-x86/mach-numaq/mach_apic.h rename to include/asm-x86/numaq/apic.h index 7a0d39edfcf..a8344ba6ea1 100644 --- a/include/asm-x86/mach-numaq/mach_apic.h +++ b/include/asm-x86/numaq/apic.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_NUMAQ__MACH_APIC_H -#define ASM_X86__MACH_NUMAQ__MACH_APIC_H +#ifndef __ASM_NUMAQ_APIC_H +#define __ASM_NUMAQ_APIC_H #include #include @@ -135,4 +135,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* ASM_X86__MACH_NUMAQ__MACH_APIC_H */ +#endif /* __ASM_NUMAQ_APIC_H */ diff --git a/include/asm-x86/mach-numaq/mach_apicdef.h b/include/asm-x86/numaq/apicdef.h similarity index 55% rename from include/asm-x86/mach-numaq/mach_apicdef.h rename to include/asm-x86/numaq/apicdef.h index f870ec5f778..e012a46cc22 100644 --- a/include/asm-x86/mach-numaq/mach_apicdef.h +++ b/include/asm-x86/numaq/apicdef.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_NUMAQ__MACH_APICDEF_H -#define ASM_X86__MACH_NUMAQ__MACH_APICDEF_H +#ifndef __ASM_NUMAQ_APICDEF_H +#define __ASM_NUMAQ_APICDEF_H #define APIC_ID_MASK (0xF<<24) @@ -11,4 +11,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif /* ASM_X86__MACH_NUMAQ__MACH_APICDEF_H */ +#endif diff --git a/include/asm-x86/mach-numaq/mach_ipi.h b/include/asm-x86/numaq/ipi.h similarity index 77% rename from include/asm-x86/mach-numaq/mach_ipi.h rename to include/asm-x86/numaq/ipi.h index 1e835823f4b..935588d286c 100644 --- a/include/asm-x86/mach-numaq/mach_ipi.h +++ b/include/asm-x86/numaq/ipi.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_NUMAQ__MACH_IPI_H -#define ASM_X86__MACH_NUMAQ__MACH_IPI_H +#ifndef __ASM_NUMAQ_IPI_H +#define __ASM_NUMAQ_IPI_H void send_IPI_mask_sequence(cpumask_t, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* ASM_X86__MACH_NUMAQ__MACH_IPI_H */ +#endif /* __ASM_NUMAQ_IPI_H */ diff --git a/include/asm-x86/numaq/mpparse.h b/include/asm-x86/numaq/mpparse.h new file mode 100644 index 00000000000..252292e077b --- /dev/null +++ b/include/asm-x86/numaq/mpparse.h @@ -0,0 +1,7 @@ +#ifndef __ASM_NUMAQ_MPPARSE_H +#define __ASM_NUMAQ_MPPARSE_H + +extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, + char *productid); + +#endif /* __ASM_NUMAQ_MPPARSE_H */ diff --git a/include/asm-x86/mach-numaq/mach_wakecpu.h b/include/asm-x86/numaq/wakecpu.h similarity index 88% rename from include/asm-x86/mach-numaq/mach_wakecpu.h rename to include/asm-x86/numaq/wakecpu.h index 0db8cea643c..c577bda5b1c 100644 --- a/include/asm-x86/mach-numaq/mach_wakecpu.h +++ b/include/asm-x86/numaq/wakecpu.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H -#define ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H +#ifndef __ASM_NUMAQ_WAKECPU_H +#define __ASM_NUMAQ_WAKECPU_H /* This file copes with machines that wakeup secondary CPUs by NMIs */ @@ -40,4 +40,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} -#endif /* ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H */ +#endif /* __ASM_NUMAQ_WAKECPU_H */ -- GitLab From 39eacc20f93614f7bab63eb1d45060503afc46d0 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 25 Jul 2008 23:30:13 +0800 Subject: [PATCH 0141/5416] arch/x86/kernel/visws_quirks.c: Removed duplicated #include Removed duplicated #include in arch/x86/kernel/visws_quirks.c. asm/apic.h asm/arch_hooks.h asm/io.h asm/visws/cobalt.h asm/visws/lithium.h asm/visws/piix4.h linux/init.h linux/interrupt.h linux/smp.h Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/visws_quirks.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 41e01b145c4..0c75691bcf5 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -29,41 +29,26 @@ #include #include #include -#include #include #include #include "mach_apic.h" -#include -#include - #include -#include -#include -#include -#include #include #include -#include #include -#include #include #include -#include #include #include extern int no_broadcast; -#include #include -#include -#include -#include char visws_board_type = -1; char visws_board_rev = -1; -- GitLab From 9749986a878e91182ff027ff0010ab8e3211031a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 26 Jul 2008 17:28:11 +0200 Subject: [PATCH 0142/5416] x86: usb debug port early console, fix fix: arch/x86/kernel/built-in.o: In function `nvidia_set_debug_port': early_printk.c:(.text+0xf8b1): undefined reference to `read_pci_config' early_printk.c:(.text+0xf8dc): undefined reference to `write_pci_config' arch/x86/kernel/built-in.o: In function `setup_early_printk': early_printk.c:(.init.text+0x5487): undefined reference to `early_pci_allowed' early_printk.c:(.init.text+0x54cb): undefined reference to `read_pci_config' early_printk.c:(.init.text+0x54ec): undefined reference to `read_pci_config_16' [...] Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 93422d2ecf6..2a3dfbd5e67 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -46,7 +46,7 @@ config EARLY_PRINTK config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" default n - depends on EARLY_PRINTK + depends on EARLY_PRINTK && PCI help Write kernel log output directly into the EHCI debug port. -- GitLab From b56afe1d41653fb07ab1b5af5ccc12001c4dd5a0 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 24 Jul 2008 12:15:45 -0300 Subject: [PATCH 0143/5416] x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags Using native_pte_val triggers the BUG_ON() in the paravirt_ops version of pte_flags(). Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 06219e60e9c..e2767c28dac 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1347,7 +1347,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { .ptep_modify_prot_commit = __ptep_modify_prot_commit, .pte_val = xen_pte_val, - .pte_flags = native_pte_val, + .pte_flags = native_pte_flags, .pgd_val = xen_pgd_val, .make_pte = xen_make_pte, -- GitLab From 3964cd3a6721f18ef1dd67b9a0a89dc5b36683b9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 26 Jul 2008 19:35:20 +0200 Subject: [PATCH 0144/5416] x86: visws_quirks, fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/visws_quirks.c: In function ‘visws_early_detect’: arch/x86/kernel/visws_quirks.c:290: error: ‘skip_ioapic_setup’ undeclared (first use in this function) arch/x86/kernel/visws_quirks.c:290: error: (Each undeclared identifier is reported only once arch/x86/kernel/visws_quirks.c:290: error: for each function it appears in.) Signed-off-by: Ingo Molnar --- arch/x86/kernel/visws_quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 0c75691bcf5..3059eb45a91 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include -- GitLab From 36a033082b5243d45d508c5ccd47a754edbc6821 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 14 Mar 2008 17:46:38 -0700 Subject: [PATCH 0145/5416] x86: tracehook_signal_handler This makes the x86 signal handling code use tracehook_signal_handler() in place of calling into ptrace guts. The call is moved after the sa_mask processing, but there is no other change. This cleanup doesn't matter to existing debuggers, but is the sensible thing: have all facets of the handler setup complete before the debugger inspects the task again. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_32.c | 6 ++++-- arch/x86/kernel/signal_64.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd893..22aae1683c1 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -558,8 +559,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -568,6 +567,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + return 0; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index b45ef8ddd65..3beb2db88c5 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -444,8 +445,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -453,6 +452,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return ret; -- GitLab From eeea3c3ff8af7f6960a0515d46dff6479bdb91f9 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 16 Mar 2008 23:36:28 -0700 Subject: [PATCH 0146/5416] x86: tracehook syscall This changes x86 syscall tracing to use the new tracehook.h entry points. There is no change, only cleanup. Signed-off-by: Roland McGrath --- arch/x86/kernel/ptrace.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e37dccce85d..19a7d2c4056 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1375,30 +1376,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) force_sig_info(SIGTRAP, &info, tsk); } -static void syscall_trace(struct pt_regs *regs) -{ - if (!(current->ptrace & PT_PTRACED)) - return; - -#if 0 - printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n", - current->comm, - regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0), - current_thread_info()->flags, current->ptrace); -#endif - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} #ifdef CONFIG_X86_32 # define IS_IA32 1 @@ -1432,8 +1409,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) ret = -1L; - if (ret || test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && + tracehook_report_syscall_entry(regs)) + ret = -1L; if (unlikely(current->audit_context)) { if (IS_IA32) @@ -1459,7 +1437,7 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + tracehook_report_syscall_exit(regs, 0); /* * If TIF_SYSCALL_EMU is set, we only get here because of @@ -1475,6 +1453,6 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && - (current->ptrace & PT_PTRACED)) + tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) send_sigtrap(current, regs, 0); } -- GitLab From 68bd0f4ef7750fc277e1268bf40f443898382409 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 18 Apr 2008 17:08:44 -0700 Subject: [PATCH 0147/5416] x86: tracehook: asm/syscall.h Add asm/syscall.h for x86 with all the required entry points. This will allow arch-independent tracing code for system calls. Signed-off-by: Roland McGrath --- include/asm-x86/ptrace.h | 5 + include/asm-x86/syscall.h | 210 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 include/asm-x86/syscall.h diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 8a71db803da..91a77f5c467 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -213,6 +213,11 @@ static inline unsigned long frame_pointer(struct pt_regs *regs) return regs->bp; } +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} + /* * These are defined as per linux/ptrace.h, which see. */ diff --git a/include/asm-x86/syscall.h b/include/asm-x86/syscall.h new file mode 100644 index 00000000000..6f293892895 --- /dev/null +++ b/include/asm-x86/syscall.h @@ -0,0 +1,210 @@ +/* + * Access to user system call parameters and results + * + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * See asm-generic/syscall.h for descriptions of what we must do here. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H 1 + +#include + +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + /* + * We always sign-extend a -1 value being set here, + * so this is always either -1L or a syscall number. + */ + return regs->orig_ax; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->ax = regs->orig_ax; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + unsigned long error = regs->ax; +#ifdef CONFIG_IA32_EMULATION + /* + * TS_COMPAT is set for 32-bit syscall entries and then + * remains set until we return to user mode. + */ + if (task_thread_info(task)->status & TS_COMPAT) + /* + * Sign-extend the value so (int)-EFOO becomes (long)-EFOO + * and will match correctly in comparisons. + */ + error = (long) (int) error; +#endif + return error >= -4095L ? error : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->ax; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->ax = (long) error ?: val; +} + +#ifdef CONFIG_X86_32 + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(args, ®s->bx + i, n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(®s->bx + i, args, n * sizeof(args[0])); +} + +#else /* CONFIG_X86_64 */ + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ +# ifdef CONFIG_IA32_EMULATION + if (task_thread_info(task)->status & TS_COMPAT) + switch (i + n) { + case 6: + if (!n--) break; + *args++ = regs->bp; + case 5: + if (!n--) break; + *args++ = regs->di; + case 4: + if (!n--) break; + *args++ = regs->si; + case 3: + if (!n--) break; + *args++ = regs->dx; + case 2: + if (!n--) break; + *args++ = regs->cx; + case 1: + if (!n--) break; + *args++ = regs->bx; + case 0: + if (!n--) break; + default: + BUG(); + break; + } + else +# endif + switch (i + n) { + case 6: + if (!n--) break; + *args++ = regs->r9; + case 5: + if (!n--) break; + *args++ = regs->r8; + case 4: + if (!n--) break; + *args++ = regs->r10; + case 3: + if (!n--) break; + *args++ = regs->dx; + case 2: + if (!n--) break; + *args++ = regs->si; + case 1: + if (!n--) break; + *args++ = regs->di; + case 0: + if (!n--) break; + default: + BUG(); + break; + } +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ +# ifdef CONFIG_IA32_EMULATION + if (task_thread_info(task)->status & TS_COMPAT) + switch (i + n) { + case 6: + if (!n--) break; + regs->bp = *args++; + case 5: + if (!n--) break; + regs->di = *args++; + case 4: + if (!n--) break; + regs->si = *args++; + case 3: + if (!n--) break; + regs->dx = *args++; + case 2: + if (!n--) break; + regs->cx = *args++; + case 1: + if (!n--) break; + regs->bx = *args++; + case 0: + if (!n--) break; + default: + BUG(); + } + else +# endif + switch (i + n) { + case 6: + if (!n--) break; + regs->r9 = *args++; + case 5: + if (!n--) break; + regs->r8 = *args++; + case 4: + if (!n--) break; + regs->r10 = *args++; + case 3: + if (!n--) break; + regs->dx = *args++; + case 2: + if (!n--) break; + regs->si = *args++; + case 1: + if (!n--) break; + regs->di = *args++; + case 0: + if (!n--) break; + default: + BUG(); + } +} + +#endif /* CONFIG_X86_32 */ + +#endif /* _ASM_SYSCALL_H */ -- GitLab From 4dfcbb997aa9f3a6a3ed8c192f0dac28b027e08f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 19 Apr 2008 15:37:09 -0700 Subject: [PATCH 0148/5416] x86 signals: use asm/syscall.h Replace local inlines with the asm/syscall.h interfaces that do the same things. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_64.c | 38 +++++-------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 3beb2db88c5..cb7cf0216ab 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "sigframe.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -346,35 +347,6 @@ give_sigsegv: return -EFAULT; } -/* - * Return -1L or the syscall number that @regs is executing. - */ -static long current_syscall(struct pt_regs *regs) -{ - /* - * We always sign-extend a -1 value being set here, - * so this is always either -1L or a syscall number. - */ - return regs->orig_ax; -} - -/* - * Return a value that is -EFOO if the system call in @regs->orig_ax - * returned an error. This only works for @regs from @current. - */ -static long current_syscall_ret(struct pt_regs *regs) -{ -#ifdef CONFIG_IA32_EMULATION - if (test_thread_flag(TIF_IA32)) - /* - * Sign-extend the value so (int)-EFOO becomes (long)-EFOO - * and will match correctly in comparisons. - */ - return (int) regs->ax; -#endif - return regs->ax; -} - /* * OK, we're invoking a handler */ @@ -386,9 +358,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, int ret; /* Are we from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* If so, check system call restarting.. */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->ax = -EINTR; @@ -511,9 +483,9 @@ static void do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* Restart the system call - no handlers present */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: -- GitLab From 59e52130f04537d2c80ea44bb007cadd1ad29543 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 19 Apr 2008 19:10:57 -0700 Subject: [PATCH 0149/5416] x86: tracehook: TIF_NOTIFY_RESUME This adds TIF_NOTIFY_RESUME support for x86, both 64-bit and 32-bit. When set, we call tracehook_notify_resume() on the way to user mode. Signed-off-by: Roland McGrath --- arch/x86/kernel/signal_32.c | 5 +++++ arch/x86/kernel/signal_64.c | 5 +++++ include/asm-x86/thread_info.h | 4 +++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 22aae1683c1..4445d26efd4 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -663,5 +663,10 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + clear_thread_flag(TIF_IRET); } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index cb7cf0216ab..d01e3f6ef26 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -523,6 +523,11 @@ void do_notify_resume(struct pt_regs *regs, void *unused, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h index da0a675adf9..4cd5b7bdc8c 100644 --- a/include/asm-x86/thread_info.h +++ b/include/asm-x86/thread_info.h @@ -71,6 +71,7 @@ struct thread_info { * Warning: layout of LSW is hardcoded in entry.S */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ @@ -93,6 +94,7 @@ struct thread_info { #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) @@ -133,7 +135,7 @@ struct thread_info { /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ - (_TIF_SIGPENDING|_TIF_MCE_NOTIFY) + (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME) /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW \ -- GitLab From 99bbc4b1e677ac695431e8d9c8e710ef391c567f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 20 Apr 2008 14:35:12 -0700 Subject: [PATCH 0150/5416] x86: tracehook: CONFIG_HAVE_ARCH_TRACEHOOK The x86 arch code has all the prerequisites, so set HAVE_ARCH_TRACEHOOK. Signed-off-by: Roland McGrath --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6fa2877b17..f463a8a3b21 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -30,6 +30,7 @@ config X86 select HAVE_FTRACE select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER + select HAVE_ARCH_TRACEHOOK select HAVE_EFFICIENT_UNALIGNED_ACCESS config ARCH_DEFCONFIG -- GitLab From d25ae38b7e005af03843833bbd811ffe8c5f8cb4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 25 Jul 2008 19:39:03 -0700 Subject: [PATCH 0151/5416] x86: add apic probe for genapic 64bit - fix intr_remapping_enabled get assigned later, so need to check that in setup_apic_routing Signed-off-by: Yinghai Lu Cc: Jack Steiner Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_64.c | 6 ++++++ arch/x86/kernel/genx2apic_cluster.c | 2 +- arch/x86/kernel/genx2apic_phys.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index b3ba969c50d..6c9bfc9e1e9 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,11 @@ static struct genapic *apic_probe[] __initdata = { */ void __init setup_apic_routing(void) { + if (genapic == &apic_x2apic_phys || genapic == &apic_x2apic_cluster) { + if (!intr_remapping_enabled) + genapic = &apic_flat; + } + if (genapic == &apic_flat) { if (max_physical_apicid >= 8) genapic = &apic_physflat; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index ef3f3182d50..fed9f68efd6 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -14,7 +14,7 @@ DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (cpu_has_x2apic && intr_remapping_enabled) + if (cpu_has_x2apic) return 1; return 0; diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3229c68aedd..958d537b4cc 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -21,7 +21,7 @@ early_param("x2apic_phys", set_x2apic_phys_mode); static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys) + if (cpu_has_x2apic && x2apic_phys) return 1; return 0; -- GitLab From b38addb2da26c0eeab5b538cfbd9d306c50a4726 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 28 Jul 2008 10:19:39 +0200 Subject: [PATCH 0152/5416] ALSA: usb-audio: add BOSS GT-10 support Add a quirk entry for the BOSS GT-10. Signed-off-by: Clemens Ladisch --- sound/usb/usbquirks.h | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 9ea726c049c..3f68359d494 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1383,7 +1383,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { /* Roland SonicCell */ USB_DEVICE(0x0582, 0x00c2), @@ -1415,7 +1414,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - +{ + /* BOSS GT-10 */ + USB_DEVICE(0x0582, 0x00da), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, /* Guillemot devices */ { -- GitLab From d0513fc6c37b009004cf5c7a8e90af0adb3755bc Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Sun, 27 Jul 2008 10:30:30 +0200 Subject: [PATCH 0153/5416] ALSA: hda: added 92HD81/83 support Added support for 92HD81/83 family of codecs. This also includes a pwr_mapping array for pins that have more than one amp to power down. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/patch_sigmatel.c | 248 ++++++++++++++++++++++++++++++--- 2 files changed, 227 insertions(+), 22 deletions(-) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 3a63c445d36..2f112626f24 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -121,6 +121,7 @@ enum { #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f +#define AC_VERB_SET_EAPD 0x788 #define AC_VERB_SET_CODEC_RESET 0x7ff /* diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6ee73ed23dd..23a7b2228e3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -71,6 +71,11 @@ enum { STAC_92HD73XX_MODELS }; +enum { + STAC_92HD83XXX_REF, + STAC_92HD83XXX_MODELS +}; + enum { STAC_92HD71BXX_REF, STAC_DELL_M4_1, @@ -145,6 +150,7 @@ struct sigmatel_spec { /* power management */ unsigned int num_pwrs; + unsigned int *pwr_mapping; hda_nid_t *pwr_nids; hda_nid_t *dac_list; @@ -240,6 +246,33 @@ static hda_nid_t stac92hd73xx_dmux_nids[2] = { 0x20, 0x21, }; +#define STAC92HD83XXX_NUM_DMICS 2 +static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { + 0x11, 0x12, 0 +}; + +#define STAC92HD81_DAC_COUNT 2 +#define STAC92HD83_DAC_COUNT 3 +static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = { + 0x13, 0x14, 0x22, +}; + +static hda_nid_t stac92hd83xxx_dmux_nids[2] = { + 0x17, 0x18, +}; + +static hda_nid_t stac92hd83xxx_adc_nids[2] = { + 0x15, 0x16, +}; + +static hda_nid_t stac92hd83xxx_pwr_nids[4] = { + 0xa, 0xb, 0xd, 0xe, +}; + +static unsigned int stac92hd83xxx_pwr_mapping[4] = { + 0x03, 0x0c, 0x10, 0x40, +}; + static hda_nid_t stac92hd71bxx_pwr_nids[3] = { 0x0a, 0x0d, 0x0f }; @@ -353,6 +386,11 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = { 0x14, 0x1e, 0x22 }; +static hda_nid_t stac92hd83xxx_pin_nids[14] = { + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x1d, 0x1e, 0x1f, 0x20 +}; static hda_nid_t stac92hd71bxx_pin_nids[10] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x14, 0x18, 0x19, 0x1e, @@ -631,6 +669,19 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = { {} }; +static struct hda_verb stac92hd83xxx_core_init[] = { + /* start of config #1 */ + { 0xe, AC_VERB_SET_CONNECT_SEL, 0x3}, + + /* start of config #2 */ + { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0}, + { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0}, + { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1}, + + /* power state controls amps */ + { 0x01, AC_VERB_SET_EAPD, 1 << 2}, +}; + static struct hda_verb stac92hd71bxx_core_init[] = { /* set master volume and direct control */ { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, @@ -701,6 +752,8 @@ static struct hda_verb stac927x_core_init[] = { static struct hda_verb stac9205_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + /* enable analog pc beep path */ + { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, {} }; @@ -823,6 +876,33 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { { } /* end */ }; + +static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT), + HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT), + + HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT), + + HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT), + + HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT), + + /* + HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT), + HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT), + */ + { } /* end */ +}; + static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { STAC_INPUT_SOURCE(2), @@ -1333,6 +1413,27 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { {} /* terminator */ }; +static unsigned int ref92hd83xxx_pin_configs[14] = { + 0x02214030, 0x02211010, 0x02a19020, 0x02170130, + 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, + 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0, + 0x01451160, 0x98560170, +}; + +static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { + [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, +}; + +static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { + [STAC_92HD83XXX_REF] = "ref", +}; + +static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { + /* SigmaTel reference board */ + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, + "DFI LanParty", STAC_92HD71BXX_REF), +}; + static unsigned int ref92hd71bxx_pin_configs[10] = { 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, 0x0181302e, 0x01114010, 0x01019020, 0x90a000f0, @@ -2587,8 +2688,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, } /* labels for mono mux outputs */ -static const char *stac92xx_mono_labels[3] = { - "DAC0", "DAC1", "Mixer" +static const char *stac92xx_mono_labels[4] = { + "DAC0", "DAC1", "Mixer", "DAC2" }; /* create mono mux for mono out on capable codecs */ @@ -2692,16 +2793,19 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, } continue; found: - wcaps = get_wcaps(codec, nid); + wcaps = get_wcaps(codec, nid) & + (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); - if (wcaps & AC_WCAP_OUT_AMP) { + if (wcaps) { sprintf(name, "%s Capture Volume", stac92xx_dmic_labels[dimux->num_items]); err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + (wcaps & AC_WCAP_OUT_AMP) ? + HDA_OUTPUT : HDA_INPUT)); if (err < 0) return err; } @@ -2825,8 +2929,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out hp_speaker_swap = 1; } if (spec->autocfg.mono_out_pin) { - int dir = (get_wcaps(codec, spec->autocfg.mono_out_pin) - & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; + int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & + (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); u32 caps = query_amp_caps(codec, spec->autocfg.mono_out_pin, dir); hda_nid_t conn_list[1]; @@ -2848,21 +2952,26 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out !(wcaps & AC_WCAP_LR_SWAP)) spec->mono_nid = conn_list[0]; } - /* all mono outs have a least a mute/unmute switch */ - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, - "Mono Playback Switch", - HDA_COMPOSE_AMP_VAL(spec->autocfg.mono_out_pin, - 1, 0, dir)); - if (err < 0) - return err; - /* check to see if there is volume support for the amp */ - if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, - "Mono Playback Volume", - HDA_COMPOSE_AMP_VAL(spec->autocfg.mono_out_pin, - 1, 0, dir)); + if (dir) { + hda_nid_t nid = spec->autocfg.mono_out_pin; + + /* most mono outs have a least a mute/unmute switch */ + dir = (dir & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; + err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, + "Mono Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); if (err < 0) return err; + /* check for volume support for the amp */ + if ((caps & AC_AMPCAP_NUM_STEPS) + >> AC_AMPCAP_NUM_STEPS_SHIFT) { + err = stac92xx_add_control(spec, + STAC_CTL_WIDGET_VOL, + "Mono Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); + if (err < 0) + return err; + } } stac92xx_auto_set_pinctl(codec, spec->autocfg.mono_out_pin, @@ -2942,7 +3051,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = dig_out; - if (spec->autocfg.dig_in_pin) + if (dig_in && spec->autocfg.dig_in_pin) spec->dig_in_nid = dig_in; if (spec->kctl_alloc) @@ -3338,7 +3447,12 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx) val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0x000000ff; presence = get_hp_pin_presence(codec, nid); - idx = 1 << idx; + + /* several codecs have two power down bits */ + if (spec->pwr_mapping) + idx = spec->pwr_mapping[idx]; + else + idx = 1 << idx; if (presence) val &= ~idx; @@ -3674,6 +3788,94 @@ again: return 0; } +static struct hda_input_mux stac92hd83xxx_dmux = { + .num_items = 3, + .items = { + { "Analog Inputs", 0x03 }, + { "Digital Mic 1", 0x04 }, + { "Digital Mic 2", 0x05 }, + } +}; + +static int patch_stac92hd83xxx(struct hda_codec *codec) +{ + struct sigmatel_spec *spec; + int err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + spec->mono_nid = 0x19; + spec->digbeep_nid = 0x21; + spec->dmic_nids = stac92hd83xxx_dmic_nids; + spec->dmux_nids = stac92hd83xxx_dmux_nids; + spec->adc_nids = stac92hd83xxx_adc_nids; + spec->pwr_nids = stac92hd83xxx_pwr_nids; + spec->pwr_mapping = stac92hd83xxx_pwr_mapping; + spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); + spec->multiout.dac_nids = stac92hd83xxx_dac_nids; + + spec->init = stac92hd83xxx_core_init; + switch (codec->vendor_id) { + case 0x111d7605: + spec->multiout.num_dacs = STAC92HD81_DAC_COUNT; + break; + default: + spec->num_pwrs--; + spec->init++; /* switch to config #2 */ + spec->multiout.num_dacs = STAC92HD83_DAC_COUNT; + } + + spec->mixer = stac92hd83xxx_mixer; + spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); + spec->num_dmuxes = ARRAY_SIZE(stac92hd83xxx_dmux_nids); + spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); + spec->num_dmics = STAC92HD83XXX_NUM_DMICS; + spec->dinput_mux = &stac92hd83xxx_dmux; + spec->pin_nids = stac92hd83xxx_pin_nids; + spec->board_config = snd_hda_check_board_config(codec, + STAC_92HD83XXX_MODELS, + stac92hd83xxx_models, + stac92hd83xxx_cfg_tbl); +again: + if (spec->board_config < 0) { + snd_printdd(KERN_INFO "hda_codec: Unknown model for" + " STAC92HD83XXX, using BIOS defaults\n"); + err = stac92xx_save_bios_config_regs(codec); + if (err < 0) { + stac92xx_free(codec); + return err; + } + spec->pin_configs = spec->bios_pin_configs; + } else { + spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config]; + stac92xx_set_config_regs(codec); + } + + err = stac92xx_parse_auto_config(codec, 0x1d, 0); + if (!err) { + if (spec->board_config < 0) { + printk(KERN_WARNING "hda_codec: No auto-config is " + "available, default to model=ref\n"); + spec->board_config = STAC_92HD83XXX_REF; + goto again; + } + err = -EINVAL; + } + + if (err < 0) { + stac92xx_free(codec); + return err; + } + + codec->patch_ops = stac92xx_patch_ops; + + return 0; +} + + static int patch_stac92hd71bxx(struct hda_codec *codec) { struct sigmatel_spec *spec; @@ -4395,6 +4597,8 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, + { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, + { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, -- GitLab From 64f53a0492b4bc11868307990bb8f7c1e0764f89 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 27 Jul 2008 08:42:32 -0700 Subject: [PATCH 0154/5416] x86: fix initialization of 'l' bit in ldt descriptors Make sure that fill_ldt() initializes the 'l' bit in the descriptor. It always sets it to 0, ignoring 'lm' in user_desc, preserving original x86_64 behaviour. Previously it was leaving 'l' uninitialized. Signed-off-by: Jeremy Fitzhardinge Cc: Glauber de Oliveira Costa Signed-off-by: Ingo Molnar Cc: Glauber de Oliveira Costa --- include/asm-x86/desc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index 24a524f5e1a..06f786f4b4f 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h @@ -24,6 +24,11 @@ static inline void fill_ldt(struct desc_struct *desc, desc->d = info->seg_32bit; desc->g = info->limit_in_pages; desc->base2 = (info->base_addr & 0xff000000) >> 24; + /* + * Don't allow setting of the lm bit. It is useless anyway + * because 64bit system calls require __USER_CS: + */ + desc->l = 0; } extern struct desc_ptr idt_descr; -- GitLab From a05d2ebab28011c2f3f520833f4bfdd2fd1b9c02 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 27 Jul 2008 08:45:02 -0700 Subject: [PATCH 0155/5416] xen: fix allocation and use of large ldts When the ldt gets to more than 1 page in size, the kernel uses vmalloc to allocate it. This means that: - when making the ldt RO, we must update the pages in both the vmalloc mapping and the linear mapping to make sure there are no RW aliases. - we need to use arbitrary_virt_to_machine to compute the machine addr for each update Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 51 ++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e2767c28dac..b011e4a5dbb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -325,24 +325,55 @@ static unsigned long xen_store_tr(void) return 0; } +/* + * If 'v' is a vmalloc mapping, then find the linear mapping of the + * page (if any) and also set its protections to match: + */ +static void set_aliased_prot(void *v, pgprot_t prot) +{ + int level; + pte_t *ptep; + pte_t pte; + unsigned long pfn; + struct page *page; + + ptep = lookup_address((unsigned long)v, &level); + BUG_ON(ptep == NULL); + + pfn = pte_pfn(*ptep); + page = pfn_to_page(pfn); + + pte = pfn_pte(pfn, prot); + + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) + BUG(); + + if (!PageHighMem(page)) { + void *av = __va(PFN_PHYS(pfn)); + + if (av != v) + if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0)) + BUG(); + } else + kmap_flush_unused(); +} + static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) { - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); - void *v = ldt; + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; - for(i = 0; i < pages; i += PAGE_SIZE) - make_lowmem_page_readonly(v + i); + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL_RO); } static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) { - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE); - void *v = ldt; + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; int i; - for(i = 0; i < pages; i += PAGE_SIZE) - make_lowmem_page_readwrite(v + i); + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL); } static void xen_set_ldt(const void *addr, unsigned entries) @@ -446,7 +477,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, const void *ptr) { unsigned long lp = (unsigned long)&dt[entrynum]; - xmaddr_t mach_lp = virt_to_machine(lp); + xmaddr_t mach_lp = arbitrary_virt_to_machine(lp); u64 entry = *(u64 *)ptr; preempt_disable(); @@ -579,7 +610,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, } static void xen_load_sp0(struct tss_struct *tss, - struct thread_struct *thread) + struct thread_struct *thread) { struct multicall_space mcs = xen_mc_entry(0); MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); -- GitLab From 7225e75144b9718cbbe1820d9c011c809d5773fd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 26 Jul 2008 17:54:22 -0700 Subject: [PATCH 0156/5416] documentation: move mtrr.txt to Doc/x86/ subdir Move mtrr.txt to the Documentation/x86/ subdirectory. Add 00-INDEX to the Documentation/x86/ subdirectory. Signed-off-by: Randy Dunlap Cc: Adrian Bunk Signed-off-by: Ingo Molnar --- Documentation/00-INDEX | 2 -- Documentation/x86/00-INDEX | 4 ++++ Documentation/{ => x86}/mtrr.txt | 4 ++-- arch/x86/Kconfig | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 Documentation/x86/00-INDEX rename Documentation/{ => x86}/mtrr.txt (99%) diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 1977fab3865..661b6ccfe18 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -253,8 +253,6 @@ mono.txt - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. moxa-smartio - file with info on installing/using Moxa multiport serial driver. -mtrr.txt - - how to use PPro Memory Type Range Registers to increase performance. mutex-design.txt - info on the generic mutex subsystem. namespaces/ diff --git a/Documentation/x86/00-INDEX b/Documentation/x86/00-INDEX new file mode 100644 index 00000000000..dbe3377754a --- /dev/null +++ b/Documentation/x86/00-INDEX @@ -0,0 +1,4 @@ +00-INDEX + - this file +mtrr.txt + - how to use x86 Memory Type Range Registers to increase performance diff --git a/Documentation/mtrr.txt b/Documentation/x86/mtrr.txt similarity index 99% rename from Documentation/mtrr.txt rename to Documentation/x86/mtrr.txt index c39ac395970..cc071dc333c 100644 --- a/Documentation/mtrr.txt +++ b/Documentation/x86/mtrr.txt @@ -18,7 +18,7 @@ Richard Gooch The AMD K6-2 (stepping 8 and above) and K6-3 processors have two MTRRs. These are supported. The AMD Athlon family provide 8 Intel style MTRRs. - + The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These are supported. @@ -87,7 +87,7 @@ reg00: base=0x00000000 ( 0MB), size= 64MB: write-back, count=1 reg01: base=0xfb000000 (4016MB), size= 16MB: write-combining, count=1 reg02: base=0xfb000000 (4016MB), size= 4kB: uncachable, count=1 -Some cards (especially Voodoo Graphics boards) need this 4 kB area +Some cards (especially Voodoo Graphics boards) need this 4 kB area excluded from the beginning of the region because it is used for registers. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 03980cb0429..06f935469d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1131,7 +1131,7 @@ config MTRR You can safely say Y even if your machine doesn't have MTRRs, you'll just add about 9 KB to your kernel. - See for more information. + See for more information. config MTRR_SANITIZER bool -- GitLab From d974ae379a2fbe8948f01eabbc6b19c0a80f09bc Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 24 Jul 2008 16:27:46 -0700 Subject: [PATCH 0157/5416] generic, memparse(): constify argument memparse()'s first argument can be const, so it should be. Signed-off-by: Jeremy Fitzhardinge Cc: Andrew Morton Signed-off-by: Ingo Molnar --- include/linux/kernel.h | 2 +- lib/cmdline.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index fdbbf72ca2e..7889c2f9b75 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -176,7 +176,7 @@ extern int vsscanf(const char *, const char *, va_list) extern int get_option(char **str, int *pint); extern char *get_options(const char *str, int nints, int *ints); -extern unsigned long long memparse(char *ptr, char **retptr); +extern unsigned long long memparse(const char *ptr, char **retptr); extern int core_kernel_text(unsigned long addr); extern int __kernel_text_address(unsigned long addr); diff --git a/lib/cmdline.c b/lib/cmdline.c index 5ba8a942a47..f5f3ad8b62f 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -126,7 +126,7 @@ char *get_options(const char *str, int nints, int *ints) * megabyte, or one gigabyte, respectively. */ -unsigned long long memparse(char *ptr, char **retptr) +unsigned long long memparse(const char *ptr, char **retptr) { char *endptr; /* local pointer to end of parsed string */ -- GitLab From 167e6cf62979df03513898966f9227847d192327 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 24 Jul 2008 16:27:52 -0700 Subject: [PATCH 0158/5416] xen-balloon: fix up sysfs issues 1. Set the class so it doesn't clash with the normal memory class 2. Fix up the sysfs show functions to match the new prototype 3. Clean up use of memparse Signed-off-by: Jeremy Fitzhardinge Cc: "viets@work.de" Cc: Andi Kleen Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d4427cb8697..cdec2d843e4 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -60,7 +60,7 @@ #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) -#define BALLOON_CLASS_NAME "memory" +#define BALLOON_CLASS_NAME "xen_memory" struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ @@ -588,12 +588,13 @@ static void balloon_release_driver_page(struct page *page) } -#define BALLOON_SHOW(name, format, args...) \ - static ssize_t show_##name(struct sys_device *dev, \ - char *buf) \ - { \ - return sprintf(buf, format, ##args); \ - } \ +#define BALLOON_SHOW(name, format, args...) \ + static ssize_t show_##name(struct sys_device *dev, \ + struct sysdev_attribute *attr, \ + char *buf) \ + { \ + return sprintf(buf, format, ##args); \ + } \ static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL) BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); @@ -604,7 +605,8 @@ BALLOON_SHOW(hard_limit_kb, (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0); BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); -static ssize_t show_target_kb(struct sys_device *dev, char *buf) +static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) { return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages)); } @@ -614,19 +616,14 @@ static ssize_t store_target_kb(struct sys_device *dev, const char *buf, size_t count) { - char memstring[64], *endchar; + char *endchar; unsigned long long target_bytes; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (count <= 1) - return -EBADMSG; /* runt */ - if (count > sizeof(memstring)) - return -EFBIG; /* too long */ - strcpy(memstring, buf); + target_bytes = memparse(buf, &endchar); - target_bytes = memparse(memstring, &endchar); balloon_set_new_target(target_bytes >> PAGE_SHIFT); return count; -- GitLab From fde28e8f49ed86e771667a3fe81fcc25c93ede8e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 24 Jul 2008 16:28:00 -0700 Subject: [PATCH 0159/5416] xen-balloon: clean up unused functions Remove some unused functions: balloon_update_driver_allowance balloon_release_driver_page only used on the (obsolete, removed) flip path in netfront alloc_empty_pages_and_pagevec free_empty_pages_and_pagevec only used in backend drivers; can be reintroduced when needed Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 147 +----------------------------------------- 1 file changed, 3 insertions(+), 144 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index cdec2d843e4..fff987b10e0 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -226,9 +226,8 @@ static int increase_reservation(unsigned long nr_pages) } set_xen_guest_handle(reservation.extent_start, frame_list); - reservation.nr_extents = nr_pages; - rc = HYPERVISOR_memory_op( - XENMEM_populate_physmap, &reservation); + reservation.nr_extents = nr_pages; + rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); if (rc < nr_pages) { if (rc > 0) { int ret; @@ -236,7 +235,7 @@ static int increase_reservation(unsigned long nr_pages) /* We hit the Xen hard limit: reprobe. */ reservation.nr_extents = rc; ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); + &reservation); BUG_ON(ret != rc); } if (rc >= 0) @@ -464,130 +463,6 @@ static void balloon_exit(void) module_exit(balloon_exit); -static void balloon_update_driver_allowance(long delta) -{ - unsigned long flags; - - spin_lock_irqsave(&balloon_lock, flags); - balloon_stats.driver_pages += delta; - spin_unlock_irqrestore(&balloon_lock, flags); -} - -static int dealloc_pte_fn( - pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) -{ - unsigned long mfn = pte_mfn(*pte); - int ret; - struct xen_memory_reservation reservation = { - .nr_extents = 1, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_xen_guest_handle(reservation.extent_start, &mfn); - set_pte_at(&init_mm, addr, pte, __pte_ma(0ull)); - set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY); - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); - BUG_ON(ret != 1); - return 0; -} - -static struct page **alloc_empty_pages_and_pagevec(int nr_pages) -{ - unsigned long vaddr, flags; - struct page *page, **pagevec; - int i, ret; - - pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL); - if (pagevec == NULL) - return NULL; - - for (i = 0; i < nr_pages; i++) { - page = pagevec[i] = alloc_page(GFP_KERNEL); - if (page == NULL) - goto err; - - vaddr = (unsigned long)page_address(page); - - scrub_page(page); - - spin_lock_irqsave(&balloon_lock, flags); - - if (xen_feature(XENFEAT_auto_translated_physmap)) { - unsigned long gmfn = page_to_pfn(page); - struct xen_memory_reservation reservation = { - .nr_extents = 1, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_xen_guest_handle(reservation.extent_start, &gmfn); - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); - if (ret == 1) - ret = 0; /* success */ - } else { - ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE, - dealloc_pte_fn, NULL); - } - - if (ret != 0) { - spin_unlock_irqrestore(&balloon_lock, flags); - __free_page(page); - goto err; - } - - totalram_pages = --balloon_stats.current_pages; - - spin_unlock_irqrestore(&balloon_lock, flags); - } - - out: - schedule_work(&balloon_worker); - flush_tlb_all(); - return pagevec; - - err: - spin_lock_irqsave(&balloon_lock, flags); - while (--i >= 0) - balloon_append(pagevec[i]); - spin_unlock_irqrestore(&balloon_lock, flags); - kfree(pagevec); - pagevec = NULL; - goto out; -} - -static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) -{ - unsigned long flags; - int i; - - if (pagevec == NULL) - return; - - spin_lock_irqsave(&balloon_lock, flags); - for (i = 0; i < nr_pages; i++) { - BUG_ON(page_count(pagevec[i]) != 1); - balloon_append(pagevec[i]); - } - spin_unlock_irqrestore(&balloon_lock, flags); - - kfree(pagevec); - - schedule_work(&balloon_worker); -} - -static void balloon_release_driver_page(struct page *page) -{ - unsigned long flags; - - spin_lock_irqsave(&balloon_lock, flags); - balloon_append(page); - balloon_stats.driver_pages--; - spin_unlock_irqrestore(&balloon_lock, flags); - - schedule_work(&balloon_worker); -} - - #define BALLOON_SHOW(name, format, args...) \ static ssize_t show_##name(struct sys_device *dev, \ struct sysdev_attribute *attr, \ @@ -691,20 +566,4 @@ static int register_balloon(struct sys_device *sysdev) return error; } -static void unregister_balloon(struct sys_device *sysdev) -{ - int i; - - sysfs_remove_group(&sysdev->kobj, &balloon_info_group); - for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) - sysdev_remove_file(sysdev, balloon_attrs[i]); - sysdev_unregister(sysdev); - sysdev_class_unregister(&balloon_sysdev_class); -} - -static void balloon_sysfs_exit(void) -{ - unregister_balloon(&balloon_sysdev); -} - MODULE_LICENSE("GPL"); -- GitLab From 8cb22bcb1f3ef70d4d48092e9b057175ad9ec78d Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Fri, 18 Jul 2008 16:03:52 -0500 Subject: [PATCH 0160/5416] x86: L3 cache index disable for 2.6.26 New versions of AMD processors have support to disable parts of their L3 caches if too many MCEs are generated by the L3 cache. This patch provides a /sysfs interface under the cache hierarchy to display which caches indices are disabled (if any) and to monitoring applications to disable a cache index. This patch does not set an automatic policy to disable the L3 cache. Policy decisions would need to be made by a RAS handler. This patch merely makes it easier to see what indices are currently disabled. Signed-off-by: Mark Langsdorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 87 +++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index ff517f0b8cc..d6ea50e270e 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -16,6 +16,7 @@ #include #include +#include #define LVL_1_INST 1 #define LVL_1_DATA 2 @@ -130,6 +131,7 @@ struct _cpuid4_info { union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ecx ecx; unsigned long size; + unsigned long can_disable; cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; @@ -251,6 +253,13 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, (ebx->split.ways_of_associativity + 1) - 1; } +static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) +{ + if (index < 3) + return; + this_leaf->can_disable = 1; +} + static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { union _cpuid4_leaf_eax eax; @@ -258,9 +267,12 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le union _cpuid4_leaf_ecx ecx; unsigned edx; - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { amd_cpuid4(index, &eax, &ebx, &ecx); - else + if (boot_cpu_data.x86 >= 0x10) + amd_check_l3_disable(index, this_leaf); + + } else cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); if (eax.split.type == CACHE_TYPE_NULL) return -EIO; /* better error ? */ @@ -637,6 +649,61 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { } } +#define to_object(k) container_of(k, struct _index_kobject, kobj) +#define to_attr(a) container_of(a, struct _cache_attr, attr) + +static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) +{ + struct pci_dev *dev; + if (this_leaf->can_disable) { + int i; + ssize_t ret = 0; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + dev = k8_northbridges[node]; + + for (i = 0; i < 2; i++) { + unsigned int reg; + pci_read_config_dword(dev, 0x1BC + i * 4, ®); + ret += sprintf(buf, "%sEntry: %d\n", buf, i); + ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", + buf, + reg & 0x80000000 ? "Disabled" : "Allowed", + reg & 0x40000000 ? "Disabled" : "Allowed"); + ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", buf, + (reg & 0x30000) >> 16, reg & 0xfff); + + } + return ret; + } + return sprintf(buf, "Feature not enabled\n"); +} + +static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) +{ + struct pci_dev *dev; + if (this_leaf->can_disable) { + /* write the MSR value */ + unsigned int ret; + unsigned int index, val; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + dev = k8_northbridges[node]; + + if (strlen(buf) > 15) + return -EINVAL; + ret = sscanf(buf, "%x %x", &index, &val); + if (ret != 2) + return -EINVAL; + if (index > 1) + return -EINVAL; + val |= 0xc0000000; + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); + wbinvd(); + pci_write_config_dword(dev, 0x1BC + index * 4, val); + return 1; + } + return 0; +} + struct _cache_attr { struct attribute attr; ssize_t (*show)(struct _cpuid4_info *, char *); @@ -657,6 +724,8 @@ define_one_ro(size); define_one_ro(shared_cpu_map); define_one_ro(shared_cpu_list); +static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable); + static struct attribute * default_attrs[] = { &type.attr, &level.attr, @@ -667,12 +736,10 @@ static struct attribute * default_attrs[] = { &size.attr, &shared_cpu_map.attr, &shared_cpu_list.attr, + &cache_disable.attr, NULL }; -#define to_object(k) container_of(k, struct _index_kobject, kobj) -#define to_attr(a) container_of(a, struct _cache_attr, attr) - static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) { struct _cache_attr *fattr = to_attr(attr); @@ -689,7 +756,15 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) static ssize_t store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { - return 0; + struct _cache_attr *fattr = to_attr(attr); + struct _index_kobject *this_leaf = to_object(kobj); + ssize_t ret; + + ret = fattr->store ? + fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), + buf, count) : + 0; + return ret; } static struct sysfs_ops sysfs_ops = { -- GitLab From 7a4983bb5f94f6521aa3236fe5c035cf9bef543f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 21 Jul 2008 13:34:21 +0200 Subject: [PATCH 0161/5416] x86: L3 cache index disable for 2.6.26, cleanups No change in functionality. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 115 ++++++++++++++------------ 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index d6ea50e270e..a61c9e399ba 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -253,14 +253,16 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, (ebx->split.ways_of_associativity + 1) - 1; } -static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) +static void __cpuinit +amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) { if (index < 3) return; this_leaf->can_disable = 1; } -static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +static int +__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; @@ -271,19 +273,20 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le amd_cpuid4(index, &eax, &ebx, &ecx); if (boot_cpu_data.x86 >= 0x10) amd_check_l3_disable(index, this_leaf); - - } else - cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); + } else { + cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); + } + if (eax.split.type == CACHE_TYPE_NULL) return -EIO; /* better error ? */ this_leaf->eax = eax; this_leaf->ebx = ebx; this_leaf->ecx = ecx; - this_leaf->size = (ecx.split.number_of_sets + 1) * - (ebx.split.coherency_line_size + 1) * - (ebx.split.physical_line_partition + 1) * - (ebx.split.ways_of_associativity + 1); + this_leaf->size = (ecx.split.number_of_sets + 1) * + (ebx.split.coherency_line_size + 1) * + (ebx.split.physical_line_partition + 1) * + (ebx.split.ways_of_associativity + 1); return 0; } @@ -649,59 +652,63 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { } } -#define to_object(k) container_of(k, struct _index_kobject, kobj) -#define to_attr(a) container_of(a, struct _cache_attr, attr) +#define to_object(k) container_of(k, struct _index_kobject, kobj) +#define to_attr(a) container_of(a, struct _cache_attr, attr) static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { - struct pci_dev *dev; - if (this_leaf->can_disable) { - int i; - ssize_t ret = 0; - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - dev = k8_northbridges[node]; - - for (i = 0; i < 2; i++) { - unsigned int reg; - pci_read_config_dword(dev, 0x1BC + i * 4, ®); - ret += sprintf(buf, "%sEntry: %d\n", buf, i); - ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", - buf, - reg & 0x80000000 ? "Disabled" : "Allowed", - reg & 0x40000000 ? "Disabled" : "Allowed"); - ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", buf, - (reg & 0x30000) >> 16, reg & 0xfff); + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + struct pci_dev *dev = k8_northbridges[node]; + ssize_t ret = 0; + int i; - } - return ret; + if (!this_leaf->can_disable) + return sprintf(buf, "Feature not enabled\n"); + + for (i = 0; i < 2; i++) { + unsigned int reg; + + pci_read_config_dword(dev, 0x1BC + i * 4, ®); + + ret += sprintf(buf, "%sEntry: %d\n", buf, i); + ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", + buf, + reg & 0x80000000 ? "Disabled" : "Allowed", + reg & 0x40000000 ? "Disabled" : "Allowed"); + ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", + buf, (reg & 0x30000) >> 16, reg & 0xfff); } - return sprintf(buf, "Feature not enabled\n"); + return ret; } -static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) +static ssize_t +store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, + size_t count) { - struct pci_dev *dev; - if (this_leaf->can_disable) { - /* write the MSR value */ - unsigned int ret; - unsigned int index, val; - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - dev = k8_northbridges[node]; - - if (strlen(buf) > 15) - return -EINVAL; - ret = sscanf(buf, "%x %x", &index, &val); - if (ret != 2) - return -EINVAL; - if (index > 1) - return -EINVAL; - val |= 0xc0000000; - pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); - wbinvd(); - pci_write_config_dword(dev, 0x1BC + index * 4, val); - return 1; - } - return 0; + int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + struct pci_dev *dev = k8_northbridges[node]; + unsigned int ret, index, val; + + if (!this_leaf->can_disable) + return 0; + + /* write the MSR value */ + + if (strlen(buf) > 15) + return -EINVAL; + + ret = sscanf(buf, "%x %x", &index, &val); + if (ret != 2) + return -EINVAL; + if (index > 1) + return -EINVAL; + + val |= 0xc0000000; + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); + wbinvd(); + pci_write_config_dword(dev, 0x1BC + index * 4, val); + + return 1; } struct _cache_attr { -- GitLab From a24e8d36f5fc047dac9af6200322ed393f2e3175 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Tue, 22 Jul 2008 13:06:02 -0500 Subject: [PATCH 0162/5416] x86: L3 cache index disable for 2.6.26 On Monday 21 July 2008, Ingo Molnar wrote: > > applied to tip/x86/cpu, thanks Mark. > > > > I've done some coding style fixes for the new functions you've > > introduced, see that commit below. > > -tip testing found the following build failure: > > arch/x86/kernel/built-in.o: In function `show_cache_disable': > intel_cacheinfo.c:(.text+0xbbf2): undefined reference to `k8_northbridges' > arch/x86/kernel/built-in.o: In function `store_cache_disable': > intel_cacheinfo.c:(.text+0xbd91): undefined reference to `k8_northbridges' > > please send a delta fix patch against the tip/x86/cpu branch: > > http://people.redhat.com/mingo/tip.git/README > > which has your patch plus the cleanup applied. delta fix patch follows. It removes the dependency on k8_northbridges. -Mark Langsdorf Operating System Research Center AMD Signed-off-by: Mark Langsdorf Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 43 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index a61c9e399ba..a0c6c6ffed4 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -13,10 +13,10 @@ #include #include #include +#include #include #include -#include #define LVL_1_INST 1 #define LVL_1_DATA 2 @@ -135,6 +135,12 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; +static struct pci_device_id k8_nb_id[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} +}; + unsigned short num_cache_leaves; /* AMD doesn't have CPUID4. Emulate it here to report the same @@ -655,16 +661,39 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { #define to_object(k) container_of(k, struct _index_kobject, kobj) #define to_attr(a) container_of(a, struct _cache_attr, attr) +static struct pci_dev *get_k8_northbridge(int node) +{ + struct pci_dev *dev = NULL; + int i; + + for (i = 0; i <= node; i++) { + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (!dev) + break; + } while (!pci_match_id(&k8_nb_id[0], dev)); + if (!dev) + break; + } + return dev; +} + static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - struct pci_dev *dev = k8_northbridges[node]; + struct pci_dev *dev = NULL; ssize_t ret = 0; int i; if (!this_leaf->can_disable) return sprintf(buf, "Feature not enabled\n"); + dev = get_k8_northbridge(node); + if (!dev) { + printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); + return -EINVAL; + } + for (i = 0; i < 2; i++) { unsigned int reg; @@ -686,14 +715,12 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) { int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); - struct pci_dev *dev = k8_northbridges[node]; + struct pci_dev *dev = NULL; unsigned int ret, index, val; if (!this_leaf->can_disable) return 0; - /* write the MSR value */ - if (strlen(buf) > 15) return -EINVAL; @@ -704,6 +731,12 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, return -EINVAL; val |= 0xc0000000; + dev = get_k8_northbridge(node); + if (!dev) { + printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); + return -EINVAL; + } + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); wbinvd(); pci_write_config_dword(dev, 0x1BC + index * 4, val); -- GitLab From cdcf772ed163651cacac8098b4974aba7f9e1c73 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 28 Jul 2008 16:20:08 +0200 Subject: [PATCH 0163/5416] x86 l3 cache index disable for 2 6 26 fix Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 39 ++++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index a0c6c6ffed4..535d662716d 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -1,8 +1,8 @@ /* - * Routines to indentify caches on Intel CPU. + * Routines to indentify caches on Intel CPU. * - * Changes: - * Venkatesh Pallipadi : Adding cache identification through cpuid(4) + * Changes: + * Venkatesh Pallipadi : Adding cache identification through cpuid(4) * Ashok Raj : Work with CPU hotplug infrastructure. * Andi Kleen / Andreas Herrmann : CPUID4 emulation on AMD. */ @@ -136,9 +136,9 @@ struct _cpuid4_info { }; static struct pci_device_id k8_nb_id[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, - {} + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} }; unsigned short num_cache_leaves; @@ -190,9 +190,10 @@ static unsigned short assocs[] __cpuinitdata = { static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 }; static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 }; -static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, - union _cpuid4_leaf_ebx *ebx, - union _cpuid4_leaf_ecx *ecx) +static void __cpuinit +amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, + union _cpuid4_leaf_ebx *ebx, + union _cpuid4_leaf_ecx *ecx) { unsigned dummy; unsigned line_size, lines_per_tag, assoc, size_in_kb; @@ -264,7 +265,7 @@ amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) { if (index < 3) return; - this_leaf->can_disable = 1; + this_leaf->can_disable = 1; } static int @@ -474,7 +475,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) /* pointer to _cpuid4_info array (for each cache leaf) */ static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info); -#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) +#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) #ifdef CONFIG_SMP static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) @@ -511,7 +512,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) this_leaf = CPUID4_INFO_IDX(cpu, index); for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { - sibling_leaf = CPUID4_INFO_IDX(sibling, index); + sibling_leaf = CPUID4_INFO_IDX(sibling, index); cpu_clear(cpu, sibling_leaf->shared_cpu_map); } } @@ -593,7 +594,7 @@ struct _index_kobject { /* pointer to array of kobjects for cpuX/cache/indexY */ static DEFINE_PER_CPU(struct _index_kobject *, index_kobject); -#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y])) +#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y])) #define show_one_plus(file_name, object, val) \ static ssize_t show_##file_name \ @@ -675,7 +676,7 @@ static struct pci_dev *get_k8_northbridge(int node) if (!dev) break; } - return dev; + return dev; } static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) @@ -736,7 +737,7 @@ store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n"); return -EINVAL; } - + pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); wbinvd(); pci_write_config_dword(dev, 0x1BC + index * 4, val); @@ -789,7 +790,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) ret = fattr->show ? fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), buf) : - 0; + 0; return ret; } @@ -800,9 +801,9 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr, struct _index_kobject *this_leaf = to_object(kobj); ssize_t ret; - ret = fattr->store ? - fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), - buf, count) : + ret = fattr->store ? + fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), + buf, count) : 0; return ret; } -- GitLab From d89961e2dc87b6e30b8e3f60bd2af5cd92cf4643 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 24 Jul 2008 13:48:58 -0700 Subject: [PATCH 0164/5416] xen: suppress known wrmsrs In general, Xen doesn't support wrmsr from an unprivileged domain; it just ends up ignoring the instruction and printing a message on the console. Given that there are sets of MSRs we know the kernel will try to write to, but we don't care, just eat them in xen_write_msr to cut down on console noise. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b011e4a5dbb..b795470ec06 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -854,6 +854,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) ret = -EFAULT; break; #endif + + case MSR_STAR: + case MSR_CSTAR: + case MSR_LSTAR: + case MSR_SYSCALL_MASK: + case MSR_IA32_SYSENTER_CS: + case MSR_IA32_SYSENTER_ESP: + case MSR_IA32_SYSENTER_EIP: + /* Fast syscall setup is all done in hypercalls, so + these are all ignored. Stub them out here to stop + Xen console noise. */ + break; + default: ret = native_write_msr_safe(msr, low, high); } -- GitLab From 239bd83104ec6bcba90221d8b0973d2565142ef8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 28 Jul 2008 16:45:49 +0200 Subject: [PATCH 0165/5416] x86: L3 cache index disable for 2.6.26, fix #2 fix !PCI build failure: arch/x86/kernel/cpu/intel_cacheinfo.c: In function 'get_k8_northbridge': arch/x86/kernel/cpu/intel_cacheinfo.c:675: error: implicit declaration of function 'pci_match_id' Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel_cacheinfo.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index d763d24187c..1677b55371a 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -135,11 +135,13 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ }; +#ifdef CONFIG_PCI static struct pci_device_id k8_nb_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, {} }; +#endif unsigned short num_cache_leaves; @@ -663,6 +665,7 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { #define to_object(k) container_of(k, struct _index_kobject, kobj) #define to_attr(a) container_of(a, struct _cache_attr, attr) +#ifdef CONFIG_PCI static struct pci_dev *get_k8_northbridge(int node) { struct pci_dev *dev = NULL; @@ -679,6 +682,12 @@ static struct pci_dev *get_k8_northbridge(int node) } return dev; } +#else +static struct pci_dev *get_k8_northbridge(int node) +{ + return NULL; +} +#endif static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { -- GitLab From 0b18cb1854152a62492aae088cb80cbeb5c0288d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 28 Jul 2008 17:07:07 +0200 Subject: [PATCH 0166/5416] ALSA: Fix commit: Add automatic model setting for the Acer Aspire 5920G laptop There is a whitespace at the end of added line. Remove it. Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 66025161bd6..38017a129ba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7942,7 +7942,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), - SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), + SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), -- GitLab From e7f5b309c9bd6142f395c4a36123ebac4bcdc1b0 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:11 +0200 Subject: [PATCH 0167/5416] x86: AMD microcode patch loading support v2 Add an entry to the MAINTAINERS file for AMD CPU microcode patch loading support. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03c5d6ccb9f..28f867d99a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -384,6 +384,11 @@ M: joerg.roedel@amd.com L: iommu@lists.linux-foundation.org S: Supported +AMD MICROCODE UPDATE SUPPORT +P: Peter Oruba +M: peter.oruba@amd.com +S: Supported + AMS (Apple Motion Sensor) DRIVER P: Stelian Pop M: stelian@popies.net -- GitLab From 9a56a0f80b52cb41c5e0add47c7ce0bb2ef25eb0 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:13 +0200 Subject: [PATCH 0168/5416] x86: moved Intel microcode patch loader declarations to seperate header file Intel specific microcode declarations have been moved to a seperate header file. There are no code changes to the code itself and no side effects to other parts. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 1 + include/asm-x86/microcode.h | 34 ++++++++++++++++++++++++++++++++++ include/asm-x86/processor.h | 35 ----------------------------------- 3 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 include/asm-x86/microcode.h diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 6994c751590..0d654bd3292 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -93,6 +93,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h new file mode 100644 index 00000000000..5a055685515 --- /dev/null +++ b/include/asm-x86/microcode.h @@ -0,0 +1,34 @@ +struct microcode_header { + unsigned int hdrver; + unsigned int rev; + unsigned int date; + unsigned int sig; + unsigned int cksum; + unsigned int ldrver; + unsigned int pf; + unsigned int datasize; + unsigned int totalsize; + unsigned int reserved[3]; +}; + +struct microcode { + struct microcode_header hdr; + unsigned int bits[0]; +}; + +typedef struct microcode microcode_t; +typedef struct microcode_header microcode_header_t; + +/* microcode format is extended from prescott processors */ +struct extended_signature { + unsigned int sig; + unsigned int pf; + unsigned int cksum; +}; + +struct extended_sigtable { + unsigned int count; + unsigned int cksum; + unsigned int reserved[3]; + struct extended_signature sigs[0]; +}; diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 5f58da401b4..58a76f69ee3 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -561,41 +561,6 @@ static inline void clear_in_cr4(unsigned long mask) write_cr4(cr4); } -struct microcode_header { - unsigned int hdrver; - unsigned int rev; - unsigned int date; - unsigned int sig; - unsigned int cksum; - unsigned int ldrver; - unsigned int pf; - unsigned int datasize; - unsigned int totalsize; - unsigned int reserved[3]; -}; - -struct microcode { - struct microcode_header hdr; - unsigned int bits[0]; -}; - -typedef struct microcode microcode_t; -typedef struct microcode_header microcode_header_t; - -/* microcode format is extended from prescott processors */ -struct extended_signature { - unsigned int sig; - unsigned int pf; - unsigned int cksum; -}; - -struct extended_sigtable { - unsigned int count; - unsigned int cksum; - unsigned int reserved[3]; - struct extended_signature sigs[0]; -}; - typedef struct { unsigned long seg; } mm_segment_t; -- GitLab From 8e61028dfdc6b8ca996abfe8f9baef6792ea2904 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:14 +0200 Subject: [PATCH 0169/5416] x86: typedef removal Removed typedefs. No functional changes to the code. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 24 ++++++++++++------------ include/asm-x86/microcode.h | 3 --- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 0d654bd3292..74e6a77bf19 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -102,17 +102,17 @@ MODULE_LICENSE("GPL"); #define MICROCODE_VERSION "1.14a" #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ #define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ #define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ #define DWSIZE (sizeof (u32)) #define get_totalsize(mc) \ - (((microcode_t *)mc)->hdr.totalsize ? \ - ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) + (((struct microcode *)mc)->hdr.totalsize ? \ + ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) #define get_datasize(mc) \ - (((microcode_t *)mc)->hdr.datasize ? \ - ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) + (((struct microcode *)mc)->hdr.datasize ? \ + ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) #define sigmatch(s1, s2, p1, p2) \ (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) @@ -130,7 +130,7 @@ static struct ucode_cpu_info { unsigned int sig; unsigned int pf; unsigned int rev; - microcode_t *mc; + struct microcode *mc; } ucode_cpu_info[NR_CPUS]; static void collect_cpu_info(int cpu_num) @@ -171,7 +171,7 @@ static void collect_cpu_info(int cpu_num) } static inline int microcode_update_match(int cpu_num, - microcode_header_t *mc_header, int sig, int pf) + struct microcode_header *mc_header, int sig, int pf) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -183,7 +183,7 @@ static inline int microcode_update_match(int cpu_num, static int microcode_sanity_check(void *mc) { - microcode_header_t *mc_header = mc; + struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header = NULL; struct extended_signature *ext_sig; unsigned long total_size, data_size, ext_table_size; @@ -268,7 +268,7 @@ static int microcode_sanity_check(void *mc) static int get_maching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - microcode_header_t *mc_header = mc; + struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); int ext_sigcount, i; @@ -355,7 +355,7 @@ static unsigned int user_buffer_size; /* it's size */ static long get_next_ucode(void **mc, long offset) { - microcode_header_t mc_header; + struct microcode_header mc_header; unsigned long total_size; /* No more data */ @@ -497,13 +497,13 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); static long get_next_ucode_from_buffer(void **mc, const u8 *buf, unsigned long size, long offset) { - microcode_header_t *mc_header; + struct microcode_header *mc_header; unsigned long total_size; /* No more data */ if (offset >= size) return 0; - mc_header = (microcode_header_t *)(buf + offset); + mc_header = (struct microcode_header *)(buf + offset); total_size = get_totalsize(mc_header); if (offset + total_size > size) { diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index 5a055685515..1519ef0674b 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -16,9 +16,6 @@ struct microcode { unsigned int bits[0]; }; -typedef struct microcode microcode_t; -typedef struct microcode_header microcode_header_t; - /* microcode format is extended from prescott processors */ struct extended_signature { unsigned int sig; -- GitLab From c3b71bcec0380836caac9b524fa1585b469b7456 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:15 +0200 Subject: [PATCH 0170/5416] x86: move per CPU microcode structure declaration to header file This structure will be later used by other modules as well and needs therfore to be moved out to a header file. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 8 +------- include/asm-x86/microcode.h | 8 ++++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 74e6a77bf19..4e7b2f65fed 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -125,13 +125,7 @@ static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ static DEFINE_MUTEX(microcode_mutex); -static struct ucode_cpu_info { - int valid; - unsigned int sig; - unsigned int pf; - unsigned int rev; - struct microcode *mc; -} ucode_cpu_info[NR_CPUS]; +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; static void collect_cpu_info(int cpu_num) { diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index 1519ef0674b..d34a1fc1b17 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -29,3 +29,11 @@ struct extended_sigtable { unsigned int reserved[3]; struct extended_signature sigs[0]; }; + +struct ucode_cpu_info { + int valid; + unsigned int sig; + unsigned int pf; + unsigned int rev; + struct microcode *mc; +}; -- GitLab From 1abae31096007cc993f67ae2576fe8f812270ad6 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:16 +0200 Subject: [PATCH 0171/5416] x86: move microcode.c to microcode_intel.c Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/{microcode.c => microcode_intel.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/kernel/{microcode.c => microcode_intel.c} (100%) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 3db651fc8ec..a9be2a0dde8 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_MICROCODE) += microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode_intel.c similarity index 100% rename from arch/x86/kernel/microcode.c rename to arch/x86/kernel/microcode_intel.c -- GitLab From 3e135d887c973b525d43fbb67dfc5972694882f6 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:17 +0200 Subject: [PATCH 0172/5416] x86: code split to two parts Split off existing code into two seperate files. One file holds general code, the other file vendor specific parts. No functional changes, only refactoring. Temporarily Introduced a new module name 'ucode' for result, due to already taken name 'microcode'. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 3 +- arch/x86/kernel/microcode.c | 463 ++++++++++++++++++++++++++++++ arch/x86/kernel/microcode_intel.c | 387 ++----------------------- 3 files changed, 488 insertions(+), 365 deletions(-) create mode 100644 arch/x86/kernel/microcode.c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a9be2a0dde8..abb32aed7f4 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,7 +51,8 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode_intel.o +obj-$(CONFIG_MICROCODE) += ucode.o +ucode-objs := microcode.o microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c new file mode 100644 index 00000000000..c1047d7f7ed --- /dev/null +++ b/arch/x86/kernel/microcode.c @@ -0,0 +1,463 @@ +/* + * Intel CPU Microcode Update Driver for Linux + * + * Copyright (C) 2000-2006 Tigran Aivazian + * 2006 Shaohua Li + * + * This driver allows to upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture + * Software Developer's Manual + * Order Number 253668 or free download from: + * + * http://developer.intel.com/design/pentium4/manuals/253668.htm + * + * For more information, go to http://www.urbanmyth.org/microcode + * + * 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. + * + * 1.0 16 Feb 2000, Tigran Aivazian + * Initial release. + * 1.01 18 Feb 2000, Tigran Aivazian + * Added read() support + cleanups. + * 1.02 21 Feb 2000, Tigran Aivazian + * Added 'device trimming' support. open(O_WRONLY) zeroes + * and frees the saved copy of applied microcode. + * 1.03 29 Feb 2000, Tigran Aivazian + * Made to use devfs (/dev/cpu/microcode) + cleanups. + * 1.04 06 Jun 2000, Simon Trimmer + * Added misc device support (now uses both devfs and misc). + * Added MICROCODE_IOCFREE ioctl to clear memory. + * 1.05 09 Jun 2000, Simon Trimmer + * Messages for error cases (non Intel & no suitable microcode). + * 1.06 03 Aug 2000, Tigran Aivazian + * Removed ->release(). Removed exclusive open and status bitmap. + * Added microcode_rwsem to serialize read()/write()/ioctl(). + * Removed global kernel lock usage. + * 1.07 07 Sep 2000, Tigran Aivazian + * Write 0 to 0x8B msr and then cpuid before reading revision, + * so that it works even if there were no update done by the + * BIOS. Otherwise, reading from 0x8B gives junk (which happened + * to be 0 on my machine which is why it worked even when I + * disabled update by the BIOS) + * Thanks to Eric W. Biederman for the fix. + * 1.08 11 Dec 2000, Richard Schaal and + * Tigran Aivazian + * Intel Pentium 4 processor support and bugfixes. + * 1.09 30 Oct 2001, Tigran Aivazian + * Bugfix for HT (Hyper-Threading) enabled processors + * whereby processor resources are shared by all logical processors + * in a single CPU package. + * 1.10 28 Feb 2002 Asit K Mallick and + * Tigran Aivazian , + * Serialize updates as required on HT processors due to speculative + * nature of implementation. + * 1.11 22 Mar 2002 Tigran Aivazian + * Fix the panic when writing zero-length microcode chunk. + * 1.12 29 Sep 2003 Nitin Kamble , + * Jun Nakajima + * Support for the microcode updates in the new format. + * 1.13 10 Oct 2003 Tigran Aivazian + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl + * because we no longer hold a copy of applied microcode + * in kernel memory. + * 1.14 25 Jun 2004 Tigran Aivazian + * Fix sigmatch() macro to handle old CPUs with pf == 0. + * Thanks to Stuart Swales for pointing out this bug. + */ + +//#define DEBUG /* pr_debug */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("Microcode Update Driver"); +MODULE_AUTHOR("Tigran Aivazian "); +MODULE_LICENSE("GPL"); + +#define MICROCODE_VERSION "1.14a" + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +DEFINE_MUTEX(microcode_mutex); + +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; + +extern long get_next_ucode(void **mc, long offset); +extern int microcode_sanity_check(void *mc); +extern int get_matching_microcode(void *mc, int cpu); +extern void collect_cpu_info(int cpu_num); +extern int cpu_request_microcode(int cpu); +extern void microcode_fini_cpu(int cpu); +extern void apply_microcode(int cpu); +extern int apply_microcode_check_cpu(int cpu); + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +void __user *user_buffer; /* user area microcode data buffer */ +unsigned int user_buffer_size; /* it's size */ + +static int do_microcode_update (void) +{ + long cursor = 0; + int error = 0; + void *new_mc = NULL; + int cpu; + cpumask_t old; + cpumask_of_cpu_ptr_declare(newmask); + + old = current->cpus_allowed; + + while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { + error = microcode_sanity_check(new_mc); + if (error) + goto out; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + for_each_online_cpu(cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!uci->valid) + continue; + cpumask_of_cpu_ptr_next(newmask, cpu); + set_cpus_allowed_ptr(current, newmask); + error = get_maching_microcode(new_mc, cpu); + if (error < 0) + goto out; + if (error == 1) + apply_microcode(cpu); + } + vfree(new_mc); + } +out: + if (cursor > 0) + vfree(new_mc); + if (cursor < 0) + error = cursor; + set_cpus_allowed_ptr(current, &old); + return error; +} + +static int microcode_open (struct inode *unused1, struct file *unused2) +{ + cycle_kernel_lock(); + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +{ + ssize_t ret; + + if ((len >> PAGE_SHIFT) > num_physpages) { + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + return -EINVAL; + } + + get_online_cpus(); + mutex_lock(µcode_mutex); + + user_buffer = (void __user *) buf; + user_buffer_size = (int) len; + + ret = do_microcode_update(); + if (!ret) + ret = (ssize_t)len; + + mutex_unlock(µcode_mutex); + put_online_cpus(); + + return ret; +} + +static const struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .write = microcode_write, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .fops = µcode_fops, +}; + +static int __init microcode_dev_init (void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) { + printk(KERN_ERR + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + return error; + } + + return 0; +} + +static void microcode_dev_exit (void) +{ + misc_deregister(µcode_dev); +} + +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); +#else +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while(0) +#endif + +/* fake device for request_firmware */ +struct platform_device *microcode_pdev; + +static void microcode_init_cpu(int cpu, int resume) +{ + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + old = current->cpus_allowed; + + set_cpus_allowed_ptr(current, newmask); + mutex_lock(µcode_mutex); + collect_cpu_info(cpu); + if (uci->valid && system_state == SYSTEM_RUNNING && !resume) + cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + set_cpus_allowed_ptr(current, &old); +} + +static ssize_t reload_store(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, size_t sz) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + char *end; + unsigned long val = simple_strtoul(buf, &end, 0); + int err = 0; + int cpu = dev->id; + + if (end == buf) + return -EINVAL; + if (val == 1) { + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + + old = current->cpus_allowed; + + get_online_cpus(); + set_cpus_allowed_ptr(current, newmask); + + mutex_lock(µcode_mutex); + if (uci->valid) + err = cpu_request_microcode(cpu); + mutex_unlock(µcode_mutex); + put_online_cpus(); + set_cpus_allowed_ptr(current, &old); + } + if (err) + return err; + return sz; +} + +static ssize_t version_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->rev); +} + +static ssize_t pf_show(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->pf); +} + +static SYSDEV_ATTR(reload, 0200, NULL, reload_store); +static SYSDEV_ATTR(version, 0400, version_show, NULL); +static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); + +static struct attribute *mc_default_attrs[] = { + &attr_reload.attr, + &attr_version.attr, + &attr_processor_flags.attr, + NULL +}; + +static struct attribute_group mc_attr_group = { + .attrs = mc_default_attrs, + .name = "microcode", +}; + +static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +{ + int err, cpu = sys_dev->id; + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d added\n", cpu); + memset(uci, 0, sizeof(*uci)); + + err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); + if (err) + return err; + + microcode_init_cpu(cpu, resume); + + return 0; +} + +static int mc_sysdev_add(struct sys_device *sys_dev) +{ + return __mc_sysdev_add(sys_dev, 0); +} + +static int mc_sysdev_remove(struct sys_device *sys_dev) +{ + int cpu = sys_dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("microcode: CPU%d removed\n", cpu); + microcode_fini_cpu(cpu); + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + return 0; +} + +static int mc_sysdev_resume(struct sys_device *dev) +{ + int cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + pr_debug("microcode: CPU%d resumed\n", cpu); + /* only CPU 0 will apply ucode here */ + apply_microcode(0); + return 0; +} + +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, + .resume = mc_sysdev_resume, +}; + +static __cpuinit int +mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_UP_CANCELED_FROZEN: + /* The CPU refused to come up during a system resume */ + microcode_fini_cpu(cpu); + break; + case CPU_ONLINE: + case CPU_DOWN_FAILED: + mc_sysdev_add(sys_dev); + break; + case CPU_ONLINE_FROZEN: + /* System-wide resume is in progress, try to apply microcode */ + if (apply_microcode_check_cpu(cpu)) { + /* The application of microcode failed */ + microcode_fini_cpu(cpu); + __mc_sysdev_add(sys_dev, 1); + break; + } + case CPU_DOWN_FAILED_FROZEN: + if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) + printk(KERN_ERR "microcode: Failed to create the sysfs " + "group for CPU%d\n", cpu); + break; + case CPU_DOWN_PREPARE: + mc_sysdev_remove(sys_dev); + break; + case CPU_DOWN_PREPARE_FROZEN: + /* Suspend is in progress, only remove the interface */ + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __refdata mc_cpu_notifier = { + .notifier_call = mc_cpu_callback, +}; + +static int __init microcode_init (void) +{ + int error; + + printk(KERN_INFO + "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + + error = microcode_dev_init(); + if (error) + return error; + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); + if (IS_ERR(microcode_pdev)) { + microcode_dev_exit(); + return PTR_ERR(microcode_pdev); + } + + get_online_cpus(); + error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + if (error) { + microcode_dev_exit(); + platform_device_unregister(microcode_pdev); + return error; + } + + register_hotcpu_notifier(&mc_cpu_notifier); + return 0; +} + +static void __exit microcode_exit (void) +{ + microcode_dev_exit(); + + unregister_hotcpu_notifier(&mc_cpu_notifier); + + get_online_cpus(); + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + put_online_cpus(); + + platform_device_unregister(microcode_pdev); +} + +module_init(microcode_init) +module_exit(microcode_exit) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 4e7b2f65fed..eded0a154ea 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -95,18 +95,16 @@ #include #include -MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); +MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14a" - #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof (struct microcode_header)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ -#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ -#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ -#define DWSIZE (sizeof (u32)) +#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ +#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ +#define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ (((struct microcode *)mc)->hdr.totalsize ? \ ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) @@ -123,11 +121,11 @@ MODULE_LICENSE("GPL"); static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); +extern struct mutex microcode_mutex; -static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -static void collect_cpu_info(int cpu_num) +void collect_cpu_info(int cpu_num) { struct cpuinfo_x86 *c = &cpu_data(cpu_num); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -140,7 +138,7 @@ static void collect_cpu_info(int cpu_num) uci->valid = 1; if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || - cpu_has(c, X86_FEATURE_IA64)) { + cpu_has(c, X86_FEATURE_IA64)) { printk(KERN_ERR "microcode: CPU%d not a capable Intel " "processor\n", cpu_num); uci->valid = 0; @@ -175,7 +173,7 @@ static inline int microcode_update_match(int cpu_num, return 1; } -static int microcode_sanity_check(void *mc) +int microcode_sanity_check(void *mc) { struct microcode_header *mc_header = mc; struct extended_sigtable *ext_header = NULL; @@ -259,7 +257,7 @@ static int microcode_sanity_check(void *mc) * return 1 - found update * return < 0 - error */ -static int get_maching_microcode(void *mc, int cpu) +int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header *mc_header = mc; @@ -288,7 +286,7 @@ static int get_maching_microcode(void *mc, int cpu) return 0; find: pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev); + " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev); new_mc = vmalloc(total_size); if (!new_mc) { printk(KERN_ERR "microcode: error! Can not allocate memory\n"); @@ -303,7 +301,7 @@ find: return 1; } -static void apply_microcode(int cpu) +void apply_microcode(int cpu) { unsigned long flags; unsigned int val[2]; @@ -344,10 +342,10 @@ static void apply_microcode(int cpu) } #ifdef CONFIG_MICROCODE_OLD_INTERFACE -static void __user *user_buffer; /* user area microcode data buffer */ -static unsigned int user_buffer_size; /* it's size */ +extern void __user *user_buffer; /* user area microcode data buffer */ +extern unsigned int user_buffer_size; /* it's size */ -static long get_next_ucode(void **mc, long offset) +long get_next_ucode(void **mc, long offset) { struct microcode_header mc_header; unsigned long total_size; @@ -375,117 +373,6 @@ static long get_next_ucode(void **mc, long offset) } return offset + total_size; } - -static int do_microcode_update (void) -{ - long cursor = 0; - int error = 0; - void *new_mc = NULL; - int cpu; - cpumask_t old; - cpumask_of_cpu_ptr_declare(newmask); - - old = current->cpus_allowed; - - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_sanity_check(new_mc); - if (error) - goto out; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - for_each_online_cpu(cpu) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!uci->valid) - continue; - cpumask_of_cpu_ptr_next(newmask, cpu); - set_cpus_allowed_ptr(current, newmask); - error = get_maching_microcode(new_mc, cpu); - if (error < 0) - goto out; - if (error == 1) - apply_microcode(cpu); - } - vfree(new_mc); - } -out: - if (cursor > 0) - vfree(new_mc); - if (cursor < 0) - error = cursor; - set_cpus_allowed_ptr(current, &old); - return error; -} - -static int microcode_open (struct inode *unused1, struct file *unused2) -{ - cycle_kernel_lock(); - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) -{ - ssize_t ret; - - if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); - return -EINVAL; - } - - get_online_cpus(); - mutex_lock(µcode_mutex); - - user_buffer = (void __user *) buf; - user_buffer_size = (int) len; - - ret = do_microcode_update(); - if (!ret) - ret = (ssize_t)len; - - mutex_unlock(µcode_mutex); - put_online_cpus(); - - return ret; -} - -static const struct file_operations microcode_fops = { - .owner = THIS_MODULE, - .write = microcode_write, - .open = microcode_open, -}; - -static struct miscdevice microcode_dev = { - .minor = MICROCODE_MINOR, - .name = "microcode", - .fops = µcode_fops, -}; - -static int __init microcode_dev_init (void) -{ - int error; - - error = misc_register(µcode_dev); - if (error) { - printk(KERN_ERR - "microcode: can't misc_register on minor=%d\n", - MICROCODE_MINOR); - return error; - } - - return 0; -} - -static void microcode_dev_exit (void) -{ - misc_deregister(µcode_dev); -} - -MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); -#else -#define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while(0) #endif static long get_next_ucode_from_buffer(void **mc, const u8 *buf, @@ -515,9 +402,9 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, } /* fake device for request_firmware */ -static struct platform_device *microcode_pdev; +extern struct platform_device *microcode_pdev; -static int cpu_request_microcode(int cpu) +int cpu_request_microcode(int cpu) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -530,7 +417,7 @@ static int cpu_request_microcode(int cpu) /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); - sprintf(name,"intel-ucode/%02x-%02x-%02x", + sprintf(name, "intel-ucode/%02x-%02x-%02x", c->x86, c->x86_model, c->x86_mask); error = request_firmware(&firmware, name, µcode_pdev->dev); if (error) { @@ -544,7 +431,7 @@ static int cpu_request_microcode(int cpu) error = microcode_sanity_check(mc); if (error) break; - error = get_maching_microcode(mc, cpu); + error = get_matching_microcode(mc, cpu); if (error < 0) break; /* @@ -566,7 +453,7 @@ static int cpu_request_microcode(int cpu) return error; } -static int apply_microcode_check_cpu(int cpu) +int apply_microcode_check_cpu(int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -615,241 +502,13 @@ static int apply_microcode_check_cpu(int cpu) return err; } -static void microcode_init_cpu(int cpu, int resume) -{ - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, newmask); - mutex_lock(µcode_mutex); - collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); -} - -static void microcode_fini_cpu(int cpu) +void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; mutex_lock(µcode_mutex); uci->valid = 0; - vfree(uci->mc); + kfree(uci->mc); uci->mc = NULL; mutex_unlock(µcode_mutex); } - -static ssize_t reload_store(struct sys_device *dev, - struct sysdev_attribute *attr, - const char *buf, size_t sz) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - char *end; - unsigned long val = simple_strtoul(buf, &end, 0); - int err = 0; - int cpu = dev->id; - - if (end == buf) - return -EINVAL; - if (val == 1) { - cpumask_t old; - cpumask_of_cpu_ptr(newmask, cpu); - - old = current->cpus_allowed; - - get_online_cpus(); - set_cpus_allowed_ptr(current, newmask); - - mutex_lock(µcode_mutex); - if (uci->valid) - err = cpu_request_microcode(cpu); - mutex_unlock(µcode_mutex); - put_online_cpus(); - set_cpus_allowed_ptr(current, &old); - } - if (err) - return err; - return sz; -} - -static ssize_t version_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->rev); -} - -static ssize_t pf_show(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; - - return sprintf(buf, "0x%x\n", uci->pf); -} - -static SYSDEV_ATTR(reload, 0200, NULL, reload_store); -static SYSDEV_ATTR(version, 0400, version_show, NULL); -static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); - -static struct attribute *mc_default_attrs[] = { - &attr_reload.attr, - &attr_version.attr, - &attr_processor_flags.attr, - NULL -}; - -static struct attribute_group mc_attr_group = { - .attrs = mc_default_attrs, - .name = "microcode", -}; - -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) -{ - int err, cpu = sys_dev->id; - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d added\n", cpu); - memset(uci, 0, sizeof(*uci)); - - err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); - if (err) - return err; - - microcode_init_cpu(cpu, resume); - - return 0; -} - -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - -static int mc_sysdev_remove(struct sys_device *sys_dev) -{ - int cpu = sys_dev->id; - - if (!cpu_online(cpu)) - return 0; - - pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - return 0; -} - -static int mc_sysdev_resume(struct sys_device *dev) -{ - int cpu = dev->id; - - if (!cpu_online(cpu)) - return 0; - pr_debug("microcode: CPU%d resumed\n", cpu); - /* only CPU 0 will apply ucode here */ - apply_microcode(0); - return 0; -} - -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, -}; - -static __cpuinit int -mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; - - sys_dev = get_cpu_sysdev(cpu); - switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; - case CPU_ONLINE: - case CPU_DOWN_FAILED: - mc_sysdev_add(sys_dev); - break; - case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } - case CPU_DOWN_FAILED_FROZEN: - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; - case CPU_DOWN_PREPARE: - mc_sysdev_remove(sys_dev); - break; - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __refdata mc_cpu_notifier = { - .notifier_call = mc_cpu_callback, -}; - -static int __init microcode_init (void) -{ - int error; - - printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); - - error = microcode_dev_init(); - if (error) - return error; - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); - if (IS_ERR(microcode_pdev)) { - microcode_dev_exit(); - return PTR_ERR(microcode_pdev); - } - - get_online_cpus(); - error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - if (error) { - microcode_dev_exit(); - platform_device_unregister(microcode_pdev); - return error; - } - - register_hotcpu_notifier(&mc_cpu_notifier); - return 0; -} - -static void __exit microcode_exit (void) -{ - microcode_dev_exit(); - - unregister_hotcpu_notifier(&mc_cpu_notifier); - - get_online_cpus(); - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); - put_online_cpus(); - - platform_device_unregister(microcode_pdev); -} - -module_init(microcode_init) -module_exit(microcode_exit) -- GitLab From d4ee36686853d5714437c4409f17ad42bfaf4211 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:18 +0200 Subject: [PATCH 0173/5416] x86: structure declaration renaming Renamed common structures to vendor specific naming scheme so other vendors will be able to use the same naming convention. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 46 ++++++++++++++++--------------- include/asm-x86/microcode.h | 10 ++++--- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index eded0a154ea..ca9861bf067 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -100,17 +100,19 @@ MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header)) /* 48 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */ #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ #define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ - (((struct microcode *)mc)->hdr.totalsize ? \ - ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) + (((struct microcode_intel *)mc)->hdr.totalsize ? \ + ((struct microcode_intel *)mc)->hdr.totalsize : \ + DEFAULT_UCODE_TOTALSIZE) + #define get_datasize(mc) \ - (((struct microcode *)mc)->hdr.datasize ? \ - ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) + (((struct microcode_intel *)mc)->hdr.datasize ? \ + ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) #define sigmatch(s1, s2, p1, p2) \ (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) @@ -134,7 +136,7 @@ void collect_cpu_info(int cpu_num) /* We should bind the task to the CPU */ BUG_ON(raw_smp_processor_id() != cpu_num); uci->pf = uci->rev = 0; - uci->mc = NULL; + uci->mc.mc_intel = NULL; uci->valid = 1; if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || @@ -163,7 +165,7 @@ void collect_cpu_info(int cpu_num) } static inline int microcode_update_match(int cpu_num, - struct microcode_header *mc_header, int sig, int pf) + struct microcode_header_intel *mc_header, int sig, int pf) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -175,7 +177,7 @@ static inline int microcode_update_match(int cpu_num, int microcode_sanity_check(void *mc) { - struct microcode_header *mc_header = mc; + struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header = NULL; struct extended_signature *ext_sig; unsigned long total_size, data_size, ext_table_size; @@ -260,7 +262,7 @@ int microcode_sanity_check(void *mc) int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - struct microcode_header *mc_header = mc; + struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); int ext_sigcount, i; @@ -294,10 +296,10 @@ find: } /* free previous update file */ - vfree(uci->mc); + vfree(uci->mc.mc_intel); memcpy(new_mc, mc, total_size); - uci->mc = new_mc; + uci->mc.mc_intel = new_mc; return 1; } @@ -311,7 +313,7 @@ void apply_microcode(int cpu) /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); - if (uci->mc == NULL) + if (uci->mc.mc_intel == NULL) return; /* serialize access to the physical write to MSR 0x79 */ @@ -319,8 +321,8 @@ void apply_microcode(int cpu) /* write microcode via MSR 0x79 */ wrmsr(MSR_IA32_UCODE_WRITE, - (unsigned long) uci->mc->bits, - (unsigned long) uci->mc->bits >> 16 >> 16); + (unsigned long) uci->mc.mc_intel->bits, + (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); /* see notes above for revision 1.07. Apparent chip bug */ @@ -330,14 +332,14 @@ void apply_microcode(int cpu) rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); spin_unlock_irqrestore(µcode_update_lock, flags); - if (val[1] != uci->mc->hdr.rev) { + if (val[1] != uci->mc.mc_intel->hdr.rev) { printk(KERN_ERR "microcode: CPU%d update from revision " "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); return; } printk(KERN_INFO "microcode: CPU%d updated from revision " "0x%x to 0x%x, date = %08x \n", - cpu_num, uci->rev, val[1], uci->mc->hdr.date); + cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date); uci->rev = val[1]; } @@ -347,7 +349,7 @@ extern unsigned int user_buffer_size; /* it's size */ long get_next_ucode(void **mc, long offset) { - struct microcode_header mc_header; + struct microcode_header_intel mc_header; unsigned long total_size; /* No more data */ @@ -378,13 +380,13 @@ long get_next_ucode(void **mc, long offset) static long get_next_ucode_from_buffer(void **mc, const u8 *buf, unsigned long size, long offset) { - struct microcode_header *mc_header; + struct microcode_header_intel *mc_header; unsigned long total_size; /* No more data */ if (offset >= size) return 0; - mc_header = (struct microcode_header *)(buf + offset); + mc_header = (struct microcode_header_intel *)(buf + offset); total_size = get_totalsize(mc_header); if (offset + total_size > size) { @@ -463,7 +465,7 @@ int apply_microcode_check_cpu(int cpu) int err = 0; /* Check if the microcode is available */ - if (!uci->mc) + if (!uci->mc.mc_intel) return 0; old = current->cpus_allowed; @@ -508,7 +510,7 @@ void microcode_fini_cpu(int cpu) mutex_lock(µcode_mutex); uci->valid = 0; - kfree(uci->mc); - uci->mc = NULL; + kfree(uci->mc.mc_intel); + uci->mc.mc_intel = NULL; mutex_unlock(µcode_mutex); } diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index d34a1fc1b17..ef77c6f438b 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -1,4 +1,4 @@ -struct microcode_header { +struct microcode_header_intel { unsigned int hdrver; unsigned int rev; unsigned int date; @@ -11,8 +11,8 @@ struct microcode_header { unsigned int reserved[3]; }; -struct microcode { - struct microcode_header hdr; +struct microcode_intel { + struct microcode_header_intel hdr; unsigned int bits[0]; }; @@ -35,5 +35,7 @@ struct ucode_cpu_info { unsigned int sig; unsigned int pf; unsigned int rev; - struct microcode *mc; + union { + struct microcode_intel *mc_intel; + } mc; }; -- GitLab From 9835fd4ad9ee5fc6b909df72aa3e3dba04415f4b Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:19 +0200 Subject: [PATCH 0174/5416] x86: add AMD specific declarations Added AMD specific declarations to header file. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- include/asm-x86/microcode.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index ef77c6f438b..4e941721c0d 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -30,6 +30,35 @@ struct extended_sigtable { struct extended_signature sigs[0]; }; +struct equiv_cpu_entry { + unsigned int installed_cpu; + unsigned int fixed_errata_mask; + unsigned int fixed_errata_compare; + unsigned int equiv_cpu; +}; + +struct microcode_header_amd { + unsigned int data_code; + unsigned int patch_id; + unsigned char mc_patch_data_id[2]; + unsigned char mc_patch_data_len; + unsigned char init_flag; + unsigned int mc_patch_data_checksum; + unsigned int nb_dev_id; + unsigned int sb_dev_id; + unsigned char processor_rev_id[2]; + unsigned char nb_rev_id; + unsigned char sb_rev_id; + unsigned char bios_api_rev; + unsigned char reserved1[3]; + unsigned int match_reg[8]; +}; + +struct microcode_amd { + struct microcode_header_amd hdr; + unsigned int mpb[0]; +}; + struct ucode_cpu_info { int valid; unsigned int sig; @@ -37,5 +66,6 @@ struct ucode_cpu_info { unsigned int rev; union { struct microcode_intel *mc_intel; + struct microcode_amd *mc_amd; } mc; }; -- GitLab From 26bf7a48c33906cc3415a4492aa9ead7a75f1353 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:20 +0200 Subject: [PATCH 0175/5416] x86: first step of refactoring, introducing microcode_ops Refactoring with the goal of having one general module and separate vendor specific modules that hook into the general one. Microcode_ops is a function pointer structure in which vendor specific modules will enter all functions that differ between vendors and that need to be accessed from the general module. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- include/asm-x86/microcode.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index 4e941721c0d..9231c876e37 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -1,3 +1,16 @@ +struct microcode_ops { + long (*get_next_ucode)(void **mc, long offset); + long (*microcode_get_next_ucode)(void **mc, long offset); + int (*get_matching_microcode)(void *mc, int cpu); + int (*apply_microcode_check_cpu)(int cpu); + int (*microcode_sanity_check)(void *mc); + int (*cpu_request_microcode)(int cpu); + void (*collect_cpu_info)(int cpu_num); + void (*apply_microcode)(int cpu); + void (*microcode_fini_cpu)(int cpu); + void (*clear_patch)(void *data); +}; + struct microcode_header_intel { unsigned int hdrver; unsigned int rev; -- GitLab From 8d86f390d9bb5b39f0a315838d1616de6363e1b9 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:21 +0200 Subject: [PATCH 0176/5416] x86: major refactoring Refactored code by introducing a two-module solution. There is one general module in which vendor specific modules can hook into. However, that is exclusive, there is only one vendor specific module allowed at a time. A CPU vendor check makes sure only the correct module for the underlying system gets called. Functinally in terms of patch loading itself there are no changes. This refactoring provides a basis for future implementations of other vendors' patch loaders. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 25 ++++++++-- arch/x86/kernel/Makefile | 4 +- arch/x86/kernel/microcode.c | 80 ++++++++++++++++++------------- arch/x86/kernel/microcode_intel.c | 50 +++++++++++++++---- include/asm-x86/microcode.h | 3 ++ 5 files changed, 112 insertions(+), 50 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6fa2877b17..6b0b885cf47 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -782,7 +782,7 @@ config X86_REBOOTFIXUPS Say N otherwise. config MICROCODE - tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" + tristate "/dev/cpu/microcode - microcode support" select FW_LOADER ---help--- If you say Y here, you will be able to update the microcode on @@ -791,14 +791,29 @@ config MICROCODE actual microcode binary data itself which is not shipped with the Linux kernel. - For latest news and information on obtaining all the required - ingredients for this driver, check: - . + This option selects the general module only, you need to select + at least one vendor specific module as well. To compile this driver as a module, choose M here: the module will be called microcode. -config MICROCODE_OLD_INTERFACE +config MICROCODE_INTEL + tristate "Intel microcode patch loading support" + depends on MICROCODE + default MICROCODE + select FW_LOADER + --help--- + This options enables microcode patch loading support for Intel + processors. + + For latest news and information on obtaining all the required + Intel ingredients for this driver, check: + . + + This driver is only available as a module: the module + will be called microcode_intel. + + config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index abb32aed7f4..f2f9f6da8c1 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -51,8 +51,8 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += ucode.o -ucode-objs := microcode.o microcode_intel.o +obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index c1047d7f7ed..1e42e79ca69 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -99,25 +99,22 @@ MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14a" +#define MICROCODE_VERSION "2.00" -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -DEFINE_MUTEX(microcode_mutex); +struct microcode_ops *microcode_ops; -struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +static DEFINE_MUTEX(microcode_mutex); +EXPORT_SYMBOL_GPL(microcode_mutex); -extern long get_next_ucode(void **mc, long offset); -extern int microcode_sanity_check(void *mc); -extern int get_matching_microcode(void *mc, int cpu); -extern void collect_cpu_info(int cpu_num); -extern int cpu_request_microcode(int cpu); -extern void microcode_fini_cpu(int cpu); -extern void apply_microcode(int cpu); -extern int apply_microcode_check_cpu(int cpu); +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE -void __user *user_buffer; /* user area microcode data buffer */ -unsigned int user_buffer_size; /* it's size */ +static void __user *user_buffer; /* user area microcode data buffer */ +EXPORT_SYMBOL_GPL(user_buffer); +static unsigned int user_buffer_size; /* it's size */ +EXPORT_SYMBOL_GPL(user_buffer_size); static int do_microcode_update (void) { @@ -130,8 +127,8 @@ static int do_microcode_update (void) old = current->cpus_allowed; - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_sanity_check(new_mc); + while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { + error = microcode_ops->microcode_sanity_check(new_mc); if (error) goto out; /* @@ -145,11 +142,12 @@ static int do_microcode_update (void) continue; cpumask_of_cpu_ptr_next(newmask, cpu); set_cpus_allowed_ptr(current, newmask); - error = get_maching_microcode(new_mc, cpu); + error = microcode_ops->get_matching_microcode(new_mc, + cpu); if (error < 0) goto out; if (error == 1) - apply_microcode(cpu); + microcode_ops->apply_microcode(cpu); } vfree(new_mc); } @@ -232,7 +230,8 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #endif /* fake device for request_firmware */ -struct platform_device *microcode_pdev; +static struct platform_device *microcode_pdev; +EXPORT_SYMBOL_GPL(microcode_pdev); static void microcode_init_cpu(int cpu, int resume) { @@ -244,9 +243,9 @@ static void microcode_init_cpu(int cpu, int resume) set_cpus_allowed_ptr(current, newmask); mutex_lock(µcode_mutex); - collect_cpu_info(cpu); + microcode_ops->collect_cpu_info(cpu); if (uci->valid && system_state == SYSTEM_RUNNING && !resume) - cpu_request_microcode(cpu); + microcode_ops->cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); set_cpus_allowed_ptr(current, &old); } @@ -274,7 +273,7 @@ static ssize_t reload_store(struct sys_device *dev, mutex_lock(µcode_mutex); if (uci->valid) - err = cpu_request_microcode(cpu); + err = microcode_ops->cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); put_online_cpus(); set_cpus_allowed_ptr(current, &old); @@ -349,7 +348,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev) return 0; pr_debug("microcode: CPU%d removed\n", cpu); - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; } @@ -362,7 +361,7 @@ static int mc_sysdev_resume(struct sys_device *dev) return 0; pr_debug("microcode: CPU%d resumed\n", cpu); /* only CPU 0 will apply ucode here */ - apply_microcode(0); + microcode_ops->apply_microcode(0); return 0; } @@ -382,7 +381,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) switch (action) { case CPU_UP_CANCELED_FROZEN: /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); break; case CPU_ONLINE: case CPU_DOWN_FAILED: @@ -390,9 +389,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) break; case CPU_ONLINE_FROZEN: /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { + if (microcode_ops->apply_microcode_check_cpu(cpu)) { /* The application of microcode failed */ - microcode_fini_cpu(cpu); + microcode_ops->microcode_fini_cpu(cpu); __mc_sysdev_add(sys_dev, 1); break; } @@ -416,12 +415,17 @@ static struct notifier_block __refdata mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; -static int __init microcode_init (void) +static int microcode_init(void *opaque, struct module *module) { + struct microcode_ops *ops = (struct microcode_ops *)opaque; int error; - printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + if (microcode_ops) { + printk(KERN_ERR "microcode: already loaded the other module\n"); + return -EEXIST; + } + + microcode_ops = ops; error = microcode_dev_init(); if (error) @@ -443,8 +447,15 @@ static int __init microcode_init (void) } register_hotcpu_notifier(&mc_cpu_notifier); + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION + " " + " \n"); + return 0; } +EXPORT_SYMBOL_GPL(microcode_init); static void __exit microcode_exit (void) { @@ -457,7 +468,10 @@ static void __exit microcode_exit (void) put_online_cpus(); platform_device_unregister(microcode_pdev); -} -module_init(microcode_init) -module_exit(microcode_exit) + microcode_ops = NULL; + + printk(KERN_INFO + "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); +} +EXPORT_SYMBOL_GPL(microcode_exit); diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index ca9861bf067..831db5363db 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -127,7 +127,7 @@ extern struct mutex microcode_mutex; extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; -void collect_cpu_info(int cpu_num) +static void collect_cpu_info(int cpu_num) { struct cpuinfo_x86 *c = &cpu_data(cpu_num); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; @@ -175,7 +175,7 @@ static inline int microcode_update_match(int cpu_num, return 1; } -int microcode_sanity_check(void *mc) +static int microcode_sanity_check(void *mc) { struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header = NULL; @@ -259,7 +259,7 @@ int microcode_sanity_check(void *mc) * return 1 - found update * return < 0 - error */ -int get_matching_microcode(void *mc, int cpu) +static int get_matching_microcode(void *mc, int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header_intel *mc_header = mc; @@ -288,7 +288,8 @@ int get_matching_microcode(void *mc, int cpu) return 0; find: pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev); + " version 0x%x (current=0x%x)\n", + cpu, mc_header->rev, uci->rev); new_mc = vmalloc(total_size); if (!new_mc) { printk(KERN_ERR "microcode: error! Can not allocate memory\n"); @@ -303,7 +304,7 @@ find: return 1; } -void apply_microcode(int cpu) +static void apply_microcode(int cpu) { unsigned long flags; unsigned int val[2]; @@ -347,7 +348,7 @@ void apply_microcode(int cpu) extern void __user *user_buffer; /* user area microcode data buffer */ extern unsigned int user_buffer_size; /* it's size */ -long get_next_ucode(void **mc, long offset) +static long get_next_ucode(void **mc, long offset) { struct microcode_header_intel mc_header; unsigned long total_size; @@ -406,7 +407,7 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, /* fake device for request_firmware */ extern struct platform_device *microcode_pdev; -int cpu_request_microcode(int cpu) +static int cpu_request_microcode(int cpu) { char name[30]; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -455,7 +456,7 @@ int cpu_request_microcode(int cpu) return error; } -int apply_microcode_check_cpu(int cpu) +static int apply_microcode_check_cpu(int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -504,13 +505,42 @@ int apply_microcode_check_cpu(int cpu) return err; } -void microcode_fini_cpu(int cpu) +static void microcode_fini_cpu(int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; mutex_lock(µcode_mutex); uci->valid = 0; - kfree(uci->mc.mc_intel); + vfree(uci->mc.mc_intel); uci->mc.mc_intel = NULL; mutex_unlock(µcode_mutex); } + +static struct microcode_ops microcode_intel_ops = { + .get_next_ucode = get_next_ucode, + .get_matching_microcode = get_matching_microcode, + .microcode_sanity_check = microcode_sanity_check, + .apply_microcode_check_cpu = apply_microcode_check_cpu, + .cpu_request_microcode = cpu_request_microcode, + .collect_cpu_info = collect_cpu_info, + .apply_microcode = apply_microcode, + .microcode_fini_cpu = microcode_fini_cpu, +}; + +static int __init microcode_intel_module_init(void) +{ + struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + + if (c->x86_vendor == X86_VENDOR_INTEL) + return microcode_init(µcode_intel_ops, THIS_MODULE); + else + return -ENODEV; +} + +static void __exit microcode_intel_module_exit(void) +{ + microcode_exit(); +} + +module_init(microcode_intel_module_init) +module_exit(microcode_intel_module_exit) diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index 9231c876e37..18b2aeec2ad 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h @@ -1,3 +1,6 @@ +extern int microcode_init(void *opaque, struct module *module); +extern void microcode_exit(void); + struct microcode_ops { long (*get_next_ucode)(void **mc, long offset); long (*microcode_get_next_ucode)(void **mc, long offset); -- GitLab From 80cc9f1020f49c9e5b50898c102fd444de70a0a3 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Mon, 28 Jul 2008 18:44:22 +0200 Subject: [PATCH 0177/5416] x86: AMD microcode patch loading support This patch introduces microcode patch loading for AMD processors. It is based on previous corresponding work for Intel processors. It hooks into the general patch loading module. Main difference is that a container file format is used to hold all patch data for multiple processors as well as an equivalent CPU table, which comes seperately, as opposed to Intel's microcode patching solution. Kconfig and Makefile have been changed provice config and build option for new source file. Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 21 +- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/microcode_amd.c | 521 ++++++++++++++++++++++++++++++++ 3 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 arch/x86/kernel/microcode_amd.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6b0b885cf47..7bb461758d3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -786,10 +786,12 @@ config MICROCODE select FW_LOADER ---help--- If you say Y here, you will be able to update the microcode on - Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, - Pentium III, Pentium 4, Xeon etc. You will obviously need the - actual microcode binary data itself which is not shipped with the - Linux kernel. + certain Intel and AMD processors. The Intel support is for the + IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, + Pentium 4, Xeon etc. The AMD support is for family 0x10 and + 0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra. + You will obviously need the actual microcode binary data itself + which is not shipped with the Linux kernel. This option selects the general module only, you need to select at least one vendor specific module as well. @@ -813,6 +815,17 @@ config MICROCODE_INTEL This driver is only available as a module: the module will be called microcode_intel. +config MICROCODE_AMD + tristate "AMD microcode patch loading support" + depends on MICROCODE + select FW_LOADER + --help--- + If you select this option, microcode patch loading support for AMD + processors will be enabled. + + This driver is only available as a module: the module + will be called microcode_amd. + config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index f2f9f6da8c1..be454f348c3 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o +obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c new file mode 100644 index 00000000000..db199e3fdd1 --- /dev/null +++ b/arch/x86/kernel/microcode_amd.c @@ -0,0 +1,521 @@ +/* + * AMD CPU Microcode Update Driver for Linux + * Copyright (C) 2008 Advanced Micro Devices Inc. + * + * Author: Peter Oruba + * + * Based on work by: + * Tigran Aivazian + * + * This driver allows to upgrade microcode on AMD + * family 0x10 and 0x11 processors. + * + * Licensed unter the terms of the GNU General Public + * License version 2. See file COPYING for details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_DESCRIPTION("AMD Microcode Update Driver"); +MODULE_AUTHOR("Peter Oruba "); +MODULE_LICENSE("GPLv2"); + +#define UCODE_MAGIC 0x00414d44 +#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 +#define UCODE_UCODE_TYPE 0x00000001 + +#define UCODE_MAX_SIZE (2048) +#define DEFAULT_UCODE_DATASIZE (896) /* 896 bytes */ +#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) /* 64 bytes */ +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */ +#define DWSIZE (sizeof(u32)) +/* For now we support a fixed ucode total size only */ +#define get_totalsize(mc) \ + ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ + + MC_HEADER_SIZE) + +extern int microcode_init(void *opaque, struct module *module); +extern void microcode_exit(void); + +/* serialize access to the physical write */ +static DEFINE_SPINLOCK(microcode_update_lock); + +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ +extern struct mutex (microcode_mutex); + +struct equiv_cpu_entry *equiv_cpu_table; + +extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; + +static void collect_cpu_info_amd(int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + /* We should bind the task to the CPU */ + BUG_ON(raw_smp_processor_id() != cpu); + uci->rev = 0; + uci->pf = 0; + uci->mc.mc_amd = NULL; + uci->valid = 1; + + if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { + printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", + cpu); + uci->valid = 0; + return; + } + + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (uci->rev) + : "i" (0x0000008B) : "ecx"); + + printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", + uci->rev); +} + +static int get_matching_microcode_amd(void *mc, int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct microcode_header_amd *mc_header = mc; + unsigned long total_size = get_totalsize(mc_header); + void *new_mc; + struct pci_dev *nb_pci_dev, *sb_pci_dev; + unsigned int current_cpu_id; + unsigned int equiv_cpu_id = 0x00; + unsigned int i = 0; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + /* This is a tricky part. We might be called from a write operation */ + /* to the device file instead of the usual process of firmware */ + /* loading. This routine needs to be able to distinguish both */ +/* cases. This is done by checking if there alread is a equivalent */ + /* CPU table installed. If not, we're written through */ + /* /dev/cpu/microcode. */ +/* Since we ignore all checks. The error case in which going through */ +/* firmware loading and that table is not loaded has already been */ + /* checked earlier. */ + if (equiv_cpu_table == NULL) { + printk(KERN_INFO "microcode: CPU%d microcode update with " + "version 0x%x (current=0x%x)\n", + cpu, mc_header->patch_id, uci->rev); + goto out; + } + + current_cpu_id = cpuid_eax(0x00000001); + + while (equiv_cpu_table[i].installed_cpu != 0) { + if (current_cpu_id == equiv_cpu_table[i].installed_cpu) { + equiv_cpu_id = equiv_cpu_table[i].equiv_cpu; + break; + } + i++; + } + + if (!equiv_cpu_id) { + printk(KERN_ERR "microcode: CPU%d cpu_id " + "not found in equivalent cpu table \n", cpu); + return 0; + } + + if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) { + printk(KERN_ERR + "microcode: CPU%d patch does not match " + "(patch is %x, cpu extended is %x) \n", + cpu, mc_header->processor_rev_id[0], + (equiv_cpu_id & 0xff)); + return 0; + } + + if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) { + printk(KERN_ERR "microcode: CPU%d patch does not match " + "(patch is %x, cpu base id is %x) \n", + cpu, mc_header->processor_rev_id[1], + ((equiv_cpu_id >> 16) & 0xff)); + + return 0; + } + + /* ucode may be northbridge specific */ + if (mc_header->nb_dev_id) { + nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, + (mc_header->nb_dev_id & 0xff), + NULL); + if ((!nb_pci_dev) || + (mc_header->nb_rev_id != nb_pci_dev->revision)) { + printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu); + pci_dev_put(nb_pci_dev); + return 0; + } + pci_dev_put(nb_pci_dev); + } + + /* ucode may be southbridge specific */ + if (mc_header->sb_dev_id) { + sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, + (mc_header->sb_dev_id & 0xff), + NULL); + if ((!sb_pci_dev) || + (mc_header->sb_rev_id != sb_pci_dev->revision)) { + printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu); + pci_dev_put(sb_pci_dev); + return 0; + } + pci_dev_put(sb_pci_dev); + } + + if (mc_header->patch_id <= uci->rev) + return 0; + + printk(KERN_INFO "microcode: CPU%d found a matching microcode " + "update with version 0x%x (current=0x%x)\n", + cpu, mc_header->patch_id, uci->rev); + +out: + new_mc = vmalloc(UCODE_MAX_SIZE); + if (!new_mc) { + printk(KERN_ERR "microcode: error, can't allocate memory\n"); + return -ENOMEM; + } + memset(new_mc, 0, UCODE_MAX_SIZE); + + /* free previous update file */ + vfree(uci->mc.mc_amd); + + memcpy(new_mc, mc, total_size); + + uci->mc.mc_amd = new_mc; + return 1; +} + +static void apply_microcode_amd(int cpu) +{ + unsigned long flags; + unsigned int eax, edx; + unsigned int rev; + int cpu_num = raw_smp_processor_id(); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; + + /* We should bind the task to the CPU */ + BUG_ON(cpu_num != cpu); + + if (uci->mc.mc_amd == NULL) + return; + + spin_lock_irqsave(µcode_update_lock, flags); + + edx = (unsigned int)(((unsigned long) + &(uci->mc.mc_amd->hdr.data_code)) >> 32); + eax = (unsigned int)(((unsigned long) + &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL); + + asm volatile("movl %0, %%ecx; wrmsr" : + : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx"); + + /* get patch id after patching */ + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (rev) + : "i" (0x0000008B) : "ecx"); + + spin_unlock_irqrestore(µcode_update_lock, flags); + + /* check current patch id and patch's id for match */ + if (rev != uci->mc.mc_amd->hdr.patch_id) { + printk(KERN_ERR "microcode: CPU%d update from revision " + "0x%x to 0x%x failed\n", cpu_num, + uci->mc.mc_amd->hdr.patch_id, rev); + return; + } + + printk(KERN_INFO "microcode: CPU%d updated from revision " + "0x%x to 0x%x \n", + cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id); + + uci->rev = rev; +} + +#ifdef CONFIG_MICROCODE_OLD_INTERFACE +extern void __user *user_buffer; /* user area microcode data buffer */ +extern unsigned int user_buffer_size; /* it's size */ + +static long get_next_ucode_amd(void **mc, long offset) +{ + struct microcode_header_amd mc_header; + unsigned long total_size; + + /* No more data */ + if (offset >= user_buffer_size) + return 0; + if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + return -EFAULT; + } + total_size = get_totalsize(&mc_header); + if (offset + total_size > user_buffer_size) { + printk(KERN_ERR "microcode: error! Bad total size in microcode " + "data file\n"); + return -EINVAL; + } + *mc = vmalloc(UCODE_MAX_SIZE); + if (!*mc) + return -ENOMEM; + memset(*mc, 0, UCODE_MAX_SIZE); + + if (copy_from_user(*mc, user_buffer + offset, total_size)) { + printk(KERN_ERR "microcode: error! Can not read user data\n"); + vfree(*mc); + return -EFAULT; + } + return offset + total_size; +} +#else +#define get_next_ucode_amd() NULL +#endif + +static long get_next_ucode_from_buffer_amd(void **mc, void *buf, + unsigned long size, long offset) +{ + struct microcode_header_amd *mc_header; + unsigned long total_size; + unsigned char *buf_pos = buf; + + /* No more data */ + if (offset >= size) + return 0; + + if (buf_pos[offset] != UCODE_UCODE_TYPE) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode payload type field\n"); + return -EINVAL; + } + + mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]); + + total_size = (unsigned long) (buf_pos[offset+4] + + (buf_pos[offset+5] << 8)); + + printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n", + size, total_size, offset); + + if (offset + total_size > size) { + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); + return -EINVAL; + } + + *mc = vmalloc(UCODE_MAX_SIZE); + if (!*mc) { + printk(KERN_ERR "microcode: error! " + "Can not allocate memory for microcode patch\n"); + return -ENOMEM; + } + + memset(*mc, 0, UCODE_MAX_SIZE); + memcpy(*mc, buf + offset + 8, total_size); + + return offset + total_size + 8; +} + +static long install_equiv_cpu_table(void *buf, unsigned long size, long offset) +{ + unsigned int *buf_pos = buf; + + /* No more data */ + if (offset >= size) + return 0; + + if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode equivalnet cpu table type field\n"); + return 0; + } + + if (size == 0) { + printk(KERN_ERR "microcode: error! " + "Wrong microcode equivalnet cpu table length\n"); + return 0; + } + + equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); + if (!equiv_cpu_table) { + printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n"); + return 0; + } + + memset(equiv_cpu_table, 0, size); + memcpy(equiv_cpu_table, &buf_pos[3], size); + + return size + 12; /* add header length */ +} + +/* fake device for request_firmware */ +extern struct platform_device *microcode_pdev; + +static int cpu_request_microcode_amd(int cpu) +{ + char name[30]; + const struct firmware *firmware; + void *buf; + unsigned int *buf_pos; + unsigned long size; + long offset = 0; + int error; + void *mc; + + /* We should bind the task to the CPU */ + BUG_ON(cpu != raw_smp_processor_id()); + + sprintf(name, "amd-ucode/microcode_amd.bin"); + error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin", + µcode_pdev->dev); + if (error) { + printk(KERN_ERR "microcode: ucode data file %s load failed\n", + name); + return error; + } + + buf_pos = buf = firmware->data; + size = firmware->size; + + if (buf_pos[0] != UCODE_MAGIC) { + printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n"); + return -EINVAL; + } + + offset = install_equiv_cpu_table(buf, buf_pos[2], offset); + + if (!offset) { + printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); + return -EINVAL; + } + + while ((offset = + get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) { + error = get_matching_microcode_amd(mc, cpu); + if (error < 0) + break; + /* + * It's possible the data file has multiple matching ucode, + * lets keep searching till the latest version + */ + if (error == 1) { + apply_microcode_amd(cpu); + error = 0; + } + vfree(mc); + } + if (offset > 0) { + vfree(mc); + vfree(equiv_cpu_table); + equiv_cpu_table = NULL; + } + if (offset < 0) + error = offset; + release_firmware(firmware); + + return error; +} + +static int apply_microcode_check_cpu_amd(int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + unsigned int rev; + cpumask_t old; + cpumask_of_cpu_ptr(newmask, cpu); + int err = 0; + + /* Check if the microcode is available */ + if (!uci->mc.mc_amd) + return 0; + + old = current->cpus_allowed; + set_cpus_allowed(current, newmask); + + /* Check if the microcode we have in memory matches the CPU */ + if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16) + err = -EINVAL; + + if (!err) { + asm volatile("movl %1, %%ecx; rdmsr" + : "=a" (rev) + : "i" (0x0000008B) : "ecx"); + + if (uci->rev != rev) + err = -EINVAL; + } + + if (!err) + apply_microcode_amd(cpu); + else + printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" + " rev=0x%x\n", + cpu, uci->rev); + + set_cpus_allowed(current, old); + return err; +} + +static void microcode_fini_cpu_amd(int cpu) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + + mutex_lock(µcode_mutex); + uci->valid = 0; + vfree(uci->mc.mc_amd); + uci->mc.mc_amd = NULL; + mutex_unlock(µcode_mutex); +} + +static struct microcode_ops microcode_amd_ops = { + .get_next_ucode = get_next_ucode_amd, + .get_matching_microcode = get_matching_microcode_amd, + .microcode_sanity_check = NULL, + .apply_microcode_check_cpu = apply_microcode_check_cpu_amd, + .cpu_request_microcode = cpu_request_microcode_amd, + .collect_cpu_info = collect_cpu_info_amd, + .apply_microcode = apply_microcode_amd, + .microcode_fini_cpu = microcode_fini_cpu_amd, +}; + +static int __init microcode_amd_module_init(void) +{ + struct cpuinfo_x86 *c = &cpu_data(get_cpu()); + + equiv_cpu_table = NULL; + if (c->x86_vendor == X86_VENDOR_AMD) + return microcode_init(µcode_amd_ops, THIS_MODULE); + else + return -ENODEV; +} + +static void __exit microcode_amd_module_exit(void) +{ + microcode_exit(); +} + +module_init(microcode_amd_module_init) +module_exit(microcode_amd_module_exit) -- GitLab From 45b1e23eca1c53fa79a611a2bc8c93697ede6c97 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 09:42:17 +0200 Subject: [PATCH 0178/5416] x86, microcode support: fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/microcode.c:412: error: static declaration of ‘microcode_init’ follows non-static declaration include/asm/microcode.h:1: error: previous declaration of ‘microcode_init’ was here arch/x86/kernel/microcode.c:454: error: static declaration of ‘microcode_exit’ follows non-static declaration include/asm/microcode.h:2: error: previous declaration of ‘microcode_exit’ was here Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 1e42e79ca69..9a881845b35 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -415,7 +415,7 @@ static struct notifier_block __refdata mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; -static int microcode_init(void *opaque, struct module *module) +int microcode_init(void *opaque, struct module *module) { struct microcode_ops *ops = (struct microcode_ops *)opaque; int error; @@ -457,7 +457,7 @@ static int microcode_init(void *opaque, struct module *module) } EXPORT_SYMBOL_GPL(microcode_init); -static void __exit microcode_exit (void) +void __exit microcode_exit (void) { microcode_dev_exit(); -- GitLab From 224e946b81166d732f3e9b414cb69612072fb500 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 09:52:55 +0200 Subject: [PATCH 0179/5416] x86, microcode: fix symbol exports fix tons of build errors: arch/x86/kernel/built-in.o: In function `microcode_fini_cpu': microcode_intel.c:(.text+0x11598): undefined reference to `microcode_mutex' microcode_intel.c:(.text+0x115a4): undefined reference to `ucode_cpu_info' microcode_intel.c:(.text+0x115ae): undefined reference to `ucode_cpu_info' microcode_intel.c:(.text+0x115bc): undefined reference to `microcode_mutex' [...] Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 9a881845b35..758b958a663 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -104,16 +104,16 @@ MODULE_LICENSE("GPL"); struct microcode_ops *microcode_ops; /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DEFINE_MUTEX(microcode_mutex); +DEFINE_MUTEX(microcode_mutex); EXPORT_SYMBOL_GPL(microcode_mutex); -static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE -static void __user *user_buffer; /* user area microcode data buffer */ +void __user *user_buffer; /* user area microcode data buffer */ EXPORT_SYMBOL_GPL(user_buffer); -static unsigned int user_buffer_size; /* it's size */ +unsigned int user_buffer_size; /* it's size */ EXPORT_SYMBOL_GPL(user_buffer_size); static int do_microcode_update (void) @@ -230,7 +230,7 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #endif /* fake device for request_firmware */ -static struct platform_device *microcode_pdev; +struct platform_device *microcode_pdev; EXPORT_SYMBOL_GPL(microcode_pdev); static void microcode_init_cpu(int cpu, int resume) -- GitLab From 5d7b605245b1aa1a9cd6549b1f57d69273eb0c37 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 29 Jul 2008 10:07:36 +0200 Subject: [PATCH 0180/5416] x86, microcode: fix module license string fix: FATAL: modpost: GPL-incompatible module microcode_amd.ko uses GPL-only symbol 'set_cpus_allowed_ptr' Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index db199e3fdd1..fd9e68e8889 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -40,7 +40,7 @@ MODULE_DESCRIPTION("AMD Microcode Update Driver"); MODULE_AUTHOR("Peter Oruba "); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); #define UCODE_MAGIC 0x00414d44 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 -- GitLab From e76d8ceaaff9d7fc1ba2b1963a9f34151832223b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Jul 2008 19:05:35 +0100 Subject: [PATCH 0181/5416] ALSA: Add jack reporting API Currently very few systems provide information about jack status to user space, even though many have hardware facilities to do detection. Those systems that do use an input device with the existing SW_HEADPHONE_INSERT switch type to do so, often independently of ALSA. This patch introduces a standard method for representing jacks to user space into ALSA. It allows drivers to register jacks for a sound card with the input subsystem, binding the input device to the card to help user space associate the input devices with their sound cards. The created input devices are named in the form "card longname jack" where jack is provided by the driver when allocating a jack. By default the parent for the input device is the sound card but this can be overridden by the card driver. The existing user space API with SW_HEADPHONE_INSERT is preserved. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/core.h | 1 + include/sound/jack.h | 75 ++++++++++++++++++++ sound/core/jack.c | 163 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 include/sound/jack.h create mode 100644 sound/core/jack.c diff --git a/include/sound/core.h b/include/sound/core.h index 558b96284bd..1a4ff0bdcf6 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -63,6 +63,7 @@ typedef int __bitwise snd_device_type_t; #define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006) #define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007) #define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008) +#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009) #define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000) typedef int __bitwise snd_device_state_t; diff --git a/include/sound/jack.h b/include/sound/jack.h new file mode 100644 index 00000000000..b1b2b8b59ad --- /dev/null +++ b/include/sound/jack.h @@ -0,0 +1,75 @@ +#ifndef __SOUND_JACK_H +#define __SOUND_JACK_H + +/* + * Jack abstraction layer + * + * Copyright 2008 Wolfson Microelectronics plc + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the 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 + +struct input_dev; + +/** + * Jack types which can be reported. These values are used as a + * bitmask. + */ +enum snd_jack_types { + SND_JACK_HEADPHONE = 0x0001, + SND_JACK_MICROPHONE = 0x0002, + SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, +}; + +struct snd_jack { + struct input_dev *input_dev; + int registered; + int type; + const char *id; + char name[100]; +}; + +#ifdef CONFIG_SND_JACK + +int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jack); +void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); + +void snd_jack_report(struct snd_jack *jack, int status); + +#else + +static inline int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jack) +{ + return 0; +} + +static inline void snd_jack_set_parent(struct snd_jack *jack, + struct device *parent) +{ +} + +static inline void snd_jack_report(struct snd_jack *jack, int status) +{ +} + +#endif + +#endif diff --git a/sound/core/jack.c b/sound/core/jack.c new file mode 100644 index 00000000000..8133a2b173a --- /dev/null +++ b/sound/core/jack.c @@ -0,0 +1,163 @@ +/* + * Jack abstraction layer + * + * Copyright 2008 Wolfson Microelectronics + * + * 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 + +static int snd_jack_dev_free(struct snd_device *device) +{ + struct snd_jack *jack = device->device_data; + + /* If the input device is registered with the input subsystem + * then we need to use a different deallocator. */ + if (jack->registered) + input_unregister_device(jack->input_dev); + else + input_free_device(jack->input_dev); + + kfree(jack); + + return 0; +} + +static int snd_jack_dev_register(struct snd_device *device) +{ + struct snd_jack *jack = device->device_data; + struct snd_card *card = device->card; + int err; + + snprintf(jack->name, sizeof(jack->name), "%s %s", + card->longname, jack->id); + jack->input_dev->name = jack->name; + + /* Default to the sound card device. */ + if (!jack->input_dev->dev.parent) + jack->input_dev->dev.parent = card->dev; + + err = input_register_device(jack->input_dev); + if (err == 0) + jack->registered = 1; + + return err; +} + +/** + * snd_jack_new - Create a new jack + * @card: the card instance + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jjack: Used to provide the allocated jack object to the caller. + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jjack will be initialised. + */ +int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jjack) +{ + struct snd_jack *jack; + int err; + static struct snd_device_ops ops = { + .dev_free = snd_jack_dev_free, + .dev_register = snd_jack_dev_register, + }; + + jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL); + if (jack == NULL) + return -ENOMEM; + + jack->id = id; + + jack->input_dev = input_allocate_device(); + if (jack->input_dev == NULL) { + err = -ENOMEM; + goto fail_input; + } + + jack->input_dev->phys = "ALSA"; + + jack->type = type; + + if (type & SND_JACK_HEADPHONE) + input_set_capability(jack->input_dev, EV_SW, + SW_HEADPHONE_INSERT); + if (type & SND_JACK_MICROPHONE) + input_set_capability(jack->input_dev, EV_SW, + SW_MICROPHONE_INSERT); + + err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); + if (err < 0) + goto fail_input; + + *jjack = jack; + + return 0; + +fail_input: + input_free_device(jack->input_dev); + kfree(jack); + return err; +} +EXPORT_SYMBOL(snd_jack_new); + +/** + * snd_jack_set_parent - Set the parent device for a jack + * + * @jack: The jack to configure + * @parent: The device to set as parent for the jack. + * + * Set the parent for the jack input device in the device tree. This + * function is only valid prior to registration of the jack. If no + * parent is configured then the parent device will be the sound card. + */ +void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) +{ + WARN_ON(jack->registered); + + jack->input_dev->dev.parent = parent; +} +EXPORT_SYMBOL(snd_jack_set_parent); + +/** + * snd_jack_report - Report the current status of a jack + * + * @jack: The jack to report status for + * @status: The current status of the jack + */ +void snd_jack_report(struct snd_jack *jack, int status) +{ + if (jack->type & SND_JACK_HEADPHONE) + input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, + status & SND_JACK_HEADPHONE); + if (jack->type & SND_JACK_MICROPHONE) + input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, + status & SND_JACK_MICROPHONE); + + input_sync(jack->input_dev); +} +EXPORT_SYMBOL(snd_jack_report); + +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("Jack detection support for ALSA"); +MODULE_LICENSE("GPL"); -- GitLab From 0d94e41abe271c86df06bcf72d24f9ca7ce771f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Jul 2008 19:05:36 +0100 Subject: [PATCH 0182/5416] ALSA: Build jack detection Since jack detection requires the input subsystem which may not be desired on small systems it is not built unless required by a driver that is being built. Drivers using jack detection should use a pattern like this: config SND_FOO tristate "..." ... select SND_JACK if INPUT=y || INPUT=SND to ensure that the jack detection API is enabled if the input subsystem is. If the input subsystem is not enabled then a stub version of the API is provided. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/Kconfig | 6 ++++++ sound/core/Makefile | 1 + 2 files changed, 7 insertions(+) diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 335d45ecde6..9c4da1cd4a6 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -12,6 +12,12 @@ config SND_HWDEP config SND_RAWMIDI tristate +# To be effective this also requires INPUT - users should say: +# select SND_JACK if INPUT=y || INPUT=SND +# to avoid having to force INPUT on. +config SND_JACK + bool + config SND_SEQUENCER tristate "Sequencer support" select SND_TIMER diff --git a/sound/core/Makefile b/sound/core/Makefile index da8e685eef9..d57125a5687 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -7,6 +7,7 @@ snd-y := sound.o init.o memory.o info.o control.o misc.o device.o snd-$(CONFIG_ISA_DMA_API) += isadma.o snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o snd-$(CONFIG_SND_VMASTER) += vmaster.o +snd-$(CONFIG_SND_JACK) += jack.o snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ pcm_memory.o -- GitLab From f6154d6d007c69a330acc9021ec77cca5da9dc4c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Jul 2008 12:08:16 +0200 Subject: [PATCH 0183/5416] ALSA: hda - use input_free_device() Use input_free_devce() correctly instead of kfree() at error path. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_beep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 5a764c48139..9b77b3e0fa9 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -103,7 +103,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) err = input_register_device(input_dev); if (err < 0) { - kfree(input_dev); + input_free_device(input_dev); kfree(beep); return err; } -- GitLab From 8a33de9e51673dbdadb552d888a4544aefe0c31d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 29 Jul 2008 11:42:24 +0100 Subject: [PATCH 0184/5416] ALSA: ASoC: Permit simultaneous compilation of both PXA AC97 drivers Signed-off-by: Dmitry Baryshkov Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/pxa/pxa2xx-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 4345f387fe4..771c592b042 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -330,7 +330,7 @@ static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK; -int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; @@ -360,7 +360,7 @@ int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_soc_platform pxa2xx_soc_platform = { .name = "pxa2xx-audio", .pcm_ops = &pxa2xx_pcm_ops, - .pcm_new = pxa2xx_pcm_new, + .pcm_new = pxa2xx_soc_pcm_new, .pcm_free = pxa2xx_pcm_free_dma_buffers, }; EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); -- GitLab From 58cd33c0f375578cfda25a52ed280caa888b6254 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Jul 2008 11:42:25 +0100 Subject: [PATCH 0185/5416] ALSA: ASoC: Allow codecs to override register display Some codecs have unusual features in their register maps such as very large registers representing arrays of coefficients. Support these codecs in the register cache sysfs file by allowing them to provide a function register_display() overriding the default output for register contents. Also ensure that we don't overflow PAGE_SIZE while writing out the register dump. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 1890d87c520..2ce530efcf1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -410,6 +410,8 @@ struct snd_soc_codec { void *control_data; /* codec control (i2c/3wire) data */ unsigned int (*read)(struct snd_soc_codec *, unsigned int); int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); + int (*display_register)(struct snd_soc_codec *, char *, + size_t, unsigned int); hw_write_t hw_write; hw_read_t hw_read; void *reg_cache; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 83f1190293a..5d3bf731a4b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -970,9 +970,29 @@ static ssize_t codec_reg_show(struct device *dev, step = codec->reg_cache_step; count += sprintf(buf, "%s registers\n", codec->name); - for (i = 0; i < codec->reg_cache_size; i += step) - count += sprintf(buf + count, "%2x: %4x\n", i, - codec->read(codec, i)); + for (i = 0; i < codec->reg_cache_size; i += step) { + count += sprintf(buf + count, "%2x: ", i); + if (count >= PAGE_SIZE - 1) + break; + + if (codec->display_register) + count += codec->display_register(codec, buf + count, + PAGE_SIZE - count, i); + else + count += snprintf(buf + count, PAGE_SIZE - count, + "%4x", codec->read(codec, i)); + + if (count >= PAGE_SIZE - 1) + break; + + count += snprintf(buf + count, PAGE_SIZE - count, "\n"); + if (count >= PAGE_SIZE - 1) + break; + } + + /* Truncate count; min() would cause a warning */ + if (count >= PAGE_SIZE) + count = PAGE_SIZE - 1; return count; } -- GitLab From 4eaa9819dc08d7bfd1065ce530e31b18a119dcaf Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Tue, 29 Jul 2008 11:42:26 +0100 Subject: [PATCH 0186/5416] ALSA: ASoC: Convert bitfields in ASoC into full int width Convert bitfields in ASoC into full int width. This is a simple mechanical conversion. Two places in the DAPM code were fixed to properly use mask. Signed-off-by: Jon Smirl Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 50 ++++++++++++++++---------- sound/soc/soc-core.c | 86 ++++++++++++++++++++++++++------------------ sound/soc/soc-dapm.c | 52 ++++++++++++++++----------- 3 files changed, 114 insertions(+), 74 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 2ce530efcf1..e647a34c809 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -26,10 +26,12 @@ /* * Convenience kcontrol builders */ -#define SOC_SINGLE_VALUE(reg, shift, max, invert) ((reg) | ((shift) << 8) |\ - ((shift) << 12) | ((max) << 16) | ((invert) << 24)) -#define SOC_SINGLE_VALUE_EXT(reg, max, invert) ((reg) | ((max) << 16) |\ - ((invert) << 31)) +#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = xshift, .max = xmax, .invert = xinvert}) +#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .max = xmax, .invert = xinvert}) #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ @@ -43,45 +45,49 @@ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } -#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ +#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ - .private_value = (reg) | ((shift_left) << 8) | \ - ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) } -#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, max, invert) \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ + .max = xmax, .invert = xinvert} } +#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ - .private_value = (reg_left) | ((shift) << 8) | \ - ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) } -#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ + .max = xmax, .invert = xinvert} } +#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ - .private_value = (reg) | ((shift_left) << 8) | \ - ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) } -#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ + .max = xmax, .invert = xinvert} } +#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ - .private_value = (reg_left) | ((shift) << 8) | \ - ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) } -#define SOC_DOUBLE_S8_TLV(xname, reg, min, max, tlv_array) \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ + .max = xmax, .invert = xinvert} } +#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_READWRITE, \ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \ .put = snd_soc_put_volsw_s8, \ - .private_value = (reg) | (((signed char)max) << 16) | \ - (((signed char)min) << 24) } + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .min = xmin, .max = xmax} } #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ .mask = xmask, .texts = xtexts } @@ -518,6 +524,12 @@ struct snd_soc_pcm_runtime { struct snd_soc_device *socdev; }; +/* mixer control */ +struct soc_mixer_control { + int min, max; + uint reg, rreg, shift, rshift, invert; +}; + /* enumerated kcontrol */ struct soc_enum { unsigned short reg; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5d3bf731a4b..4b94f1f6ee2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1454,9 +1454,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int max = (kcontrol->private_value >> 16) & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; + uint shift = mc->min; + uint rshift = mc->rshift; if (max == 1) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; @@ -1482,13 +1484,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw); int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int max = (kcontrol->private_value >> 16) & 0xff; - int mask = (1 << fls(max)) - 1; - int invert = (kcontrol->private_value >> 24) & 0x01; + uint reg = mc->reg; + uint shift = mc->shift; + uint rshift = mc->rshift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; ucontrol->value.integer.value[0] = (snd_soc_read(codec, reg) >> shift) & mask; @@ -1519,13 +1523,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int max = (kcontrol->private_value >> 16) & 0xff; - int mask = (1 << fls(max)) - 1; - int invert = (kcontrol->private_value >> 24) & 0x01; + uint reg = mc->reg; + uint shift = mc->shift; + uint rshift = mc->rshift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); @@ -1557,7 +1563,9 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int max = (kcontrol->private_value >> 12) & 0xff; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; if (max == 1) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; @@ -1583,13 +1591,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 24) & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int max = (kcontrol->private_value >> 12) & 0xff; - int mask = (1<private_value >> 20) & 0x01; + uint reg = mc->reg; + uint reg2 = mc->rreg; + uint shift = mc->shift; + int max = mc->max; + uint mask = (1<invert; ucontrol->value.integer.value[0] = (snd_soc_read(codec, reg) >> shift) & mask; @@ -1618,13 +1628,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r); int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 24) & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int max = (kcontrol->private_value >> 12) & 0xff; - int mask = (1 << fls(max)) - 1; - int invert = (kcontrol->private_value >> 20) & 0x01; + uint reg = mc->reg; + uint reg2 = mc->rreg; + uint shift = mc->shift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; int err; unsigned short val, val2, val_mask; @@ -1661,8 +1673,10 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int max = (signed char)((kcontrol->private_value >> 16) & 0xff); - int min = (signed char)((kcontrol->private_value >> 24) & 0xff); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; + int min = mc->min; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; @@ -1684,9 +1698,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int min = (signed char)((kcontrol->private_value >> 24) & 0xff); + uint reg = mc->reg; + int min = mc->min; int val = snd_soc_read(codec, reg); ucontrol->value.integer.value[0] = @@ -1709,9 +1725,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8); int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int min = (signed char)((kcontrol->private_value >> 24) & 0xff); + uint reg = mc->reg; + int min = mc->min; unsigned short val; val = (ucontrol->value.integer.value[0]+min) & 0xff; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f9d100bc847..bbdca0dacba 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -104,10 +104,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_switch: case snd_soc_dapm_mixer: { int val; - int reg = w->kcontrols[i].private_value & 0xff; - int shift = (w->kcontrols[i].private_value >> 8) & 0x0f; - int mask = (w->kcontrols[i].private_value >> 16) & 0xff; - int invert = (w->kcontrols[i].private_value >> 24) & 0x01; + struct soc_mixer_control *mc = (struct soc_mixer_control *) + w->kcontrols[i].private_value; + uint reg = mc->reg; + uint shift = mc->shift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; val = snd_soc_read(w->codec, reg); val = (val >> shift) & mask; @@ -247,16 +250,19 @@ static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power) return 0; if (widget->num_kcontrols && k) { - int reg = k->private_value & 0xff; - int shift = (k->private_value >> 8) & 0x0f; - int mask = (k->private_value >> 16) & 0xff; - int invert = (k->private_value >> 24) & 0x01; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)k->private_value; + uint reg = mc->reg; + uint shift = mc->shift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; if (power) { int i; /* power up has happended, increase volume to last level */ if (invert) { - for (i = mask; i > widget->saved_value; i--) + for (i = max; i > widget->saved_value; i--) snd_soc_update_bits(widget->codec, reg, mask, i); } else { for (i = 0; i < widget->saved_value; i++) @@ -1133,12 +1139,14 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int max = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0x01; - int mask = (1 << fls(max)) - 1; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + uint reg = mc->reg; + uint shift = mc->shift; + uint rshift = mc->rshift; + int max = mc->max; + uint invert = mc->invert; + uint mask = (1 << fls(max)) - 1; /* return the saved value if we are powered down */ if (widget->id == snd_soc_dapm_pga && !widget->power) { @@ -1176,12 +1184,14 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int max = (kcontrol->private_value >> 16) & 0xff; - int mask = (1 << fls(max)) - 1; - int invert = (kcontrol->private_value >> 24) & 0x01; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + uint reg = mc->reg; + uint shift = mc->shift; + uint rshift = mc->rshift; + int max = mc->max; + uint mask = (1 << fls(max)) - 1; + uint invert = mc->invert; unsigned short val, val2, val_mask; int ret; -- GitLab From f8ba0b7bfd06a2a5b3c49ff8d71cad31f57b0d51 Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Tue, 29 Jul 2008 11:42:27 +0100 Subject: [PATCH 0187/5416] ALSA: ASoC: Rename mask to max to reflect usage Most of the ASoC controls refer to the maximum value that can be set for a control as mask but there is no actual requirement for all bits to be set at the highest possible value making the name mask misleading. Change the code to use max instead. Signed-off-by: Jon Smirl Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 22 +++++++++++----------- sound/soc/soc-core.c | 20 ++++++++++---------- sound/soc/soc-dapm.c | 14 +++++++------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index e647a34c809..5ca231f080a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -88,25 +88,25 @@ .put = snd_soc_put_volsw_s8, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .min = xmin, .max = xmax} } -#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ +#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .texts = xtexts } -#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \ - SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts) -#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \ -{ .mask = xmask, .texts = xtexts } + .max = xmax, .texts = xtexts } +#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ + SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) +#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ +{ .max = xmax, .texts = xtexts } #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ .private_value = (unsigned long)&xenum } -#define SOC_SINGLE_EXT(xname, xreg, xshift, xmask, xinvert,\ +#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) } -#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmask, xinvert,\ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } +#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -114,7 +114,7 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \ @@ -536,7 +536,7 @@ struct soc_enum { unsigned short reg2; unsigned char shift_l; unsigned char shift_r; - unsigned int mask; + unsigned int max; const char **texts; void *dapm; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4b94f1f6ee2..11a881caba7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1316,10 +1316,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = e->shift_l == e->shift_r ? 1 : 2; - uinfo->value.enumerated.items = e->mask; + uinfo->value.enumerated.items = e->max; - if (uinfo->value.enumerated.item > e->mask - 1) - uinfo->value.enumerated.item = e->mask - 1; + if (uinfo->value.enumerated.item > e->max - 1) + uinfo->value.enumerated.item = e->max - 1; strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]); return 0; @@ -1342,7 +1342,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned short val, bitmask; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) + for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; val = snd_soc_read(codec, e->reg); ucontrol->value.enumerated.item[0] @@ -1372,14 +1372,14 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, unsigned short val; unsigned short mask, bitmask; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) + for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; - if (ucontrol->value.enumerated.item[0] > e->mask - 1) + if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; mask = (bitmask - 1) << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->mask - 1) + if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= (bitmask - 1) << e->shift_r; @@ -1406,10 +1406,10 @@ int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; - uinfo->value.enumerated.items = e->mask; + uinfo->value.enumerated.items = e->max; - if (uinfo->value.enumerated.item > e->mask - 1) - uinfo->value.enumerated.item = e->mask - 1; + if (uinfo->value.enumerated.item > e->max - 1) + uinfo->value.enumerated.item = e->max - 1; strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]); return 0; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bbdca0dacba..f08be8a329e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -125,13 +125,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; int val, item, bitmask; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) + for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; val = snd_soc_read(w->codec, e->reg); item = (val >> e->shift_l) & (bitmask - 1); p->connect = 0; - for (i = 0; i < e->mask; i++) { + for (i = 0; i < e->max; i++) { if (!(strcmp(p->name, e->texts[i])) && item == i) p->connect = 1; } @@ -168,7 +168,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int i; - for (i = 0; i < e->mask; i++) { + for (i = 0; i < e->max; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &codec->dapm_paths); list_add(&path->list_sink, &dest->sources); @@ -1258,7 +1258,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned short val, bitmask; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) + for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; val = snd_soc_read(widget->codec, e->reg); ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); @@ -1288,15 +1288,15 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, unsigned short mask, bitmask; int ret = 0; - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) + for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; - if (ucontrol->value.enumerated.item[0] > e->mask - 1) + if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = mux << e->shift_l; mask = (bitmask - 1) << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->mask - 1) + if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= (bitmask - 1) << e->shift_r; -- GitLab From 84bc278b1f04920e867e4b46e094bcc066393d41 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 29 Jul 2008 11:42:28 +0100 Subject: [PATCH 0188/5416] ALSA: ASoC: Add OpenFirmware helper for matching bus and codec drivers Simple utility layer for creating ASoC machine instances based on data in the OpenFirmware device tree. OF aware platform drivers and codec drivers register themselves with this framework and the framework automatically instantiates a machine driver. At the moment, the driver is not very capable and it is expected to be extended as more features are needed for specifying the configuration in the device tree. This is most likely temporary glue code to work around limitations in the ASoC v1 framework. When v2 is merged, most of this driver will need to be reworked. Signed-off-by: Grant Likely Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc-of-simple.h | 21 +++++ sound/soc/fsl/Kconfig | 3 + sound/soc/fsl/Makefile | 3 + sound/soc/fsl/soc-of-simple.c | 171 ++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 include/sound/soc-of-simple.h create mode 100644 sound/soc/fsl/soc-of-simple.c diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h new file mode 100644 index 00000000000..696fc513e23 --- /dev/null +++ b/include/sound/soc-of-simple.h @@ -0,0 +1,21 @@ +/* + * OF helpers for ALSA SoC + * + * Copyright (C) 2008, Secret Lab Technologies Ltd. + */ + +#ifndef _INCLUDE_SOC_OF_H_ +#define _INCLUDE_SOC_OF_H_ + +#include +#include + +int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, + void *codec_data, struct snd_soc_dai *dai, + struct device_node *node); + +int of_snd_soc_register_platform(struct snd_soc_platform *platform, + struct device_node *node, + struct snd_soc_dai *cpu_dai); + +#endif /* _INCLUDE_SOC_OF_H_ */ diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3368ace6097..398f0020867 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,3 +1,6 @@ +config SND_SOC_OF_SIMPLE + tristate + config SND_SOC_MPC8610 bool "ALSA SoC support for the MPC8610 SOC" depends on MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 62f680a4a77..aa2100b4114 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -1,3 +1,6 @@ +# Simple machine driver that extracts configuration from the OF device tree +obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o + # MPC8610 HPCD Machine Support obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c new file mode 100644 index 00000000000..0382fdac51c --- /dev/null +++ b/sound/soc/fsl/soc-of-simple.c @@ -0,0 +1,171 @@ +/* + * OF helpers for ALSA SoC Layer + * + * Copyright (C) 2008, Secret Lab Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings"); + +static DEFINE_MUTEX(of_snd_soc_mutex); +static LIST_HEAD(of_snd_soc_device_list); +static int of_snd_soc_next_index; + +struct of_snd_soc_device { + int id; + struct list_head list; + struct snd_soc_device device; + struct snd_soc_machine machine; + struct snd_soc_dai_link dai_link; + struct platform_device *pdev; + struct device_node *platform_node; + struct device_node *codec_node; +}; + +static struct snd_soc_ops of_snd_soc_ops = { +}; + +static struct of_snd_soc_device * +of_snd_soc_get_device(struct device_node *codec_node) +{ + struct of_snd_soc_device *of_soc; + + list_for_each_entry(of_soc, &of_snd_soc_device_list, list) { + if (of_soc->codec_node == codec_node) + return of_soc; + } + + of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL); + if (!of_soc) + return NULL; + + /* Initialize the structure and add it to the global list */ + of_soc->codec_node = codec_node; + of_soc->id = of_snd_soc_next_index++; + of_soc->machine.dai_link = &of_soc->dai_link; + of_soc->machine.num_links = 1; + of_soc->device.machine = &of_soc->machine; + of_soc->dai_link.ops = &of_snd_soc_ops; + list_add(&of_soc->list, &of_snd_soc_device_list); + + return of_soc; +} + +static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc) +{ + struct platform_device *pdev; + int rc; + + /* Only register the device if both the codec and platform have + * been registered */ + if ((!of_soc->device.codec_data) || (!of_soc->platform_node)) + return; + + pr_info("platform<-->codec match achieved; registering machine\n"); + + pdev = platform_device_alloc("soc-audio", of_soc->id); + if (!pdev) { + pr_err("of_soc: platform_device_alloc() failed\n"); + return; + } + + pdev->dev.platform_data = of_soc; + platform_set_drvdata(pdev, &of_soc->device); + of_soc->device.dev = &pdev->dev; + + /* The ASoC device is complete; register it */ + rc = platform_device_add(pdev); + if (rc) { + pr_err("of_soc: platform_device_add() failed\n"); + return; + } + +} + +int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, + void *codec_data, struct snd_soc_dai *dai, + struct device_node *node) +{ + struct of_snd_soc_device *of_soc; + int rc = 0; + + pr_info("registering ASoC codec driver: %s\n", node->full_name); + + mutex_lock(&of_snd_soc_mutex); + of_soc = of_snd_soc_get_device(node); + if (!of_soc) { + rc = -ENOMEM; + goto out; + } + + /* Store the codec data */ + of_soc->device.codec_data = codec_data; + of_soc->device.codec_dev = codec_dev; + of_soc->dai_link.name = (char *)node->name; + of_soc->dai_link.stream_name = (char *)node->name; + of_soc->dai_link.codec_dai = dai; + + /* Now try to register the SoC device */ + of_snd_soc_register_device(of_soc); + + out: + mutex_unlock(&of_snd_soc_mutex); + return rc; +} +EXPORT_SYMBOL_GPL(of_snd_soc_register_codec); + +int of_snd_soc_register_platform(struct snd_soc_platform *platform, + struct device_node *node, + struct snd_soc_dai *cpu_dai) +{ + struct of_snd_soc_device *of_soc; + struct device_node *codec_node; + const phandle *handle; + int len, rc = 0; + + pr_info("registering ASoC platform driver: %s\n", node->full_name); + + handle = of_get_property(node, "codec-handle", &len); + if (!handle || len < sizeof(handle)) + return -ENODEV; + codec_node = of_find_node_by_phandle(*handle); + if (!codec_node) + return -ENODEV; + pr_info("looking for codec: %s\n", codec_node->full_name); + + mutex_lock(&of_snd_soc_mutex); + of_soc = of_snd_soc_get_device(codec_node); + if (!of_soc) { + rc = -ENOMEM; + goto out; + } + + of_soc->platform_node = node; + of_soc->dai_link.cpu_dai = cpu_dai; + of_soc->device.platform = platform; + of_soc->machine.name = of_soc->dai_link.cpu_dai->name; + + /* Now try to register the SoC device */ + of_snd_soc_register_device(of_soc); + + out: + mutex_unlock(&of_snd_soc_mutex); + return rc; +} +EXPORT_SYMBOL_GPL(of_snd_soc_register_platform); -- GitLab From b78ddb10704a7f930e5e631de8227c78a6676a1b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Jul 2008 11:42:29 +0100 Subject: [PATCH 0189/5416] ALSA: ASoC: Make OpenFirmware helper include file conditional The OpenFirmware API headers don't build on all platforms so ensure that they are not included unless they are being used. Signed-off-by: Mark Brown Acked-by: Grant Likely Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc-of-simple.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h index 696fc513e23..a064e1934a5 100644 --- a/include/sound/soc-of-simple.h +++ b/include/sound/soc-of-simple.h @@ -7,6 +7,8 @@ #ifndef _INCLUDE_SOC_OF_H_ #define _INCLUDE_SOC_OF_H_ +#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE) + #include #include @@ -18,4 +20,6 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform, struct device_node *node, struct snd_soc_dai *cpu_dai); +#endif + #endif /* _INCLUDE_SOC_OF_H_ */ -- GitLab From dc641378b5ee220aa29ed8b8f51b7af9a19a7719 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 29 Jul 2008 11:42:30 +0100 Subject: [PATCH 0190/5416] ALSA: ASoC: Add mpc5200-psc I2S driver This is an I2S bus driver for the MPC5200 PSC device. It depends on the soc-of helper functions to match a PSC device with a codec based on data in the device tree. Signed-off-by: Grant Likely Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/Kconfig | 7 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/mpc5200_psc_i2s.c | 884 ++++++++++++++++++++++++++++++++ 3 files changed, 893 insertions(+) create mode 100644 sound/soc/fsl/mpc5200_psc_i2s.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 398f0020867..bba9546ba5f 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -17,3 +17,10 @@ config SND_SOC_MPC8610_HPCD default y if MPC8610_HPCD help Say Y if you want to enable audio on the Freescale MPC8610 HPCD. + +config SND_SOC_MPC5200_I2S + tristate "Freescale MPC5200 PSC in I2S mode driver" + select SND_SOC_OF_SIMPLE + depends on SND_SOC && PPC_MPC52xx + help + Say Y here to support the MPC5200 PSCs in I2S mode. diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index aa2100b4114..035da4afec3 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o # MPC8610 Platform Support obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o +obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o + diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c new file mode 100644 index 00000000000..86923299bc1 --- /dev/null +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -0,0 +1,884 @@ +/* + * Freescale MPC5200 PSC in I2S mode + * ALSA SoC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2008 Secret Lab Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver"); +MODULE_LICENSE("GPL"); + +/** + * PSC_I2S_RATES: sample rates supported by the I2S + * + * This driver currently only supports the PSC running in I2S slave mode, + * which means the codec determines the sample rate. Therefore, we tell + * ALSA that we support all rates and let the codec driver decide what rates + * are really supported. + */ +#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ + SNDRV_PCM_RATE_CONTINUOUS) + +/** + * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode + */ +#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \ + SNDRV_PCM_FMTBIT_S32_BE) + +/** + * psc_i2s_stream - Data specific to a single stream (playback or capture) + * @active: flag indicating if the stream is active + * @psc_i2s: pointer back to parent psc_i2s data structure + * @bcom_task: bestcomm task structure + * @irq: irq number for bestcomm task + * @period_start: physical address of start of DMA region + * @period_end: physical address of end of DMA region + * @period_next_pt: physical address of next DMA buffer to enqueue + * @period_bytes: size of DMA period in bytes + */ +struct psc_i2s_stream { + int active; + struct psc_i2s *psc_i2s; + struct bcom_task *bcom_task; + int irq; + struct snd_pcm_substream *stream; + dma_addr_t period_start; + dma_addr_t period_end; + dma_addr_t period_next_pt; + dma_addr_t period_current_pt; + int period_bytes; +}; + +/** + * psc_i2s - Private driver data + * @name: short name for this device ("PSC0", "PSC1", etc) + * @psc_regs: pointer to the PSC's registers + * @fifo_regs: pointer to the PSC's FIFO registers + * @irq: IRQ of this PSC + * @dev: struct device pointer + * @dai: the CPU DAI for this device + * @sicr: Base value used in serial interface control register; mode is ORed + * with this value. + * @playback: Playback stream context data + * @capture: Capture stream context data + */ +struct psc_i2s { + char name[32]; + struct mpc52xx_psc __iomem *psc_regs; + struct mpc52xx_psc_fifo __iomem *fifo_regs; + unsigned int irq; + struct device *dev; + struct snd_soc_dai dai; + spinlock_t lock; + u32 sicr; + + /* per-stream data */ + struct psc_i2s_stream playback; + struct psc_i2s_stream capture; + + /* Statistics */ + struct { + int overrun_count; + int underrun_count; + } stats; +}; + +/* + * Interrupt handlers + */ +static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s) +{ + struct psc_i2s *psc_i2s = _psc_i2s; + struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs; + u16 isr; + + isr = in_be16(®s->mpc52xx_psc_isr); + + /* Playback underrun error */ + if (psc_i2s->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP)) + psc_i2s->stats.underrun_count++; + + /* Capture overrun error */ + if (psc_i2s->capture.active && (isr & MPC52xx_PSC_IMR_ORERR)) + psc_i2s->stats.overrun_count++; + + out_8(®s->command, 4 << 4); /* reset the error status */ + + return IRQ_HANDLED; +} + +/** + * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer + * @s: pointer to stream private data structure + * + * Enqueues another audio period buffer into the bestcomm queue. + * + * Note: The routine must only be called when there is space available in + * the queue. Otherwise the enqueue will fail and the audio ring buffer + * will get out of sync + */ +static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s) +{ + struct bcom_bd *bd; + + /* Prepare and enqueue the next buffer descriptor */ + bd = bcom_prepare_next_buffer(s->bcom_task); + bd->status = s->period_bytes; + bd->data[0] = s->period_next_pt; + bcom_submit_next_buffer(s->bcom_task, NULL); + + /* Update for next period */ + s->period_next_pt += s->period_bytes; + if (s->period_next_pt >= s->period_end) + s->period_next_pt = s->period_start; +} + +/* Bestcomm DMA irq handler */ +static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream) +{ + struct psc_i2s_stream *s = _psc_i2s_stream; + + /* For each finished period, dequeue the completed period buffer + * and enqueue a new one in it's place. */ + while (bcom_buffer_done(s->bcom_task)) { + bcom_retrieve_buffer(s->bcom_task, NULL, NULL); + s->period_current_pt += s->period_bytes; + if (s->period_current_pt >= s->period_end) + s->period_current_pt = s->period_start; + psc_i2s_bcom_enqueue_next_buffer(s); + bcom_enable(s->bcom_task); + } + + /* If the stream is active, then also inform the PCM middle layer + * of the period finished event. */ + if (s->active) + snd_pcm_period_elapsed(s->stream); + + return IRQ_HANDLED; +} + +/** + * psc_i2s_startup: create a new substream + * + * This is the first function called when a stream is opened. + * + * If this is the first stream open, then grab the IRQ and program most of + * the PSC registers. + */ +static int psc_i2s_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + int rc; + + dev_dbg(psc_i2s->dev, "psc_i2s_startup(substream=%p)\n", substream); + + if (!psc_i2s->playback.active && + !psc_i2s->capture.active) { + /* Setup the IRQs */ + rc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED, + "psc-i2s-status", psc_i2s); + rc |= request_irq(psc_i2s->capture.irq, + &psc_i2s_bcom_irq, IRQF_SHARED, + "psc-i2s-capture", &psc_i2s->capture); + rc |= request_irq(psc_i2s->playback.irq, + &psc_i2s_bcom_irq, IRQF_SHARED, + "psc-i2s-playback", &psc_i2s->playback); + if (rc) { + free_irq(psc_i2s->irq, psc_i2s); + free_irq(psc_i2s->capture.irq, + &psc_i2s->capture); + free_irq(psc_i2s->playback.irq, + &psc_i2s->playback); + return -ENODEV; + } + } + + return 0; +} + +static int psc_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + u32 mode; + + dev_dbg(psc_i2s->dev, "%s(substream=%p) p_size=%i p_bytes=%i" + " periods=%i buffer_size=%i buffer_bytes=%i\n", + __func__, substream, params_period_size(params), + params_period_bytes(params), params_periods(params), + params_buffer_size(params), params_buffer_bytes(params)); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + mode = MPC52xx_PSC_SICR_SIM_CODEC_8; + break; + case SNDRV_PCM_FORMAT_S16_BE: + mode = MPC52xx_PSC_SICR_SIM_CODEC_16; + break; + case SNDRV_PCM_FORMAT_S24_BE: + mode = MPC52xx_PSC_SICR_SIM_CODEC_24; + break; + case SNDRV_PCM_FORMAT_S32_BE: + mode = MPC52xx_PSC_SICR_SIM_CODEC_32; + break; + default: + dev_dbg(psc_i2s->dev, "invalid format\n"); + return -EINVAL; + } + out_be32(&psc_i2s->psc_regs->sicr, psc_i2s->sicr | mode); + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} + +static int psc_i2s_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +/** + * psc_i2s_trigger: start and stop the DMA transfer. + * + * This function is called by ALSA to start, stop, pause, and resume the DMA + * transfer of data. + */ +static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct psc_i2s_stream *s; + struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs; + u16 imr; + u8 psc_cmd; + long flags; + + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) + s = &psc_i2s->capture; + else + s = &psc_i2s->playback; + + dev_dbg(psc_i2s->dev, "psc_i2s_trigger(substream=%p, cmd=%i)" + " stream_id=%i\n", + substream, cmd, substream->pstr->stream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + s->period_bytes = frames_to_bytes(runtime, + runtime->period_size); + s->period_start = virt_to_phys(runtime->dma_area); + s->period_end = s->period_start + + (s->period_bytes * runtime->periods); + s->period_next_pt = s->period_start; + s->period_current_pt = s->period_start; + s->active = 1; + + /* First; reset everything */ + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { + out_8(®s->command, MPC52xx_PSC_RST_RX); + out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); + } else { + out_8(®s->command, MPC52xx_PSC_RST_TX); + out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); + } + + /* Next, fill up the bestcomm bd queue and enable DMA. + * This will begin filling the PSC's fifo. */ + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) + bcom_gen_bd_rx_reset(s->bcom_task); + else + bcom_gen_bd_tx_reset(s->bcom_task); + while (!bcom_queue_full(s->bcom_task)) + psc_i2s_bcom_enqueue_next_buffer(s); + bcom_enable(s->bcom_task); + + /* Due to errata in the i2s mode; need to line up enabling + * the transmitter with a transition on the frame sync + * line */ + + spin_lock_irqsave(&psc_i2s->lock, flags); + /* first make sure it is low */ + while ((in_8(®s->ipcr_acr.ipcr) & 0x80) != 0) + ; + /* then wait for the transition to high */ + while ((in_8(®s->ipcr_acr.ipcr) & 0x80) == 0) + ; + /* Finally, enable the PSC. + * Receiver must always be enabled; even when we only want + * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */ + psc_cmd = MPC52xx_PSC_RX_ENABLE; + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) + psc_cmd |= MPC52xx_PSC_TX_ENABLE; + out_8(®s->command, psc_cmd); + spin_unlock_irqrestore(&psc_i2s->lock, flags); + + break; + + case SNDRV_PCM_TRIGGER_STOP: + /* Turn off the PSC */ + s->active = 0; + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (!psc_i2s->playback.active) { + out_8(®s->command, 2 << 4); /* reset rx */ + out_8(®s->command, 3 << 4); /* reset tx */ + out_8(®s->command, 4 << 4); /* reset err */ + } + } else { + out_8(®s->command, 3 << 4); /* reset tx */ + out_8(®s->command, 4 << 4); /* reset err */ + if (!psc_i2s->capture.active) + out_8(®s->command, 2 << 4); /* reset rx */ + } + + bcom_disable(s->bcom_task); + while (!bcom_queue_empty(s->bcom_task)) + bcom_retrieve_buffer(s->bcom_task, NULL, NULL); + + break; + + default: + dev_dbg(psc_i2s->dev, "invalid command\n"); + return -EINVAL; + } + + /* Update interrupt enable settings */ + imr = 0; + if (psc_i2s->playback.active) + imr |= MPC52xx_PSC_IMR_TXEMP; + if (psc_i2s->capture.active) + imr |= MPC52xx_PSC_IMR_ORERR; + out_be16(®s->isr_imr.imr, imr); + + return 0; +} + +/** + * psc_i2s_shutdown: shutdown the data transfer on a stream + * + * Shutdown the PSC if there are no other substreams open. + */ +static void psc_i2s_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + + dev_dbg(psc_i2s->dev, "psc_i2s_shutdown(substream=%p)\n", substream); + + /* + * If this is the last active substream, disable the PSC and release + * the IRQ. + */ + if (!psc_i2s->playback.active && + !psc_i2s->capture.active) { + + /* Disable all interrupts and reset the PSC */ + out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0); + out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset tx */ + out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset rx */ + out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */ + out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */ + + /* Release irqs */ + free_irq(psc_i2s->irq, psc_i2s); + free_irq(psc_i2s->capture.irq, &psc_i2s->capture); + free_irq(psc_i2s->playback.irq, &psc_i2s->playback); + } +} + +/** + * psc_i2s_set_sysclk: set the clock frequency and direction + * + * This function is called by the machine driver to tell us what the clock + * frequency and direction are. + * + * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN), + * and we don't care about the frequency. Return an error if the direction + * is not SND_SOC_CLOCK_IN. + * + * @clk_id: reserved, should be zero + * @freq: the frequency of the given clock ID, currently ignored + * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) + */ +static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct psc_i2s *psc_i2s = cpu_dai->private_data; + dev_dbg(psc_i2s->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", + cpu_dai, dir); + return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; +} + +/** + * psc_i2s_set_fmt: set the serial format. + * + * This function is called by the machine driver to tell us what serial + * format to use. + * + * This driver only supports I2S mode. Return an error if the format is + * not SND_SOC_DAIFMT_I2S. + * + * @format: one of SND_SOC_DAIFMT_xxx + */ +static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) +{ + struct psc_i2s *psc_i2s = cpu_dai->private_data; + dev_dbg(psc_i2s->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", + cpu_dai, format); + return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; +} + +/* --------------------------------------------------------------------- + * ALSA SoC Bindings + * + * - Digital Audio Interface (DAI) template + * - create/destroy dai hooks + */ + +/** + * psc_i2s_dai_template: template CPU Digital Audio Interface + */ +static struct snd_soc_dai psc_i2s_dai_template = { + .type = SND_SOC_DAI_I2S, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = PSC_I2S_RATES, + .formats = PSC_I2S_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = PSC_I2S_RATES, + .formats = PSC_I2S_FORMATS, + }, + .ops = { + .startup = psc_i2s_startup, + .hw_params = psc_i2s_hw_params, + .hw_free = psc_i2s_hw_free, + .shutdown = psc_i2s_shutdown, + .trigger = psc_i2s_trigger, + }, + .dai_ops = { + .set_sysclk = psc_i2s_set_sysclk, + .set_fmt = psc_i2s_set_fmt, + }, +}; + +/* --------------------------------------------------------------------- + * The PSC I2S 'ASoC platform' driver + * + * Can be referenced by an 'ASoC machine' driver + * This driver only deals with the audio bus; it doesn't have any + * interaction with the attached codec + */ + +static const struct snd_pcm_hardware psc_i2s_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .period_bytes_max = 1024 * 1024, + .period_bytes_min = 32, + .periods_min = 2, + .periods_max = 256, + .buffer_bytes_max = 2 * 1024 * 1024, + .fifo_size = 0, +}; + +static int psc_i2s_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + struct psc_i2s_stream *s; + + dev_dbg(psc_i2s->dev, "psc_i2s_pcm_open(substream=%p)\n", substream); + + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) + s = &psc_i2s->capture; + else + s = &psc_i2s->playback; + + snd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware); + + s->stream = substream; + return 0; +} + +static int psc_i2s_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + struct psc_i2s_stream *s; + + dev_dbg(psc_i2s->dev, "psc_i2s_pcm_close(substream=%p)\n", substream); + + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) + s = &psc_i2s->capture; + else + s = &psc_i2s->playback; + + s->stream = NULL; + return 0; +} + +static snd_pcm_uframes_t +psc_i2s_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; + struct psc_i2s_stream *s; + dma_addr_t count; + + if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) + s = &psc_i2s->capture; + else + s = &psc_i2s->playback; + + count = s->period_current_pt - s->period_start; + + return bytes_to_frames(substream->runtime, count); +} + +static struct snd_pcm_ops psc_i2s_pcm_ops = { + .open = psc_i2s_pcm_open, + .close = psc_i2s_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .pointer = psc_i2s_pcm_pointer, +}; + +static u64 psc_i2s_pcm_dmamask = 0xffffffff; +static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, + struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + size_t size = psc_i2s_pcm_hardware.buffer_bytes_max; + int rc = 0; + + dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\n", + card, dai, pcm); + + if (!card->dev->dma_mask) + card->dev->dma_mask = &psc_i2s_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = 0xffffffff; + + if (pcm->streams[0].substream) { + rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size, + &pcm->streams[0].substream->dma_buffer); + if (rc) + goto playback_alloc_err; + } + + if (pcm->streams[1].substream) { + rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size, + &pcm->streams[1].substream->dma_buffer); + if (rc) + goto capture_alloc_err; + } + + return 0; + + capture_alloc_err: + if (pcm->streams[0].substream) + snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); + playback_alloc_err: + dev_err(card->dev, "Cannot allocate buffer(s)\n"); + return -ENOMEM; +} + +static void psc_i2s_pcm_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_pcm_substream *substream; + int stream; + + dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_free(pcm=%p)\n", pcm); + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (substream) { + snd_dma_free_pages(&substream->dma_buffer); + substream->dma_buffer.area = NULL; + substream->dma_buffer.addr = 0; + } + } +} + +struct snd_soc_platform psc_i2s_pcm_soc_platform = { + .name = "mpc5200-psc-audio", + .pcm_ops = &psc_i2s_pcm_ops, + .pcm_new = &psc_i2s_pcm_new, + .pcm_free = &psc_i2s_pcm_free, +}; + +/* --------------------------------------------------------------------- + * Sysfs attributes for debugging + */ + +static ssize_t psc_i2s_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct psc_i2s *psc_i2s = dev_get_drvdata(dev); + + return sprintf(buf, "status=%.4x sicr=%.8x rfnum=%i rfstat=0x%.4x " + "tfnum=%i tfstat=0x%.4x\n", + in_be16(&psc_i2s->psc_regs->sr_csr.status), + in_be32(&psc_i2s->psc_regs->sicr), + in_be16(&psc_i2s->fifo_regs->rfnum) & 0x1ff, + in_be16(&psc_i2s->fifo_regs->rfstat), + in_be16(&psc_i2s->fifo_regs->tfnum) & 0x1ff, + in_be16(&psc_i2s->fifo_regs->tfstat)); +} + +static int *psc_i2s_get_stat_attr(struct psc_i2s *psc_i2s, const char *name) +{ + if (strcmp(name, "playback_underrun") == 0) + return &psc_i2s->stats.underrun_count; + if (strcmp(name, "capture_overrun") == 0) + return &psc_i2s->stats.overrun_count; + + return NULL; +} + +static ssize_t psc_i2s_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct psc_i2s *psc_i2s = dev_get_drvdata(dev); + int *attrib; + + attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name); + if (!attrib) + return 0; + + return sprintf(buf, "%i\n", *attrib); +} + +static ssize_t psc_i2s_stat_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct psc_i2s *psc_i2s = dev_get_drvdata(dev); + int *attrib; + + attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name); + if (!attrib) + return 0; + + *attrib = simple_strtoul(buf, NULL, 0); + return count; +} + +DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL); +DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store); +DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store); + +/* --------------------------------------------------------------------- + * OF platform bus binding code: + * - Probe/remove operations + * - OF device match table + */ +static int __devinit psc_i2s_of_probe(struct of_device *op, + const struct of_device_id *match) +{ + phys_addr_t fifo; + struct psc_i2s *psc_i2s; + struct resource res; + int size, psc_id, irq, rc; + const __be32 *prop; + void __iomem *regs; + + dev_dbg(&op->dev, "probing psc i2s device\n"); + + /* Get the PSC ID */ + prop = of_get_property(op->node, "cell-index", &size); + if (!prop || size < sizeof *prop) + return -ENODEV; + psc_id = be32_to_cpu(*prop); + + /* Fetch the registers and IRQ of the PSC */ + irq = irq_of_parse_and_map(op->node, 0); + if (of_address_to_resource(op->node, 0, &res)) { + dev_err(&op->dev, "Missing reg property\n"); + return -ENODEV; + } + regs = ioremap(res.start, 1 + res.end - res.start); + if (!regs) { + dev_err(&op->dev, "Could not map registers\n"); + return -ENODEV; + } + + /* Allocate and initialize the driver private data */ + psc_i2s = kzalloc(sizeof *psc_i2s, GFP_KERNEL); + if (!psc_i2s) { + iounmap(regs); + return -ENOMEM; + } + spin_lock_init(&psc_i2s->lock); + psc_i2s->irq = irq; + psc_i2s->psc_regs = regs; + psc_i2s->fifo_regs = regs + sizeof *psc_i2s->psc_regs; + psc_i2s->dev = &op->dev; + psc_i2s->playback.psc_i2s = psc_i2s; + psc_i2s->capture.psc_i2s = psc_i2s; + snprintf(psc_i2s->name, sizeof psc_i2s->name, "PSC%u", psc_id+1); + + /* Fill out the CPU DAI structure */ + memcpy(&psc_i2s->dai, &psc_i2s_dai_template, sizeof psc_i2s->dai); + psc_i2s->dai.private_data = psc_i2s; + psc_i2s->dai.name = psc_i2s->name; + psc_i2s->dai.id = psc_id; + + /* Find the address of the fifo data registers and setup the + * DMA tasks */ + fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32); + psc_i2s->capture.bcom_task = + bcom_psc_gen_bd_rx_init(psc_id, 10, fifo, 512); + psc_i2s->playback.bcom_task = + bcom_psc_gen_bd_tx_init(psc_id, 10, fifo); + if (!psc_i2s->capture.bcom_task || + !psc_i2s->playback.bcom_task) { + dev_err(&op->dev, "Could not allocate bestcomm tasks\n"); + iounmap(regs); + kfree(psc_i2s); + return -ENODEV; + } + + /* Disable all interrupts and reset the PSC */ + out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0); + out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset transmitter */ + out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset receiver */ + out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */ + out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */ + + /* Configure the serial interface mode; defaulting to CODEC8 mode */ + psc_i2s->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S | + MPC52xx_PSC_SICR_CLKPOL; + if (of_get_property(op->node, "fsl,cellslave", NULL)) + psc_i2s->sicr |= MPC52xx_PSC_SICR_CELLSLAVE | + MPC52xx_PSC_SICR_GENCLK; + out_be32(&psc_i2s->psc_regs->sicr, + psc_i2s->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8); + + /* Check for the codec handle. If it is not present then we + * are done */ + if (!of_get_property(op->node, "codec-handle", NULL)) + return 0; + + /* Set up mode register; + * First write: RxRdy (FIFO Alarm) generates rx FIFO irq + * Second write: register Normal mode for non loopback + */ + out_8(&psc_i2s->psc_regs->mode, 0); + out_8(&psc_i2s->psc_regs->mode, 0); + + /* Set the TX and RX fifo alarm thresholds */ + out_be16(&psc_i2s->fifo_regs->rfalarm, 0x100); + out_8(&psc_i2s->fifo_regs->rfcntl, 0x4); + out_be16(&psc_i2s->fifo_regs->tfalarm, 0x100); + out_8(&psc_i2s->fifo_regs->tfcntl, 0x7); + + /* Lookup the IRQ numbers */ + psc_i2s->playback.irq = + bcom_get_task_irq(psc_i2s->playback.bcom_task); + psc_i2s->capture.irq = + bcom_get_task_irq(psc_i2s->capture.bcom_task); + + /* Save what we've done so it can be found again later */ + dev_set_drvdata(&op->dev, psc_i2s); + + /* Register the SYSFS files */ + rc = device_create_file(psc_i2s->dev, &dev_attr_status); + rc = device_create_file(psc_i2s->dev, &dev_attr_capture_overrun); + rc = device_create_file(psc_i2s->dev, &dev_attr_playback_underrun); + if (rc) + dev_info(psc_i2s->dev, "error creating sysfs files\n"); + + /* Tell the ASoC OF helpers about it */ + of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node, + &psc_i2s->dai); + + return 0; +} + +static int __devexit psc_i2s_of_remove(struct of_device *op) +{ + struct psc_i2s *psc_i2s = dev_get_drvdata(&op->dev); + + dev_dbg(&op->dev, "psc_i2s_remove()\n"); + + bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task); + bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task); + + iounmap(psc_i2s->psc_regs); + iounmap(psc_i2s->fifo_regs); + kfree(psc_i2s); + dev_set_drvdata(&op->dev, NULL); + + return 0; +} + +/* Match table for of_platform binding */ +static struct of_device_id psc_i2s_match[] __devinitdata = { + { .compatible = "fsl,mpc5200-psc-i2s", }, + {} +}; +MODULE_DEVICE_TABLE(of, psc_i2s_match); + +static struct of_platform_driver psc_i2s_driver = { + .match_table = psc_i2s_match, + .probe = psc_i2s_of_probe, + .remove = __devexit_p(psc_i2s_of_remove), + .driver = { + .name = "mpc5200-psc-i2s", + .owner = THIS_MODULE, + }, +}; + +/* --------------------------------------------------------------------- + * Module setup and teardown; simply register the of_platform driver + * for the PSC in I2S mode. + */ +static int __init psc_i2s_init(void) +{ + return of_register_platform_driver(&psc_i2s_driver); +} +module_init(psc_i2s_init); + +static void __exit psc_i2s_exit(void) +{ + of_unregister_platform_driver(&psc_i2s_driver); +} +module_exit(psc_i2s_exit); + + -- GitLab From d8e3bb7385da0bcdda4ffa600489fa1439b14673 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 29 Jul 2008 11:42:31 +0100 Subject: [PATCH 0191/5416] ALSA: ASoC: Add Texas Instruments TLV320AIC26 codec driver ASoC Codec driver for the TLV320AIC26 device. As it stands, this driver doesn't support all the modes and clocking options of the AIC16, but it is a start. Signed-off-by: Grant Likely Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic26.c | 519 +++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic26.h | 93 ++++++ 4 files changed, 618 insertions(+) create mode 100644 sound/soc/codecs/tlv320aic26.c create mode 100644 sound/soc/codecs/tlv320aic26.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1db04a28a53..9e09fa5f2d4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -47,6 +47,10 @@ config SND_SOC_CS4270_VD33_ERRATA bool depends on SND_SOC_CS4270 +config SND_SOC_TLV320AIC26 + tristate "TI TLV320AIC26 Codec support" + depends on SND_SOC && SPI + config SND_SOC_TLV320AIC3X tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d7b97abcf72..dc0357e20fe 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -9,6 +9,7 @@ snd-soc-wm8990-objs := wm8990.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o snd-soc-cs4270-objs := cs4270.o +snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o @@ -22,4 +23,5 @@ obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o +obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c new file mode 100644 index 00000000000..4621fda5705 --- /dev/null +++ b/sound/soc/codecs/tlv320aic26.c @@ -0,0 +1,519 @@ +/* + * Texas Instruments TLV320AIC26 low power audio CODEC + * ALSA SoC CODEC driver + * + * Copyright (C) 2008 Secret Lab Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlv320aic26.h" + +MODULE_DESCRIPTION("ASoC TLV320AIC26 codec driver"); +MODULE_AUTHOR("Grant Likely "); +MODULE_LICENSE("GPL"); + +/* AIC26 driver private data */ +struct aic26 { + struct spi_device *spi; + struct snd_soc_codec codec; + u16 reg_cache[AIC26_NUM_REGS]; /* shadow registers */ + int master; + int datfm; + int mclk; + + /* Keyclick parameters */ + int keyclick_amplitude; + int keyclick_freq; + int keyclick_len; +}; + +/* --------------------------------------------------------------------- + * Register access routines + */ +static unsigned int aic26_reg_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + struct aic26 *aic26 = codec->private_data; + u16 *cache = codec->reg_cache; + u16 cmd, value; + u8 buffer[2]; + int rc; + + if (reg >= AIC26_NUM_REGS) { + WARN_ON_ONCE(1); + return 0; + } + + /* Do SPI transfer; first 16bits are command; remaining is + * register contents */ + cmd = AIC26_READ_COMMAND_WORD(reg); + buffer[0] = (cmd >> 8) & 0xff; + buffer[1] = cmd & 0xff; + rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2); + if (rc) { + dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); + return -EIO; + } + value = (buffer[0] << 8) | buffer[1]; + + /* Update the cache before returning with the value */ + cache[reg] = value; + return value; +} + +static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + if (reg >= AIC26_NUM_REGS) { + WARN_ON_ONCE(1); + return 0; + } + + return cache[reg]; +} + +static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + struct aic26 *aic26 = codec->private_data; + u16 *cache = codec->reg_cache; + u16 cmd; + u8 buffer[4]; + int rc; + + if (reg >= AIC26_NUM_REGS) { + WARN_ON_ONCE(1); + return -EINVAL; + } + + /* Do SPI transfer; first 16bits are command; remaining is data + * to write into register */ + cmd = AIC26_WRITE_COMMAND_WORD(reg); + buffer[0] = (cmd >> 8) & 0xff; + buffer[1] = cmd & 0xff; + buffer[2] = value >> 8; + buffer[3] = value; + rc = spi_write(aic26->spi, buffer, 4); + if (rc) { + dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); + return -EIO; + } + + /* update cache before returning */ + cache[reg] = value; + return 0; +} + +/* --------------------------------------------------------------------- + * Digital Audio Interface Operations + */ +static int aic26_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + struct aic26 *aic26 = codec->private_data; + int fsref, divisor, wlen, pval, jval, dval, qval; + u16 reg; + + dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n", + substream, params); + dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params), + params_format(params)); + + switch (params_rate(params)) { + case 8000: fsref = 48000; divisor = AIC26_DIV_6; break; + case 11025: fsref = 44100; divisor = AIC26_DIV_4; break; + case 12000: fsref = 48000; divisor = AIC26_DIV_4; break; + case 16000: fsref = 48000; divisor = AIC26_DIV_3; break; + case 22050: fsref = 44100; divisor = AIC26_DIV_2; break; + case 24000: fsref = 48000; divisor = AIC26_DIV_2; break; + case 32000: fsref = 48000; divisor = AIC26_DIV_1_5; break; + case 44100: fsref = 44100; divisor = AIC26_DIV_1; break; + case 48000: fsref = 48000; divisor = AIC26_DIV_1; break; + default: + dev_dbg(&aic26->spi->dev, "bad rate\n"); return -EINVAL; + } + + /* select data word length */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break; + case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break; + case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break; + case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break; + default: + dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; + } + + /* Configure PLL */ + pval = 1; + jval = (fsref == 44100) ? 7 : 8; + dval = (fsref == 44100) ? 5264 : 1920; + qval = 0; + reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; + aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); + reg = dval << 2; + aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg); + + /* Audio Control 3 (master mode, fsref rate) */ + reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); + reg &= ~0xf800; + if (aic26->master) + reg |= 0x0800; + if (fsref == 48000) + reg |= 0x2000; + aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); + + /* Audio Control 1 (FSref divisor) */ + reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); + reg &= ~0x0fff; + reg |= wlen | aic26->datfm | (divisor << 3) | divisor; + aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg); + + return 0; +} + +/** + * aic26_mute - Mute control to reduce noise when changing audio format + */ +static int aic26_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct aic26 *aic26 = codec->private_data; + u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN); + + dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n", + dai, mute); + + if (mute) + reg |= 0x8080; + else + reg &= ~0x8080; + aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg); + + return 0; +} + +static int aic26_set_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct aic26 *aic26 = codec->private_data; + + dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i," + " freq=%i, dir=%i)\n", + codec_dai, clk_id, freq, dir); + + /* MCLK needs to fall between 2MHz and 50 MHz */ + if ((freq < 2000000) || (freq > 50000000)) + return -EINVAL; + + aic26->mclk = freq; + return 0; +} + +static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct aic26 *aic26 = codec->private_data; + + dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n", + codec_dai, fmt); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: aic26->master = 1; break; + case SND_SOC_DAIFMT_CBS_CFS: aic26->master = 0; break; + default: + dev_dbg(&aic26->spi->dev, "bad master\n"); return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: aic26->datfm = AIC26_DATFM_I2S; break; + case SND_SOC_DAIFMT_DSP_A: aic26->datfm = AIC26_DATFM_DSP; break; + case SND_SOC_DAIFMT_RIGHT_J: aic26->datfm = AIC26_DATFM_RIGHTJ; break; + case SND_SOC_DAIFMT_LEFT_J: aic26->datfm = AIC26_DATFM_LEFTJ; break; + default: + dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; + } + + return 0; +} + +/* --------------------------------------------------------------------- + * Digital Audio Interface Definition + */ +#define AIC26_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000) +#define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) + +struct snd_soc_dai aic26_dai = { + .name = "tlv320aic26", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = AIC26_RATES, + .formats = AIC26_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = AIC26_RATES, + .formats = AIC26_FORMATS, + }, + .ops = { + .hw_params = aic26_hw_params, + }, + .dai_ops = { + .digital_mute = aic26_mute, + .set_sysclk = aic26_set_sysclk, + .set_fmt = aic26_set_fmt, + }, +}; +EXPORT_SYMBOL_GPL(aic26_dai); + +/* --------------------------------------------------------------------- + * ALSA controls + */ +static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; +static const struct soc_enum aic26_capture_src_enum = + SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); + +static const struct snd_kcontrol_new aic26_snd_controls[] = { + /* Output */ + SOC_DOUBLE("PCM Playback Volume", AIC26_REG_DAC_GAIN, 8, 0, 0x7f, 1), + SOC_DOUBLE("PCM Playback Switch", AIC26_REG_DAC_GAIN, 15, 7, 1, 1), + SOC_SINGLE("PCM Capture Volume", AIC26_REG_ADC_GAIN, 8, 0x7f, 0), + SOC_SINGLE("PCM Capture Mute", AIC26_REG_ADC_GAIN, 15, 1, 1), + SOC_SINGLE("Keyclick activate", AIC26_REG_AUDIO_CTRL2, 15, 0x1, 0), + SOC_SINGLE("Keyclick amplitude", AIC26_REG_AUDIO_CTRL2, 12, 0x7, 0), + SOC_SINGLE("Keyclick frequency", AIC26_REG_AUDIO_CTRL2, 8, 0x7, 0), + SOC_SINGLE("Keyclick period", AIC26_REG_AUDIO_CTRL2, 4, 0xf, 0), + SOC_ENUM("Capture Source", aic26_capture_src_enum), +}; + +/* --------------------------------------------------------------------- + * SoC CODEC portion of driver: probe and release routines + */ +static int aic26_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + struct snd_kcontrol *kcontrol; + struct aic26 *aic26; + int i, ret, err; + + dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); + dev_dbg(&pdev->dev, "socdev=%p\n", socdev); + dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); + + /* Fetch the relevant aic26 private data here (it's already been + * stored in the .codec pointer) */ + aic26 = socdev->codec_data; + if (aic26 == NULL) { + dev_err(&pdev->dev, "aic26: missing codec pointer\n"); + return -ENODEV; + } + codec = &aic26->codec; + socdev->codec = codec; + + dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", + &pdev->dev, socdev->dev); + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(&pdev->dev, "aic26: failed to create pcms\n"); + return -ENODEV; + } + + /* register controls */ + dev_dbg(&pdev->dev, "Registering controls\n"); + for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) { + kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL); + err = snd_ctl_add(codec->card, kcontrol); + WARN_ON(err < 0); + } + + /* CODEC is setup, we can register the card now */ + dev_dbg(&pdev->dev, "Registering card\n"); + ret = snd_soc_register_card(socdev); + if (ret < 0) { + dev_err(&pdev->dev, "aic26: failed to register card\n"); + goto card_err; + } + return 0; + + card_err: + snd_soc_free_pcms(socdev); + return ret; +} + +static int aic26_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + snd_soc_free_pcms(socdev); + return 0; +} + +struct snd_soc_codec_device aic26_soc_codec_dev = { + .probe = aic26_probe, + .remove = aic26_remove, +}; + +/* --------------------------------------------------------------------- + * SPI device portion of driver: sysfs files for debugging + */ + +static ssize_t aic26_keyclick_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aic26 *aic26 = dev_get_drvdata(dev); + int val, amp, freq, len; + + val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); + amp = (val >> 12) & 0x7; + freq = (125 << ((val >> 8) & 0x7)) >> 1; + len = 2 * (1 + ((val >> 4) & 0xf)); + + return sprintf(buf, "amp=%x freq=%iHz len=%iclks\n", amp, freq, len); +} + +/* Any write to the keyclick attribute will trigger the keyclick event */ +static ssize_t aic26_keyclick_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aic26 *aic26 = dev_get_drvdata(dev); + int val; + + val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); + val |= 0x8000; + aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val); + + return count; +} + +DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); + +/* --------------------------------------------------------------------- + * SPI device portion of driver: probe and release routines and SPI + * driver registration. + */ +static int aic26_spi_probe(struct spi_device *spi) +{ + struct aic26 *aic26; + int rc, i, reg; + + dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); + + /* Allocate driver data */ + aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); + if (!aic26) + return -ENOMEM; + + /* Initialize the driver data */ + aic26->spi = spi; + dev_set_drvdata(&spi->dev, aic26); + + /* Setup what we can in the codec structure so that the register + * access functions will work as expected. More will be filled + * out when it is probed by the SoC CODEC part of this driver */ + aic26->codec.private_data = aic26; + aic26->codec.name = "aic26"; + aic26->codec.owner = THIS_MODULE; + aic26->codec.dai = &aic26_dai; + aic26->codec.num_dai = 1; + aic26->codec.read = aic26_reg_read; + aic26->codec.write = aic26_reg_write; + aic26->master = 1; + mutex_init(&aic26->codec.mutex); + INIT_LIST_HEAD(&aic26->codec.dapm_widgets); + INIT_LIST_HEAD(&aic26->codec.dapm_paths); + aic26->codec.reg_cache_size = AIC26_NUM_REGS; + aic26->codec.reg_cache = aic26->reg_cache; + + /* Reset the codec to power on defaults */ + aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); + + /* Power up CODEC */ + aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); + + /* Audio Control 3 (master mode, fsref rate) */ + reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); + reg &= ~0xf800; + reg |= 0x0800; /* set master mode */ + aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); + + /* Fill register cache */ + for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) + aic26_reg_read(&aic26->codec, i); + + /* Register the sysfs files for debugging */ + /* Create SysFS files */ + rc = device_create_file(&spi->dev, &dev_attr_keyclick); + if (rc) + dev_info(&spi->dev, "error creating sysfs files\n"); + +#if defined(CONFIG_SND_SOC_OF_SIMPLE) + /* Tell the of_soc helper about this codec */ + of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, + spi->dev.archdata.of_node); +#endif + + dev_dbg(&spi->dev, "SPI device initialized\n"); + return 0; +} + +static int aic26_spi_remove(struct spi_device *spi) +{ + struct aic26 *aic26 = dev_get_drvdata(&spi->dev); + + kfree(aic26); + + return 0; +} + +static struct spi_driver aic26_spi = { + .driver = { + .name = "tlv320aic26", + .owner = THIS_MODULE, + }, + .probe = aic26_spi_probe, + .remove = aic26_spi_remove, +}; + +static int __init aic26_init(void) +{ + return spi_register_driver(&aic26_spi); +} +module_init(aic26_init); + +static void __exit aic26_exit(void) +{ + spi_unregister_driver(&aic26_spi); +} +module_exit(aic26_exit); diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h new file mode 100644 index 00000000000..62b1f226142 --- /dev/null +++ b/sound/soc/codecs/tlv320aic26.h @@ -0,0 +1,93 @@ +/* + * Texas Instruments TLV320AIC26 low power audio CODEC + * register definitions + * + * Copyright (C) 2008 Secret Lab Technologies Ltd. + */ + +#ifndef _TLV320AIC16_H_ +#define _TLV320AIC16_H_ + +/* AIC26 Registers */ +#define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5)) +#define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5)) +#define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset) +#define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0) + +/* Page 0: Auxillary data registers */ +#define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05) +#define AIC26_REG_BAT2 AIC26_PAGE_ADDR(0, 0x06) +#define AIC26_REG_AUX AIC26_PAGE_ADDR(0, 0x07) +#define AIC26_REG_TEMP1 AIC26_PAGE_ADDR(0, 0x09) +#define AIC26_REG_TEMP2 AIC26_PAGE_ADDR(0, 0x0A) + +/* Page 1: Auxillary control registers */ +#define AIC26_REG_AUX_ADC AIC26_PAGE_ADDR(1, 0x00) +#define AIC26_REG_STATUS AIC26_PAGE_ADDR(1, 0x01) +#define AIC26_REG_REFERENCE AIC26_PAGE_ADDR(1, 0x03) +#define AIC26_REG_RESET AIC26_PAGE_ADDR(1, 0x04) + +/* Page 2: Audio control registers */ +#define AIC26_REG_AUDIO_CTRL1 AIC26_PAGE_ADDR(2, 0x00) +#define AIC26_REG_ADC_GAIN AIC26_PAGE_ADDR(2, 0x01) +#define AIC26_REG_DAC_GAIN AIC26_PAGE_ADDR(2, 0x02) +#define AIC26_REG_SIDETONE AIC26_PAGE_ADDR(2, 0x03) +#define AIC26_REG_AUDIO_CTRL2 AIC26_PAGE_ADDR(2, 0x04) +#define AIC26_REG_POWER_CTRL AIC26_PAGE_ADDR(2, 0x05) +#define AIC26_REG_AUDIO_CTRL3 AIC26_PAGE_ADDR(2, 0x06) + +#define AIC26_REG_FILTER_COEFF_L_N0 AIC26_PAGE_ADDR(2, 0x07) +#define AIC26_REG_FILTER_COEFF_L_N1 AIC26_PAGE_ADDR(2, 0x08) +#define AIC26_REG_FILTER_COEFF_L_N2 AIC26_PAGE_ADDR(2, 0x09) +#define AIC26_REG_FILTER_COEFF_L_N3 AIC26_PAGE_ADDR(2, 0x0A) +#define AIC26_REG_FILTER_COEFF_L_N4 AIC26_PAGE_ADDR(2, 0x0B) +#define AIC26_REG_FILTER_COEFF_L_N5 AIC26_PAGE_ADDR(2, 0x0C) +#define AIC26_REG_FILTER_COEFF_L_D1 AIC26_PAGE_ADDR(2, 0x0D) +#define AIC26_REG_FILTER_COEFF_L_D2 AIC26_PAGE_ADDR(2, 0x0E) +#define AIC26_REG_FILTER_COEFF_L_D4 AIC26_PAGE_ADDR(2, 0x0F) +#define AIC26_REG_FILTER_COEFF_L_D5 AIC26_PAGE_ADDR(2, 0x10) +#define AIC26_REG_FILTER_COEFF_R_N0 AIC26_PAGE_ADDR(2, 0x11) +#define AIC26_REG_FILTER_COEFF_R_N1 AIC26_PAGE_ADDR(2, 0x12) +#define AIC26_REG_FILTER_COEFF_R_N2 AIC26_PAGE_ADDR(2, 0x13) +#define AIC26_REG_FILTER_COEFF_R_N3 AIC26_PAGE_ADDR(2, 0x14) +#define AIC26_REG_FILTER_COEFF_R_N4 AIC26_PAGE_ADDR(2, 0x15) +#define AIC26_REG_FILTER_COEFF_R_N5 AIC26_PAGE_ADDR(2, 0x16) +#define AIC26_REG_FILTER_COEFF_R_D1 AIC26_PAGE_ADDR(2, 0x17) +#define AIC26_REG_FILTER_COEFF_R_D2 AIC26_PAGE_ADDR(2, 0x18) +#define AIC26_REG_FILTER_COEFF_R_D4 AIC26_PAGE_ADDR(2, 0x19) +#define AIC26_REG_FILTER_COEFF_R_D5 AIC26_PAGE_ADDR(2, 0x1A) + +#define AIC26_REG_PLL_PROG1 AIC26_PAGE_ADDR(2, 0x1B) +#define AIC26_REG_PLL_PROG2 AIC26_PAGE_ADDR(2, 0x1C) +#define AIC26_REG_AUDIO_CTRL4 AIC26_PAGE_ADDR(2, 0x1D) +#define AIC26_REG_AUDIO_CTRL5 AIC26_PAGE_ADDR(2, 0x1E) + +/* fsref dividers; used in register 'Audio Control 1' */ +enum aic26_divisors { + AIC26_DIV_1 = 0, + AIC26_DIV_1_5 = 1, + AIC26_DIV_2 = 2, + AIC26_DIV_3 = 3, + AIC26_DIV_4 = 4, + AIC26_DIV_5 = 5, + AIC26_DIV_5_5 = 6, + AIC26_DIV_6 = 7, +}; + +/* Digital data format */ +enum aic26_datfm { + AIC26_DATFM_I2S = 0 << 8, + AIC26_DATFM_DSP = 1 << 8, + AIC26_DATFM_RIGHTJ = 2 << 8, /* right justified */ + AIC26_DATFM_LEFTJ = 3 << 8, /* left justified */ +}; + +/* Sample word length in bits; used in register 'Audio Control 1' */ +enum aic26_wlen { + AIC26_WLEN_16 = 0 << 10, + AIC26_WLEN_20 = 1 << 10, + AIC26_WLEN_24 = 2 << 10, + AIC26_WLEN_32 = 3 << 10, +}; + +#endif /* _TLV320AIC16_H_ */ -- GitLab From ecb0b3f62762cec4fd02eb6b0375aee1f5a49520 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Jul 2008 11:42:32 +0100 Subject: [PATCH 0192/5416] ALSA: ASoC: Export DAI and codec for TLV320AIC26 This fixes sparse warnings and allows non-OpenFirmware systems to attempt to bind to the device. Signed-off-by: Mark Brown Acked-by: Grant Likely Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tlv320aic26.c | 1 + sound/soc/codecs/tlv320aic26.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 4621fda5705..73b70271e58 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -383,6 +383,7 @@ struct snd_soc_codec_device aic26_soc_codec_dev = { .probe = aic26_probe, .remove = aic26_remove, }; +EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); /* --------------------------------------------------------------------- * SPI device portion of driver: sysfs files for debugging diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 62b1f226142..786ba16c945 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h @@ -90,4 +90,7 @@ enum aic26_wlen { AIC26_WLEN_32 = 3 << 10, }; +extern struct snd_soc_dai aic26_dai; +extern struct snd_soc_codec_device aic26_soc_codec_dev; + #endif /* _TLV320AIC16_H_ */ -- GitLab From 9cce39a1ba2e69a0fedc9ad9356d3b4a81e138a4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Jul 2008 11:42:33 +0100 Subject: [PATCH 0193/5416] ALSA: ASoC: Staticise keyclick dev_attr in tlv320aic26 Signed-off-by: Mark Brown Acked-by: Grant Likely Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/tlv320aic26.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 73b70271e58..bed8a9e63dd 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -418,7 +418,7 @@ static ssize_t aic26_keyclick_set(struct device *dev, return count; } -DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); +static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); /* --------------------------------------------------------------------- * SPI device portion of driver: probe and release routines and SPI -- GitLab From 5f57dc8b2a05f1d69f913fd885539b8c1f8fb8a1 Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Tue, 29 Jul 2008 11:42:34 +0100 Subject: [PATCH 0194/5416] ALSA: ASoC: AD1980 audio codec driver [Mechanical updates from code review applied -- broonie] Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 3 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/ad1980.c | 309 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/ad1980.h | 23 +++ 4 files changed, 337 insertions(+) create mode 100644 sound/soc/codecs/ad1980.c create mode 100644 sound/soc/codecs/ad1980.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9e09fa5f2d4..7ab74cd7b85 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2,6 +2,9 @@ config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC +config SND_SOC_AD1980 + tristate + config SND_SOC_AK4535 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index dc0357e20fe..409e4dd1789 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,4 +1,5 @@ snd-soc-ac97-objs := ac97.o +snd-soc-ad1980-objs := ad1980.o snd-soc-ak4535-objs := ak4535.o snd-soc-uda1380-objs := uda1380.o snd-soc-wm8510-objs := wm8510.o @@ -13,6 +14,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o +obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c new file mode 100644 index 00000000000..bfbab3d6c35 --- /dev/null +++ b/sound/soc/codecs/ad1980.c @@ -0,0 +1,309 @@ +/* + * ad1980.c -- ALSA Soc AD1980 codec support + * + * Copyright: Analog Device Inc. + * Author: Roy Huang + * Cliff Cai + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad1980.h" + +static unsigned int ac97_read(struct snd_soc_codec *codec, + unsigned int reg); +static int ac97_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val); + +/* + * AD1980 register cache + */ +static const u16 ad1980_reg[] = { + 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */ + 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */ + 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */ + 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */ + 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */ + 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */ + 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */ + 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ + 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ + 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ + 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ + 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ + 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */ + 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */ +}; + +static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", + "Stereo Mix", "Mono Mix", "Phone"}; + +static const struct soc_enum ad1980_cap_src = + SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel); + +static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = { +SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), +SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), + +SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), +SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), + +SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), +SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), + +SOC_DOUBLE("PCM Capture Volume", AC97_REC_GAIN, 8, 0, 31, 0), +SOC_SINGLE("PCM Capture Switch", AC97_REC_GAIN, 15, 1, 1), + +SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), +SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), + +SOC_SINGLE("Phone Capture Volume", AC97_PHONE, 0, 31, 1), +SOC_SINGLE("Phone Capture Switch", AC97_PHONE, 15, 1, 1), + +SOC_SINGLE("Mic Volume", AC97_MIC, 0, 31, 1), +SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1), + +SOC_SINGLE("Stereo Mic Switch", AC97_AD_MISC, 6, 1, 0), +SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0), + +SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), +SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), + +SOC_ENUM("Capture Source", ad1980_cap_src), + +SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), +}; + +/* add non dapm controls */ +static int ad1980_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) { + err = snd_ctl_add(codec->card, snd_soc_cnew( + &ad1980_snd_ac97_controls[i], codec, NULL)); + if (err < 0) + return err; + } + return 0; +} + +static unsigned int ac97_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + switch (reg) { + case AC97_RESET: + case AC97_INT_PAGING: + case AC97_POWERDOWN: + case AC97_EXTENDED_STATUS: + case AC97_VENDOR_ID1: + case AC97_VENDOR_ID2: + return soc_ac97_ops.read(codec->ac97, reg); + default: + reg = reg >> 1; + + if (reg >= (ARRAY_SIZE(ad1980_reg))) + return -EINVAL; + + return cache[reg]; + } +} + +static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int val) +{ + u16 *cache = codec->reg_cache; + + soc_ac97_ops.write(codec->ac97, reg, val); + reg = reg >> 1; + if (reg < (ARRAY_SIZE(ad1980_reg))) + cache[reg] = val; + + return 0; +} + +struct snd_soc_codec_dai ad1980_dai = { + .name = "AC97", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, +}; +EXPORT_SYMBOL_GPL(ad1980_dai); + +static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) +{ + u16 retry_cnt = 0; + +retry: + if (try_warm && soc_ac97_ops.warm_reset) { + soc_ac97_ops.warm_reset(codec->ac97); + if (ac97_read(codec, AC97_RESET) == 0x0090) + return 1; + } + + soc_ac97_ops.reset(codec->ac97); + /* Set bit 16slot in register 74h, then every slot will has only 16 + * bits. This command is sent out in 20bit mode, in which case the + * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ + ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900); + + if (ac97_read(codec, AC97_RESET) != 0x0090) + goto err; + return 0; + +err: + while (retry_cnt++ < 10) + goto retry; + + printk(KERN_ERR "AD1980 AC97 reset failed\n"); + return -EIO; +} + +static int ad1980_soc_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; + u16 vendor_id2; + + printk(KERN_INFO "AD1980 SoC Audio Codec\n"); + + socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->codec == NULL) + return -ENOMEM; + codec = socdev->codec; + mutex_init(&codec->mutex); + + codec->reg_cache = + kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL); + if (codec->reg_cache == NULL) { + ret = -ENOMEM; + goto cache_err; + } + memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \ + ARRAY_SIZE(ad1980_reg)); + codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg); + codec->reg_cache_step = 2; + codec->name = "AD1980"; + codec->owner = THIS_MODULE; + codec->dai = &ad1980_dai; + codec->num_dai = 1; + codec->write = ac97_write; + codec->read = ac97_read; + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + if (ret < 0) { + printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); + goto codec_err; + } + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) + goto pcm_err; + + + ret = ad1980_reset(codec, 0); + if (ret < 0) { + printk(KERN_ERR "AC97 link error\n"); + goto reset_err; + } + + /* Read out vendor ID to make sure it is ad1980 */ + if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) + goto reset_err; + + vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); + + if (vendor_id2 != 0x5370) { + if (vendor_id2 != 0x5374) + goto reset_err; + else + printk(KERN_WARNING "ad1980: " + "Found AD1981 - only 2/2 IN/OUT Channels " + "supported\n"); + } + + ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */ + ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */ + ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */ + + ad1980_add_controls(codec); + ret = snd_soc_register_card(socdev); + if (ret < 0) { + printk(KERN_ERR "ad1980: failed to register card\n"); + goto reset_err; + } + + return 0; + +reset_err: + snd_soc_free_pcms(socdev); + +pcm_err: + snd_soc_free_ac97_codec(codec); + +codec_err: + kfree(codec->reg_cache); + +cache_err: + kfree(socdev->codec); + socdev->codec = NULL; + return ret; +} + +static int ad1980_soc_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec == NULL) + return 0; + + snd_soc_dapm_free(socdev); + snd_soc_free_pcms(socdev); + snd_soc_free_ac97_codec(codec); + kfree(codec->reg_cache); + kfree(codec); + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_ad1980 = { + .probe = ad1980_soc_probe, + .remove = ad1980_soc_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); + +MODULE_DESCRIPTION("ASoC ad1980 driver"); +MODULE_AUTHOR("Roy Huang, Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h new file mode 100644 index 00000000000..5d4710db832 --- /dev/null +++ b/sound/soc/codecs/ad1980.h @@ -0,0 +1,23 @@ +/* + * ad1980.h -- ad1980 Soc Audio driver + */ + +#ifndef _AD1980_H +#define _AD1980_H +/* Bit definition of Power-Down Control/Status Register */ +#define ADC 0x0001 +#define DAC 0x0002 +#define ANL 0x0004 +#define REF 0x0008 +#define PR0 0x0100 +#define PR1 0x0200 +#define PR2 0x0400 +#define PR3 0x0800 +#define PR4 0x1000 +#define PR5 0x2000 +#define PR6 0x4000 + +extern struct snd_soc_codec_dai ad1980_dai; +extern struct snd_soc_codec_device soc_codec_dev_ad1980; + +#endif -- GitLab From 0c94161580eee8137b868301434ea392083258b5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Jul 2008 11:42:35 +0100 Subject: [PATCH 0195/5416] ALSA: ASoC: Add all CODECs Kconfig option Allow all the CODEC drivers to be built without a machine driver in order to facilitate testing of subsystem-wide changes and gain better coverage from automated testing efforts. This also helps things like the generic OpenFirmware machine driver for PowerPC. Currently AC97 CODECs are not included since the current setup relies on having a controller driver available. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7ab74cd7b85..1c934230494 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1,3 +1,26 @@ +config SND_SOC_ALL_CODECS + tristate "Build all ASoC CODEC drivers" + select I2C + select SPI + select SND_SOC_AK4535 + select SND_SOC_UDA1380 + select SND_SOC_WM8510 + select SND_SOC_WM8731 + select SND_SOC_WM8750 + select SND_SOC_WM8753 + select SND_SOC_WM8990 + select SND_SOC_CS4270 + select SND_SOC_TLV320AIC26 + select SND_SOC_TLV320AIC3X + help + Normally ASoC codec drivers are only built if a machine driver which + uses them is also built since they are only usable with a machine + driver. Selecting this option will allow these drivers to be built + without an explicit machine driver for test and development purposes. + + If unsure select "N". + + config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC -- GitLab From 815ecf8dec95d07e260a16ebe8409f4b7c0fdc0f Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Tue, 29 Jul 2008 10:22:24 -0400 Subject: [PATCH 0196/5416] ALSA: ASoC: convert use of uint to unsigned int ASOC: convert use of uint to unsigned int Signed-off-by: Jon Smirl Acked-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/soc.h | 2 +- sound/soc/soc-core.c | 48 ++++++++++++++++++++++---------------------- sound/soc/soc-dapm.c | 36 ++++++++++++++++----------------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 5ca231f080a..a1e0357a84d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -527,7 +527,7 @@ struct snd_soc_pcm_runtime { /* mixer control */ struct soc_mixer_control { int min, max; - uint reg, rreg, shift, rshift, invert; + unsigned int reg, rreg, shift, rshift, invert; }; /* enumerated kcontrol */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 11a881caba7..1563ceedf61 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1457,8 +1457,8 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int max = mc->max; - uint shift = mc->min; - uint rshift = mc->rshift; + unsigned int shift = mc->min; + unsigned int rshift = mc->rshift; if (max == 1) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; @@ -1487,12 +1487,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; - uint shift = mc->shift; - uint rshift = mc->rshift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; ucontrol->value.integer.value[0] = (snd_soc_read(codec, reg) >> shift) & mask; @@ -1526,12 +1526,12 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; - uint shift = mc->shift; - uint rshift = mc->rshift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); @@ -1594,12 +1594,12 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; - uint reg2 = mc->rreg; - uint shift = mc->shift; + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + unsigned int shift = mc->shift; int max = mc->max; - uint mask = (1<invert; + unsigned int mask = (1<invert; ucontrol->value.integer.value[0] = (snd_soc_read(codec, reg) >> shift) & mask; @@ -1631,12 +1631,12 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; - uint reg2 = mc->rreg; - uint shift = mc->shift; + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + unsigned int shift = mc->shift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; int err; unsigned short val, val2, val_mask; @@ -1701,7 +1701,7 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; + unsigned int reg = mc->reg; int min = mc->min; int val = snd_soc_read(codec, reg); @@ -1728,7 +1728,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - uint reg = mc->reg; + unsigned int reg = mc->reg; int min = mc->min; unsigned short val; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f08be8a329e..7a88f764daf 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -106,11 +106,11 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrols[i].private_value; - uint reg = mc->reg; - uint shift = mc->shift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; val = snd_soc_read(w->codec, reg); val = (val >> shift) & mask; @@ -252,11 +252,11 @@ static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power) if (widget->num_kcontrols && k) { struct soc_mixer_control *mc = (struct soc_mixer_control *)k->private_value; - uint reg = mc->reg; - uint shift = mc->shift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; if (power) { int i; @@ -1141,12 +1141,12 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - uint reg = mc->reg; - uint shift = mc->shift; - uint rshift = mc->rshift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; int max = mc->max; - uint invert = mc->invert; - uint mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; /* return the saved value if we are powered down */ if (widget->id == snd_soc_dapm_pga && !widget->power) { @@ -1186,12 +1186,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - uint reg = mc->reg; - uint shift = mc->shift; - uint rshift = mc->rshift; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; int max = mc->max; - uint mask = (1 << fls(max)) - 1; - uint invert = mc->invert; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; unsigned short val, val2, val_mask; int ret; -- GitLab From 9423969005586e6e27ca380e01b4a8c50698e2af Mon Sep 17 00:00:00 2001 From: Pawel MOLL Date: Tue, 29 Jul 2008 17:34:26 +0100 Subject: [PATCH 0197/5416] ALSA: Fix limit of 8 PCM devices in SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE When compiled with CONFIG_SND_DYNAMIC_MINORS the ALSA core is fine to have more than 8 PCM devices per card, except one place - the SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE ioctl, which will not enumerate devices > 7. This patch fixes the issue, changing the devices list organisation. Instead of adding new device to the tail, the list is now kept always ordered (by card number, then device number). Thus, during enumeration, it is easy to discover the fact that there is no more given card's devices. The same limit was present in OSS emulation code. It has been fixed as well. Additionally the device field of struct snd_pcm is now int, instead of unsigned int, as there is no obvious reason for keeping it unsigned. This caused a lot of problems with comparing this value with other (almost always signed) variables. There is just one more place where device number is unsigned - in struct snd_pcm_info, which should be also sorted out in future. Signed-off-by: Pawel MOLL Signed-off-by: Jaroslav Kysela --- include/sound/minors.h | 2 ++ include/sound/pcm.h | 4 +--- sound/core/oss/pcm_oss.c | 10 ++++---- sound/core/pcm.c | 50 +++++++++++++++++++++++++++++----------- sound/core/sound.c | 2 -- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/include/sound/minors.h b/include/sound/minors.h index 46bcd2023ed..a81798ab73e 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -21,6 +21,8 @@ * */ +#define SNDRV_OS_MINORS 256 + #define SNDRV_MINOR_DEVICES 32 #define SNDRV_MINOR_CARD(minor) ((minor) >> 5) #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 51d58ccda2d..bfc096ac82e 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -84,8 +84,6 @@ struct snd_pcm_ops { * */ -#define SNDRV_PCM_DEVICES 8 - #define SNDRV_PCM_IOCTL1_FALSE ((void *)0) #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) @@ -416,7 +414,7 @@ struct snd_pcm_str { struct snd_pcm { struct snd_card *card; struct list_head list; - unsigned int device; /* device number */ + int device; /* device number */ unsigned int info_flags; unsigned short dev_class; unsigned short dev_subclass; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4c601b192dd..4ccd761a5f4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2947,7 +2947,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index) static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) { pcm->oss.reg = 0; - if (dsp_map[pcm->card->number] == (int)pcm->device) { + if (dsp_map[pcm->card->number] == pcm->device) { char name[128]; int duplex; register_oss_dsp(pcm, 0); @@ -2963,7 +2963,7 @@ static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) pcm->oss.reg++; pcm->oss.reg_mask |= 1; } - if (adsp_map[pcm->card->number] == (int)pcm->device) { + if (adsp_map[pcm->card->number] == pcm->device) { register_oss_dsp(pcm, 1); pcm->oss.reg++; pcm->oss.reg_mask |= 2; @@ -2988,7 +2988,7 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, pcm->card, 1); } - if (dsp_map[pcm->card->number] == (int)pcm->device) { + if (dsp_map[pcm->card->number] == pcm->device) { #ifdef SNDRV_OSS_INFO_DEV_AUDIO snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); #endif @@ -3019,12 +3019,12 @@ static int __init alsa_pcm_oss_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { - if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { + if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_OS_MINORS) { snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", i, dsp_map[i]); dsp_map[i] = 0; } - if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { + if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_OS_MINORS) { snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", i, adsp_map[i]); adsp_map[i] = 1; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ece25c718e9..24271a3bd90 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) +static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) return NULL; } +static inline int snd_pcm_next(struct snd_card *card, int device) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == card && pcm->device > device) + return pcm->device; + else if (pcm->card->number > card->number) + return -1; + } + return -1; +} + +static inline int snd_pcm_add(struct snd_pcm *newpcm) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == newpcm->card && pcm->device == newpcm->device) + return -EBUSY; + if (pcm->card->number > newpcm->card->number || + (pcm->card == newpcm->card && + pcm->device > newpcm->device)) { + list_add(&newpcm->list, pcm->list.prev); + return 0; + } + } + list_add_tail(&newpcm->list, &snd_pcm_devices); + return 0; +} + static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; - while (device < SNDRV_PCM_DEVICES) { - if (snd_pcm_search(card, device)) - break; - device++; - } - if (device == SNDRV_PCM_DEVICES) - device = -1; + device = snd_pcm_next(card, device); mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_search(card, device); + pcm = snd_pcm_get(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -931,11 +955,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - if (snd_pcm_search(pcm->card, pcm->device)) { + err = snd_pcm_add(pcm); + if (err) { mutex_unlock(®ister_mutex); - return -EBUSY; + return err; } - list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) diff --git a/sound/core/sound.c b/sound/core/sound.c index 1003ae375d4..838dd9ee957 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -34,8 +34,6 @@ #include #include -#define SNDRV_OS_MINORS 256 - static int major = CONFIG_SND_MAJOR; int snd_major; EXPORT_SYMBOL(snd_major); -- GitLab From 6902c0bead4ce266226fc0c5b3828b850bdc884a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 6 Jun 2008 01:33:22 -0400 Subject: [PATCH 0198/5416] Input: gameport - make gameport_register_driver() return errors Perform actual driver registration right in gameport_register_driver() instead of offloading it to kgameportd and return proper error code to callers if driver registration fails. Note that driver <-> port matching is still done by kgameportd. Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 88 +++++++++++++++++++++++-------- include/linux/gameport.h | 7 +-- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 078e4eed089..2880eaae157 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport) enum gameport_event_type { GAMEPORT_REGISTER_PORT, GAMEPORT_REGISTER_DRIVER, + GAMEPORT_ATTACH_DRIVER, }; struct gameport_event { @@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list); static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); static struct task_struct *gameport_task; -static void gameport_queue_event(void *object, struct module *owner, - enum gameport_event_type event_type) +static int gameport_queue_event(void *object, struct module *owner, + enum gameport_event_type event_type) { unsigned long flags; struct gameport_event *event; + int retval = 0; spin_lock_irqsave(&gameport_event_lock, flags); @@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner, } } - if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { - if (!try_module_get(owner)) { - printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); - kfree(event); - goto out; - } - - event->type = event_type; - event->object = object; - event->owner = owner; + event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); + if (!event) { + printk(KERN_ERR + "gameport: Not enough memory to queue event %d\n", + event_type); + retval = -ENOMEM; + goto out; + } - list_add_tail(&event->node, &gameport_event_list); - wake_up(&gameport_wait); - } else { - printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type); + if (!try_module_get(owner)) { + printk(KERN_WARNING + "gameport: Can't get module reference, dropping event %d\n", + event_type); + kfree(event); + retval = -EINVAL; + goto out; } + + event->type = event_type; + event->object = object; + event->owner = owner; + + list_add_tail(&event->node, &gameport_event_list); + wake_up(&gameport_wait); + out: spin_unlock_irqrestore(&gameport_event_lock, flags); + return retval; } static void gameport_free_event(struct gameport_event *event) @@ -378,9 +390,10 @@ static void gameport_handle_event(void) } /* - * Remove all events that have been submitted for a given gameport port. + * Remove all events that have been submitted for a given object, + * be it a gameport port or a driver. */ -static void gameport_remove_pending_events(struct gameport *gameport) +static void gameport_remove_pending_events(void *object) { struct list_head *node, *next; struct gameport_event *event; @@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport) list_for_each_safe(node, next, &gameport_event_list) { event = list_entry(node, struct gameport_event, node); - if (event->object == gameport) { + if (event->object == object) { list_del_init(node); gameport_free_event(event); } @@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv) drv->driver.name, error); } -void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) +int __gameport_register_driver(struct gameport_driver *drv, struct module *owner, + const char *mod_name) { + int error; + drv->driver.bus = &gameport_bus; - gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); + drv->driver.owner = owner; + drv->driver.mod_name = mod_name; + + /* + * Temporarily disable automatic binding because probing + * takes long time and we are better off doing it in kgameportd + */ + drv->ignore = 1; + + error = driver_register(&drv->driver); + if (error) { + printk(KERN_ERR + "gameport: driver_register() failed for %s, error: %d\n", + drv->driver.name, error); + return error; + } + + /* + * Reset ignore flag and let kgameportd bind the driver to free ports + */ + drv->ignore = 0; + error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); + if (error) { + driver_unregister(&drv->driver); + return error; + } + + return 0; } void gameport_unregister_driver(struct gameport_driver *drv) @@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv) struct gameport *gameport; mutex_lock(&gameport_mutex); + drv->ignore = 1; /* so gameport_find_driver ignores it */ + gameport_remove_pending_events(drv); start_over: list_for_each_entry(gameport, &gameport_list, node) { @@ -729,6 +774,7 @@ start_over: } driver_unregister(&drv->driver); + mutex_unlock(&gameport_mutex); } diff --git a/include/linux/gameport.h b/include/linux/gameport.h index f64e29c0ef3..5126125afd4 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -146,10 +146,11 @@ static inline void gameport_unpin_driver(struct gameport *gameport) mutex_unlock(&gameport->drv_mutex); } -void __gameport_register_driver(struct gameport_driver *drv, struct module *owner); -static inline void gameport_register_driver(struct gameport_driver *drv) +int __gameport_register_driver(struct gameport_driver *drv, + struct module *owner, const char *mod_name); +static inline int gameport_register_driver(struct gameport_driver *drv) { - __gameport_register_driver(drv, THIS_MODULE); + return __gameport_register_driver(drv, THIS_MODULE, KBUILD_MODNAME); } void gameport_unregister_driver(struct gameport_driver *drv); -- GitLab From 2547203d583cc267b98f518d5d93e3a0469d8f62 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 6 Jun 2008 01:33:37 -0400 Subject: [PATCH 0199/5416] Input: gameport - check return value of gameport_register_driver() Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/a3d.c | 3 +-- drivers/input/joystick/adi.c | 3 +-- drivers/input/joystick/analog.c | 4 +--- drivers/input/joystick/cobra.c | 3 +-- drivers/input/joystick/gf2k.c | 3 +-- drivers/input/joystick/grip.c | 3 +-- drivers/input/joystick/grip_mp.c | 3 +-- drivers/input/joystick/guillemot.c | 3 +-- drivers/input/joystick/interact.c | 3 +-- drivers/input/joystick/joydump.c | 3 +-- drivers/input/joystick/sidewinder.c | 3 +-- drivers/input/joystick/tmdc.c | 3 +-- 12 files changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 92498d470b1..6489f4010c4 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = { static int __init a3d_init(void) { - gameport_register_driver(&a3d_drv); - return 0; + return gameport_register_driver(&a3d_drv); } static void __exit a3d_exit(void) diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index d1ca8a14950..89c4c084d4a 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = { static int __init adi_init(void) { - gameport_register_driver(&adi_drv); - return 0; + return gameport_register_driver(&adi_drv); } static void __exit adi_exit(void) diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 708c5ae13b2..356b3a25efa 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = { static int __init analog_init(void) { analog_parse_options(); - gameport_register_driver(&analog_drv); - - return 0; + return gameport_register_driver(&analog_drv); } static void __exit analog_exit(void) diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 639b975a8ed..3497b87c3d0 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = { static int __init cobra_init(void) { - gameport_register_driver(&cobra_drv); - return 0; + return gameport_register_driver(&cobra_drv); } static void __exit cobra_exit(void) diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index cb6eef1f2d9..67c207f5b1a 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = { static int __init gf2k_init(void) { - gameport_register_driver(&gf2k_drv); - return 0; + return gameport_register_driver(&gf2k_drv); } static void __exit gf2k_exit(void) diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 684e07cfccc..fc55899ba6c 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = { static int __init grip_init(void) { - gameport_register_driver(&grip_drv); - return 0; + return gameport_register_driver(&grip_drv); } static void __exit grip_exit(void) diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 8279481b16e..2d47baf4776 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = { static int __init grip_init(void) { - gameport_register_driver(&grip_drv); - return 0; + return gameport_register_driver(&grip_drv); } static void __exit grip_exit(void) diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 25ec3fad9f2..4058d4b272f 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = { static int __init guillemot_init(void) { - gameport_register_driver(&guillemot_drv); - return 0; + return gameport_register_driver(&guillemot_drv); } static void __exit guillemot_exit(void) diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 8c3290b6820..2478289aeee 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = { static int __init interact_init(void) { - gameport_register_driver(&interact_drv); - return 0; + return gameport_register_driver(&interact_drv); } static void __exit interact_exit(void) diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index 2a1b82c8b31..cd894a0564a 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c @@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = { static int __init joydump_init(void) { - gameport_register_driver(&joydump_drv); - return 0; + return gameport_register_driver(&joydump_drv); } static void __exit joydump_exit(void) diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 7b4865fdee5..ca13a6bec33 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = { static int __init sw_init(void) { - gameport_register_driver(&sw_drv); - return 0; + return gameport_register_driver(&sw_drv); } static void __exit sw_exit(void) diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 60c37bcb938..d6c60980711 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = { static int __init tmdc_init(void) { - gameport_register_driver(&tmdc_drv); - return 0; + return gameport_register_driver(&tmdc_drv); } static void __exit tmdc_exit(void) -- GitLab From 8c4b3c29329eb7ffded3023e6d65bc415cb4e215 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 6 Jun 2008 01:33:51 -0400 Subject: [PATCH 0200/5416] Input: gameport - mark gameport_register_driver() __must_check Signed-off-by: Dmitry Torokhov --- include/linux/gameport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/gameport.h b/include/linux/gameport.h index 5126125afd4..0cd825f7363 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -148,7 +148,7 @@ static inline void gameport_unpin_driver(struct gameport *gameport) int __gameport_register_driver(struct gameport_driver *drv, struct module *owner, const char *mod_name); -static inline int gameport_register_driver(struct gameport_driver *drv) +static inline int __must_check gameport_register_driver(struct gameport_driver *drv) { return __gameport_register_driver(drv, THIS_MODULE, KBUILD_MODNAME); } -- GitLab From 1971b9d56fce9d8903e623b953c5e2fffe3a878e Mon Sep 17 00:00:00 2001 From: Ville Syrjala Date: Thu, 3 Jul 2008 10:45:37 -0400 Subject: [PATCH 0201/5416] Input: ati_remote2 - add loadable keymap support Support for loadable keymaps. The driver now supports individual keymaps for each of the five modes (AUX1-AUX4 and PC) of the remote. To achieve this the keymap scancode is interpreted as a combination of the mode and actual button scancode. The original keycode patches were done by Peter Stokes but I modified it quite a lot. Signed-off-by: Ville Syrjala Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ati_remote2.c | 130 ++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 29 deletions(-) diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index a7fabafbd94..f4918b9bb94 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -1,8 +1,8 @@ /* * ati_remote2 - ATI/Philips USB RF remote driver * - * Copyright (C) 2005 Ville Syrjala - * Copyright (C) 2007 Peter Stokes + * Copyright (C) 2005-2008 Ville Syrjala + * Copyright (C) 2007-2008 Peter Stokes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -12,7 +12,7 @@ #include #define DRIVER_DESC "ATI/Philips USB RF remote driver" -#define DRIVER_VERSION "0.2" +#define DRIVER_VERSION "0.3" MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); @@ -27,7 +27,7 @@ MODULE_LICENSE("GPL"); * A remote's "channel" may be altered by pressing and holding the "PC" button for * approximately 3 seconds, after which the button will slowly flash the count of the * currently configured "channel", using the numeric keypad enter a number between 1 and - * 16 and then the "PC" button again, the button will slowly flash the count of the + * 16 and then press the "PC" button again, the button will slowly flash the count of the * newly configured "channel". */ @@ -45,9 +45,18 @@ static struct usb_device_id ati_remote2_id_table[] = { }; MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); -static struct { - int hw_code; - int key_code; +enum { + ATI_REMOTE2_AUX1, + ATI_REMOTE2_AUX2, + ATI_REMOTE2_AUX3, + ATI_REMOTE2_AUX4, + ATI_REMOTE2_PC, + ATI_REMOTE2_MODES, +}; + +static const struct { + u8 hw_code; + u16 keycode; } ati_remote2_key_table[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, @@ -73,6 +82,7 @@ static struct { { 0x37, KEY_RECORD }, { 0x38, KEY_DVD }, { 0x39, KEY_TV }, + { 0x3f, KEY_PROG1 }, /* AUX1-AUX4 and PC */ { 0x54, KEY_MENU }, { 0x58, KEY_UP }, { 0x59, KEY_DOWN }, @@ -91,15 +101,9 @@ static struct { { 0xa9, BTN_LEFT }, { 0xaa, BTN_RIGHT }, { 0xbe, KEY_QUESTION }, - { 0xd5, KEY_FRONT }, { 0xd0, KEY_EDIT }, + { 0xd5, KEY_FRONT }, { 0xf9, KEY_INFO }, - { (0x00 << 8) | 0x3f, KEY_PROG1 }, - { (0x01 << 8) | 0x3f, KEY_PROG2 }, - { (0x02 << 8) | 0x3f, KEY_PROG3 }, - { (0x03 << 8) | 0x3f, KEY_PROG4 }, - { (0x04 << 8) | 0x3f, KEY_PC }, - { 0, KEY_RESERVED } }; struct ati_remote2 { @@ -117,6 +121,9 @@ struct ati_remote2 { char name[64]; char phys[64]; + + /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */ + u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; }; static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); @@ -172,7 +179,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) mode = data[0] & 0x0F; - if (mode > 4) { + if (mode > ATI_REMOTE2_PC) { dev_err(&ar2->intf[0]->dev, "Unknown mode byte (%02x %02x %02x %02x)\n", data[3], data[2], data[1], data[0]); @@ -191,7 +198,7 @@ static int ati_remote2_lookup(unsigned int hw_code) { int i; - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) + for (i = 0; i < ARRAY_SIZE(ati_remote2_key_table); i++) if (ati_remote2_key_table[i].hw_code == hw_code) return i; @@ -211,7 +218,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) mode = data[0] & 0x0F; - if (mode > 4) { + if (mode > ATI_REMOTE2_PC) { dev_err(&ar2->intf[1]->dev, "Unknown mode byte (%02x %02x %02x %02x)\n", data[3], data[2], data[1], data[0]); @@ -219,10 +226,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) } hw_code = data[2]; - /* - * Mode keys (AUX1-AUX4, PC) all generate the same code byte. - * Use the mode byte to figure out which one was pressed. - */ if (hw_code == 0x3f) { /* * For some incomprehensible reason the mouse pad generates @@ -236,8 +239,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) if (data[1] == 0) ar2->mode = mode; - - hw_code |= mode << 8; } if (!((1 << mode) & mode_mask)) @@ -260,8 +261,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) case 2: /* repeat */ /* No repeat for mouse buttons. */ - if (ati_remote2_key_table[index].key_code == BTN_LEFT || - ati_remote2_key_table[index].key_code == BTN_RIGHT) + if (ar2->keycode[mode][index] == BTN_LEFT || + ar2->keycode[mode][index] == BTN_RIGHT) return; if (!time_after_eq(jiffies, ar2->jiffies)) @@ -276,7 +277,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) return; } - input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); + input_event(idev, EV_KEY, ar2->keycode[mode][index], data[1]); input_sync(idev); } @@ -334,10 +335,60 @@ static void ati_remote2_complete_key(struct urb *urb) "%s(): usb_submit_urb() = %d\n", __func__, r); } +static int ati_remote2_getkeycode(struct input_dev *idev, + int scancode, int *keycode) +{ + struct ati_remote2 *ar2 = input_get_drvdata(idev); + int index, mode; + + mode = scancode >> 8; + if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) + return -EINVAL; + + index = ati_remote2_lookup(scancode & 0xFF); + if (index < 0) + return -EINVAL; + + *keycode = ar2->keycode[mode][index]; + return 0; +} + +static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) +{ + struct ati_remote2 *ar2 = input_get_drvdata(idev); + int index, mode, old_keycode; + + mode = scancode >> 8; + if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) + return -EINVAL; + + index = ati_remote2_lookup(scancode & 0xFF); + if (index < 0) + return -EINVAL; + + if (keycode < KEY_RESERVED || keycode > KEY_MAX) + return -EINVAL; + + old_keycode = ar2->keycode[mode][index]; + ar2->keycode[mode][index] = keycode; + set_bit(keycode, idev->keybit); + + for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { + for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { + if (ar2->keycode[mode][index] == old_keycode) + return 0; + } + } + + clear_bit(old_keycode, idev->keybit); + + return 0; +} + static int ati_remote2_input_init(struct ati_remote2 *ar2) { struct input_dev *idev; - int i, retval; + int index, mode, retval; idev = input_allocate_device(); if (!idev) @@ -350,8 +401,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - set_bit(ati_remote2_key_table[i].key_code, idev->keybit); + + for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { + for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { + ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; + set_bit(ar2->keycode[mode][index], idev->keybit); + } + } + + /* AUX1-AUX4 and PC generate the same scancode. */ + index = ati_remote2_lookup(0x3f); + ar2->keycode[ATI_REMOTE2_AUX1][index] = KEY_PROG1; + ar2->keycode[ATI_REMOTE2_AUX2][index] = KEY_PROG2; + ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; + ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; + ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; + set_bit(KEY_PROG1, idev->keybit); + set_bit(KEY_PROG2, idev->keybit); + set_bit(KEY_PROG3, idev->keybit); + set_bit(KEY_PROG4, idev->keybit); + set_bit(KEY_PC, idev->keybit); idev->rep[REP_DELAY] = 250; idev->rep[REP_PERIOD] = 33; @@ -359,6 +428,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) idev->open = ati_remote2_open; idev->close = ati_remote2_close; + idev->getkeycode = ati_remote2_getkeycode; + idev->setkeycode = ati_remote2_setkeycode; + idev->name = ar2->name; idev->phys = ar2->phys; -- GitLab From d6505ab9cd5672f99adeba86696499c2651a6e73 Mon Sep 17 00:00:00 2001 From: Ville Syrjala Date: Thu, 3 Jul 2008 10:45:37 -0400 Subject: [PATCH 0202/5416] Input: ati_remote2 - add autosuspend support Signed-off-by: Ville Syrjala Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ati_remote2.c | 133 +++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 6 deletions(-) diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index f4918b9bb94..3c9988dc0e9 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -45,6 +45,13 @@ static struct usb_device_id ati_remote2_id_table[] = { }; MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); +static DEFINE_MUTEX(ati_remote2_mutex); + +enum { + ATI_REMOTE2_OPENED = 0x1, + ATI_REMOTE2_SUSPENDED = 0x2, +}; + enum { ATI_REMOTE2_AUX1, ATI_REMOTE2_AUX2, @@ -124,46 +131,103 @@ struct ati_remote2 { /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */ u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; + + unsigned int flags; }; static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); static void ati_remote2_disconnect(struct usb_interface *interface); +static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); +static int ati_remote2_resume(struct usb_interface *interface); static struct usb_driver ati_remote2_driver = { .name = "ati_remote2", .probe = ati_remote2_probe, .disconnect = ati_remote2_disconnect, .id_table = ati_remote2_id_table, + .suspend = ati_remote2_suspend, + .resume = ati_remote2_resume, + .supports_autosuspend = 1, }; -static int ati_remote2_open(struct input_dev *idev) +static int ati_remote2_submit_urbs(struct ati_remote2 *ar2) { - struct ati_remote2 *ar2 = input_get_drvdata(idev); int r; r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); if (r) { dev_err(&ar2->intf[0]->dev, - "%s: usb_submit_urb() = %d\n", __func__, r); + "%s(): usb_submit_urb() = %d\n", __func__, r); return r; } r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); if (r) { usb_kill_urb(ar2->urb[0]); dev_err(&ar2->intf[1]->dev, - "%s: usb_submit_urb() = %d\n", __func__, r); + "%s(): usb_submit_urb() = %d\n", __func__, r); return r; } return 0; } +static void ati_remote2_kill_urbs(struct ati_remote2 *ar2) +{ + usb_kill_urb(ar2->urb[1]); + usb_kill_urb(ar2->urb[0]); +} + +static int ati_remote2_open(struct input_dev *idev) +{ + struct ati_remote2 *ar2 = input_get_drvdata(idev); + int r; + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + r = usb_autopm_get_interface(ar2->intf[0]); + if (r) { + dev_err(&ar2->intf[0]->dev, + "%s(): usb_autopm_get_interface() = %d\n", __func__, r); + goto fail1; + } + + mutex_lock(&ati_remote2_mutex); + + if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) { + r = ati_remote2_submit_urbs(ar2); + if (r) + goto fail2; + } + + ar2->flags |= ATI_REMOTE2_OPENED; + + mutex_unlock(&ati_remote2_mutex); + + usb_autopm_put_interface(ar2->intf[0]); + + return 0; + + fail2: + mutex_unlock(&ati_remote2_mutex); + usb_autopm_put_interface(ar2->intf[0]); + fail1: + return r; +} + static void ati_remote2_close(struct input_dev *idev) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - usb_kill_urb(ar2->urb[0]); - usb_kill_urb(ar2->urb[1]); + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + mutex_lock(&ati_remote2_mutex); + + if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) + ati_remote2_kill_urbs(ar2); + + ar2->flags &= ~ATI_REMOTE2_OPENED; + + mutex_unlock(&ati_remote2_mutex); } static void ati_remote2_input_mouse(struct ati_remote2 *ar2) @@ -288,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) switch (urb->status) { case 0: + usb_mark_last_busy(ar2->udev); ati_remote2_input_mouse(ar2); break; case -ENOENT: @@ -298,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) "%s(): urb status = %d\n", __func__, urb->status); return; default: + usb_mark_last_busy(ar2->udev); dev_err(&ar2->intf[0]->dev, "%s(): urb status = %d\n", __func__, urb->status); } @@ -315,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb) switch (urb->status) { case 0: + usb_mark_last_busy(ar2->udev); ati_remote2_input_key(ar2); break; case -ENOENT: @@ -325,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb) "%s(): urb status = %d\n", __func__, urb->status); return; default: + usb_mark_last_busy(ar2->udev); dev_err(&ar2->intf[1]->dev, "%s(): urb status = %d\n", __func__, urb->status); } @@ -562,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d usb_set_intfdata(interface, ar2); + interface->needs_remote_wakeup = 1; + return 0; fail2: @@ -594,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface) kfree(ar2); } +static int ati_remote2_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct ati_remote2 *ar2; + struct usb_host_interface *alt = interface->cur_altsetting; + + if (alt->desc.bInterfaceNumber) + return 0; + + ar2 = usb_get_intfdata(interface); + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + mutex_lock(&ati_remote2_mutex); + + if (ar2->flags & ATI_REMOTE2_OPENED) + ati_remote2_kill_urbs(ar2); + + ar2->flags |= ATI_REMOTE2_SUSPENDED; + + mutex_unlock(&ati_remote2_mutex); + + return 0; +} + +static int ati_remote2_resume(struct usb_interface *interface) +{ + struct ati_remote2 *ar2; + struct usb_host_interface *alt = interface->cur_altsetting; + int r = 0; + + if (alt->desc.bInterfaceNumber) + return 0; + + ar2 = usb_get_intfdata(interface); + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + mutex_lock(&ati_remote2_mutex); + + if (ar2->flags & ATI_REMOTE2_OPENED) + r = ati_remote2_submit_urbs(ar2); + + if (!r) + ar2->flags &= ~ATI_REMOTE2_SUSPENDED; + + mutex_unlock(&ati_remote2_mutex); + + return r; +} + static int __init ati_remote2_init(void) { int r; -- GitLab From 03bac96fae0efdb25e2059e5accbe4f3ee6328dd Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 23 Jun 2008 10:47:34 -0400 Subject: [PATCH 0203/5416] Input: expand keycode space Expand the number of potential key codes from 512 to 768 since people are coming up with more and more keys. Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 2 +- include/linux/mod_devicetable.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/input.h b/include/linux/input.h index a5802c9c81a..7fae1dee356 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -579,7 +579,7 @@ struct input_absinfo { /* We avoid low common keys in module aliases so they don't get huge. */ #define KEY_MIN_INTERESTING KEY_MUTE -#define KEY_MAX 0x1ff +#define KEY_MAX 0x2ff #define KEY_CNT (KEY_MAX+1) /* diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index c4db5827963..0dddfa44ec1 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -274,7 +274,7 @@ struct pcmcia_device_id { /* Input */ #define INPUT_DEVICE_ID_EV_MAX 0x1f #define INPUT_DEVICE_ID_KEY_MIN_INTERESTING 0x71 -#define INPUT_DEVICE_ID_KEY_MAX 0x1ff +#define INPUT_DEVICE_ID_KEY_MAX 0x2ff #define INPUT_DEVICE_ID_REL_MAX 0x0f #define INPUT_DEVICE_ID_ABS_MAX 0x3f #define INPUT_DEVICE_ID_MSC_MAX 0x07 -- GitLab From 5a599a15182ed48e5bf54111feb3b21e425e194d Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Mon, 23 Jun 2008 10:47:53 -0400 Subject: [PATCH 0204/5416] Input: add keycodes for remote controls/phone keypads The new keys are separate from normal numeric keys and standard numeric keypads. The userspace should not attempt to apply modifiers like shift and NumLock to these so tey work properly regardless of the language mapping used. Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/input.h b/include/linux/input.h index 7fae1dee356..b86fb5581ce 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -577,6 +577,19 @@ struct input_absinfo { #define KEY_BRL_DOT9 0x1f9 #define KEY_BRL_DOT10 0x1fa +#define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */ +#define KEY_NUMERIC_1 0x201 /* and other keypads */ +#define KEY_NUMERIC_2 0x202 +#define KEY_NUMERIC_3 0x203 +#define KEY_NUMERIC_4 0x204 +#define KEY_NUMERIC_5 0x205 +#define KEY_NUMERIC_6 0x206 +#define KEY_NUMERIC_7 0x207 +#define KEY_NUMERIC_8 0x208 +#define KEY_NUMERIC_9 0x209 +#define KEY_NUMERIC_STAR 0x20a +#define KEY_NUMERIC_POUND 0x20b + /* We avoid low common keys in module aliases so they don't get huge. */ #define KEY_MIN_INTERESTING KEY_MUTE #define KEY_MAX 0x2ff -- GitLab From a648bf4632628c787abb0514277f2a231fca39ca Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:18 -0700 Subject: [PATCH 0205/5416] x86, xsave: xsave cpuid feature bits Add xsave CPU feature bits. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/feature_names.c | 2 +- include/asm-x86/cpufeature.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index 0bf4d37a048..74154722565 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -46,7 +46,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = { "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "xsave", NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 42afe9ca3a3..c76b3f67cb3 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -92,6 +92,7 @@ #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ #define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */ +#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ @@ -191,6 +192,7 @@ extern const char * const x86_power_flags[32]; #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) +#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 -- GitLab From dc1e35c6e95e8923cf1d3510438b63c600fee1e2 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:19 -0700 Subject: [PATCH 0206/5416] x86, xsave: enable xsave/xrstor on cpus with xsave support Enables xsave/xrstor by turning on cr4.osxsave on cpu's which have the xsave support. For now, features that OS supports/enabled are FP and SSE. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/cpu/common.c | 8 +++ arch/x86/kernel/i387.c | 12 +++++ arch/x86/kernel/traps_32.c | 1 - arch/x86/kernel/traps_64.c | 4 -- arch/x86/kernel/xsave.c | 87 +++++++++++++++++++++++++++++++ include/asm-x86/i387.h | 1 + include/asm-x86/processor-flags.h | 1 + include/asm-x86/processor.h | 12 +++++ include/asm-x86/xsave.h | 26 +++++++++ 10 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 arch/x86/kernel/xsave.c create mode 100644 include/asm-x86/xsave.h diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a07ec14f331..d6ea91abaeb 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -38,7 +38,7 @@ obj-y += tsc.o io_delay.o rtc.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-y += process.o -obj-y += i387.o +obj-y += i387.o xsave.o obj-y += ptrace.o obj-y += ds.o obj-$(CONFIG_X86_32) += tls.o diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa3..fabbcb7020f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -712,6 +712,14 @@ void __cpuinit cpu_init(void) current_thread_info()->status = 0; clear_used_math(); mxcsr_feature_mask_init(); + + /* + * Boot processor to setup the FP and extended state context info. + */ + if (!smp_processor_id()) + init_thread_xstate(); + + xsave_init(); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index eb9ddd8efb8..e22a9a9dce8 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -61,6 +61,11 @@ void __init init_thread_xstate(void) return; } + if (cpu_has_xsave) { + xsave_cntxt_init(); + return; + } + if (cpu_has_fxsr) xstate_size = sizeof(struct i387_fxsave_struct); #ifdef CONFIG_X86_32 @@ -83,6 +88,13 @@ void __cpuinit fpu_init(void) write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */ + /* + * Boot processor to setup the FP and extended state context info. + */ + if (!smp_processor_id()) + init_thread_xstate(); + xsave_init(); + mxcsr_feature_mask_init(); /* clean state in init */ current_thread_info()->status = 0; diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 03df8e45e5a..da5a5964fcc 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -1228,7 +1228,6 @@ void __init trap_init(void) set_bit(SYSCALL_VECTOR, used_vectors); - init_thread_xstate(); /* * Should be a barrier for any external CPU state: */ diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 513caaca711..3580a7938a2 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -1172,10 +1172,6 @@ void __init trap_init(void) #ifdef CONFIG_IA32_EMULATION set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall); #endif - /* - * initialize the per thread extended state: - */ - init_thread_xstate(); /* * Should be a barrier for any external CPU state: */ diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c new file mode 100644 index 00000000000..c68b7c4ca24 --- /dev/null +++ b/arch/x86/kernel/xsave.c @@ -0,0 +1,87 @@ +/* + * xsave/xrstor support. + * + * Author: Suresh Siddha + */ +#include +#include +#include + +/* + * Supported feature mask by the CPU and the kernel. + */ +unsigned int pcntxt_hmask, pcntxt_lmask; + +/* + * Represents init state for the supported extended state. + */ +struct xsave_struct *init_xstate_buf; + +/* + * Enable the extended processor state save/restore feature + */ +void __cpuinit xsave_init(void) +{ + if (!cpu_has_xsave) + return; + + set_in_cr4(X86_CR4_OSXSAVE); + + /* + * Enable all the features that the HW is capable of + * and the Linux kernel is aware of. + * + * xsetbv(); + */ + asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0), + "a" (pcntxt_lmask), "d" (pcntxt_hmask)); +} + +/* + * setup the xstate image representing the init state + */ +void setup_xstate_init(void) +{ + init_xstate_buf = alloc_bootmem(xstate_size); + init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; +} + +/* + * Enable and initialize the xsave feature. + */ +void __init xsave_cntxt_init(void) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + + pcntxt_lmask = eax; + pcntxt_hmask = edx; + + if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) { + printk(KERN_ERR "FP/SSE not shown under xsave features %x\n", + pcntxt_lmask); + BUG(); + } + + /* + * for now OS knows only about FP/SSE + */ + pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK; + pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK; + + xsave_init(); + + /* + * Recompute the context size for enabled features + */ + cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + + xstate_size = ebx; + + setup_xstate_init(); + + printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " + "cntxt size 0x%x\n", + (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size); +} diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 3958de6aad0..6a664789667 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -18,6 +18,7 @@ #include #include #include +#include extern void fpu_init(void); extern void mxcsr_feature_mask_init(void); diff --git a/include/asm-x86/processor-flags.h b/include/asm-x86/processor-flags.h index 5dd79774f69..dc5f0712f9f 100644 --- a/include/asm-x86/processor-flags.h +++ b/include/asm-x86/processor-flags.h @@ -59,6 +59,7 @@ #define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */ #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ #define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */ +#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */ /* * x86-64 Task Priority Register, CR8 diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index d60b4d81feb..d7c0221c027 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -346,6 +346,18 @@ struct i387_soft_struct { u32 entry_eip; }; +struct xsave_hdr_struct { + u64 xstate_bv; + u64 reserved1[2]; + u64 reserved2[5]; +} __attribute__((packed)); + +struct xsave_struct { + struct i387_fxsave_struct i387; + struct xsave_hdr_struct xsave_hdr; + /* new processor state extensions will go here */ +} __attribute__ ((packed, aligned (64))); + union thread_xstate { struct i387_fsave_struct fsave; struct i387_fxsave_struct fxsave; diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h new file mode 100644 index 00000000000..6d70e62c6bd --- /dev/null +++ b/include/asm-x86/xsave.h @@ -0,0 +1,26 @@ +#ifndef __ASM_X86_XSAVE_H +#define __ASM_X86_XSAVE_H + +#include +#include + +#define XSTATE_FP 0x1 +#define XSTATE_SSE 0x2 + +#define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE) + +#define FXSAVE_SIZE 512 + +/* + * These are the features that the OS can handle currently. + */ +#define XCNTXT_LMASK (XSTATE_FP | XSTATE_SSE) +#define XCNTXT_HMASK 0x0 + +extern unsigned int xstate_size, pcntxt_hmask, pcntxt_lmask; +extern struct xsave_struct *init_xstate_buf; + +extern void xsave_cntxt_init(void); +extern void xsave_init(void); + +#endif -- GitLab From b359e8a434cc3d09847010fc4aeccf48d69740e4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:20 -0700 Subject: [PATCH 0207/5416] x86, xsave: context switch support using xsave/xrstor Uses xsave/xrstor (instead of traditional fxsave/fxrstor) in context switch when available. Introduces TS_XSAVE flag, which determine the need to use xsave/xrstor instructions during context switch instead of the legacy fxsave/fxrstor instructions. Thread-synchronous status word is already in L1 cache during this code patch and thus minimizes the performance penality compared to (cpu_has_xsave) checks. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 5 ++- arch/x86/kernel/i387.c | 5 ++- arch/x86/kernel/traps_64.c | 2 +- include/asm-x86/i387.h | 64 ++++++++++++++++++++++++++++++++--- include/asm-x86/processor.h | 1 + include/asm-x86/thread_info.h | 1 + include/asm-x86/xsave.h | 35 ++++++++++++++++++- 7 files changed, 104 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fabbcb7020f..6c2b9e756db 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -709,7 +709,10 @@ void __cpuinit cpu_init(void) /* * Force FPU initialization: */ - current_thread_info()->status = 0; + if (cpu_has_xsave) + current_thread_info()->status = TS_XSAVE; + else + current_thread_info()->status = 0; clear_used_math(); mxcsr_feature_mask_init(); diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index e22a9a9dce8..b778e17e4b0 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -97,7 +97,10 @@ void __cpuinit fpu_init(void) mxcsr_feature_mask_init(); /* clean state in init */ - current_thread_info()->status = 0; + if (cpu_has_xsave) + current_thread_info()->status = TS_XSAVE; + else + current_thread_info()->status = 0; clear_used_math(); } #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3580a7938a2..38eb76156a4 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -1134,7 +1134,7 @@ asmlinkage void math_state_restore(void) /* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */ - if (unlikely(restore_fpu_checking(&me->thread.xstate->fxsave))) { + if (unlikely(restore_fpu_checking(me))) { stts(); force_sig(SIGSEGV, me); return; diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 6a664789667..a6d256f4ac8 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -36,6 +36,8 @@ extern int save_i387_ia32(struct _fpstate_ia32 __user *buf); extern int restore_i387_ia32(struct _fpstate_ia32 __user *buf); #endif +#define X87_FSW_ES (1 << 7) /* Exception Summary */ + #ifdef CONFIG_X86_64 /* Ignore delayed exceptions from user space */ @@ -46,7 +48,7 @@ static inline void tolerant_fwait(void) _ASM_EXTABLE(1b, 2b)); } -static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) +static inline int fxrstor_checking(struct i387_fxsave_struct *fx) { int err; @@ -66,15 +68,31 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) return err; } -#define X87_FSW_ES (1 << 7) /* Exception Summary */ +static inline int restore_fpu_checking(struct task_struct *tsk) +{ + if (task_thread_info(tsk)->status & TS_XSAVE) + return xrstor_checking(&tsk->thread.xstate->xsave); + else + return fxrstor_checking(&tsk->thread.xstate->fxsave); +} /* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed values. The kernel data segment can be sometimes 0 and sometimes new user value. Both should be ok. Use the PDA as safe address because it should be already in L1. */ -static inline void clear_fpu_state(struct i387_fxsave_struct *fx) +static inline void clear_fpu_state(struct task_struct *tsk) { + struct xsave_struct *xstate = &tsk->thread.xstate->xsave; + struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + + /* + * xsave header may indicate the init state of the FP. + */ + if ((task_thread_info(tsk)->status & TS_XSAVE) && + !(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) + return; + if (unlikely(fx->swd & X87_FSW_ES)) asm volatile("fnclex"); alternative_input(ASM_NOP8 ASM_NOP2, @@ -107,7 +125,7 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx) return err; } -static inline void __save_init_fpu(struct task_struct *tsk) +static inline void fxsave(struct task_struct *tsk) { /* Using "rex64; fxsave %0" is broken because, if the memory operand uses any extended registers for addressing, a second REX prefix @@ -132,7 +150,16 @@ static inline void __save_init_fpu(struct task_struct *tsk) : "=m" (tsk->thread.xstate->fxsave) : "cdaSDb" (&tsk->thread.xstate->fxsave)); #endif - clear_fpu_state(&tsk->thread.xstate->fxsave); +} + +static inline void __save_init_fpu(struct task_struct *tsk) +{ + if (task_thread_info(tsk)->status & TS_XSAVE) + xsave(tsk); + else + fxsave(tsk); + + clear_fpu_state(tsk); task_thread_info(tsk)->status &= ~TS_USEDFPU; } @@ -147,6 +174,10 @@ static inline void tolerant_fwait(void) static inline void restore_fpu(struct task_struct *tsk) { + if (task_thread_info(tsk)->status & TS_XSAVE) { + xrstor_checking(&tsk->thread.xstate->xsave); + return; + } /* * The "nop" is needed to make the instructions the same * length. @@ -172,6 +203,27 @@ static inline void restore_fpu(struct task_struct *tsk) */ static inline void __save_init_fpu(struct task_struct *tsk) { + if (task_thread_info(tsk)->status & TS_XSAVE) { + struct xsave_struct *xstate = &tsk->thread.xstate->xsave; + struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + + xsave(tsk); + + /* + * xsave header may indicate the init state of the FP. + */ + if (!(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) + goto end; + + if (unlikely(fx->swd & X87_FSW_ES)) + asm volatile("fnclex"); + + /* + * we can do a simple return here or be paranoid :) + */ + goto clear_state; + } + /* Use more nops than strictly needed in case the compiler varies code */ alternative_input( @@ -181,6 +233,7 @@ static inline void __save_init_fpu(struct task_struct *tsk) X86_FEATURE_FXSR, [fx] "m" (tsk->thread.xstate->fxsave), [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory"); +clear_state: /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed values. safe_address is a random variable that should be in L1 */ @@ -190,6 +243,7 @@ static inline void __save_init_fpu(struct task_struct *tsk) "fildl %[addr]", /* set F?P to defined value */ X86_FEATURE_FXSAVE_LEAK, [addr] "m" (safe_address)); +end: task_thread_info(tsk)->status &= ~TS_USEDFPU; } diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index d7c0221c027..77b7af6b573 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -362,6 +362,7 @@ union thread_xstate { struct i387_fsave_struct fsave; struct i387_fxsave_struct fxsave; struct i387_soft_struct soft; + struct xsave_struct xsave; }; #ifdef CONFIG_X86_64 diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h index e64be8863b7..30586f2ee55 100644 --- a/include/asm-x86/thread_info.h +++ b/include/asm-x86/thread_info.h @@ -239,6 +239,7 @@ static inline struct thread_info *stack_thread_info(void) #define TS_POLLING 0x0004 /* true if in idle loop and not sleeping */ #define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */ +#define TS_XSAVE 0x0010 /* Use xsave/xrstor */ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING) diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h index 6d70e62c6bd..e835a917ee1 100644 --- a/include/asm-x86/xsave.h +++ b/include/asm-x86/xsave.h @@ -17,10 +17,43 @@ #define XCNTXT_LMASK (XSTATE_FP | XSTATE_SSE) #define XCNTXT_HMASK 0x0 +#ifdef CONFIG_X86_64 +#define REX_PREFIX "0x48, " +#else +#define REX_PREFIX +#endif + extern unsigned int xstate_size, pcntxt_hmask, pcntxt_lmask; extern struct xsave_struct *init_xstate_buf; extern void xsave_cntxt_init(void); extern void xsave_init(void); - +extern int init_fpu(struct task_struct *child); + +static inline int xrstor_checking(struct xsave_struct *fx) +{ + int err; + + asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + _ASM_EXTABLE(1b, 3b) + : [err] "=r" (err) + : "D" (fx), "m" (*fx), "a" (-1), "d" (-1), "0" (0) + : "memory"); + + return err; +} + +static inline void xsave(struct task_struct *tsk) +{ + /* This, however, we can work around by forcing the compiler to select + an addressing mode that doesn't require extended registers. */ + __asm__ __volatile__(".byte " REX_PREFIX "0x0f,0xae,0x27" + : : "D" (&(tsk->thread.xstate->xsave)), + "a" (-1), "d"(-1) : "memory"); +} #endif -- GitLab From 3c1c7f101426cb2ecc79d817a8a65928965fc860 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:21 -0700 Subject: [PATCH 0208/5416] x86, xsave: dynamically allocate sigframes fpstate instead of static allocation dynamically allocate fpstate on the stack, instead of static allocation in the current sigframe layout on the user stack. This will allow the fpstate structure to grow in the future, which includes extended state information supporting xsave/xrstor. signal handlers will be able to access the fpstate pointer from the sigcontext structure asusual, with no change. For the non RT sigframe's (which are supported only for 32bit apps), current static fpstate layout in the sigframe will be unused(so that we don't change the extramask[] offset in the sigframe and thus prevent breaking app's which modify extramask[]). Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 24 ++++++++++++++++-------- arch/x86/kernel/i387.c | 2 ++ arch/x86/kernel/sigframe.h | 14 ++++++++++++-- arch/x86/kernel/signal_32.c | 18 +++++++++++++----- arch/x86/kernel/signal_64.c | 2 +- arch/x86/kernel/xsave.c | 4 ++++ include/asm-x86/i387.h | 2 ++ 7 files changed, 50 insertions(+), 16 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579..a05bf0fb741 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -179,9 +179,10 @@ struct sigframe u32 pretcode; int sig; struct sigcontext_ia32 sc; - struct _fpstate_ia32 fpstate; + struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */ unsigned int extramask[_COMPAT_NSIG_WORDS-1]; char retcode[8]; + /* fp state follows here */ }; struct rt_sigframe @@ -192,8 +193,8 @@ struct rt_sigframe u32 puc; compat_siginfo_t info; struct ucontext_ia32 uc; - struct _fpstate_ia32 fpstate; char retcode[8]; + /* fp state follows here */ }; #define COPY(x) { \ @@ -402,7 +403,8 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, * Determine which stack to use.. */ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) + size_t frame_size, + struct _fpstate_ia32 **fpstate) { unsigned long sp; @@ -421,6 +423,11 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, ka->sa.sa_restorer) sp = (unsigned long) ka->sa.sa_restorer; + if (used_math()) { + sp = sp - sig_xstate_ia32_size; + *fpstate = (struct _fpstate_ia32 *) sp; + } + sp -= frame_size; /* Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ @@ -434,6 +441,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, struct sigframe __user *frame; void __user *restorer; int err = 0; + struct _fpstate_ia32 __user *fpstate = NULL; /* copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -448,7 +456,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, 0, }; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -457,8 +465,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, if (err) goto give_sigsegv; - err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, - set->sig[0]); + err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) goto give_sigsegv; @@ -522,6 +529,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; void __user *restorer; int err = 0; + struct _fpstate_ia32 __user *fpstate = NULL; /* __copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -537,7 +545,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 0, }; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -556,7 +564,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index b778e17e4b0..51fb288a2c9 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -24,6 +24,7 @@ # define save_i387_ia32 save_i387 # define restore_i387_ia32 restore_i387 # define _fpstate_ia32 _fpstate +# define sig_xstate_ia32_size sig_xstate_size # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct #endif @@ -36,6 +37,7 @@ static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; unsigned int xstate_size; +unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32); static struct i387_fxsave_struct fx_scratch __cpuinitdata; void __cpuinit mxcsr_feature_mask_init(void) diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h index 72bbb519d2d..6dd7e2b70a4 100644 --- a/arch/x86/kernel/sigframe.h +++ b/arch/x86/kernel/sigframe.h @@ -3,9 +3,18 @@ struct sigframe { char __user *pretcode; int sig; struct sigcontext sc; - struct _fpstate fpstate; + /* + * fpstate is unused. fpstate is moved/allocated after + * retcode[] below. This movement allows to have the FP state and the + * future state extensions (xsave) stay together. + * And at the same time retaining the unused fpstate, prevents changing + * the offset of extramask[] in the sigframe and thus prevent any + * legacy application accessing/modifying it. + */ + struct _fpstate fpstate_unused; unsigned long extramask[_NSIG_WORDS-1]; char retcode[8]; + /* fp state follows here */ }; struct rt_sigframe { @@ -15,13 +24,14 @@ struct rt_sigframe { void __user *puc; struct siginfo info; struct ucontext uc; - struct _fpstate fpstate; char retcode[8]; + /* fp state follows here */ }; #else struct rt_sigframe { char __user *pretcode; struct ucontext uc; struct siginfo info; + /* fp state follows here */ }; #endif diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd893..19a7a5669b5 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -306,7 +306,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, * Determine which stack to use.. */ static inline void __user * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, + struct _fpstate **fpstate) { unsigned long sp; @@ -332,6 +333,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) sp = (unsigned long) ka->sa.sa_restorer; } + if (used_math()) { + sp = sp - sig_xstate_size; + *fpstate = (struct _fpstate *) sp; + } + sp -= frame_size; /* * Align the stack pointer according to the i386 ABI, @@ -350,8 +356,9 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, void __user *restorer; int err = 0; int usig; + struct _fpstate __user *fpstate = NULL; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -366,7 +373,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, if (err) goto give_sigsegv; - err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); + err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); if (err) goto give_sigsegv; @@ -427,8 +434,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer; int err = 0; int usig; + struct _fpstate __user *fpstate = NULL; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -453,7 +461,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ca316b5b742..0deab8eff33 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -281,7 +281,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct task_struct *me = current; if (used_math()) { - fp = get_stack(ka, regs, sizeof(struct _fpstate)); + fp = get_stack(ka, regs, sig_xstate_size); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index c68b7c4ca24..7ad169e3352 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -17,6 +17,10 @@ unsigned int pcntxt_hmask, pcntxt_lmask; */ struct xsave_struct *init_xstate_buf; +#ifdef CONFIG_X86_64 +unsigned int sig_xstate_size = sizeof(struct _fpstate); +#endif + /* * Enable the extended processor state save/restore feature */ diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index a6d256f4ac8..36dca8db166 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -20,6 +20,7 @@ #include #include +extern unsigned int sig_xstate_size; extern void fpu_init(void); extern void mxcsr_feature_mask_init(void); extern int init_fpu(struct task_struct *child); @@ -31,6 +32,7 @@ extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set; #ifdef CONFIG_IA32_EMULATION +extern unsigned int sig_xstate_ia32_size; struct _fpstate_ia32; extern int save_i387_ia32(struct _fpstate_ia32 __user *buf); extern int restore_i387_ia32(struct _fpstate_ia32 __user *buf); -- GitLab From ab5137015fed9b948fe835a2d99a4cfbd50a0c40 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:22 -0700 Subject: [PATCH 0209/5416] x86, xsave: reorganization of signal save/restore fpstate code layout move 64bit routines that saves/restores fpstate in/from user stack from signal_64.c to xsave.c restore_i387_xstate() now handles the condition when user passes NULL fpstate. Other misc changes for prepartion of xsave/xrstor sigcontext support. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 28 ++++--------- arch/x86/kernel/i387.c | 44 ++++++++++++++------ arch/x86/kernel/signal_32.c | 28 ++++--------- arch/x86/kernel/signal_64.c | 83 ++----------------------------------- arch/x86/kernel/xsave.c | 79 +++++++++++++++++++++++++++++++++++ include/asm-x86/i387.h | 13 +++--- 6 files changed, 134 insertions(+), 141 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index a05bf0fb741..c596eabbe98 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -216,7 +216,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, unsigned int *peax) { unsigned int tmpflags, gs, oldgs, err = 0; - struct _fpstate_ia32 __user *buf; + void __user *buf; u32 tmp; /* Always make any pending restarted system calls return -EINTR */ @@ -260,26 +260,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, err |= __get_user(tmp, &sc->fpstate); buf = compat_ptr(tmp); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387_ia32(buf); - } else { - struct task_struct *me = current; - - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate_ia32(buf); err |= __get_user(tmp, &sc->ax); *peax = tmp; return err; - -badframe: - return 1; } asmlinkage long sys32_sigreturn(struct pt_regs *regs) @@ -351,7 +337,7 @@ badframe: */ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, - struct _fpstate_ia32 __user *fpstate, + void __user *fpstate, struct pt_regs *regs, unsigned int mask) { int tmp, err = 0; @@ -382,7 +368,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, err |= __put_user((u32)regs->flags, &sc->flags); err |= __put_user((u32)regs->sp, &sc->sp_at_signal); - tmp = save_i387_ia32(fpstate); + tmp = save_i387_xstate_ia32(fpstate); if (tmp < 0) err = -EFAULT; else { @@ -404,7 +390,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, */ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, - struct _fpstate_ia32 **fpstate) + void **fpstate) { unsigned long sp; @@ -441,7 +427,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, struct sigframe __user *frame; void __user *restorer; int err = 0; - struct _fpstate_ia32 __user *fpstate = NULL; + void __user *fpstate = NULL; /* copy_to_user optimizes that into a single 8 byte store */ static const struct { @@ -529,7 +515,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; void __user *restorer; int err = 0; - struct _fpstate_ia32 __user *fpstate = NULL; + void __user *fpstate = NULL; /* __copy_to_user optimizes that into a single 8 byte store */ static const struct { diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 51fb288a2c9..7daf3a011dd 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -21,9 +21,10 @@ # include # include #else -# define save_i387_ia32 save_i387 -# define restore_i387_ia32 restore_i387 +# define save_i387_xstate_ia32 save_i387_xstate +# define restore_i387_xstate_ia32 restore_i387_xstate # define _fpstate_ia32 _fpstate +# define _xstate_ia32 _xstate # define sig_xstate_ia32_size sig_xstate_size # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct @@ -424,7 +425,6 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) struct task_struct *tsk = current; struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; - unlazy_fpu(tsk); fp->status = fp->swd; if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) return -1; @@ -438,8 +438,6 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) struct user_i387_ia32_struct env; int err = 0; - unlazy_fpu(tsk); - convert_from_fxsr(&env, tsk); if (__copy_to_user(buf, &env, sizeof(env))) return -1; @@ -455,10 +453,16 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) return 1; } -int save_i387_ia32(struct _fpstate_ia32 __user *buf) +int save_i387_xstate_ia32(void __user *buf) { + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; + struct task_struct *tsk = current; + if (!used_math()) return 0; + + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size)) + return -EACCES; /* * This will cause a "finit" to be triggered by the next * attempted FPU operation by the 'current' process. @@ -468,13 +472,15 @@ int save_i387_ia32(struct _fpstate_ia32 __user *buf) if (!HAVE_HWFP) { return fpregs_soft_get(current, NULL, 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) ? -1 : 1; + NULL, fp) ? -1 : 1; } + unlazy_fpu(tsk); + if (cpu_has_fxsr) - return save_i387_fxsave(buf); + return save_i387_fxsave(fp); else - return save_i387_fsave(buf); + return save_i387_fsave(fp); } static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) @@ -502,14 +508,26 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) return 0; } -int restore_i387_ia32(struct _fpstate_ia32 __user *buf) +int restore_i387_xstate_ia32(void __user *buf) { int err; struct task_struct *tsk = current; + struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; if (HAVE_HWFP) clear_fpu(tsk); + if (!buf) { + if (used_math()) { + clear_fpu(tsk); + clear_used_math(); + } + + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size)) + return -EACCES; + if (!used_math()) { err = init_fpu(tsk); if (err) @@ -518,13 +536,13 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) if (HAVE_HWFP) { if (cpu_has_fxsr) - err = restore_i387_fxsave(buf); + err = restore_i387_fxsave(fp); else - err = restore_i387_fsave(buf); + err = restore_i387_fsave(fp); } else { err = fpregs_soft_set(current, NULL, 0, sizeof(struct user_i387_ia32_struct), - NULL, buf) != 0; + NULL, fp) != 0; } set_used_math(); diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 19a7a5669b5..690cc616ac0 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -159,28 +159,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user *buf; + void __user *buf; err |= __get_user(buf, &sc->fpstate); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); - } else { - struct task_struct *me = current; - - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate(buf); } err |= __get_user(*pax, &sc->ax); return err; - -badframe: - return 1; } asmlinkage unsigned long sys_sigreturn(unsigned long __unused) @@ -262,7 +248,7 @@ badframe: * Set up a signal frame. */ static int -setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, +setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, struct pt_regs *regs, unsigned long mask) { int tmp, err = 0; @@ -289,7 +275,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, err |= __put_user(regs->sp, &sc->sp_at_signal); err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); - tmp = save_i387(fpstate); + tmp = save_i387_xstate(fpstate); if (tmp < 0) err = 1; else @@ -307,7 +293,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, */ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, - struct _fpstate **fpstate) + void **fpstate) { unsigned long sp; @@ -356,7 +342,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, void __user *restorer; int err = 0; int usig; - struct _fpstate __user *fpstate = NULL; + void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); @@ -434,7 +420,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer; int err = 0; int usig; - struct _fpstate __user *fpstate = NULL; + void __user *fpstate = NULL; frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 0deab8eff33..ddf6123a55c 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -53,69 +53,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, return do_sigaltstack(uss, uoss, regs->sp); } -/* - * Signal frame handlers. - */ - -static inline int save_i387(struct _fpstate __user *buf) -{ - struct task_struct *tsk = current; - int err = 0; - - BUILD_BUG_ON(sizeof(struct user_i387_struct) != - sizeof(tsk->thread.xstate->fxsave)); - - if ((unsigned long)buf % 16) - printk("save_i387: bad fpstate %p\n", buf); - - if (!used_math()) - return 0; - clear_used_math(); /* trigger finit */ - if (task_thread_info(tsk)->status & TS_USEDFPU) { - err = save_i387_checking((struct i387_fxsave_struct __user *) - buf); - if (err) - return err; - task_thread_info(tsk)->status &= ~TS_USEDFPU; - stts(); - } else { - if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, - sizeof(struct i387_fxsave_struct))) - return -1; - } - return 1; -} - -/* - * This restores directly out of user space. Exceptions are handled. - */ -static inline int restore_i387(struct _fpstate __user *buf) -{ - struct task_struct *tsk = current; - int err; - - if (!used_math()) { - err = init_fpu(tsk); - if (err) - return err; - } - - if (!(task_thread_info(current)->status & TS_USEDFPU)) { - clts(); - task_thread_info(current)->status |= TS_USEDFPU; - } - err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf); - if (unlikely(err)) { - /* - * Encountered an error while doing the restore from the - * user buffer, clear the fpu state. - */ - clear_fpu(tsk); - clear_used_math(); - } - return err; -} - /* * Do a signal return; undo the signal stack. */ @@ -160,25 +97,11 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, { struct _fpstate __user * buf; err |= __get_user(buf, &sc->fpstate); - - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); - } else { - struct task_struct *me = current; - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } - } + err |= restore_i387_xstate(buf); } err |= __get_user(*pax, &sc->ax); return err; - -badframe: - return 1; } asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) @@ -276,7 +199,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; + void __user *fp = NULL; int err = 0; struct task_struct *me = current; @@ -288,7 +211,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; - if (save_i387(fp) < 0) + if (save_i387_xstate(fp) < 0) err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 7ad169e3352..608e72d7ca6 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -12,6 +12,85 @@ */ unsigned int pcntxt_hmask, pcntxt_lmask; +#ifdef CONFIG_X86_64 +/* + * Signal frame handlers. + */ + +int save_i387_xstate(void __user *buf) +{ + struct task_struct *tsk = current; + int err = 0; + + if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) + return -EACCES; + + BUILD_BUG_ON(sizeof(struct user_i387_struct) != + sizeof(tsk->thread.xstate->fxsave)); + + if ((unsigned long)buf % 16) + printk("save_i387_xstate: bad fpstate %p\n", buf); + + if (!used_math()) + return 0; + clear_used_math(); /* trigger finit */ + if (task_thread_info(tsk)->status & TS_USEDFPU) { + err = save_i387_checking((struct i387_fxsave_struct __user *) + buf); + if (err) + return err; + task_thread_info(tsk)->status &= ~TS_USEDFPU; + stts(); + } else { + if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, + xstate_size)) + return -1; + } + return 1; +} + +/* + * This restores directly out of user space. Exceptions are handled. + */ +int restore_i387_xstate(void __user *buf) +{ + struct task_struct *tsk = current; + int err; + + if (!buf) { + if (used_math()) { + clear_fpu(tsk); + clear_used_math(); + } + + return 0; + } else + if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) + return -EACCES; + + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } + + if (!(task_thread_info(current)->status & TS_USEDFPU)) { + clts(); + task_thread_info(current)->status |= TS_USEDFPU; + } + err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); + if (unlikely(err)) { + /* + * Encountered an error while doing the restore from the + * user buffer, clear the fpu state. + */ + clear_fpu(tsk); + clear_used_math(); + } + return err; +} +#endif + /* * Represents init state for the supported extended state. */ diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 36dca8db166..dc3745e8040 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -34,8 +34,9 @@ extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set; #ifdef CONFIG_IA32_EMULATION extern unsigned int sig_xstate_ia32_size; struct _fpstate_ia32; -extern int save_i387_ia32(struct _fpstate_ia32 __user *buf); -extern int restore_i387_ia32(struct _fpstate_ia32 __user *buf); +struct _xstate_ia32; +extern int save_i387_xstate_ia32(void __user *buf); +extern int restore_i387_xstate_ia32(void __user *buf); #endif #define X87_FSW_ES (1 << 7) /* Exception Summary */ @@ -249,13 +250,13 @@ end: task_thread_info(tsk)->status &= ~TS_USEDFPU; } +#endif /* CONFIG_X86_64 */ + /* * Signal frame handlers... */ -extern int save_i387(struct _fpstate __user *buf); -extern int restore_i387(struct _fpstate __user *buf); - -#endif /* CONFIG_X86_64 */ +extern int save_i387_xstate(void __user *buf); +extern int restore_i387_xstate(void __user *buf); static inline void __unlazy_fpu(struct task_struct *tsk) { -- GitLab From 9dc89c0f96a6ce6a1b7f9a47dd8bf6f17e2002c9 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:23 -0700 Subject: [PATCH 0210/5416] x86, xsave: xsave/xrstor specific routines Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/asm-x86/xsave.h | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h index e835a917ee1..b716511aede 100644 --- a/include/asm-x86/xsave.h +++ b/include/asm-x86/xsave.h @@ -48,6 +48,58 @@ static inline int xrstor_checking(struct xsave_struct *fx) return err; } +static inline int xsave_check(struct xsave_struct __user *buf) +{ + int err; + __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + _ASM_ALIGN "\n" + _ASM_PTR "1b,3b\n" + ".previous" + : [err] "=r" (err) + : "D" (buf), "a" (-1), "d" (-1), "0" (0) + : "memory"); + if (unlikely(err) && __clear_user(buf, xstate_size)) + err = -EFAULT; + /* No need to clear here because the caller clears USED_MATH */ + return err; +} + +static inline int xrestore_user(struct xsave_struct __user *buf, + unsigned int lmask, + unsigned int hmask) +{ + int err; + struct xsave_struct *xstate = ((__force struct xsave_struct *)buf); + + __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl $-1,%[err]\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + _ASM_ALIGN "\n" + _ASM_PTR "1b,3b\n" + ".previous" + : [err] "=r" (err) + : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0) + : "memory"); /* memory required? */ + return err; +} + +static inline void xrstor_state(struct xsave_struct *fx, int lmask, int hmask) +{ + asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" + : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) + : "memory"); +} + static inline void xsave(struct task_struct *tsk) { /* This, however, we can work around by forcing the compiler to select -- GitLab From bdd8caba5ed5bb7ee21c9f061597284ffeb280bf Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:24 -0700 Subject: [PATCH 0211/5416] x86, xsave: struct _fpstate extensions to include extended state information Bytes 464..511 in the current 512byte layout of fxsave/fxrstor frame, are reserved for SW usage. On cpu's supporting xsave/xrstor, these bytes are used to extended the fpstate pointer in the sigcontext, which now includes the extended state information along with fpstate information. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/asm-x86/processor.h | 7 ++- include/asm-x86/sigcontext.h | 87 ++++++++++++++++++++++++++++++++-- include/asm-x86/sigcontext32.h | 6 ++- 3 files changed, 94 insertions(+), 6 deletions(-) diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 77b7af6b573..eb4bd8c0773 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -322,7 +322,12 @@ struct i387_fxsave_struct { /* 16*16 bytes for each XMM-reg = 256 bytes: */ u32 xmm_space[64]; - u32 padding[24]; + u32 padding[12]; + + union { + u32 padding1[12]; + u32 sw_reserved[12]; + }; } __attribute__((aligned(16))); diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h index 24879c85b29..899fe2f8abb 100644 --- a/include/asm-x86/sigcontext.h +++ b/include/asm-x86/sigcontext.h @@ -4,6 +4,40 @@ #include #include +#define FP_XSTATE_MAGIC1 0x46505853U +#define FP_XSTATE_MAGIC2 0x46505845U +#define FP_XSTATE_MAGIC2_SIZE sizeof(FP_XSTATE_MAGIC2) + +/* + * bytes 464..511 in the current 512byte layout of fxsave/fxrstor frame + * are reserved for SW usage. On cpu's supporting xsave/xrstor, these bytes + * are used to extended the fpstate pointer in the sigcontext, which now + * includes the extended state information along with fpstate information. + * + * Presence of FP_XSTATE_MAGIC1 at the beginning of this SW reserved + * area and FP_XSTATE_MAGIC2 at the end of memory layout + * (extended_size - FP_XSTATE_MAGIC2_SIZE) indicates the presence of the + * extended state information in the memory layout pointed by the fpstate + * pointer in sigcontext. + */ +struct _fpx_sw_bytes { + __u32 magic1; /* FP_XSTATE_MAGIC1 */ + __u32 extended_size; /* total size of the layout referred by + * fpstate pointer in the sigcontext. + */ + __u64 xstate_bv; + /* feature bit mask (including fp/sse/extended + * state) that is present in the memory + * layout. + */ + __u32 xstate_size; /* actual xsave state size, based on the + * features saved in the layout. + * 'extended_size' will be greater than + * 'xstate_size'. + */ + __u32 padding[7]; /* for future use. */ +}; + #ifdef __i386__ /* * As documented in the iBCS2 standard.. @@ -53,7 +87,13 @@ struct _fpstate { unsigned long reserved; struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ struct _xmmreg _xmm[8]; - unsigned long padding[56]; + unsigned long padding1[44]; + + union { + unsigned long padding2[12]; + struct _fpx_sw_bytes sw_reserved; /* represents the extended + * state info */ + }; }; #define X86_FXSR_MAGIC 0x0000 @@ -79,7 +119,15 @@ struct sigcontext { unsigned long flags; unsigned long sp_at_signal; unsigned short ss, __ssh; - struct _fpstate __user *fpstate; + + /* + * fpstate is really (struct _fpstate *) or (struct _xstate *) + * depending on the FP_XSTATE_MAGIC1 encoded in the SW reserved + * bytes of (struct _fpstate) and FP_XSTATE_MAGIC2 present at the end + * of extended memory layout. See comments at the defintion of + * (struct _fpx_sw_bytes) + */ + void __user *fpstate; /* zero when no FPU/extended context */ unsigned long oldmask; unsigned long cr2; }; @@ -130,7 +178,12 @@ struct _fpstate { __u32 mxcsr_mask; __u32 st_space[32]; /* 8*16 bytes for each FP-reg */ __u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg */ - __u32 reserved2[24]; + __u32 reserved2[12]; + union { + __u32 reserved3[12]; + struct _fpx_sw_bytes sw_reserved; /* represents the extended + * state information */ + }; }; #ifdef __KERNEL__ @@ -161,7 +214,15 @@ struct sigcontext { unsigned long trapno; unsigned long oldmask; unsigned long cr2; - struct _fpstate __user *fpstate; /* zero when no FPU context */ + + /* + * fpstate is really (struct _fpstate *) or (struct _xstate *) + * depending on the FP_XSTATE_MAGIC1 encoded in the SW reserved + * bytes of (struct _fpstate) and FP_XSTATE_MAGIC2 present at the end + * of extended memory layout. See comments at the defintion of + * (struct _fpx_sw_bytes) + */ + void __user *fpstate; /* zero when no FPU/extended context */ unsigned long reserved1[8]; }; #else /* __KERNEL__ */ @@ -202,4 +263,22 @@ struct sigcontext { #endif /* !__i386__ */ +struct _xsave_hdr { + u64 xstate_bv; + u64 reserved1[2]; + u64 reserved2[5]; +}; + +/* + * Extended state pointed by the fpstate pointer in the sigcontext. + * In addition to the fpstate, information encoded in the xstate_hdr + * indicates the presence of other extended state information + * supported by the processor and OS. + */ +struct _xstate { + struct _fpstate fpstate; + struct _xsave_hdr xstate_hdr; + /* new processor state extensions go here */ +}; + #endif /* ASM_X86__SIGCONTEXT_H */ diff --git a/include/asm-x86/sigcontext32.h b/include/asm-x86/sigcontext32.h index 4e2ec732dd0..8c347032c2f 100644 --- a/include/asm-x86/sigcontext32.h +++ b/include/asm-x86/sigcontext32.h @@ -40,7 +40,11 @@ struct _fpstate_ia32 { __u32 reserved; struct _fpxreg _fxsr_st[8]; struct _xmmreg _xmm[8]; /* It's actually 16 */ - __u32 padding[56]; + __u32 padding[44]; + union { + __u32 padding2[12]; + struct _fpx_sw_bytes sw_reserved; + }; }; struct sigcontext_ia32 { -- GitLab From c37b5efea43f9e500363f9973dd00e3d2cdcc685 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:25 -0700 Subject: [PATCH 0212/5416] x86, xsave: save/restore the extended state context in sigframe On cpu's supporting xsave/xrstor, fpstate pointer in the sigcontext, will include the extended state information along with fpstate information. Presence of extended state information is indicated by the presence of FP_XSTATE_MAGIC1 at fpstate.sw_reserved.magic1 and FP_XSTATE_MAGIC2 at fpstate + (fpstate.sw_reserved.extended_size - FP_XSTATE_MAGIC2_SIZE). Extended feature bit mask that is saved in the memory layout is represented by the fpstate.sw_reserved.xstate_bv For RT signal frames, UC_FP_XSTATE in the uc_flags also indicate the presence of extended state information in the sigcontext's fpstate pointer. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 5 +- arch/x86/kernel/i387.c | 82 +++++++++++++++-- arch/x86/kernel/signal_32.c | 5 +- arch/x86/kernel/signal_64.c | 7 +- arch/x86/kernel/xsave.c | 172 +++++++++++++++++++++++++++++++++--- include/asm-x86/i387.h | 4 +- include/asm-x86/ucontext.h | 6 ++ include/asm-x86/xsave.h | 5 +- 8 files changed, 264 insertions(+), 22 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index c596eabbe98..f25a1012400 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -544,7 +544,10 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 7daf3a011dd..cbb9dc474a2 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -26,6 +26,7 @@ # define _fpstate_ia32 _fpstate # define _xstate_ia32 _xstate # define sig_xstate_ia32_size sig_xstate_size +# define fx_sw_reserved_ia32 fx_sw_reserved # define user_i387_ia32_struct user_i387_struct # define user32_fxsr_struct user_fxsr_struct #endif @@ -447,12 +448,30 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) if (err) return -1; - if (__copy_to_user(&buf->_fxsr_env[0], fx, - sizeof(struct i387_fxsave_struct))) + if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size)) return -1; return 1; } +static int save_i387_xsave(void __user *buf) +{ + struct _fpstate_ia32 __user *fx = buf; + int err = 0; + + if (save_i387_fxsave(fx) < 0) + return -1; + + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32, + sizeof(struct _fpx_sw_bytes)); + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_ia32_size + - FP_XSTATE_MAGIC2_SIZE)); + if (err) + return -1; + + return 1; +} + int save_i387_xstate_ia32(void __user *buf) { struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; @@ -477,6 +496,8 @@ int save_i387_xstate_ia32(void __user *buf) unlazy_fpu(tsk); + if (cpu_has_xsave) + return save_i387_xsave(fp); if (cpu_has_fxsr) return save_i387_fxsave(fp); else @@ -491,14 +512,15 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) sizeof(struct i387_fsave_struct)); } -static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) +static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf, + unsigned int size) { struct task_struct *tsk = current; struct user_i387_ia32_struct env; int err; err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], - sizeof(struct i387_fxsave_struct)); + size); /* mxcsr reserved bits must be masked to zero for security reasons */ tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; if (err || __copy_from_user(&env, buf, sizeof(env))) @@ -508,6 +530,51 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) return 0; } +static int restore_i387_xsave(void __user *buf) +{ + struct _fpx_sw_bytes fx_sw_user; + struct _fpstate_ia32 __user *fx_user = + ((struct _fpstate_ia32 __user *) buf); + struct i387_fxsave_struct __user *fx = + (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; + struct xsave_hdr_struct *xsave_hdr = + ¤t->thread.xstate->xsave.xsave_hdr; + unsigned int lmask, hmask; + int err; + + if (check_for_xstate(fx, buf, &fx_sw_user)) + goto fx_only; + + lmask = fx_sw_user.xstate_bv; + hmask = fx_sw_user.xstate_bv >> 32; + + err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); + + xsave_hdr->xstate_bv &= (pcntxt_lmask | (((u64) pcntxt_hmask) << 32)); + /* + * These bits must be zero. + */ + xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; + + /* + * Init the state that is not present in the memory layout + * and enabled by the OS. + */ + lmask = ~(pcntxt_lmask & ~lmask); + hmask = ~(pcntxt_hmask & ~hmask); + xsave_hdr->xstate_bv &= (lmask | (((u64) hmask) << 32)); + + return err; +fx_only: + /* + * Couldn't find the extended state information in the memory + * layout. Restore the FP/SSE and init the other extended state + * enabled by the OS. + */ + xsave_hdr->xstate_bv = XSTATE_FPSSE; + return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct)); +} + int restore_i387_xstate_ia32(void __user *buf) { int err; @@ -535,8 +602,11 @@ int restore_i387_xstate_ia32(void __user *buf) } if (HAVE_HWFP) { - if (cpu_has_fxsr) - err = restore_i387_fxsave(fp); + if (cpu_has_xsave) + err = restore_i387_xsave(buf); + else if (cpu_has_fxsr) + err = restore_i387_fxsave(fp, sizeof(struct + i387_fxsave_struct)); else err = restore_i387_fsave(fp); } else { diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 690cc616ac0..0f98d69fbdb 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -441,7 +441,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ddf6123a55c..2621b98f5bf 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -192,7 +192,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) sp = current->sas_ss_sp + current->sas_ss_size; } - return (void __user *)round_down(sp - size, 16); + return (void __user *)round_down(sp - size, 64); } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -226,7 +226,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); + if (cpu_has_xsave) + err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + else + err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 608e72d7ca6..dd66d0714c1 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -6,12 +6,68 @@ #include #include #include +#ifdef CONFIG_IA32_EMULATION +#include +#endif /* * Supported feature mask by the CPU and the kernel. */ unsigned int pcntxt_hmask, pcntxt_lmask; +struct _fpx_sw_bytes fx_sw_reserved; +#ifdef CONFIG_IA32_EMULATION +struct _fpx_sw_bytes fx_sw_reserved_ia32; +#endif + +/* + * Check for the presence of extended state information in the + * user fpstate pointer in the sigcontext. + */ +int check_for_xstate(struct i387_fxsave_struct __user *buf, + void __user *fpstate, + struct _fpx_sw_bytes *fx_sw_user) +{ + int min_xstate_size = sizeof(struct i387_fxsave_struct) + + sizeof(struct xsave_hdr_struct); + unsigned int magic2; + int err; + + err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0], + sizeof(struct _fpx_sw_bytes)); + + if (err) + return err; + + /* + * First Magic check failed. + */ + if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1) + return -1; + + /* + * Check for error scenarios. + */ + if (fx_sw_user->xstate_size < min_xstate_size || + fx_sw_user->xstate_size > xstate_size || + fx_sw_user->xstate_size > fx_sw_user->extended_size) + return -1; + + err = __get_user(magic2, (__u32 *) (((void *)fpstate) + + fx_sw_user->extended_size - + FP_XSTATE_MAGIC2_SIZE)); + /* + * Check for the presence of second magic word at the end of memory + * layout. This detects the case where the user just copied the legacy + * fpstate layout with out copying the extended state information + * in the memory layout. + */ + if (err || magic2 != FP_XSTATE_MAGIC2) + return -1; + + return 0; +} + #ifdef CONFIG_X86_64 /* * Signal frame handlers. @@ -28,15 +84,18 @@ int save_i387_xstate(void __user *buf) BUILD_BUG_ON(sizeof(struct user_i387_struct) != sizeof(tsk->thread.xstate->fxsave)); - if ((unsigned long)buf % 16) + if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); if (!used_math()) return 0; clear_used_math(); /* trigger finit */ if (task_thread_info(tsk)->status & TS_USEDFPU) { - err = save_i387_checking((struct i387_fxsave_struct __user *) - buf); + if (task_thread_info(tsk)->status & TS_XSAVE) + err = xsave_user(buf); + else + err = fxsave_user(buf); + if (err) return err; task_thread_info(tsk)->status &= ~TS_USEDFPU; @@ -46,23 +105,77 @@ int save_i387_xstate(void __user *buf) xstate_size)) return -1; } + + if (task_thread_info(tsk)->status & TS_XSAVE) { + struct _fpstate __user *fx = buf; + + err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); + + err |= __put_user(FP_XSTATE_MAGIC2, + (__u32 __user *) (buf + sig_xstate_size + - FP_XSTATE_MAGIC2_SIZE)); + } + return 1; } +/* + * Restore the extended state if present. Otherwise, restore the FP/SSE + * state. + */ +int restore_user_xstate(void __user *buf) +{ + struct _fpx_sw_bytes fx_sw_user; + unsigned int lmask, hmask; + int err; + + if (((unsigned long)buf % 64) || + check_for_xstate(buf, buf, &fx_sw_user)) + goto fx_only; + + lmask = fx_sw_user.xstate_bv; + hmask = fx_sw_user.xstate_bv >> 32; + + /* + * restore the state passed by the user. + */ + err = xrestore_user(buf, lmask, hmask); + if (err) + return err; + + /* + * init the state skipped by the user. + */ + lmask = pcntxt_lmask & ~lmask; + hmask = pcntxt_hmask & ~hmask; + + xrstor_state(init_xstate_buf, lmask, hmask); + + return 0; + +fx_only: + /* + * couldn't find the extended state information in the + * memory layout. Restore just the FP/SSE and init all + * the other extended state. + */ + xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE, + pcntxt_hmask); + return fxrstor_checking((__force struct i387_fxsave_struct *)buf); +} + /* * This restores directly out of user space. Exceptions are handled. */ int restore_i387_xstate(void __user *buf) { struct task_struct *tsk = current; - int err; + int err = 0; if (!buf) { - if (used_math()) { - clear_fpu(tsk); - clear_used_math(); - } - + if (used_math()) + goto clear; return 0; } else if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) @@ -78,12 +191,17 @@ int restore_i387_xstate(void __user *buf) clts(); task_thread_info(current)->status |= TS_USEDFPU; } - err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); + if (task_thread_info(tsk)->status & TS_XSAVE) + err = restore_user_xstate(buf); + else + err = fxrstor_checking((__force struct i387_fxsave_struct *) + buf); if (unlikely(err)) { /* * Encountered an error while doing the restore from the * user buffer, clear the fpu state. */ +clear: clear_fpu(tsk); clear_used_math(); } @@ -91,6 +209,38 @@ int restore_i387_xstate(void __user *buf) } #endif +/* + * Prepare the SW reserved portion of the fxsave memory layout, indicating + * the presence of the extended state information in the memory layout + * pointed by the fpstate pointer in the sigcontext. + * This will be saved when ever the FP and extended state context is + * saved on the user stack during the signal handler delivery to the user. + */ +void prepare_fx_sw_frame(void) +{ + int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) + + FP_XSTATE_MAGIC2_SIZE; + + sig_xstate_size = sizeof(struct _fpstate) + size_extended; + +#ifdef CONFIG_IA32_EMULATION + sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended; +#endif + + memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved)); + + fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; + fx_sw_reserved.extended_size = sig_xstate_size; + fx_sw_reserved.xstate_bv = pcntxt_lmask | + (((u64) (pcntxt_hmask)) << 32); + fx_sw_reserved.xstate_size = xstate_size; +#ifdef CONFIG_IA32_EMULATION + memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, + sizeof(struct _fpx_sw_bytes)); + fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size; +#endif +} + /* * Represents init state for the supported extended state. */ @@ -162,6 +312,8 @@ void __init xsave_cntxt_init(void) xstate_size = ebx; + prepare_fx_sw_frame(); + setup_xstate_init(); printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index dc3745e8040..d3dda716195 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -31,8 +31,10 @@ extern user_regset_active_fn fpregs_active, xfpregs_active; extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set; +extern struct _fpx_sw_bytes fx_sw_reserved; #ifdef CONFIG_IA32_EMULATION extern unsigned int sig_xstate_ia32_size; +extern struct _fpx_sw_bytes fx_sw_reserved_ia32; struct _fpstate_ia32; struct _xstate_ia32; extern int save_i387_xstate_ia32(void __user *buf); @@ -104,7 +106,7 @@ static inline void clear_fpu_state(struct task_struct *tsk) X86_FEATURE_FXSAVE_LEAK); } -static inline int save_i387_checking(struct i387_fxsave_struct __user *fx) +static inline int fxsave_user(struct i387_fxsave_struct __user *fx) { int err; diff --git a/include/asm-x86/ucontext.h b/include/asm-x86/ucontext.h index 9948dd32808..89eaa5456a7 100644 --- a/include/asm-x86/ucontext.h +++ b/include/asm-x86/ucontext.h @@ -1,6 +1,12 @@ #ifndef ASM_X86__UCONTEXT_H #define ASM_X86__UCONTEXT_H +#define UC_FP_XSTATE 0x1 /* indicates the presence of extended state + * information in the memory layout pointed + * by the fpstate pointer in the ucontext's + * sigcontext struct (uc_mcontext). + */ + struct ucontext { unsigned long uc_flags; struct ucontext *uc_link; diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h index b716511aede..b7f64b9fcd9 100644 --- a/include/asm-x86/xsave.h +++ b/include/asm-x86/xsave.h @@ -29,6 +29,9 @@ extern struct xsave_struct *init_xstate_buf; extern void xsave_cntxt_init(void); extern void xsave_init(void); extern int init_fpu(struct task_struct *child); +extern int check_for_xstate(struct i387_fxsave_struct __user *buf, + void __user *fpstate, + struct _fpx_sw_bytes *sw); static inline int xrstor_checking(struct xsave_struct *fx) { @@ -48,7 +51,7 @@ static inline int xrstor_checking(struct xsave_struct *fx) return err; } -static inline int xsave_check(struct xsave_struct __user *buf) +static inline int xsave_user(struct xsave_struct __user *buf) { int err; __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" -- GitLab From 42deec6f2c3688fdaf986225ac901b817cd91568 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 29 Jul 2008 10:29:26 -0700 Subject: [PATCH 0213/5416] x86, xsave: update xsave header bits during ptrace fpregs set FP/SSE bits may be zero in the xsave header(representing the init state). Update these bits during the ptrace fpregs set operation, to indicate the non-init state. Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/i387.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index cbb9dc474a2..e0ed59f5c19 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -214,6 +214,13 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, */ target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; + /* + * update the header bits in the xsave header, indicating the + * presence of FP and SSE state. + */ + if (cpu_has_xsave) + target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + return ret; } @@ -414,6 +421,12 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, if (!ret) convert_to_fxsr(target, &env); + /* + * update the header bit in the xsave header, indicating the + * presence of FP. + */ + if (cpu_has_xsave) + target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FP; return ret; } -- GitLab From b4a091a62c8e91d6077e575600363cff73fa02ef Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 29 Jul 2008 17:30:29 -0700 Subject: [PATCH 0214/5416] x86, xsave: add header file for XCR registers Add header file for the XCR registers and their access functions. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/asm-x86/xcr.h | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 include/asm-x86/xcr.h diff --git a/include/asm-x86/xcr.h b/include/asm-x86/xcr.h new file mode 100644 index 00000000000..f2cba4e79a2 --- /dev/null +++ b/include/asm-x86/xcr.h @@ -0,0 +1,49 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + * Copyright 2008 rPath, Inc. - All Rights Reserved + * + * This file is part of the Linux kernel, and is made available under + * the terms of the GNU General Public License version 2 or (at your + * option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * asm-x86/xcr.h + * + * Definitions for the eXtended Control Register instructions + */ + +#ifndef _ASM_X86_XCR_H +#define _ASM_X86_XCR_H + +#define XCR_XFEATURE_ENABLED_MASK 0x00000000 + +#ifdef __KERNEL__ +# ifndef __ASSEMBLY__ + +#include + +static inline u64 xgetbv(u32 index) +{ + u32 eax, edx; + + asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */ + : "=a" (eax), "=d" (edx) + : "c" (index)); + return eax + ((u64)edx << 32); +} + +static inline void xsetbv(u32 index, u64 value) +{ + u32 eax = value; + u32 edx = value >> 32; + + asm volatile(".byte 0x0f,0x01,0xd1" /* xsetbv */ + : : "a" (eax), "d" (edx), "c" (index)); +} + +# endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ + +#endif /* _ASM_X86_XCR_H */ -- GitLab From 6152e4b1c99a3689fc318d092cd144597f7dbd14 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 29 Jul 2008 17:23:16 -0700 Subject: [PATCH 0215/5416] x86, xsave: keep the XSAVE feature mask as an u64 The XSAVE feature mask is a 64-bit number; keep it that way, in order to avoid the mistake done with rdmsr/wrmsr. Use the xsetbv() function provided in the previous patch. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/kernel/i387.c | 12 +++++------ arch/x86/kernel/xsave.c | 45 ++++++++++++++++------------------------- include/asm-x86/xsave.h | 18 ++++++++++------- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index e0ed59f5c19..45723f1fe19 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -552,18 +552,17 @@ static int restore_i387_xsave(void __user *buf) (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; struct xsave_hdr_struct *xsave_hdr = ¤t->thread.xstate->xsave.xsave_hdr; - unsigned int lmask, hmask; + u64 mask; int err; if (check_for_xstate(fx, buf, &fx_sw_user)) goto fx_only; - lmask = fx_sw_user.xstate_bv; - hmask = fx_sw_user.xstate_bv >> 32; + mask = fx_sw_user.xstate_bv; err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); - xsave_hdr->xstate_bv &= (pcntxt_lmask | (((u64) pcntxt_hmask) << 32)); + xsave_hdr->xstate_bv &= pcntxt_mask; /* * These bits must be zero. */ @@ -573,9 +572,8 @@ static int restore_i387_xsave(void __user *buf) * Init the state that is not present in the memory layout * and enabled by the OS. */ - lmask = ~(pcntxt_lmask & ~lmask); - hmask = ~(pcntxt_hmask & ~hmask); - xsave_hdr->xstate_bv &= (lmask | (((u64) hmask) << 32)); + mask = ~(pcntxt_mask & ~mask); + xsave_hdr->xstate_bv &= mask; return err; fx_only: diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index dd66d0714c1..7415f3e38a5 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -9,11 +9,12 @@ #ifdef CONFIG_IA32_EMULATION #include #endif +#include /* * Supported feature mask by the CPU and the kernel. */ -unsigned int pcntxt_hmask, pcntxt_lmask; +u64 pcntxt_mask; struct _fpx_sw_bytes fx_sw_reserved; #ifdef CONFIG_IA32_EMULATION @@ -127,30 +128,28 @@ int save_i387_xstate(void __user *buf) int restore_user_xstate(void __user *buf) { struct _fpx_sw_bytes fx_sw_user; - unsigned int lmask, hmask; + u64 mask; int err; if (((unsigned long)buf % 64) || check_for_xstate(buf, buf, &fx_sw_user)) goto fx_only; - lmask = fx_sw_user.xstate_bv; - hmask = fx_sw_user.xstate_bv >> 32; + mask = fx_sw_user.xstate_bv; /* * restore the state passed by the user. */ - err = xrestore_user(buf, lmask, hmask); + err = xrestore_user(buf, mask); if (err) return err; /* * init the state skipped by the user. */ - lmask = pcntxt_lmask & ~lmask; - hmask = pcntxt_hmask & ~hmask; + mask = pcntxt_mask & ~mask; - xrstor_state(init_xstate_buf, lmask, hmask); + xrstor_state(init_xstate_buf, mask); return 0; @@ -160,8 +159,7 @@ fx_only: * memory layout. Restore just the FP/SSE and init all * the other extended state. */ - xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE, - pcntxt_hmask); + xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); return fxrstor_checking((__force struct i387_fxsave_struct *)buf); } @@ -231,8 +229,7 @@ void prepare_fx_sw_frame(void) fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; fx_sw_reserved.extended_size = sig_xstate_size; - fx_sw_reserved.xstate_bv = pcntxt_lmask | - (((u64) (pcntxt_hmask)) << 32); + fx_sw_reserved.xstate_bv = pcntxt_mask; fx_sw_reserved.xstate_size = xstate_size; #ifdef CONFIG_IA32_EMULATION memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, @@ -263,11 +260,8 @@ void __cpuinit xsave_init(void) /* * Enable all the features that the HW is capable of * and the Linux kernel is aware of. - * - * xsetbv(); */ - asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0), - "a" (pcntxt_lmask), "d" (pcntxt_hmask)); + xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); } /* @@ -287,36 +281,31 @@ void __init xsave_cntxt_init(void) unsigned int eax, ebx, ecx, edx; cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); + pcntxt_mask = eax + ((u64)edx << 32); - pcntxt_lmask = eax; - pcntxt_hmask = edx; - - if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) { - printk(KERN_ERR "FP/SSE not shown under xsave features %x\n", - pcntxt_lmask); + if ((pcntxt_mask & XSTATE_FPSSE) != XSTATE_FPSSE) { + printk(KERN_ERR "FP/SSE not shown under xsave features 0x%llx\n", + pcntxt_mask); BUG(); } /* * for now OS knows only about FP/SSE */ - pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK; - pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK; - + pcntxt_mask = pcntxt_mask & XCNTXT_MASK; xsave_init(); /* * Recompute the context size for enabled features */ cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); - xstate_size = ebx; prepare_fx_sw_frame(); setup_xstate_init(); - printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " + printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%llx, " "cntxt size 0x%x\n", - (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size); + pcntxt_mask, xstate_size); } diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h index b7f64b9fcd9..08e9a1ac07a 100644 --- a/include/asm-x86/xsave.h +++ b/include/asm-x86/xsave.h @@ -1,6 +1,7 @@ #ifndef __ASM_X86_XSAVE_H #define __ASM_X86_XSAVE_H +#include #include #include @@ -14,8 +15,7 @@ /* * These are the features that the OS can handle currently. */ -#define XCNTXT_LMASK (XSTATE_FP | XSTATE_SSE) -#define XCNTXT_HMASK 0x0 +#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE) #ifdef CONFIG_X86_64 #define REX_PREFIX "0x48, " @@ -23,7 +23,8 @@ #define REX_PREFIX #endif -extern unsigned int xstate_size, pcntxt_hmask, pcntxt_lmask; +extern unsigned int xstate_size; +extern u64 pcntxt_mask; extern struct xsave_struct *init_xstate_buf; extern void xsave_cntxt_init(void); @@ -73,12 +74,12 @@ static inline int xsave_user(struct xsave_struct __user *buf) return err; } -static inline int xrestore_user(struct xsave_struct __user *buf, - unsigned int lmask, - unsigned int hmask) +static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) { int err; struct xsave_struct *xstate = ((__force struct xsave_struct *)buf); + u32 lmask = mask; + u32 hmask = mask >> 32; __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n" "2:\n" @@ -96,8 +97,11 @@ static inline int xrestore_user(struct xsave_struct __user *buf, return err; } -static inline void xrstor_state(struct xsave_struct *fx, int lmask, int hmask) +static inline void xrstor_state(struct xsave_struct *fx, u64 mask) { + u32 lmask = mask; + u32 hmask = mask >> 32; + asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) : "memory"); -- GitLab From 0d1edf46ba229b46efacf75c0544b88c05a7b266 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 28 Jul 2008 11:53:57 -0700 Subject: [PATCH 0216/5416] xen: compile irq functions without -pg for ftrace For some reason I managed to miss a bunch of irq-related functions which also need to be compiled without -pg when using ftrace. This patch moves them into their own file, and starts a cleanup process I've been meaning to do anyway. Signed-off-by: Jeremy Fitzhardinge Cc: Sam Ravnborg Cc: "Alex Nixon (Intern)" Cc: Eduardo Habkost Signed-off-by: Ingo Molnar --- arch/x86/xen/Makefile | 3 +- arch/x86/xen/enlighten.c | 122 +------------------------------- arch/x86/xen/irq.c | 143 ++++++++++++++++++++++++++++++++++++++ arch/x86/xen/xen-asm_32.S | 2 +- arch/x86/xen/xen-asm_64.S | 2 +- arch/x86/xen/xen-ops.h | 1 + drivers/xen/events.c | 11 --- 7 files changed, 150 insertions(+), 134 deletions(-) create mode 100644 arch/x86/xen/irq.c diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 5bfee243cf9..9ee745fa552 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -2,9 +2,10 @@ ifdef CONFIG_FTRACE # Do not profile debug and lowlevel utilities CFLAGS_REMOVE_spinlock.o = -pg CFLAGS_REMOVE_time.o = -pg +CFLAGS_REMOVE_irq.o = -pg endif -obj-y := enlighten.o setup.o multicalls.o mmu.o \ +obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ time.o xen-asm_$(BITS).o grant-table.o suspend.o obj-$(CONFIG_SMP) += smp.o spinlock.o diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b795470ec06..cf8b3a93122 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -226,94 +225,6 @@ static unsigned long xen_get_debugreg(int reg) return HYPERVISOR_get_debugreg(reg); } -static unsigned long xen_save_fl(void) -{ - struct vcpu_info *vcpu; - unsigned long flags; - - vcpu = x86_read_percpu(xen_vcpu); - - /* flag has opposite sense of mask */ - flags = !vcpu->evtchn_upcall_mask; - - /* convert to IF type flag - -0 -> 0x00000000 - -1 -> 0xffffffff - */ - return (-flags) & X86_EFLAGS_IF; -} - -static void xen_restore_fl(unsigned long flags) -{ - struct vcpu_info *vcpu; - - /* convert from IF type flag */ - flags = !(flags & X86_EFLAGS_IF); - - /* There's a one instruction preempt window here. We need to - make sure we're don't switch CPUs between getting the vcpu - pointer and updating the mask. */ - preempt_disable(); - vcpu = x86_read_percpu(xen_vcpu); - vcpu->evtchn_upcall_mask = flags; - preempt_enable_no_resched(); - - /* Doesn't matter if we get preempted here, because any - pending event will get dealt with anyway. */ - - if (flags == 0) { - preempt_check_resched(); - barrier(); /* unmask then check (avoid races) */ - if (unlikely(vcpu->evtchn_upcall_pending)) - force_evtchn_callback(); - } -} - -static void xen_irq_disable(void) -{ - /* There's a one instruction preempt window here. We need to - make sure we're don't switch CPUs between getting the vcpu - pointer and updating the mask. */ - preempt_disable(); - x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; - preempt_enable_no_resched(); -} - -static void xen_irq_enable(void) -{ - struct vcpu_info *vcpu; - - /* We don't need to worry about being preempted here, since - either a) interrupts are disabled, so no preemption, or b) - the caller is confused and is trying to re-enable interrupts - on an indeterminate processor. */ - - vcpu = x86_read_percpu(xen_vcpu); - vcpu->evtchn_upcall_mask = 0; - - /* Doesn't matter if we get preempted here, because any - pending event will get dealt with anyway. */ - - barrier(); /* unmask then check (avoid races) */ - if (unlikely(vcpu->evtchn_upcall_pending)) - force_evtchn_callback(); -} - -static void xen_safe_halt(void) -{ - /* Blocking includes an implicit local_irq_enable(). */ - if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) - BUG(); -} - -static void xen_halt(void) -{ - if (irqs_disabled()) - HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); - else - xen_safe_halt(); -} - static void xen_leave_lazy(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); @@ -1308,36 +1219,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { }, }; -static void __init __xen_init_IRQ(void) -{ -#ifdef CONFIG_X86_64 - int i; - - /* Create identity vector->irq map */ - for(i = 0; i < NR_VECTORS; i++) { - int cpu; - - for_each_possible_cpu(cpu) - per_cpu(vector_irq, cpu)[i] = i; - } -#endif /* CONFIG_X86_64 */ - - xen_init_IRQ(); -} - -static const struct pv_irq_ops xen_irq_ops __initdata = { - .init_IRQ = __xen_init_IRQ, - .save_fl = xen_save_fl, - .restore_fl = xen_restore_fl, - .irq_disable = xen_irq_disable, - .irq_enable = xen_irq_enable, - .safe_halt = xen_safe_halt, - .halt = xen_halt, -#ifdef CONFIG_X86_64 - .adjust_exception_frame = xen_adjust_exception_frame, -#endif -}; - static const struct pv_apic_ops xen_apic_ops __initdata = { #ifdef CONFIG_X86_LOCAL_APIC .apic_write = xen_apic_write, @@ -1740,10 +1621,11 @@ asmlinkage void __init xen_start_kernel(void) pv_init_ops = xen_init_ops; pv_time_ops = xen_time_ops; pv_cpu_ops = xen_cpu_ops; - pv_irq_ops = xen_irq_ops; pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; + xen_init_irq_ops(); + if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c new file mode 100644 index 00000000000..28b85ab8422 --- /dev/null +++ b/arch/x86/xen/irq.c @@ -0,0 +1,143 @@ +#include + +#include +#include +#include + +#include +#include + +#include "xen-ops.h" + +/* + * Force a proper event-channel callback from Xen after clearing the + * callback mask. We do this in a very simple manner, by making a call + * down into Xen. The pending flag will be checked by Xen on return. + */ +void xen_force_evtchn_callback(void) +{ + (void)HYPERVISOR_xen_version(0, NULL); +} + +static void __init __xen_init_IRQ(void) +{ +#ifdef CONFIG_X86_64 + int i; + + /* Create identity vector->irq map */ + for(i = 0; i < NR_VECTORS; i++) { + int cpu; + + for_each_possible_cpu(cpu) + per_cpu(vector_irq, cpu)[i] = i; + } +#endif /* CONFIG_X86_64 */ + + xen_init_IRQ(); +} + +static unsigned long xen_save_fl(void) +{ + struct vcpu_info *vcpu; + unsigned long flags; + + vcpu = x86_read_percpu(xen_vcpu); + + /* flag has opposite sense of mask */ + flags = !vcpu->evtchn_upcall_mask; + + /* convert to IF type flag + -0 -> 0x00000000 + -1 -> 0xffffffff + */ + return (-flags) & X86_EFLAGS_IF; +} + +static void xen_restore_fl(unsigned long flags) +{ + struct vcpu_info *vcpu; + + /* convert from IF type flag */ + flags = !(flags & X86_EFLAGS_IF); + + /* There's a one instruction preempt window here. We need to + make sure we're don't switch CPUs between getting the vcpu + pointer and updating the mask. */ + preempt_disable(); + vcpu = x86_read_percpu(xen_vcpu); + vcpu->evtchn_upcall_mask = flags; + preempt_enable_no_resched(); + + /* Doesn't matter if we get preempted here, because any + pending event will get dealt with anyway. */ + + if (flags == 0) { + preempt_check_resched(); + barrier(); /* unmask then check (avoid races) */ + if (unlikely(vcpu->evtchn_upcall_pending)) + xen_force_evtchn_callback(); + } +} + +static void xen_irq_disable(void) +{ + /* There's a one instruction preempt window here. We need to + make sure we're don't switch CPUs between getting the vcpu + pointer and updating the mask. */ + preempt_disable(); + x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); +} + +static void xen_irq_enable(void) +{ + struct vcpu_info *vcpu; + + /* We don't need to worry about being preempted here, since + either a) interrupts are disabled, so no preemption, or b) + the caller is confused and is trying to re-enable interrupts + on an indeterminate processor. */ + + vcpu = x86_read_percpu(xen_vcpu); + vcpu->evtchn_upcall_mask = 0; + + /* Doesn't matter if we get preempted here, because any + pending event will get dealt with anyway. */ + + barrier(); /* unmask then check (avoid races) */ + if (unlikely(vcpu->evtchn_upcall_pending)) + xen_force_evtchn_callback(); +} + +static void xen_safe_halt(void) +{ + /* Blocking includes an implicit local_irq_enable(). */ + if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) + BUG(); +} + +static void xen_halt(void) +{ + if (irqs_disabled()) + HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); + else + xen_safe_halt(); +} + +static const struct pv_irq_ops xen_irq_ops __initdata = { + .init_IRQ = __xen_init_IRQ, + .save_fl = xen_save_fl, + .restore_fl = xen_restore_fl, + .irq_disable = xen_irq_disable, + .irq_enable = xen_irq_enable, + .safe_halt = xen_safe_halt, + .halt = xen_halt, +#ifdef CONFIG_X86_64 + .adjust_exception_frame = xen_adjust_exception_frame, +#endif +}; + +void __init xen_init_irq_ops() +{ + pv_irq_ops = xen_irq_ops; +} diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 2497a30f41d..42786f59d9c 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -298,7 +298,7 @@ check_events: push %eax push %ecx push %edx - call force_evtchn_callback + call xen_force_evtchn_callback pop %edx pop %ecx pop %eax diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 7f58304fafb..3b9bda46487 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -122,7 +122,7 @@ check_events: push %r9 push %r10 push %r11 - call force_evtchn_callback + call xen_force_evtchn_callback pop %r11 pop %r10 pop %r9 diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 8847fb34f17..3c70ebc50b1 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -31,6 +31,7 @@ void xen_vcpu_restore(void); void __init xen_build_dynamic_phys_to_machine(void); +void xen_init_irq_ops(void); void xen_setup_timer(int cpu); void xen_setup_cpu_clockevents(void); unsigned long xen_tsc_khz(void); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 0e0c28574af..a0837036d89 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -84,17 +84,6 @@ static int irq_bindcount[NR_IRQS]; /* Xen will never allocate port zero for any purpose. */ #define VALID_EVTCHN(chn) ((chn) != 0) -/* - * Force a proper event-channel callback from Xen after clearing the - * callback mask. We do this in a very simple manner, by making a call - * down into Xen. The pending flag will be checked by Xen on return. - */ -void force_evtchn_callback(void) -{ - (void)HYPERVISOR_xen_version(0, NULL); -} -EXPORT_SYMBOL_GPL(force_evtchn_callback); - static struct irq_chip xen_dynamic_chip; /* Constructor for packed IRQ information. */ -- GitLab From cef43bf6b3afd819f7cdcba356af0e8220fb3789 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 28 Jul 2008 13:33:44 -0700 Subject: [PATCH 0217/5416] xen: fix allocation and use of large ldts, cleanup Add a proper comment for set_aliased_prot() and fix an unsigned long/void * warning. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index cf8b3a93122..04ec69e4d02 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -237,8 +237,10 @@ static unsigned long xen_store_tr(void) } /* - * If 'v' is a vmalloc mapping, then find the linear mapping of the - * page (if any) and also set its protections to match: + * Set the page permissions for a particular virtual address. If the + * address is a vmalloc mapping (or other non-linear mapping), then + * find the linear mapping of the page and also set its protections to + * match. */ static void set_aliased_prot(void *v, pgprot_t prot) { @@ -387,8 +389,7 @@ static void xen_load_gs_index(unsigned int idx) static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, const void *ptr) { - unsigned long lp = (unsigned long)&dt[entrynum]; - xmaddr_t mach_lp = arbitrary_virt_to_machine(lp); + xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]); u64 entry = *(u64 *)ptr; preempt_disable(); -- GitLab From 169ad16bb87c10a3f7c108bb7008ebc0270f617a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 28 Jul 2008 18:32:09 -0300 Subject: [PATCH 0218/5416] xen_alloc_ptpage: cast PFN_PHYS() argument to unsigned long Currently paravirt_ops alloc_p*() uses u32 for the pfn args. We should change that later, but while the pfn parameter is still u32, we need to cast the PFN_PHYS() argument at xen_alloc_ptpage() to unsigned long, otherwise it will lose bits on the shift. I think PFN_PHYS() should behave better when fed with smaller integers, but a cast to unsigned long won't be enough for all cases on 32-bit PAE, and a cast to u64 would be overkill for most users of PFN_PHYS(). We could have two different flavors of PFN_PHYS: one for low pages only (unsigned long) and another that works for any page (u64)), but while we don't have it, we will need the cast to unsigned long on xen_alloc_ptpage(). Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 04ec69e4d02..53afa14eb31 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -822,7 +822,7 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) SetPagePinned(page); if (!PageHighMem(page)) { - make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); + make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); if (level == PT_PTE) pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); } else -- GitLab From 7de08b4e1ed8d80e6086f71b7e99fc4b397aae39 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:51 -0300 Subject: [PATCH 0219/5416] x86: coding styles fixes to arch/x86/kernel/process_64.c Fix about 50 errors and many warnings without change process_64.o arch/x86/kernel/process_64.o: text data bss dec hex filename 5236 8 24 5268 1494 process_64.o.after 5236 8 24 5268 1494 process_64.o.before md5: 9c35e9debdea4e471288c6e8ca267a75 process_64.o.after 9c35e9debdea4e471288c6e8ca267a75 process_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 101 +++++++++++++++++------------------ 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3fb62a7d9a1..4da8514dd25 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,11 +37,11 @@ #include #include #include +#include +#include -#include #include #include -#include #include #include #include @@ -88,7 +88,7 @@ void exit_idle(void) #ifdef CONFIG_HOTPLUG_CPU DECLARE_PER_CPU(int, cpu_state); -#include +#include /* We halt the CPU with physical CPU hotplug */ static inline void play_dead(void) { @@ -152,7 +152,7 @@ void cpu_idle(void) } /* Prints also some state that isn't saved in the pt_regs */ -void __show_regs(struct pt_regs * regs) +void __show_regs(struct pt_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; unsigned long d0, d1, d2, d3, d6, d7; @@ -177,28 +177,28 @@ void __show_regs(struct pt_regs * regs) printk("RBP: %016lx R08: %016lx R09: %016lx\n", regs->bp, regs->r8, regs->r9); printk("R10: %016lx R11: %016lx R12: %016lx\n", - regs->r10, regs->r11, regs->r12); + regs->r10, regs->r11, regs->r12); printk("R13: %016lx R14: %016lx R15: %016lx\n", - regs->r13, regs->r14, regs->r15); + regs->r13, regs->r14, regs->r15); - asm("movl %%ds,%0" : "=r" (ds)); - asm("movl %%cs,%0" : "=r" (cs)); - asm("movl %%es,%0" : "=r" (es)); + asm("movl %%ds,%0" : "=r" (ds)); + asm("movl %%cs,%0" : "=r" (cs)); + asm("movl %%es,%0" : "=r" (es)); asm("movl %%fs,%0" : "=r" (fsindex)); asm("movl %%gs,%0" : "=r" (gsindex)); rdmsrl(MSR_FS_BASE, fs); - rdmsrl(MSR_GS_BASE, gs); - rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); + rdmsrl(MSR_GS_BASE, gs); + rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); cr4 = read_cr4(); - printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", - fs,fsindex,gs,gsindex,shadowgs); - printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); + printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + fs, fsindex, gs, gsindex, shadowgs); + printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); get_debugreg(d0, 0); @@ -314,10 +314,10 @@ void prepare_to_copy(struct task_struct *tsk) int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, - struct task_struct * p, struct pt_regs * regs) + struct task_struct *p, struct pt_regs *regs) { int err; - struct pt_regs * childregs; + struct pt_regs *childregs; struct task_struct *me = current; childregs = ((struct pt_regs *) @@ -362,10 +362,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if (test_thread_flag(TIF_IA32)) err = do_set_thread_area(p, -1, (struct user_desc __user *)childregs->si, 0); - else -#endif - err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); - if (err) + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); + if (err) goto out; } err = 0; @@ -544,7 +544,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) unsigned fsindex, gsindex; /* we're going to use this soon, after a few expensive things */ - if (next_p->fpu_counter>5) + if (next_p->fpu_counter > 5) prefetch(next->xstate); /* @@ -552,13 +552,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ load_sp0(tss, next); - /* + /* * Switch DS and ES. * This won't pick up thread selector changes, but I guess that is ok. */ savesegment(es, prev->es); if (unlikely(next->es | prev->es)) - loadsegment(es, next->es); + loadsegment(es, next->es); savesegment(ds, prev->ds); if (unlikely(next->ds | prev->ds)) @@ -584,7 +584,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ arch_leave_lazy_cpu_mode(); - /* + /* * Switch FS and GS. * * Segment register != 0 always requires a reload. Also @@ -593,13 +593,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); - /* + /* * Check if the user used a selector != 0; if yes * clear 64bit base, since overloaded base is always * mapped to the Null selector */ if (fsindex) - prev->fs = 0; + prev->fs = 0; } /* when next process has a 64bit base use it */ if (next->fs) @@ -609,7 +609,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) if (unlikely(gsindex | next->gsindex | prev->gs)) { load_gs_index(next->gsindex); if (gsindex) - prev->gs = 0; + prev->gs = 0; } if (next->gs) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); @@ -618,12 +618,12 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* Must be after DS reload */ unlazy_fpu(prev_p); - /* + /* * Switch the PDA and FPU contexts. */ prev->usersp = read_pda(oldrsp); write_pda(oldrsp, next->usersp); - write_pda(pcurrent, next_p); + write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)task_stack_page(next_p) + @@ -664,7 +664,7 @@ long sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp, struct pt_regs *regs) { long error; - char * filename; + char *filename; filename = getname(name); error = PTR_ERR(filename); @@ -722,55 +722,55 @@ asmlinkage long sys_vfork(struct pt_regs *regs) unsigned long get_wchan(struct task_struct *p) { unsigned long stack; - u64 fp,ip; + u64 fp, ip; int count = 0; - if (!p || p == current || p->state==TASK_RUNNING) - return 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; stack = (unsigned long)task_stack_page(p); if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); - do { + do { if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) - return 0; + return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) return ip; - fp = *(u64 *)fp; - } while (count++ < 16); + fp = *(u64 *)fp; + } while (count++ < 16); return 0; } long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) -{ - int ret = 0; +{ + int ret = 0; int doit = task == current; int cpu; - switch (code) { + switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE_OF(task)) - return -EPERM; + return -EPERM; cpu = get_cpu(); - /* handle small bases via the GDT because that's faster to + /* handle small bases via the GDT because that's faster to switch. */ - if (addr <= 0xffffffff) { - set_32bit_tls(task, GS_TLS, addr); - if (doit) { + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { load_TLS(&task->thread, cpu); - load_gs_index(GS_TLS_SEL); + load_gs_index(GS_TLS_SEL); } - task->thread.gsindex = GS_TLS_SEL; + task->thread.gsindex = GS_TLS_SEL; task->thread.gs = 0; - } else { + } else { task->thread.gsindex = 0; task->thread.gs = addr; if (doit) { load_gs_index(0); ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); - } + } } put_cpu(); break; @@ -824,8 +824,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) rdmsrl(MSR_KERNEL_GS_BASE, base); else base = task->thread.gs; - } - else + } else base = task->thread.gs; ret = put_user(base, (unsigned long __user *)addr); break; -- GitLab From 8092c654de9a964c14d89da56834f73a80548a58 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:52 -0300 Subject: [PATCH 0220/5416] x86: add KERN_INFO to printks on process_64.c Fix many coding style warnings. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 4da8514dd25..3560d7f4d74 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -161,24 +161,24 @@ void __show_regs(struct pt_regs *regs) printk("\n"); print_modules(); - printk("Pid: %d, comm: %.20s %s %s %.*s\n", + printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); - printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); + printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); printk_address(regs->ip, 1); - printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, - regs->flags); - printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, + regs->sp, regs->flags); + printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", regs->ax, regs->bx, regs->cx); - printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", regs->dx, regs->si, regs->di); - printk("RBP: %016lx R08: %016lx R09: %016lx\n", + printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", regs->bp, regs->r8, regs->r9); - printk("R10: %016lx R11: %016lx R12: %016lx\n", + printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", regs->r10, regs->r11, regs->r12); - printk("R13: %016lx R14: %016lx R15: %016lx\n", + printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", regs->r13, regs->r14, regs->r15); asm("movl %%ds,%0" : "=r" (ds)); @@ -196,24 +196,26 @@ void __show_regs(struct pt_regs *regs) cr3 = read_cr3(); cr4 = read_cr4(); - printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", fs, fsindex, gs, gsindex, shadowgs); - printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); - printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); + printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, + es, cr0); + printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, + cr4); get_debugreg(d0, 0); get_debugreg(d1, 1); get_debugreg(d2, 2); - printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); + printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); get_debugreg(d3, 3); get_debugreg(d6, 6); get_debugreg(d7, 7); - printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); + printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); } void show_regs(struct pt_regs *regs) { - printk("CPU %d:", smp_processor_id()); + printk(KERN_INFO "CPU %d:", smp_processor_id()); __show_regs(regs); show_trace(NULL, regs, (void *)(regs + 1), regs->bp); } -- GitLab From 08aadf069d0482ade033badefa8f03eb2fcddd9c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:53 -0300 Subject: [PATCH 0221/5416] x86: coding style fixes to arch/x86/kernel/crash_dump_64.c Fix conding style without change crash_dump_64.o arch/x86/kernel/crash_dump_64.o text data bss dec hex filename 129 0 0 129 81 crash_dump_64.o.after 129 0 0 129 81 crash_dump_64.o.before md5: 885b52c1b92737e6b12e5107e90fc1f1 crash_dump_64.o.after 885b52c1b92737e6b12e5107e90fc1f1 crash_dump_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash_dump_64.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 15e6c6bc4a4..d3e524c8452 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -7,9 +7,8 @@ #include #include - -#include -#include +#include +#include /** * copy_oldmem_page - copy one page from "oldmem" @@ -25,7 +24,7 @@ * in the current kernel. We stitch up a pte, similar to kmap_atomic. */ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, int userbuf) + size_t csize, unsigned long offset, int userbuf) { void *vaddr; -- GitLab From caa007dd3687d38a0252484d9d0a8f9d929ba932 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:54 -0300 Subject: [PATCH 0222/5416] x86: coding style fixes to arch/x86/kernel/signal_64.c Fix all errors and many warnings reported by checkpatch.pl without change signal_64.o arch/x86/kernel/signal_64.o text data bss dec hex filename 5143 0 8 5151 141f signal_64.o.after 5143 0 8 5151 141f signal_64.o.before md5: e68718092b3641cb27e79e55ce57e3ad signal_64.o.after e68718092b3641cb27e79e55ce57e3ad signal_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/sigframe.h | 5 +++ arch/x86/kernel/signal_64.c | 62 ++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h index 72bbb519d2d..8b4956e800a 100644 --- a/arch/x86/kernel/sigframe.h +++ b/arch/x86/kernel/sigframe.h @@ -24,4 +24,9 @@ struct rt_sigframe { struct ucontext uc; struct siginfo info; }; + +int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs); +int ia32_setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs); #endif diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index b45ef8ddd65..87a9c2f28d9 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -19,9 +19,10 @@ #include #include #include +#include + #include #include -#include #include #include #include @@ -41,11 +42,6 @@ # define FIX_EFLAGS __FIX_EFLAGS #endif -int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs); -int ia32_setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs * regs); - asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) @@ -119,7 +115,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; -#define COPY(x) err |= __get_user(regs->x, &sc->x) +#define COPY(x) (err |= __get_user(regs->x, &sc->x)) COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); @@ -149,7 +145,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user * buf; + struct _fpstate __user *buf; err |= __get_user(buf, &sc->fpstate); if (buf) { @@ -189,7 +185,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) goto badframe; @@ -199,16 +195,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) return ax; badframe: - signal_fault(regs,frame,"sigreturn"); + signal_fault(regs, frame, "sigreturn"); return 0; -} +} /* * Set up a signal frame. */ static inline int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, + unsigned long mask, struct task_struct *me) { int err = 0; @@ -264,35 +261,35 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; + struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; if (used_math()) { - fp = get_stack(ka, regs, sizeof(struct _fpstate)); + fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; - if (save_i387(fp) < 0) - err |= -1; + if (save_i387(fp) < 0) + err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - if (ka->sa.sa_flags & SA_SIGINFO) { + if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; } - + /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); @@ -302,9 +299,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); - if (sizeof(*set) == 16) { + if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); - __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); } else err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -315,7 +312,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { /* could use a vstub here */ - goto give_sigsegv; + goto give_sigsegv; } if (err) @@ -323,7 +320,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->di = sig; - /* In case the signal handler was declared without prototypes */ + /* In case the signal handler was declared without prototypes */ regs->ax = 0; /* This also works for non SA_SIGINFO handlers because they expect the @@ -376,7 +373,7 @@ static long current_syscall_ret(struct pt_regs *regs) /* * OK, we're invoking a handler - */ + */ static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, @@ -420,7 +417,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); - } else + } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); @@ -448,9 +445,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); + sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } @@ -552,14 +549,15 @@ void do_notify_resume(struct pt_regs *regs, void *unused, } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) -{ - struct task_struct *me = current; +{ + struct task_struct *me = current; if (show_unhandled_signals && printk_ratelimit()) { printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", - me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); + me->comm, me->pid, where, frame, regs->ip, + regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); printk("\n"); } - force_sig(SIGSEGV, me); -} + force_sig(SIGSEGV, me); +} -- GitLab From 4df9e510a9fda29aca71d8acac853b98aa6884d1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:55 -0300 Subject: [PATCH 0223/5416] x86: coding style fixes to arch/x86/kernel/traps_64.c Fix all errors and many warnings reported by checkpath.pl. Except the change of include to the traps.o before and after changes are the same. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 59 +++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3f18d73f420..fe36d96ba70 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #if defined(CONFIG_EDAC) #include @@ -45,9 +47,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -85,7 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) void printk_address(unsigned long address, int reliable) { - printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address); + printk(" [<%016lx>] %s%pS\n", address, reliable ? + "" : "? ", (void *) address); } static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -98,7 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", #if DEBUG_STKSZ > EXCEPTION_STKSZ - [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" + [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / + EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; unsigned k; @@ -163,7 +164,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, } /* - * x86-64 can have up to three kernel stacks: + * x86-64 can have up to three kernel stacks: * process stack * interrupt stack * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack @@ -219,7 +220,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, const struct stacktrace_ops *ops, void *data) { const unsigned cpu = get_cpu(); - unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr; + unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; unsigned used = 0; struct thread_info *tinfo; @@ -237,7 +238,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!bp) { if (task == current) { /* Grab bp right from our regs */ - asm("movq %%rbp, %0" : "=r" (bp) :); + asm("movq %%rbp, %0" : "=r" (bp) : ); } else { /* bp is the last reg pushed by switch_to */ bp = *(unsigned long *) task->thread.sp; @@ -357,11 +358,13 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack; int i; const int cpu = smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr); - unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); + unsigned long *irqstack_end = + (unsigned long *) (cpu_pda(cpu)->irqstackptr); + unsigned long *irqstack = + (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); - // debugging aid: "show_stack(NULL, NULL);" prints the - // back trace for this cpu. + /* debugging aid: "show_stack(NULL, NULL);" prints the + back trace for this cpu. */ if (sp == NULL) { if (task) @@ -404,7 +407,7 @@ void dump_stack(void) #ifdef CONFIG_FRAME_POINTER if (!bp) - asm("movq %%rbp, %0" : "=r" (bp):); + asm("movq %%rbp, %0" : "=r" (bp) : ); #endif printk("Pid: %d, comm: %.20s %s %s %.*s\n", @@ -414,7 +417,6 @@ void dump_stack(void) init_utsname()->version); show_trace(NULL, NULL, &stack, bp); } - EXPORT_SYMBOL(dump_stack); void show_registers(struct pt_regs *regs) @@ -493,7 +495,7 @@ unsigned __kprobes long oops_begin(void) raw_local_irq_save(flags); cpu = smp_processor_id(); if (!__raw_spin_trylock(&die_lock)) { - if (cpu == die_owner) + if (cpu == die_owner) /* nested oops. should stop eventually */; else __raw_spin_lock(&die_lock); @@ -638,7 +640,7 @@ kernel_trap: } #define DO_ERROR(trapnr, signr, str, name) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ @@ -648,7 +650,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ } #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ @@ -683,7 +685,7 @@ asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) preempt_conditional_cli(regs); } -asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) +asmlinkage void do_double_fault(struct pt_regs *regs, long error_code) { static const char str[] = "double fault"; struct task_struct *tsk = current; @@ -778,9 +780,10 @@ io_check_error(unsigned char reason, struct pt_regs *regs) } static notrace __kprobes void -unknown_nmi_error(unsigned char reason, struct pt_regs * regs) +unknown_nmi_error(unsigned char reason, struct pt_regs *regs) { - if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) + if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == + NOTIFY_STOP) return; printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", reason); @@ -882,7 +885,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) else if (user_mode(eregs)) regs = task_pt_regs(current); /* Exception from kernel and interrupts are enabled. Move to - kernel process stack. */ + kernel process stack. */ else if (eregs->flags & X86_EFLAGS_IF) regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); if (eregs != regs) @@ -891,7 +894,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) } /* runs on IST stack. */ -asmlinkage void __kprobes do_debug(struct pt_regs * regs, +asmlinkage void __kprobes do_debug(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk = current; @@ -1035,7 +1038,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs) asmlinkage void bad_intr(void) { - printk("bad interrupt"); + printk("bad interrupt"); } asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) @@ -1047,7 +1050,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) conditional_sti(regs); if (!user_mode(regs) && - kernel_math_error(regs, "kernel simd math error", 19)) + kernel_math_error(regs, "kernel simd math error", 19)) return; /* @@ -1092,7 +1095,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) +asmlinkage void do_spurious_interrupt_bug(struct pt_regs *regs) { } @@ -1142,8 +1145,10 @@ void __init trap_init(void) set_intr_gate(0, ÷_error); set_intr_gate_ist(1, &debug, DEBUG_STACK); set_intr_gate_ist(2, &nmi, NMI_STACK); - set_system_gate_ist(3, &int3, DEBUG_STACK); /* int3 can be called from all */ - set_system_gate(4, &overflow); /* int4 can be called from all */ + /* int3 can be called from all */ + set_system_gate_ist(3, &int3, DEBUG_STACK); + /* int4 can be called from all */ + set_system_gate(4, &overflow); set_intr_gate(5, &bounds); set_intr_gate(6, &invalid_op); set_intr_gate(7, &device_not_available); -- GitLab From e9c8abb66cc37801bdb5d4360bb78d180c3bbb73 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 29 Jul 2008 02:48:56 -0300 Subject: [PATCH 0224/5416] x86: coding style fixes to arch/x86/kernel/sys_x86_64.c Fix all errors and many warnings reported by checkpatch.pl without change sys_x86_64.o arch/x86/kernel/sys_x86_64.o: text data bss dec hex filename 1567 0 0 1567 61f sys_x86_64.o.after 1567 0 0 1567 61f sys_x86_64.o.before md5: de28ffedcb5851dfd7ec87a03afec1fd sys_x86_64.o.after de28ffedcb5851dfd7ec87a03afec1fd sys_x86_64.o.before Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/sys_x86_64.c | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 3b360ef3381..56eb8f916e9 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -13,15 +13,16 @@ #include #include #include +#include -#include #include -asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long off) +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off) { long error; - struct file * file; + struct file *file; error = -EINVAL; if (off & ~PAGE_MASK) @@ -56,9 +57,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, unmapped base down for this case. This can give conflicts with the heap, but we assume that glibc malloc knows how to fall back to mmap. Give it 1GB - of playground for now. -AK */ - *begin = 0x40000000; - *end = 0x80000000; + of playground for now. -AK */ + *begin = 0x40000000; + *end = 0x80000000; if (current->flags & PF_RANDOMIZE) { new_begin = randomize_range(*begin, *begin + 0x02000000, 0); if (new_begin) @@ -66,9 +67,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, } } else { *begin = TASK_UNMAPPED_BASE; - *end = TASK_SIZE; + *end = TASK_SIZE; } -} +} unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, @@ -78,11 +79,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; unsigned long start_addr; unsigned long begin, end; - + if (flags & MAP_FIXED) return addr; - find_start_end(flags, &begin, &end); + find_start_end(flags, &begin, &end); if (len > end) return -ENOMEM; @@ -96,12 +97,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, } if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32)) && len <= mm->cached_hole_size) { - mm->cached_hole_size = 0; + mm->cached_hole_size = 0; mm->free_area_cache = begin; } addr = mm->free_area_cache; - if (addr < begin) - addr = begin; + if (addr < begin) + addr = begin; start_addr = addr; full_search: @@ -127,7 +128,7 @@ full_search: return addr; } if (addr + mm->cached_hole_size < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; + mm->cached_hole_size = vma->vm_start - addr; addr = vma->vm_end; } @@ -177,7 +178,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr-len); if (!vma || addr <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr-len); + return mm->free_area_cache = addr-len; } if (mm->mmap_base < len) @@ -194,7 +195,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr); if (!vma || addr+len <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr); + return mm->free_area_cache = addr; /* remember the largest hole we saw so far */ if (addr + mm->cached_hole_size < vma->vm_start) @@ -224,13 +225,13 @@ bottomup: } -asmlinkage long sys_uname(struct new_utsname __user * name) +asmlinkage long sys_uname(struct new_utsname __user *name) { int err; down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); + err = copy_to_user(name, utsname(), sizeof(*name)); up_read(&uts_sem); - if (personality(current->personality) == PER_LINUX32) - err |= copy_to_user(&name->machine, "i686", 5); + if (personality(current->personality) == PER_LINUX32) + err |= copy_to_user(&name->machine, "i686", 5); return err ? -EFAULT : 0; } -- GitLab From 64a76f667d987a559ad0726b4692c987800b22bc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 29 Jul 2008 12:47:38 -0700 Subject: [PATCH 0225/5416] hpet: /dev/hpet - fixes and cleanup Minor /dev/hpet updates and bugfixes: * Remove dead code, mostly remnants of an incomplete/unusable kernel interface ... noted when addressing "sparse" warnings: + hpet_unregister() and a routine it calls + hpet_task and all references, including hpet_task_lock + hpet_data.hd_flags (and HPET_DATA_PLATFORM) * Correct and improve boot message: + displays *counter* (shared between comparators) bit width, not *timer* bit widths (which are often mixed) + relabel "timers" as "comparators"; this is less confusing, they are not independent like normal timers are (sigh) + display MHz not Hz; it's never less than 10 MHz. * Tighten and correct the userspace interface code + don't accidentally program comparators in 64-bit mode using 32-bit values ... always force comparators into 32-bit mode + provide the correct bit definition flagging comparators with periodic capability ... the ABI is unchanged * Update Documentation/hpet.txt + be more correct and current + expand description a bit + don't mention that now-gone kernel interface Plus, add a FIXME comment for something that could cause big trouble on systems with more capable HPETs than at least Intel seems to ship. It seems that few folk use this userspace interface; it's not very usable given the general lack of HPET IRQ routing. I'm told that the only real point of it any more is to mmap for fast timestamps; IMO that's handled better through the gettimeofday() vsyscall. Signed-off-by: David Brownell Acked-by: Clemens Ladisch Signed-off-by: Ingo Molnar --- Documentation/timers/hpet.txt | 43 ++++++++--------- arch/x86/kernel/hpet.c | 6 ++- drivers/char/hpet.c | 90 ++++++++++------------------------- include/linux/hpet.h | 11 +---- 4 files changed, 51 insertions(+), 99 deletions(-) diff --git a/Documentation/timers/hpet.txt b/Documentation/timers/hpet.txt index 6ad52d9dad6..e7c09abcfab 100644 --- a/Documentation/timers/hpet.txt +++ b/Documentation/timers/hpet.txt @@ -1,21 +1,32 @@ High Precision Event Timer Driver for Linux -The High Precision Event Timer (HPET) hardware is the future replacement -for the 8254 and Real Time Clock (RTC) periodic timer functionality. -Each HPET can have up to 32 timers. It is possible to configure the -first two timers as legacy replacements for 8254 and RTC periodic timers. -A specification done by Intel and Microsoft can be found at -. +The High Precision Event Timer (HPET) hardware follows a specification +by Intel and Microsoft which can be found at + + http://www.intel.com/technology/architecture/hpetspec.htm + +Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision") +and up to 32 comparators. Normally three or more comparators are provided, +each of which can generate oneshot interupts and at least one of which has +additional hardware to support periodic interrupts. The comparators are +also called "timers", which can be misleading since usually timers are +independent of each other ... these share a counter, complicating resets. + +HPET devices can support two interrupt routing modes. In one mode, the +comparators are additional interrupt sources with no particular system +role. Many x86 BIOS writers don't route HPET interrupts at all, which +prevents use of that mode. They support the other "legacy replacement" +mode where the first two comparators block interrupts from 8254 timers +and from the RTC. The driver supports detection of HPET driver allocation and initialization of the HPET before the driver module_init routine is called. This enables platform code which uses timer 0 or 1 as the main timer to intercept HPET initialization. An example of this initialization can be found in -arch/i386/kernel/time_hpet.c. +arch/x86/kernel/hpet.c. -The driver provides two APIs which are very similar to the API found in -the rtc.c driver. There is a user space API and a kernel space API. -An example user space program is provided below. +The driver provides a userspace API which resembles the API found in the +RTC driver framework. An example user space program is provided below. #include #include @@ -286,15 +297,3 @@ out: return; } - -The kernel API has three interfaces exported from the driver: - - hpet_register(struct hpet_task *tp, int periodic) - hpet_unregister(struct hpet_task *tp) - hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) - -The kernel module using this interface fills in the ht_func and ht_data -members of the hpet_task structure before calling hpet_register. -hpet_control simply vectors to the hpet_ioctl routine and has the same -commands and respective arguments as the user API. hpet_unregister -is used to terminate usage of the HPET timer reserved by hpet_register. diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ad2b15a1334..82d459186fd 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id) hd.hd_phys_address = hpet_address; hd.hd_address = hpet; hd.hd_nirqs = nrtimers; - hd.hd_flags = HPET_DATA_PLATFORM; hpet_reserve_timer(&hd, 0); #ifdef CONFIG_HPET_EMULATE_RTC hpet_reserve_timer(&hd, 1); #endif + /* + * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254 + * is wrong for i8259!) not the output IRQ. Many BIOS writers + * don't bother configuring *any* comparator interrupts. + */ hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index f3981ffe20f..4bc1da4d4f8 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -53,6 +53,11 @@ #define HPET_RANGE_SIZE 1024 /* from HPET spec */ + +/* WARNING -- don't get confused. These macros are never used + * to write the (single) counter, and rarely to read it. + * They're badly named; to fix, someday. + */ #if BITS_PER_LONG == 64 #define write_counter(V, MC) writeq(V, MC) #define read_counter(MC) readq(MC) @@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = { .rating = 250, .read = read_hpet, .mask = CLOCKSOURCE_MASK(64), - .mult = 0, /*to be caluclated*/ + .mult = 0, /* to be calculated */ .shift = 10, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource; /* A lock for concurrent access by app and isr hpet activity. */ static DEFINE_SPINLOCK(hpet_lock); -/* A lock for concurrent intermodule access to hpet and isr hpet activity. */ -static DEFINE_SPINLOCK(hpet_task_lock); #define HPET_DEV_NAME (7) @@ -99,7 +102,6 @@ struct hpet_dev { unsigned long hd_irqdata; wait_queue_head_t hd_waitqueue; struct fasync_struct *hd_async_queue; - struct hpet_task *hd_task; unsigned int hd_flags; unsigned int hd_irq; unsigned int hd_hdwirq; @@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data) writel(isr, &devp->hd_hpet->hpet_isr); spin_unlock(&hpet_lock); - spin_lock(&hpet_task_lock); - if (devp->hd_task) - devp->hd_task->ht_func(devp->hd_task->ht_data); - spin_unlock(&hpet_task_lock); - wake_up_interruptible(&devp->hd_waitqueue); kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); @@ -260,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file) for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) for (i = 0; i < hpetp->hp_ntimer; i++) - if (hpetp->hp_dev[i].hd_flags & HPET_OPEN - || hpetp->hp_dev[i].hd_task) + if (hpetp->hp_dev[i].hd_flags & HPET_OPEN) continue; else { devp = &hpetp->hp_dev[i]; @@ -504,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) devp->hd_irq = irq; t = devp->hd_ireqfreq; v = readq(&timer->hpet_config); - g = v | Tn_INT_ENB_CNF_MASK; + + /* 64-bit comparators are not yet supported through the ioctls, + * so force this into 32-bit mode if it supports both modes + */ + g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK; if (devp->hd_flags & HPET_PERIODIC) { write_counter(t, &timer->hpet_compare); @@ -514,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) v |= Tn_VAL_SET_CNF_MASK; writeq(v, &timer->hpet_config); local_irq_save(flags); + + /* NOTE: what we modify here is a hidden accumulator + * register supported by periodic-capable comparators. + * We never want to modify the (single) counter; that + * would affect all the comparators. + */ m = read_counter(&hpet->hpet_mc); write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); } else { @@ -667,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp) return 0; } -static inline int hpet_tpcheck(struct hpet_task *tp) -{ - struct hpet_dev *devp; - struct hpets *hpetp; - - devp = tp->ht_opaque; - - if (!devp) - return -ENXIO; - - for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (devp >= hpetp->hp_dev - && devp < (hpetp->hp_dev + hpetp->hp_ntimer) - && devp->hd_hpet == hpetp->hp_hpet) - return 0; - - return -ENXIO; -} - -#if 0 -int hpet_unregister(struct hpet_task *tp) -{ - struct hpet_dev *devp; - struct hpet_timer __iomem *timer; - int err; - - if ((err = hpet_tpcheck(tp))) - return err; - - spin_lock_irq(&hpet_task_lock); - spin_lock(&hpet_lock); - - devp = tp->ht_opaque; - if (devp->hd_task != tp) { - spin_unlock(&hpet_lock); - spin_unlock_irq(&hpet_task_lock); - return -ENXIO; - } - - timer = devp->hd_timer; - writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), - &timer->hpet_config); - devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC); - devp->hd_task = NULL; - spin_unlock(&hpet_lock); - spin_unlock_irq(&hpet_task_lock); - - return 0; -} -#endif /* 0 */ - static ctl_table hpet_table[] = { { .ctl_name = CTL_UNNUMBERED, @@ -872,9 +827,12 @@ int hpet_alloc(struct hpet_data *hdp) printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); printk("\n"); - printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", - hpetp->hp_which, hpetp->hp_ntimer, - cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); + printk(KERN_INFO + "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n", + hpetp->hp_which, hpetp->hp_ntimer, + cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, + (unsigned) (hpetp->hp_tick_freq / 1000000), + (unsigned) (hpetp->hp_tick_freq % 1000000)); mcfg = readq(&hpet->hpet_config); if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { diff --git a/include/linux/hpet.h b/include/linux/hpet.h index 6d2626b63a9..79f63a27bce 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h @@ -92,23 +92,14 @@ struct hpet { * exported interfaces */ -struct hpet_task { - void (*ht_func) (void *); - void *ht_data; - void *ht_opaque; -}; - struct hpet_data { unsigned long hd_phys_address; void __iomem *hd_address; unsigned short hd_nirqs; - unsigned short hd_flags; unsigned int hd_state; /* timer allocated */ unsigned int hd_irq[HPET_MAX_TIMERS]; }; -#define HPET_DATA_PLATFORM 0x0001 /* platform call to hpet_alloc */ - static inline void hpet_reserve_timer(struct hpet_data *hd, int timer) { hd->hd_state |= (1 << timer); @@ -126,7 +117,7 @@ struct hpet_info { unsigned short hi_timer; }; -#define HPET_INFO_PERIODIC 0x0001 /* timer is periodic */ +#define HPET_INFO_PERIODIC 0x0010 /* periodic-capable comparator */ #define HPET_IE_ON _IO('h', 0x01) /* interrupt on */ #define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */ -- GitLab From f92a789d259eb95afe7498ff5938fe2a93d39c82 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 31 Jul 2008 12:59:56 -0700 Subject: [PATCH 0226/5416] hpet: /dev/hpet - fixes and cleanup, fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: On Thursday 31 July 2008, Ingo Molnar wrote: >   drivers/built-in.o: In function `hpet_alloc': >   : undefined reference to `__udivdi3' >   drivers/built-in.o: In function `hpet_alloc': >   : undefined reference to `__umoddi3' Signed-off-by: David Brownell Signed-off-by: Ingo Molnar --- drivers/char/hpet.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 4bc1da4d4f8..2908a0eb63a 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -764,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp) static struct hpets *last = NULL; unsigned long period; unsigned long long temp; + u32 remainder; /* * hpet_alloc can be called by platform dependent code. @@ -827,12 +828,13 @@ int hpet_alloc(struct hpet_data *hdp) printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); printk("\n"); + temp = hpetp->hp_tick_freq; + remainder = do_div(temp, 1000000); printk(KERN_INFO "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n", hpetp->hp_which, hpetp->hp_ntimer, cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, - (unsigned) (hpetp->hp_tick_freq / 1000000), - (unsigned) (hpetp->hp_tick_freq % 1000000)); + (unsigned) temp, remainder); mcfg = readq(&hpet->hpet_config); if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { -- GitLab From a677f58a8c8c541bf7d02c658545084040f3708d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 29 Jul 2008 00:37:10 -0700 Subject: [PATCH 0227/5416] x86: print per_cpu data address to make sure per_cpu data on correct node. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup_percpu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index f7745f94c00..61f3966632a 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -180,9 +180,16 @@ void __init setup_per_cpu_areas(void) printk(KERN_INFO "cpu %d has no node %d or node-local memory\n", cpu, node); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n", + cpu, __pa(ptr)); } - else + else { ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n", + cpu, node, __pa(ptr)); + } #endif per_cpu_offset(cpu) = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); -- GitLab From a0ac87d61ba20932e54f08464d3f3439d78fa878 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:04 +0200 Subject: [PATCH 0228/5416] x86: AMD microcode patch loader style corrections Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 07e52beacb4..6789530ef33 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -47,9 +47,9 @@ MODULE_LICENSE("GPL v2"); #define UCODE_UCODE_TYPE 0x00000001 #define UCODE_MAX_SIZE (2048) -#define DEFAULT_UCODE_DATASIZE (896) /* 896 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) /* 64 bytes */ -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */ +#define DEFAULT_UCODE_DATASIZE (896) +#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define DWSIZE (sizeof(u32)) /* For now we support a fixed ucode total size only */ #define get_totalsize(mc) \ -- GitLab From f516526febb75500f280def2108688d388df4e1e Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:05 +0200 Subject: [PATCH 0229/5416] x86: Intel microcode patch loader style corrections Signed-off-by: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 6da4a85ff46..a61986e8b69 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -55,8 +55,8 @@ * in a single CPU package. * 1.10 28 Feb 2002 Asit K Mallick and * Tigran Aivazian , - * Serialize updates as required on HT processors due to speculative - * nature of implementation. + * Serialize updates as required on HT processors due to + * speculative nature of implementation. * 1.11 22 Mar 2002 Tigran Aivazian * Fix the panic when writing zero-length microcode chunk. * 1.12 29 Sep 2003 Nitin Kamble , @@ -71,7 +71,7 @@ * Thanks to Stuart Swales for pointing out this bug. */ -//#define DEBUG /* pr_debug */ +/* #define DEBUG */ /* pr_debug */ #include #include #include @@ -99,11 +99,11 @@ MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ -#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */ -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ -#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */ -#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */ +#define DEFAULT_UCODE_DATASIZE (2000) +#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) +#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) +#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) #define DWSIZE (sizeof(u32)) #define get_totalsize(mc) \ (((struct microcode_intel *)mc)->hdr.totalsize ? \ -- GitLab From 831f9bd3151ebd22959a0cb2a20b44a06b26d4ed Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:06 +0200 Subject: [PATCH 0230/5416] x86: moved function declarations out from AMD microcode patch loader to heade file Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 6789530ef33..2b98e6ab1bf 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -56,9 +56,6 @@ MODULE_LICENSE("GPL v2"); ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ + MC_HEADER_SIZE) -extern int microcode_init(void *opaque, struct module *module); -extern void microcode_exit(void); - /* serialize access to the physical write */ static DEFINE_SPINLOCK(microcode_update_lock); -- GitLab From daa9c0fee1cbe1d49fbe29af3d4bb16312043b1e Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Tue, 29 Jul 2008 17:41:07 +0200 Subject: [PATCH 0231/5416] x86: minor pointer type cast in AMD microcode patch loader Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_amd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 2b98e6ab1bf..33b2a217a8c 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -394,7 +394,8 @@ static int cpu_request_microcode_amd(int cpu) return error; } - buf_pos = buf = firmware->data; + buf_pos = (unsigned int *)firmware->data; + buf = (void *)firmware->data; size = firmware->size; if (buf_pos[0] != UCODE_MAGIC) { -- GitLab From 7ab6af7ab69df8c9c5fbc380004fb81187742096 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 30 Jul 2008 17:36:48 -0700 Subject: [PATCH 0232/5416] x86_32: use apic_ops at print_local_APIC() Use apic_icr_read at print_local_APIC() in io_apic_32.c Signed-off-by: Hiroshi Shimamoto Cc: Suresh Siddha Cc: Yinghai Lu Signed-off-by: Ingo Molnar Cc: Suresh Siddha Cc: Yinghai Lu --- arch/x86/kernel/io_apic_32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 98e4db5373f..39e063a9a28 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -1486,6 +1486,7 @@ static void print_APIC_bitfield(int base) void /*__init*/ print_local_APIC(void *dummy) { unsigned int v, ver, maxlvt; + u64 icr; if (apic_verbosity == APIC_QUIET) return; @@ -1536,10 +1537,9 @@ void /*__init*/ print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC ESR: %08x\n", v); } - v = apic_read(APIC_ICR); - printk(KERN_DEBUG "... APIC ICR: %08x\n", v); - v = apic_read(APIC_ICR2); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); + icr = apic_icr_read(); + printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); -- GitLab From 687fbc3fece34e7e1c2ac529348ad897095a0bde Mon Sep 17 00:00:00 2001 From: Pawel MOLL Date: Fri, 1 Aug 2008 11:23:44 +0100 Subject: [PATCH 0233/5416] ALSA: IEC958 definition for consumer status channel update Updated IEC958 consumer status channel definitions according to the third edition of IEC60958-3 spec. Signed-off-by: Pawel Moll Signed-off-by: Jaroslav Kysela --- include/sound/asoundef.h | 89 +++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h index a6e0facf8a3..20ebf3298eb 100644 --- a/include/sound/asoundef.h +++ b/include/sound/asoundef.h @@ -60,35 +60,56 @@ #define IEC958_AES1_PRO_USERBITS_UDEF (12<<4) /* user defined application */ #define IEC958_AES1_CON_CATEGORY 0x7f #define IEC958_AES1_CON_GENERAL 0x00 -#define IEC958_AES1_CON_EXPERIMENTAL 0x40 -#define IEC958_AES1_CON_SOLIDMEM_MASK 0x0f -#define IEC958_AES1_CON_SOLIDMEM_ID 0x08 -#define IEC958_AES1_CON_BROADCAST1_MASK 0x07 -#define IEC958_AES1_CON_BROADCAST1_ID 0x04 -#define IEC958_AES1_CON_DIGDIGCONV_MASK 0x07 -#define IEC958_AES1_CON_DIGDIGCONV_ID 0x02 -#define IEC958_AES1_CON_ADC_COPYRIGHT_MASK 0x1f -#define IEC958_AES1_CON_ADC_COPYRIGHT_ID 0x06 -#define IEC958_AES1_CON_ADC_MASK 0x1f -#define IEC958_AES1_CON_ADC_ID 0x16 -#define IEC958_AES1_CON_BROADCAST2_MASK 0x0f -#define IEC958_AES1_CON_BROADCAST2_ID 0x0e #define IEC958_AES1_CON_LASEROPT_MASK 0x07 #define IEC958_AES1_CON_LASEROPT_ID 0x01 -#define IEC958_AES1_CON_MUSICAL_MASK 0x07 -#define IEC958_AES1_CON_MUSICAL_ID 0x05 -#define IEC958_AES1_CON_MAGNETIC_MASK 0x07 -#define IEC958_AES1_CON_MAGNETIC_ID 0x03 #define IEC958_AES1_CON_IEC908_CD (IEC958_AES1_CON_LASEROPT_ID|0x00) #define IEC958_AES1_CON_NON_IEC908_CD (IEC958_AES1_CON_LASEROPT_ID|0x08) +#define IEC958_AES1_CON_MINI_DISC (IEC958_AES1_CON_LASEROPT_ID|0x48) +#define IEC958_AES1_CON_DVD (IEC958_AES1_CON_LASEROPT_ID|0x18) +#define IEC958_AES1_CON_LASTEROPT_OTHER (IEC958_AES1_CON_LASEROPT_ID|0x78) +#define IEC958_AES1_CON_DIGDIGCONV_MASK 0x07 +#define IEC958_AES1_CON_DIGDIGCONV_ID 0x02 #define IEC958_AES1_CON_PCM_CODER (IEC958_AES1_CON_DIGDIGCONV_ID|0x00) -#define IEC958_AES1_CON_SAMPLER (IEC958_AES1_CON_DIGDIGCONV_ID|0x20) #define IEC958_AES1_CON_MIXER (IEC958_AES1_CON_DIGDIGCONV_ID|0x10) #define IEC958_AES1_CON_RATE_CONVERTER (IEC958_AES1_CON_DIGDIGCONV_ID|0x18) -#define IEC958_AES1_CON_SYNTHESIZER (IEC958_AES1_CON_MUSICAL_ID|0x00) -#define IEC958_AES1_CON_MICROPHONE (IEC958_AES1_CON_MUSICAL_ID|0x08) +#define IEC958_AES1_CON_SAMPLER (IEC958_AES1_CON_DIGDIGCONV_ID|0x20) +#define IEC958_AES1_CON_DSP (IEC958_AES1_CON_DIGDIGCONV_ID|0x28) +#define IEC958_AES1_CON_DIGDIGCONV_OTHER (IEC958_AES1_CON_DIGDIGCONV_ID|0x78) +#define IEC958_AES1_CON_MAGNETIC_MASK 0x07 +#define IEC958_AES1_CON_MAGNETIC_ID 0x03 #define IEC958_AES1_CON_DAT (IEC958_AES1_CON_MAGNETIC_ID|0x00) #define IEC958_AES1_CON_VCR (IEC958_AES1_CON_MAGNETIC_ID|0x08) +#define IEC958_AES1_CON_DCC (IEC958_AES1_CON_MAGNETIC_ID|0x40) +#define IEC958_AES1_CON_MAGNETIC_DISC (IEC958_AES1_CON_MAGNETIC_ID|0x18) +#define IEC958_AES1_CON_MAGNETIC_OTHER (IEC958_AES1_CON_MAGNETIC_ID|0x78) +#define IEC958_AES1_CON_BROADCAST1_MASK 0x07 +#define IEC958_AES1_CON_BROADCAST1_ID 0x04 +#define IEC958_AES1_CON_DAB_JAPAN (IEC958_AES1_CON_BROADCAST1_ID|0x00) +#define IEC958_AES1_CON_DAB_EUROPE (IEC958_AES1_CON_BROADCAST1_ID|0x08) +#define IEC958_AES1_CON_DAB_USA (IEC958_AES1_CON_BROADCAST1_ID|0x60) +#define IEC958_AES1_CON_SOFTWARE (IEC958_AES1_CON_BROADCAST1_ID|0x40) +#define IEC958_AES1_CON_IEC62105 (IEC958_AES1_CON_BROADCAST1_ID|0x20) +#define IEC958_AES1_CON_BROADCAST1_OTHER (IEC958_AES1_CON_BROADCAST1_ID|0x78) +#define IEC958_AES1_CON_BROADCAST2_MASK 0x0f +#define IEC958_AES1_CON_BROADCAST2_ID 0x0e +#define IEC958_AES1_CON_MUSICAL_MASK 0x07 +#define IEC958_AES1_CON_MUSICAL_ID 0x05 +#define IEC958_AES1_CON_SYNTHESIZER (IEC958_AES1_CON_MUSICAL_ID|0x00) +#define IEC958_AES1_CON_MICROPHONE (IEC958_AES1_CON_MUSICAL_ID|0x08) +#define IEC958_AES1_CON_MUSICAL_OTHER (IEC958_AES1_CON_MUSICAL_ID|0x78) +#define IEC958_AES1_CON_ADC_MASK 0x1f +#define IEC958_AES1_CON_ADC_ID 0x06 +#define IEC958_AES1_CON_ADC (IEC958_AES1_CON_ADC_ID|0x00) +#define IEC958_AES1_CON_ADC_OTHER (IEC958_AES1_CON_ADC_ID|0x60) +#define IEC958_AES1_CON_ADC_COPYRIGHT_MASK 0x1f +#define IEC958_AES1_CON_ADC_COPYRIGHT_ID 0x16 +#define IEC958_AES1_CON_ADC_COPYRIGHT (IEC958_AES1_CON_ADC_COPYRIGHT_ID|0x00) +#define IEC958_AES1_CON_ADC_COPYRIGHT_OTHER (IEC958_AES1_CON_ADC_COPYRIGHT_ID|0x60) +#define IEC958_AES1_CON_SOLIDMEM_MASK 0x0f +#define IEC958_AES1_CON_SOLIDMEM_ID 0x08 +#define IEC958_AES1_CON_SOLIDMEM_DIGITAL_RECORDER_PLAYER (IEC958_AES1_CON_SOLIDMEM_ID|0x00) +#define IEC958_AES1_CON_SOLIDMEM_OTHER (IEC958_AES1_CON_SOLIDMEM_ID|0x70) +#define IEC958_AES1_CON_EXPERIMENTAL 0x40 #define IEC958_AES1_CON_ORIGINAL (1<<7) /* this bits depends on the category code */ #define IEC958_AES2_PRO_SBITS (7<<0) /* mask - sample bits */ #define IEC958_AES2_PRO_SBITS_20 (2<<0) /* 20-bit - coordination */ @@ -106,8 +127,16 @@ #define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */ #define IEC958_AES3_CON_FS (15<<0) /* mask - sample frequency */ #define IEC958_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */ +#define IEC958_AES3_CON_FS_NOTID (1<<0) /* non indicated */ #define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */ #define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */ +#define IEC958_AES3_CON_FS_22050 (4<<0) /* 22.05kHz */ +#define IEC958_AES3_CON_FS_24000 (6<<0) /* 24kHz */ +#define IEC958_AES3_CON_FS_88200 (8<<0) /* 88.2kHz */ +#define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */ +#define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */ +#define IEC958_AES3_CON_FS_176400 (12<<0) /* 176.4kHz */ +#define IEC958_AES3_CON_FS_192000 (14<<0) /* 192kHz */ #define IEC958_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */ #define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */ #define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */ @@ -120,6 +149,26 @@ #define IEC958_AES4_CON_WORDLEN_23_19 (4<<1) /* 23-bit or 19-bit */ #define IEC958_AES4_CON_WORDLEN_24_20 (5<<1) /* 24-bit or 20-bit */ #define IEC958_AES4_CON_WORDLEN_21_17 (6<<1) /* 21-bit or 17-bit */ +#define IEC958_AES4_CON_ORIGFS (15<<4) /* mask - original sample frequency */ +#define IEC958_AES4_CON_ORIGFS_NOTID (0<<4) /* not indicated */ +#define IEC958_AES4_CON_ORIGFS_192000 (1<<4) /* 192kHz */ +#define IEC958_AES4_CON_ORIGFS_12000 (2<<4) /* 12kHz */ +#define IEC958_AES4_CON_ORIGFS_176400 (3<<4) /* 176.4kHz */ +#define IEC958_AES4_CON_ORIGFS_96000 (5<<4) /* 96kHz */ +#define IEC958_AES4_CON_ORIGFS_8000 (6<<4) /* 8kHz */ +#define IEC958_AES4_CON_ORIGFS_88200 (7<<4) /* 88.2kHz */ +#define IEC958_AES4_CON_ORIGFS_16000 (8<<4) /* 16kHz */ +#define IEC958_AES4_CON_ORIGFS_24000 (9<<4) /* 24kHz */ +#define IEC958_AES4_CON_ORIGFS_11025 (10<<4) /* 11.025kHz */ +#define IEC958_AES4_CON_ORIGFS_22050 (11<<4) /* 22.05kHz */ +#define IEC958_AES4_CON_ORIGFS_32000 (12<<4) /* 32kHz */ +#define IEC958_AES4_CON_ORIGFS_48000 (13<<4) /* 48kHz */ +#define IEC958_AES4_CON_ORIGFS_44100 (15<<4) /* 44.1kHz */ +#define IEC958_AES5_CON_CGMSA (3<<0) /* mask - CGMS-A */ +#define IEC958_AES5_CON_CGMSA_COPYFREELY (0<<0) /* copying is permitted without restriction */ +#define IEC958_AES5_CON_CGMSA_COPYONCE (1<<0) /* one generation of copies may be made */ +#define IEC958_AES5_CON_CGMSA_COPYNOMORE (2<<0) /* condition not be used */ +#define IEC958_AES5_CON_CGMSA_COPYNEVER (3<<0) /* no copying is permitted */ /***************************************************************************** * * -- GitLab From 896e6cc20e67038af12e1a7711eef32647e62f23 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 1 Aug 2008 13:36:04 +0200 Subject: [PATCH 0234/5416] sound: Revert "ALSA: Fix limit of 8 PCM devices in SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE" This reverts commit fb3d6f2b77bdec75d45aa9d4464287ed87927866. New, updated patch with same subject replaces this commit. Signed-off-by: Jaroslav Kysela --- include/sound/minors.h | 2 -- include/sound/pcm.h | 4 +++- sound/core/oss/pcm_oss.c | 10 ++++---- sound/core/pcm.c | 50 +++++++++++----------------------------- sound/core/sound.c | 2 ++ 5 files changed, 23 insertions(+), 45 deletions(-) diff --git a/include/sound/minors.h b/include/sound/minors.h index a81798ab73e..46bcd2023ed 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -21,8 +21,6 @@ * */ -#define SNDRV_OS_MINORS 256 - #define SNDRV_MINOR_DEVICES 32 #define SNDRV_MINOR_CARD(minor) ((minor) >> 5) #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index bfc096ac82e..51d58ccda2d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -84,6 +84,8 @@ struct snd_pcm_ops { * */ +#define SNDRV_PCM_DEVICES 8 + #define SNDRV_PCM_IOCTL1_FALSE ((void *)0) #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) @@ -414,7 +416,7 @@ struct snd_pcm_str { struct snd_pcm { struct snd_card *card; struct list_head list; - int device; /* device number */ + unsigned int device; /* device number */ unsigned int info_flags; unsigned short dev_class; unsigned short dev_subclass; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4ccd761a5f4..4c601b192dd 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2947,7 +2947,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index) static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) { pcm->oss.reg = 0; - if (dsp_map[pcm->card->number] == pcm->device) { + if (dsp_map[pcm->card->number] == (int)pcm->device) { char name[128]; int duplex; register_oss_dsp(pcm, 0); @@ -2963,7 +2963,7 @@ static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) pcm->oss.reg++; pcm->oss.reg_mask |= 1; } - if (adsp_map[pcm->card->number] == pcm->device) { + if (adsp_map[pcm->card->number] == (int)pcm->device) { register_oss_dsp(pcm, 1); pcm->oss.reg++; pcm->oss.reg_mask |= 2; @@ -2988,7 +2988,7 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, pcm->card, 1); } - if (dsp_map[pcm->card->number] == pcm->device) { + if (dsp_map[pcm->card->number] == (int)pcm->device) { #ifdef SNDRV_OSS_INFO_DEV_AUDIO snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); #endif @@ -3019,12 +3019,12 @@ static int __init alsa_pcm_oss_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { - if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_OS_MINORS) { + if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", i, dsp_map[i]); dsp_map[i] = 0; } - if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_OS_MINORS) { + if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", i, adsp_map[i]); adsp_map[i] = 1; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 24271a3bd90..ece25c718e9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) +static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,37 +53,6 @@ static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) return NULL; } -static inline int snd_pcm_next(struct snd_card *card, int device) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == card && pcm->device > device) - return pcm->device; - else if (pcm->card->number > card->number) - return -1; - } - return -1; -} - -static inline int snd_pcm_add(struct snd_pcm *newpcm) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == newpcm->card && pcm->device == newpcm->device) - return -EBUSY; - if (pcm->card->number > newpcm->card->number || - (pcm->card == newpcm->card && - pcm->device > newpcm->device)) { - list_add(&newpcm->list, pcm->list.prev); - return 0; - } - } - list_add_tail(&newpcm->list, &snd_pcm_devices); - return 0; -} - static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -96,7 +65,14 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = snd_pcm_next(card, device); + device = device < 0 ? 0 : device + 1; + while (device < SNDRV_PCM_DEVICES) { + if (snd_pcm_search(card, device)) + break; + device++; + } + if (device == SNDRV_PCM_DEVICES) + device = -1; mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -122,7 +98,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_get(card, device); + pcm = snd_pcm_search(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -955,11 +931,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - err = snd_pcm_add(pcm); - if (err) { + if (snd_pcm_search(pcm->card, pcm->device)) { mutex_unlock(®ister_mutex); - return err; + return -EBUSY; } + list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) diff --git a/sound/core/sound.c b/sound/core/sound.c index 838dd9ee957..1003ae375d4 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -34,6 +34,8 @@ #include #include +#define SNDRV_OS_MINORS 256 + static int major = CONFIG_SND_MAJOR; int snd_major; EXPORT_SYMBOL(snd_major); -- GitLab From 030a07e441296c372f946cd4065b5d831d8dc40c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Wed, 30 Jul 2008 15:13:29 +0200 Subject: [PATCH 0235/5416] ALSA: Add USB US122L driver Added a new US122L usb-audio driver. This driver works together with a dedicated alsa-lib plugin. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/asound.h | 3 +- sound/usb/Kconfig | 11 + sound/usb/Makefile | 1 + sound/usb/usbaudio.h | 1 + sound/usb/usbmidi.c | 39 ++ sound/usb/usx2y/Makefile | 2 + sound/usb/usx2y/us122l.c | 692 +++++++++++++++++++++++++++++++ sound/usb/usx2y/us122l.h | 27 ++ sound/usb/usx2y/usb_stream.c | 761 +++++++++++++++++++++++++++++++++++ sound/usb/usx2y/usb_stream.h | 112 ++++++ 10 files changed, 1648 insertions(+), 1 deletion(-) create mode 100644 sound/usb/usx2y/us122l.c create mode 100644 sound/usb/usx2y/us122l.h create mode 100644 sound/usb/usx2y/usb_stream.c create mode 100644 sound/usb/usx2y/usb_stream.h diff --git a/include/sound/asound.h b/include/sound/asound.h index 3eaf155b850..ca2f3582664 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -93,9 +93,10 @@ enum { SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ + SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ /* Don't forget to change the following: */ - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_HDA + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM }; struct snd_hwdep_info { diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index ffcdc8f4ef6..0463b342ec7 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -67,5 +67,16 @@ config SND_USB_CAIAQ_INPUT * Native Instruments Kore Controller 2 * Native Instruments Audio Kontrol 1 +config SND_USB_US122L + tristate "Tascam US-122L USB driver" + depends on X86 && EXPERIMENTAL + select SND_RAWMIDI + help + Say Y here to include support for Tascam US-122L USB Audio/MIDI + interfaces. + + To compile this driver as a module, choose M here: the module + will be called snd-usb-us122l. + endif # SND_USB diff --git a/sound/usb/Makefile b/sound/usb/Makefile index aa252ef2ebf..abb288bfe35 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -8,5 +8,6 @@ snd-usb-lib-objs := usbmidi.o # Toplevel Module Dependency obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o +obj-$(CONFIG_SND_USB_US122L) += snd-usb-lib.o obj-$(CONFIG_SND) += usx2y/ caiaq/ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 7cf18c38dc4..140ba363414 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -156,6 +156,7 @@ enum quirk_type { QUIRK_MIDI_RAW, QUIRK_MIDI_EMAGIC, QUIRK_MIDI_CME, + QUIRK_MIDI_US122L, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UA700_UA25, diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 6676a177c99..c0c7770198a 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -669,6 +669,42 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = { .output = snd_usbmidi_raw_output, }; +static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep, + uint8_t *buffer, int buffer_length) +{ + if (buffer_length != 9) + return; + buffer_length = 8; + while (buffer_length && buffer[buffer_length - 1] == 0xFD) + buffer_length--; + if (buffer_length) + snd_usbmidi_input_data(ep, 0, buffer, buffer_length); +} + +static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep) +{ + int count; + + if (!ep->ports[0].active) + return; + count = ep->urb->dev->speed == USB_SPEED_HIGH ? 1 : 2; + count = snd_rawmidi_transmit(ep->ports[0].substream, + ep->urb->transfer_buffer, + count); + if (count < 1) { + ep->ports[0].active = 0; + return; + } + + memset(ep->urb->transfer_buffer + count, 0xFD, 9 - count); + ep->urb->transfer_buffer_length = count; +} + +static struct usb_protocol_ops snd_usbmidi_122l_ops = { + .input = snd_usbmidi_us122l_input, + .output = snd_usbmidi_us122l_output, +}; + /* * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching. */ @@ -1714,6 +1750,9 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip, umidi->usb_protocol_ops = &snd_usbmidi_maudio_broken_running_status_ops; break; + case QUIRK_MIDI_US122L: + umidi->usb_protocol_ops = &snd_usbmidi_122l_ops; + /* fall through */ case QUIRK_MIDI_FIXED_ENDPOINT: memcpy(&endpoints[0], quirk->data, sizeof(struct snd_usb_midi_endpoint_info)); diff --git a/sound/usb/usx2y/Makefile b/sound/usb/usx2y/Makefile index 9ac22bce112..748933054b6 100644 --- a/sound/usb/usx2y/Makefile +++ b/sound/usb/usx2y/Makefile @@ -1,3 +1,5 @@ snd-usb-usx2y-objs := usbusx2y.o usX2Yhwdep.o usx2yhwdeppcm.o +snd-usb-us122l-objs := us122l.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-usx2y.o +obj-$(CONFIG_SND_USB_US122L) += snd-usb-us122l.o diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c new file mode 100644 index 00000000000..b441fe2cd19 --- /dev/null +++ b/sound/usb/usx2y/us122l.c @@ -0,0 +1,692 @@ +/* + * Copyright (C) 2007, 2008 Karsten Wiese + * + * 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 +#define MODNAME "US122L" +#include "usb_stream.c" +#include "../usbaudio.h" +#include "us122l.h" + +MODULE_AUTHOR("Karsten Wiese "); +MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.5"); +MODULE_LICENSE("GPL"); + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ + /* Enable this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS"."); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); + +static int snd_us122l_card_used[SNDRV_CARDS]; + + +static int us122l_create_usbmidi(struct snd_card *card) +{ + static struct snd_usb_midi_endpoint_info quirk_data = { + .out_ep = 4, + .in_ep = 3, + .out_cables = 0x001, + .in_cables = 0x001 + }; + static struct snd_usb_audio_quirk quirk = { + .vendor_name = "US122L", + .product_name = NAME_ALLCAPS, + .ifnum = 1, + .type = QUIRK_MIDI_US122L, + .data = &quirk_data + }; + struct usb_device *dev = US122L(card)->chip.dev; + struct usb_interface *iface = usb_ifnum_to_if(dev, 1); + + return snd_usb_create_midi_interface(&US122L(card)->chip, + iface, &quirk); +} + +/* + * Wrapper for usb_control_msg(). + * Allocates a temp buffer to prevent dmaing from/to the stack. + */ +static int us122l_ctl_msg(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, + __u16 value, __u16 index, void *data, + __u16 size, int timeout) +{ + int err; + void *buf = NULL; + + if (size > 0) { + buf = kmemdup(data, size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } + err = usb_control_msg(dev, pipe, request, requesttype, + value, index, buf, size, timeout); + if (size > 0) { + memcpy(data, buf, size); + kfree(buf); + } + return err; +} + +static void pt_info_set(struct usb_device *dev, u8 v) +{ + int ret; + + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 'I', + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + v, 0, NULL, 0, 1000); + snd_printdd(KERN_DEBUG "%i\n", ret); +} + +static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) +{ + struct us122l *us122l = area->vm_private_data; + atomic_inc(&us122l->mmap_count); + snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); +} + +static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area, + struct vm_fault *vmf) +{ + unsigned long offset; + struct page *page; + void *vaddr; + struct us122l *us122l = area->vm_private_data; + struct usb_stream *s; + int vm_f = VM_FAULT_SIGBUS; + + mutex_lock(&us122l->mutex); + s = us122l->sk.s; + if (!s) + goto out; + + offset = vmf->pgoff << PAGE_SHIFT; + if (offset < PAGE_ALIGN(s->read_size)) + vaddr = (char *)s + offset; + else { + offset -= PAGE_ALIGN(s->read_size); + if (offset >= PAGE_ALIGN(s->write_size)) + goto out; + + vaddr = us122l->sk.write_page + offset; + } + page = virt_to_page(vaddr); + + get_page(page); + mutex_unlock(&us122l->mutex); + + vmf->page = page; + vm_f = 0; +out: + return vm_f; +} + +static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) +{ + struct us122l *us122l = area->vm_private_data; + atomic_dec(&us122l->mmap_count); + snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); +} + +static struct vm_operations_struct usb_stream_hwdep_vm_ops = { + .open = usb_stream_hwdep_vm_open, + .fault = usb_stream_hwdep_vm_fault, + .close = usb_stream_hwdep_vm_close, +}; + + +static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) +{ + struct us122l *us122l = hw->private_data; + struct usb_interface *iface; + snd_printdd(KERN_DEBUG "%p %p\n", hw, file); + if (hw->used >= 2) + return -EBUSY; + + if (!us122l->first) + us122l->first = file; + iface = usb_ifnum_to_if(us122l->chip.dev, 1); + usb_autopm_get_interface(iface); + return 0; +} + +static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) +{ + struct us122l *us122l = hw->private_data; + struct usb_interface *iface = usb_ifnum_to_if(us122l->chip.dev, 1); + snd_printdd(KERN_DEBUG "%p %p\n", hw, file); + usb_autopm_put_interface(iface); + if (us122l->first == file) + us122l->first = NULL; + mutex_lock(&us122l->mutex); + if (us122l->master == file) + us122l->master = us122l->slave; + + us122l->slave = NULL; + mutex_unlock(&us122l->mutex); + return 0; +} + +static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, + struct file *filp, struct vm_area_struct *area) +{ + unsigned long size = area->vm_end - area->vm_start; + struct us122l *us122l = hw->private_data; + unsigned long offset; + struct usb_stream *s; + int err = 0; + bool read; + + offset = area->vm_pgoff << PAGE_SHIFT; + mutex_lock(&us122l->mutex); + s = us122l->sk.s; + read = offset < s->read_size; + if (read && area->vm_flags & VM_WRITE) { + err = -EPERM; + goto out; + } + snd_printdd(KERN_DEBUG "%lu %u\n", size, + read ? s->read_size : s->write_size); + /* if userspace tries to mmap beyond end of our buffer, fail */ + if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) { + snd_printk(KERN_WARNING "%lu > %u\n", size, + read ? s->read_size : s->write_size); + err = -EINVAL; + goto out; + } + + area->vm_ops = &usb_stream_hwdep_vm_ops; + area->vm_flags |= VM_RESERVED; + area->vm_private_data = us122l; + atomic_inc(&us122l->mmap_count); +out: + mutex_unlock(&us122l->mutex); + return err; +} + +static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw, + struct file *file, poll_table *wait) +{ + struct us122l *us122l = hw->private_data; + struct usb_stream *s = us122l->sk.s; + unsigned *polled; + unsigned int mask; + + poll_wait(file, &us122l->sk.sleep, wait); + + switch (s->state) { + case usb_stream_ready: + if (us122l->first == file) + polled = &s->periods_polled; + else + polled = &us122l->second_periods_polled; + if (*polled != s->periods_done) { + *polled = s->periods_done; + mask = POLLIN | POLLOUT | POLLWRNORM; + break; + } + /* Fall through */ + mask = 0; + break; + default: + mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR; + break; + } + return mask; +} + +static void us122l_stop(struct us122l *us122l) +{ + struct list_head *p; + list_for_each(p, &us122l->chip.midi_list) + snd_usbmidi_input_stop(p); + + usb_stream_stop(&us122l->sk); + usb_stream_free(&us122l->sk); +} + +static int us122l_set_sample_rate(struct usb_device *dev, int rate) +{ + unsigned int ep = 0x81; + unsigned char data[3]; + int err; + + data[0] = rate; + data[1] = rate >> 8; + data[2] = rate >> 16; + err = us122l_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, + USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, + SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000); + if (err < 0) + snd_printk(KERN_ERR "%d: cannot set freq %d to ep 0x%x\n", + dev->devnum, rate, ep); + return err; +} + +static bool us122l_start(struct us122l *us122l, + unsigned rate, unsigned period_frames) +{ + struct list_head *p; + int err; + unsigned use_packsize = 0; + bool success = false; + + if (us122l->chip.dev->speed == USB_SPEED_HIGH) { + /* The us-122l's descriptor defaults to iso max_packsize 78, + which isn't needed for samplerates <= 48000. + Lets save some memory: + */ + switch (rate) { + case 44100: + use_packsize = 36; + break; + case 48000: + use_packsize = 42; + break; + case 88200: + use_packsize = 72; + break; + } + } + if (!usb_stream_new(&us122l->sk, us122l->chip.dev, 1, 2, + rate, use_packsize, period_frames, 6)) + goto out; + + err = us122l_set_sample_rate(us122l->chip.dev, rate); + if (err < 0) { + us122l_stop(us122l); + snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); + goto out; + } + err = usb_stream_start(&us122l->sk); + if (err < 0) { + us122l_stop(us122l); + snd_printk(KERN_ERR "us122l_start error %i \n", err); + goto out; + } + list_for_each(p, &us122l->chip.midi_list) + snd_usbmidi_input_start(p); + success = true; +out: + return success; +} + +static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, + unsigned cmd, unsigned long arg) +{ + struct usb_stream_config *cfg; + struct us122l *us122l = hw->private_data; + unsigned min_period_frames; + int err = 0; + bool high_speed; + + if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS) + return -ENOTTY; + + cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + if (copy_from_user(cfg, (void *)arg, sizeof(*cfg))) { + err = -EFAULT; + goto free; + } + if (cfg->version != USB_STREAM_INTERFACE_VERSION) { + err = -ENXIO; + goto free; + } + high_speed = us122l->chip.dev->speed == USB_SPEED_HIGH; + if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000 && + (!high_speed || + (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) || + cfg->frame_size != 6 || + cfg->period_frames > 0x3000) { + err = -EINVAL; + goto free; + } + switch (cfg->sample_rate) { + case 44100: + min_period_frames = 48; + break; + case 48000: + min_period_frames = 52; + break; + default: + min_period_frames = 104; + break; + } + if (!high_speed) + min_period_frames <<= 1; + if (cfg->period_frames < min_period_frames) { + err = -EINVAL; + goto free; + } + + snd_power_wait(hw->card, SNDRV_CTL_POWER_D0); + + mutex_lock(&us122l->mutex); + if (!us122l->master) + us122l->master = file; + else if (us122l->master != file) { + if (memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg))) { + err = -EIO; + goto unlock; + } + us122l->slave = file; + } + if (!us122l->sk.s || + memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg)) || + us122l->sk.s->state == usb_stream_xrun) { + us122l_stop(us122l); + if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames)) + err = -EIO; + else + err = 1; + } +unlock: + mutex_unlock(&us122l->mutex); +free: + kfree(cfg); + return err; +} + +#define SND_USB_STREAM_ID "USB STREAM" +static int usb_stream_hwdep_new(struct snd_card *card) +{ + int err; + struct snd_hwdep *hw; + struct usb_device *dev = US122L(card)->chip.dev; + + err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw); + if (err < 0) + return err; + + hw->iface = SNDRV_HWDEP_IFACE_USB_STREAM; + hw->private_data = US122L(card); + hw->ops.open = usb_stream_hwdep_open; + hw->ops.release = usb_stream_hwdep_release; + hw->ops.ioctl = usb_stream_hwdep_ioctl; + hw->ops.ioctl_compat = usb_stream_hwdep_ioctl; + hw->ops.mmap = usb_stream_hwdep_mmap; + hw->ops.poll = usb_stream_hwdep_poll; + + sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm", + dev->bus->busnum, dev->devnum); + return 0; +} + + +static bool us122l_create_card(struct snd_card *card) +{ + int err; + struct us122l *us122l = US122L(card); + + err = usb_set_interface(us122l->chip.dev, 1, 1); + if (err) { + snd_printk(KERN_ERR "usb_set_interface error \n"); + return false; + } + + pt_info_set(us122l->chip.dev, 0x11); + pt_info_set(us122l->chip.dev, 0x10); + + if (!us122l_start(us122l, 44100, 256)) + return false; + + err = us122l_create_usbmidi(card); + if (err < 0) { + snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); + us122l_stop(us122l); + return false; + } + err = usb_stream_hwdep_new(card); + if (err < 0) { +/* release the midi resources */ + struct list_head *p; + list_for_each(p, &us122l->chip.midi_list) + snd_usbmidi_disconnect(p); + + us122l_stop(us122l); + return false; + } + return true; +} + +static struct snd_card *usx2y_create_card(struct usb_device *device) +{ + int dev; + struct snd_card *card; + for (dev = 0; dev < SNDRV_CARDS; ++dev) + if (enable[dev] && !snd_us122l_card_used[dev]) + break; + if (dev >= SNDRV_CARDS) + return NULL; + card = snd_card_new(index[dev], id[dev], THIS_MODULE, + sizeof(struct us122l)); + if (!card) + return NULL; + snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; + + US122L(card)->chip.dev = device; + US122L(card)->chip.card = card; + mutex_init(&US122L(card)->mutex); + init_waitqueue_head(&US122L(card)->sk.sleep); + INIT_LIST_HEAD(&US122L(card)->chip.midi_list); + strcpy(card->driver, "USB "NAME_ALLCAPS""); + sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); + sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", + card->shortname, + le16_to_cpu(device->descriptor.idVendor), + le16_to_cpu(device->descriptor.idProduct), + 0, + US122L(card)->chip.dev->bus->busnum, + US122L(card)->chip.dev->devnum + ); + snd_card_set_dev(card, &device->dev); + return card; +} + +static void *us122l_usb_probe(struct usb_interface *intf, + const struct usb_device_id *device_id) +{ + struct usb_device *device = interface_to_usbdev(intf); + struct snd_card *card = usx2y_create_card(device); + + if (!card) + return NULL; + + if (!us122l_create_card(card) || + snd_card_register(card) < 0) { + snd_card_free(card); + return NULL; + } + + usb_get_dev(device); + return card; +} + +static int snd_us122l_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct snd_card *card; + snd_printdd(KERN_DEBUG"%p:%i\n", + intf, intf->cur_altsetting->desc.bInterfaceNumber); + if (intf->cur_altsetting->desc.bInterfaceNumber != 1) + return 0; + + card = us122l_usb_probe(usb_get_intf(intf), id); + + if (card) { + usb_set_intfdata(intf, card); + return 0; + } + + usb_put_intf(intf); + return -EIO; +} + +static void snd_us122l_disconnect(struct usb_interface *intf) +{ + struct snd_card *card; + struct us122l *us122l; + struct list_head *p; + + card = usb_get_intfdata(intf); + if (!card) + return; + + snd_card_disconnect(card); + + us122l = US122L(card); + mutex_lock(&us122l->mutex); + us122l_stop(us122l); + mutex_unlock(&us122l->mutex); + us122l->chip.shutdown = 1; + +/* release the midi resources */ + list_for_each(p, &us122l->chip.midi_list) { + snd_usbmidi_disconnect(p); + } + + usb_put_intf(intf); + usb_put_dev(US122L(card)->chip.dev); + + while (atomic_read(&us122l->mmap_count)) + msleep(500); + + snd_card_free(card); +} + +static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct snd_card *card; + struct us122l *us122l; + struct list_head *p; + + card = dev_get_drvdata(&intf->dev); + if (!card) + return 0; + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + us122l = US122L(card); + if (!us122l) + return 0; + + list_for_each(p, &us122l->chip.midi_list) + snd_usbmidi_input_stop(p); + + mutex_lock(&us122l->mutex); + usb_stream_stop(&us122l->sk); + mutex_unlock(&us122l->mutex); + + return 0; +} + +static int snd_us122l_resume(struct usb_interface *intf) +{ + struct snd_card *card; + struct us122l *us122l; + struct list_head *p; + int err; + + card = dev_get_drvdata(&intf->dev); + if (!card) + return 0; + + us122l = US122L(card); + if (!us122l) + return 0; + + mutex_lock(&us122l->mutex); + /* needed, doesn't restart without: */ + err = usb_set_interface(us122l->chip.dev, 1, 1); + if (err) { + snd_printk(KERN_ERR "usb_set_interface error \n"); + goto unlock; + } + + pt_info_set(us122l->chip.dev, 0x11); + pt_info_set(us122l->chip.dev, 0x10); + + err = us122l_set_sample_rate(us122l->chip.dev, + us122l->sk.s->cfg.sample_rate); + if (err < 0) { + snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); + goto unlock; + } + err = usb_stream_start(&us122l->sk); + if (err) + goto unlock; + + list_for_each(p, &us122l->chip.midi_list) + snd_usbmidi_input_start(p); +unlock: + mutex_unlock(&us122l->mutex); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return err; +} + +static struct usb_device_id snd_us122l_usb_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x0644, + .idProduct = USB_ID_US122L + }, +/* { */ /* US-144 maybe works when @USB1.1. Untested. */ +/* .match_flags = USB_DEVICE_ID_MATCH_DEVICE, */ +/* .idVendor = 0x0644, */ +/* .idProduct = USB_ID_US144 */ +/* }, */ + { /* terminator */ } +}; + +MODULE_DEVICE_TABLE(usb, snd_us122l_usb_id_table); +static struct usb_driver snd_us122l_usb_driver = { + .name = "snd-usb-us122l", + .probe = snd_us122l_probe, + .disconnect = snd_us122l_disconnect, + .suspend = snd_us122l_suspend, + .resume = snd_us122l_resume, + .reset_resume = snd_us122l_resume, + .id_table = snd_us122l_usb_id_table, + .supports_autosuspend = 1 +}; + + +static int __init snd_us122l_module_init(void) +{ + return usb_register(&snd_us122l_usb_driver); +} + +static void __exit snd_us122l_module_exit(void) +{ + usb_deregister(&snd_us122l_usb_driver); +} + +module_init(snd_us122l_module_init) +module_exit(snd_us122l_module_exit) diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h new file mode 100644 index 00000000000..3d10c4b2a0f --- /dev/null +++ b/sound/usb/usx2y/us122l.h @@ -0,0 +1,27 @@ +#ifndef US122L_H +#define US122L_H + + +struct us122l { + struct snd_usb_audio chip; + int stride; + struct usb_stream_kernel sk; + + struct mutex mutex; + struct file *first; + unsigned second_periods_polled; + struct file *master; + struct file *slave; + + atomic_t mmap_count; +}; + + +#define US122L(c) ((struct us122l *)(c)->private_data) + +#define NAME_ALLCAPS "US-122L" + +#define USB_ID_US122L 0x800E +#define USB_ID_US144 0x800F + +#endif diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c new file mode 100644 index 00000000000..ff23cc1ce3b --- /dev/null +++ b/sound/usb/usx2y/usb_stream.c @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2007, 2008 Karsten Wiese + * + * 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 "usb_stream.h" + + +/* setup */ + +static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk) +{ + struct usb_stream *s = sk->s; + sk->out_phase_peeked = (sk->out_phase & 0xffff) + sk->freqn; + return (sk->out_phase_peeked >> 16) * s->cfg.frame_size; +} + +static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) +{ + struct usb_stream *s = sk->s; + unsigned l = 0; + int pack; + + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = usb_stream_next_packet_size(sk); + sk->out_phase = sk->out_phase_peeked; + urb->transfer_buffer_length = urb->iso_frame_desc[0].length; + + for (pack = 1; pack < sk->n_o_ps; pack++) { + l = usb_stream_next_packet_size(sk); + if (s->idle_outsize + urb->transfer_buffer_length + l > + s->period_size) + goto check; + + sk->out_phase = sk->out_phase_peeked; + urb->iso_frame_desc[pack].offset = urb->transfer_buffer_length; + urb->iso_frame_desc[pack].length = l; + urb->transfer_buffer_length += l; + } + snd_printdd(KERN_DEBUG "%i\n", urb->transfer_buffer_length); + +check: + urb->number_of_packets = pack; + s->idle_outsize += urb->transfer_buffer_length - s->period_size; + snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize, + urb->transfer_buffer_length, s->period_size); +} + +static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + struct urb **urbs, char *transfer, + struct usb_device *dev, int pipe) +{ + int u, p; + int maxpacket = use_packsize ? + use_packsize : usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + int transfer_length = maxpacket * sk->n_o_ps; + + for (u = 0; u < USB_STREAM_NURBS; + ++u, transfer += transfer_length) { + struct urb *urb = urbs[u]; + struct usb_iso_packet_descriptor *desc; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = transfer; + urb->dev = dev; + urb->pipe = pipe; + urb->number_of_packets = sk->n_o_ps; + urb->context = sk; + urb->interval = 1; + if (usb_pipeout(pipe)) + continue; + + urb->transfer_buffer_length = transfer_length; + desc = urb->iso_frame_desc; + desc->offset = 0; + desc->length = maxpacket; + for (p = 1; p < sk->n_o_ps; ++p) { + desc[p].offset = desc[p - 1].offset + maxpacket; + desc[p].length = maxpacket; + } + } +} + +static void init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + struct usb_device *dev, int in_pipe, int out_pipe) +{ + struct usb_stream *s = sk->s; + char *indata = (char *)s + sizeof(*s) + + sizeof(struct usb_stream_packet) * + s->inpackets; + int u; + + for (u = 0; u < USB_STREAM_NURBS; ++u) { + sk->inurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL); + sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL); + } + + init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe); + init_pipe_urbs(sk, use_packsize, sk->outurb, sk->write_page, dev, + out_pipe); +} + + +/* + * convert a sampling rate into our full speed format (fs/1000 in Q16.16) + * this will overflow at approx 524 kHz + */ +static inline unsigned get_usb_full_speed_rate(unsigned rate) +{ + return ((rate << 13) + 62) / 125; +} + +/* + * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) + * this will overflow at approx 4 MHz + */ +static inline unsigned get_usb_high_speed_rate(unsigned rate) +{ + return ((rate << 10) + 62) / 125; +} + +void usb_stream_free(struct usb_stream_kernel *sk) +{ + struct usb_stream *s; + unsigned u; + + for (u = 0; u < USB_STREAM_NURBS; ++u) { + usb_free_urb(sk->inurb[u]); + sk->inurb[u] = NULL; + usb_free_urb(sk->outurb[u]); + sk->outurb[u] = NULL; + } + + s = sk->s; + if (!s) + return; + + free_pages((unsigned long)sk->write_page, get_order(s->write_size)); + sk->write_page = NULL; + free_pages((unsigned long)s, get_order(s->read_size)); + sk->s = NULL; +} + +struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, + struct usb_device *dev, + unsigned in_endpoint, unsigned out_endpoint, + unsigned sample_rate, unsigned use_packsize, + unsigned period_frames, unsigned frame_size) +{ + int packets, max_packsize; + int in_pipe, out_pipe; + int read_size = sizeof(struct usb_stream); + int write_size; + int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000; + int pg; + + in_pipe = usb_rcvisocpipe(dev, in_endpoint); + out_pipe = usb_sndisocpipe(dev, out_endpoint); + + max_packsize = use_packsize ? + use_packsize : usb_maxpacket(dev, in_pipe, 0); + + /* + t_period = period_frames / sample_rate + iso_packs = t_period / t_iso_frame + = (period_frames / sample_rate) * (1 / t_iso_frame) + */ + + packets = period_frames * usb_frames / sample_rate + 1; + + if (dev->speed == USB_SPEED_HIGH) + packets = (packets + 7) & ~7; + + read_size += packets * USB_STREAM_URBDEPTH * + (max_packsize + sizeof(struct usb_stream_packet)); + + max_packsize = usb_maxpacket(dev, out_pipe, 1); + write_size = max_packsize * packets * USB_STREAM_URBDEPTH; + + if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) { + snd_printk(KERN_WARNING "a size exceeds 128*PAGE_SIZE\n"); + goto out; + } + + pg = get_order(read_size); + sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + if (!sk->s) { + snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); + goto out; + } + sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; + + sk->s->read_size = read_size; + + sk->s->cfg.sample_rate = sample_rate; + sk->s->cfg.frame_size = frame_size; + sk->n_o_ps = packets; + sk->s->inpackets = packets * USB_STREAM_URBDEPTH; + sk->s->cfg.period_frames = period_frames; + sk->s->period_size = frame_size * period_frames; + + sk->s->write_size = write_size; + pg = get_order(write_size); + + sk->write_page = + (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); + if (!sk->write_page) { + snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); + usb_stream_free(sk); + return NULL; + } + + /* calculate the frequency in 16.16 format */ + if (dev->speed == USB_SPEED_FULL) + sk->freqn = get_usb_full_speed_rate(sample_rate); + else + sk->freqn = get_usb_high_speed_rate(sample_rate); + + init_urbs(sk, use_packsize, dev, in_pipe, out_pipe); + sk->s->state = usb_stream_stopped; +out: + return sk->s; +} + + +/* start */ + +static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb) +{ + bool r; + if (unlikely(urb->status)) { + if (urb->status != -ESHUTDOWN && urb->status != -ENOENT) + snd_printk(KERN_WARNING "status=%i\n", urb->status); + sk->iso_frame_balance = 0x7FFFFFFF; + return false; + } + r = sk->iso_frame_balance == 0; + if (!r) + sk->i_urb = urb; + return r; +} + +static bool balance_playback(struct usb_stream_kernel *sk, struct urb *urb) +{ + sk->iso_frame_balance += urb->number_of_packets; + return balance_check(sk, urb); +} + +static bool balance_capture(struct usb_stream_kernel *sk, struct urb *urb) +{ + sk->iso_frame_balance -= urb->number_of_packets; + return balance_check(sk, urb); +} + +static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) +{ + int u; + + for (u = 0; u < USB_STREAM_NURBS; u++) { + struct urb *urb = urbs[u]; + urb->complete = complete; + } +} + +int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct urb *inurb) +{ + struct usb_stream *s = sk->s; + struct urb *io; + struct usb_iso_packet_descriptor *id, *od; + int p, l = 0; + + io = sk->idle_outurb; + od = io->iso_frame_desc; + io->transfer_buffer_length = 0; + + for (p = 0; s->sync_packet < 0; ++p, ++s->sync_packet) { + struct urb *ii = sk->completed_inurb; + id = ii->iso_frame_desc + + ii->number_of_packets + s->sync_packet; + l = id->actual_length; + + od[p].length = l; + od[p].offset = io->transfer_buffer_length; + io->transfer_buffer_length += l; + } + + for (; + s->sync_packet < inurb->number_of_packets && p < sk->n_o_ps; + ++p, ++s->sync_packet) { + l = inurb->iso_frame_desc[s->sync_packet].actual_length; + + if (s->idle_outsize + io->transfer_buffer_length + l > + s->period_size) + goto check_ok; + + od[p].length = l; + od[p].offset = io->transfer_buffer_length; + io->transfer_buffer_length += l; + } + +check_ok: + s->sync_packet -= inurb->number_of_packets; + if (s->sync_packet < -2 || s->sync_packet > 0) { + snd_printk(KERN_WARNING "invalid sync_packet = %i;" + " p=%i nop=%i %i %x %x %x > %x\n", + s->sync_packet, p, inurb->number_of_packets, + s->idle_outsize + io->transfer_buffer_length + l, + s->idle_outsize, io->transfer_buffer_length, l, + s->period_size); + return -1; + } + if (io->transfer_buffer_length % s->cfg.frame_size) { + snd_printk(KERN_WARNING"invalid outsize = %i\n", + io->transfer_buffer_length); + return -1; + } + s->idle_outsize += io->transfer_buffer_length - s->period_size; + io->number_of_packets = p; + if (s->idle_outsize > 0) { + snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); + return -1; + } + return 0; +} + +static void prepare_inurb(int number_of_packets, struct urb *iu) +{ + struct usb_iso_packet_descriptor *id; + int p; + + iu->number_of_packets = number_of_packets; + id = iu->iso_frame_desc; + id->offset = 0; + for (p = 0; p < iu->number_of_packets - 1; ++p) + id[p + 1].offset = id[p].offset + id[p].length; + + iu->transfer_buffer_length = + id[0].length * iu->number_of_packets; +} + +static int submit_urbs(struct usb_stream_kernel *sk, + struct urb *inurb, struct urb *outurb) +{ + int err; + prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb); + err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC); + if (err < 0) { + snd_printk(KERN_ERR "%i\n", err); + return err; + } + sk->idle_inurb = sk->completed_inurb; + sk->completed_inurb = inurb; + err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC); + if (err < 0) { + snd_printk(KERN_ERR "%i\n", err); + return err; + } + sk->idle_outurb = sk->completed_outurb; + sk->completed_outurb = outurb; + return 0; +} + +#ifdef DEBUG_LOOP_BACK +/* + This loop_back() shows how to read/write the period data. + */ +static void loop_back(struct usb_stream *s) +{ + char *i, *o; + int il, ol, l, p; + struct urb *iu; + struct usb_iso_packet_descriptor *id; + + o = s->playback1st_to; + ol = s->playback1st_size; + l = 0; + + if (s->insplit_pack >= 0) { + iu = sk->idle_inurb; + id = iu->iso_frame_desc; + p = s->insplit_pack; + } else + goto second; +loop: + for (; p < iu->number_of_packets && l < s->period_size; ++p) { + i = iu->transfer_buffer + id[p].offset; + il = id[p].actual_length; + if (l + il > s->period_size) + il = s->period_size - l; + if (il <= ol) { + memcpy(o, i, il); + o += il; + ol -= il; + } else { + memcpy(o, i, ol); + singen_6pack(o, ol); + o = s->playback_to; + memcpy(o, i + ol, il - ol); + o += il - ol; + ol = s->period_size - s->playback1st_size; + } + l += il; + } + if (iu == sk->completed_inurb) { + if (l != s->period_size) + printk(KERN_DEBUG"%s:%i %i\n", __func__, __LINE__, + l/(int)s->cfg.frame_size); + + return; + } +second: + iu = sk->completed_inurb; + id = iu->iso_frame_desc; + p = 0; + goto loop; + +} +#else +static void loop_back(struct usb_stream *s) +{ +} +#endif + +static void stream_idle(struct usb_stream_kernel *sk, + struct urb *inurb, struct urb *outurb) +{ + struct usb_stream *s = sk->s; + int l, p; + int insize = s->idle_insize; + int urb_size = 0; + + s->inpacket_split = s->next_inpacket_split; + s->inpacket_split_at = s->next_inpacket_split_at; + s->next_inpacket_split = -1; + s->next_inpacket_split_at = 0; + + for (p = 0; p < inurb->number_of_packets; ++p) { + struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc; + l = id[p].actual_length; + if (unlikely(l == 0 || id[p].status)) { + snd_printk(KERN_WARNING "underrun, status=%u\n", + id[p].status); + goto err_out; + } + s->inpacket_head++; + s->inpacket_head %= s->inpackets; + if (s->inpacket_split == -1) + s->inpacket_split = s->inpacket_head; + + s->inpacket[s->inpacket_head].offset = + id[p].offset + (inurb->transfer_buffer - (void *)s); + s->inpacket[s->inpacket_head].length = l; + if (insize + l > s->period_size && + s->next_inpacket_split == -1) { + s->next_inpacket_split = s->inpacket_head; + s->next_inpacket_split_at = s->period_size - insize; + } + insize += l; + urb_size += l; + } + s->idle_insize += urb_size - s->period_size; + if (s->idle_insize < 0) { + snd_printk(KERN_WARNING "%i\n", + (s->idle_insize)/(int)s->cfg.frame_size); + goto err_out; + } + s->insize_done += urb_size; + + l = s->idle_outsize; + s->outpacket[0].offset = (sk->idle_outurb->transfer_buffer - + sk->write_page) - l; + + if (usb_stream_prepare_playback(sk, inurb) < 0) + goto err_out; + + s->outpacket[0].length = sk->idle_outurb->transfer_buffer_length + l; + s->outpacket[1].offset = sk->completed_outurb->transfer_buffer - + sk->write_page; + + if (submit_urbs(sk, inurb, outurb) < 0) + goto err_out; + + loop_back(s); + s->periods_done++; + wake_up_all(&sk->sleep); + return; +err_out: + s->state = usb_stream_xrun; + wake_up_all(&sk->sleep); +} + +static void i_capture_idle(struct urb *urb) +{ + struct usb_stream_kernel *sk = urb->context; + if (balance_capture(sk, urb)) + stream_idle(sk, urb, sk->i_urb); +} + +static void i_playback_idle(struct urb *urb) +{ + struct usb_stream_kernel *sk = urb->context; + if (balance_playback(sk, urb)) + stream_idle(sk, sk->i_urb, urb); +} + +static void stream_start(struct usb_stream_kernel *sk, + struct urb *inurb, struct urb *outurb) +{ + struct usb_stream *s = sk->s; + if (s->state >= usb_stream_sync1) { + int l, p, max_diff, max_diff_0; + int urb_size = 0; + unsigned frames_per_packet, min_frames = 0; + frames_per_packet = (s->period_size - s->idle_insize); + frames_per_packet <<= 8; + frames_per_packet /= + s->cfg.frame_size * inurb->number_of_packets; + frames_per_packet++; + + max_diff_0 = s->cfg.frame_size; + if (s->cfg.period_frames >= 256) + max_diff_0 <<= 1; + if (s->cfg.period_frames >= 1024) + max_diff_0 <<= 1; + max_diff = max_diff_0; + for (p = 0; p < inurb->number_of_packets; ++p) { + int diff; + l = inurb->iso_frame_desc[p].actual_length; + urb_size += l; + + min_frames += frames_per_packet; + diff = urb_size - + (min_frames >> 8) * s->cfg.frame_size; + if (diff < max_diff) { + snd_printdd(KERN_DEBUG "%i %i %i %i\n", + s->insize_done, + urb_size / (int)s->cfg.frame_size, + inurb->number_of_packets, diff); + max_diff = diff; + } + } + s->idle_insize -= max_diff - max_diff_0; + s->idle_insize += urb_size - s->period_size; + if (s->idle_insize < 0) { + snd_printk("%i %i %i\n", + s->idle_insize, urb_size, s->period_size); + return; + } else if (s->idle_insize == 0) { + s->next_inpacket_split = + (s->inpacket_head + 1) % s->inpackets; + s->next_inpacket_split_at = 0; + } else { + unsigned split = s->inpacket_head; + l = s->idle_insize; + while (l > s->inpacket[split].length) { + l -= s->inpacket[split].length; + if (split == 0) + split = s->inpackets - 1; + else + split--; + } + s->next_inpacket_split = split; + s->next_inpacket_split_at = + s->inpacket[split].length - l; + } + + s->insize_done += urb_size; + + if (usb_stream_prepare_playback(sk, inurb) < 0) + return; + + } else + playback_prep_freqn(sk, sk->idle_outurb); + + if (submit_urbs(sk, inurb, outurb) < 0) + return; + + if (s->state == usb_stream_sync1 && s->insize_done > 360000) { + /* just guesswork ^^^^^^ */ + s->state = usb_stream_ready; + subs_set_complete(sk->inurb, i_capture_idle); + subs_set_complete(sk->outurb, i_playback_idle); + } +} + +static void i_capture_start(struct urb *urb) +{ + struct usb_iso_packet_descriptor *id = urb->iso_frame_desc; + struct usb_stream_kernel *sk = urb->context; + struct usb_stream *s = sk->s; + int p; + int empty = 0; + + if (urb->status) { + snd_printk(KERN_WARNING "status=%i\n", urb->status); + return; + } + + for (p = 0; p < urb->number_of_packets; ++p) { + int l = id[p].actual_length; + if (l < s->cfg.frame_size) { + ++empty; + if (s->state >= usb_stream_sync0) { + snd_printk(KERN_WARNING "%i\n", l); + return; + } + } + s->inpacket_head++; + s->inpacket_head %= s->inpackets; + s->inpacket[s->inpacket_head].offset = + id[p].offset + (urb->transfer_buffer - (void *)s); + s->inpacket[s->inpacket_head].length = l; + } +#ifdef SHOW_EMPTY + if (empty) { + printk(KERN_DEBUG"%s:%i: %i", __func__, __LINE__, + urb->iso_frame_desc[0].actual_length); + for (pack = 1; pack < urb->number_of_packets; ++pack) { + int l = urb->iso_frame_desc[pack].actual_length; + printk(" %i", l); + } + printk("\n"); + } +#endif + if (!empty && s->state < usb_stream_sync1) + ++s->state; + + if (balance_capture(sk, urb)) + stream_start(sk, urb, sk->i_urb); +} + +static void i_playback_start(struct urb *urb) +{ + struct usb_stream_kernel *sk = urb->context; + if (balance_playback(sk, urb)) + stream_start(sk, sk->i_urb, urb); +} + +int usb_stream_start(struct usb_stream_kernel *sk) +{ + struct usb_stream *s = sk->s; + int frame = 0, iters = 0; + int u, err; + int try = 0; + + if (s->state != usb_stream_stopped) + return -EAGAIN; + + subs_set_complete(sk->inurb, i_capture_start); + subs_set_complete(sk->outurb, i_playback_start); + memset(sk->write_page, 0, s->write_size); +dotry: + s->insize_done = 0; + s->idle_insize = 0; + s->idle_outsize = 0; + s->sync_packet = -1; + s->inpacket_head = -1; + sk->iso_frame_balance = 0; + ++try; + for (u = 0; u < 2; u++) { + struct urb *inurb = sk->inurb[u]; + struct urb *outurb = sk->outurb[u]; + playback_prep_freqn(sk, outurb); + inurb->number_of_packets = outurb->number_of_packets; + inurb->transfer_buffer_length = + inurb->number_of_packets * + inurb->iso_frame_desc[0].length; + preempt_disable(); + if (u == 0) { + int now; + struct usb_device *dev = inurb->dev; + frame = usb_get_current_frame_number(dev); + do { + now = usb_get_current_frame_number(dev); + ++iters; + } while (now > -1 && now == frame); + } + err = usb_submit_urb(inurb, GFP_ATOMIC); + if (err < 0) { + preempt_enable(); + snd_printk(KERN_ERR"usb_submit_urb(sk->inurb[%i])" + " returned %i\n", u, err); + return err; + } + err = usb_submit_urb(outurb, GFP_ATOMIC); + if (err < 0) { + preempt_enable(); + snd_printk(KERN_ERR"usb_submit_urb(sk->outurb[%i])" + " returned %i\n", u, err); + return err; + } + preempt_enable(); + if (inurb->start_frame != outurb->start_frame) { + snd_printd(KERN_DEBUG + "u[%i] start_frames differ in:%u out:%u\n", + u, inurb->start_frame, outurb->start_frame); + goto check_retry; + } + } + snd_printdd(KERN_DEBUG "%i %i\n", frame, iters); + try = 0; +check_retry: + if (try) { + usb_stream_stop(sk); + if (try < 5) { + msleep(1500); + snd_printd(KERN_DEBUG "goto dotry;\n"); + goto dotry; + } + snd_printk(KERN_WARNING"couldn't start" + " all urbs on the same start_frame.\n"); + return -EFAULT; + } + + sk->idle_inurb = sk->inurb[USB_STREAM_NURBS - 2]; + sk->idle_outurb = sk->outurb[USB_STREAM_NURBS - 2]; + sk->completed_inurb = sk->inurb[USB_STREAM_NURBS - 1]; + sk->completed_outurb = sk->outurb[USB_STREAM_NURBS - 1]; + +/* wait, check */ + { + int wait_ms = 3000; + while (s->state != usb_stream_ready && wait_ms > 0) { + snd_printdd(KERN_DEBUG "%i\n", s->state); + msleep(200); + wait_ms -= 200; + } + } + + return s->state == usb_stream_ready ? 0 : -EFAULT; +} + + +/* stop */ + +void usb_stream_stop(struct usb_stream_kernel *sk) +{ + int u; + if (!sk->s) + return; + for (u = 0; u < USB_STREAM_NURBS; ++u) { + usb_kill_urb(sk->inurb[u]); + usb_kill_urb(sk->outurb[u]); + } + sk->s->state = usb_stream_stopped; + msleep(400); +} diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h new file mode 100644 index 00000000000..4dd74ab1e9c --- /dev/null +++ b/sound/usb/usx2y/usb_stream.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2007, 2008 Karsten Wiese + * + * 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. + */ + +#define USB_STREAM_INTERFACE_VERSION 2 + +#define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \ + _IOW('H', 0x90, struct usb_stream_config) + +struct usb_stream_packet { + unsigned offset; + unsigned length; +}; + + +struct usb_stream_config { + unsigned version; + unsigned sample_rate; + unsigned period_frames; + unsigned frame_size; +}; + +struct usb_stream { + struct usb_stream_config cfg; + unsigned read_size; + unsigned write_size; + + int period_size; + + unsigned state; + + int idle_insize; + int idle_outsize; + int sync_packet; + unsigned insize_done; + unsigned periods_done; + unsigned periods_polled; + + struct usb_stream_packet outpacket[2]; + unsigned inpackets; + unsigned inpacket_head; + unsigned inpacket_split; + unsigned inpacket_split_at; + unsigned next_inpacket_split; + unsigned next_inpacket_split_at; + struct usb_stream_packet inpacket[0]; +}; + +enum usb_stream_state { + usb_stream_invalid, + usb_stream_stopped, + usb_stream_sync0, + usb_stream_sync1, + usb_stream_ready, + usb_stream_running, + usb_stream_xrun, +}; + +#if __KERNEL__ + +#define USB_STREAM_NURBS 4 +#define USB_STREAM_URBDEPTH 4 + +struct usb_stream_kernel { + struct usb_stream *s; + + void *write_page; + + unsigned n_o_ps; + + struct urb *inurb[USB_STREAM_NURBS]; + struct urb *idle_inurb; + struct urb *completed_inurb; + struct urb *outurb[USB_STREAM_NURBS]; + struct urb *idle_outurb; + struct urb *completed_outurb; + struct urb *i_urb; + + int iso_frame_balance; + + wait_queue_head_t sleep; + + unsigned out_phase; + unsigned out_phase_peeked; + unsigned freqn; +}; + +struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, + struct usb_device *dev, + unsigned in_endpoint, unsigned out_endpoint, + unsigned sample_rate, unsigned use_packsize, + unsigned period_frames, unsigned frame_size); +void usb_stream_free(struct usb_stream_kernel *); +int usb_stream_start(struct usb_stream_kernel *); +void usb_stream_stop(struct usb_stream_kernel *); + + +#endif -- GitLab From f90c06a2b613eea24a77d56f24b084745c43713d Mon Sep 17 00:00:00 2001 From: Pawel MOLL Date: Wed, 30 Jul 2008 12:46:40 +0100 Subject: [PATCH 0236/5416] ALSA: Fix limit of 8 PCM devices in SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE When compiled with CONFIG_SND_DYNAMIC_MINORS the ALSA core is fine to have more than 8 PCM devices per card, except one place - the SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE ioctl, which will not enumerate devices > 7. This patch fixes the issue, changing the devices list organisation. Instead of adding new device to the tail, the list is now kept always ordered (by card number, then device number). Thus, during enumeration, it is easy to discover the fact that there is no more given card's devices. Additionally the device field of struct snd_pcm had to be changed to int, as its "unsignednity" caused a lot of problems when comparing it to potentially negative signed values. (-1 is 0xffffffff or even more then ;-) Signed-off-by: Pawel Moll Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/minors.h | 2 ++ include/sound/pcm.h | 9 ++++++-- sound/core/pcm.c | 50 +++++++++++++++++++++++++++++++----------- sound/core/sound.c | 2 -- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/include/sound/minors.h b/include/sound/minors.h index 46bcd2023ed..a81798ab73e 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -21,6 +21,8 @@ * */ +#define SNDRV_OS_MINORS 256 + #define SNDRV_MINOR_DEVICES 32 #define SNDRV_MINOR_CARD(minor) ((minor) >> 5) #define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 51d58ccda2d..5dd8ea4a8c4 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -84,7 +85,11 @@ struct snd_pcm_ops { * */ -#define SNDRV_PCM_DEVICES 8 +#if defined(CONFIG_SND_DYNAMIC_MINORS) +#define SNDRV_PCM_DEVICES (SNDRV_OS_MINORS-2) +#else +#define SNDRV_PCM_DEVICES 8 +#endif #define SNDRV_PCM_IOCTL1_FALSE ((void *)0) #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) @@ -416,7 +421,7 @@ struct snd_pcm_str { struct snd_pcm { struct snd_card *card; struct list_head list; - unsigned int device; /* device number */ + int device; /* device number */ unsigned int info_flags; unsigned short dev_class; unsigned short dev_subclass; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ece25c718e9..517388b2eba 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) +static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) return NULL; } +static int snd_pcm_next(struct snd_card *card, int device) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == card && pcm->device > device) + return pcm->device; + else if (pcm->card->number > card->number) + return -1; + } + return -1; +} + +static int snd_pcm_add(struct snd_pcm *newpcm) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == newpcm->card && pcm->device == newpcm->device) + return -EBUSY; + if (pcm->card->number > newpcm->card->number || + (pcm->card == newpcm->card && + pcm->device > newpcm->device)) { + list_add(&newpcm->list, pcm->list.prev); + return 0; + } + } + list_add_tail(&newpcm->list, &snd_pcm_devices); + return 0; +} + static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; - while (device < SNDRV_PCM_DEVICES) { - if (snd_pcm_search(card, device)) - break; - device++; - } - if (device == SNDRV_PCM_DEVICES) - device = -1; + device = snd_pcm_next(card, device); mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_search(card, device); + pcm = snd_pcm_get(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -931,11 +955,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - if (snd_pcm_search(pcm->card, pcm->device)) { + err = snd_pcm_add(pcm); + if (err) { mutex_unlock(®ister_mutex); - return -EBUSY; + return err; } - list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) diff --git a/sound/core/sound.c b/sound/core/sound.c index 1003ae375d4..838dd9ee957 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -34,8 +34,6 @@ #include #include -#define SNDRV_OS_MINORS 256 - static int major = CONFIG_SND_MAJOR; int snd_major; EXPORT_SYMBOL(snd_major); -- GitLab From 740dc9c4766b462ae88a630e969ddd3ef83a6125 Mon Sep 17 00:00:00 2001 From: Misha Zhilin Date: Fri, 1 Aug 2008 12:45:14 +0200 Subject: [PATCH 0237/5416] ALSA: ice1724 - Support for Terrasoniq/MUSONIK TS22 PCI card Added support for Terrasoniq/MUSONIK TS22 PCI card. Signed-off-by: Misha Zhilin Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ice1712/phase.c | 12 ++++++++++++ sound/pci/ice1712/phase.h | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 5a158b73dca..f5acdeef443 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c @@ -120,6 +120,7 @@ static int __devinit phase22_init(struct snd_ice1712 *ice) // Configure DAC/ADC description for generic part of ice1724 switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_PHASE22: + case VT1724_SUBDEVICE_TS22: ice->num_total_dacs = 2; ice->num_total_adcs = 2; ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO @@ -136,6 +137,7 @@ static int __devinit phase22_init(struct snd_ice1712 *ice) ice->akm_codecs = 1; switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_PHASE22: + case VT1724_SUBDEVICE_TS22: if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0) return err; break; @@ -150,6 +152,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice) switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_PHASE22: + case VT1724_SUBDEVICE_TS22: err = snd_ice1712_akm4xxx_build_controls(ice); if (err < 0) return err; @@ -904,5 +907,14 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { .eeprom_size = sizeof(phase28_eeprom), .eeprom_data = phase28_eeprom, }, + { + .subvendor = VT1724_SUBDEVICE_TS22, + .name = "Terrasoniq TS22 PCI", + .model = "TS22", + .chip_init = phase22_init, + .build_controls = phase22_add_controls, + .eeprom_size = sizeof(phase22_eeprom), + .eeprom_data = phase22_eeprom, + }, { } /* terminator */ }; diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h index 13e841b5548..5f0c4dbf30d 100644 --- a/sound/pci/ice1712/phase.h +++ b/sound/pci/ice1712/phase.h @@ -25,10 +25,12 @@ */ #define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\ - "{Terratec,Phase 28}," + "{Terratec,Phase 28},"\ + "{Terrasoniq,TS22}," #define VT1724_SUBDEVICE_PHASE22 0x3b155011 #define VT1724_SUBDEVICE_PHASE28 0x3b154911 +#define VT1724_SUBDEVICE_TS22 0x3b157b11 /* entry point */ extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; -- GitLab From 53efec9513cfb1acff602c7ebdd945d677808e9e Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 28 Jul 2008 19:44:05 +0200 Subject: [PATCH 0238/5416] pcmcia: only copy CIS override data once Instead of copying CIS override data in socket_sysfs.c or ds.c, and then again in cistpl.c, only do so once. Also, cisdump_t is now only used by the deprecated ioctl. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cistpl.c | 18 +++++++++--------- drivers/pcmcia/ds.c | 12 +----------- drivers/pcmcia/pcmcia_ioctl.c | 2 +- drivers/pcmcia/socket_sysfs.c | 13 ++----------- include/pcmcia/cistpl.h | 10 ++-------- include/pcmcia/ds.h | 6 ++++++ include/pcmcia/ss.h | 4 ++-- 7 files changed, 23 insertions(+), 42 deletions(-) diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 65129b54eb0..11c473c865a 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); ======================================================================*/ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, - u_int len, void *ptr) + size_t len, void *ptr) { struct cis_cache_entry *cis; int ret; if (s->fake_cis) { - if (s->fake_cis_len > addr+len) + if (s->fake_cis_len >= addr+len) memcpy(ptr, s->fake_cis+addr, len); else memset(ptr, 0xff, len); @@ -380,17 +380,17 @@ int verify_cis_cache(struct pcmcia_socket *s) ======================================================================*/ -int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) +int pcmcia_replace_cis(struct pcmcia_socket *s, + const u8 *data, const size_t len) { - kfree(s->fake_cis); - s->fake_cis = NULL; - if (cis->Length > CISTPL_MAX_CIS_SIZE) + if (len > CISTPL_MAX_CIS_SIZE) return CS_BAD_SIZE; - s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); + kfree(s->fake_cis); + s->fake_cis = kmalloc(len, GFP_KERNEL); if (s->fake_cis == NULL) return CS_OUT_OF_RESOURCE; - s->fake_cis_len = cis->Length; - memcpy(s->fake_cis, cis->Data, cis->Length); + s->fake_cis_len = len; + memcpy(s->fake_cis, data, len); return CS_SUCCESS; } EXPORT_SYMBOL(pcmcia_replace_cis); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4174d9656e3..2382341975e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -854,7 +854,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) int ret = -ENOMEM; int no_funcs; int old_funcs; - cisdump_t *cis; cistpl_longlink_mfc_t mfc; if (!filename) @@ -877,16 +876,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) goto release; } - cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) { - ret = -ENOMEM; - goto release; - } - - cis->Length = fw->size + 1; - memcpy(cis->Data, fw->data, fw->size); - - if (!pcmcia_replace_cis(s, cis)) + if (!pcmcia_replace_cis(s, fw->data, fw->size)) ret = 0; else { printk(KERN_ERR "pcmcia: CIS override failed\n"); diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 419f97fc9a6..6c086ffea44 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, &buf->win_info.map); break; case DS_REPLACE_CIS: - ret = pcmcia_replace_cis(s, &buf->cisdump); + ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length); break; case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) { diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 006a29e91d8..ff9a3bb3c88 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); - cisdump_t *cis; int error; if (off) return -EINVAL; - if (count >= 0x200) + if (count >= CISTPL_MAX_CIS_SIZE) return -EINVAL; if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) - return -ENOMEM; - - cis->Length = count + 1; - memcpy(cis->Data, buf, count); - - error = pcmcia_replace_cis(s, cis); - kfree(cis); + error = pcmcia_replace_cis(s, buf, count); if (error) return -EIO; diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index e2e10c1e9a0..552a332ad71 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -580,14 +580,8 @@ typedef struct cisinfo_t { #define CISTPL_MAX_CIS_SIZE 0x200 -/* For ReplaceCIS */ -typedef struct cisdump_t { - u_int Length; - cisdata_t Data[CISTPL_MAX_CIS_SIZE]; -} cisdump_t; - - -int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis); +int pcmcia_replace_cis(struct pcmcia_socket *s, + const u8 *data, const size_t len); /* don't use outside of PCMCIA core yet */ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index b316027c853..2d36a4f80e5 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -68,6 +68,12 @@ typedef struct region_info_t { #define REGION_BAR_MASK 0xe000 #define REGION_BAR_SHIFT 13 +/* For ReplaceCIS */ +typedef struct cisdump_t { + u_int Length; + cisdata_t Data[CISTPL_MAX_CIS_SIZE]; +} cisdump_t; + typedef union ds_ioctl_arg_t { adjust_t adjust; config_info_t config; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index ed919dd9bb5..e34bef0fc74 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -199,8 +199,8 @@ struct pcmcia_socket { io_window_t io[MAX_IO_WIN]; window_t win[MAX_WIN]; struct list_head cis_cache; - u_int fake_cis_len; - char *fake_cis; + size_t fake_cis_len; + u8 *fake_cis; struct list_head socket_list; struct completion socket_released; -- GitLab From 3583a71183a02c51ca71cd180e9189cfb0411cc1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Jul 2008 20:21:23 +0300 Subject: [PATCH 0239/5416] make selinux_write_opts() static This patch makes the needlessly global selinux_write_opts() static. Signed-off-by: Adrian Bunk Signed-off-by: James Morris --- security/selinux/hooks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3ae9bec5a50..0ffd8814af3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -957,7 +957,8 @@ out_err: return rc; } -void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) +static void selinux_write_opts(struct seq_file *m, + struct security_mnt_opts *opts) { int i; char *prefix; -- GitLab From df4ea865f09580b1cad621c0426612f598847815 Mon Sep 17 00:00:00 2001 From: Vesa-Matti J Kari Date: Sun, 20 Jul 2008 23:57:01 +0300 Subject: [PATCH 0240/5416] SELinux: Trivial minor fixes that change C null character style Trivial minor fixes that change C null character style. Signed-off-by: Vesa-Matti Kari Signed-off-by: James Morris --- security/selinux/ss/conditional.c | 2 +- security/selinux/ss/mls.c | 14 +++++++------- security/selinux/ss/policydb.c | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index fb4efe4f4bc..f8c850a56ed 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto err; - key[len] = 0; + key[len] = '\0'; if (hashtab_insert(h, key, booldatum)) goto err; diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 77d745da48b..b5407f16c2a 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol, p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; for (l = 0; l < 2; l++) { levdatum = hashtab_search(pol->p_levels.table, scontextp); @@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol, while (*p && *p != ',' && *p != '-') p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; /* Separate into range if exists */ rngptr = strchr(scontextp, '.'); if (rngptr != NULL) { /* Remove '.' */ - *rngptr++ = 0; + *rngptr++ = '\0'; } catdatum = hashtab_search(pol->p_cats.table, @@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol, p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; } else break; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2391761ae42..26646305dc0 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -932,7 +932,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, perdatum); if (rc) @@ -979,7 +979,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; for (i = 0; i < nel; i++) { rc = perm_read(p, comdatum->permissions.table, fp); @@ -1117,7 +1117,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; if (len2) { cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); @@ -1128,7 +1128,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(cladatum->comkey, fp, len2); if (rc < 0) goto bad; - cladatum->comkey[len2] = 0; + cladatum->comkey[len2] = '\0'; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); @@ -1201,7 +1201,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = ebitmap_read(&role->dominates, fp); if (rc) @@ -1262,7 +1262,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, typdatum); if (rc) @@ -1334,7 +1334,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = ebitmap_read(&usrdatum->roles, fp); if (rc) @@ -1388,7 +1388,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); if (!levdatum->level) { @@ -1440,7 +1440,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, catdatum); if (rc) @@ -1523,7 +1523,7 @@ int policydb_read(struct policydb *p, void *fp) kfree(policydb_str); goto bad; } - policydb_str[len] = 0; + policydb_str[len] = '\0'; if (strcmp(policydb_str, POLICYDB_STRING)) { printk(KERN_ERR "SELinux: policydb string %s does not match " "my string %s\n", policydb_str, POLICYDB_STRING); -- GitLab From 0c0e186f812457e527c420f7a4d02865fd0dc7d2 Mon Sep 17 00:00:00 2001 From: Vesa-Matti J Kari Date: Mon, 21 Jul 2008 02:50:20 +0300 Subject: [PATCH 0241/5416] SELinux: trivial, remove unneeded local variable Hello, Remove unneeded local variable: struct avtab_node *newnode Signed-off-by: Vesa-Matti Kari Signed-off-by: James Morris --- security/selinux/ss/avtab.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a1be97f8bee..e8ae812d6af 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -98,7 +98,7 @@ struct avtab_node * avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) { int hvalue; - struct avtab_node *prev, *cur, *newnode; + struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h || !h->htable) @@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu key->target_class < cur->key.target_class) break; } - newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); - - return newnode; + return avtab_insert_node(h, hvalue, prev, cur, key, datum); } struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) -- GitLab From cf9481e289247fe9cf40f2e2481220d899132049 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sun, 27 Jul 2008 21:31:07 +1000 Subject: [PATCH 0242/5416] SELinux: Fix a potentially uninitialised variable in SELinux hooks Fix a potentially uninitialised variable in SELinux hooks that's given a pointer to the network address by selinux_parse_skb() passing a pointer back through its argument list. By restructuring selinux_parse_skb(), the compiler can see that the error case need not set it as the caller will return immediately. Signed-off-by: David Howells Signed-off-by: James Morris --- security/selinux/hooks.c | 42 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0ffd8814af3..3eae3060970 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3539,38 +3539,44 @@ out: #endif /* IPV6 */ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, - char **addrp, int src, u8 *proto) + char **_addrp, int src, u8 *proto) { - int ret = 0; + char *addrp; + int ret; switch (ad->u.net.family) { case PF_INET: ret = selinux_parse_skb_ipv4(skb, ad, proto); - if (ret || !addrp) - break; - *addrp = (char *)(src ? &ad->u.net.v4info.saddr : - &ad->u.net.v4info.daddr); - break; + if (ret) + goto parse_error; + addrp = (char *)(src ? &ad->u.net.v4info.saddr : + &ad->u.net.v4info.daddr); + goto okay; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: ret = selinux_parse_skb_ipv6(skb, ad, proto); - if (ret || !addrp) - break; - *addrp = (char *)(src ? &ad->u.net.v6info.saddr : - &ad->u.net.v6info.daddr); - break; + if (ret) + goto parse_error; + addrp = (char *)(src ? &ad->u.net.v6info.saddr : + &ad->u.net.v6info.daddr); + goto okay; #endif /* IPV6 */ default: - break; + addrp = NULL; + goto okay; } - if (unlikely(ret)) - printk(KERN_WARNING - "SELinux: failure in selinux_parse_skb()," - " unable to parse packet\n"); - +parse_error: + printk(KERN_WARNING + "SELinux: failure in selinux_parse_skb()," + " unable to parse packet\n"); return ret; + +okay: + if (_addrp) + *_addrp = addrp; + return 0; } /** -- GitLab From 15446235367fa4a621ff5abfa4b6ebbe25b33763 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Wed, 30 Jul 2008 15:37:11 -0700 Subject: [PATCH 0243/5416] smack: limit privilege by label There have been a number of requests to make the Smack LSM enforce MAC even in the face of privilege, either capability based or superuser based. This is not universally desired, however, so it seems desirable to make it optional. Further, at least one legacy OS implemented a scheme whereby only processes running with one particular label could be exempt from MAC. This patch supports these three cases. If /smack/onlycap is empty (unset or null-string) privilege is enforced in the normal way. If /smack/onlycap contains a label only processes running with that label may be MAC exempt. If the label in /smack/onlycap is the star label ("*") the semantics of the star label combine with the privilege restrictions to prevent any violations of MAC, even in the presence of privilege. Again, this will be independent of the privilege scheme. Signed-off-by: Casey Schaufler Reviewed-by: James Morris --- security/smack/smack.h | 1 + security/smack/smack_access.c | 10 +++- security/smack/smackfs.c | 92 +++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index 4a4477f5afd..31dce559595 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -178,6 +178,7 @@ u32 smack_to_secid(const char *); extern int smack_cipso_direct; extern int smack_net_nltype; extern char *smack_net_ambient; +extern char *smack_onlycap; extern struct smack_known *smack_known; extern struct smack_known smack_known_floor; diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f6b5f6eed6d..79ff21ed4c3 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request) * * This function checks the current subject label/object label pair * in the access rule list and returns 0 if the access is permitted, - * non zero otherwise. It allows that current my have the capability + * non zero otherwise. It allows that current may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode) @@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode) if (rc == 0) return 0; + /* + * Return if a specific label has been designated as the + * only one that gets privilege and current does not + * have that label. + */ + if (smack_onlycap != NULL && smack_onlycap != current->security) + return rc; + if (capable(CAP_MAC_OVERRIDE)) return 0; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 271a835fbbe..e7c642458ec 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -39,6 +39,7 @@ enum smk_inos { SMK_DIRECT = 6, /* CIPSO level indicating direct label */ SMK_AMBIENT = 7, /* internet ambient label */ SMK_NLTYPE = 8, /* label scheme to use by default */ + SMK_ONLYCAP = 9, /* the only "capable" label */ }; /* @@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; */ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; +/* + * Unless a process is running with this label even + * having CAP_MAC_OVERRIDE isn't enough to grant + * privilege to violate MAC policy. If no label is + * designated (the NULL case) capabilities apply to + * everyone. It is expected that the hat (^) label + * will be used if any label is used. + */ +char *smack_onlycap; + static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; struct smk_list_entry *smack_list; @@ -787,6 +798,85 @@ static const struct file_operations smk_ambient_ops = { .write = smk_write_ambient, }; +/** + * smk_read_onlycap - read() for /smack/onlycap + * @filp: file pointer, not actually used + * @buf: where to put the result + * @cn: maximum to send along + * @ppos: where to start + * + * Returns number of bytes read or error code, as appropriate + */ +static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, + size_t cn, loff_t *ppos) +{ + char *smack = ""; + ssize_t rc = -EINVAL; + int asize; + + if (*ppos != 0) + return 0; + + if (smack_onlycap != NULL) + smack = smack_onlycap; + + asize = strlen(smack) + 1; + + if (cn >= asize) + rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); + + return rc; +} + +/** + * smk_write_onlycap - write() for /smack/onlycap + * @filp: file pointer, not actually used + * @buf: where to get the data from + * @count: bytes sent + * @ppos: where to start + * + * Returns number of bytes written or error code, as appropriate + */ +static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char in[SMK_LABELLEN]; + char *sp = current->security; + + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + /* + * This can be done using smk_access() but is done + * explicitly for clarity. The smk_access() implementation + * would use smk_access(smack_onlycap, MAY_WRITE) + */ + if (smack_onlycap != NULL && smack_onlycap != sp) + return -EPERM; + + if (count >= SMK_LABELLEN) + return -EINVAL; + + if (copy_from_user(in, buf, count) != 0) + return -EFAULT; + + /* + * Should the null string be passed in unset the onlycap value. + * This seems like something to be careful with as usually + * smk_import only expects to return NULL for errors. It + * is usually the case that a nullstring or "\n" would be + * bad to pass to smk_import but in fact this is useful here. + */ + smack_onlycap = smk_import(in, count); + + return count; +} + +static const struct file_operations smk_onlycap_ops = { + .read = smk_read_onlycap, + .write = smk_write_onlycap, +}; + struct option_names { int o_number; char *o_name; @@ -919,6 +1009,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, [SMK_NLTYPE] = {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, + [SMK_ONLYCAP] = + {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, /* last one */ {""} }; -- GitLab From 9295aea1e8e00ea83965eb739b8d0bd2ea03c7cb Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:00:17 +0200 Subject: [PATCH 0244/5416] ALSA: wss_lib: move cs4231_lib into wss_lib Move the file sound/isa/cs423x/cs4231_lib.c into sound/isa/cs423x/wss_lib.c This is the first step toward merging all libraries for Windows Sound System compatible chips into a single library. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/Kconfig | 28 ++++++------ sound/isa/Makefile | 2 +- sound/isa/cs423x/Makefile | 2 - sound/isa/wss/Makefile | 10 +++++ .../{cs423x/cs4231_lib.c => wss/wss_lib.c} | 44 +++++++++---------- 5 files changed, 47 insertions(+), 39 deletions(-) create mode 100644 sound/isa/wss/Makefile rename sound/isa/{cs423x/cs4231_lib.c => wss/wss_lib.c} (99%) diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 5769a13c1d9..87055568ccd 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -4,7 +4,7 @@ config SND_AD1848_LIB tristate select SND_PCM -config SND_CS4231_LIB +config SND_WSS_LIB tristate select SND_PCM @@ -86,7 +86,7 @@ config SND_AZT2320 select ISAPNP select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for soundcards based on the Aztech Systems AZT2320 chip. @@ -108,7 +108,7 @@ config SND_CMI8330 config SND_CS4231 tristate "Generic Cirrus Logic CS4231 driver" select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for CS4231 chips from Cirrus Logic - Crystal Semiconductors. @@ -120,7 +120,7 @@ config SND_CS4232 tristate "Generic Cirrus Logic CS4232 driver" select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for CS4232 chips from Cirrus Logic - Crystal Semiconductors. @@ -132,7 +132,7 @@ config SND_CS4236 tristate "Generic Cirrus Logic CS4236+ driver" select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, CS4239 chips from Cirrus Logic - Crystal Semiconductors. @@ -228,7 +228,7 @@ config SND_GUSEXTREME config SND_GUSMAX tristate "Gravis UltraSound MAX" select SND_RAWMIDI - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for Gravis UltraSound MAX soundcards. @@ -240,7 +240,7 @@ config SND_INTERWAVE tristate "AMD InterWave, Gravis UltraSound PnP" depends on PNP select SND_RAWMIDI - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for AMD InterWave based soundcards (Gravis UltraSound Plug & Play, STB SoundRage32, @@ -253,7 +253,7 @@ config SND_INTERWAVE_STB tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)" depends on PNP select SND_RAWMIDI - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for AMD InterWave based soundcards with a TEA6330T bass and treble regulator @@ -266,7 +266,7 @@ config SND_OPL3SA2 tristate "Yamaha OPL3-SA2/SA3" select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 chips. @@ -292,7 +292,7 @@ config SND_OPTI92X_CS4231 select SND_OPL3_LIB select SND_OPL4_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for soundcards based on Opti 82C92x chips and using a CS4231 codec. @@ -304,7 +304,7 @@ config SND_OPTI93X tristate "OPTi 82C93x" select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for soundcards based on Opti 82C93x chips. @@ -315,7 +315,7 @@ config SND_OPTI93X config SND_MIRO tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver" select SND_OPL4_LIB - select SND_CS4231_LIB + select SND_WSS_LIB select SND_MPU401_UART select SND_PCM help @@ -384,7 +384,7 @@ config SND_SSCAPE tristate "Ensoniq SoundScape PnP driver" select SND_HWDEP select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for Ensoniq SoundScape PnP soundcards. @@ -397,7 +397,7 @@ config SND_WAVEFRONT select FW_LOADER select SND_OPL3_LIB select SND_MPU401_UART - select SND_CS4231_LIB + select SND_WSS_LIB help Say Y here to include support for Turtle Beach Maui, Tropez and Tropez+ soundcards based on the Wavefront chip. diff --git a/sound/isa/Makefile b/sound/isa/Makefile index c0ce7db2a1b..63af13d901a 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile @@ -27,4 +27,4 @@ obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \ - sb/ wavefront/ + sb/ wavefront/ wss/ diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile index 5067ee00193..5870ca21ab5 100644 --- a/sound/isa/cs423x/Makefile +++ b/sound/isa/cs423x/Makefile @@ -3,14 +3,12 @@ # Copyright (c) 2001 by Jaroslav Kysela # -snd-cs4231-lib-objs := cs4231_lib.o snd-cs4236-lib-objs := cs4236_lib.o snd-cs4231-objs := cs4231.o snd-cs4232-objs := cs4232.o snd-cs4236-objs := cs4236.o # Toplevel Module Dependency -obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o obj-$(CONFIG_SND_CS4231) += snd-cs4231.o obj-$(CONFIG_SND_CS4232) += snd-cs4232.o obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o diff --git a/sound/isa/wss/Makefile b/sound/isa/wss/Makefile new file mode 100644 index 00000000000..454fee769a3 --- /dev/null +++ b/sound/isa/wss/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for ALSA +# Copyright (c) 2008 by Jaroslav Kysela +# + +snd-wss-lib-objs := wss_lib.o + +# Toplevel Module Dependency +obj-$(CONFIG_SND_WSS_LIB) += snd-wss-lib.o + diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/wss/wss_lib.c similarity index 99% rename from sound/isa/cs423x/cs4231_lib.c rename to sound/isa/wss/wss_lib.c index 521db705d17..c5795f32ed3 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -3,7 +3,7 @@ * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips * * Bugs: - * - sometimes record brokes playback with WSS portion of + * - sometimes record brokes playback with WSS portion of * Yamaha OPL3-SA3 chip * - CS4231 (GUS MAX) - still trouble with occasional noises * - broken initialization? @@ -176,7 +176,7 @@ static void snd_cs4231_wait(struct snd_cs4231 *chip) for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) - udelay(100); + udelay(100); } static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, @@ -205,7 +205,7 @@ static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) - udelay(10); + udelay(10); cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); cs4231_outb(chip, CS4231P(REG), value); mb(); @@ -322,7 +322,7 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) - udelay(10); + udelay(10); } void snd_cs4231_mce_up(struct snd_cs4231 *chip) @@ -537,7 +537,7 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); if (chip->hardware == CS4231_HW_INTERWAVE) { snd_cs4231_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); - snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]); + snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]); snd_cs4231_dout(chip, CS4231_LINE_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]); snd_cs4231_dout(chip, CS4231_LINE_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]); } @@ -952,7 +952,7 @@ irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id) if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); - } + } if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) { if (status & CS4231_PLAYBACK_IRQ) { if (chip->mode & CS4231_MODE_PLAY) { @@ -1000,7 +1000,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *su { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); size_t ptr; - + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); @@ -1234,8 +1234,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) /* hardware bug in InterWave chipset */ if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3) - runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; - + runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; + /* hardware limitation of cheap chips */ if (chip->hardware == CS4231_HW_CS4235 || chip->hardware == CS4231_HW_CS4239) @@ -1319,7 +1319,7 @@ static void snd_cs4231_suspend(struct snd_cs4231 *chip) { int reg; unsigned long flags; - + snd_pcm_suspend_all(chip->pcm); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) @@ -1333,7 +1333,7 @@ static void snd_cs4231_resume(struct snd_cs4231 *chip) int reg; unsigned long flags; /* int timeout; */ - + snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) { @@ -1396,7 +1396,7 @@ static int snd_cs4231_free(struct snd_cs4231 *chip) static int snd_cs4231_dev_free(struct snd_device *device) { struct snd_cs4231 *chip = device->device_data; - return snd_cs4231_free(chip); + return snd_cs4231_free(chip); } const char *snd_cs4231_chip_id(struct snd_cs4231 *chip) @@ -1469,7 +1469,7 @@ int snd_cs4231_create(struct snd_card *card, err = snd_cs4231_new(card, hardware, hwshare, &chip); if (err < 0) return err; - + chip->irq = -1; chip->dma1 = -1; chip->dma2 = -1; @@ -1575,7 +1575,7 @@ int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); - + /* global setup */ pcm->private_data = chip; pcm->info_flags = 0; @@ -1624,7 +1624,7 @@ int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rti *rtimer = timer; return 0; } - + /* * MIXER part */ @@ -1663,7 +1663,7 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; - + spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6; @@ -1677,7 +1677,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem unsigned long flags; unsigned short left, right; int change; - + if (ucontrol->value.enumerated.item[0] > 3 || ucontrol->value.enumerated.item[1] > 3) return -EINVAL; @@ -1713,7 +1713,7 @@ int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - + spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -1732,7 +1732,7 @@ int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int invert = (kcontrol->private_value >> 24) & 0xff; int change; unsigned short val; - + val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; @@ -1766,7 +1766,7 @@ int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int shift_right = (kcontrol->private_value >> 19) & 0x07; int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - + spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; @@ -1790,7 +1790,7 @@ int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int invert = (kcontrol->private_value >> 22) & 1; int change; unsigned short val1, val2; - + val1 = ucontrol->value.integer.value[0] & mask; val2 = ucontrol->value.integer.value[1] & mask; if (invert) { @@ -1834,7 +1834,7 @@ CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0) CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1) }; - + static struct snd_kcontrol_new snd_opti93x_controls[] = { CS4231_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), -- GitLab From 61ef19d7e771ce021edb0dff0da134b6d688d4aa Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:02:42 +0200 Subject: [PATCH 0245/5416] ALSA: wss_lib: rename cs4231.h into wss.h Rename file include/sound/cs4231.h into include/sound/wss.h Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/snd_wavefront.h | 1 - include/sound/{cs4231.h => wss.h} | 0 sound/isa/azt2320.c | 2 +- sound/isa/cs423x/cs4231.c | 2 +- sound/isa/cs423x/cs4236.c | 2 +- sound/isa/cs423x/cs4236_lib.c | 2 +- sound/isa/gus/gusmax.c | 2 +- sound/isa/gus/interwave.c | 2 +- sound/isa/opl3sa2.c | 2 +- sound/isa/opti9xx/miro.c | 2 +- sound/isa/opti9xx/opti92x-ad1848.c | 2 +- sound/isa/sscape.c | 2 +- sound/isa/wavefront/wavefront.c | 1 + sound/isa/wss/wss_lib.c | 2 +- 14 files changed, 12 insertions(+), 12 deletions(-) rename include/sound/{cs4231.h => wss.h} (100%) diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h index 9688d4be918..fa149ca77e4 100644 --- a/include/sound/snd_wavefront.h +++ b/include/sound/snd_wavefront.h @@ -1,7 +1,6 @@ #ifndef __SOUND_SND_WAVEFRONT_H__ #define __SOUND_SND_WAVEFRONT_H__ -#include "cs4231.h" #include "mpu401.h" #include "hwdep.h" #include "rawmidi.h" diff --git a/include/sound/cs4231.h b/include/sound/wss.h similarity index 100% rename from include/sound/cs4231.h rename to include/sound/wss.h diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 154e728f592..a24db091d44 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index e9462b9944b..7da28e7c032 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 4d4b8ddc26b..246c221556e 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index de71910401e..eb227d856d1 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -85,7 +85,7 @@ #include #include #include -#include +#include #include MODULE_AUTHOR("Jaroslav Kysela "); diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index f87c6236661..cd82891db80 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_DMA #include diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index ca0d7ace0c7..eac8cc77e33 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #ifdef SNDRV_STB #include #endif diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 854a9f74b46..e81cbe86823 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 2a1e2f5d12c..59f7c55baf3 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 0797ca441a3..93a03d9c7a9 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -34,7 +34,7 @@ #include #include #if defined(CS4231) || defined(OPTi93X) -#include +#include #else #include #endif /* CS4231 */ diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 06ad7863dff..1dc4224b320 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 3a6c6fe1ec4..2fb058b5a45 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -29,6 +29,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Paul Barton-Davis "); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index c5795f32ed3..549e6ab34b0 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include -- GitLab From 7779f75f072784d3fccf721b8ec43107f93619a0 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:03:41 +0200 Subject: [PATCH 0246/5416] ALSA: wss_lib: rename cs4321_foo to wss_foo Rename functions and structures from the former cs4321_lib to names more corresponding with the new name: wss_lib. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/wss.h | 172 ++-- sound/isa/azt2320.c | 27 +- sound/isa/cs423x/cs4231.c | 16 +- sound/isa/cs423x/cs4236.c | 47 +- sound/isa/cs423x/cs4236_lib.c | 344 ++++---- sound/isa/gus/gusmax.c | 48 +- sound/isa/gus/interwave.c | 65 +- sound/isa/opl3sa2.c | 34 +- sound/isa/opti9xx/miro.c | 23 +- sound/isa/opti9xx/opti92x-ad1848.c | 36 +- sound/isa/sscape.c | 61 +- sound/isa/wavefront/wavefront.c | 61 +- sound/isa/wss/wss_lib.c | 1247 ++++++++++++++++------------ 13 files changed, 1225 insertions(+), 956 deletions(-) diff --git a/include/sound/wss.h b/include/sound/wss.h index f0785f9f4ae..3b53973f96a 100644 --- a/include/sound/wss.h +++ b/include/sound/wss.h @@ -1,5 +1,5 @@ -#ifndef __SOUND_CS4231_H -#define __SOUND_CS4231_H +#ifndef __SOUND_WSS_H +#define __SOUND_WSS_H /* * Copyright (c) by Jaroslav Kysela @@ -30,42 +30,42 @@ /* defines for codec.mode */ -#define CS4231_MODE_NONE 0x0000 -#define CS4231_MODE_PLAY 0x0001 -#define CS4231_MODE_RECORD 0x0002 -#define CS4231_MODE_TIMER 0x0004 -#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER) +#define WSS_MODE_NONE 0x0000 +#define WSS_MODE_PLAY 0x0001 +#define WSS_MODE_RECORD 0x0002 +#define WSS_MODE_TIMER 0x0004 +#define WSS_MODE_OPEN (WSS_MODE_PLAY|WSS_MODE_RECORD|WSS_MODE_TIMER) /* defines for codec.hardware */ -#define CS4231_HW_DETECT 0x0000 /* let CS4231 driver detect chip */ -#define CS4231_HW_DETECT3 0x0001 /* allow mode 3 */ -#define CS4231_HW_TYPE_MASK 0xff00 /* type mask */ -#define CS4231_HW_CS4231_MASK 0x0100 /* CS4231 serie */ -#define CS4231_HW_CS4231 0x0100 /* CS4231 chip */ -#define CS4231_HW_CS4231A 0x0101 /* CS4231A chip */ -#define CS4231_HW_AD1845 0x0102 /* AD1845 chip */ -#define CS4231_HW_CS4232_MASK 0x0200 /* CS4232 serie (has control ports) */ -#define CS4231_HW_CS4232 0x0200 /* CS4232 */ -#define CS4231_HW_CS4232A 0x0201 /* CS4232A */ -#define CS4231_HW_CS4236 0x0202 /* CS4236 */ -#define CS4231_HW_CS4236B_MASK 0x0400 /* CS4236B serie (has extended control regs) */ -#define CS4231_HW_CS4235 0x0400 /* CS4235 - Crystal Clear (tm) stereo enhancement */ -#define CS4231_HW_CS4236B 0x0401 /* CS4236B */ -#define CS4231_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */ -#define CS4231_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */ -#define CS4231_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */ +#define WSS_HW_DETECT 0x0000 /* let CS4231 driver detect chip */ +#define WSS_HW_DETECT3 0x0001 /* allow mode 3 */ +#define WSS_HW_TYPE_MASK 0xff00 /* type mask */ +#define WSS_HW_CS4231_MASK 0x0100 /* CS4231 serie */ +#define WSS_HW_CS4231 0x0100 /* CS4231 chip */ +#define WSS_HW_CS4231A 0x0101 /* CS4231A chip */ +#define WSS_HW_AD1845 0x0102 /* AD1845 chip */ +#define WSS_HW_CS4232_MASK 0x0200 /* CS4232 serie (has control ports) */ +#define WSS_HW_CS4232 0x0200 /* CS4232 */ +#define WSS_HW_CS4232A 0x0201 /* CS4232A */ +#define WSS_HW_CS4236 0x0202 /* CS4236 */ +#define WSS_HW_CS4236B_MASK 0x0400 /* CS4236B serie (has extended control regs) */ +#define WSS_HW_CS4235 0x0400 /* CS4235 - Crystal Clear (tm) stereo enhancement */ +#define WSS_HW_CS4236B 0x0401 /* CS4236B */ +#define WSS_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */ +#define WSS_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */ +#define WSS_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */ /* compatible, but clones */ -#define CS4231_HW_INTERWAVE 0x1000 /* InterWave chip */ -#define CS4231_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */ -#define CS4231_HW_OPTI93X 0x1102 /* Opti 930/931/933 */ +#define WSS_HW_INTERWAVE 0x1000 /* InterWave chip */ +#define WSS_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */ +#define WSS_HW_OPTI93X 0x1102 /* Opti 930/931/933 */ /* defines for codec.hwshare */ -#define CS4231_HWSHARE_IRQ (1<<0) -#define CS4231_HWSHARE_DMA1 (1<<1) -#define CS4231_HWSHARE_DMA2 (1<<2) +#define WSS_HWSHARE_IRQ (1<<0) +#define WSS_HWSHARE_DMA1 (1<<1) +#define WSS_HWSHARE_DMA2 (1<<2) -struct snd_cs4231 { +struct snd_wss { unsigned long port; /* base i/o port */ struct resource *res_port; unsigned long cport; /* control base i/o port (CS4236) */ @@ -74,8 +74,8 @@ struct snd_cs4231 { int dma1; /* playback DMA */ int dma2; /* record DMA */ unsigned short version; /* version of CODEC chip */ - unsigned short mode; /* see to CS4231_MODE_XXXX */ - unsigned short hardware; /* see to CS4231_HW_XXXX */ + unsigned short mode; /* see to WSS_MODE_XXXX */ + unsigned short hardware; /* see to WSS_HW_XXXX */ unsigned short hwshare; /* shared resources */ unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */ ebus_flag:1; /* SPARC: EBUS present */ @@ -100,43 +100,50 @@ struct snd_cs4231 { struct mutex open_mutex; int (*rate_constraint) (struct snd_pcm_runtime *runtime); - void (*set_playback_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char pdfr); - void (*set_capture_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char cdfr); - void (*trigger) (struct snd_cs4231 *chip, unsigned int what, int start); + void (*set_playback_format) (struct snd_wss *chip, + struct snd_pcm_hw_params *hw_params, + unsigned char pdfr); + void (*set_capture_format) (struct snd_wss *chip, + struct snd_pcm_hw_params *hw_params, + unsigned char cdfr); + void (*trigger) (struct snd_wss *chip, unsigned int what, int start); #ifdef CONFIG_PM - void (*suspend) (struct snd_cs4231 *chip); - void (*resume) (struct snd_cs4231 *chip); + void (*suspend) (struct snd_wss *chip); + void (*resume) (struct snd_wss *chip); #endif void *dma_private_data; - int (*claim_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma); - int (*release_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma); + int (*claim_dma) (struct snd_wss *chip, + void *dma_private_data, int dma); + int (*release_dma) (struct snd_wss *chip, + void *dma_private_data, int dma); }; /* exported functions */ -void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val); -unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg); -void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val); -unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg); -void snd_cs4231_mce_up(struct snd_cs4231 *chip); -void snd_cs4231_mce_down(struct snd_cs4231 *chip); +void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char val); +unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg); +void snd_cs4236_ext_out(struct snd_wss *chip, + unsigned char reg, unsigned char val); +unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg); +void snd_wss_mce_up(struct snd_wss *chip); +void snd_wss_mce_down(struct snd_wss *chip); -void snd_cs4231_overrange(struct snd_cs4231 *chip); +void snd_wss_overrange(struct snd_wss *chip); -irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id); +irqreturn_t snd_wss_interrupt(int irq, void *dev_id); -const char *snd_cs4231_chip_id(struct snd_cs4231 *chip); +const char *snd_wss_chip_id(struct snd_wss *chip); -int snd_cs4231_create(struct snd_card *card, +int snd_wss_create(struct snd_card *card, unsigned long port, unsigned long cport, int irq, int dma1, int dma2, unsigned short hardware, unsigned short hwshare, - struct snd_cs4231 ** rchip); -int snd_cs4231_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm); -int snd_cs4231_timer(struct snd_cs4231 * chip, int device, struct snd_timer **rtimer); -int snd_cs4231_mixer(struct snd_cs4231 * chip); + struct snd_wss **rchip); +int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); +int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); +int snd_wss_mixer(struct snd_wss *chip); int snd_cs4236_create(struct snd_card *card, unsigned long port, @@ -144,32 +151,45 @@ int snd_cs4236_create(struct snd_card *card, int irq, int dma1, int dma2, unsigned short hardware, unsigned short hwshare, - struct snd_cs4231 ** rchip); -int snd_cs4236_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm); -int snd_cs4236_mixer(struct snd_cs4231 * chip); + struct snd_wss **rchip); +int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); +int snd_cs4236_mixer(struct snd_wss *chip); /* * mixer library */ -#define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_single, \ - .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ +#define WSS_SINGLE(xname, xindex, reg, shift, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_wss_info_single, \ + .get = snd_wss_get_single, \ + .put = snd_wss_put_single, \ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); - -#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_double, \ - .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); - -#endif /* __SOUND_CS4231_H */ +int snd_wss_info_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +int snd_wss_get_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_wss_put_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +#define WSS_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_wss_info_double, \ + .get = snd_wss_get_double, \ + .put = snd_wss_put_double, \ + .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ + (shift_right << 19) | (mask << 24) | (invert << 22) } + +int snd_wss_info_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +int snd_wss_get_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_wss_put_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + +#endif /* __SOUND_WSS_H */ diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index a24db091d44..3e74d1a3928 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -76,7 +76,7 @@ struct snd_card_azt2320 { int dev_no; struct pnp_dev *dev; struct pnp_dev *devmpu; - struct snd_cs4231 *chip; + struct snd_wss *chip; }; static struct pnp_card_device_id snd_azt2320_pnpids[] = { @@ -181,7 +181,7 @@ static int __devinit snd_card_azt2320_probe(int dev, int error; struct snd_card *card; struct snd_card_azt2320 *acard; - struct snd_cs4231 *chip; + struct snd_wss *chip; struct snd_opl3 *opl3; if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, @@ -200,11 +200,11 @@ static int __devinit snd_card_azt2320_probe(int dev, return error; } - if ((error = snd_cs4231_create(card, wss_port[dev], -1, - irq[dev], - dma1[dev], - dma2[dev], - CS4231_HW_DETECT, 0, &chip)) < 0) { + error = snd_wss_create(card, wss_port[dev], -1, + irq[dev], + dma1[dev], dma2[dev], + WSS_HW_DETECT, 0, &chip); + if (error < 0) { snd_card_free(card); return error; } @@ -214,15 +214,18 @@ static int __devinit snd_card_azt2320_probe(int dev, sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - if ((error = snd_cs4231_pcm(chip, 0, NULL)) < 0) { + error = snd_wss_pcm(chip, 0, NULL); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_cs4231_mixer(chip)) < 0) { + error = snd_wss_mixer(chip); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_cs4231_timer(chip, 0, NULL)) < 0) { + error = snd_wss_timer(chip, 0, NULL); + if (error < 0) { snd_card_free(card); return error; } @@ -293,7 +296,7 @@ static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t sta { struct snd_card *card = pnp_get_card_drvdata(pcard); struct snd_card_azt2320 *acard = card->private_data; - struct snd_cs4231 *chip = acard->chip; + struct snd_wss *chip = acard->chip; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); chip->suspend(chip); @@ -304,7 +307,7 @@ static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard) { struct snd_card *card = pnp_get_card_drvdata(pcard); struct snd_card_azt2320 *acard = card->private_data; - struct snd_cs4231 *chip = acard->chip; + struct snd_wss *chip = acard->chip; chip->resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 7da28e7c032..ddd289120aa 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -91,7 +91,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) { struct snd_card *card; - struct snd_cs4231 *chip; + struct snd_wss *chip; struct snd_pcm *pcm; int error; @@ -99,14 +99,14 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) if (!card) return -EINVAL; - error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n], - CS4231_HW_DETECT, 0, &chip); + error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], + WSS_HW_DETECT, 0, &chip); if (error < 0) goto out; card->private_data = chip; - error = snd_cs4231_pcm(chip, 0, &pcm); + error = snd_wss_pcm(chip, 0, &pcm); if (error < 0) goto out; @@ -118,11 +118,11 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) if (dma2[n] >= 0) sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); - error = snd_cs4231_mixer(chip); + error = snd_wss_mixer(chip); if (error < 0) goto out; - error = snd_cs4231_timer(chip, 0, NULL); + error = snd_wss_timer(chip, 0, NULL); if (error < 0) goto out; @@ -160,7 +160,7 @@ static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n) static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) { struct snd_card *card = dev_get_drvdata(dev); - struct snd_cs4231 *chip = card->private_data; + struct snd_wss *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); chip->suspend(chip); @@ -170,7 +170,7 @@ static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t s static int snd_cs4231_resume(struct device *dev, unsigned int n) { struct snd_card *card = dev_get_drvdata(dev); - struct snd_cs4231 *chip = card->private_data; + struct snd_wss *chip = card->private_data; chip->resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 246c221556e..3ff0f122991 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -134,7 +134,7 @@ static int pnp_registered; #endif /* CONFIG_PNP */ struct snd_card_cs4236 { - struct snd_cs4231 *chip; + struct snd_wss *chip; struct resource *res_sb_port; #ifdef CONFIG_PNP struct pnp_dev *wss; @@ -396,7 +396,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) { struct snd_card_cs4236 *acard; struct snd_pcm *pcm; - struct snd_cs4231 *chip; + struct snd_wss *chip; struct snd_opl3 *opl3; int err; @@ -408,41 +408,37 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) } #ifdef CS4232 - if ((err = snd_cs4231_create(card, - port[dev], - cport[dev], - irq[dev], - dma1[dev], - dma2[dev], - CS4231_HW_DETECT, - 0, - &chip)) < 0) + err = snd_wss_create(card, port[dev], cport[dev], + irq[dev], + dma1[dev], dma2[dev], + WSS_HW_DETECT, 0, &chip); + if (err < 0) return err; acard->chip = chip; - if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) + err = snd_wss_pcm(chip, 0, &pcm); + if (err < 0) return err; - if ((err = snd_cs4231_mixer(chip)) < 0) + err = snd_wss_mixer(chip); + if (err < 0) return err; #else /* CS4236 */ - if ((err = snd_cs4236_create(card, - port[dev], - cport[dev], - irq[dev], - dma1[dev], - dma2[dev], - CS4231_HW_DETECT, - 0, - &chip)) < 0) + err = snd_cs4236_create(card, + port[dev], cport[dev], + irq[dev], dma1[dev], dma2[dev], + WSS_HW_DETECT, 0, &chip); + if (err < 0) return err; acard->chip = chip; - if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) + err = snd_cs4236_pcm(chip, 0, &pcm); + if (err < 0) return err; - if ((err = snd_cs4236_mixer(chip)) < 0) + err = snd_cs4236_mixer(chip); + if (err < 0) return err; #endif strcpy(card->driver, pcm->name); @@ -455,7 +451,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) if (dma2[dev] >= 0) sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) + err = snd_wss_timer(chip, 0, NULL); + if (err < 0) return err; if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index eb227d856d1..33e9cf178b8 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -121,13 +121,14 @@ static unsigned char snd_cs4236_ext_map[18] = { * */ -static void snd_cs4236_ctrl_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val) +static void snd_cs4236_ctrl_out(struct snd_wss *chip, + unsigned char reg, unsigned char val) { outb(reg, chip->cport + 3); outb(chip->cimage[reg] = val, chip->cport + 4); } -static unsigned char snd_cs4236_ctrl_in(struct snd_cs4231 *chip, unsigned char reg) +static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg) { outb(reg, chip->cport + 3); return inb(chip->cport + 4); @@ -180,44 +181,52 @@ static unsigned char divisor_to_rate_register(unsigned int divisor) } } -static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) +static void snd_cs4236_playback_format(struct snd_wss *chip, + struct snd_pcm_hw_params *params, + unsigned char pdfr) { unsigned long flags; unsigned char rate = divisor_to_rate_register(params->rate_den); spin_lock_irqsave(&chip->reg_lock, flags); /* set fast playback format change and clean playback FIFO */ - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] | 0x10); + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] & ~0x10); snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } -static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr) +static void snd_cs4236_capture_format(struct snd_wss *chip, + struct snd_pcm_hw_params *params, + unsigned char cdfr) { unsigned long flags; unsigned char rate = divisor_to_rate_register(params->rate_den); spin_lock_irqsave(&chip->reg_lock, flags); /* set fast capture format change and clean capture FIFO */ - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] | 0x20); + snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] & ~0x20); snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } #ifdef CONFIG_PM -static void snd_cs4236_suspend(struct snd_cs4231 *chip) +static void snd_cs4236_suspend(struct snd_wss *chip) { int reg; unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_cs4231_in(chip, reg); + chip->image[reg] = snd_wss_in(chip, reg); for (reg = 0; reg < 18; reg++) chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg)); for (reg = 2; reg < 9; reg++) @@ -225,12 +234,12 @@ static void snd_cs4236_suspend(struct snd_cs4231 *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); } -static void snd_cs4236_resume(struct snd_cs4231 *chip) +static void snd_cs4236_resume(struct snd_wss *chip) { int reg; unsigned long flags; - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) { switch (reg) { @@ -240,7 +249,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip) case 29: /* why? CS4235 - master right */ break; default: - snd_cs4231_out(chip, reg, chip->image[reg]); + snd_wss_out(chip, reg, chip->image[reg]); break; } } @@ -255,7 +264,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip) } } spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); } #endif /* CONFIG_PM */ @@ -266,24 +275,26 @@ int snd_cs4236_create(struct snd_card *card, int irq, int dma1, int dma2, unsigned short hardware, unsigned short hwshare, - struct snd_cs4231 ** rchip) + struct snd_wss **rchip) { - struct snd_cs4231 *chip; + struct snd_wss *chip; unsigned char ver1, ver2; unsigned int reg; int err; *rchip = NULL; - if (hardware == CS4231_HW_DETECT) - hardware = CS4231_HW_DETECT3; + if (hardware == WSS_HW_DETECT) + hardware = WSS_HW_DETECT3; if (cport < 0x100) { snd_printk("please, specify control port for CS4236+ chips\n"); return -ENODEV; } - if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0) + err = snd_wss_create(card, port, cport, + irq, dma1, dma2, hardware, hwshare, &chip); + if (err < 0) return err; - if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) { + if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware); snd_device_free(card, chip); return -ENODEV; @@ -330,20 +341,20 @@ int snd_cs4236_create(struct snd_card *card, snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]); /* initialize compatible but more featured registers */ - snd_cs4231_out(chip, CS4231_LEFT_INPUT, 0x40); - snd_cs4231_out(chip, CS4231_RIGHT_INPUT, 0x40); - snd_cs4231_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); - snd_cs4231_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff); - snd_cs4231_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf); - snd_cs4231_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf); - snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff); - snd_cs4231_out(chip, CS4231_LEFT_LINE_IN, 0xff); - snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff); + snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40); + snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40); + snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); + snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff); + snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf); + snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf); + snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); + snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff); + snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); switch (chip->hardware) { - case CS4231_HW_CS4235: - case CS4231_HW_CS4239: - snd_cs4231_out(chip, CS4235_LEFT_MASTER, 0xff); - snd_cs4231_out(chip, CS4235_RIGHT_MASTER, 0xff); + case WSS_HW_CS4235: + case WSS_HW_CS4239: + snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff); + snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff); break; } @@ -351,12 +362,13 @@ int snd_cs4236_create(struct snd_card *card, return 0; } -int snd_cs4236_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) +int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; - if ((err = snd_cs4231_pcm(chip, device, &pcm)) < 0) + err = snd_wss_pcm(chip, device, &pcm); + if (err < 0) return err; pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; if (rpcm) @@ -387,7 +399,7 @@ static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -404,7 +416,7 @@ static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -433,7 +445,7 @@ static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -450,7 +462,7 @@ static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -490,7 +502,7 @@ static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -512,7 +524,7 @@ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -555,7 +567,7 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -577,7 +589,7 @@ static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -600,7 +612,7 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_ val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)]; - snd_cs4231_out(chip, left_reg, val1); + snd_wss_out(chip, left_reg, val1); snd_cs4236_ext_out(chip, right_reg, val2); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; @@ -619,7 +631,7 @@ static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -631,7 +643,7 @@ static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct s static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1, val2; @@ -678,7 +690,7 @@ static inline int snd_cs4235_mixer_output_accu_set_volume(int vol) static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -690,7 +702,7 @@ static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1, val2; @@ -701,108 +713,160 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; - snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1); - snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2); + snd_wss_out(chip, CS4235_LEFT_MASTER, val1); + snd_wss_out(chip, CS4235_RIGHT_MASTER, val2); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } static struct snd_kcontrol_new snd_cs4236_controls[] = { -CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), -CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), +CS4236_DOUBLE("Master Digital Playback Switch", 0, + CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), +CS4236_DOUBLE("Master Digital Capture Switch", 0, + CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), CS4236_MASTER_DIGITAL("Master Digital Volume", 0), -CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), - -CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), - -CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), -CS4236_DOUBLE("DSP Playback Volume", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1), - -CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), -CS4236_DOUBLE("FM Playback Volume", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1), - -CS4236_DOUBLE("Wavetable Playback Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), -CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), - -CS4231_DOUBLE("Synth Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), -CS4231_DOUBLE("Synth Capture Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), - -CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), -CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), +CS4236_DOUBLE("Capture Boost Volume", 0, + CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), + +WSS_DOUBLE("PCM Playback Switch", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), + +CS4236_DOUBLE("DSP Playback Switch", 0, + CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), +CS4236_DOUBLE("DSP Playback Volume", 0, + CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1), + +CS4236_DOUBLE("FM Playback Switch", 0, + CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), +CS4236_DOUBLE("FM Playback Volume", 0, + CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1), + +CS4236_DOUBLE("Wavetable Playback Switch", 0, + CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), +CS4236_DOUBLE("Wavetable Playback Volume", 0, + CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), + +WSS_DOUBLE("Synth Playback Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +WSS_DOUBLE("Synth Volume", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), +WSS_DOUBLE("Synth Capture Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), +WSS_DOUBLE("Synth Capture Bypass", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), + +CS4236_DOUBLE("Mic Playback Switch", 0, + CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), +CS4236_DOUBLE("Mic Capture Switch", 0, + CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), -CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), - -CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_DOUBLE("Line Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), - -CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("CD Volume", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), - -CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), -CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), -CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), - -CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), -CS4231_DOUBLE("Analog Loopback Capture Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), - -CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), -CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) +CS4236_DOUBLE("Mic Playback Boost", 0, + CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), + +WSS_DOUBLE("Line Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Line Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), +WSS_DOUBLE("Line Capture Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), +WSS_DOUBLE("Line Capture Bypass", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), + +WSS_DOUBLE("CD Playback Switch", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("CD Volume", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), +WSS_DOUBLE("CD Capture Switch", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), + +CS4236_DOUBLE1("Mono Output Playback Switch", 0, + CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), +CS4236_DOUBLE1("Mono Playback Switch", 0, + CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), +WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), +WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), + +WSS_DOUBLE("Capture Volume", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +WSS_DOUBLE("Analog Loopback Capture Switch", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), + +WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), +CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, + CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) }; static struct snd_kcontrol_new snd_cs4235_controls[] = { -CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), -CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), +WSS_DOUBLE("Master Switch", 0, + CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), +WSS_DOUBLE("Master Volume", 0, + CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), CS4235_OUTPUT_ACCU("Playback Volume", 0), -CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), -CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), +CS4236_DOUBLE("Master Digital Playback Switch", 0, + CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), +CS4236_DOUBLE("Master Digital Capture Switch", 0, + CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), CS4236_MASTER_DIGITAL("Master Digital Volume", 0), -CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Master Digital Capture Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), +WSS_DOUBLE("Master Digital Playback Switch", 1, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +WSS_DOUBLE("Master Digital Capture Switch", 1, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), +WSS_DOUBLE("Master Digital Volume", 1, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), -CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), +CS4236_DOUBLE("Capture Volume", 0, + CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), -CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), +WSS_DOUBLE("PCM Switch", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("PCM Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), -CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), +CS4236_DOUBLE("Wavetable Switch", 0, + CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), -CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), -CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), +CS4236_DOUBLE("Mic Capture Switch", 0, + CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), +CS4236_DOUBLE("Mic Playback Switch", 0, + CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), -CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), - -CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Capture Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), -CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), - -CS4236_DOUBLE1("Master Mono Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), - -CS4236_DOUBLE1("Mono Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), - -CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), +WSS_DOUBLE("Aux Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Capture Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), +WSS_DOUBLE("Aux Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), + +WSS_DOUBLE("Aux Playback Switch", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Capture Switch", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), +WSS_DOUBLE("Aux Volume", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), + +CS4236_DOUBLE1("Master Mono Switch", 0, + CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), + +CS4236_DOUBLE1("Mono Switch", 0, + CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), +WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), + +WSS_DOUBLE("Analog Loopback Switch", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), }; #define CS4236_IEC958_ENABLE(xname, xindex) \ @@ -813,14 +877,14 @@ CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; #if 0 printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), + snd_wss_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), snd_cs4236_ctrl_in(chip, 5), @@ -833,7 +897,7 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short enable, val; @@ -841,23 +905,23 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn enable = ucontrol->value.integer.value[0] & 1; mutex_lock(&chip->mce_mutex); - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); change = val != chip->image[CS4231_ALT_FEATURE_1]; - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, val); val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; snd_cs4236_ctrl_out(chip, 4, val); udelay(100); val &= ~0x40; snd_cs4236_ctrl_out(chip, 4, val); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); mutex_unlock(&chip->mce_mutex); #if 0 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), + snd_wss_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), snd_cs4236_ctrl_in(chip, 5), @@ -896,7 +960,7 @@ CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1), CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) }; -int snd_cs4236_mixer(struct snd_cs4231 *chip) +int snd_cs4236_mixer(struct snd_wss *chip) { struct snd_card *card; unsigned int idx, count; @@ -905,10 +969,10 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip) snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); card = chip->card; - strcpy(card->mixername, snd_cs4231_chip_id(chip)); + strcpy(card->mixername, snd_wss_chip_id(chip)); - if (chip->hardware == CS4231_HW_CS4235 || - chip->hardware == CS4231_HW_CS4239) { + if (chip->hardware == WSS_HW_CS4235 || + chip->hardware == WSS_HW_CS4239) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) return err; @@ -920,16 +984,16 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip) } } switch (chip->hardware) { - case CS4231_HW_CS4235: - case CS4231_HW_CS4239: + case WSS_HW_CS4235: + case WSS_HW_CS4239: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235); kcontrol = snd_cs4236_3d_controls_cs4235; break; - case CS4231_HW_CS4237B: + case WSS_HW_CS4237B: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237); kcontrol = snd_cs4236_3d_controls_cs4237; break; - case CS4231_HW_CS4238B: + case WSS_HW_CS4238B: count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238); kcontrol = snd_cs4236_3d_controls_cs4238; break; @@ -941,8 +1005,8 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip) if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) return err; } - if (chip->hardware == CS4231_HW_CS4237B || - chip->hardware == CS4231_HW_CS4238B) { + if (chip->hardware == WSS_HW_CS4237B || + chip->hardware == WSS_HW_CS4238B) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) return err; diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index cd82891db80..f94c1976e63 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -75,7 +75,7 @@ struct snd_gusmax { int irq; struct snd_card *card; struct snd_gus_card *gus; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; unsigned short gus_status_reg; unsigned short pcm_status_reg; }; @@ -117,7 +117,7 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id) } if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ handled = 1; - snd_cs4231_interrupt(irq, maxcard->cs4231); + snd_wss_interrupt(irq, maxcard->wss); loop++; } } while (loop && --max > 0); @@ -140,10 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card, outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT)); } -#define CS4231_PRIVATE( left, right, shift, mute ) \ - ((left << 24)|(right << 16)|(shift<<8)|mute) - -static int __devinit snd_gusmax_mixer(struct snd_cs4231 *chip) +static int __devinit snd_gusmax_mixer(struct snd_wss *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -214,7 +211,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) int xirq, xdma1, xdma2, err; struct snd_card *card; struct snd_gus_card *gus = NULL; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; struct snd_gusmax *maxcard; card = snd_card_new(index[dev], id[dev], THIS_MODULE, @@ -301,33 +298,39 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) } maxcard->irq = xirq; - if ((err = snd_cs4231_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - CS4231_HW_DETECT, - CS4231_HWSHARE_IRQ | - CS4231_HWSHARE_DMA1 | - CS4231_HWSHARE_DMA2, - &cs4231)) < 0) + err = snd_wss_create(card, + gus->gf1.port + 0x10c, -1, xirq, + xdma2 < 0 ? xdma1 : xdma2, xdma1, + WSS_HW_DETECT, + WSS_HWSHARE_IRQ | + WSS_HWSHARE_DMA1 | + WSS_HWSHARE_DMA2, + &wss); + if (err < 0) goto _err; - if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) + err = snd_wss_pcm(wss, 0, NULL); + if (err < 0) goto _err; - if ((err = snd_cs4231_mixer(cs4231)) < 0) + err = snd_wss_mixer(wss); + if (err < 0) goto _err; - if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) + err = snd_wss_timer(wss, 2, NULL); + if (err < 0) goto _err; if (pcm_channels[dev] > 0) { if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) goto _err; } - if ((err = snd_gusmax_mixer(cs4231)) < 0) + err = snd_gusmax_mixer(wss); + if (err < 0) goto _err; - if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) + err = snd_gf1_rawmidi_new(gus, 0, NULL); + if (err < 0) goto _err; sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1); @@ -336,11 +339,12 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) snd_card_set_dev(card, pdev); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto _err; maxcard->gus = gus; - maxcard->cs4231 = cs4231; + maxcard->wss = wss; dev_set_drvdata(pdev, card); return 0; diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index eac8cc77e33..5faecfb602d 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -118,7 +118,7 @@ struct snd_interwave { int irq; struct snd_card *card; struct snd_gus_card *gus; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; #ifdef SNDRV_STB struct resource *i2c_res; #endif @@ -312,7 +312,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id) } if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ handled = 1; - snd_cs4231_interrupt(irq, iwcard->cs4231); + snd_wss_interrupt(irq, iwcard->wss); loop++; } } while (loop && --max > 0); @@ -498,13 +498,17 @@ static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus) } static struct snd_kcontrol_new snd_interwave_controls[] = { -CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), -CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) +WSS_DOUBLE("Master Playback Switch", 0, + CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("Master Playback Volume", 0, + CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), +WSS_DOUBLE("Mic Playback Switch", 0, + CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Mic Playback Volume", 0, + CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) }; -static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip) +static int __devinit snd_interwave_mixer(struct snd_wss *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -527,10 +531,10 @@ static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip) for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) return err; - snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); - snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); - snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); - snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f); + snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); + snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); + snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); + snd_wss_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f); /* reassign AUXA to SYNTHESIZER */ strcpy(id1.name, "Aux Playback Switch"); strcpy(id2.name, "Synth Playback Switch"); @@ -642,7 +646,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) { int xirq, xdma1, xdma2; struct snd_interwave *iwcard = card->private_data; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; struct snd_gus_card *gus; #ifdef SNDRV_STB struct snd_i2c_bus *i2c_bus; @@ -684,33 +688,39 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) } iwcard->irq = xirq; - if ((err = snd_cs4231_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - CS4231_HW_INTERWAVE, - CS4231_HWSHARE_IRQ | - CS4231_HWSHARE_DMA1 | - CS4231_HWSHARE_DMA2, - &cs4231)) < 0) + err = snd_wss_create(card, + gus->gf1.port + 0x10c, -1, xirq, + xdma2 < 0 ? xdma1 : xdma2, xdma1, + WSS_HW_INTERWAVE, + WSS_HWSHARE_IRQ | + WSS_HWSHARE_DMA1 | + WSS_HWSHARE_DMA2, + &wss); + if (err < 0) return err; - if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) + err = snd_wss_pcm(wss, 0, &pcm); + if (err < 0) return err; sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); strcat(pcm->name, " (codec)"); - if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) + err = snd_wss_timer(wss, 2, NULL); + if (err < 0) return err; - if ((err = snd_cs4231_mixer(cs4231)) < 0) + err = snd_wss_mixer(wss); + if (err < 0) return err; if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) + err = snd_gf1_pcm_new(gus, 1, 1, NULL); + if (err < 0) return err; } - if ((err = snd_interwave_mixer(cs4231)) < 0) + err = snd_interwave_mixer(wss); + if (err < 0) return err; #ifdef SNDRV_STB @@ -754,10 +764,11 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) return err; - iwcard->cs4231 = cs4231; + iwcard->wss = wss; iwcard->gus = gus; return 0; } diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index e81cbe86823..949fee5cd07 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -133,7 +133,7 @@ struct snd_opl3sa2 { spinlock_t reg_lock; struct snd_hwdep *synth; struct snd_rawmidi *rmidi; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; unsigned char ctlregs[0x20]; int ymode; /* SL added */ struct snd_kcontrol *master_switch; @@ -318,7 +318,7 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) if (status & 0x07) { /* TI,CI,PI */ handled = 1; - snd_cs4231_interrupt(irq, chip->cs4231); + snd_wss_interrupt(irq, chip->wss); } if (status & 0x40) { /* hardware volume change */ @@ -573,7 +573,7 @@ static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) struct snd_opl3sa2 *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->cs4231->suspend(chip->cs4231); + chip->wss->suspend(chip->wss); /* power down */ snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); @@ -597,8 +597,8 @@ static int snd_opl3sa2_resume(struct snd_card *card) for (i = 0x12; i <= 0x16; i++) snd_opl3sa2_write(chip, i, chip->ctlregs[i]); } - /* restore cs4231 */ - chip->cs4231->resume(chip->cs4231); + /* restore wss */ + chip->wss->resume(chip->wss); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; @@ -659,7 +659,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) { int xirq, xdma1, xdma2; struct snd_opl3sa2 *chip; - struct snd_cs4231 *cs4231; + struct snd_wss *wss; struct snd_opl3 *opl3; int err; @@ -679,23 +679,25 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) return -ENODEV; } chip->irq = xirq; - if ((err = snd_cs4231_create(card, - wss_port[dev] + 4, -1, - xirq, xdma1, xdma2, - CS4231_HW_OPL3SA2, - CS4231_HWSHARE_IRQ, - &cs4231)) < 0) { + err = snd_wss_create(card, + wss_port[dev] + 4, -1, + xirq, xdma1, xdma2, + WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss); + if (err < 0) { snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); return err; } - chip->cs4231 = cs4231; - if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) + chip->wss = wss; + err = snd_wss_pcm(wss, 0, NULL); + if (err < 0) return err; - if ((err = snd_cs4231_mixer(cs4231)) < 0) + err = snd_wss_mixer(wss); + if (err < 0) return err; if ((err = snd_opl3sa2_mixer(chip)) < 0) return err; - if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0) + err = snd_wss_timer(wss, 0, NULL); + if (err < 0) return err; if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { if ((err = snd_opl3_create(card, fm_port[dev], diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 59f7c55baf3..4641daa7844 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1221,7 +1221,7 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) int error; struct snd_miro *miro; - struct snd_cs4231 *codec; + struct snd_wss *codec; struct snd_timer *timer; struct snd_card *card; struct snd_pcm *pcm; @@ -1310,29 +1310,32 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) } } - if ((error = snd_miro_configure(miro))) { + error = snd_miro_configure(miro); + if (error) { snd_card_free(card); return error; } - if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1, - miro->irq, miro->dma1, miro->dma2, - CS4231_HW_AD1845, - 0, - &codec)) < 0) { + error = snd_wss_create(card, miro->wss_base + 4, -1, + miro->irq, miro->dma1, miro->dma2, + WSS_HW_AD1845, 0, &codec); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) { + error = snd_wss_pcm(codec, 0, &pcm); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_cs4231_mixer(codec)) < 0) { + error = snd_wss_mixer(codec); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) { + error = snd_wss_timer(codec, 0, &timer); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 93a03d9c7a9..fefb8597717 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -139,7 +139,7 @@ struct snd_opti9xx { unsigned long mc_base_size; #ifdef OPTi93X unsigned long mc_indir_index; - struct snd_cs4231 *codec; + struct snd_wss *codec; #endif /* OPTi93X */ unsigned long pwd_reg; @@ -562,7 +562,7 @@ __skip_mpu: static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) { - struct snd_cs4231 *codec = dev_id; + struct snd_wss *codec = dev_id; struct snd_opti9xx *chip = codec->card->private_data; unsigned char status; @@ -570,7 +570,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) snd_pcm_period_elapsed(codec->playback_substream); if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) { - snd_cs4231_overrange(codec); + snd_wss_overrange(codec); snd_pcm_period_elapsed(codec->capture_substream); } outb(0x00, OPTi93X_PORT(codec, STATUS)); @@ -691,7 +691,7 @@ static void snd_card_opti9xx_free(struct snd_card *card) if (chip) { #ifdef OPTi93X - struct snd_cs4231 *codec = chip->codec; + struct snd_wss *codec = chip->codec; if (codec && codec->irq > 0) { disable_irq(codec->irq); free_irq(codec->irq, codec); @@ -707,7 +707,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) int error; struct snd_opti9xx *chip = card->private_data; #if defined(CS4231) || defined(OPTi93X) - struct snd_cs4231 *codec; + struct snd_wss *codec; #ifdef CS4231 struct snd_timer *timer; #endif @@ -734,33 +734,39 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #endif if (chip->wss_base == SNDRV_AUTO_PORT) { - if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { + chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4); + if (chip->wss_base < 0) { snd_printk("unable to find a free WSS port\n"); return -EBUSY; } } - if ((error = snd_opti9xx_configure(chip))) + error = snd_opti9xx_configure(chip); + if (error) return error; #if defined(CS4231) || defined(OPTi93X) - if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1, - chip->irq, chip->dma1, chip->dma2, + error = snd_wss_create(card, chip->wss_base + 4, -1, + chip->irq, chip->dma1, chip->dma2, #ifdef CS4231 - CS4231_HW_DETECT, 0, + WSS_HW_DETECT, 0, #else /* OPTi93x */ - CS4231_HW_OPTI93X, CS4231_HWSHARE_IRQ, + WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, #endif - &codec)) < 0) + &codec); + if (error < 0) return error; #ifdef OPTi93X chip->codec = codec; #endif - if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) + error = snd_wss_pcm(codec, 0, &pcm); + if (error < 0) return error; - if ((error = snd_cs4231_mixer(codec)) < 0) + error = snd_wss_mixer(codec); + if (error < 0) return error; #ifdef CS4231 - if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) + error = snd_wss_timer(codec, 0, &timer); + if (error < 0) return error; #else /* OPTI93X */ error = request_irq(chip->irq, snd_opti93x_interrupt, diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 1dc4224b320..48a16d86583 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -147,7 +147,7 @@ struct soundscape { enum card_type type; struct resource *io_res; struct resource *wss_res; - struct snd_cs4231 *chip; + struct snd_wss *chip; struct snd_mpu401 *mpu; struct snd_hwdep *hw; @@ -726,7 +726,7 @@ static int sscape_midi_info(struct snd_kcontrol *ctl, static int sscape_midi_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kctl); + struct snd_wss *chip = snd_kcontrol_chip(kctl); struct snd_card *card = chip->card; register struct soundscape *s = get_card_soundscape(card); unsigned long flags; @@ -746,7 +746,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, static int sscape_midi_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kctl); + struct snd_wss *chip = snd_kcontrol_chip(kctl); struct snd_card *card = chip->card; register struct soundscape *s = get_card_soundscape(card); unsigned long flags; @@ -958,7 +958,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l * Override for the CS4231 playback format function. * The AD1845 has much simpler format and rate selection. */ -static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) +static void ad1845_playback_format(struct snd_wss *chip, + struct snd_pcm_hw_params *params, + unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); @@ -983,9 +985,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); - snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); - snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); + snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); + snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } @@ -994,7 +996,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p * Override for the CS4231 capture format function. * The AD1845 has much simpler format and rate selection. */ -static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) +static void ad1845_capture_format(struct snd_wss *chip, + struct snd_pcm_hw_params *params, + unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); @@ -1019,9 +1023,9 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ - snd_cs4231_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); - snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); - snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); + snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); + snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); + snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } @@ -1036,7 +1040,7 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1, int dma2) { register struct soundscape *sscape = get_card_soundscape(card); - struct snd_cs4231 *chip; + struct snd_wss *chip; int err; if (sscape->type == SSCAPE_VIVO) @@ -1045,9 +1049,8 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, if (dma1 == dma2) dma2 = -1; - err = snd_cs4231_create(card, - port, -1, irq, dma1, dma2, - CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip); + err = snd_wss_create(card, port, -1, irq, dma1, dma2, + WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip); if (!err) { unsigned long flags; struct snd_pcm *pcm; @@ -1063,11 +1066,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, * #define AD1845_IFACE_CONFIG \ (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE) - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG); + snd_wss_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); */ if (sscape->type != SSCAPE_VIVO) { @@ -1077,11 +1080,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, * be 14.31818 MHz, because we must set this register * to get the playback to sound correct ... */ - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); + snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); /* * More custom configuration: @@ -1089,28 +1092,28 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, * b) enable frequency selection (for capture/playback) */ spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_MISC_INFO, - CS4231_MODE2 | 0x10); - val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL); - snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, - val | AD1845_FREQ_SEL_ENABLE); + snd_wss_out(chip, CS4231_MISC_INFO, + CS4231_MODE2 | 0x10); + val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL); + snd_wss_out(chip, AD1845_PWR_DOWN_CTRL, + val | AD1845_FREQ_SEL_ENABLE); spin_unlock_irqrestore(&chip->reg_lock, flags); } - err = snd_cs4231_pcm(chip, 0, &pcm); + err = snd_wss_pcm(chip, 0, &pcm); if (err < 0) { snd_printk(KERN_ERR "sscape: No PCM device " "for AD1845 chip\n"); goto _error; } - err = snd_cs4231_mixer(chip); + err = snd_wss_mixer(chip); if (err < 0) { snd_printk(KERN_ERR "sscape: No mixer device " "for AD1845 chip\n"); goto _error; } - err = snd_cs4231_timer(chip, 0, NULL); + err = snd_wss_timer(chip, 0, NULL); if (err < 0) { snd_printk(KERN_ERR "sscape: No timer device " "for AD1845 chip\n"); diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 2fb058b5a45..4c095bc7c72 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -1,6 +1,6 @@ /* * ALSA card-level driver for Turtle Beach Wavefront cards - * (Maui,Tropez,Tropez+) + * (Maui,Tropez,Tropez+) * * Copyright (c) 1997-1999 by Paul Barton-Davis * @@ -320,8 +320,8 @@ snd_wavefront_new_midi (struct snd_card *card, snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input); rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; + SNDRV_RAWMIDI_INFO_INPUT | + SNDRV_RAWMIDI_INFO_DUPLEX; return rmidi; } @@ -364,7 +364,7 @@ static int __devinit snd_wavefront_probe (struct snd_card *card, int dev) { snd_wavefront_card_t *acard = card->private_data; - struct snd_cs4231 *chip; + struct snd_wss *chip; struct snd_hwdep *wavefront_synth; struct snd_rawmidi *ics2115_internal_rmidi = NULL; struct snd_rawmidi *ics2115_external_rmidi = NULL; @@ -373,21 +373,20 @@ snd_wavefront_probe (struct snd_card *card, int dev) /* --------- PCM --------------- */ - if ((err = snd_cs4231_create (card, - cs4232_pcm_port[dev], - -1, - cs4232_pcm_irq[dev], - dma1[dev], - dma2[dev], - CS4231_HW_DETECT, 0, &chip)) < 0) { - snd_printk (KERN_ERR "can't allocate CS4231 device\n"); + err = snd_wss_create(card, cs4232_pcm_port[dev], -1, + cs4232_pcm_irq[dev], dma1[dev], dma2[dev], + WSS_HW_DETECT, 0, &chip); + if (err < 0) { + snd_printk(KERN_ERR "can't allocate WSS device\n"); return err; } - if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0) + err = snd_wss_pcm(chip, 0, NULL); + if (err < 0) return err; - if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0) + err = snd_wss_timer(chip, 0, NULL); + if (err < 0) return err; /* ---------- OPL3 synth --------- */ @@ -395,24 +394,24 @@ snd_wavefront_probe (struct snd_card *card, int dev) if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { struct snd_opl3 *opl3; - if ((err = snd_opl3_create(card, - fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3_CS, - 0, &opl3)) < 0) { + err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, + OPL3_HW_OPL3_CS, 0, &opl3); + if (err < 0) { snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); return err; } - if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0) + err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL); + if (err < 0) return err; hw_dev++; } /* ------- ICS2115 Wavetable synth ------- */ - if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16, - "ICS2115")) == NULL) { + acard->wavefront.res_base = request_region(ics2115_port[dev], 16, + "ICS2115"); + if (acard->wavefront.res_base == NULL) { snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", ics2115_port[dev], ics2115_port[dev] + 16 - 1); return -EBUSY; @@ -426,7 +425,8 @@ snd_wavefront_probe (struct snd_card *card, int dev) acard->wavefront.irq = ics2115_irq[dev]; acard->wavefront.base = ics2115_port[dev]; - if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) { + wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); + if (wavefront_synth == NULL) { snd_printk (KERN_ERR "can't create WaveFront synth device\n"); return -ENOMEM; } @@ -437,7 +437,8 @@ snd_wavefront_probe (struct snd_card *card, int dev) /* --------- Mixer ------------ */ - if ((err = snd_cs4231_mixer(chip)) < 0) { + err = snd_wss_mixer(chip); + if (err < 0) { snd_printk (KERN_ERR "can't allocate mixer device\n"); return err; } @@ -445,11 +446,11 @@ snd_wavefront_probe (struct snd_card *card, int dev) /* -------- CS4232 MPU-401 interface -------- */ if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { - if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, - cs4232_mpu_port[dev], 0, - cs4232_mpu_irq[dev], - IRQF_DISABLED, - NULL)) < 0) { + err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, + cs4232_mpu_port[dev], 0, + cs4232_mpu_irq[dev], IRQF_DISABLED, + NULL); + if (err < 0) { snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); return err; } @@ -602,7 +603,7 @@ static struct isa_driver snd_wavefront_driver = { #ifdef CONFIG_PNP static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) + const struct pnp_card_device_id *pid) { static int dev; struct snd_card *card; diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 549e6ab34b0..a982997805c 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -6,7 +6,7 @@ * - sometimes record brokes playback with WSS portion of * Yamaha OPL3-SA3 chip * - CS4231 (GUS MAX) - still trouble with occasional noises - * - broken initialization? + * - broken initialization? * * 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 @@ -78,12 +78,13 @@ static struct snd_pcm_hw_constraint_list hw_constraints_rates = { .mask = 0, }; -static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime) +static int snd_wss_xrate(struct snd_pcm_runtime *runtime) { - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); + return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraints_rates); } -static unsigned char snd_cs4231_original_image[32] = +static unsigned char snd_wss_original_image[32] = { 0x00, /* 00/00 - lic */ 0x00, /* 01/01 - ric */ @@ -159,150 +160,209 @@ static unsigned char snd_opti93x_original_image[32] = * Basic I/O functions */ -static inline void cs4231_outb(struct snd_cs4231 *chip, u8 offset, u8 val) +static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val) { outb(val, chip->port + offset); } -static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset) +static inline u8 wss_inb(struct snd_wss *chip, u8 offset) { return inb(chip->port + offset); } -static void snd_cs4231_wait(struct snd_cs4231 *chip) +static void snd_wss_wait(struct snd_wss *chip) { int timeout; for (timeout = 250; - timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); + timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) udelay(100); } -static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, +static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, unsigned char mask, unsigned char value) { unsigned char tmp = (chip->image[reg] & mask) | value; - snd_cs4231_wait(chip); + snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif chip->image[reg] = tmp; if (!chip->calibrate_mute) { - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wmb(); - cs4231_outb(chip, CS4231P(REG), tmp); + wss_outb(chip, CS4231P(REG), tmp); mb(); } } -static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, + unsigned char value) { int timeout; for (timeout = 250; - timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); + timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) udelay(10); - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - cs4231_outb(chip, CS4231P(REG), value); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); + wss_outb(chip, CS4231P(REG), value); mb(); } -void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) { - snd_cs4231_wait(chip); + snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - cs4231_outb(chip, CS4231P(REG), value); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); + wss_outb(chip, CS4231P(REG), value); chip->image[reg] = value; mb(); snd_printdd("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); } +EXPORT_SYMBOL(snd_wss_out); -unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) +unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) { - snd_cs4231_wait(chip); + snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); #endif - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); mb(); - return cs4231_inb(chip, CS4231P(REG)); + return wss_inb(chip, CS4231P(REG)); } +EXPORT_SYMBOL(snd_wss_in); -void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val) +void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, + unsigned char val) { - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01)); - cs4231_outb(chip, CS4231P(REG), val); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); + wss_outb(chip, CS4231P(REG), + reg | (chip->image[CS4236_EXT_REG] & 0x01)); + wss_outb(chip, CS4231P(REG), val); chip->eimage[CS4236_REG(reg)] = val; #if 0 printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val); #endif } +EXPORT_SYMBOL(snd_cs4236_ext_out); -unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg) +unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) { - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01)); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); + wss_outb(chip, CS4231P(REG), + reg | (chip->image[CS4236_EXT_REG] & 0x01)); #if 1 - return cs4231_inb(chip, CS4231P(REG)); + return wss_inb(chip, CS4231P(REG)); #else { unsigned char res; - res = cs4231_inb(chip, CS4231P(REG)); + res = wss_inb(chip, CS4231P(REG)); printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res); return res; } #endif } +EXPORT_SYMBOL(snd_cs4236_ext_in); #if 0 -static void snd_cs4231_debug(struct snd_cs4231 *chip) -{ - printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL))); - printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS))); - printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00)); - printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10)); - printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01)); - printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11)); - printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02)); - printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12)); - printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03)); - printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13)); - printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04)); - printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14)); - printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05)); - printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15)); - printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06)); - printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16)); - printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07)); - printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17)); - printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08)); - printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18)); - printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09)); - printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19)); - printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a)); - printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a)); - printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b)); - printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b)); - printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c)); - printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c)); - printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d)); - printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d)); - printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e)); - printk(" 0x1e: ply lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e)); - printk(" 0x0f: rec upr count = 0x%02x ", snd_cs4231_in(chip, 0x0f)); - printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f)); +static void snd_wss_debug(struct snd_wss *chip) +{ + printk(KERN_DEBUG + "CS4231 REGS: INDEX = 0x%02x " + " STATUS = 0x%02x\n", + wss_inb(chip, CS4231P(REGSEL), + wss_inb(chip, CS4231P(STATUS))); + printk(KERN_DEBUG + " 0x00: left input = 0x%02x " + " 0x10: alt 1 (CFIG 2) = 0x%02x\n", + snd_wss_in(chip, 0x00), + snd_wss_in(chip, 0x10)); + printk(KERN_DEBUG + " 0x01: right input = 0x%02x " + " 0x11: alt 2 (CFIG 3) = 0x%02x\n", + snd_wss_in(chip, 0x01), + snd_wss_in(chip, 0x11)); + printk(KERN_DEBUG + " 0x02: GF1 left input = 0x%02x " + " 0x12: left line in = 0x%02x\n", + snd_wss_in(chip, 0x02), + snd_wss_in(chip, 0x12)); + printk(KERN_DEBUG + " 0x03: GF1 right input = 0x%02x " + " 0x13: right line in = 0x%02x\n", + snd_wss_in(chip, 0x03), + snd_wss_in(chip, 0x13)); + printk(KERN_DEBUG + " 0x04: CD left input = 0x%02x " + " 0x14: timer low = 0x%02x\n", + snd_wss_in(chip, 0x04), + snd_wss_in(chip, 0x14)); + printk(KERN_DEBUG + " 0x05: CD right input = 0x%02x " + " 0x15: timer high = 0x%02x\n", + snd_wss_in(chip, 0x05), + snd_wss_in(chip, 0x15)); + printk(KERN_DEBUG + " 0x06: left output = 0x%02x " + " 0x16: left MIC (PnP) = 0x%02x\n", + snd_wss_in(chip, 0x06), + snd_wss_in(chip, 0x16)); + printk(KERN_DEBUG + " 0x07: right output = 0x%02x " + " 0x17: right MIC (PnP) = 0x%02x\n", + snd_wss_in(chip, 0x07), + snd_wss_in(chip, 0x17)); + printk(KERN_DEBUG + " 0x08: playback format = 0x%02x " + " 0x18: IRQ status = 0x%02x\n", + snd_wss_in(chip, 0x08), + snd_wss_in(chip, 0x18)); + printk(KERN_DEBUG + " 0x09: iface (CFIG 1) = 0x%02x " + " 0x19: left line out = 0x%02x\n", + snd_wss_in(chip, 0x09), + snd_wss_in(chip, 0x19)); + printk(KERN_DEBUG + " 0x0a: pin control = 0x%02x " + " 0x1a: mono control = 0x%02x\n", + snd_wss_in(chip, 0x0a), + snd_wss_in(chip, 0x1a)); + printk(KERN_DEBUG + " 0x0b: init & status = 0x%02x " + " 0x1b: right line out = 0x%02x\n", + snd_wss_in(chip, 0x0b), + snd_wss_in(chip, 0x1b)); + printk(KERN_DEBUG + " 0x0c: revision & mode = 0x%02x " + " 0x1c: record format = 0x%02x\n", + snd_wss_in(chip, 0x0c), + snd_wss_in(chip, 0x1c)); + printk(KERN_DEBUG + " 0x0d: loopback = 0x%02x " + " 0x1d: var freq (PnP) = 0x%02x\n", + snd_wss_in(chip, 0x0d), + snd_wss_in(chip, 0x1d)); + printk(KERN_DEBUG + " 0x0e: ply upr count = 0x%02x " + " 0x1e: ply lwr count = 0x%02x\n", + snd_wss_in(chip, 0x0e), + snd_wss_in(chip, 0x1e)); + printk(KERN_DEBUG + " 0x0f: rec upr count = 0x%02x " + " 0x1f: rec lwr count = 0x%02x\n", + snd_wss_in(chip, 0x0f), + snd_wss_in(chip, 0x1f)); } #endif @@ -311,61 +371,63 @@ static void snd_cs4231_debug(struct snd_cs4231 *chip) * CS4231 detection / MCE routines */ -static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) +static void snd_wss_busy_wait(struct snd_wss *chip) { int timeout; /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ for (timeout = 5; timeout > 0; timeout--) - cs4231_inb(chip, CS4231P(REGSEL)); + wss_inb(chip, CS4231P(REGSEL)); /* end of cleanup sequence */ for (timeout = 250; - timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); + timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) udelay(10); } -void snd_cs4231_mce_up(struct snd_cs4231 *chip) +void snd_wss_mce_up(struct snd_wss *chip) { unsigned long flags; int timeout; - snd_cs4231_wait(chip); + snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= CS4231_MCE; - timeout = cs4231_inb(chip, CS4231P(REGSEL)); + timeout = wss_inb(chip, CS4231P(REGSEL)); if (timeout == 0x80) snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); if (!(timeout & CS4231_MCE)) - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); + wss_outb(chip, CS4231P(REGSEL), + chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); } +EXPORT_SYMBOL(snd_wss_mce_up); -void snd_cs4231_mce_down(struct snd_cs4231 *chip) +void snd_wss_mce_down(struct snd_wss *chip) { unsigned long flags; unsigned long end_time; int timeout; - snd_cs4231_busy_wait(chip); + snd_wss_busy_wait(chip); #ifdef CONFIG_SND_DEBUG - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit &= ~CS4231_MCE; - timeout = cs4231_inb(chip, CS4231P(REGSEL)); - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); + timeout = wss_inb(chip, CS4231P(REGSEL)); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); if ((timeout & CS4231_MCE) == 0 || - !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) { + !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { return; } @@ -380,7 +442,7 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip) /* check condition up to 250 ms */ end_time = jiffies + msecs_to_jiffies(250); - while (snd_cs4231_in(chip, CS4231_TEST_INIT) & + while (snd_wss_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { if (time_after(jiffies, end_time)) { @@ -395,7 +457,7 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip) /* check condition up to 100 ms */ end_time = jiffies + msecs_to_jiffies(100); - while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { + while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { if (time_after(jiffies, end_time)) { snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); return; @@ -404,10 +466,11 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip) } snd_printdd("(3) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL))); + snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL))); } +EXPORT_SYMBOL(snd_wss_mce_down); -static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) +static unsigned int snd_wss_get_count(unsigned char format, unsigned int size) { switch (format & 0xe0) { case CS4231_LINEAR_16: @@ -422,19 +485,15 @@ static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size return size; } -static int snd_cs4231_trigger(struct snd_pcm_substream *substream, - int cmd) +static int snd_wss_trigger(struct snd_pcm_substream *substream, + int cmd) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); int result = 0; unsigned int what; struct snd_pcm_substream *s; int do_start; -#if 0 - printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS))); -#endif - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -466,10 +525,10 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, if (chip->trigger) chip->trigger(chip, what, 0); } - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); spin_unlock(&chip->reg_lock); #if 0 - snd_cs4231_debug(chip); + snd_wss_debug(chip); #endif return result; } @@ -478,7 +537,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, * CODEC I/O */ -static unsigned char snd_cs4231_get_rate(unsigned int rate) +static unsigned char snd_wss_get_rate(unsigned int rate) { int i; @@ -489,9 +548,9 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) return freq_bits[ARRAY_SIZE(rates) - 1]; } -static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, - int format, - int channels) +static unsigned char snd_wss_get_format(struct snd_wss *chip, + int format, + int channels) { unsigned char rformat; @@ -511,7 +570,7 @@ static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, return rformat; } -static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) +static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) { unsigned long flags; @@ -522,30 +581,46 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) return; } if (!mute) { - snd_cs4231_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]); - snd_cs4231_dout(chip, CS4231_RIGHT_INPUT, chip->image[CS4231_RIGHT_INPUT]); - snd_cs4231_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]); + snd_wss_dout(chip, CS4231_LEFT_INPUT, + chip->image[CS4231_LEFT_INPUT]); + snd_wss_dout(chip, CS4231_RIGHT_INPUT, + chip->image[CS4231_RIGHT_INPUT]); + snd_wss_dout(chip, CS4231_LOOPBACK, + chip->image[CS4231_LOOPBACK]); } - snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]); - snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]); - snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]); - snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]); - snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]); - snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]); - snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN, mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); - snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN, mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); - snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); - if (chip->hardware == CS4231_HW_INTERWAVE) { - snd_cs4231_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); - snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]); - snd_cs4231_dout(chip, CS4231_LINE_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]); - snd_cs4231_dout(chip, CS4231_LINE_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]); + snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, + mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]); + snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, + mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]); + snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT, + mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]); + snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT, + mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]); + snd_wss_dout(chip, CS4231_LEFT_OUTPUT, + mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]); + snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, + mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]); + snd_wss_dout(chip, CS4231_LEFT_LINE_IN, + mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); + snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, + mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); + snd_wss_dout(chip, CS4231_MONO_CTRL, + mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); + if (chip->hardware == WSS_HW_INTERWAVE) { + snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, + mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); + snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT, + mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]); + snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT, + mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]); + snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT, + mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]); } chip->calibrate_mute = mute; spin_unlock_irqrestore(&chip->reg_lock, flags); } -static void snd_cs4231_playback_format(struct snd_cs4231 *chip, +static void snd_wss_playback_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) { @@ -553,79 +628,88 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); - snd_cs4231_calibrate_mute(chip, 1); - if (chip->hardware == CS4231_HW_CS4231A || - (chip->hardware & CS4231_HW_CS4232_MASK)) { + snd_wss_calibrate_mute(chip, 1); + if (chip->hardware == WSS_HW_CS4231A || + (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */ - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] | 0x10); + chip->image[CS4231_PLAYBK_FORMAT] = pdfr; + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] &= ~0x10); udelay(100); /* Fixes audible clicks at least on GUS MAX */ full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != CS4231_HW_INTERWAVE && !chip->single_dma) { - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, - (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ? - (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) : - pdfr); + if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) { + if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) + pdfr = (pdfr & 0xf0) | + (chip->image[CS4231_REC_FORMAT] & 0x0f); } else { - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); + chip->image[CS4231_PLAYBK_FORMAT] = pdfr; } + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr); spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->hardware == CS4231_HW_OPL3SA2) + if (chip->hardware == WSS_HW_OPL3SA2) udelay(100); /* this seems to help */ - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); } - snd_cs4231_calibrate_mute(chip, 0); + snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } -static void snd_cs4231_capture_format(struct snd_cs4231 *chip, - struct snd_pcm_hw_params *params, - unsigned char cdfr) +static void snd_wss_capture_format(struct snd_wss *chip, + struct snd_pcm_hw_params *params, + unsigned char cdfr) { unsigned long flags; int full_calib = 1; mutex_lock(&chip->mce_mutex); - snd_cs4231_calibrate_mute(chip, 1); - if (chip->hardware == CS4231_HW_CS4231A || - (chip->hardware & CS4231_HW_CS4232_MASK)) { + snd_wss_calibrate_mute(chip, 1); + if (chip->hardware == WSS_HW_CS4231A || + (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */ (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT] = cdfr); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x20); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] | 0x20); + snd_wss_out(chip, CS4231_REC_FORMAT, + chip->image[CS4231_REC_FORMAT] = cdfr); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] &= ~0x20); full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != CS4231_HW_INTERWAVE) { - if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, - ((chip->single_dma ? cdfr : chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) | - (cdfr & 0x0f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); - snd_cs4231_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - } + if (chip->hardware != WSS_HW_INTERWAVE && + !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { + if (chip->single_dma) + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); + else + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, + (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) | + (cdfr & 0x0f)); + spin_unlock_irqrestore(&chip->reg_lock, flags); + snd_wss_mce_down(chip); + snd_wss_mce_up(chip); + spin_lock_irqsave(&chip->reg_lock, flags); } - snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr); + snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); } - snd_cs4231_calibrate_mute(chip, 0); + snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } @@ -633,130 +717,146 @@ static void snd_cs4231_capture_format(struct snd_cs4231 *chip, * Timer interface */ -static unsigned long snd_cs4231_timer_resolution(struct snd_timer * timer) +static unsigned long snd_wss_timer_resolution(struct snd_timer *timer) { - struct snd_cs4231 *chip = snd_timer_chip(timer); - if (chip->hardware & CS4231_HW_CS4236B_MASK) + struct snd_wss *chip = snd_timer_chip(timer); + if (chip->hardware & WSS_HW_CS4236B_MASK) return 14467; else return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920; } -static int snd_cs4231_timer_start(struct snd_timer * timer) +static int snd_wss_timer_start(struct snd_timer *timer) { unsigned long flags; unsigned int ticks; - struct snd_cs4231 *chip = snd_timer_chip(timer); + struct snd_wss *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->reg_lock, flags); ticks = timer->sticks; if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 || (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] || (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) { - snd_cs4231_out(chip, CS4231_TIMER_HIGH, chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8)); - snd_cs4231_out(chip, CS4231_TIMER_LOW, chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); + chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8); + snd_wss_out(chip, CS4231_TIMER_HIGH, + chip->image[CS4231_TIMER_HIGH]); + chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks; + snd_wss_out(chip, CS4231_TIMER_LOW, + chip->image[CS4231_TIMER_LOW]); + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1] | + CS4231_TIMER_ENABLE); } spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } -static int snd_cs4231_timer_stop(struct snd_timer * timer) +static int snd_wss_timer_stop(struct snd_timer *timer) { unsigned long flags; - struct snd_cs4231 *chip = snd_timer_chip(timer); + struct snd_wss *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE); + chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; + snd_wss_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } -static void snd_cs4231_init(struct snd_cs4231 *chip) +static void snd_wss_init(struct snd_wss *chip) { unsigned long flags; - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE snd_printk("init: (1)\n"); #endif - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO | - CS4231_CALIB_MODE); + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | + CS4231_PLAYBACK_PIO | + CS4231_RECORD_ENABLE | + CS4231_RECORD_PIO | + CS4231_CALIB_MODE); chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE snd_printk("init: (2)\n"); #endif - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); + snd_wss_out(chip, + CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); + snd_printk("init: (3) - afei = 0x%x\n", + chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]); + snd_wss_out(chip, CS4231_ALT_FEATURE_2, + chip->image[CS4231_ALT_FEATURE_2]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]); + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE snd_printk("init: (4)\n"); #endif - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); + snd_wss_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE snd_printk("init: (5)\n"); #endif } -static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) +static int snd_wss_open(struct snd_wss *chip, unsigned int mode) { unsigned long flags; mutex_lock(&chip->open_mutex); if ((chip->mode & mode) || - ((chip->mode & CS4231_MODE_OPEN) && chip->single_dma)) { + ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) { mutex_unlock(&chip->open_mutex); return -EAGAIN; } - if (chip->mode & CS4231_MODE_OPEN) { + if (chip->mode & WSS_MODE_OPEN) { chip->mode |= mode; mutex_unlock(&chip->open_mutex); return 0; } /* ok. now enable and ack CODEC IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + snd_wss_out(chip, CS4231_IRQ_STATUS, + CS4231_PLAYBACK_IRQ | + CS4231_RECORD_IRQ | + CS4231_TIMER_IRQ); + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; - snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); + snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); + snd_wss_out(chip, CS4231_IRQ_STATUS, + CS4231_PLAYBACK_IRQ | + CS4231_RECORD_IRQ | + CS4231_TIMER_IRQ); + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = mode; @@ -764,48 +864,49 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) return 0; } -static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) +static void snd_wss_close(struct snd_wss *chip, unsigned int mode) { unsigned long flags; mutex_lock(&chip->open_mutex); chip->mode &= ~mode; - if (chip->mode & CS4231_MODE_OPEN) { + if (chip->mode & WSS_MODE_OPEN) { mutex_unlock(&chip->open_mutex); return; } - snd_cs4231_calibrate_mute(chip, 1); + snd_wss_calibrate_mute(chip, 1); /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; - snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); + snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); /* now disable record & playback */ if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) { spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_wss_out(chip, CS4231_IFACE_CTRL, + chip->image[CS4231_IFACE_CTRL]); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); spin_lock_irqsave(&chip->reg_lock, flags); } /* clear IRQ again */ - snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ + wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_calibrate_mute(chip, 0); + snd_wss_calibrate_mute(chip, 0); chip->mode = 0; mutex_unlock(&chip->open_mutex); @@ -815,59 +916,60 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) * timer open/close */ -static int snd_cs4231_timer_open(struct snd_timer * timer) +static int snd_wss_timer_open(struct snd_timer *timer) { - struct snd_cs4231 *chip = snd_timer_chip(timer); - snd_cs4231_open(chip, CS4231_MODE_TIMER); + struct snd_wss *chip = snd_timer_chip(timer); + snd_wss_open(chip, WSS_MODE_TIMER); return 0; } -static int snd_cs4231_timer_close(struct snd_timer * timer) +static int snd_wss_timer_close(struct snd_timer *timer) { - struct snd_cs4231 *chip = snd_timer_chip(timer); - snd_cs4231_close(chip, CS4231_MODE_TIMER); + struct snd_wss *chip = snd_timer_chip(timer); + snd_wss_close(chip, WSS_MODE_TIMER); return 0; } -static struct snd_timer_hardware snd_cs4231_timer_table = +static struct snd_timer_hardware snd_wss_timer_table = { .flags = SNDRV_TIMER_HW_AUTO, .resolution = 9945, .ticks = 65535, - .open = snd_cs4231_timer_open, - .close = snd_cs4231_timer_close, - .c_resolution = snd_cs4231_timer_resolution, - .start = snd_cs4231_timer_start, - .stop = snd_cs4231_timer_stop, + .open = snd_wss_timer_open, + .close = snd_wss_timer_close, + .c_resolution = snd_wss_timer_resolution, + .start = snd_wss_timer_start, + .stop = snd_wss_timer_stop, }; /* * ok.. exported functions.. */ -static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, +static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); unsigned char new_pdfr; int err; if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) return err; - new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | - snd_cs4231_get_rate(params_rate(hw_params)); + new_pdfr = snd_wss_get_format(chip, params_format(hw_params), + params_channels(hw_params)) | + snd_wss_get_rate(params_rate(hw_params)); chip->set_playback_format(chip, hw_params, new_pdfr); return 0; } -static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream) +static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } -static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) +static int snd_wss_playback_prepare(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); @@ -877,39 +979,40 @@ static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) chip->p_dma_size = size; chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - count = snd_cs4231_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1; - snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); + count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1; + snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); + snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); spin_unlock_irqrestore(&chip->reg_lock, flags); #if 0 - snd_cs4231_debug(chip); + snd_wss_debug(chip); #endif return 0; } -static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, +static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); unsigned char new_cdfr; int err; if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) return err; - new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | - snd_cs4231_get_rate(params_rate(hw_params)); + new_cdfr = snd_wss_get_format(chip, params_format(hw_params), + params_channels(hw_params)) | + snd_wss_get_rate(params_rate(hw_params)); chip->set_capture_format(chip, hw_params, new_cdfr); return 0; } -static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream) +static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } -static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) +static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); @@ -919,49 +1022,52 @@ static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) chip->c_dma_size = size; chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - count = snd_cs4231_get_count(chip->image[CS4231_REC_FORMAT], count) - 1; - if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) { - snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); + count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], count) - 1; + if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { + snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); + snd_wss_out(chip, CS4231_PLY_UPR_CNT, + (unsigned char) (count >> 8)); } else { - snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count); - snd_cs4231_out(chip, CS4231_REC_UPR_CNT, (unsigned char) (count >> 8)); + snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count); + snd_wss_out(chip, CS4231_REC_UPR_CNT, + (unsigned char) (count >> 8)); } spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; } -void snd_cs4231_overrange(struct snd_cs4231 *chip) +void snd_wss_overrange(struct snd_wss *chip) { unsigned long flags; unsigned char res; spin_lock_irqsave(&chip->reg_lock, flags); - res = snd_cs4231_in(chip, CS4231_TEST_INIT); + res = snd_wss_in(chip, CS4231_TEST_INIT); spin_unlock_irqrestore(&chip->reg_lock, flags); if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ chip->capture_substream->runtime->overrange++; } +EXPORT_SYMBOL(snd_wss_overrange); -irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id) +irqreturn_t snd_wss_interrupt(int irq, void *dev_id) { - struct snd_cs4231 *chip = dev_id; + struct snd_wss *chip = dev_id; unsigned char status; - status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); + status = snd_wss_in(chip, CS4231_IRQ_STATUS); if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); } - if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) { + if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { if (status & CS4231_PLAYBACK_IRQ) { - if (chip->mode & CS4231_MODE_PLAY) { + if (chip->mode & WSS_MODE_PLAY) { if (chip->playback_substream) snd_pcm_period_elapsed(chip->playback_substream); } - if (chip->mode & CS4231_MODE_RECORD) { + if (chip->mode & WSS_MODE_RECORD) { if (chip->capture_substream) { - snd_cs4231_overrange(chip); + snd_wss_overrange(chip); snd_pcm_period_elapsed(chip->capture_substream); } } @@ -973,21 +1079,22 @@ irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id) } if (status & CS4231_RECORD_IRQ) { if (chip->capture_substream) { - snd_cs4231_overrange(chip); + snd_wss_overrange(chip); snd_pcm_period_elapsed(chip->capture_substream); } } } spin_lock(&chip->reg_lock); - snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); + snd_wss_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } +EXPORT_SYMBOL(snd_wss_interrupt); -static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); size_t ptr; if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) @@ -996,9 +1103,9 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *s return bytes_to_frames(substream->runtime, ptr); } -static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); size_t ptr; if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) @@ -1011,7 +1118,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *su */ -static int snd_cs4231_probe(struct snd_cs4231 *chip) +static int snd_wss_probe(struct snd_wss *chip) { unsigned long flags; int i, id, rev; @@ -1019,103 +1126,104 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) unsigned int hw; #if 0 - snd_cs4231_debug(chip); + snd_wss_debug(chip); #endif id = 0; for (i = 0; i < 50; i++) { mb(); - if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) udelay(2000); else { spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); - id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f; + snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); + id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; spin_unlock_irqrestore(&chip->reg_lock, flags); if (id == 0x0a) break; /* this is valid value */ } } - snd_printdd("cs4231: port = 0x%lx, id = 0x%x\n", chip->port, id); + snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); if (id != 0x0a) return -ENODEV; /* no valid device found */ - if (((hw = chip->hardware) & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) { - rev = snd_cs4231_in(chip, CS4231_VERSION) & 0xe7; + hw = chip->hardware; + if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { + rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); if (rev == 0x80) { - unsigned char tmp = snd_cs4231_in(chip, 23); - snd_cs4231_out(chip, 23, ~tmp); - if (snd_cs4231_in(chip, 23) != tmp) - chip->hardware = CS4231_HW_AD1845; + unsigned char tmp = snd_wss_in(chip, 23); + snd_wss_out(chip, 23, ~tmp); + if (snd_wss_in(chip, 23) != tmp) + chip->hardware = WSS_HW_AD1845; else - chip->hardware = CS4231_HW_CS4231; + chip->hardware = WSS_HW_CS4231; } else if (rev == 0xa0) { - chip->hardware = CS4231_HW_CS4231A; + chip->hardware = WSS_HW_CS4231A; } else if (rev == 0xa2) { - chip->hardware = CS4231_HW_CS4232; + chip->hardware = WSS_HW_CS4232; } else if (rev == 0xb2) { - chip->hardware = CS4231_HW_CS4232A; + chip->hardware = WSS_HW_CS4232A; } else if (rev == 0x83) { - chip->hardware = CS4231_HW_CS4236; + chip->hardware = WSS_HW_CS4236; } else if (rev == 0x03) { - chip->hardware = CS4231_HW_CS4236B; + chip->hardware = WSS_HW_CS4236B; } else { snd_printk("unknown CS chip with version 0x%x\n", rev); return -ENODEV; /* unknown CS4231 chip? */ } } spin_lock_irqsave(&chip->reg_lock, flags); - cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ - cs4231_outb(chip, CS4231P(STATUS), 0); + wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ + wss_outb(chip, CS4231P(STATUS), 0); mb(); spin_unlock_irqrestore(&chip->reg_lock, flags); chip->image[CS4231_MISC_INFO] = CS4231_MODE2; switch (chip->hardware) { - case CS4231_HW_INTERWAVE: + case WSS_HW_INTERWAVE: chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; break; - case CS4231_HW_CS4235: - case CS4231_HW_CS4236B: - case CS4231_HW_CS4237B: - case CS4231_HW_CS4238B: - case CS4231_HW_CS4239: - if (hw == CS4231_HW_DETECT3) + case WSS_HW_CS4235: + case WSS_HW_CS4236B: + case WSS_HW_CS4237B: + case WSS_HW_CS4238B: + case WSS_HW_CS4239: + if (hw == WSS_HW_DETECT3) chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3; else - chip->hardware = CS4231_HW_CS4236; + chip->hardware = WSS_HW_CS4236; break; } chip->image[CS4231_IFACE_CTRL] = (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) | (chip->single_dma ? CS4231_SINGLE_DMA : 0); - if (chip->hardware != CS4231_HW_OPTI93X) { + if (chip->hardware != WSS_HW_OPTI93X) { chip->image[CS4231_ALT_FEATURE_1] = 0x80; chip->image[CS4231_ALT_FEATURE_2] = - chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01; + chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; } ptr = (unsigned char *) &chip->image; - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); spin_lock_irqsave(&chip->reg_lock, flags); for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ - snd_cs4231_out(chip, i, *ptr++); + snd_wss_out(chip, i, *ptr++); spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_cs4231_mce_up(chip); - snd_cs4231_mce_down(chip); + snd_wss_mce_up(chip); + snd_wss_mce_down(chip); mdelay(2); /* ok.. try check hardware version for CS4236+ chips */ - if ((hw & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) { - if (chip->hardware == CS4231_HW_CS4236B) { + if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { + if (chip->hardware == WSS_HW_CS4236B) { rev = snd_cs4236_ext_in(chip, CS4236_VERSION); snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff); id = snd_cs4236_ext_in(chip, CS4236_VERSION); snd_cs4236_ext_out(chip, CS4236_VERSION, rev); snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id); if ((id & 0x1f) == 0x1d) { /* CS4235 */ - chip->hardware = CS4231_HW_CS4235; + chip->hardware = WSS_HW_CS4235; switch (id >> 5) { case 4: case 5: @@ -1130,13 +1238,13 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) case 5: case 6: case 7: - chip->hardware = CS4231_HW_CS4236B; + chip->hardware = WSS_HW_CS4236B; break; default: snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id); } } else if ((id & 0x1f) == 0x08) { /* CS4237B */ - chip->hardware = CS4231_HW_CS4237B; + chip->hardware = WSS_HW_CS4237B; switch (id >> 5) { case 4: case 5: @@ -1147,7 +1255,7 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id); } } else if ((id & 0x1f) == 0x09) { /* CS4238B */ - chip->hardware = CS4231_HW_CS4238B; + chip->hardware = WSS_HW_CS4238B; switch (id >> 5) { case 5: case 6: @@ -1157,7 +1265,7 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id); } } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ - chip->hardware = CS4231_HW_CS4239; + chip->hardware = WSS_HW_CS4239; switch (id >> 5) { case 4: case 5: @@ -1178,7 +1286,7 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) */ -static struct snd_pcm_hardware snd_cs4231_playback = +static struct snd_pcm_hardware snd_wss_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID | @@ -1199,7 +1307,7 @@ static struct snd_pcm_hardware snd_cs4231_playback = .fifo_size = 0, }; -static struct snd_pcm_hardware snd_cs4231_capture = +static struct snd_pcm_hardware snd_wss_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID | @@ -1224,21 +1332,21 @@ static struct snd_pcm_hardware snd_cs4231_capture = */ -static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) +static int snd_wss_playback_open(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err; - runtime->hw = snd_cs4231_playback; + runtime->hw = snd_wss_playback; /* hardware bug in InterWave chipset */ - if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3) + if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; /* hardware limitation of cheap chips */ - if (chip->hardware == CS4231_HW_CS4235 || - chip->hardware == CS4231_HW_CS4239) + if (chip->hardware == WSS_HW_CS4235 || + chip->hardware == WSS_HW_CS4239) runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE; snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); @@ -1249,7 +1357,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) return err; } - if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) { + err = snd_wss_open(chip, WSS_MODE_PLAY); + if (err < 0) { if (chip->release_dma) chip->release_dma(chip, chip->dma_private_data, chip->dma1); snd_free_pages(runtime->dma_area, runtime->dma_bytes); @@ -1261,17 +1370,17 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) return 0; } -static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) +static int snd_wss_capture_open(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err; - runtime->hw = snd_cs4231_capture; + runtime->hw = snd_wss_capture; /* hardware limitation of cheap chips */ - if (chip->hardware == CS4231_HW_CS4235 || - chip->hardware == CS4231_HW_CS4239) + if (chip->hardware == WSS_HW_CS4235 || + chip->hardware == WSS_HW_CS4239) runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE; snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); @@ -1282,7 +1391,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) return err; } - if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) { + err = snd_wss_open(chip, WSS_MODE_RECORD); + if (err < 0) { if (chip->release_dma) chip->release_dma(chip, chip->dma_private_data, chip->dma2); snd_free_pages(runtime->dma_area, runtime->dma_bytes); @@ -1294,28 +1404,28 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) return 0; } -static int snd_cs4231_playback_close(struct snd_pcm_substream *substream) +static int snd_wss_playback_close(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); chip->playback_substream = NULL; - snd_cs4231_close(chip, CS4231_MODE_PLAY); + snd_wss_close(chip, WSS_MODE_PLAY); return 0; } -static int snd_cs4231_capture_close(struct snd_pcm_substream *substream) +static int snd_wss_capture_close(struct snd_pcm_substream *substream) { - struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); chip->capture_substream = NULL; - snd_cs4231_close(chip, CS4231_MODE_RECORD); + snd_wss_close(chip, WSS_MODE_RECORD); return 0; } #ifdef CONFIG_PM /* lowlevel suspend callback for CS4231 */ -static void snd_cs4231_suspend(struct snd_cs4231 *chip) +static void snd_wss_suspend(struct snd_wss *chip) { int reg; unsigned long flags; @@ -1323,67 +1433,68 @@ static void snd_cs4231_suspend(struct snd_cs4231 *chip) snd_pcm_suspend_all(chip->pcm); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_cs4231_in(chip, reg); + chip->image[reg] = snd_wss_in(chip, reg); spin_unlock_irqrestore(&chip->reg_lock, flags); } /* lowlevel resume callback for CS4231 */ -static void snd_cs4231_resume(struct snd_cs4231 *chip) +static void snd_wss_resume(struct snd_wss *chip) { int reg; unsigned long flags; /* int timeout; */ - snd_cs4231_mce_up(chip); + snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) { switch (reg) { case CS4231_VERSION: break; default: - snd_cs4231_out(chip, reg, chip->image[reg]); + snd_wss_out(chip, reg, chip->image[reg]); break; } } spin_unlock_irqrestore(&chip->reg_lock, flags); #if 1 - snd_cs4231_mce_down(chip); + snd_wss_mce_down(chip); #else /* The following is a workaround to avoid freeze after resume on TP600E. - This is the first half of copy of snd_cs4231_mce_down(), but doesn't + This is the first half of copy of snd_wss_mce_down(), but doesn't include rescheduling. -- iwai */ - snd_cs4231_busy_wait(chip); + snd_wss_busy_wait(chip); spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit &= ~CS4231_MCE; - timeout = cs4231_inb(chip, CS4231P(REGSEL)); - cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); + timeout = wss_inb(chip, CS4231P(REGSEL)); + wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port); if ((timeout & CS4231_MCE) == 0 || - !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) { + !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { return; } - snd_cs4231_busy_wait(chip); + snd_wss_busy_wait(chip); #endif } #endif /* CONFIG_PM */ -static int snd_cs4231_free(struct snd_cs4231 *chip) +static int snd_wss_free(struct snd_wss *chip) { release_and_free_resource(chip->res_port); release_and_free_resource(chip->res_cport); if (chip->irq >= 0) { disable_irq(chip->irq); - if (!(chip->hwshare & CS4231_HWSHARE_IRQ)) + if (!(chip->hwshare & WSS_HWSHARE_IRQ)) free_irq(chip->irq, (void *) chip); } - if (!(chip->hwshare & CS4231_HWSHARE_DMA1) && chip->dma1 >= 0) { + if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) { snd_dma_disable(chip->dma1); free_dma(chip->dma1); } - if (!(chip->hwshare & CS4231_HWSHARE_DMA2) && chip->dma2 >= 0 && chip->dma2 != chip->dma1) { + if (!(chip->hwshare & WSS_HWSHARE_DMA2) && + chip->dma2 >= 0 && chip->dma2 != chip->dma1) { snd_dma_disable(chip->dma2); free_dma(chip->dma2); } @@ -1393,39 +1504,55 @@ static int snd_cs4231_free(struct snd_cs4231 *chip) return 0; } -static int snd_cs4231_dev_free(struct snd_device *device) +static int snd_wss_dev_free(struct snd_device *device) { - struct snd_cs4231 *chip = device->device_data; - return snd_cs4231_free(chip); + struct snd_wss *chip = device->device_data; + return snd_wss_free(chip); } -const char *snd_cs4231_chip_id(struct snd_cs4231 *chip) +const char *snd_wss_chip_id(struct snd_wss *chip) { switch (chip->hardware) { - case CS4231_HW_CS4231: return "CS4231"; - case CS4231_HW_CS4231A: return "CS4231A"; - case CS4231_HW_CS4232: return "CS4232"; - case CS4231_HW_CS4232A: return "CS4232A"; - case CS4231_HW_CS4235: return "CS4235"; - case CS4231_HW_CS4236: return "CS4236"; - case CS4231_HW_CS4236B: return "CS4236B"; - case CS4231_HW_CS4237B: return "CS4237B"; - case CS4231_HW_CS4238B: return "CS4238B"; - case CS4231_HW_CS4239: return "CS4239"; - case CS4231_HW_INTERWAVE: return "AMD InterWave"; - case CS4231_HW_OPL3SA2: return chip->card->shortname; - case CS4231_HW_AD1845: return "AD1845"; - case CS4231_HW_OPTI93X: return "OPTi 93x"; - default: return "???"; + case WSS_HW_CS4231: + return "CS4231"; + case WSS_HW_CS4231A: + return "CS4231A"; + case WSS_HW_CS4232: + return "CS4232"; + case WSS_HW_CS4232A: + return "CS4232A"; + case WSS_HW_CS4235: + return "CS4235"; + case WSS_HW_CS4236: + return "CS4236"; + case WSS_HW_CS4236B: + return "CS4236B"; + case WSS_HW_CS4237B: + return "CS4237B"; + case WSS_HW_CS4238B: + return "CS4238B"; + case WSS_HW_CS4239: + return "CS4239"; + case WSS_HW_INTERWAVE: + return "AMD InterWave"; + case WSS_HW_OPL3SA2: + return chip->card->shortname; + case WSS_HW_AD1845: + return "AD1845"; + case WSS_HW_OPTI93X: + return "OPTi 93x"; + default: + return "???"; } } +EXPORT_SYMBOL(snd_wss_chip_id); -static int snd_cs4231_new(struct snd_card *card, +static int snd_wss_new(struct snd_card *card, unsigned short hardware, unsigned short hwshare, - struct snd_cs4231 ** rchip) + struct snd_wss **rchip) { - struct snd_cs4231 *chip; + struct snd_wss *chip; *rchip = NULL; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1438,35 +1565,35 @@ static int snd_cs4231_new(struct snd_card *card, mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); chip->card = card; - chip->rate_constraint = snd_cs4231_xrate; - chip->set_playback_format = snd_cs4231_playback_format; - chip->set_capture_format = snd_cs4231_capture_format; - if (chip->hardware == CS4231_HW_OPTI93X) + chip->rate_constraint = snd_wss_xrate; + chip->set_playback_format = snd_wss_playback_format; + chip->set_capture_format = snd_wss_capture_format; + if (chip->hardware == WSS_HW_OPTI93X) memcpy(&chip->image, &snd_opti93x_original_image, sizeof(snd_opti93x_original_image)); else - memcpy(&chip->image, &snd_cs4231_original_image, - sizeof(snd_cs4231_original_image)); + memcpy(&chip->image, &snd_wss_original_image, + sizeof(snd_wss_original_image)); - *rchip = chip; - return 0; + *rchip = chip; + return 0; } -int snd_cs4231_create(struct snd_card *card, - unsigned long port, - unsigned long cport, +int snd_wss_create(struct snd_card *card, + unsigned long port, + unsigned long cport, int irq, int dma1, int dma2, unsigned short hardware, unsigned short hwshare, - struct snd_cs4231 ** rchip) + struct snd_wss **rchip) { static struct snd_device_ops ops = { - .dev_free = snd_cs4231_dev_free, + .dev_free = snd_wss_dev_free, }; - struct snd_cs4231 *chip; + struct snd_wss *chip; int err; - err = snd_cs4231_new(card, hardware, hwshare, &chip); + err = snd_wss_new(card, hardware, hwshare, &chip); if (err < 0) return err; @@ -1474,33 +1601,41 @@ int snd_cs4231_create(struct snd_card *card, chip->dma1 = -1; chip->dma2 = -1; - if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) { - snd_printk(KERN_ERR "cs4231: can't grab port 0x%lx\n", port); - snd_cs4231_free(chip); + chip->res_port = request_region(port, 4, "CS4231"); + if (!chip->res_port) { + snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); + snd_wss_free(chip); return -EBUSY; } chip->port = port; - if ((long)cport >= 0 && (chip->res_cport = request_region(cport, 8, "CS4232 Control")) == NULL) { - snd_printk(KERN_ERR "cs4231: can't grab control port 0x%lx\n", cport); - snd_cs4231_free(chip); - return -ENODEV; + if ((long)cport >= 0) { + chip->res_cport = request_region(cport, 8, "CS4232 Control"); + if (!chip->res_cport) { + snd_printk(KERN_ERR + "wss: can't grab control port 0x%lx\n", cport); + snd_wss_free(chip); + return -ENODEV; + } } chip->cport = cport; - if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, IRQF_DISABLED, "CS4231", (void *) chip)) { - snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq); - snd_cs4231_free(chip); - return -EBUSY; - } + if (!(hwshare & WSS_HWSHARE_IRQ)) + if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, + "CS4231", (void *) chip)) { + snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); + snd_wss_free(chip); + return -EBUSY; + } chip->irq = irq; - if (!(hwshare & CS4231_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) { - snd_printk(KERN_ERR "cs4231: can't grab DMA1 %d\n", dma1); - snd_cs4231_free(chip); + if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) { + snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); + snd_wss_free(chip); return -EBUSY; } chip->dma1 = dma1; - if (!(hwshare & CS4231_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) { - snd_printk(KERN_ERR "cs4231: can't grab DMA2 %d\n", dma2); - snd_cs4231_free(chip); + if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && + dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) { + snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); + snd_wss_free(chip); return -EBUSY; } if (dma1 == dma2 || dma2 < 0) { @@ -1510,58 +1645,60 @@ int snd_cs4231_create(struct snd_card *card, chip->dma2 = dma2; /* global setup */ - if (snd_cs4231_probe(chip) < 0) { - snd_cs4231_free(chip); + if (snd_wss_probe(chip) < 0) { + snd_wss_free(chip); return -ENODEV; } - snd_cs4231_init(chip); + snd_wss_init(chip); #if 0 - if (chip->hardware & CS4231_HW_CS4232_MASK) { + if (chip->hardware & WSS_HW_CS4232_MASK) { if (chip->res_cport == NULL) snd_printk("CS4232 control port features are not accessible\n"); } #endif /* Register device */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_cs4231_free(chip); + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { + snd_wss_free(chip); return err; } #ifdef CONFIG_PM /* Power Management */ - chip->suspend = snd_cs4231_suspend; - chip->resume = snd_cs4231_resume; + chip->suspend = snd_wss_suspend; + chip->resume = snd_wss_resume; #endif *rchip = chip; return 0; } +EXPORT_SYMBOL(snd_wss_create); -static struct snd_pcm_ops snd_cs4231_playback_ops = { - .open = snd_cs4231_playback_open, - .close = snd_cs4231_playback_close, +static struct snd_pcm_ops snd_wss_playback_ops = { + .open = snd_wss_playback_open, + .close = snd_wss_playback_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4231_playback_hw_params, - .hw_free = snd_cs4231_playback_hw_free, - .prepare = snd_cs4231_playback_prepare, - .trigger = snd_cs4231_trigger, - .pointer = snd_cs4231_playback_pointer, + .hw_params = snd_wss_playback_hw_params, + .hw_free = snd_wss_playback_hw_free, + .prepare = snd_wss_playback_prepare, + .trigger = snd_wss_trigger, + .pointer = snd_wss_playback_pointer, }; -static struct snd_pcm_ops snd_cs4231_capture_ops = { - .open = snd_cs4231_capture_open, - .close = snd_cs4231_capture_close, +static struct snd_pcm_ops snd_wss_capture_ops = { + .open = snd_wss_capture_open, + .close = snd_wss_capture_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4231_capture_hw_params, - .hw_free = snd_cs4231_capture_hw_free, - .prepare = snd_cs4231_capture_prepare, - .trigger = snd_cs4231_trigger, - .pointer = snd_cs4231_capture_pointer, + .hw_params = snd_wss_capture_hw_params, + .hw_free = snd_wss_capture_hw_free, + .prepare = snd_wss_capture_prepare, + .trigger = snd_wss_trigger, + .pointer = snd_wss_capture_pointer, }; -int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) +int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -1573,17 +1710,17 @@ int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); /* global setup */ pcm->private_data = chip; pcm->info_flags = 0; if (chip->single_dma) pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - if (chip->hardware != CS4231_HW_INTERWAVE) + if (chip->hardware != WSS_HW_INTERWAVE) pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX; - strcpy(pcm->name, snd_cs4231_chip_id(chip)); + strcpy(pcm->name, snd_wss_chip_id(chip)); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(), @@ -1594,14 +1731,15 @@ int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) *rpcm = pcm; return 0; } +EXPORT_SYMBOL(snd_wss_pcm); -static void snd_cs4231_timer_free(struct snd_timer *timer) +static void snd_wss_timer_free(struct snd_timer *timer) { - struct snd_cs4231 *chip = timer->private_data; + struct snd_wss *chip = timer->private_data; chip->timer = NULL; } -int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rtimer) +int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer) { struct snd_timer *timer; struct snd_timer_id tid; @@ -1615,21 +1753,23 @@ int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rti tid.subdevice = 0; if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) return err; - strcpy(timer->name, snd_cs4231_chip_id(chip)); + strcpy(timer->name, snd_wss_chip_id(chip)); timer->private_data = chip; - timer->private_free = snd_cs4231_timer_free; - timer->hw = snd_cs4231_timer_table; + timer->private_free = snd_wss_timer_free; + timer->hw = snd_wss_timer_table; chip->timer = timer; if (rtimer) *rtimer = timer; return 0; } +EXPORT_SYMBOL(snd_wss_timer); /* * MIXER part */ -static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_wss_info_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { static char *texts[4] = { "Line", "Aux", "Mic", "Mix" @@ -1641,7 +1781,7 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele "Line", "Synth", "Mic", "Mix" }; char **ptexts = texts; - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); snd_assert(chip->card != NULL, return -EINVAL); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -1652,16 +1792,21 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele if (!strcmp(chip->card->driver, "GUS MAX")) ptexts = gusmax_texts; switch (chip->hardware) { - case CS4231_HW_INTERWAVE: ptexts = gusmax_texts; break; - case CS4231_HW_OPL3SA2: ptexts = opl3sa_texts; break; + case WSS_HW_INTERWAVE: + ptexts = gusmax_texts; + break; + case WSS_HW_OPL3SA2: + ptexts = opl3sa_texts; + break; } strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]); return 0; } -static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_wss_get_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -1671,9 +1816,10 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem return 0; } -static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_wss_put_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; unsigned short left, right; int change; @@ -1687,14 +1833,15 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; change = left != chip->image[CS4231_LEFT_INPUT] || - right != chip->image[CS4231_RIGHT_INPUT]; - snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); - snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); + right != chip->image[CS4231_RIGHT_INPUT]; + snd_wss_out(chip, CS4231_LEFT_INPUT, left); + snd_wss_out(chip, CS4231_RIGHT_INPUT, right); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } -int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +int snd_wss_info_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; @@ -1704,10 +1851,12 @@ int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_in uinfo->value.integer.max = mask; return 0; } +EXPORT_SYMBOL(snd_wss_info_single); -int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_wss_get_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -1721,10 +1870,12 @@ int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; } +EXPORT_SYMBOL(snd_wss_get_single); -int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_wss_put_single(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -1740,12 +1891,14 @@ int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val spin_lock_irqsave(&chip->reg_lock, flags); val = (chip->image[reg] & ~(mask << shift)) | val; change = val != chip->image[reg]; - snd_cs4231_out(chip, reg, val); + snd_wss_out(chip, reg, val); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } +EXPORT_SYMBOL(snd_wss_put_single); -int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +int snd_wss_info_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { int mask = (kcontrol->private_value >> 24) & 0xff; @@ -1755,10 +1908,12 @@ int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_in uinfo->value.integer.max = mask; return 0; } +EXPORT_SYMBOL(snd_wss_info_double); -int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_wss_get_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -1777,10 +1932,12 @@ int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val } return 0; } +EXPORT_SYMBOL(snd_wss_get_double); -int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_wss_put_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -1803,81 +1960,98 @@ int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; - snd_cs4231_out(chip, left_reg, val1); - snd_cs4231_out(chip, right_reg, val2); + snd_wss_out(chip, left_reg, val1); + snd_wss_out(chip, right_reg, val2); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } - -static struct snd_kcontrol_new snd_cs4231_controls[] = { -CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), -CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), -CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), -CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), -CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), -CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +EXPORT_SYMBOL(snd_wss_put_double); + +static struct snd_kcontrol_new snd_wss_controls[] = { +WSS_DOUBLE("PCM Playback Switch", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), +WSS_DOUBLE("Line Playback Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +WSS_DOUBLE("Line Playback Volume", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), +WSS_DOUBLE("Aux Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Playback Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), +WSS_DOUBLE("Aux Playback Switch", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Playback Volume", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), +WSS_SINGLE("Mono Playback Switch", 0, + CS4231_MONO_CTRL, 7, 1, 1), +WSS_SINGLE("Mono Playback Volume", 0, + CS4231_MONO_CTRL, 0, 15, 1), +WSS_SINGLE("Mono Output Playback Switch", 0, + CS4231_MONO_CTRL, 6, 1, 1), +WSS_SINGLE("Mono Output Playback Bypass", 0, + CS4231_MONO_CTRL, 5, 1, 0), +WSS_DOUBLE("Capture Volume", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", - .info = snd_cs4231_info_mux, - .get = snd_cs4231_get_mux, - .put = snd_cs4231_put_mux, + .info = snd_wss_info_mux, + .get = snd_wss_get_mux, + .put = snd_wss_put_mux, }, -CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), -CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), -CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1) +WSS_DOUBLE("Mic Boost", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), +WSS_SINGLE("Loopback Capture Switch", 0, + CS4231_LOOPBACK, 0, 1, 0), +WSS_SINGLE("Loopback Capture Volume", 0, + CS4231_LOOPBACK, 2, 63, 1) }; static struct snd_kcontrol_new snd_opti93x_controls[] = { -CS4231_DOUBLE("Master Playback Switch", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), -CS4231_DOUBLE("Master Playback Volume", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), -CS4231_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1), -CS4231_DOUBLE("FM Playback Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("FM Playback Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1), -CS4231_DOUBLE("Line Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Line Playback Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1), -CS4231_DOUBLE("Mic Playback Switch", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Mic Playback Volume", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), -CS4231_DOUBLE("Mic Boost", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), -CS4231_DOUBLE("CD Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("CD Playback Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1), -CS4231_DOUBLE("Aux Playback Switch", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), -CS4231_DOUBLE("Capture Volume", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +WSS_DOUBLE("Master Playback Switch", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), +WSS_DOUBLE("Master Playback Volume", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), +WSS_DOUBLE("PCM Playback Switch", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1), +WSS_DOUBLE("FM Playback Switch", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("FM Playback Volume", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1), +WSS_DOUBLE("Line Playback Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +WSS_DOUBLE("Line Playback Volume", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1), +WSS_DOUBLE("Mic Playback Switch", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Mic Playback Volume", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), +WSS_DOUBLE("Mic Boost", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), +WSS_DOUBLE("CD Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("CD Playback Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1), +WSS_DOUBLE("Aux Playback Switch", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Playback Volume", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), +WSS_DOUBLE("Capture Volume", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", - .info = snd_cs4231_info_mux, - .get = snd_cs4231_get_mux, - .put = snd_cs4231_put_mux, + .info = snd_wss_info_mux, + .get = snd_wss_get_mux, + .put = snd_wss_put_mux, } }; -int snd_cs4231_mixer(struct snd_cs4231 *chip) +int snd_wss_mixer(struct snd_wss *chip) { struct snd_card *card; unsigned int idx; @@ -1889,7 +2063,7 @@ int snd_cs4231_mixer(struct snd_cs4231 *chip) strcpy(card->mixername, chip->pcm->name); - if (chip->hardware == CS4231_HW_OPTI93X) + if (chip->hardware == WSS_HW_OPTI93X) for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) { err = snd_ctl_add(card, snd_ctl_new1(&snd_opti93x_controls[idx], @@ -1898,48 +2072,29 @@ int snd_cs4231_mixer(struct snd_cs4231 *chip) return err; } else - for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { + for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) { err = snd_ctl_add(card, - snd_ctl_new1(&snd_cs4231_controls[idx], + snd_ctl_new1(&snd_wss_controls[idx], chip)); if (err < 0) return err; } return 0; } - -EXPORT_SYMBOL(snd_cs4231_out); -EXPORT_SYMBOL(snd_cs4231_in); -EXPORT_SYMBOL(snd_cs4236_ext_out); -EXPORT_SYMBOL(snd_cs4236_ext_in); -EXPORT_SYMBOL(snd_cs4231_mce_up); -EXPORT_SYMBOL(snd_cs4231_mce_down); -EXPORT_SYMBOL(snd_cs4231_overrange); -EXPORT_SYMBOL(snd_cs4231_interrupt); -EXPORT_SYMBOL(snd_cs4231_chip_id); -EXPORT_SYMBOL(snd_cs4231_create); -EXPORT_SYMBOL(snd_cs4231_pcm); -EXPORT_SYMBOL(snd_cs4231_mixer); -EXPORT_SYMBOL(snd_cs4231_timer); -EXPORT_SYMBOL(snd_cs4231_info_single); -EXPORT_SYMBOL(snd_cs4231_get_single); -EXPORT_SYMBOL(snd_cs4231_put_single); -EXPORT_SYMBOL(snd_cs4231_info_double); -EXPORT_SYMBOL(snd_cs4231_get_double); -EXPORT_SYMBOL(snd_cs4231_put_double); +EXPORT_SYMBOL(snd_wss_mixer); /* * INIT part */ -static int __init alsa_cs4231_init(void) +static int __init alsa_wss_init(void) { return 0; } -static void __exit alsa_cs4231_exit(void) +static void __exit alsa_wss_exit(void) { } -module_init(alsa_cs4231_init) -module_exit(alsa_cs4231_exit) +module_init(alsa_wss_init); +module_exit(alsa_wss_exit); -- GitLab From 241b3ee70d2d69e88d5c144ce938b1887cd6d3fc Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:04:37 +0200 Subject: [PATCH 0247/5416] ALSA: wss_lib: use struct snd_wss instead of snd_ad1848 The snd_wss is superset of the snd_ad1848 so kill the latter and replace it with the snd_wss. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 43 ++-------- include/sound/wss.h | 6 +- sound/isa/ad1848/ad1848.c | 6 +- sound/isa/ad1848/ad1848_lib.c | 128 +++++++++++++++-------------- sound/isa/cmi8330.c | 2 +- sound/isa/opti9xx/opti92x-ad1848.c | 4 - sound/isa/sc6000.c | 4 +- sound/isa/sgalaxy.c | 8 +- 8 files changed, 91 insertions(+), 110 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index d9aebdf6db6..d740e633e81 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -25,6 +25,8 @@ #include "pcm.h" #include +#include "wss.h" /* temporary till the driver is removed */ + /* IO ports */ #define AD1848P( chip, x ) ( (chip) -> port + c_d_c_AD1848##x ) @@ -127,48 +129,20 @@ #define AD1848_THINKPAD_CTL_PORT2 0x15e9 #define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02 -struct snd_ad1848 { - unsigned long port; /* i/o port */ - struct resource *res_port; - int irq; /* IRQ line */ - int dma; /* data DMA */ - unsigned short version; /* version of CODEC chip */ - unsigned short mode; /* see to AD1848_MODE_XXXX */ - unsigned short hardware; /* see to AD1848_HW_XXXX */ - unsigned short single_dma:1; /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */ - - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - struct snd_card *card; - - unsigned char image[32]; /* SGalaxy needs an access to extended registers */ - int mce_bit; - int calibrate_mute; - int dma_size; - int thinkpad_flag; /* Thinkpad CS4248 needs some extra help */ - -#ifdef CONFIG_PM - void (*suspend)(struct snd_ad1848 *chip); - void (*resume)(struct snd_ad1848 *chip); -#endif - - spinlock_t reg_lock; -}; - /* exported functions */ -void snd_ad1848_out(struct snd_ad1848 *chip, unsigned char reg, unsigned char value); +void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, + unsigned char value); int snd_ad1848_create(struct snd_card *card, unsigned long port, int irq, int dma, unsigned short hardware, - struct snd_ad1848 ** chip); + struct snd_wss **chip); -int snd_ad1848_pcm(struct snd_ad1848 * chip, int device, struct snd_pcm **rpcm); +int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction); -int snd_ad1848_mixer(struct snd_ad1848 * chip); +int snd_ad1848_mixer(struct snd_wss *chip); /* exported mixer stuffs */ enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE }; @@ -213,6 +187,7 @@ struct ad1848_mix_elem { .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ .tlv = xtlv } -int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c); +int snd_ad1848_add_ctl_elem(struct snd_wss *chip, + const struct ad1848_mix_elem *c); #endif /* __SOUND_AD1848_H */ diff --git a/include/sound/wss.h b/include/sound/wss.h index 3b53973f96a..1e0dc77f0d2 100644 --- a/include/sound/wss.h +++ b/include/sound/wss.h @@ -77,8 +77,10 @@ struct snd_wss { unsigned short mode; /* see to WSS_MODE_XXXX */ unsigned short hardware; /* see to WSS_HW_XXXX */ unsigned short hwshare; /* shared resources */ - unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */ - ebus_flag:1; /* SPARC: EBUS present */ + unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit */ + /* daughter board) or dma1 == dma2 */ + ebus_flag:1, /* SPARC: EBUS present */ + thinkpad_flag:1; /* Thinkpad CS4248 needs extra help */ struct snd_card *card; struct snd_pcm *pcm; diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 5f5271efdc5..74db24ae650 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -87,7 +87,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n) static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) { struct snd_card *card; - struct snd_ad1848 *chip; + struct snd_wss *chip; struct snd_pcm *pcm; int error; @@ -142,7 +142,7 @@ static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n) static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) { struct snd_card *card = dev_get_drvdata(dev); - struct snd_ad1848 *chip = card->private_data; + struct snd_wss *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); chip->suspend(chip); @@ -152,7 +152,7 @@ static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t s static int snd_ad1848_resume(struct device *dev, unsigned int n) { struct snd_card *card = dev_get_drvdata(dev); - struct snd_ad1848 *chip = card->private_data; + struct snd_wss *chip = card->private_data; chip->resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 630c90f9ee5..e25fadffdb5 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -98,7 +98,7 @@ static unsigned char snd_ad1848_original_image[16] = * Basic I/O functions */ -static void snd_ad1848_wait(struct snd_ad1848 *chip) +static void snd_ad1848_wait(struct snd_wss *chip) { int timeout; @@ -109,7 +109,7 @@ static void snd_ad1848_wait(struct snd_ad1848 *chip) } } -void snd_ad1848_out(struct snd_ad1848 *chip, +void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, unsigned char value) { @@ -128,7 +128,7 @@ void snd_ad1848_out(struct snd_ad1848 *chip, EXPORT_SYMBOL(snd_ad1848_out); -static void snd_ad1848_dout(struct snd_ad1848 *chip, +static void snd_ad1848_dout(struct snd_wss *chip, unsigned char reg, unsigned char value) { snd_ad1848_wait(chip); @@ -137,7 +137,7 @@ static void snd_ad1848_dout(struct snd_ad1848 *chip, mb(); } -static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) +static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) { snd_ad1848_wait(chip); #ifdef CONFIG_SND_DEBUG @@ -152,7 +152,7 @@ static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) #if 0 -static void snd_ad1848_debug(struct snd_ad1848 *chip) +static void snd_ad1848_debug(struct snd_wss *chip) { printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL))); printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS))); @@ -180,7 +180,7 @@ static void snd_ad1848_debug(struct snd_ad1848 *chip) * AD1848 detection / MCE routines */ -static void snd_ad1848_mce_up(struct snd_ad1848 *chip) +static void snd_ad1848_mce_up(struct snd_wss *chip) { unsigned long flags; int timeout; @@ -200,7 +200,7 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); } -static void snd_ad1848_mce_down(struct snd_ad1848 *chip) +static void snd_ad1848_mce_down(struct snd_wss *chip) { unsigned long flags, timeout; int reg; @@ -268,7 +268,7 @@ static unsigned int snd_ad1848_get_count(unsigned char format, return size; } -static int snd_ad1848_trigger(struct snd_ad1848 *chip, unsigned char what, +static int snd_ad1848_trigger(struct snd_wss *chip, unsigned char what, int channel, int cmd) { int result = 0; @@ -337,7 +337,7 @@ static unsigned char snd_ad1848_get_format(int format, int channels) return rformat; } -static void snd_ad1848_calibrate_mute(struct snd_ad1848 *chip, int mute) +static void snd_ad1848_calibrate_mute(struct snd_wss *chip, int mute) { unsigned long flags; @@ -361,7 +361,8 @@ static void snd_ad1848_calibrate_mute(struct snd_ad1848 *chip, int mute) spin_unlock_irqrestore(&chip->reg_lock, flags); } -static void snd_ad1848_set_data_format(struct snd_ad1848 *chip, struct snd_pcm_hw_params *hw_params) +static void snd_ad1848_set_data_format(struct snd_wss *chip, + struct snd_pcm_hw_params *hw_params) { if (hw_params == NULL) { chip->image[AD1848_DATA_FORMAT] = 0x20; @@ -373,7 +374,7 @@ static void snd_ad1848_set_data_format(struct snd_ad1848 *chip, struct snd_pcm_h // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]); } -static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) +static int snd_ad1848_open(struct snd_wss *chip, unsigned int mode) { unsigned long flags; @@ -424,7 +425,7 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) return 0; } -static void snd_ad1848_close(struct snd_ad1848 *chip) +static void snd_ad1848_close(struct snd_wss *chip) { unsigned long flags; @@ -464,21 +465,21 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd); } static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd); } static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); unsigned long flags; int err; @@ -502,15 +503,16 @@ static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream) static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); - chip->dma_size = size; + chip->p_dma_size = size; chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO); - snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); + snd_dma_program(chip->dma1, runtime->dma_addr, size, + DMA_MODE_WRITE | DMA_AUTOINIT); count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1; spin_lock_irqsave(&chip->reg_lock, flags); snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count); @@ -522,7 +524,7 @@ static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream) static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); unsigned long flags; int err; @@ -546,15 +548,16 @@ static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream) static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned long flags; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); - chip->dma_size = size; + chip->c_dma_size = size; chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO); - snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); + snd_dma_program(chip->dma2, runtime->dma_addr, size, + DMA_MODE_READ | DMA_AUTOINIT); count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1; spin_lock_irqsave(&chip->reg_lock, flags); snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count); @@ -565,7 +568,7 @@ static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream) static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) { - struct snd_ad1848 *chip = dev_id; + struct snd_wss *chip = dev_id; if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream && (chip->mode & AD1848_MODE_RUNNING)) @@ -579,23 +582,23 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); size_t ptr; if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE)) return 0; - ptr = snd_dma_pointer(chip->dma, chip->dma_size); + ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); return bytes_to_frames(substream->runtime, ptr); } static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); size_t ptr; if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE)) return 0; - ptr = snd_dma_pointer(chip->dma, chip->dma_size); + ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); return bytes_to_frames(substream->runtime, ptr); } @@ -603,8 +606,8 @@ static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *su */ -static void snd_ad1848_thinkpad_twiddle(struct snd_ad1848 *chip, int on) { - +static void snd_ad1848_thinkpad_twiddle(struct snd_wss *chip, int on) +{ int tmp; if (!chip->thinkpad_flag) return; @@ -624,14 +627,14 @@ static void snd_ad1848_thinkpad_twiddle(struct snd_ad1848 *chip, int on) { } #ifdef CONFIG_PM -static void snd_ad1848_suspend(struct snd_ad1848 *chip) +static void snd_ad1848_suspend(struct snd_wss *chip) { snd_pcm_suspend_all(chip->pcm); if (chip->thinkpad_flag) snd_ad1848_thinkpad_twiddle(chip, 0); } -static void snd_ad1848_resume(struct snd_ad1848 *chip) +static void snd_ad1848_resume(struct snd_wss *chip) { int i; @@ -651,7 +654,7 @@ static void snd_ad1848_resume(struct snd_ad1848 *chip) } #endif /* CONFIG_PM */ -static int snd_ad1848_probe(struct snd_ad1848 * chip) +static int snd_ad1848_probe(struct snd_wss *chip) { unsigned long flags; int i, id, rev, ad1847; @@ -775,7 +778,7 @@ static struct snd_pcm_hardware snd_ad1848_capture = static int snd_ad1848_playback_open(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err; @@ -783,15 +786,15 @@ static int snd_ad1848_playback_open(struct snd_pcm_substream *substream) return err; chip->playback_substream = substream; runtime->hw = snd_ad1848_playback; - snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max); + snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); + snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); return 0; } static int snd_ad1848_capture_open(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err; @@ -799,15 +802,15 @@ static int snd_ad1848_capture_open(struct snd_pcm_substream *substream) return err; chip->capture_substream = substream; runtime->hw = snd_ad1848_capture; - snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max); + snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); + snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); return 0; } static int snd_ad1848_playback_close(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); chip->mode &= ~AD1848_MODE_PLAY; chip->playback_substream = NULL; @@ -817,7 +820,7 @@ static int snd_ad1848_playback_close(struct snd_pcm_substream *substream) static int snd_ad1848_capture_close(struct snd_pcm_substream *substream) { - struct snd_ad1848 *chip = snd_pcm_substream_chip(substream); + struct snd_wss *chip = snd_pcm_substream_chip(substream); chip->mode &= ~AD1848_MODE_CAPTURE; chip->capture_substream = NULL; @@ -825,14 +828,14 @@ static int snd_ad1848_capture_close(struct snd_pcm_substream *substream) return 0; } -static int snd_ad1848_free(struct snd_ad1848 *chip) +static int snd_ad1848_free(struct snd_wss *chip) { release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); - if (chip->dma >= 0) { - snd_dma_disable(chip->dma); - free_dma(chip->dma); + if (chip->dma1 >= 0) { + snd_dma_disable(chip->dma1); + free_dma(chip->dma1); } kfree(chip); return 0; @@ -840,11 +843,11 @@ static int snd_ad1848_free(struct snd_ad1848 *chip) static int snd_ad1848_dev_free(struct snd_device *device) { - struct snd_ad1848 *chip = device->device_data; + struct snd_wss *chip = device->device_data; return snd_ad1848_free(chip); } -static const char *snd_ad1848_chip_id(struct snd_ad1848 *chip) +static const char *snd_ad1848_chip_id(struct snd_wss *chip) { switch (chip->hardware) { case AD1848_HW_AD1847: return "AD1847"; @@ -859,12 +862,12 @@ int snd_ad1848_create(struct snd_card *card, unsigned long port, int irq, int dma, unsigned short hardware, - struct snd_ad1848 ** rchip) + struct snd_wss **rchip) { static struct snd_device_ops ops = { .dev_free = snd_ad1848_dev_free, }; - struct snd_ad1848 *chip; + struct snd_wss *chip; int err; *rchip = NULL; @@ -875,7 +878,9 @@ int snd_ad1848_create(struct snd_card *card, chip->card = card; chip->port = port; chip->irq = -1; - chip->dma = -1; + chip->dma1 = -1; + chip->dma2 = -1; + chip->single_dma = 1; chip->hardware = hardware; memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image)); @@ -895,7 +900,8 @@ int snd_ad1848_create(struct snd_card *card, snd_ad1848_free(chip); return -EBUSY; } - chip->dma = dma; + chip->dma1 = dma; + chip->dma2 = dma; if (hardware == AD1848_HW_THINKPAD) { chip->thinkpad_flag = 1; @@ -947,7 +953,7 @@ static struct snd_pcm_ops snd_ad1848_capture_ops = { .pointer = snd_ad1848_capture_pointer, }; -int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm) +int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) { struct snd_pcm *pcm; int err; @@ -964,7 +970,9 @@ int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(), - 64*1024, chip->dma > 3 ? 128*1024 : 64*1024); + 64 * 1024, + chip->dma1 > 3 ? + 128 * 1024 : 64 * 1024); chip->pcm = pcm; if (rpcm) @@ -1003,7 +1011,7 @@ static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -1015,7 +1023,7 @@ static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; unsigned short left, right; int change; @@ -1049,7 +1057,7 @@ static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -1066,7 +1074,7 @@ static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; @@ -1100,7 +1108,7 @@ static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -1122,7 +1130,7 @@ static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol); + struct snd_wss *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; int left_reg = kcontrol->private_value & 0xff; int right_reg = (kcontrol->private_value >> 8) & 0xff; @@ -1159,7 +1167,7 @@ static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e /* */ -int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, +int snd_ad1848_add_ctl_elem(struct snd_wss *chip, const struct ad1848_mix_elem *c) { static struct snd_kcontrol_new newctls[] = { @@ -1227,7 +1235,7 @@ AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0, db_scale_6bit), }; -int snd_ad1848_mixer(struct snd_ad1848 *chip) +int snd_ad1848_mixer(struct snd_wss *chip) { struct snd_card *card; struct snd_pcm *pcm; diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 4d198ec71e9..aefd2f4a057 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -151,7 +151,7 @@ struct snd_cmi8330 { struct pnp_dev *play; #endif struct snd_card *card; - struct snd_ad1848 *wss; + struct snd_wss *wss; struct snd_sb *sb; struct snd_pcm *pcm; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index fefb8597717..ff9baf751b2 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -706,13 +706,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; int error; struct snd_opti9xx *chip = card->private_data; -#if defined(CS4231) || defined(OPTi93X) struct snd_wss *codec; #ifdef CS4231 struct snd_timer *timer; -#endif -#else - struct snd_ad1848 *codec; #endif struct snd_pcm *pcm; struct snd_rawmidi *rmidi; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index da3d152bcad..1771f15d6d3 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -397,7 +397,7 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, return 0; } -static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip) +static int __devinit snd_sc6000_mixer(struct snd_wss *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -483,7 +483,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) int xirq = irq[dev]; int xdma = dma[dev]; struct snd_card *card; - struct snd_ad1848 *chip; + struct snd_wss *chip; struct snd_opl3 *opl3; char __iomem *vport; char __iomem *vmss_port; diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index a07274ecb14..879c00c566b 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -180,7 +180,7 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7 AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) }; -static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip) +static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -237,7 +237,7 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) static int possible_dmas[] = {1, 3, 0, -1}; int err, xirq, xdma1; struct snd_card *card; - struct snd_ad1848 *chip; + struct snd_wss *chip; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) @@ -312,7 +312,7 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n, pm_message_t state) { struct snd_card *card = dev_get_drvdata(pdev); - struct snd_ad1848 *chip = card->private_data; + struct snd_wss *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); chip->suspend(chip); @@ -322,7 +322,7 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n, static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) { struct snd_card *card = dev_get_drvdata(pdev); - struct snd_ad1848 *chip = card->private_data; + struct snd_wss *chip = card->private_data; chip->resume(chip); snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); -- GitLab From ece11c9b6db5b96179df8eb9cdc54c78953a4c0f Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:05:44 +0200 Subject: [PATCH 0248/5416] ALSA: wss_lib: use wss constants instead of ad1848 ones Use wss constants for mode. Move ad1848 hardware constants to the wss.h. Move mixer tlv macros into the ad1848_lib.c from the ad1848.h. Drop the MODE_RUNNING spurious IRQ guard on AD1848 as it doesn not seem to be needed. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 32 -------------------- include/sound/wss.h | 6 ++++ sound/isa/ad1848/ad1848.c | 2 +- sound/isa/ad1848/ad1848_lib.c | 48 +++++++++++++++++++----------- sound/isa/cmi8330.c | 4 +-- sound/isa/opti9xx/opti92x-ad1848.c | 2 +- sound/isa/sc6000.c | 2 +- sound/isa/sgalaxy.c | 2 +- 8 files changed, 42 insertions(+), 56 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index d740e633e81..a881d5173c6 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -106,24 +106,6 @@ #define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ #define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */ -/* defines for codec.mode */ - -#define AD1848_MODE_NONE 0x0000 -#define AD1848_MODE_PLAY 0x0001 -#define AD1848_MODE_CAPTURE 0x0002 -#define AD1848_MODE_TIMER 0x0004 -#define AD1848_MODE_OPEN (AD1848_MODE_PLAY|AD1848_MODE_CAPTURE|AD1848_MODE_TIMER) -#define AD1848_MODE_RUNNING 0x0010 - -/* defines for codec.hardware */ - -#define AD1848_HW_DETECT 0x0000 /* let AD1848 driver detect chip */ -#define AD1848_HW_AD1847 0x0001 /* AD1847 chip */ -#define AD1848_HW_AD1848 0x0002 /* AD1848 chip */ -#define AD1848_HW_CS4248 0x0003 /* CS4248 chip */ -#define AD1848_HW_CMI8330 0x0004 /* CMI8330 chip */ -#define AD1848_HW_THINKPAD 0x0005 /* Thinkpad 360/750/755 */ - /* IBM Thinkpad specific stuff */ #define AD1848_THINKPAD_CTL_PORT1 0x15e8 #define AD1848_THINKPAD_CTL_PORT2 0x15e9 @@ -167,26 +149,12 @@ struct ad1848_mix_elem { .type = AD1848_MIX_SINGLE, \ .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) } -#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_SINGLE, \ - .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \ - .tlv = xtlv } - #define AD1848_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ { .name = xname, \ .index = xindex, \ .type = AD1848_MIX_DOUBLE, \ .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) } -#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_DOUBLE, \ - .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ - .tlv = xtlv } - int snd_ad1848_add_ctl_elem(struct snd_wss *chip, const struct ad1848_mix_elem *c); diff --git a/include/sound/wss.h b/include/sound/wss.h index 1e0dc77f0d2..2cc1f1462d8 100644 --- a/include/sound/wss.h +++ b/include/sound/wss.h @@ -55,6 +55,12 @@ #define WSS_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */ #define WSS_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */ #define WSS_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */ +#define WSS_HW_AD1848_MASK 0x0800 /* AD1848 serie (half duplex) */ +#define WSS_HW_AD1847 0x0801 /* AD1847 chip */ +#define WSS_HW_AD1848 0x0802 /* AD1848 chip */ +#define WSS_HW_CS4248 0x0803 /* CS4248 chip */ +#define WSS_HW_CMI8330 0x0804 /* CMI8330 chip */ +#define WSS_HW_THINKPAD 0x0805 /* Thinkpad 360/750/755 */ /* compatible, but clones */ #define WSS_HW_INTERWAVE 0x1000 /* InterWave chip */ #define WSS_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */ diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 74db24ae650..40de24b280d 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -96,7 +96,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) return -EINVAL; error = snd_ad1848_create(card, port[n], irq[n], dma1[n], - thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip); + thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, &chip); if (error < 0) goto out; diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index e25fadffdb5..5aa8f6dae75 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -283,14 +283,12 @@ static int snd_ad1848_trigger(struct snd_wss *chip, unsigned char what, return 0; } snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what); - chip->mode |= AD1848_MODE_RUNNING; } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { if (!(chip->image[AD1848_IFACE_CTRL] & what)) { spin_unlock(&chip->reg_lock); return 0; } snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what); - chip->mode &= ~AD1848_MODE_RUNNING; } else { result = -EINVAL; } @@ -378,7 +376,7 @@ static int snd_ad1848_open(struct snd_wss *chip, unsigned int mode) { unsigned long flags; - if (chip->mode & AD1848_MODE_OPEN) + if (chip->mode & WSS_MODE_OPEN) return -EAGAIN; snd_ad1848_mce_down(chip); @@ -570,11 +568,9 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) { struct snd_wss *chip = dev_id; - if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream && - (chip->mode & AD1848_MODE_RUNNING)) + if ((chip->mode & WSS_MODE_PLAY) && chip->playback_substream) snd_pcm_period_elapsed(chip->playback_substream); - if ((chip->mode & AD1848_MODE_CAPTURE) && chip->capture_substream && - (chip->mode & AD1848_MODE_RUNNING)) + if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream) snd_pcm_period_elapsed(chip->capture_substream); outb(0, AD1848P(chip, STATUS)); /* clear global interrupt bit */ return IRQ_HANDLED; @@ -690,19 +686,19 @@ static int snd_ad1848_probe(struct snd_wss *chip) } if (id != 1) return -ENODEV; /* no valid device found */ - if (chip->hardware == AD1848_HW_DETECT) { + if (chip->hardware == WSS_HW_DETECT) { if (ad1847) { - chip->hardware = AD1848_HW_AD1847; + chip->hardware = WSS_HW_AD1847; } else { - chip->hardware = AD1848_HW_AD1848; + chip->hardware = WSS_HW_AD1848; rev = snd_ad1848_in(chip, AD1848_MISC_INFO); if (rev & 0x80) { - chip->hardware = AD1848_HW_CS4248; + chip->hardware = WSS_HW_CS4248; } else if ((rev & 0x0f) == 0x0a) { snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40); for (i = 0; i < 16; ++i) { if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) { - chip->hardware = AD1848_HW_CMI8330; + chip->hardware = WSS_HW_CMI8330; break; } } @@ -782,7 +778,8 @@ static int snd_ad1848_playback_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0) + err = snd_ad1848_open(chip, WSS_MODE_PLAY); + if (err < 0) return err; chip->playback_substream = substream; runtime->hw = snd_ad1848_playback; @@ -798,7 +795,8 @@ static int snd_ad1848_capture_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0) + err = snd_ad1848_open(chip, WSS_MODE_RECORD); + if (err < 0) return err; chip->capture_substream = substream; runtime->hw = snd_ad1848_capture; @@ -812,7 +810,7 @@ static int snd_ad1848_playback_close(struct snd_pcm_substream *substream) { struct snd_wss *chip = snd_pcm_substream_chip(substream); - chip->mode &= ~AD1848_MODE_PLAY; + chip->mode &= ~WSS_MODE_PLAY; chip->playback_substream = NULL; snd_ad1848_close(chip); return 0; @@ -822,7 +820,7 @@ static int snd_ad1848_capture_close(struct snd_pcm_substream *substream) { struct snd_wss *chip = snd_pcm_substream_chip(substream); - chip->mode &= ~AD1848_MODE_CAPTURE; + chip->mode &= ~WSS_MODE_RECORD; chip->capture_substream = NULL; snd_ad1848_close(chip); return 0; @@ -903,9 +901,9 @@ int snd_ad1848_create(struct snd_card *card, chip->dma1 = dma; chip->dma2 = dma; - if (hardware == AD1848_HW_THINKPAD) { + if (hardware == WSS_HW_THINKPAD) { chip->thinkpad_flag = 1; - chip->hardware = AD1848_HW_DETECT; /* reset */ + chip->hardware = WSS_HW_DETECT; /* reset */ snd_ad1848_thinkpad_twiddle(chip, 1); } @@ -1214,6 +1212,20 @@ static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); +#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ +{ .name = xname, \ + .index = xindex, \ + .type = AD1848_MIX_SINGLE, \ + .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \ + .tlv = xtlv } + +#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ +{ .name = xname, \ + .index = xindex, \ + .type = AD1848_MIX_DOUBLE, \ + .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ + .tlv = xtlv } + static struct ad1848_mix_elem snd_ad1848_controls[] = { AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index aefd2f4a057..af6ba129910 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -465,12 +465,12 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) wssport[dev] + 4, wssirq[dev], wssdma[dev], - AD1848_HW_DETECT, + WSS_HW_DETECT, &acard->wss)) < 0) { snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); return err; } - if (acard->wss->hardware != AD1848_HW_CMI8330) { + if (acard->wss->hardware != WSS_HW_CMI8330) { snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n"); return -ENODEV; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index ff9baf751b2..1f6d6fcd6e5 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -775,7 +775,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #else if ((error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, chip->dma1, - AD1848_HW_DETECT, &codec)) < 0) + WSS_HW_DETECT, &codec)) < 0) return error; if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0) return error; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 1771f15d6d3..0b6cf472ddc 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -549,7 +549,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) goto err_unmap2; err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, - AD1848_HW_DETECT, &chip); + WSS_HW_DETECT, &chip); if (err < 0) goto err_unmap2; card->private_data = chip; diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 879c00c566b..9a5a7cc0e60 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -265,7 +265,7 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) if ((err = snd_ad1848_create(card, wssport[dev] + 4, xirq, xdma1, - AD1848_HW_DETECT, &chip)) < 0) + WSS_HW_DETECT, &chip)) < 0) goto _err; card->private_data = chip; -- GitLab From 0c5e3e98220e743f8ac095249b09ca8c87bd655b Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:06:46 +0200 Subject: [PATCH 0249/5416] ALSA: wss_lib: replace ad1848 mixer element macros with wss ones Use the wss macros instead of ad1848 ones. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 32 --------- sound/isa/ad1848/ad1848_lib.c | 123 ++++++++++++++-------------------- sound/isa/cmi8330.c | 82 +++++++++++++++-------- sound/isa/sgalaxy.c | 12 ++-- 4 files changed, 114 insertions(+), 135 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index a881d5173c6..1271e0dada9 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -126,36 +126,4 @@ int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction); int snd_ad1848_mixer(struct snd_wss *chip); -/* exported mixer stuffs */ -enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE }; - -#define AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) \ - ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24)) -#define AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) \ - ((left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22)) - -/* for ease of use */ -struct ad1848_mix_elem { - const char *name; - int index; - int type; - unsigned long private_value; - const unsigned int *tlv; -}; - -#define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_SINGLE, \ - .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) } - -#define AD1848_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_DOUBLE, \ - .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) } - -int snd_ad1848_add_ctl_elem(struct snd_wss *chip, - const struct ad1848_mix_elem *c); - #endif /* __SOUND_AD1848_H */ diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 5aa8f6dae75..4f7aaf4e098 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -1163,88 +1163,64 @@ static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } -/* - */ -int snd_ad1848_add_ctl_elem(struct snd_wss *chip, - const struct ad1848_mix_elem *c) -{ - static struct snd_kcontrol_new newctls[] = { - [AD1848_MIX_SINGLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_ad1848_info_single, - .get = snd_ad1848_get_single, - .put = snd_ad1848_put_single, - }, - [AD1848_MIX_DOUBLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_ad1848_info_double, - .get = snd_ad1848_get_double, - .put = snd_ad1848_put_double, - }, - [AD1848_MIX_CAPTURE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_ad1848_info_mux, - .get = snd_ad1848_get_mux, - .put = snd_ad1848_put_mux, - }, - }; - struct snd_kcontrol *ctl; - int err; - - ctl = snd_ctl_new1(&newctls[c->type], chip); - if (! ctl) - return -ENOMEM; - strlcpy(ctl->id.name, c->name, sizeof(ctl->id.name)); - ctl->id.index = c->index; - ctl->private_value = c->private_value; - if (c->tlv) { - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - ctl->tlv.p = c->tlv; - } - if ((err = snd_ctl_add(chip->card, ctl)) < 0) - return err; - return 0; -} - -EXPORT_SYMBOL(snd_ad1848_add_ctl_elem); - static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); #define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .name = xname, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ + .name = xname, \ .index = xindex, \ - .type = AD1848_MIX_SINGLE, \ - .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \ - .tlv = xtlv } + .info = snd_ad1848_info_single, \ + .get = snd_ad1848_get_single, \ + .put = snd_ad1848_put_single, \ + .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ + .tlv = { .p = (xtlv) } } #define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .name = xname, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ + .name = xname, \ .index = xindex, \ - .type = AD1848_MIX_DOUBLE, \ - .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ - .tlv = xtlv } - -static struct ad1848_mix_elem snd_ad1848_controls[] = { -AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), -AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -AD1848_DOUBLE_TLV("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, - db_scale_rec_gain), + .info = snd_ad1848_info_double, \ + .get = snd_ad1848_get_double, \ + .put = snd_ad1848_put_double, \ + .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ + (shift_right << 19) | (mask << 24) | (invert << 22), \ + .tlv = { .p = (xtlv) } } + +static struct snd_kcontrol_new snd_ad1848_controls[] = { +WSS_DOUBLE("PCM Playback Switch", 0, + AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), +AD1848_DOUBLE_TLV("PCM Playback Volume", 0, + AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, + db_scale_6bit), +WSS_DOUBLE("Aux Playback Switch", 0, + AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +AD1848_DOUBLE_TLV("Aux Playback Volume", 0, + AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, + db_scale_5bit_12db_max), +WSS_DOUBLE("Aux Playback Switch", 1, + AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +AD1848_DOUBLE_TLV("Aux Playback Volume", 1, + AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, + db_scale_5bit_12db_max), +AD1848_DOUBLE_TLV("Capture Volume", 0, + AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, + db_scale_rec_gain), { .name = "Capture Source", - .type = AD1848_MIX_CAPTURE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_ad1848_info_mux, + .get = snd_ad1848_get_mux, + .put = snd_ad1848_put_mux, }, -AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0), -AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0, - db_scale_6bit), +WSS_SINGLE("Loopback Capture Switch", 0, + AD1848_LOOPBACK, 0, 1, 0), +AD1848_SINGLE_TLV("Loopback Capture Volume", 0, + AD1848_LOOPBACK, 1, 63, 0, + db_scale_6bit), }; int snd_ad1848_mixer(struct snd_wss *chip) @@ -1261,9 +1237,12 @@ int snd_ad1848_mixer(struct snd_wss *chip) strcpy(card->mixername, pcm->name); - for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) - if ((err = snd_ad1848_add_ctl_elem(chip, &snd_ad1848_controls[idx])) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_ad1848_controls[idx], chip)); + if (err < 0) return err; + } return 0; } diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index af6ba129910..ca6f602f15c 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -174,32 +174,57 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids); #endif -static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = { -AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), -AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), -AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), -AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), -AD1848_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), -AD1848_DOUBLE("Line Playback Volume", 0, CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), -AD1848_DOUBLE("Line Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), -AD1848_DOUBLE("Line Capture Volume", 0, CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), -AD1848_DOUBLE("CD Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), -AD1848_DOUBLE("CD Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), -AD1848_DOUBLE("CD Playback Volume", 0, CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), -AD1848_DOUBLE("CD Capture Volume", 0, CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), -AD1848_SINGLE("Mic Playback Switch", 0, CMI8330_MUTEMUX, 0, 1, 0), -AD1848_SINGLE("Mic Playback Volume", 0, CMI8330_OUTPUTVOL, 0, 7, 0), -AD1848_SINGLE("Mic Capture Switch", 0, CMI8330_RMUX3D, 0, 1, 0), -AD1848_SINGLE("Mic Capture Volume", 0, CMI8330_OUTPUTVOL, 5, 7, 0), -AD1848_DOUBLE("Wavetable Playback Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), -AD1848_DOUBLE("Wavetable Playback Volume", 0, CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), -AD1848_DOUBLE("Wavetable Capture Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), -AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), -AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1), -AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0), -AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1), -AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",CAPTURE,SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1), -AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMUX, 7, 1, 1), +static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = { +WSS_DOUBLE("Master Playback Volume", 0, + CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), +WSS_SINGLE("Loud Playback Switch", 0, + CMI8330_MUTEMUX, 6, 1, 1), +WSS_DOUBLE("PCM Playback Switch", 0, + AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), +WSS_DOUBLE("PCM Playback Volume", 0, + AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), +WSS_DOUBLE("Line Playback Switch", 0, + CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), +WSS_DOUBLE("Line Playback Volume", 0, + CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), +WSS_DOUBLE("Line Capture Switch", 0, + CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), +WSS_DOUBLE("Line Capture Volume", 0, + CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), +WSS_DOUBLE("CD Playback Switch", 0, + CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), +WSS_DOUBLE("CD Capture Switch", 0, + CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), +WSS_DOUBLE("CD Playback Volume", 0, + CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), +WSS_DOUBLE("CD Capture Volume", 0, + CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), +WSS_SINGLE("Mic Playback Switch", 0, + CMI8330_MUTEMUX, 0, 1, 0), +WSS_SINGLE("Mic Playback Volume", 0, + CMI8330_OUTPUTVOL, 0, 7, 0), +WSS_SINGLE("Mic Capture Switch", 0, + CMI8330_RMUX3D, 0, 1, 0), +WSS_SINGLE("Mic Capture Volume", 0, + CMI8330_OUTPUTVOL, 5, 7, 0), +WSS_DOUBLE("Wavetable Playback Switch", 0, + CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), +WSS_DOUBLE("Wavetable Playback Volume", 0, + CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), +WSS_DOUBLE("Wavetable Capture Switch", 0, + CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), +WSS_DOUBLE("Wavetable Capture Volume", 0, + CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), +WSS_SINGLE("3D Control - Switch", 0, + CMI8330_RMUX3D, 5, 1, 1), +WSS_SINGLE("PC Speaker Playback Volume", 0, + CMI8330_OUTPUTVOL, 3, 3, 0), +WSS_SINGLE("FM Playback Switch", 0, + CMI8330_RECMUX, 3, 1, 1), +WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, + CMI8330_RMUX3D, 7, 1, 1), +WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, + CMI8330_MUTEMUX, 7, 1, 1), }; #ifdef ENABLE_SB_MIXER @@ -268,7 +293,10 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 strcpy(card->mixername, "CMI8330/C3D"); for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) { - if ((err = snd_ad1848_add_ctl_elem(acard->wss, &snd_cmi8330_controls[idx])) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&snd_cmi8330_controls[idx], + acard->wss)); + if (err < 0) return err; } diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 9a5a7cc0e60..5894b2d4db6 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -175,9 +175,11 @@ static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma) return snd_sgalaxy_setup_wss(wssport[dev], irq, dma); } -static struct ad1848_mix_elem snd_sgalaxy_controls[] = { -AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), -AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) +static struct snd_kcontrol_new snd_sgalaxy_controls[] = { +WSS_DOUBLE("Aux Playback Switch", 0, + SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), +WSS_DOUBLE("Aux Playback Volume", 0, + SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) }; static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip) @@ -210,7 +212,9 @@ static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip) return err; /* build AUX2 input */ for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) { - if ((err = snd_ad1848_add_ctl_elem(chip, &snd_sgalaxy_controls[idx])) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&snd_sgalaxy_controls[idx], chip)); + if (err < 0) return err; } return 0; -- GitLab From 811585e9d1769d6e282852fc0675735209547ca0 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:07:30 +0200 Subject: [PATCH 0250/5416] ALSA: wss_lib: use CS4231P instead of AD1848P (kill the AD1848P) Use CS4231P instead of AD1848P (kill the AD1848P). Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 9 --- sound/isa/ad1848/ad1848_lib.c | 104 ++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 58 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index 1271e0dada9..29f63b78635 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -27,15 +27,6 @@ #include "wss.h" /* temporary till the driver is removed */ -/* IO ports */ - -#define AD1848P( chip, x ) ( (chip) -> port + c_d_c_AD1848##x ) - -#define c_d_c_AD1848REGSEL 0 -#define c_d_c_AD1848REG 1 -#define c_d_c_AD1848STATUS 2 -#define c_d_c_AD1848PIO 3 - /* codec registers */ #define AD1848_LEFT_INPUT 0x00 /* left input control */ diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 4f7aaf4e098..07756fa3694 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -103,7 +103,7 @@ static void snd_ad1848_wait(struct snd_wss *chip) int timeout; for (timeout = 250; timeout > 0; timeout--) { - if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0) + if ((inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) == 0) break; udelay(100); } @@ -115,12 +115,12 @@ void snd_ad1848_out(struct snd_wss *chip, { snd_ad1848_wait(chip); #ifdef CONFIG_SND_DEBUG - if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) + if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) snd_printk(KERN_WARNING "auto calibration time out - " "reg = 0x%x, value = 0x%x\n", reg, value); #endif - outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); - outb(chip->image[reg] = value, AD1848P(chip, REG)); + outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); + outb(chip->image[reg] = value, chip->port + CS4231P(REG)); mb(); snd_printdd("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); @@ -132,8 +132,8 @@ static void snd_ad1848_dout(struct snd_wss *chip, unsigned char reg, unsigned char value) { snd_ad1848_wait(chip); - outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); - outb(value, AD1848P(chip, REG)); + outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); + outb(value, chip->port + CS4231P(REG)); mb(); } @@ -141,37 +141,37 @@ static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) { snd_ad1848_wait(chip); #ifdef CONFIG_SND_DEBUG - if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) + if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) snd_printk(KERN_WARNING "auto calibration time out - " "reg = 0x%x\n", reg); #endif - outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); + outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); mb(); - return inb(AD1848P(chip, REG)); + return inb(chip->port + CS4231P(REG)); } #if 0 static void snd_ad1848_debug(struct snd_wss *chip) { - printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL))); - printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS))); - printk(" 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00)); - printk(" 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08)); - printk(" 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01)); - printk(" 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09)); - printk(" 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02)); - printk(" 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a)); - printk(" 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03)); - printk(" 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b)); - printk(" 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04)); - printk(" 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c)); - printk(" 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05)); - printk(" 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d)); - printk(" 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06)); - printk(" 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e)); - printk(" 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07)); - printk(" 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f)); + printk(KERN_DEBUG "AD1848 REGS: INDEX = 0x%02x ", inb(chip->port + CS4231P(REGSEL))); + printk(KERN_DEBUG " STATUS = 0x%02x\n", inb(chip->port + CS4231P(STATUS))); + printk(KERN_DEBUG " 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00)); + printk(KERN_DEBUG " 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08)); + printk(KERN_DEBUG " 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01)); + printk(KERN_DEBUG " 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09)); + printk(KERN_DEBUG " 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02)); + printk(KERN_DEBUG " 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a)); + printk(KERN_DEBUG " 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03)); + printk(KERN_DEBUG " 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b)); + printk(KERN_DEBUG " 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04)); + printk(KERN_DEBUG " 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c)); + printk(KERN_DEBUG " 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05)); + printk(KERN_DEBUG " 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d)); + printk(KERN_DEBUG " 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06)); + printk(KERN_DEBUG " 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e)); + printk(KERN_DEBUG " 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07)); + printk(KERN_DEBUG " 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f)); } #endif @@ -187,16 +187,17 @@ static void snd_ad1848_mce_up(struct snd_wss *chip) snd_ad1848_wait(chip); #ifdef CONFIG_SND_DEBUG - if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) + if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= AD1848_MCE; - timeout = inb(AD1848P(chip, REGSEL)); + timeout = inb(chip->port + CS4231P(REGSEL)); if (timeout == 0x80) snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); if (!(timeout & AD1848_MCE)) - outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); + outb(chip->mce_bit | (timeout & 0x1f), + chip->port + CS4231P(REGSEL)); spin_unlock_irqrestore(&chip->reg_lock, flags); } @@ -207,21 +208,25 @@ static void snd_ad1848_mce_down(struct snd_wss *chip) spin_lock_irqsave(&chip->reg_lock, flags); for (timeout = 5; timeout > 0; timeout--) - inb(AD1848P(chip, REGSEL)); + inb(chip->port + CS4231P(REGSEL)); /* end of cleanup sequence */ - for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) + for (timeout = 12000; + timeout > 0 && (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT); + timeout--) udelay(100); snd_printdd("(1) timeout = %ld\n", timeout); #ifdef CONFIG_SND_DEBUG - if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) - snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); + if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) + snd_printk(KERN_WARNING + "mce_down [0x%lx] - auto calibration time out (0)\n", + chip->port + CS4231P(REGSEL)); #endif chip->mce_bit &= ~AD1848_MCE; - reg = inb(AD1848P(chip, REGSEL)); - outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL)); + reg = inb(chip->port + CS4231P(REGSEL)); + outb(chip->mce_bit | (reg & 0x1f), chip->port + CS4231P(REGSEL)); if (reg == 0x80) snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); if ((reg & AD1848_MCE) == 0) { @@ -252,7 +257,8 @@ static void snd_ad1848_mce_down(struct snd_wss *chip) "mce_down - auto calibration time out (2)\n"); snd_printdd("(4) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); + snd_printd("mce_down - exit = 0x%x\n", + inb(chip->port + CS4231P(REGSEL))); } static unsigned int snd_ad1848_get_count(unsigned char format, @@ -412,8 +418,8 @@ static int snd_ad1848_open(struct snd_wss *chip, unsigned int mode) /* ok. now enable and ack CODEC IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE; snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]); spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -431,8 +437,8 @@ static void snd_ad1848_close(struct snd_wss *chip) return; /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE; snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]); spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -449,8 +455,8 @@ static void snd_ad1848_close(struct snd_wss *chip) /* clear IRQ again */ spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ - outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ + outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = 0; @@ -572,7 +578,7 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) snd_pcm_period_elapsed(chip->playback_substream); if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream) snd_pcm_period_elapsed(chip->capture_substream); - outb(0, AD1848P(chip, STATUS)); /* clear global interrupt bit */ + outb(0, chip->port + CS4231P(STATUS)); /* clear global interrupt bit */ return IRQ_HANDLED; } @@ -638,8 +644,8 @@ static void snd_ad1848_resume(struct snd_wss *chip) snd_ad1848_thinkpad_twiddle(chip, 1); /* clear any pendings IRQ */ - inb(AD1848P(chip, STATUS)); - outb(0, AD1848P(chip, STATUS)); + inb(chip->port + CS4231P(STATUS)); + outb(0, chip->port + CS4231P(STATUS)); mb(); snd_ad1848_mce_down(chip); @@ -662,7 +668,7 @@ static int snd_ad1848_probe(struct snd_wss *chip) id = ad1847 = 0; for (i = 0; i < 1000; i++) { mb(); - if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) + if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) udelay(500); else { spin_lock_irqsave(&chip->reg_lock, flags); @@ -707,8 +713,8 @@ static int snd_ad1848_probe(struct snd_wss *chip) } } spin_lock_irqsave(&chip->reg_lock, flags); - inb(AD1848P(chip, STATUS)); /* clear any pendings IRQ */ - outb(0, AD1848P(chip, STATUS)); + inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ + outb(0, chip->port + CS4231P(STATUS)); mb(); spin_unlock_irqrestore(&chip->reg_lock, flags); -- GitLab From 5664daa1c1fa250dd7f6b336278b0402638e8edc Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:08:32 +0200 Subject: [PATCH 0251/5416] ALSA: wss_lib: use wss mixer code instead of ad1848 one Use the wss mixer code and kill the ad1848 mixer code. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 1 - include/sound/wss.h | 25 +++ sound/isa/ad1848/ad1848.c | 2 +- sound/isa/ad1848/ad1848_lib.c | 261 ----------------------------- sound/isa/opti9xx/opti92x-ad1848.c | 22 +-- sound/isa/sc6000.c | 4 +- sound/isa/sgalaxy.c | 5 +- sound/isa/wss/wss_lib.c | 61 ++++++- 8 files changed, 98 insertions(+), 283 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index 29f63b78635..03e2abf64a7 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -115,6 +115,5 @@ int snd_ad1848_create(struct snd_card *card, int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction); -int snd_ad1848_mixer(struct snd_wss *chip); #endif /* __SOUND_AD1848_H */ diff --git a/include/sound/wss.h b/include/sound/wss.h index 2cc1f1462d8..c896f6e1f93 100644 --- a/include/sound/wss.h +++ b/include/sound/wss.h @@ -193,6 +193,31 @@ int snd_wss_put_single(struct snd_kcontrol *kcontrol, .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ (shift_right << 19) | (mask << 24) | (invert << 22) } +#define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ + .name = xname, \ + .index = xindex, \ + .info = snd_wss_info_single, \ + .get = snd_wss_get_single, \ + .put = snd_wss_put_single, \ + .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ + .tlv = { .p = (xtlv) } } + +#define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \ + shift_left, shift_right, mask, invert, xtlv) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ + .name = xname, \ + .index = xindex, \ + .info = snd_wss_info_double, \ + .get = snd_wss_get_double, \ + .put = snd_wss_put_double, \ + .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ + (shift_right << 19) | (mask << 24) | (invert << 22), \ + .tlv = { .p = (xtlv) } } + + int snd_wss_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_wss_get_double(struct snd_kcontrol *kcontrol, diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 40de24b280d..d5a96631587 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -106,7 +106,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) if (error < 0) goto out; - error = snd_ad1848_mixer(chip); + error = snd_wss_mixer(chip); if (error < 0) goto out; diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 07756fa3694..5de04601433 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -994,267 +994,6 @@ const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); -/* - * MIXER part - */ - -static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "Line", "Aux", "Mic", "Mix" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6; - ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short left, right; - int change; - - if (ucontrol->value.enumerated.item[0] > 3 || - ucontrol->value.enumerated.item[1] > 3) - return -EINVAL; - left = ucontrol->value.enumerated.item[0] << 6; - right = ucontrol->value.enumerated.item[1] << 6; - spin_lock_irqsave(&chip->reg_lock, flags); - left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left; - right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right; - change = left != chip->image[AD1848_LEFT_INPUT] || - right != chip->image[AD1848_RIGHT_INPUT]; - snd_ad1848_out(chip, AD1848_LEFT_INPUT, left); - snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[reg] & ~(mask << shift)) | val; - change = val != chip->image[reg]; - snd_ad1848_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; - snd_ad1848_out(chip, left_reg, val1); - snd_ad1848_out(chip, right_reg, val2); - } else { - val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != chip->image[left_reg]; - snd_ad1848_out(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, \ - .index = xindex, \ - .info = snd_ad1848_info_single, \ - .get = snd_ad1848_get_single, \ - .put = snd_ad1848_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, \ - .index = xindex, \ - .info = snd_ad1848_info_double, \ - .get = snd_ad1848_get_double, \ - .put = snd_ad1848_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ - (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static struct snd_kcontrol_new snd_ad1848_controls[] = { -WSS_DOUBLE("PCM Playback Switch", 0, - AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("PCM Playback Volume", 0, - AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), -WSS_DOUBLE("Aux Playback Switch", 0, - AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 0, - AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Aux Playback Switch", 1, - AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 1, - AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -AD1848_DOUBLE_TLV("Capture Volume", 0, - AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, - db_scale_rec_gain), -{ - .name = "Capture Source", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_ad1848_info_mux, - .get = snd_ad1848_get_mux, - .put = snd_ad1848_put_mux, -}, -WSS_SINGLE("Loopback Capture Switch", 0, - AD1848_LOOPBACK, 0, 1, 0), -AD1848_SINGLE_TLV("Loopback Capture Volume", 0, - AD1848_LOOPBACK, 1, 63, 0, - db_scale_6bit), -}; - -int snd_ad1848_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - struct snd_pcm *pcm; - unsigned int idx; - int err; - - snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); - - pcm = chip->pcm; - card = chip->card; - - strcpy(card->mixername, pcm->name); - - for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_ad1848_controls[idx], chip)); - if (err < 0) - return err; - } - - return 0; -} - -EXPORT_SYMBOL(snd_ad1848_mixer); - /* * INIT part */ diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 1f6d6fcd6e5..4f172a21924 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -757,6 +757,15 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) error = snd_wss_pcm(codec, 0, &pcm); if (error < 0) return error; +#else + error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, + chip->dma1, WSS_HW_DETECT, &codec); + if (error < 0) + return error; + error = snd_ad1848_pcm(codec, 0, &pcm); + if (error < 0) + return error; +#endif error = snd_wss_mixer(codec); if (error < 0) return error; @@ -764,23 +773,14 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) error = snd_wss_timer(codec, 0, &timer); if (error < 0) return error; -#else /* OPTI93X */ +#endif +#ifdef OPTi93X error = request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec); if (error < 0) { snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); return error; } -#endif -#else - if ((error = snd_ad1848_create(card, chip->wss_base + 4, - chip->irq, chip->dma1, - WSS_HW_DETECT, &codec)) < 0) - return error; - if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0) - return error; - if ((error = snd_ad1848_mixer(codec)) < 0) - return error; #endif strcpy(card->driver, chip->name); sprintf(card->shortname, "OPTi %s", card->driver); diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 0b6cf472ddc..ef98fe7dced 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -560,9 +560,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) "error creating new ad1848 PCM device\n"); goto err_unmap2; } - err = snd_ad1848_mixer(chip); + err = snd_wss_mixer(chip); if (err < 0) { - snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n"); + snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); goto err_unmap2; } err = snd_sc6000_mixer(chip); diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 5894b2d4db6..e4f06de3480 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -277,8 +277,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) snd_printdd(PFX "error creating new ad1848 PCM device\n"); goto _err; } - if ((err = snd_ad1848_mixer(chip)) < 0) { - snd_printdd(PFX "error creating new ad1848 mixer\n"); + err = snd_wss_mixer(chip); + if (err < 0) { + snd_printdd(PFX "error creating new WSS mixer\n"); goto _err; } if ((err = snd_sgalaxy_mixer(chip)) < 0) { diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index a982997805c..1688f07a14b 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1957,16 +1958,58 @@ int snd_wss_put_double(struct snd_kcontrol *kcontrol, val1 <<= shift_left; val2 <<= shift_right; spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; - snd_wss_out(chip, left_reg, val1); - snd_wss_out(chip, right_reg, val2); + if (left_reg != right_reg) { + val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; + val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; + change = val1 != chip->image[left_reg] || + val2 != chip->image[right_reg]; + snd_wss_out(chip, left_reg, val1); + snd_wss_out(chip, right_reg, val2); + } else { + mask = (mask << shift_left) | (mask << shift_right); + val1 = (chip->image[left_reg] & ~mask) | val1 | val2; + change = val1 != chip->image[left_reg]; + snd_wss_out(chip, left_reg, val1); + } spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } EXPORT_SYMBOL(snd_wss_put_double); +static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); + +static struct snd_kcontrol_new snd_ad1848_controls[] = { +WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, + 7, 7, 1, 1), +WSS_DOUBLE_TLV("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, + db_scale_6bit), +WSS_DOUBLE("Aux Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Aux Playback Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, + db_scale_5bit_12db_max), +WSS_DOUBLE("Aux Playback Switch", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE_TLV("Aux Playback Volume", 1, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, + db_scale_5bit_12db_max), +WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, + 0, 0, 15, 0, db_scale_rec_gain), +{ + .name = "Capture Source", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_wss_info_mux, + .get = snd_wss_get_mux, + .put = snd_wss_put_mux, +}, +WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), +WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0, + db_scale_6bit), +}; + static struct snd_kcontrol_new snd_wss_controls[] = { WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), @@ -2071,6 +2114,14 @@ int snd_wss_mixer(struct snd_wss *chip) if (err < 0) return err; } + else if (chip->hardware & WSS_HW_AD1848_MASK) + for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_ad1848_controls[idx], + chip)); + if (err < 0) + return err; + } else for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) { err = snd_ctl_add(card, -- GitLab From ead893c0deeec165524cc8a06e7e739d7d84b4c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:09:32 +0200 Subject: [PATCH 0252/5416] ALSA: wss_lib: use wss pcm code instead of ad1848 one Use the wss pcm code and kill the ad1848 pcm code. The AD1848 chip is much slower than CS4231 chips so the waiting loop was increased 100x (10x is not enough). Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 8 - include/sound/wss.h | 7 + sound/isa/Kconfig | 5 +- sound/isa/ad1848/ad1848.c | 2 +- sound/isa/ad1848/ad1848_lib.c | 544 +---------------------------- sound/isa/cmi8330.c | 2 +- sound/isa/opti9xx/opti92x-ad1848.c | 7 +- sound/isa/sc6000.c | 4 +- sound/isa/sgalaxy.c | 5 +- sound/isa/wss/wss_lib.c | 126 +++++-- 10 files changed, 129 insertions(+), 581 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index 03e2abf64a7..7ff484f55b0 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -97,11 +97,6 @@ #define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ #define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */ -/* IBM Thinkpad specific stuff */ -#define AD1848_THINKPAD_CTL_PORT1 0x15e8 -#define AD1848_THINKPAD_CTL_PORT2 0x15e9 -#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02 - /* exported functions */ void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, @@ -113,7 +108,4 @@ int snd_ad1848_create(struct snd_card *card, unsigned short hardware, struct snd_wss **chip); -int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); -const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction); - #endif /* __SOUND_AD1848_H */ diff --git a/include/sound/wss.h b/include/sound/wss.h index c896f6e1f93..fd01f22825c 100644 --- a/include/sound/wss.h +++ b/include/sound/wss.h @@ -71,6 +71,11 @@ #define WSS_HWSHARE_DMA1 (1<<1) #define WSS_HWSHARE_DMA2 (1<<2) +/* IBM Thinkpad specific stuff */ +#define AD1848_THINKPAD_CTL_PORT1 0x15e8 +#define AD1848_THINKPAD_CTL_PORT2 0x15e9 +#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02 + struct snd_wss { unsigned long port; /* base i/o port */ struct resource *res_port; @@ -153,6 +158,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); int snd_wss_mixer(struct snd_wss *chip); +const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction); + int snd_cs4236_create(struct snd_card *card, unsigned long port, unsigned long cport, diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 87055568ccd..cca11d5dc33 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -1,12 +1,13 @@ # ALSA ISA drivers -config SND_AD1848_LIB +config SND_WSS_LIB tristate select SND_PCM -config SND_WSS_LIB +config SND_AD1848_LIB tristate select SND_PCM + select SND_WSS_LIB config SND_SB_COMMON tristate diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index d5a96631587..17970c2f27e 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -102,7 +102,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) card->private_data = chip; - error = snd_ad1848_pcm(chip, 0, &pcm); + error = snd_wss_pcm(chip, 0, &pcm); if (error < 0) goto out; diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 5de04601433..aa803d38a8a 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -46,34 +46,6 @@ MODULE_LICENSE("GPL"); * Some variables */ -static unsigned char freq_bits[14] = { - /* 5510 */ 0x00 | AD1848_XTAL2, - /* 6620 */ 0x0E | AD1848_XTAL2, - /* 8000 */ 0x00 | AD1848_XTAL1, - /* 9600 */ 0x0E | AD1848_XTAL1, - /* 11025 */ 0x02 | AD1848_XTAL2, - /* 16000 */ 0x02 | AD1848_XTAL1, - /* 18900 */ 0x04 | AD1848_XTAL2, - /* 22050 */ 0x06 | AD1848_XTAL2, - /* 27042 */ 0x04 | AD1848_XTAL1, - /* 32000 */ 0x06 | AD1848_XTAL1, - /* 33075 */ 0x0C | AD1848_XTAL2, - /* 37800 */ 0x08 | AD1848_XTAL2, - /* 44100 */ 0x0A | AD1848_XTAL2, - /* 48000 */ 0x0C | AD1848_XTAL1 -}; - -static unsigned int rates[14] = { - 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, - 27042, 32000, 33075, 37800, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - static unsigned char snd_ad1848_original_image[16] = { 0x00, /* 00 - lic */ @@ -128,15 +100,6 @@ void snd_ad1848_out(struct snd_wss *chip, EXPORT_SYMBOL(snd_ad1848_out); -static void snd_ad1848_dout(struct snd_wss *chip, - unsigned char reg, unsigned char value) -{ - snd_ad1848_wait(chip); - outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); - outb(value, chip->port + CS4231P(REG)); - mb(); -} - static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) { snd_ad1848_wait(chip); @@ -261,315 +224,6 @@ static void snd_ad1848_mce_down(struct snd_wss *chip) inb(chip->port + CS4231P(REGSEL))); } -static unsigned int snd_ad1848_get_count(unsigned char format, - unsigned int size) -{ - switch (format & 0xe0) { - case AD1848_LINEAR_16: - size >>= 1; - break; - } - if (format & AD1848_STEREO) - size >>= 1; - return size; -} - -static int snd_ad1848_trigger(struct snd_wss *chip, unsigned char what, - int channel, int cmd) -{ - int result = 0; - -#if 0 - printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(AD1848P(card, STATUS))); -#endif - spin_lock(&chip->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (chip->image[AD1848_IFACE_CTRL] & what) { - spin_unlock(&chip->reg_lock); - return 0; - } - snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - if (!(chip->image[AD1848_IFACE_CTRL] & what)) { - spin_unlock(&chip->reg_lock); - return 0; - } - snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what); - } else { - result = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return result; -} - -/* - * CODEC I/O - */ - -static unsigned char snd_ad1848_get_rate(unsigned int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (rate == rates[i]) - return freq_bits[i]; - snd_BUG(); - return freq_bits[ARRAY_SIZE(rates) - 1]; -} - -static int snd_ad1848_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static unsigned char snd_ad1848_get_format(int format, int channels) -{ - unsigned char rformat; - - rformat = AD1848_LINEAR_8; - switch (format) { - case SNDRV_PCM_FORMAT_A_LAW: rformat = AD1848_ALAW_8; break; - case SNDRV_PCM_FORMAT_MU_LAW: rformat = AD1848_ULAW_8; break; - case SNDRV_PCM_FORMAT_S16_LE: rformat = AD1848_LINEAR_16; break; - } - if (channels > 1) - rformat |= AD1848_STEREO; -#if 0 - snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); -#endif - return rformat; -} - -static void snd_ad1848_calibrate_mute(struct snd_wss *chip, int mute) -{ - unsigned long flags; - - mute = mute ? 1 : 0; - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->calibrate_mute == mute) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return; - } - if (!mute) { - snd_ad1848_dout(chip, AD1848_LEFT_INPUT, chip->image[AD1848_LEFT_INPUT]); - snd_ad1848_dout(chip, AD1848_RIGHT_INPUT, chip->image[AD1848_RIGHT_INPUT]); - } - snd_ad1848_dout(chip, AD1848_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_LEFT_INPUT]); - snd_ad1848_dout(chip, AD1848_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_RIGHT_INPUT]); - snd_ad1848_dout(chip, AD1848_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_LEFT_INPUT]); - snd_ad1848_dout(chip, AD1848_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_RIGHT_INPUT]); - snd_ad1848_dout(chip, AD1848_LEFT_OUTPUT, mute ? 0x80 : chip->image[AD1848_LEFT_OUTPUT]); - snd_ad1848_dout(chip, AD1848_RIGHT_OUTPUT, mute ? 0x80 : chip->image[AD1848_RIGHT_OUTPUT]); - chip->calibrate_mute = mute; - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_ad1848_set_data_format(struct snd_wss *chip, - struct snd_pcm_hw_params *hw_params) -{ - if (hw_params == NULL) { - chip->image[AD1848_DATA_FORMAT] = 0x20; - } else { - chip->image[AD1848_DATA_FORMAT] = - snd_ad1848_get_format(params_format(hw_params), params_channels(hw_params)) | - snd_ad1848_get_rate(params_rate(hw_params)); - } - // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]); -} - -static int snd_ad1848_open(struct snd_wss *chip, unsigned int mode) -{ - unsigned long flags; - - if (chip->mode & WSS_MODE_OPEN) - return -EAGAIN; - - snd_ad1848_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk("open: (1)\n"); -#endif - snd_ad1848_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO | - AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO | - AD1848_CALIB_MODE); - chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB; - snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk("open: (2)\n"); -#endif - - snd_ad1848_set_data_format(chip, NULL); - - snd_ad1848_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk("open: (3)\n"); -#endif - - /* ok. now enable and ack CODEC IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE; - snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = mode; - - return 0; -} - -static void snd_ad1848_close(struct snd_wss *chip) -{ - unsigned long flags; - - if (!chip->mode) - return; - /* disable IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE; - snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* now disable capture & playback */ - - snd_ad1848_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO | - AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO); - snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - - /* clear IRQ again */ - spin_lock_irqsave(&chip->reg_lock, flags); - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = 0; -} - -/* - * ok.. exported functions.. - */ - -static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd); -} - -static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd); -} - -static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - snd_ad1848_calibrate_mute(chip, 1); - snd_ad1848_set_data_format(chip, hw_params); - snd_ad1848_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - snd_ad1848_calibrate_mute(chip, 0); - return 0; -} - -static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->p_dma_size = size; - chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO); - snd_dma_program(chip->dma1, runtime->dma_addr, size, - DMA_MODE_WRITE | DMA_AUTOINIT); - count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count); - snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - snd_ad1848_calibrate_mute(chip, 1); - snd_ad1848_set_data_format(chip, hw_params); - snd_ad1848_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - snd_ad1848_calibrate_mute(chip, 0); - return 0; -} - -static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->c_dma_size = size; - chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO); - snd_dma_program(chip->dma2, runtime->dma_addr, size, - DMA_MODE_READ | DMA_AUTOINIT); - count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count); - snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) { struct snd_wss *chip = dev_id; @@ -582,28 +236,6 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - /* */ @@ -728,6 +360,16 @@ static int snd_ad1848_probe(struct snd_wss *chip) snd_ad1848_out(chip, i, *ptr++); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_ad1848_mce_up(chip); + /* init needed for WSS pcm */ + spin_lock_irqsave(&chip->reg_lock, flags); + chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | + AD1848_PLAYBACK_PIO | + AD1848_CAPTURE_ENABLE | + AD1848_CAPTURE_PIO | + AD1848_CALIB_MODE); + chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB; + snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]); + spin_unlock_irqrestore(&chip->reg_lock, flags); snd_ad1848_mce_down(chip); return 0; /* all things are ok.. */ } @@ -736,102 +378,6 @@ static int snd_ad1848_probe(struct snd_wss *chip) */ -static struct snd_pcm_hardware snd_ad1848_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ad1848_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - - */ - -static int snd_ad1848_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - err = snd_ad1848_open(chip, WSS_MODE_PLAY); - if (err < 0) - return err; - chip->playback_substream = substream; - runtime->hw = snd_ad1848_playback; - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - return 0; -} - -static int snd_ad1848_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - err = snd_ad1848_open(chip, WSS_MODE_RECORD); - if (err < 0) - return err; - chip->capture_substream = substream; - runtime->hw = snd_ad1848_capture; - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - return 0; -} - -static int snd_ad1848_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->mode &= ~WSS_MODE_PLAY; - chip->playback_substream = NULL; - snd_ad1848_close(chip); - return 0; -} - -static int snd_ad1848_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->mode &= ~WSS_MODE_RECORD; - chip->capture_substream = NULL; - snd_ad1848_close(chip); - return 0; -} - static int snd_ad1848_free(struct snd_wss *chip) { release_and_free_resource(chip->res_port); @@ -851,17 +397,6 @@ static int snd_ad1848_dev_free(struct snd_device *device) return snd_ad1848_free(chip); } -static const char *snd_ad1848_chip_id(struct snd_wss *chip) -{ - switch (chip->hardware) { - case AD1848_HW_AD1847: return "AD1847"; - case AD1848_HW_AD1848: return "AD1848"; - case AD1848_HW_CS4248: return "CS4248"; - case AD1848_HW_CMI8330: return "CMI8330/C3D"; - default: return "???"; - } -} - int snd_ad1848_create(struct snd_card *card, unsigned long port, int irq, int dma, @@ -935,65 +470,6 @@ int snd_ad1848_create(struct snd_card *card, EXPORT_SYMBOL(snd_ad1848_create); -static struct snd_pcm_ops snd_ad1848_playback_ops = { - .open = snd_ad1848_playback_open, - .close = snd_ad1848_playback_close, - .ioctl = snd_ad1848_ioctl, - .hw_params = snd_ad1848_playback_hw_params, - .hw_free = snd_ad1848_playback_hw_free, - .prepare = snd_ad1848_playback_prepare, - .trigger = snd_ad1848_playback_trigger, - .pointer = snd_ad1848_playback_pointer, -}; - -static struct snd_pcm_ops snd_ad1848_capture_ops = { - .open = snd_ad1848_capture_open, - .close = snd_ad1848_capture_close, - .ioctl = snd_ad1848_ioctl, - .hw_params = snd_ad1848_capture_hw_params, - .hw_free = snd_ad1848_capture_hw_free, - .prepare = snd_ad1848_capture_prepare, - .trigger = snd_ad1848_capture_trigger, - .pointer = snd_ad1848_capture_pointer, -}; - -int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - strcpy(pcm->name, snd_ad1848_chip_id(chip)); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64 * 1024, - chip->dma1 > 3 ? - 128 * 1024 : 64 * 1024); - - chip->pcm = pcm; - if (rpcm) - *rpcm = pcm; - return 0; -} - -EXPORT_SYMBOL(snd_ad1848_pcm); - -const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) -{ - return direction == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_ad1848_playback_ops : &snd_ad1848_capture_ops; -} - -EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); - /* * INIT part */ diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index ca6f602f15c..6f7e8bb6ae6 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -413,7 +413,7 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 * chip->streams[CMI_SB_STREAM].private_data = chip->sb; /* AD1848 */ - ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM); + ops = snd_wss_get_pcm_ops(CMI_AD_STREAM); chip->streams[CMI_AD_STREAM].ops = *ops; chip->streams[CMI_AD_STREAM].open = ops->open; chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM]; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 4f172a21924..561d4b3ed09 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -754,18 +754,15 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #ifdef OPTi93X chip->codec = codec; #endif - error = snd_wss_pcm(codec, 0, &pcm); - if (error < 0) - return error; #else error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, chip->dma1, WSS_HW_DETECT, &codec); if (error < 0) return error; - error = snd_ad1848_pcm(codec, 0, &pcm); +#endif + error = snd_wss_pcm(codec, 0, &pcm); if (error < 0) return error; -#endif error = snd_wss_mixer(codec); if (error < 0) return error; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index ef98fe7dced..2f89ecb95de 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -554,10 +554,10 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) goto err_unmap2; card->private_data = chip; - err = snd_ad1848_pcm(chip, 0, NULL); + err = snd_wss_pcm(chip, 0, NULL); if (err < 0) { snd_printk(KERN_ERR PFX - "error creating new ad1848 PCM device\n"); + "error creating new WSS PCM device\n"); goto err_unmap2; } err = snd_wss_mixer(chip); diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index e4f06de3480..b43d6678ba2 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -273,8 +273,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) goto _err; card->private_data = chip; - if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) { - snd_printdd(PFX "error creating new ad1848 PCM device\n"); + err = snd_wss_pcm(chip, 0, NULL); + if (err < 0) { + snd_printdd(PFX "error creating new WSS PCM device\n"); goto _err; } err = snd_wss_mixer(chip); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 1688f07a14b..57d1e8ee6bb 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -380,7 +380,7 @@ static void snd_wss_busy_wait(struct snd_wss *chip) for (timeout = 5; timeout > 0; timeout--) wss_inb(chip, CS4231P(REGSEL)); /* end of cleanup sequence */ - for (timeout = 250; + for (timeout = 25000; timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) udelay(10); @@ -413,6 +413,7 @@ void snd_wss_mce_down(struct snd_wss *chip) unsigned long flags; unsigned long end_time; int timeout; + int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848; snd_wss_busy_wait(chip); @@ -427,10 +428,8 @@ void snd_wss_mce_down(struct snd_wss *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); - if ((timeout & CS4231_MCE) == 0 || - !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { + if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) return; - } /* * Wait for (possible -- during init auto-calibration may not be set) @@ -601,12 +600,14 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]); snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]); - snd_wss_dout(chip, CS4231_LEFT_LINE_IN, - mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); - snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, - mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); - snd_wss_dout(chip, CS4231_MONO_CTRL, - mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) { + snd_wss_dout(chip, CS4231_LEFT_LINE_IN, + mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); + snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, + mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); + snd_wss_dout(chip, CS4231_MONO_CTRL, + mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); + } if (chip->hardware == WSS_HW_INTERWAVE) { snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); @@ -706,7 +707,10 @@ static void snd_wss_capture_format(struct snd_wss *chip, snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); } - snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); + if (chip->hardware & WSS_HW_AD1848_MASK) + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); + else + snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } @@ -818,7 +822,9 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) + snd_wss_out(chip, CS4231_REC_FORMAT, + chip->image[CS4231_REC_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); @@ -844,20 +850,24 @@ static int snd_wss_open(struct snd_wss *chip, unsigned int mode) } /* ok. now enable and ack CODEC IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) { + snd_wss_out(chip, CS4231_IRQ_STATUS, + CS4231_PLAYBACK_IRQ | + CS4231_RECORD_IRQ | + CS4231_TIMER_IRQ); + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + } wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) { + snd_wss_out(chip, CS4231_IRQ_STATUS, + CS4231_PLAYBACK_IRQ | + CS4231_RECORD_IRQ | + CS4231_TIMER_IRQ); + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + } spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = mode; @@ -879,7 +889,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; @@ -902,7 +913,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) } /* clear IRQ again */ - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); + if (!(chip->hardware & WSS_HW_AD1848_MASK)) + snd_wss_out(chip, CS4231_IRQ_STATUS, 0); wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -1023,7 +1035,13 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) chip->c_dma_size = size; chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], count) - 1; + if (chip->hardware & WSS_HW_AD1848_MASK) + count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], + count); + else + count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], + count); + count--; if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); snd_wss_out(chip, CS4231_PLY_UPR_CNT, @@ -1341,6 +1359,11 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_wss_playback; + /* hardware limitation of older chipsets */ + if (chip->hardware & WSS_HW_AD1848_MASK) + runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_S16_BE); + /* hardware bug in InterWave chipset */ if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; @@ -1379,6 +1402,11 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_wss_capture; + /* hardware limitation of older chipsets */ + if (chip->hardware & WSS_HW_AD1848_MASK) + runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_S16_BE); + /* hardware limitation of cheap chips */ if (chip->hardware == WSS_HW_CS4235 || chip->hardware == WSS_HW_CS4239) @@ -1423,6 +1451,26 @@ static int snd_wss_capture_close(struct snd_pcm_substream *substream) return 0; } +static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on) +{ + int tmp; + + if (!chip->thinkpad_flag) + return; + + outb(0x1c, AD1848_THINKPAD_CTL_PORT1); + tmp = inb(AD1848_THINKPAD_CTL_PORT2); + + if (on) + /* turn it on */ + tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT; + else + /* turn it off */ + tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT; + + outb(tmp, AD1848_THINKPAD_CTL_PORT2); +} + #ifdef CONFIG_PM /* lowlevel suspend callback for CS4231 */ @@ -1436,6 +1484,8 @@ static void snd_wss_suspend(struct snd_wss *chip) for (reg = 0; reg < 32; reg++) chip->image[reg] = snd_wss_in(chip, reg); spin_unlock_irqrestore(&chip->reg_lock, flags); + if (chip->thinkpad_flag) + snd_wss_thinkpad_twiddle(chip, 0); } /* lowlevel resume callback for CS4231 */ @@ -1445,6 +1495,8 @@ static void snd_wss_resume(struct snd_wss *chip) unsigned long flags; /* int timeout; */ + if (chip->thinkpad_flag) + snd_wss_thinkpad_twiddle(chip, 1); snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); for (reg = 0; reg < 32; reg++) { @@ -1542,6 +1594,14 @@ const char *snd_wss_chip_id(struct snd_wss *chip) return "AD1845"; case WSS_HW_OPTI93X: return "OPTi 93x"; + case WSS_HW_AD1847: + return "AD1847"; + case WSS_HW_AD1848: + return "AD1848"; + case WSS_HW_CS4248: + return "CS4248"; + case WSS_HW_CMI8330: + return "CMI8330/C3D"; default: return "???"; } @@ -1704,7 +1764,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm); + if (err < 0) return err; spin_lock_init(&chip->reg_lock); @@ -1714,6 +1775,12 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); + /* temporary */ + if (chip->hardware & WSS_HW_AD1848_MASK) { + chip->rate_constraint = snd_wss_xrate; + chip->set_playback_format = snd_wss_playback_format; + chip->set_capture_format = snd_wss_capture_format; + } /* global setup */ pcm->private_data = chip; pcm->info_flags = 0; @@ -2134,6 +2201,13 @@ int snd_wss_mixer(struct snd_wss *chip) } EXPORT_SYMBOL(snd_wss_mixer); +const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction) +{ + return direction == SNDRV_PCM_STREAM_PLAYBACK ? + &snd_wss_playback_ops : &snd_wss_capture_ops; +} +EXPORT_SYMBOL(snd_wss_get_pcm_ops); + /* * INIT part */ -- GitLab From 760fc6b838d8c783c363e8bdb3714bd92a8945c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:10:47 +0200 Subject: [PATCH 0253/5416] ALSA: wss_lib: use wss detection code instead of ad1848 one Use the wss detection code and kill the ad1848 library. The library is fully assimilated into the new wss library. This required reworking of the AD1848 family code so the code is changed to correctly detect chips from the AD1848 and CS4231 families. I have tested it on following cards: Gallant SC-6600 (codec: AD1848, driver: snd-sc6600) SoundScape VIVO/90 (codec: AD1845, driver: snd-sscape) SG Waverider (codec: CS4231A, driver: Rene Herman's snd-galaxy) Opti930 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Opti931 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Gallant SC-70P (chip/codec: CS4237B, driver: snd-cs4236) Audio Plus 3D (chip/codec: CMI8330A, driver: snd-cmi8330) Dell Latitude CP (chip/codec: cs4236, driver snd-cs4232) Sound playback and recording works on all these cards. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/ad1848.h | 111 ------- sound/isa/Kconfig | 15 +- sound/isa/ad1848/Makefile | 2 - sound/isa/ad1848/ad1848.c | 7 +- sound/isa/ad1848/ad1848_lib.c | 487 ----------------------------- sound/isa/cmi8330.c | 22 +- sound/isa/opti9xx/opti92x-ad1848.c | 15 - sound/isa/sc6000.c | 6 +- sound/isa/sgalaxy.c | 13 +- sound/isa/wss/wss_lib.c | 150 +++++++-- 10 files changed, 150 insertions(+), 678 deletions(-) diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index 7ff484f55b0..e69de29bb2d 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -1,111 +0,0 @@ -#ifndef __SOUND_AD1848_H -#define __SOUND_AD1848_H - -/* - * Copyright (c) by Jaroslav Kysela - * Definitions for AD1847/AD1848/CS4248 chips - * - * - * 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 "pcm.h" -#include - -#include "wss.h" /* temporary till the driver is removed */ - -/* codec registers */ - -#define AD1848_LEFT_INPUT 0x00 /* left input control */ -#define AD1848_RIGHT_INPUT 0x01 /* right input control */ -#define AD1848_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */ -#define AD1848_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */ -#define AD1848_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */ -#define AD1848_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */ -#define AD1848_LEFT_OUTPUT 0x06 /* left output control register */ -#define AD1848_RIGHT_OUTPUT 0x07 /* right output control register */ -#define AD1848_DATA_FORMAT 0x08 /* clock and data format - playback/capture - bits 7-0 MCE */ -#define AD1848_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */ -#define AD1848_PIN_CTRL 0x0a /* pin control */ -#define AD1848_TEST_INIT 0x0b /* test and initialization */ -#define AD1848_MISC_INFO 0x0c /* miscellaneous information */ -#define AD1848_LOOPBACK 0x0d /* loopback control */ -#define AD1848_DATA_UPR_CNT 0x0e /* playback/capture upper base count */ -#define AD1848_DATA_LWR_CNT 0x0f /* playback/capture lower base count */ - -/* definitions for codec register select port - CODECP( REGSEL ) */ - -#define AD1848_INIT 0x80 /* CODEC is initializing */ -#define AD1848_MCE 0x40 /* mode change enable */ -#define AD1848_TRD 0x20 /* transfer request disable */ - -/* definitions for codec status register - CODECP( STATUS ) */ - -#define AD1848_GLOBALIRQ 0x01 /* IRQ is active */ - -/* definitions for AD1848_LEFT_INPUT and AD1848_RIGHT_INPUT registers */ - -#define AD1848_ENABLE_MIC_GAIN 0x20 - -#define AD1848_MIXS_LINE1 0x00 -#define AD1848_MIXS_AUX1 0x40 -#define AD1848_MIXS_LINE2 0x80 -#define AD1848_MIXS_ALL 0xc0 - -/* definitions for clock and data format register - AD1848_PLAYBK_FORMAT */ - -#define AD1848_LINEAR_8 0x00 /* 8-bit unsigned data */ -#define AD1848_ALAW_8 0x60 /* 8-bit A-law companded */ -#define AD1848_ULAW_8 0x20 /* 8-bit U-law companded */ -#define AD1848_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */ -#define AD1848_STEREO 0x10 /* stereo mode */ -/* bits 3-1 define frequency divisor */ -#define AD1848_XTAL1 0x00 /* 24.576 crystal */ -#define AD1848_XTAL2 0x01 /* 16.9344 crystal */ - -/* definitions for interface control register - AD1848_IFACE_CTRL */ - -#define AD1848_CAPTURE_PIO 0x80 /* capture PIO enable */ -#define AD1848_PLAYBACK_PIO 0x40 /* playback PIO enable */ -#define AD1848_CALIB_MODE 0x18 /* calibration mode bits */ -#define AD1848_AUTOCALIB 0x08 /* auto calibrate */ -#define AD1848_SINGLE_DMA 0x04 /* use single DMA channel */ -#define AD1848_CAPTURE_ENABLE 0x02 /* capture enable */ -#define AD1848_PLAYBACK_ENABLE 0x01 /* playback enable */ - -/* definitions for pin control register - AD1848_PIN_CTRL */ - -#define AD1848_IRQ_ENABLE 0x02 /* enable IRQ */ -#define AD1848_XCTL1 0x40 /* external control #1 */ -#define AD1848_XCTL0 0x80 /* external control #0 */ - -/* definitions for test and init register - AD1848_TEST_INIT */ - -#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ -#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */ - -/* exported functions */ - -void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, - unsigned char value); - -int snd_ad1848_create(struct snd_card *card, - unsigned long port, - int irq, int dma, - unsigned short hardware, - struct snd_wss **chip); - -#endif /* __SOUND_AD1848_H */ diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index cca11d5dc33..ec80444c2a9 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -4,11 +4,6 @@ config SND_WSS_LIB tristate select SND_PCM -config SND_AD1848_LIB - tristate - select SND_PCM - select SND_WSS_LIB - config SND_SB_COMMON tristate @@ -56,7 +51,7 @@ config SND_AD1816A config SND_AD1848 tristate "Generic AD1848/CS4248 driver" - select SND_AD1848_LIB + select SND_WSS_LIB help Say Y here to include support for AD1848 (Analog Devices) or CS4248 (Cirrus Logic - Crystal Semiconductors) chips. @@ -97,7 +92,7 @@ config SND_AZT2320 config SND_CMI8330 tristate "C-Media CMI8330" - select SND_AD1848_LIB + select SND_WSS_LIB select SND_SB16_DSP help Say Y here to include support for soundcards based on the @@ -193,7 +188,7 @@ config SND_ES18XX config SND_SC6000 tristate "Gallant SC-6000, Audio Excel DSP 16" depends on HAS_IOPORT - select SND_AD1848_LIB + select SND_WSS_LIB select SND_OPL3_LIB select SND_MPU401_UART help @@ -280,7 +275,7 @@ config SND_OPTI92X_AD1848 select SND_OPL3_LIB select SND_OPL4_LIB select SND_MPU401_UART - select SND_AD1848_LIB + select SND_WSS_LIB help Say Y here to include support for soundcards based on Opti 82C92x or OTI-601 chips and using an AD1848 codec. @@ -373,7 +368,7 @@ config SND_SB16_CSP config SND_SGALAXY tristate "Aztech Sound Galaxy" - select SND_AD1848_LIB + select SND_WSS_LIB help Say Y here to include support for Aztech Sound Galaxy soundcards. diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile index ae23331e920..3d6dea3ff92 100644 --- a/sound/isa/ad1848/Makefile +++ b/sound/isa/ad1848/Makefile @@ -3,10 +3,8 @@ # Copyright (c) 2001 by Jaroslav Kysela # -snd-ad1848-lib-objs := ad1848_lib.o snd-ad1848-objs := ad1848.o # Toplevel Module Dependency obj-$(CONFIG_SND_AD1848) += snd-ad1848.o -obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 17970c2f27e..b68d20edc20 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #define CRD_NAME "Generic AD1848/AD1847/CS4248" @@ -95,8 +95,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) if (!card) return -EINVAL; - error = snd_ad1848_create(card, port[n], irq[n], dma1[n], - thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, &chip); + error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, + thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, + 0, &chip); if (error < 0) goto out; diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index aa803d38a8a..e69de29bb2d 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -1,487 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of AD1848/AD1847/CS4248 - * - * - * 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 - * - */ - -#define SNDRV_MAIN_OBJECT_FILE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); -MODULE_LICENSE("GPL"); - -#if 0 -#define SNDRV_DEBUG_MCE -#endif - -/* - * Some variables - */ - -static unsigned char snd_ad1848_original_image[16] = -{ - 0x00, /* 00 - lic */ - 0x00, /* 01 - ric */ - 0x9f, /* 02 - la1ic */ - 0x9f, /* 03 - ra1ic */ - 0x9f, /* 04 - la2ic */ - 0x9f, /* 05 - ra2ic */ - 0xbf, /* 06 - loc */ - 0xbf, /* 07 - roc */ - 0x20, /* 08 - dfr */ - AD1848_AUTOCALIB, /* 09 - ic */ - 0x00, /* 0a - pc */ - 0x00, /* 0b - ti */ - 0x00, /* 0c - mi */ - 0x00, /* 0d - lbc */ - 0x00, /* 0e - dru */ - 0x00, /* 0f - drl */ -}; - -/* - * Basic I/O functions - */ - -static void snd_ad1848_wait(struct snd_wss *chip) -{ - int timeout; - - for (timeout = 250; timeout > 0; timeout--) { - if ((inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) == 0) - break; - udelay(100); - } -} - -void snd_ad1848_out(struct snd_wss *chip, - unsigned char reg, - unsigned char value) -{ - snd_ad1848_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) - snd_printk(KERN_WARNING "auto calibration time out - " - "reg = 0x%x, value = 0x%x\n", reg, value); -#endif - outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); - outb(chip->image[reg] = value, chip->port + CS4231P(REG)); - mb(); - snd_printdd("codec out - reg 0x%x = 0x%x\n", - chip->mce_bit | reg, value); -} - -EXPORT_SYMBOL(snd_ad1848_out); - -static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) -{ - snd_ad1848_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) - snd_printk(KERN_WARNING "auto calibration time out - " - "reg = 0x%x\n", reg); -#endif - outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); - mb(); - return inb(chip->port + CS4231P(REG)); -} - -#if 0 - -static void snd_ad1848_debug(struct snd_wss *chip) -{ - printk(KERN_DEBUG "AD1848 REGS: INDEX = 0x%02x ", inb(chip->port + CS4231P(REGSEL))); - printk(KERN_DEBUG " STATUS = 0x%02x\n", inb(chip->port + CS4231P(STATUS))); - printk(KERN_DEBUG " 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00)); - printk(KERN_DEBUG " 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08)); - printk(KERN_DEBUG " 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01)); - printk(KERN_DEBUG " 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09)); - printk(KERN_DEBUG " 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02)); - printk(KERN_DEBUG " 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a)); - printk(KERN_DEBUG " 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03)); - printk(KERN_DEBUG " 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b)); - printk(KERN_DEBUG " 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04)); - printk(KERN_DEBUG " 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c)); - printk(KERN_DEBUG " 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05)); - printk(KERN_DEBUG " 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d)); - printk(KERN_DEBUG " 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06)); - printk(KERN_DEBUG " 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e)); - printk(KERN_DEBUG " 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07)); - printk(KERN_DEBUG " 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f)); -} - -#endif - -/* - * AD1848 detection / MCE routines - */ - -static void snd_ad1848_mce_up(struct snd_wss *chip) -{ - unsigned long flags; - int timeout; - - snd_ad1848_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) - snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit |= AD1848_MCE; - timeout = inb(chip->port + CS4231P(REGSEL)); - if (timeout == 0x80) - snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); - if (!(timeout & AD1848_MCE)) - outb(chip->mce_bit | (timeout & 0x1f), - chip->port + CS4231P(REGSEL)); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_ad1848_mce_down(struct snd_wss *chip) -{ - unsigned long flags, timeout; - int reg; - - spin_lock_irqsave(&chip->reg_lock, flags); - for (timeout = 5; timeout > 0; timeout--) - inb(chip->port + CS4231P(REGSEL)); - /* end of cleanup sequence */ - for (timeout = 12000; - timeout > 0 && (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT); - timeout--) - udelay(100); - - snd_printdd("(1) timeout = %ld\n", timeout); - -#ifdef CONFIG_SND_DEBUG - if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) - snd_printk(KERN_WARNING - "mce_down [0x%lx] - auto calibration time out (0)\n", - chip->port + CS4231P(REGSEL)); -#endif - - chip->mce_bit &= ~AD1848_MCE; - reg = inb(chip->port + CS4231P(REGSEL)); - outb(chip->mce_bit | (reg & 0x1f), chip->port + CS4231P(REGSEL)); - if (reg == 0x80) - snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); - if ((reg & AD1848_MCE) == 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return; - } - - /* - * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low. - * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for - * the process to _start_, so it is important to wait at least that long - * before checking. Otherwise we might think AC has finished when it - * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles - * for ACI to drop. This gives a wait of at most 70 ms with a more - * typical value of 3-9 ms. - */ - timeout = jiffies + msecs_to_jiffies(250); - do { - spin_unlock_irqrestore(&chip->reg_lock, flags); - msleep(1); - spin_lock_irqsave(&chip->reg_lock, flags); - reg = snd_ad1848_in(chip, AD1848_TEST_INIT) & - AD1848_CALIB_IN_PROGRESS; - } while (reg && time_before(jiffies, timeout)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (reg) - snd_printk(KERN_ERR - "mce_down - auto calibration time out (2)\n"); - - snd_printdd("(4) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", - inb(chip->port + CS4231P(REGSEL))); -} - -static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) -{ - struct snd_wss *chip = dev_id; - - if ((chip->mode & WSS_MODE_PLAY) && chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream) - snd_pcm_period_elapsed(chip->capture_substream); - outb(0, chip->port + CS4231P(STATUS)); /* clear global interrupt bit */ - return IRQ_HANDLED; -} - -/* - - */ - -static void snd_ad1848_thinkpad_twiddle(struct snd_wss *chip, int on) -{ - int tmp; - - if (!chip->thinkpad_flag) return; - - outb(0x1c, AD1848_THINKPAD_CTL_PORT1); - tmp = inb(AD1848_THINKPAD_CTL_PORT2); - - if (on) - /* turn it on */ - tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT; - else - /* turn it off */ - tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT; - - outb(tmp, AD1848_THINKPAD_CTL_PORT2); - -} - -#ifdef CONFIG_PM -static void snd_ad1848_suspend(struct snd_wss *chip) -{ - snd_pcm_suspend_all(chip->pcm); - if (chip->thinkpad_flag) - snd_ad1848_thinkpad_twiddle(chip, 0); -} - -static void snd_ad1848_resume(struct snd_wss *chip) -{ - int i; - - if (chip->thinkpad_flag) - snd_ad1848_thinkpad_twiddle(chip, 1); - - /* clear any pendings IRQ */ - inb(chip->port + CS4231P(STATUS)); - outb(0, chip->port + CS4231P(STATUS)); - mb(); - - snd_ad1848_mce_down(chip); - for (i = 0; i < 16; i++) - snd_ad1848_out(chip, i, chip->image[i]); - snd_ad1848_mce_up(chip); - snd_ad1848_mce_down(chip); -} -#endif /* CONFIG_PM */ - -static int snd_ad1848_probe(struct snd_wss *chip) -{ - unsigned long flags; - int i, id, rev, ad1847; - unsigned char *ptr; - -#if 0 - snd_ad1848_debug(chip); -#endif - id = ad1847 = 0; - for (i = 0; i < 1000; i++) { - mb(); - if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) - udelay(500); - else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00); - snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa); - snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45); - rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT); - if (rev == 0x65) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - id = 1; - ad1847 = 1; - break; - } - if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - id = 1; - break; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - } - if (id != 1) - return -ENODEV; /* no valid device found */ - if (chip->hardware == WSS_HW_DETECT) { - if (ad1847) { - chip->hardware = WSS_HW_AD1847; - } else { - chip->hardware = WSS_HW_AD1848; - rev = snd_ad1848_in(chip, AD1848_MISC_INFO); - if (rev & 0x80) { - chip->hardware = WSS_HW_CS4248; - } else if ((rev & 0x0f) == 0x0a) { - snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40); - for (i = 0; i < 16; ++i) { - if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) { - chip->hardware = WSS_HW_CMI8330; - break; - } - } - snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00); - } - } - } - spin_lock_irqsave(&chip->reg_lock, flags); - inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ - outb(0, chip->port + CS4231P(STATUS)); - mb(); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->image[AD1848_MISC_INFO] = 0x00; - chip->image[AD1848_IFACE_CTRL] = - (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA; - ptr = (unsigned char *) &chip->image; - snd_ad1848_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */ - snd_ad1848_out(chip, i, *ptr++); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_up(chip); - /* init needed for WSS pcm */ - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | - AD1848_PLAYBACK_PIO | - AD1848_CAPTURE_ENABLE | - AD1848_CAPTURE_PIO | - AD1848_CALIB_MODE); - chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB; - snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_ad1848_mce_down(chip); - return 0; /* all things are ok.. */ -} - -/* - - */ - -static int snd_ad1848_free(struct snd_wss *chip) -{ - release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); - if (chip->dma1 >= 0) { - snd_dma_disable(chip->dma1); - free_dma(chip->dma1); - } - kfree(chip); - return 0; -} - -static int snd_ad1848_dev_free(struct snd_device *device) -{ - struct snd_wss *chip = device->device_data; - return snd_ad1848_free(chip); -} - -int snd_ad1848_create(struct snd_card *card, - unsigned long port, - int irq, int dma, - unsigned short hardware, - struct snd_wss **rchip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_ad1848_dev_free, - }; - struct snd_wss *chip; - int err; - - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->reg_lock); - chip->card = card; - chip->port = port; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - chip->single_dma = 1; - chip->hardware = hardware; - memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image)); - - if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) { - snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port); - snd_ad1848_free(chip); - return -EBUSY; - } - if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) { - snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq); - snd_ad1848_free(chip); - return -EBUSY; - } - chip->irq = irq; - if (request_dma(dma, "AD1848")) { - snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma); - snd_ad1848_free(chip); - return -EBUSY; - } - chip->dma1 = dma; - chip->dma2 = dma; - - if (hardware == WSS_HW_THINKPAD) { - chip->thinkpad_flag = 1; - chip->hardware = WSS_HW_DETECT; /* reset */ - snd_ad1848_thinkpad_twiddle(chip, 1); - } - - if (snd_ad1848_probe(chip) < 0) { - snd_ad1848_free(chip); - return -ENODEV; - } - - /* Register device */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_ad1848_free(chip); - return err; - } - -#ifdef CONFIG_PM - chip->suspend = snd_ad1848_suspend; - chip->resume = snd_ad1848_resume; -#endif - - *rchip = chip; - return 0; -} - -EXPORT_SYMBOL(snd_ad1848_create); - -/* - * INIT part - */ - -static int __init alsa_ad1848_init(void) -{ - return 0; -} - -static void __exit alsa_ad1848_exit(void) -{ -} - -module_init(alsa_ad1848_init) -module_exit(alsa_ad1848_exit) diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 6f7e8bb6ae6..e49aec700a5 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include @@ -180,9 +180,9 @@ WSS_DOUBLE("Master Playback Volume", 0, WSS_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), WSS_DOUBLE("PCM Playback Switch", 0, - AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), WSS_DOUBLE("PCM Playback Volume", 0, - AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), WSS_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), WSS_DOUBLE("Line Playback Volume", 0, @@ -489,12 +489,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) int i, err; acard = card->private_data; - if ((err = snd_ad1848_create(card, - wssport[dev] + 4, - wssirq[dev], - wssdma[dev], - WSS_HW_DETECT, - &acard->wss)) < 0) { + err = snd_wss_create(card, wssport[dev] + 4, -1, + wssirq[dev], + wssdma[dev], -1, + WSS_HW_DETECT, 0, &acard->wss); + if (err < 0) { snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); return err; } @@ -517,9 +516,10 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) return err; } - snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */ + snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) - snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]); + snd_wss_out(acard->wss, i, + snd_cmi8330_image[i - CMI8330_RMUX3D]); if ((err = snd_cmi8330_mixer(card, acard)) < 0) { snd_printk(KERN_ERR PFX "failed to create mixers\n"); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 561d4b3ed09..cb5f66bde5d 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -33,11 +33,7 @@ #include #include #include -#if defined(CS4231) || defined(OPTi93X) #include -#else -#include -#endif /* CS4231 */ #include #include #ifndef OPTi93X @@ -148,9 +144,7 @@ struct snd_opti9xx { long wss_base; int irq; int dma1; -#if defined(CS4231) || defined(OPTi93X) int dma2; -#endif /* CS4231 || OPTi93X */ long fm_port; @@ -225,9 +219,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, chip->wss_base = -1; chip->irq = -1; chip->dma1 = -1; -#if defined(CS4231) || defined (OPTi93X) chip->dma2 = -1; -#endif /* CS4231 || OPTi93X */ chip->fm_port = -1; chip->mpu_port = -1; chip->mpu_irq = -1; @@ -740,7 +732,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (error) return error; -#if defined(CS4231) || defined(OPTi93X) error = snd_wss_create(card, chip->wss_base + 4, -1, chip->irq, chip->dma1, chip->dma2, #ifdef CS4231 @@ -753,12 +744,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) return error; #ifdef OPTi93X chip->codec = codec; -#endif -#else - error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, - chip->dma1, WSS_HW_DETECT, &codec); - if (error < 0) - return error; #endif error = snd_wss_pcm(codec, 0, &pcm); if (error < 0) diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 2f89ecb95de..ca35924dc3b 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -548,8 +548,8 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) if (err < 0) goto err_unmap2; - err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, - WSS_HW_DETECT, &chip); + err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1, + WSS_HW_DETECT, 0, &chip); if (err < 0) goto err_unmap2; card->private_data = chip; diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index b43d6678ba2..2c7503bf127 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_DMA @@ -267,9 +267,10 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) goto _err; - if ((err = snd_ad1848_create(card, wssport[dev] + 4, - xirq, xdma1, - WSS_HW_DETECT, &chip)) < 0) + err = snd_wss_create(card, wssport[dev] + 4, -1, + xirq, xdma1, -1, + WSS_HW_DETECT, 0, &chip); + if (err < 0) goto _err; card->private_data = chip; @@ -331,8 +332,8 @@ static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) struct snd_wss *chip = card->private_data; chip->resume(chip); - snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); - snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); + snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); + snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 57d1e8ee6bb..a5602f515f4 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1073,7 +1073,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) struct snd_wss *chip = dev_id; unsigned char status; - status = snd_wss_in(chip, CS4231_IRQ_STATUS); + if (chip->hardware & WSS_HW_AD1848_MASK) + /* pretend it was the only possible irq for AD1848 */ + status = CS4231_PLAYBACK_IRQ; + else + status = snd_wss_in(chip, CS4231_IRQ_STATUS); if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); @@ -1105,7 +1109,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) } spin_lock(&chip->reg_lock); - snd_wss_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); + status = ~CS4231_ALL_IRQS | ~status; + if (chip->hardware & WSS_HW_AD1848_MASK) + wss_outb(chip, CS4231P(STATUS), 0); + else + snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -1137,36 +1145,112 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst */ -static int snd_wss_probe(struct snd_wss *chip) +static int snd_ad1848_probe(struct snd_wss *chip) { unsigned long flags; - int i, id, rev; - unsigned char *ptr; - unsigned int hw; + int i, id, rev, ad1847; -#if 0 - snd_wss_debug(chip); -#endif id = 0; - for (i = 0; i < 50; i++) { + ad1847 = 0; + for (i = 0; i < 1000; i++) { mb(); - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - udelay(2000); + if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT) + msleep(1); else { spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); - id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; + snd_wss_out(chip, CS4231_MISC_INFO, 0x00); + snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa); + snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45); + rev = snd_wss_in(chip, CS4231_RIGHT_INPUT); + if (rev == 0x65) { + spin_unlock_irqrestore(&chip->reg_lock, flags); + id = 1; + ad1847 = 1; + break; + } + if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa && + rev == 0x45) { + spin_unlock_irqrestore(&chip->reg_lock, flags); + id = 1; + break; + } spin_unlock_irqrestore(&chip->reg_lock, flags); - if (id == 0x0a) - break; /* this is valid value */ } } - snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); - if (id != 0x0a) + if (id != 1) return -ENODEV; /* no valid device found */ + id = 0; + if (chip->hardware == WSS_HW_DETECT) + id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848; + + spin_lock_irqsave(&chip->reg_lock, flags); + inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ + outb(0, chip->port + CS4231P(STATUS)); + mb(); + if (id == WSS_HW_AD1848) { + /* check if there are more than 16 registers */ + rev = snd_wss_in(chip, CS4231_MISC_INFO); + snd_wss_out(chip, CS4231_MISC_INFO, 0x40); + for (i = 0; i < 16; ++i) { + if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) { + id = WSS_HW_CMI8330; + break; + } + } + snd_wss_out(chip, CS4231_MISC_INFO, 0x00); + if (id != WSS_HW_CMI8330 && (rev & 0x80)) + id = WSS_HW_CS4248; + if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a) + id = 0; + } + if (id == WSS_HW_CMI8330) { + /* verify it is not CS4231 by changing the version register */ + /* on CMI8330 it is volume control register and can be set 0 */ + snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); + snd_wss_dout(chip, CS4231_VERSION, 0x00); + rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; + if (rev) + id = 0; + snd_wss_out(chip, CS4231_MISC_INFO, 0); + } + if (id) + chip->hardware = id; + + spin_unlock_irqrestore(&chip->reg_lock, flags); + return 0; /* all things are ok.. */ +} + +static int snd_wss_probe(struct snd_wss *chip) +{ + unsigned long flags; + int i, id, rev, regnum; + unsigned char *ptr; + unsigned int hw; + + id = snd_ad1848_probe(chip); + if (id < 0) + return id; hw = chip->hardware; if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { + for (i = 0; i < 50; i++) { + mb(); + if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) + msleep(2); + else { + spin_lock_irqsave(&chip->reg_lock, flags); + snd_wss_out(chip, CS4231_MISC_INFO, + CS4231_MODE2); + id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; + spin_unlock_irqrestore(&chip->reg_lock, flags); + if (id == 0x0a) + break; /* this is valid value */ + } + } + snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); + if (id != 0x0a) + return -ENODEV; /* no valid device found */ + rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); if (rev == 0x80) { @@ -1197,7 +1281,8 @@ static int snd_wss_probe(struct snd_wss *chip) mb(); spin_unlock_irqrestore(&chip->reg_lock, flags); - chip->image[CS4231_MISC_INFO] = CS4231_MODE2; + if (!(chip->hardware & WSS_HW_AD1848_MASK)) + chip->image[CS4231_MISC_INFO] = CS4231_MODE2; switch (chip->hardware) { case WSS_HW_INTERWAVE: chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; @@ -1223,9 +1308,10 @@ static int snd_wss_probe(struct snd_wss *chip) chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; } ptr = (unsigned char *) &chip->image; + regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; snd_wss_mce_down(chip); spin_lock_irqsave(&chip->reg_lock, flags); - for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ + for (i = 0; i < regnum; i++) /* ok.. fill all registers */ snd_wss_out(chip, i, *ptr++); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_up(chip); @@ -1635,6 +1721,10 @@ static int snd_wss_new(struct snd_card *card, else memcpy(&chip->image, &snd_wss_original_image, sizeof(snd_wss_original_image)); + if (chip->hardware & WSS_HW_AD1848_MASK) { + chip->image[CS4231_PIN_CTRL] = 0; + chip->image[CS4231_TEST_INIT] = 0; + } *rchip = chip; return 0; @@ -1662,7 +1752,7 @@ int snd_wss_create(struct snd_card *card, chip->dma1 = -1; chip->dma2 = -1; - chip->res_port = request_region(port, 4, "CS4231"); + chip->res_port = request_region(port, 4, "WSS"); if (!chip->res_port) { snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); snd_wss_free(chip); @@ -1681,20 +1771,20 @@ int snd_wss_create(struct snd_card *card, chip->cport = cport; if (!(hwshare & WSS_HWSHARE_IRQ)) if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, - "CS4231", (void *) chip)) { + "WSS", (void *) chip)) { snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); snd_wss_free(chip); return -EBUSY; } chip->irq = irq; - if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) { + if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) { snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); snd_wss_free(chip); return -EBUSY; } chip->dma1 = dma1; if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && - dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) { + dma2 >= 0 && request_dma(dma2, "WSS - 2")) { snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); snd_wss_free(chip); return -EBUSY; @@ -1705,6 +1795,12 @@ int snd_wss_create(struct snd_card *card, } else chip->dma2 = dma2; + if (hardware == WSS_HW_THINKPAD) { + chip->thinkpad_flag = 1; + chip->hardware = WSS_HW_DETECT; /* reset */ + snd_wss_thinkpad_twiddle(chip, 1); + } + /* global setup */ if (snd_wss_probe(chip) < 0) { snd_wss_free(chip); @@ -1775,12 +1871,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); - /* temporary */ - if (chip->hardware & WSS_HW_AD1848_MASK) { - chip->rate_constraint = snd_wss_xrate; - chip->set_playback_format = snd_wss_playback_format; - chip->set_capture_format = snd_wss_capture_format; - } /* global setup */ pcm->private_data = chip; pcm->info_flags = 0; -- GitLab From 31eca307fd9b1eb9ec138eb01bcfed16af60dabb Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 31 Jul 2008 21:11:46 +0200 Subject: [PATCH 0254/5416] ALSA: wss_lib: fix opti93x capture formats limitations Limit opti93x cards capture formats to only linear ones. Signed-off-by: Krzysztof Helt Reviewed-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/wss/wss_lib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index a5602f515f4..f2df77bd130 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1495,8 +1495,10 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream) /* hardware limitation of cheap chips */ if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239) - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE; + chip->hardware == WSS_HW_CS4239 || + chip->hardware == WSS_HW_OPTI93X) + runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE; snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); -- GitLab From a0d9274cd888ada59fe2734f45019d84bc40ac3d Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Mon, 4 Aug 2008 05:26:26 +0200 Subject: [PATCH 0255/5416] ALSA: wss_lib: opti92x-ad1848 WSS_HW_DETECT fix snd-opti92x-ad1848 mistakingly passes WSS_HW_OPTI93X currently. This fixes it as tested with a OPTi 82C929A/AD1848 card. Signed-off-by: Rene Herman Acked-by: Krzysztof Helt Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/opti9xx/opti92x-ad1848.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index cb5f66bde5d..19706b0d849 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -719,6 +719,8 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) chip->dma1 = dma1; #if defined(CS4231) || defined(OPTi93X) chip->dma2 = dma2; +#else + chip->dma2 = -1; #endif if (chip->wss_base == SNDRV_AUTO_PORT) { @@ -734,10 +736,10 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) error = snd_wss_create(card, chip->wss_base + 4, -1, chip->irq, chip->dma1, chip->dma2, -#ifdef CS4231 - WSS_HW_DETECT, 0, -#else /* OPTi93x */ +#ifdef OPTi93X WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, +#else + WSS_HW_DETECT, 0, #endif &codec); if (error < 0) -- GitLab From f1789f451d2ee18ff2bbc5afe78e1a7b9b714003 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 3 Aug 2008 17:57:21 +0200 Subject: [PATCH 0256/5416] ALSA: wss_lib: remove second mutexes initialization Remove initializations of spinlock and mutexes which are done earlier in snd_wss_new(). The snd_wss_new() is called from snd_wss_create(). Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/wss/wss_lib.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index f2df77bd130..fff8a3b79fd 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1866,10 +1866,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) if (err < 0) return err; - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->mce_mutex); - mutex_init(&chip->open_mutex); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); -- GitLab From ebae22590dccd2b8495c97e85290f5e07af7dc62 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Mon, 4 Aug 2008 01:23:43 +0200 Subject: [PATCH 0257/5416] ALSA: snd-cs4236: add Techmakers MF-4236PW PnP card ID Add the Techmakers MF-4236PW (Crystal CX4236B-XQ3) PnP card ID. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/cs423x/cs4236.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 3ff0f122991..91f9c15d3e3 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -239,6 +239,8 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = { { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, /* Gallant SC-70P */ { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, + /* Techmakers MF-4236PW */ + { .id = "CSCa736", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, /* TerraTec AudioSystem EWS64XL - CS4236B */ { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } }, /* TerraTec AudioSystem EWS64XL - CS4236B */ -- GitLab From 6ddfa7432adc24c7471abe9d338a78540d0d025b Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Tue, 5 Aug 2008 09:33:33 +0200 Subject: [PATCH 0258/5416] ALSA: wss_lib: fix AZT2320 probe. After the transition from cs4321_lib to wss_lib, azt2320 probe visits snd_ad1848_probe during detection. It expects register 0 (LEFT_INPUT) to be able to retain the value 0xaa during detection but AZT2320 does not support MIC gain meaning it reads back as 0x8a instead. Signed-off-by: Rene Herman Acked-by: Krzysztof Helt Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/wss/wss_lib.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index fff8a3b79fd..866e8686dbe 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1168,11 +1168,13 @@ static int snd_ad1848_probe(struct snd_wss *chip) ad1847 = 1; break; } - if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa && - rev == 0x45) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - id = 1; - break; + if (rev == 0x45) { + rev = snd_wss_in(chip, CS4231_LEFT_INPUT); + if (rev == 0xaa || rev == 0x8a) { + spin_unlock_irqrestore(&chip->reg_lock, flags); + id = 1; + break; + } } spin_unlock_irqrestore(&chip->reg_lock, flags); } -- GitLab From e8f9ae2a4a0654e7798b8c0ae956e3f0fdc23c8d Mon Sep 17 00:00:00 2001 From: Pascal Terjan Date: Mon, 4 Aug 2008 14:36:05 +0200 Subject: [PATCH 0259/5416] ALSA: hda - Fix sound on NEC Versa S9100 This patch adds sound support for NEC Versa S9100 With it, we get sound on the internal speaker and headphone (with automute working) while there is no sound by default. External mic also works fine but I don't know if there is an internal one (if there is an internal mic it does not work currently), and I had to send back the hardware. Signed-off-by: Pascal Terjan Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 38017a129ba..4bd26725355 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -100,6 +100,7 @@ enum { ALC262_BENQ_T31, ALC262_ULTRA, ALC262_LENOVO_3000, + ALC262_NEC, ALC262_AUTO, ALC262_MODEL_LAST /* last tag */ }; @@ -8947,6 +8948,41 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec, alc262_hippo1_automute(codec); } +/* + * nec model + * 0x15 = headphone + * 0x16 = internal speaker + * 0x18 = external mic + */ + +static struct snd_kcontrol_new alc262_nec_mixer[] = { + HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), + { } /* end */ +}; + +static struct hda_verb alc262_nec_verbs[] = { + /* Unmute Speaker */ + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + + /* Headphone */ + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + + /* External mic to headphone */ + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* External mic to speaker */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {} +}; + /* * fujitsu model * 0x14 = headphone/spdif-out, 0x15 = internal speaker, @@ -9731,11 +9767,13 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { [ALC262_SONY_ASSAMD] = "sony-assamd", [ALC262_ULTRA] = "ultra", [ALC262_LENOVO_3000] = "lenovo-3000", + [ALC262_NEC] = "nec", [ALC262_AUTO] = "auto", }; static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), + SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), @@ -9946,6 +9984,16 @@ static struct alc_config_preset alc262_presets[] = { .input_mux = &alc262_fujitsu_capture_source, .unsol_event = alc262_lenovo_3000_unsol_event, }, + [ALC262_NEC] = { + .mixers = { alc262_nec_mixer }, + .init_verbs = { alc262_nec_verbs }, + .num_dacs = ARRAY_SIZE(alc262_dac_nids), + .dac_nids = alc262_dac_nids, + .hp_nid = 0x03, + .num_channel_mode = ARRAY_SIZE(alc262_modes), + .channel_mode = alc262_modes, + .input_mux = &alc262_capture_source, + }, }; static int patch_alc262(struct hda_codec *codec) -- GitLab From 8c650087992f1d7a3a7be2e632f4e85a52d20619 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 4 Aug 2008 10:39:59 -0300 Subject: [PATCH 0260/5416] ALSA: hda: Add support for ECS/PC Chips boards with Sigmatel codecs Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) and CDI Brasil (www.cdibrasil.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 23a7b2228e3..fac6b3ca5fe 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -110,6 +110,7 @@ enum { STAC_MACBOOK_PRO_V2, STAC_IMAC_INTEL, STAC_IMAC_INTEL_20, + STAC_ECS_202, STAC_922X_DELL_D81, STAC_922X_DELL_D82, STAC_922X_DELL_M81, @@ -1586,6 +1587,11 @@ static unsigned int intel_mac_v5_pin_configs[10] = { 0x400000fc, 0x400000fb, }; +static unsigned int ecs202_pin_configs[10] = { + 0x0221401f, 0x02a19020, 0x01a19020, 0x01114010, + 0x408000f0, 0x01813022, 0x074510a0, 0x40c400f1, + 0x9037012e, 0x40e000f2, +}; static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { [STAC_D945_REF] = ref922x_pin_configs, @@ -1604,6 +1610,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, + [STAC_ECS_202] = ecs202_pin_configs, [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs, [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs, [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs, @@ -1627,6 +1634,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = { [STAC_MACBOOK_PRO_V2] = "macbook-pro", [STAC_IMAC_INTEL] = "imac-intel", [STAC_IMAC_INTEL_20] = "imac-intel-20", + [STAC_ECS_202] = "ecs202", [STAC_922X_DELL_D81] = "dell-d81", [STAC_922X_DELL_D82] = "dell-d82", [STAC_922X_DELL_M81] = "dell-m81", @@ -1713,6 +1721,33 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { "unknown Dell", STAC_922X_DELL_D81), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, "Dell XPS M1210", STAC_922X_DELL_M82), + /* ECS/PC Chips boards */ + SND_PCI_QUIRK(0x1019, 0x2144, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2608, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2633, + "ECS/PC chips P17G/1333", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2811, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2812, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2813, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2814, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2815, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2816, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2817, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2818, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2819, + "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2820, + "ECS/PC chips", STAC_ECS_202), {} /* terminator */ }; -- GitLab From 0e0e16a87a0b973702feb572c2552d82e1aec5b9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Aug 2008 12:06:45 +0100 Subject: [PATCH 0261/5416] ALSA: ASoC: Add WM8900 CODEC driver The WM8900 is designed for portable multimedia applications requiring low power consumption, high performance audio and a compact form factor providing: - 24 bit stereo ADC and DAC - Microphone and line inputs - Line outputs - Class G headphone amplifier Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm8900.c | 1542 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm8900.h | 64 ++ 4 files changed, 1612 insertions(+) create mode 100644 sound/soc/codecs/wm8900.c create mode 100644 sound/soc/codecs/wm8900.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1c934230494..d7bacf6c529 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -8,6 +8,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8731 select SND_SOC_WM8750 select SND_SOC_WM8753 + select SND_SOC_WM8900 select SND_SOC_WM8990 select SND_SOC_CS4270 select SND_SOC_TLV320AIC26 @@ -46,6 +47,9 @@ config SND_SOC_WM8750 config SND_SOC_WM8753 tristate +config SND_SOC_WM8900 + tristate + config SND_SOC_WM8990 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 409e4dd1789..98808d945de 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -6,6 +6,7 @@ snd-soc-wm8510-objs := wm8510.o snd-soc-wm8731-objs := wm8731.o snd-soc-wm8750-objs := wm8750.o snd-soc-wm8753-objs := wm8753.o +snd-soc-wm8900-objs := wm8900.o snd-soc-wm8990-objs := wm8990.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o @@ -21,6 +22,7 @@ obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o +obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c new file mode 100644 index 00000000000..0b8c6d38b48 --- /dev/null +++ b/sound/soc/codecs/wm8900.c @@ -0,0 +1,1542 @@ +/* + * wm8900.c -- WM8900 ALSA Soc Audio driver + * + * Copyright 2007, 2008 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * TODO: + * - Tristating. + * - TDM. + * - Jack detect. + * - FLL source configuration, currently only MCLK is supported. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm8900.h" + +/* WM8900 register space */ +#define WM8900_REG_RESET 0x0 +#define WM8900_REG_ID 0x0 +#define WM8900_REG_POWER1 0x1 +#define WM8900_REG_POWER2 0x2 +#define WM8900_REG_POWER3 0x3 +#define WM8900_REG_AUDIO1 0x4 +#define WM8900_REG_AUDIO2 0x5 +#define WM8900_REG_CLOCKING1 0x6 +#define WM8900_REG_CLOCKING2 0x7 +#define WM8900_REG_AUDIO3 0x8 +#define WM8900_REG_AUDIO4 0x9 +#define WM8900_REG_DACCTRL 0xa +#define WM8900_REG_LDAC_DV 0xb +#define WM8900_REG_RDAC_DV 0xc +#define WM8900_REG_SIDETONE 0xd +#define WM8900_REG_ADCCTRL 0xe +#define WM8900_REG_LADC_DV 0xf +#define WM8900_REG_RADC_DV 0x10 +#define WM8900_REG_GPIO 0x12 +#define WM8900_REG_INCTL 0x15 +#define WM8900_REG_LINVOL 0x16 +#define WM8900_REG_RINVOL 0x17 +#define WM8900_REG_INBOOSTMIX1 0x18 +#define WM8900_REG_INBOOSTMIX2 0x19 +#define WM8900_REG_ADCPATH 0x1a +#define WM8900_REG_AUXBOOST 0x1b +#define WM8900_REG_ADDCTL 0x1e +#define WM8900_REG_FLLCTL1 0x24 +#define WM8900_REG_FLLCTL2 0x25 +#define WM8900_REG_FLLCTL3 0x26 +#define WM8900_REG_FLLCTL4 0x27 +#define WM8900_REG_FLLCTL5 0x28 +#define WM8900_REG_FLLCTL6 0x29 +#define WM8900_REG_LOUTMIXCTL1 0x2c +#define WM8900_REG_ROUTMIXCTL1 0x2d +#define WM8900_REG_BYPASS1 0x2e +#define WM8900_REG_BYPASS2 0x2f +#define WM8900_REG_AUXOUT_CTL 0x30 +#define WM8900_REG_LOUT1CTL 0x33 +#define WM8900_REG_ROUT1CTL 0x34 +#define WM8900_REG_LOUT2CTL 0x35 +#define WM8900_REG_ROUT2CTL 0x36 +#define WM8900_REG_HPCTL1 0x3a +#define WM8900_REG_OUTBIASCTL 0x73 + +#define WM8900_MAXREG 0x80 + +#define WM8900_REG_ADDCTL_OUT1_DIS 0x80 +#define WM8900_REG_ADDCTL_OUT2_DIS 0x40 +#define WM8900_REG_ADDCTL_VMID_DIS 0x20 +#define WM8900_REG_ADDCTL_BIAS_SRC 0x10 +#define WM8900_REG_ADDCTL_VMID_SOFTST 0x04 +#define WM8900_REG_ADDCTL_TEMP_SD 0x02 + +#define WM8900_REG_GPIO_TEMP_ENA 0x2 + +#define WM8900_REG_POWER1_STARTUP_BIAS_ENA 0x0100 +#define WM8900_REG_POWER1_BIAS_ENA 0x0008 +#define WM8900_REG_POWER1_VMID_BUF_ENA 0x0004 +#define WM8900_REG_POWER1_FLL_ENA 0x0040 + +#define WM8900_REG_POWER2_SYSCLK_ENA 0x8000 +#define WM8900_REG_POWER2_ADCL_ENA 0x0002 +#define WM8900_REG_POWER2_ADCR_ENA 0x0001 + +#define WM8900_REG_POWER3_DACL_ENA 0x0002 +#define WM8900_REG_POWER3_DACR_ENA 0x0001 + +#define WM8900_REG_AUDIO1_AIF_FMT_MASK 0x0018 +#define WM8900_REG_AUDIO1_LRCLK_INV 0x0080 +#define WM8900_REG_AUDIO1_BCLK_INV 0x0100 + +#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1 +#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100 +#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e) +#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000) + +#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0 +#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c + +#define WM8900_REG_DACCTRL_MUTE 0x004 +#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 + +#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 + +#define WM8900_REG_AUDIO4_DACLRC_DIR 0x0800 + +#define WM8900_REG_FLLCTL1_OSC_ENA 0x100 + +#define WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF 0x100 + +#define WM8900_REG_HPCTL1_HP_IPSTAGE_ENA 0x80 +#define WM8900_REG_HPCTL1_HP_OPSTAGE_ENA 0x40 +#define WM8900_REG_HPCTL1_HP_CLAMP_IP 0x20 +#define WM8900_REG_HPCTL1_HP_CLAMP_OP 0x10 +#define WM8900_REG_HPCTL1_HP_SHORT 0x08 +#define WM8900_REG_HPCTL1_HP_SHORT2 0x04 + +#define WM8900_LRC_MASK 0xfc00 + +struct snd_soc_codec_device soc_codec_dev_wm8900; + +struct wm8900_priv { + u32 fll_in; /* FLL input frequency */ + u32 fll_out; /* FLL output frequency */ +}; + +/* + * wm8900 register cache. We can't read the entire register space and we + * have slow control buses so we cache the registers. + */ +static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { + 0x8900, 0x0000, + 0xc000, 0x0000, + 0x4050, 0x4000, + 0x0008, 0x0000, + 0x0040, 0x0040, + 0x1004, 0x00c0, + 0x00c0, 0x0000, + 0x0100, 0x00c0, + 0x00c0, 0x0000, + 0xb001, 0x0000, + 0x0000, 0x0044, + 0x004c, 0x004c, + 0x0044, 0x0044, + 0x0000, 0x0044, + 0x0000, 0x0000, + 0x0002, 0x0000, + 0x0000, 0x0000, + 0x0000, 0x0000, + 0x0008, 0x0000, + 0x0000, 0x0008, + 0x0097, 0x0100, + 0x0000, 0x0000, + 0x0050, 0x0050, + 0x0055, 0x0055, + 0x0055, 0x0000, + 0x0000, 0x0079, + 0x0079, 0x0079, + 0x0079, 0x0000, + /* Remaining registers all zero */ +}; + +/* + * read wm8900 register cache + */ +static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= WM8900_MAXREG); + + if (reg == WM8900_REG_ID) + return 0; + + return cache[reg]; +} + +/* + * write wm8900 register cache + */ +static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= WM8900_MAXREG); + + cache[reg] = value; +} + +/* + * write to the WM8900 register space + */ +static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[3]; + + if (value == wm8900_read_reg_cache(codec, reg)) + return 0; + + /* data is + * D15..D9 WM8900 register offset + * D8...D0 register data + */ + data[0] = reg; + data[1] = value >> 8; + data[2] = value & 0x00ff; + + wm8900_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 3) == 3) + return 0; + else + return -EIO; +} + +/* + * Read from the wm8900. + */ +static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg) +{ + struct i2c_msg xfer[2]; + u16 data; + int ret; + struct i2c_client *client = codec->control_data; + + BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1); + + /* Write register */ + xfer[0].addr = client->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = ® + + /* Read data */ + xfer[1].addr = client->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (u8 *)&data; + + ret = i2c_transfer(client->adapter, xfer, 2); + if (ret != 2) { + printk(KERN_CRIT "i2c_transfer returned %d\n", ret); + return 0; + } + + return (data >> 8) | ((data & 0xff) << 8); +} + +/* + * Read from the WM8900 register space. Most registers can't be read + * and are therefore supplied from cache. + */ +static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg) +{ + switch (reg) { + case WM8900_REG_ID: + return wm8900_chip_read(codec, reg); + default: + return wm8900_read_reg_cache(codec, reg); + } +} + +static void wm8900_reset(struct snd_soc_codec *codec) +{ + wm8900_write(codec, WM8900_REG_RESET, 0); + + memcpy(codec->reg_cache, wm8900_reg_defaults, + sizeof(codec->reg_cache)); +} + +static int wm8900_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Clamp headphone outputs */ + hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP | + WM8900_REG_HPCTL1_HP_CLAMP_OP; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + break; + + case SND_SOC_DAPM_POST_PMU: + /* Enable the input stage */ + hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP; + hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT | + WM8900_REG_HPCTL1_HP_SHORT2 | + WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + + msleep(400); + + /* Enable the output stage */ + hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP; + hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + + /* Remove the shorts */ + hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + break; + + case SND_SOC_DAPM_PRE_PMD: + /* Short the output */ + hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + + /* Disable the output stage */ + hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + + /* Clamp the outputs and power down input */ + hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP | + WM8900_REG_HPCTL1_HP_CLAMP_OP; + hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); + break; + + case SND_SOC_DAPM_POST_PMD: + /* Disable everything */ + wm8900_write(codec, WM8900_REG_HPCTL1, 0); + break; + + default: + BUG(); + } + + return 0; +} + +static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0); + +static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0); + +static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0); + +static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0); + +static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); + +static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1); + +static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0); + +static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); + +static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" }; + +static const struct soc_enum mic_bias_level = +SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt); + +static const char *dac_mute_rate_txt[] = { "Fast", "Slow" }; + +static const struct soc_enum dac_mute_rate = +SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt); + +static const char *dac_deemphasis_txt[] = { + "Disabled", "32kHz", "44.1kHz", "48kHz" +}; + +static const struct soc_enum dac_deemphasis = +SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt); + +static const char *adc_hpf_cut_txt[] = { + "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3" +}; + +static const struct soc_enum adc_hpf_cut = +SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt); + +static const char *lr_txt[] = { + "Left", "Right" +}; + +static const struct soc_enum aifl_src = +SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt); + +static const struct soc_enum aifr_src = +SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt); + +static const struct soc_enum dacl_src = +SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt); + +static const struct soc_enum dacr_src = +SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt); + +static const char *sidetone_txt[] = { + "Disabled", "Left ADC", "Right ADC" +}; + +static const struct soc_enum dacl_sidetone = +SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt); + +static const struct soc_enum dacr_sidetone = +SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt); + +static const struct snd_kcontrol_new wm8900_snd_controls[] = { +SOC_ENUM("Mic Bias Level", mic_bias_level), + +SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0, + in_pga_tlv), +SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1), +SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0), + +SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0, + in_pga_tlv), +SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1), +SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0), + +SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1), +SOC_ENUM("DAC Mute Rate", dac_mute_rate), +SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), +SOC_ENUM("DAC Deemphasis", dac_deemphasis), +SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0), +SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, + 12, 1, 0), + +SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0), +SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut), +SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0), +SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0, + adc_svol_tlv), +SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0, + adc_svol_tlv), +SOC_ENUM("Left Digital Audio Source", aifl_src), +SOC_ENUM("Right Digital Audio Source", aifr_src), + +SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0, + dac_boost_tlv), +SOC_ENUM("Left DAC Source", dacl_src), +SOC_ENUM("Right DAC Source", dacr_src), +SOC_ENUM("Left DAC Sidetone", dacl_sidetone), +SOC_ENUM("Right DAC Sidetone", dacr_sidetone), +SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0), + +SOC_DOUBLE_R_TLV("Digital Playback Volume", + WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV, + 1, 96, 0, dac_tlv), +SOC_DOUBLE_R_TLV("Digital Capture Volume", + WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv), + +SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0, + out_mix_tlv), + +SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0, + out_mix_tlv), +SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0, + out_mix_tlv), + +SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0, + in_boost_tlv), +SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0, + in_boost_tlv), +SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0, + in_boost_tlv), +SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0, + in_boost_tlv), +SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0, + in_boost_tlv), +SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0, + in_boost_tlv), + +SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, + 0, 63, 0, out_pga_tlv), +SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, + 6, 1, 1), +SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, + 7, 1, 0), + +SOC_DOUBLE_R_TLV("LINEOUT2 Volume", + WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, + 0, 63, 0, out_pga_tlv), +SOC_DOUBLE_R("LINEOUT2 Switch", + WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1), +SOC_DOUBLE_R("LINEOUT2 ZC Switch", + WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0), +SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, + 0, 1, 1), + +}; + +/* add non dapm controls */ +static int wm8900_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&wm8900_snd_controls[i], + codec, NULL)); + if (err < 0) + return err; + } + + return 0; +} + +static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = +SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); + +static const struct snd_kcontrol_new wm8900_dapm_routput2_control = +SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0); + +static const struct snd_kcontrol_new wm8900_loutmix_controls[] = { +SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0), +SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0), +SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0), +SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0), +SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0), +}; + +static const struct snd_kcontrol_new wm8900_routmix_controls[] = { +SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0), +SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0), +SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0), +SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0), +SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0), +}; + +static const struct snd_kcontrol_new wm8900_linmix_controls[] = { +SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1), +SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1), +SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1), +SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0), +}; + +static const struct snd_kcontrol_new wm8900_rinmix_controls[] = { +SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1), +SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1), +SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1), +SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0), +}; + +static const struct snd_kcontrol_new wm8900_linpga_controls[] = { +SOC_DAPM_SINGLE("LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0), +SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0), +SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0), +}; + +static const struct snd_kcontrol_new wm8900_rinpga_controls[] = { +SOC_DAPM_SINGLE("RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0), +SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), +SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), +}; + +static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; + +static const struct soc_enum wm8900_lineout2_lp_mux = +SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux); + +static const struct snd_kcontrol_new wm8900_lineout2_lp = +SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); + +static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = { + +/* Externally visible pins */ +SND_SOC_DAPM_OUTPUT("LINEOUT1L"), +SND_SOC_DAPM_OUTPUT("LINEOUT1R"), +SND_SOC_DAPM_OUTPUT("LINEOUT2L"), +SND_SOC_DAPM_OUTPUT("LINEOUT2R"), +SND_SOC_DAPM_OUTPUT("HP_L"), +SND_SOC_DAPM_OUTPUT("HP_R"), + +SND_SOC_DAPM_INPUT("RINPUT1"), +SND_SOC_DAPM_INPUT("LINPUT1"), +SND_SOC_DAPM_INPUT("RINPUT2"), +SND_SOC_DAPM_INPUT("LINPUT2"), +SND_SOC_DAPM_INPUT("RINPUT3"), +SND_SOC_DAPM_INPUT("LINPUT3"), +SND_SOC_DAPM_INPUT("AUX"), + +SND_SOC_DAPM_VMID("VMID"), + +/* Input */ +SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0, + wm8900_linpga_controls, + ARRAY_SIZE(wm8900_linpga_controls)), +SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0, + wm8900_rinpga_controls, + ARRAY_SIZE(wm8900_rinpga_controls)), + +SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0, + wm8900_linmix_controls, + ARRAY_SIZE(wm8900_linmix_controls)), +SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0, + wm8900_rinmix_controls, + ARRAY_SIZE(wm8900_rinmix_controls)), + +SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0), + +SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0), +SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0), + +/* Output */ +SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0), +SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0), + +SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0, + wm8900_hp_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0), +SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0), + +SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp), +SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0), +SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0), + +SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0, + wm8900_loutmix_controls, + ARRAY_SIZE(wm8900_loutmix_controls)), +SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0, + wm8900_routmix_controls, + ARRAY_SIZE(wm8900_routmix_controls)), +}; + +/* Target, Path, Source */ +static const struct snd_soc_dapm_route audio_map[] = { +/* Inputs */ +{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"}, +{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"}, +{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"}, + +{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"}, +{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"}, +{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"}, + +{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"}, +{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"}, +{"Left Input Mixer", "AUX Switch", "AUX"}, +{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"}, + +{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"}, +{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"}, +{"Right Input Mixer", "AUX Switch", "AUX"}, +{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"}, + +{"ADCL", NULL, "Left Input Mixer"}, +{"ADCR", NULL, "Right Input Mixer"}, + +/* Outputs */ +{"LINEOUT1L", NULL, "LINEOUT1L PGA"}, +{"LINEOUT1L PGA", NULL, "Left Output Mixer"}, +{"LINEOUT1R", NULL, "LINEOUT1R PGA"}, +{"LINEOUT1R PGA", NULL, "Right Output Mixer"}, + +{"LINEOUT2L PGA", NULL, "Left Output Mixer"}, +{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"}, +{"LINEOUT2 LP", "Enabled", "Left Output Mixer"}, +{"LINEOUT2L", NULL, "LINEOUT2 LP"}, + +{"LINEOUT2R PGA", NULL, "Right Output Mixer"}, +{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"}, +{"LINEOUT2 LP", "Enabled", "Right Output Mixer"}, +{"LINEOUT2R", NULL, "LINEOUT2 LP"}, + +{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"}, +{"Left Output Mixer", "AUX Bypass Switch", "AUX"}, +{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"}, +{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"}, +{"Left Output Mixer", "DACL Switch", "DACL"}, + +{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"}, +{"Right Output Mixer", "AUX Bypass Switch", "AUX"}, +{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"}, +{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"}, +{"Right Output Mixer", "DACR Switch", "DACR"}, + +/* Note that the headphone output stage needs to be connected + * externally to LINEOUT2 via DC blocking capacitors. Other + * configurations are not supported. + * + * Note also that left and right headphone paths are treated as a + * mono path. + */ +{"Headphone Amplifier", NULL, "LINEOUT2 LP"}, +{"Headphone Amplifier", NULL, "LINEOUT2 LP"}, +{"HP_L", NULL, "Headphone Amplifier"}, +{"HP_R", NULL, "Headphone Amplifier"}, +}; + +static int wm8900_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets, + ARRAY_SIZE(wm8900_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_new_widgets(codec); + + return 0; +} + +static int wm8900_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + u16 reg; + + reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + reg |= 0x20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + reg |= 0x40; + break; + case SNDRV_PCM_FORMAT_S32_LE: + reg |= 0x60; + break; + default: + return -EINVAL; + } + + wm8900_write(codec, WM8900_REG_AUDIO1, reg); + + return 0; +} + +/* FLL divisors */ +struct _fll_div { + u16 fll_ratio; + u16 fllclk_div; + u16 fll_slow_lock_ref; + u16 n; + u16 k; +}; + +/* The size in bits of the FLL divide multiplied by 10 + * to allow rounding later */ +#define FIXED_FLL_SIZE ((1 << 16) * 10) + +static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, + unsigned int Fout) +{ + u64 Kpart; + unsigned int K, Ndiv, Nmod, target; + unsigned int div; + + BUG_ON(!Fout); + + /* The FLL must run at 90-100MHz which is then scaled down to + * the output value by FLLCLK_DIV. */ + target = Fout; + div = 1; + while (target < 90000000) { + div *= 2; + target *= 2; + } + + if (target > 100000000) + printk(KERN_WARNING "wm8900: FLL rate %d out of range, Fref=%d" + " Fout=%d\n", target, Fref, Fout); + if (div > 32) { + printk(KERN_ERR "wm8900: Invalid FLL division rate %u, " + "Fref=%d, Fout=%d, target=%d\n", + div, Fref, Fout, target); + return -EINVAL; + } + + fll_div->fllclk_div = div >> 2; + + if (Fref < 48000) + fll_div->fll_slow_lock_ref = 1; + else + fll_div->fll_slow_lock_ref = 0; + + Ndiv = target / Fref; + + if (Fref < 1000000) + fll_div->fll_ratio = 8; + else + fll_div->fll_ratio = 1; + + fll_div->n = Ndiv / fll_div->fll_ratio; + Nmod = (target / fll_div->fll_ratio) % Fref; + + /* Calculate fractional part - scale up so we can round. */ + Kpart = FIXED_FLL_SIZE * (long long)Nmod; + + do_div(Kpart, Fref); + + K = Kpart & 0xFFFFFFFF; + + if ((K % 10) >= 5) + K += 5; + + /* Move down to proper range now rounding is done */ + fll_div->k = K / 10; + + BUG_ON(target != Fout * (fll_div->fllclk_div << 2)); + BUG_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n); + + return 0; +} + +static int wm8900_set_fll(struct snd_soc_codec *codec, + int fll_id, unsigned int freq_in, unsigned int freq_out) +{ + struct wm8900_priv *wm8900 = codec->private_data; + struct _fll_div fll_div; + unsigned int reg; + + if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out) + return 0; + + /* The digital side should be disabled during any change. */ + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, + reg & (~WM8900_REG_POWER1_FLL_ENA)); + + /* Disable the FLL? */ + if (!freq_in || !freq_out) { + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, + reg & (~WM8900_REG_CLOCKING1_MCLK_SRC)); + + reg = wm8900_read(codec, WM8900_REG_FLLCTL1); + wm8900_write(codec, WM8900_REG_FLLCTL1, + reg & (~WM8900_REG_FLLCTL1_OSC_ENA)); + + wm8900->fll_in = freq_in; + wm8900->fll_out = freq_out; + + return 0; + } + + if (fll_factors(&fll_div, freq_in, freq_out) != 0) + goto reenable; + + wm8900->fll_in = freq_in; + wm8900->fll_out = freq_out; + + /* The osclilator *MUST* be enabled before we enable the + * digital circuit. */ + wm8900_write(codec, WM8900_REG_FLLCTL1, + fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA); + + wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); + wm8900_write(codec, WM8900_REG_FLLCTL5, + (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f)); + + if (fll_div.k) { + wm8900_write(codec, WM8900_REG_FLLCTL2, + (fll_div.k >> 8) | 0x100); + wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); + } else + wm8900_write(codec, WM8900_REG_FLLCTL2, 0); + + if (fll_div.fll_slow_lock_ref) + wm8900_write(codec, WM8900_REG_FLLCTL6, + WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF); + else + wm8900_write(codec, WM8900_REG_FLLCTL6, 0); + + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, + reg | WM8900_REG_POWER1_FLL_ENA); + +reenable: + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, + reg | WM8900_REG_CLOCKING1_MCLK_SRC); + + return 0; +} + +static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, + int pll_id, unsigned int freq_in, unsigned int freq_out) +{ + return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); +} + +static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai, + int div_id, int div) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int reg; + + switch (div_id) { + case WM8900_BCLK_DIV: + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, + div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK)); + break; + case WM8900_OPCLK_DIV: + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, + div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK)); + break; + case WM8900_DAC_LRCLK: + reg = wm8900_read(codec, WM8900_REG_AUDIO4); + wm8900_write(codec, WM8900_REG_AUDIO4, + div | (reg & WM8900_LRC_MASK)); + break; + case WM8900_ADC_LRCLK: + reg = wm8900_read(codec, WM8900_REG_AUDIO3); + wm8900_write(codec, WM8900_REG_AUDIO3, + div | (reg & WM8900_LRC_MASK)); + break; + case WM8900_DAC_CLKDIV: + reg = wm8900_read(codec, WM8900_REG_CLOCKING2); + wm8900_write(codec, WM8900_REG_CLOCKING2, + div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV)); + break; + case WM8900_ADC_CLKDIV: + reg = wm8900_read(codec, WM8900_REG_CLOCKING2); + wm8900_write(codec, WM8900_REG_CLOCKING2, + div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV)); + break; + case WM8900_LRCLK_MODE: + reg = wm8900_read(codec, WM8900_REG_DACCTRL); + wm8900_write(codec, WM8900_REG_DACCTRL, + div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE)); + break; + default: + return -EINVAL; + } + + return 0; +} + + +static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int clocking1, aif1, aif3, aif4; + + clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1); + aif1 = wm8900_read(codec, WM8900_REG_AUDIO1); + aif3 = wm8900_read(codec, WM8900_REG_AUDIO3); + aif4 = wm8900_read(codec, WM8900_REG_AUDIO4); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; + aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; + aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; + break; + case SND_SOC_DAIFMT_CBS_CFM: + clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; + aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; + aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; + break; + case SND_SOC_DAIFMT_CBM_CFM: + clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; + aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; + aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; + aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; + aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK; + aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; + break; + case SND_SOC_DAIFMT_DSP_B: + aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK; + aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; + break; + case SND_SOC_DAIFMT_I2S: + aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; + aif1 |= 0x10; + break; + case SND_SOC_DAIFMT_RIGHT_J: + aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; + break; + case SND_SOC_DAIFMT_LEFT_J: + aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; + aif1 |= 0x8; + break; + default: + return -EINVAL; + } + + /* Clock inversion */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + /* frame inversion not valid for DSP modes */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + aif1 |= WM8900_REG_AUDIO1_BCLK_INV; + break; + default: + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; + aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; + break; + case SND_SOC_DAIFMT_IB_IF: + aif1 |= WM8900_REG_AUDIO1_BCLK_INV; + aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + aif1 |= WM8900_REG_AUDIO1_BCLK_INV; + aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; + aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1); + wm8900_write(codec, WM8900_REG_AUDIO1, aif1); + wm8900_write(codec, WM8900_REG_AUDIO3, aif3); + wm8900_write(codec, WM8900_REG_AUDIO4, aif4); + + return 0; +} + +static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 reg; + + reg = wm8900_read(codec, WM8900_REG_DACCTRL); + + if (mute) + reg |= WM8900_REG_DACCTRL_MUTE; + else + reg &= ~WM8900_REG_DACCTRL_MUTE; + + wm8900_write(codec, WM8900_REG_DACCTRL, reg); + + return 0; +} + +#define WM8900_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define WM8900_PCM_FORMATS \ + (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ + SNDRV_PCM_FORMAT_S24_LE) + +struct snd_soc_dai wm8900_dai = { + .name = "WM8900 HiFi", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8900_RATES, + .formats = WM8900_PCM_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8900_RATES, + .formats = WM8900_PCM_FORMATS, + }, + .ops = { + .hw_params = wm8900_hw_params, + }, + .dai_ops = { + .set_clkdiv = wm8900_set_dai_clkdiv, + .set_pll = wm8900_set_dai_pll, + .set_fmt = wm8900_set_dai_fmt, + .digital_mute = wm8900_digital_mute, + }, +}; +EXPORT_SYMBOL_GPL(wm8900_dai); + +static int wm8900_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + u16 reg; + + switch (level) { + case SND_SOC_BIAS_ON: + /* Enable thermal shutdown */ + reg = wm8900_read(codec, WM8900_REG_GPIO); + wm8900_write(codec, WM8900_REG_GPIO, + reg | WM8900_REG_GPIO_TEMP_ENA); + reg = wm8900_read(codec, WM8900_REG_ADDCTL); + wm8900_write(codec, WM8900_REG_ADDCTL, + reg | WM8900_REG_ADDCTL_TEMP_SD); + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + /* Charge capacitors if initial power up */ + if (codec->bias_level == SND_SOC_BIAS_OFF) { + /* STARTUP_BIAS_ENA on */ + wm8900_write(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_STARTUP_BIAS_ENA); + + /* Startup bias mode */ + wm8900_write(codec, WM8900_REG_ADDCTL, + WM8900_REG_ADDCTL_BIAS_SRC | + WM8900_REG_ADDCTL_VMID_SOFTST); + + /* VMID 2x50k */ + wm8900_write(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1); + + /* Allow capacitors to charge */ + schedule_timeout_interruptible(msecs_to_jiffies(400)); + + /* Enable bias */ + wm8900_write(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_STARTUP_BIAS_ENA | + WM8900_REG_POWER1_BIAS_ENA | 0x1); + + wm8900_write(codec, WM8900_REG_ADDCTL, 0); + + wm8900_write(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_BIAS_ENA | 0x1); + } + + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, + (reg & WM8900_REG_POWER1_FLL_ENA) | + WM8900_REG_POWER1_BIAS_ENA | 0x1); + wm8900_write(codec, WM8900_REG_POWER2, + WM8900_REG_POWER2_SYSCLK_ENA); + wm8900_write(codec, WM8900_REG_POWER3, 0); + break; + + case SND_SOC_BIAS_OFF: + /* Startup bias enable */ + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, + reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); + wm8900_write(codec, WM8900_REG_ADDCTL, + WM8900_REG_ADDCTL_BIAS_SRC | + WM8900_REG_ADDCTL_VMID_SOFTST); + + /* Discharge caps */ + wm8900_write(codec, WM8900_REG_POWER1, + WM8900_REG_POWER1_STARTUP_BIAS_ENA); + schedule_timeout_interruptible(msecs_to_jiffies(500)); + + /* Remove clamp */ + wm8900_write(codec, WM8900_REG_HPCTL1, 0); + + /* Power down */ + wm8900_write(codec, WM8900_REG_ADDCTL, 0); + wm8900_write(codec, WM8900_REG_POWER1, 0); + wm8900_write(codec, WM8900_REG_POWER2, 0); + wm8900_write(codec, WM8900_REG_POWER3, 0); + + /* Need to let things settle before stopping the clock + * to ensure that restart works, see "Stopping the + * master clock" in the datasheet. */ + schedule_timeout_interruptible(msecs_to_jiffies(1)); + wm8900_write(codec, WM8900_REG_POWER2, + WM8900_REG_POWER2_SYSCLK_ENA); + break; + } + codec->bias_level = level; + return 0; +} + +static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + struct wm8900_priv *wm8900 = codec->private_data; + int fll_out = wm8900->fll_out; + int fll_in = wm8900->fll_in; + int ret; + + /* Stop the FLL in an orderly fashion */ + ret = wm8900_set_fll(codec, 0, 0, 0); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to stop FLL\n"); + return ret; + } + + wm8900->fll_out = fll_out; + wm8900->fll_in = fll_in; + + wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); + + return 0; +} + +static int wm8900_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + struct wm8900_priv *wm8900 = codec->private_data; + u16 *cache; + int i, ret; + + cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), + GFP_KERNEL); + + wm8900_reset(codec); + wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + /* Restart the FLL? */ + if (wm8900->fll_out) { + int fll_out = wm8900->fll_out; + int fll_in = wm8900->fll_in; + + wm8900->fll_in = 0; + wm8900->fll_out = 0; + + ret = wm8900_set_fll(codec, 0, fll_in, fll_out); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to restart FLL\n"); + return ret; + } + } + + if (cache) { + for (i = 0; i < WM8900_MAXREG; i++) + wm8900_write(codec, i, cache[i]); + kfree(cache); + } else + dev_err(&pdev->dev, "Unable to allocate register cache\n"); + + return 0; +} + +/* + * initialise the WM8900 driver + * register the mixer and dsp interfaces with the kernel + */ +static int wm8900_init(struct snd_soc_device *socdev) +{ + struct snd_soc_codec *codec = socdev->codec; + int ret = 0; + unsigned int reg; + struct i2c_client *i2c_client = socdev->codec->control_data; + + codec->name = "WM8900"; + codec->owner = THIS_MODULE; + codec->read = wm8900_read; + codec->write = wm8900_write; + codec->dai = &wm8900_dai; + codec->num_dai = 1; + codec->reg_cache_size = WM8900_MAXREG; + codec->reg_cache = kmemdup(wm8900_reg_defaults, + sizeof(wm8900_reg_defaults), GFP_KERNEL); + + if (codec->reg_cache == NULL) + return -ENOMEM; + + reg = wm8900_read(codec, WM8900_REG_ID); + if (reg != 0x8900) { + dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n", + reg); + return -ENODEV; + } + + codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + if (codec->private_data == NULL) { + ret = -ENOMEM; + goto priv_err; + } + + /* Read back from the chip */ + reg = wm8900_chip_read(codec, WM8900_REG_POWER1); + reg = (reg >> 12) & 0xf; + dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg); + + wm8900_reset(codec); + + /* Latch the volume update bits */ + wm8900_write(codec, WM8900_REG_LINVOL, + wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); + wm8900_write(codec, WM8900_REG_RINVOL, + wm8900_read(codec, WM8900_REG_RINVOL) | 0x100); + wm8900_write(codec, WM8900_REG_LOUT1CTL, + wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100); + wm8900_write(codec, WM8900_REG_ROUT1CTL, + wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100); + wm8900_write(codec, WM8900_REG_LOUT2CTL, + wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100); + wm8900_write(codec, WM8900_REG_ROUT2CTL, + wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100); + wm8900_write(codec, WM8900_REG_LDAC_DV, + wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_RDAC_DV, + wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_LADC_DV, + wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_RADC_DV, + wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100); + + /* Set the DAC and mixer output bias */ + wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); + + /* Register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(&i2c_client->dev, "Failed to register new PCMs\n"); + goto pcm_err; + } + + /* Turn the chip on */ + codec->bias_level = SND_SOC_BIAS_OFF; + wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + wm8900_add_controls(codec); + wm8900_add_widgets(codec); + + ret = snd_soc_register_card(socdev); + if (ret < 0) { + dev_err(&i2c_client->dev, "Failed to register card\n"); + goto card_err; + } + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); +priv_err: + kfree(codec->private_data); + return ret; +} + +static struct snd_soc_device *wm8900_socdev; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + +static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; + +/* Magic definition of all other variables and things */ +I2C_CLIENT_INSMOD; + +static struct i2c_driver wm8900_i2c_driver; +static struct i2c_client client_template; + +/* If the i2c layer weren't so broken, we could pass this kind of data + around */ +static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct snd_soc_device *socdev = wm8900_socdev; + struct wm8900_setup_data *setup = socdev->codec_data; + struct snd_soc_codec *codec = socdev->codec; + struct i2c_client *i2c; + int ret; + + if (addr != setup->i2c_address) + return -ENODEV; + + dev_err(&adap->dev, "Probe on %x\n", addr); + + client_template.adapter = adap; + client_template.addr = addr; + + i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); + if (i2c == NULL) { + kfree(codec); + return -ENOMEM; + } + i2c_set_clientdata(i2c, codec); + codec->control_data = i2c; + + ret = i2c_attach_client(i2c); + if (ret < 0) { + dev_err(&adap->dev, + "failed to attach codec at addr %x\n", addr); + goto err; + } + + ret = wm8900_init(socdev); + if (ret < 0) { + dev_err(&adap->dev, "failed to initialise WM8900\n"); + goto err; + } + return ret; + +err: + kfree(codec); + kfree(i2c); + return ret; +} + +static int wm8900_i2c_detach(struct i2c_client *client) +{ + struct snd_soc_codec *codec = i2c_get_clientdata(client); + i2c_detach_client(client); + kfree(codec->reg_cache); + kfree(client); + return 0; +} + +static int wm8900_i2c_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, wm8900_codec_probe); +} + +/* corgi i2c codec control layer */ +static struct i2c_driver wm8900_i2c_driver = { + .driver = { + .name = "WM8900 I2C codec", + .owner = THIS_MODULE, + }, + .attach_adapter = wm8900_i2c_attach, + .detach_client = wm8900_i2c_detach, + .command = NULL, +}; + +static struct i2c_client client_template = { + .name = "WM8900", + .driver = &wm8900_i2c_driver, +}; +#endif + +static int wm8900_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct wm8900_setup_data *setup; + struct snd_soc_codec *codec; + int ret = 0; + + dev_info(&pdev->dev, "WM8900 Audio Codec\n"); + + setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; + + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + socdev->codec = codec; + + codec->set_bias_level = wm8900_set_bias_level; + + wm8900_socdev = socdev; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (setup->i2c_address) { + normal_i2c[0] = setup->i2c_address; + codec->hw_write = (hw_write_t)i2c_master_send; + ret = i2c_add_driver(&wm8900_i2c_driver); + if (ret != 0) + printk(KERN_ERR "can't add i2c driver"); + } +#else +#error Non-I2C interfaces not yet supported +#endif + return ret; +} + +/* power down chip */ +static int wm8900_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec->control_data) + wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8900_i2c_driver); +#endif + kfree(codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm8900 = { + .probe = wm8900_probe, + .remove = wm8900_remove, + .suspend = wm8900_suspend, + .resume = wm8900_resume, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); + +MODULE_DESCRIPTION("ASoC WM8900 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h new file mode 100644 index 00000000000..ba450d99e90 --- /dev/null +++ b/sound/soc/codecs/wm8900.h @@ -0,0 +1,64 @@ +/* + * wm8900.h -- WM890 Soc Audio driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM8900_H +#define _WM8900_H + +#define WM8900_FLL 1 + +#define WM8900_BCLK_DIV 1 +#define WM8900_ADC_CLKDIV 2 +#define WM8900_DAC_CLKDIV 3 +#define WM8900_ADC_LRCLK 4 +#define WM8900_DAC_LRCLK 5 +#define WM8900_OPCLK_DIV 6 +#define WM8900_LRCLK_MODE 7 + +#define WM8900_BCLK_DIV_1 0x00 +#define WM8900_BCLK_DIV_1_5 0x02 +#define WM8900_BCLK_DIV_2 0x04 +#define WM8900_BCLK_DIV_3 0x06 +#define WM8900_BCLK_DIV_4 0x08 +#define WM8900_BCLK_DIV_5_5 0x0a +#define WM8900_BCLK_DIV_6 0x0c +#define WM8900_BCLK_DIV_8 0x0e +#define WM8900_BCLK_DIV_11 0x10 +#define WM8900_BCLK_DIV_12 0x12 +#define WM8900_BCLK_DIV_16 0x14 +#define WM8900_BCLK_DIV_22 0x16 +#define WM8900_BCLK_DIV_24 0x18 +#define WM8900_BCLK_DIV_32 0x1a +#define WM8900_BCLK_DIV_44 0x1c +#define WM8900_BCLK_DIV_48 0x1e + +#define WM8900_ADC_CLKDIV_1 0x00 +#define WM8900_ADC_CLKDIV_1_5 0x20 +#define WM8900_ADC_CLKDIV_2 0x40 +#define WM8900_ADC_CLKDIV_3 0x60 +#define WM8900_ADC_CLKDIV_4 0x80 +#define WM8900_ADC_CLKDIV_5_5 0xa0 +#define WM8900_ADC_CLKDIV_6 0xc0 + +#define WM8900_DAC_CLKDIV_1 0x00 +#define WM8900_DAC_CLKDIV_1_5 0x04 +#define WM8900_DAC_CLKDIV_2 0x08 +#define WM8900_DAC_CLKDIV_3 0x0c +#define WM8900_DAC_CLKDIV_4 0x10 +#define WM8900_DAC_CLKDIV_5_5 0x14 +#define WM8900_DAC_CLKDIV_6 0x18 + +#define WM8900_ + +struct wm8900_setup_data { + unsigned short i2c_address; +}; + +extern struct snd_soc_dai wm8900_dai; +extern struct snd_soc_codec_device soc_codec_dev_wm8900; + +#endif -- GitLab From b9c196e1452e1d4cbf0a1499f1e9c1b3edf59320 Mon Sep 17 00:00:00 2001 From: Phillip Michael Jordan Date: Tue, 5 Aug 2008 11:01:00 +0200 Subject: [PATCH 0262/5416] ALSA: snd_usb_audio: fix SB Extigy IR Remote regression The support for the SB Extigy's remote seems to be broken in all recent ALSA versions, including 1.0.17. The driver detects the event correctly, then submits a URB to query the RC code. On the Extigy, the URB is submitted with a length of 2 bytes. My hardware, however, only replies with 1 byte, containing the correct RC button code. The current implementation discards this as being too short. (line 1784 of usbmixer.c) This patch specifies a "minimum packet length" in the remote control configuration. I've left the values for the Audigy 2/Live! the same as the packet length, as I'm assuming the existing code works with them. (I don't have the hardware to confirm) This fixes the Extigy RC support, e.g. for use with Lirc. Signed-off-by: Phillip Michael Jordan Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/usbmixer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 89c63d073cc..5f98bee0695 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -59,12 +59,13 @@ static const struct rc_config { u8 offset; u8 length; u8 packet_length; + u8 min_packet_length; /* minimum accepted length of the URB result */ u8 mute_mixer_id; u32 mute_code; } rc_configs[] = { - { USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */ - { USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */ - { USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */ + { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ + { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ + { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ }; struct usb_mixer_interface { @@ -1781,7 +1782,7 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb) const struct rc_config *rc = mixer->rc_cfg; u32 code; - if (urb->status < 0 || urb->actual_length < rc->packet_length) + if (urb->status < 0 || urb->actual_length < rc->min_packet_length) return; code = mixer->rc_buffer[rc->offset]; -- GitLab From 8f4f4ef6fed55a3636db3146a3e50b7febcbd7de Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 5 Aug 2008 15:45:45 +0200 Subject: [PATCH 0263/5416] ALSA: ac97 - Enable mono-out on ALC203 codec as default Use pin 37 for mono-out as default on ALC203. Reported-by: george pee Tested-by: george pee Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ac97/ac97_codec.c | 2 +- sound/pci/ac97/ac97_patch.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index f6a7d721649..171559c19b3 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -122,7 +122,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL }, { 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL }, { 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, -{ 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL }, +{ 0x414c4770, 0xfffffff0, "ALC203", patch_alc203, NULL }, { 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, { 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index f4fbc795ee8..bb028f8f9a2 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -2560,6 +2560,14 @@ static int patch_ad1986(struct snd_ac97 * ac97) return 0; } +/* + * realtek ALC203: use mono-out for pin 37 + */ +static int patch_alc203(struct snd_ac97 *ac97) +{ + snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400); + return 0; +} /* * realtek ALC65x/850 codecs -- GitLab From c9a7dc2c5279830c0ad77715c0ace3e1edb07f4c Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 6 Aug 2008 08:09:34 +0200 Subject: [PATCH 0264/5416] ALSA: wss_lib: rework snd_ad1848_probe() Make snd_ad1848_probe() easier to follow. With an exception for only trying once as soon as the codec is out of init (which should be all that's needed) the detection logic should be unchanged. Signed-off-by: Rene Herman Acked-by: Krzysztof Helt Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/wss/wss_lib.c | 133 +++++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 866e8686dbe..011da7a2315 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1147,79 +1147,84 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst static int snd_ad1848_probe(struct snd_wss *chip) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned long flags; - int i, id, rev, ad1847; + unsigned char r; + unsigned short hardware = 0; + int err = 0; + int i; - id = 0; - ad1847 = 0; - for (i = 0; i < 1000; i++) { - mb(); - if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT) - msleep(1); - else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_MISC_INFO, 0x00); - snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa); - snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45); - rev = snd_wss_in(chip, CS4231_RIGHT_INPUT); - if (rev == 0x65) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - id = 1; - ad1847 = 1; - break; - } - if (rev == 0x45) { - rev = snd_wss_in(chip, CS4231_LEFT_INPUT); - if (rev == 0xaa || rev == 0x8a) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - id = 1; - break; - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } + while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { + if (time_after(jiffies, timeout)) + return -ENODEV; + cond_resched(); } - if (id != 1) - return -ENODEV; /* no valid device found */ - id = 0; - if (chip->hardware == WSS_HW_DETECT) - id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848; - spin_lock_irqsave(&chip->reg_lock, flags); - inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ - outb(0, chip->port + CS4231P(STATUS)); - mb(); - if (id == WSS_HW_AD1848) { - /* check if there are more than 16 registers */ - rev = snd_wss_in(chip, CS4231_MISC_INFO); - snd_wss_out(chip, CS4231_MISC_INFO, 0x40); - for (i = 0; i < 16; ++i) { - if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) { - id = WSS_HW_CMI8330; - break; - } + + /* set CS423x MODE 1 */ + snd_wss_out(chip, CS4231_MISC_INFO, 0); + + snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */ + r = snd_wss_in(chip, CS4231_RIGHT_INPUT); + if (r != 0x45) { + /* RMGE always high on AD1847 */ + if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) { + err = -ENODEV; + goto out; + } + hardware = WSS_HW_AD1847; + } else { + snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa); + r = snd_wss_in(chip, CS4231_LEFT_INPUT); + /* L/RMGE always low on AT2320 */ + if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) { + err = -ENODEV; + goto out; } - snd_wss_out(chip, CS4231_MISC_INFO, 0x00); - if (id != WSS_HW_CMI8330 && (rev & 0x80)) - id = WSS_HW_CS4248; - if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a) - id = 0; } - if (id == WSS_HW_CMI8330) { - /* verify it is not CS4231 by changing the version register */ - /* on CMI8330 it is volume control register and can be set 0 */ - snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); - snd_wss_dout(chip, CS4231_VERSION, 0x00); - rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - if (rev) - id = 0; - snd_wss_out(chip, CS4231_MISC_INFO, 0); + + /* clear pending IRQ */ + wss_inb(chip, CS4231P(STATUS)); + wss_outb(chip, CS4231P(STATUS), 0); + mb(); + + if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT) + goto out; + + if (hardware) { + chip->hardware = hardware; + goto out; } - if (id) - chip->hardware = id; + r = snd_wss_in(chip, CS4231_MISC_INFO); + + /* set CS423x MODE 2 */ + snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); + for (i = 0; i < 16; i++) { + if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) { + /* we have more than 16 registers: check ID */ + if ((r & 0xf) != 0xa) + goto out_mode; + /* + * on CMI8330, CS4231_VERSION is volume control and + * can be set to 0 + */ + snd_wss_dout(chip, CS4231_VERSION, 0); + r = snd_wss_in(chip, CS4231_VERSION) & 0xe7; + if (!r) + chip->hardware = WSS_HW_CMI8330; + goto out_mode; + } + } + if (r & 0x80) + chip->hardware = WSS_HW_CS4248; + else + chip->hardware = WSS_HW_AD1848; +out_mode: + snd_wss_out(chip, CS4231_MISC_INFO, 0); +out: spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; /* all things are ok.. */ + return err; } static int snd_wss_probe(struct snd_wss *chip) -- GitLab From 421fae06be9e0dac45747494756b3580643815f9 Mon Sep 17 00:00:00 2001 From: Vesa-Matti Kari Date: Wed, 6 Aug 2008 18:24:51 +0300 Subject: [PATCH 0265/5416] selinux: conditional expression type validation was off-by-one expr_isvalid() in conditional.c was off-by-one and allowed invalid expression type COND_LAST. However, it is this header file that needs to be fixed. That way the if-statement's disjunction's second component reads more naturally, "if expr type is greater than the last allowed value" ( rather than using ">=" in conditional.c): if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) Signed-off-by: Vesa-Matti Kari Signed-off-by: James Morris --- security/selinux/ss/conditional.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 65b9f8366e9..53ddb013ae5 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h @@ -28,7 +28,7 @@ struct cond_expr { #define COND_XOR 5 /* bool ^ bool */ #define COND_EQ 6 /* bool == bool */ #define COND_NEQ 7 /* bool != bool */ -#define COND_LAST 8 +#define COND_LAST COND_NEQ __u32 expr_type; __u32 bool; struct cond_expr *next; -- GitLab From c04148f915e5ba7947752e6348e0da4cdab1329e Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Fri, 8 Aug 2008 11:49:08 -0400 Subject: [PATCH 0266/5416] Input: add driver for USB VoIP phones with CM109 chipset Signed-off-by: Alfred E. Heggestad Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 13 + drivers/input/misc/Makefile | 1 + drivers/input/misc/cm109.c | 884 ++++++++++++++++++++++++++++++++++++ 3 files changed, 898 insertions(+) create mode 100644 drivers/input/misc/cm109.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e99b7882f38..199055db508 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -180,6 +180,19 @@ config INPUT_YEALINK To compile this driver as a module, choose M here: the module will be called yealink. +config INPUT_CM109 + tristate "C-Media CM109 USB I/O Controller" + depends on EXPERIMENTAL + depends on USB_ARCH_HAS_HCD + select USB + help + Say Y here if you want to enable keyboard and buzzer functions of the + C-Media CM109 usb phones. The audio part is enabled by the generic + usb sound driver, so you might want to enable that as well. + + To compile this driver as a module, choose M here: the module will be + called cm109. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f48009b5222..d7db2aeb8a9 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o +obj-$(CONFIG_INPUT_CM109) += cm109.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_APANEL) += apanel.o diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c new file mode 100644 index 00000000000..404fd49243f --- /dev/null +++ b/drivers/input/misc/cm109.c @@ -0,0 +1,884 @@ +/* + * Driver for the VoIP USB phones with CM109 chipsets. + * + * Copyright (C) 2007 - 2008 Alfred E. Heggestad + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + */ + +/* + * Tested devices: + * - Komunikate KIP1000 + * - Genius G-talk + * - Allied-Telesis Corega USBPH01 + * - ... + * + * This driver is based on the yealink.c driver + * + * Thanks to: + * - Authors of yealink.c + * - Thomas Reitmayr + * - Oliver Neukum for good review comments and code + * - Shaun Jackman for Genius G-talk keymap + * - Dmitry Torokhov for valuable input and review + * + * Todo: + * - Read/write EEPROM + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CM109_DEBUG 0 + +#define DRIVER_VERSION "20080805" +#define DRIVER_AUTHOR "Alfred E. Heggestad" +#define DRIVER_DESC "CM109 phone driver" + +static char *phone = "kip1000"; +module_param(phone, charp, S_IRUSR); +MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}"); + +enum { + /* HID Registers */ + HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down */ + HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0 */ + HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1 */ + HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL */ + HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */ + HID_OR1 = 0x01, /* GPO - General Purpose Output */ + HID_OR2 = 0x02, /* Set GPIO to input/output mode */ + HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL */ + + /* HID_IR0 */ + RECORD_MUTE = 1 << 3, + PLAYBACK_MUTE = 1 << 2, + VOLUME_DOWN = 1 << 1, + VOLUME_UP = 1 << 0, + + /* HID_OR0 */ + /* bits 7-6 + 0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer + and SPDIF + 1: HID_OR0-3 are used as generic HID registers + 2: Values written to HID_OR0-3 are also mapped to MCU_CTRL, + EEPROM_DATA0-1, EEPROM_CTRL (see Note) + 3: Reserved + */ + HID_OR_GPO_BUZ_SPDIF = 0 << 6, + HID_OR_GENERIC_HID_REG = 1 << 6, + HID_OR_MAP_MCU_EEPROM = 2 << 6, + + BUZZER_ON = 1 << 5, + + /* up to 256 normal keys, up to 16 special keys */ + KEYMAP_SIZE = 256 + 16, +}; + +/* CM109 protocol packet */ +struct cm109_ctl_packet { + u8 byte[4]; +} __attribute__ ((packed)); + +enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) }; + +/* CM109 device structure */ +struct cm109_dev { + struct input_dev *idev; /* input device */ + struct usb_device *udev; /* usb device */ + struct usb_interface *intf; + + /* irq input channel */ + struct cm109_ctl_packet *irq_data; + dma_addr_t irq_dma; + struct urb *urb_irq; + + /* control output channel */ + struct cm109_ctl_packet *ctl_data; + dma_addr_t ctl_dma; + struct usb_ctrlrequest *ctl_req; + dma_addr_t ctl_req_dma; + struct urb *urb_ctl; + /* + * The 3 bitfields below are protected by ctl_submit_lock. + * They have to be separate since they are accessed from IRQ + * context. + */ + unsigned irq_urb_pending:1; /* irq_urb is in flight */ + unsigned ctl_urb_pending:1; /* ctl_urb is in flight */ + unsigned buzzer_pending:1; /* need to issue buzz command */ + spinlock_t ctl_submit_lock; + + unsigned char buzzer_state; /* on/off */ + + /* flags */ + unsigned open:1; + unsigned resetting:1; + unsigned shutdown:1; + + /* This mutex protects writes to the above flags */ + struct mutex pm_mutex; + + unsigned short keymap[KEYMAP_SIZE]; + + char phys[64]; /* physical device path */ + int key_code; /* last reported key */ + int keybit; /* 0=new scan 1,2,4,8=scan columns */ + u8 gpi; /* Cached value of GPI (high nibble) */ +}; + +/****************************************************************************** + * CM109 key interface + *****************************************************************************/ + +static unsigned short special_keymap(int code) +{ + if (code > 0xff) { + switch (code - 0xff) { + case RECORD_MUTE: return KEY_MUTE; + case PLAYBACK_MUTE: return KEY_MUTE; + case VOLUME_DOWN: return KEY_VOLUMEDOWN; + case VOLUME_UP: return KEY_VOLUMEUP; + } + } + return KEY_RESERVED; +} + +/* Map device buttons to internal key events. + * + * The "up" and "down" keys, are symbolised by arrows on the button. + * The "pickup" and "hangup" keys are symbolised by a green and red phone + * on the button. + + Komunikate KIP1000 Keyboard Matrix + + -> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10) + | | | | + <- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20) + | | | | + END - 7 -- 8 -- 9 --> GPI pin 6 (0x40) + | | | | + OK -- * -- 0 -- # --> GPI pin 7 (0x80) + | | | | + + /|\ /|\ /|\ /|\ + | | | | +GPO +pin: 3 2 1 0 + 0x8 0x4 0x2 0x1 + + */ +static unsigned short keymap_kip1000(int scancode) +{ + switch (scancode) { /* phone key: */ + case 0x82: return KEY_NUMERIC_0; /* 0 */ + case 0x14: return KEY_NUMERIC_1; /* 1 */ + case 0x12: return KEY_NUMERIC_2; /* 2 */ + case 0x11: return KEY_NUMERIC_3; /* 3 */ + case 0x24: return KEY_NUMERIC_4; /* 4 */ + case 0x22: return KEY_NUMERIC_5; /* 5 */ + case 0x21: return KEY_NUMERIC_6; /* 6 */ + case 0x44: return KEY_NUMERIC_7; /* 7 */ + case 0x42: return KEY_NUMERIC_8; /* 8 */ + case 0x41: return KEY_NUMERIC_9; /* 9 */ + case 0x81: return KEY_NUMERIC_POUND; /* # */ + case 0x84: return KEY_NUMERIC_STAR; /* * */ + case 0x88: return KEY_ENTER; /* pickup */ + case 0x48: return KEY_ESC; /* hangup */ + case 0x28: return KEY_LEFT; /* IN */ + case 0x18: return KEY_RIGHT; /* OUT */ + default: return special_keymap(scancode); + } +} + +/* + Contributed by Shaun Jackman + + Genius G-Talk keyboard matrix + 0 1 2 3 + 4: 0 4 8 Talk + 5: 1 5 9 End + 6: 2 6 # Up + 7: 3 7 * Down +*/ +static unsigned short keymap_gtalk(int scancode) +{ + switch (scancode) { + case 0x11: return KEY_NUMERIC_0; + case 0x21: return KEY_NUMERIC_1; + case 0x41: return KEY_NUMERIC_2; + case 0x81: return KEY_NUMERIC_3; + case 0x12: return KEY_NUMERIC_4; + case 0x22: return KEY_NUMERIC_5; + case 0x42: return KEY_NUMERIC_6; + case 0x82: return KEY_NUMERIC_7; + case 0x14: return KEY_NUMERIC_8; + case 0x24: return KEY_NUMERIC_9; + case 0x44: return KEY_NUMERIC_POUND; /* # */ + case 0x84: return KEY_NUMERIC_STAR; /* * */ + case 0x18: return KEY_ENTER; /* Talk (green handset) */ + case 0x28: return KEY_ESC; /* End (red handset) */ + case 0x48: return KEY_UP; /* Menu up (rocker switch) */ + case 0x88: return KEY_DOWN; /* Menu down (rocker switch) */ + default: return special_keymap(scancode); + } +} + +/* + * Keymap for Allied-Telesis Corega USBPH01 + * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html + * + * Contributed by july@nat.bg + */ +static unsigned short keymap_usbph01(int scancode) +{ + switch (scancode) { + case 0x11: return KEY_NUMERIC_0; /* 0 */ + case 0x21: return KEY_NUMERIC_1; /* 1 */ + case 0x41: return KEY_NUMERIC_2; /* 2 */ + case 0x81: return KEY_NUMERIC_3; /* 3 */ + case 0x12: return KEY_NUMERIC_4; /* 4 */ + case 0x22: return KEY_NUMERIC_5; /* 5 */ + case 0x42: return KEY_NUMERIC_6; /* 6 */ + case 0x82: return KEY_NUMERIC_7; /* 7 */ + case 0x14: return KEY_NUMERIC_8; /* 8 */ + case 0x24: return KEY_NUMERIC_9; /* 9 */ + case 0x44: return KEY_NUMERIC_POUND; /* # */ + case 0x84: return KEY_NUMERIC_STAR; /* * */ + case 0x18: return KEY_ENTER; /* pickup */ + case 0x28: return KEY_ESC; /* hangup */ + case 0x48: return KEY_LEFT; /* IN */ + case 0x88: return KEY_RIGHT; /* OUT */ + default: return special_keymap(scancode); + } +} + +static unsigned short (*keymap)(int) = keymap_kip1000; + +/* + * Completes a request by converting the data into events for the + * input subsystem. + */ +static void report_key(struct cm109_dev *dev, int key) +{ + struct input_dev *idev = dev->idev; + + if (dev->key_code >= 0) { + /* old key up */ + input_report_key(idev, dev->key_code, 0); + } + + dev->key_code = key; + if (key >= 0) { + /* new valid key */ + input_report_key(idev, key, 1); + } + + input_sync(idev); +} + +/****************************************************************************** + * CM109 usb communication interface + *****************************************************************************/ + +static void cm109_submit_buzz_toggle(struct cm109_dev *dev) +{ + int error; + + if (dev->buzzer_state) + dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; + else + dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; + + error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); + if (error) + err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); +} + +/* + * IRQ handler + */ +static void cm109_urb_irq_callback(struct urb *urb) +{ + struct cm109_dev *dev = urb->context; + const int status = urb->status; + int error; + +#if CM109_DEBUG + info("### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x", + dev->irq_data->byte[0], + dev->irq_data->byte[1], + dev->irq_data->byte[2], + dev->irq_data->byte[3], + dev->keybit); +#endif + + if (status) { + if (status == -ESHUTDOWN) + return; + err("%s: urb status %d", __func__, status); + } + + /* Special keys */ + if (dev->irq_data->byte[HID_IR0] & 0x0f) { + const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); + report_key(dev, dev->keymap[0xff + code]); + } + + /* Scan key column */ + if (dev->keybit == 0xf) { + + /* Any changes ? */ + if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0)) + goto out; + + dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0; + dev->keybit = 0x1; + } else { + report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]); + + dev->keybit <<= 1; + if (dev->keybit > 0x8) + dev->keybit = 0xf; + } + + out: + + spin_lock(&dev->ctl_submit_lock); + + dev->irq_urb_pending = 0; + + if (likely(!dev->shutdown)) { + + if (dev->buzzer_state) + dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; + else + dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; + + dev->ctl_data->byte[HID_OR1] = dev->keybit; + dev->ctl_data->byte[HID_OR2] = dev->keybit; + + dev->buzzer_pending = 0; + dev->ctl_urb_pending = 1; + + error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); + if (error) + err("%s: usb_submit_urb (urb_ctl) failed %d", + __func__, error); + } + + spin_unlock(&dev->ctl_submit_lock); +} + +static void cm109_urb_ctl_callback(struct urb *urb) +{ + struct cm109_dev *dev = urb->context; + const int status = urb->status; + int error; + +#if CM109_DEBUG + info("### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]", + dev->ctl_data->byte[0], + dev->ctl_data->byte[1], + dev->ctl_data->byte[2], + dev->ctl_data->byte[3]); +#endif + + if (status) + err("%s: urb status %d", __func__, status); + + spin_lock(&dev->ctl_submit_lock); + + dev->ctl_urb_pending = 0; + + if (likely(!dev->shutdown)) { + + if (dev->buzzer_pending) { + dev->buzzer_pending = 0; + dev->ctl_urb_pending = 1; + cm109_submit_buzz_toggle(dev); + } else if (likely(!dev->irq_urb_pending)) { + /* ask for key data */ + dev->irq_urb_pending = 1; + error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); + if (error) + err("%s: usb_submit_urb (urb_irq) failed %d", + __func__, error); + } + } + + spin_unlock(&dev->ctl_submit_lock); +} + +static void cm109_toggle_buzzer_async(struct cm109_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->ctl_submit_lock, flags); + + if (dev->ctl_urb_pending) { + /* URB completion will resubmit */ + dev->buzzer_pending = 1; + } else { + dev->ctl_urb_pending = 1; + cm109_submit_buzz_toggle(dev); + } + + spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); +} + +static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on) +{ + int error; + + if (on) + dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; + else + dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; + + error = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + dev->ctl_req->bRequest, + dev->ctl_req->bRequestType, + le16_to_cpu(dev->ctl_req->wValue), + le16_to_cpu(dev->ctl_req->wIndex), + dev->ctl_data, + USB_PKT_LEN, USB_CTRL_SET_TIMEOUT); + if (error && error != EINTR) + err("%s: usb_control_msg() failed %d", __func__, error); +} + +static void cm109_stop_traffic(struct cm109_dev *dev) +{ + dev->shutdown = 1; + /* + * Make sure other CPUs see this + */ + smp_wmb(); + + usb_kill_urb(dev->urb_ctl); + usb_kill_urb(dev->urb_irq); + + cm109_toggle_buzzer_sync(dev, 0); + + dev->shutdown = 0; + smp_wmb(); +} + +static void cm109_restore_state(struct cm109_dev *dev) +{ + if (dev->open) { + /* + * Restore buzzer state. + * This will also kick regular URB submission + */ + cm109_toggle_buzzer_async(dev); + } +} + +/****************************************************************************** + * input event interface + *****************************************************************************/ + +static int cm109_input_open(struct input_dev *idev) +{ + struct cm109_dev *dev = input_get_drvdata(idev); + int error; + + error = usb_autopm_get_interface(dev->intf); + if (error < 0) { + err("%s - cannot autoresume, result %d", + __func__, error); + return error; + } + + mutex_lock(&dev->pm_mutex); + + dev->buzzer_state = 0; + dev->key_code = -1; /* no keys pressed */ + dev->keybit = 0xf; + + /* issue INIT */ + dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; + dev->ctl_data->byte[HID_OR1] = dev->keybit; + dev->ctl_data->byte[HID_OR2] = dev->keybit; + dev->ctl_data->byte[HID_OR3] = 0x00; + + error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); + if (error) + err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); + else + dev->open = 1; + + mutex_unlock(&dev->pm_mutex); + + if (error) + usb_autopm_put_interface(dev->intf); + + return error; +} + +static void cm109_input_close(struct input_dev *idev) +{ + struct cm109_dev *dev = input_get_drvdata(idev); + + mutex_lock(&dev->pm_mutex); + + /* + * Once we are here event delivery is stopped so we + * don't need to worry about someone starting buzzer + * again + */ + cm109_stop_traffic(dev); + dev->open = 0; + + mutex_unlock(&dev->pm_mutex); + + usb_autopm_put_interface(dev->intf); +} + +static int cm109_input_ev(struct input_dev *idev, unsigned int type, + unsigned int code, int value) +{ + struct cm109_dev *dev = input_get_drvdata(idev); + +#if CM109_DEBUG + info("input_ev: type=%u code=%u value=%d", type, code, value); +#endif + + if (type != EV_SND) + return -EINVAL; + + switch (code) { + case SND_TONE: + case SND_BELL: + dev->buzzer_state = !!value; + if (!dev->resetting) + cm109_toggle_buzzer_async(dev); + return 0; + + default: + return -EINVAL; + } +} + + +/****************************************************************************** + * Linux interface and usb initialisation + *****************************************************************************/ + +struct driver_info { + char *name; +}; + +static const struct driver_info info_cm109 = { + .name = "CM109 USB driver", +}; + +enum { + VENDOR_ID = 0x0d8c, /* C-Media Electronics */ + PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */ +}; + +/* table of devices that work with this driver */ +static const struct usb_device_id cm109_usb_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = VENDOR_ID, + .idProduct = PRODUCT_ID_CM109, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .driver_info = (kernel_ulong_t) &info_cm109 + }, + /* you can add more devices here with product ID 0x0008 - 0x000f */ + { } +}; + +static void cm109_usb_cleanup(struct cm109_dev *dev) +{ + if (dev->ctl_req) + usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), + dev->ctl_req, dev->ctl_req_dma); + if (dev->ctl_data) + usb_buffer_free(dev->udev, USB_PKT_LEN, + dev->ctl_data, dev->ctl_dma); + if (dev->irq_data) + usb_buffer_free(dev->udev, USB_PKT_LEN, + dev->irq_data, dev->irq_dma); + + usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ + usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ + kfree(dev); +} + +static void cm109_usb_disconnect(struct usb_interface *interface) +{ + struct cm109_dev *dev = usb_get_intfdata(interface); + + usb_set_intfdata(interface, NULL); + input_unregister_device(dev->idev); + cm109_usb_cleanup(dev); +} + +static int cm109_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct driver_info *nfo = (struct driver_info *)id->driver_info; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct cm109_dev *dev; + struct input_dev *input_dev = NULL; + int ret, pipe, i; + int error = -ENOMEM; + + interface = intf->cur_altsetting; + endpoint = &interface->endpoint[0].desc; + + if (!usb_endpoint_is_int_in(endpoint)) + return -ENODEV; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + spin_lock_init(&dev->ctl_submit_lock); + mutex_init(&dev->pm_mutex); + + dev->udev = udev; + dev->intf = intf; + + dev->idev = input_dev = input_allocate_device(); + if (!input_dev) + goto err_out; + + /* allocate usb buffers */ + dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->irq_dma); + if (!dev->irq_data) + goto err_out; + + dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->ctl_dma); + if (!dev->ctl_data) + goto err_out; + + dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), + GFP_KERNEL, &dev->ctl_req_dma); + if (!dev->ctl_req) + goto err_out; + + /* allocate urb structures */ + dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->urb_irq) + goto err_out; + + dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->urb_ctl) + goto err_out; + + /* get a handle to the interrupt data pipe */ + pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); + ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + if (ret != USB_PKT_LEN) + err("invalid payload size %d, expected %d", ret, USB_PKT_LEN); + + /* initialise irq urb */ + usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data, + USB_PKT_LEN, + cm109_urb_irq_callback, dev, endpoint->bInterval); + dev->urb_irq->transfer_dma = dev->irq_dma; + dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + dev->urb_irq->dev = udev; + + /* initialise ctl urb */ + dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | + USB_DIR_OUT; + dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; + dev->ctl_req->wValue = cpu_to_le16(0x200); + dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); + dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); + + usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), + (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, + cm109_urb_ctl_callback, dev); + dev->urb_ctl->setup_dma = dev->ctl_req_dma; + dev->urb_ctl->transfer_dma = dev->ctl_dma; + dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | + URB_NO_TRANSFER_DMA_MAP; + dev->urb_ctl->dev = udev; + + /* find out the physical bus location */ + usb_make_path(udev, dev->phys, sizeof(dev->phys)); + strlcat(dev->phys, "/input0", sizeof(dev->phys)); + + /* register settings for the input device */ + input_dev->name = nfo->name; + input_dev->phys = dev->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, dev); + input_dev->open = cm109_input_open; + input_dev->close = cm109_input_close; + input_dev->event = cm109_input_ev; + + input_dev->keycode = dev->keymap; + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = ARRAY_SIZE(dev->keymap); + + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND); + input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); + + /* register available key events */ + for (i = 0; i < KEYMAP_SIZE; i++) { + unsigned short k = keymap(i); + dev->keymap[i] = k; + __set_bit(k, input_dev->keybit); + } + __clear_bit(KEY_RESERVED, input_dev->keybit); + + error = input_register_device(dev->idev); + if (error) + goto err_out; + + usb_set_intfdata(intf, dev); + + return 0; + + err_out: + input_free_device(input_dev); + cm109_usb_cleanup(dev); + return error; +} + +static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct cm109_dev *dev = usb_get_intfdata(intf); + + info("cm109: usb_suspend (event=%d)", message.event); + + mutex_lock(&dev->pm_mutex); + cm109_stop_traffic(dev); + mutex_unlock(&dev->pm_mutex); + + return 0; +} + +static int cm109_usb_resume(struct usb_interface *intf) +{ + struct cm109_dev *dev = usb_get_intfdata(intf); + + info("cm109: usb_resume"); + + mutex_lock(&dev->pm_mutex); + cm109_restore_state(dev); + mutex_unlock(&dev->pm_mutex); + + return 0; +} + +static int cm109_usb_pre_reset(struct usb_interface *intf) +{ + struct cm109_dev *dev = usb_get_intfdata(intf); + + mutex_lock(&dev->pm_mutex); + + /* + * Make sure input events don't try to toggle buzzer + * while we are resetting + */ + dev->resetting = 1; + smp_wmb(); + + cm109_stop_traffic(dev); + + return 0; +} + +static int cm109_usb_post_reset(struct usb_interface *intf) +{ + struct cm109_dev *dev = usb_get_intfdata(intf); + + dev->resetting = 0; + smp_wmb(); + + cm109_restore_state(dev); + + mutex_unlock(&dev->pm_mutex); + + return 0; +} + +static struct usb_driver cm109_driver = { + .name = "cm109", + .probe = cm109_usb_probe, + .disconnect = cm109_usb_disconnect, + .suspend = cm109_usb_suspend, + .resume = cm109_usb_resume, + .reset_resume = cm109_usb_resume, + .pre_reset = cm109_usb_pre_reset, + .post_reset = cm109_usb_post_reset, + .id_table = cm109_usb_table, + .supports_autosuspend = 1, +}; + +static int __init cm109_select_keymap(void) +{ + /* Load the phone keymap */ + if (!strcasecmp(phone, "kip1000")) { + keymap = keymap_kip1000; + info("Keymap for Komunikate KIP1000 phone loaded"); + } else if (!strcasecmp(phone, "gtalk")) { + keymap = keymap_gtalk; + info("Keymap for Genius G-talk phone loaded"); + } else if (!strcasecmp(phone, "usbph01")) { + keymap = keymap_usbph01; + info("Keymap for Allied-Telesis Corega USBPH01 phone loaded"); + } else { + err("Unsupported phone: %s", phone); + return -EINVAL; + } + + return 0; +} + +static int __init cm109_init(void) +{ + int err; + + err = cm109_select_keymap(); + if (err) + return err; + + err = usb_register(&cm109_driver); + if (err) + return err; + + info(DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR); + + return 0; +} + +static void __exit cm109_exit(void) +{ + usb_deregister(&cm109_driver); +} + +module_init(cm109_init); +module_exit(cm109_exit); + +MODULE_DEVICE_TABLE(usb, cm109_usb_table); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); -- GitLab From 34a7c48c221676ff8322ca4b8ded84eada34cf12 Mon Sep 17 00:00:00 2001 From: Remi Herilier Date: Fri, 8 Aug 2008 12:13:13 -0400 Subject: [PATCH 0267/5416] Input: wistron - add support for Fujitsu-Siemens Amilo Pro v3505 Wistron button support for Fujitsu-Siemens Amilo Pro Edition V3505. Signed-off-by: Remi Herilier Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index fe268be3293..7c8957dd22c 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { { KE_END, 0 } }; +static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ + { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ + { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ + { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ + { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ + { KE_WIFI, 0x78 }, /* satelite dish button */ + { KE_END, 0 } +}; + static struct key_entry keymap_fujitsu_n3510[] __initdata = { { KE_KEY, 0x11, {KEY_PROG1} }, { KE_KEY, 0x12, {KEY_PROG2} }, @@ -616,6 +626,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, .driver_data = keymap_fs_amilo_pro_v2000 }, + { + .callback = dmi_matched, + .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), + }, + .driver_data = keymap_fs_amilo_pro_v3505 + }, { .callback = dmi_matched, .ident = "Fujitsu-Siemens Amilo M7400", -- GitLab From 57ffe9d539e0eb741bb9ca8f2834d210e70ee2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 8 Aug 2008 12:14:34 -0400 Subject: [PATCH 0268/5416] Input: gpio-keys - optimize interrupt handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By passing a gpio_button_data structure to the handler instead of the whole platform_device the search for the right button can go away. Signed-off-by: Uwe Kleine-König Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 35 ++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index be58730e636..e2809d29d99 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -56,29 +56,18 @@ static void gpio_check_button(unsigned long _data) static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { - struct platform_device *pdev = dev_id; - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; - struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); - int i; + struct gpio_button_data *bdata = dev_id; + struct gpio_keys_button *button = bdata->button; - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; + BUG_ON(irq != gpio_to_irq(button->gpio)); - if (irq == gpio_to_irq(button->gpio)) { - struct gpio_button_data *bdata = &ddata->data[i]; - - if (button->debounce_interval) - mod_timer(&bdata->timer, - jiffies + - msecs_to_jiffies(button->debounce_interval)); - else - gpio_keys_report_event(button, bdata->input); - - return IRQ_HANDLED; - } - } + if (button->debounce_interval) + mod_timer(&bdata->timer, + jiffies + msecs_to_jiffies(button->debounce_interval)); + else + gpio_keys_report_event(button, bdata->input); - return IRQ_NONE; + return IRQ_HANDLED; } static int __devinit gpio_keys_probe(struct platform_device *pdev) @@ -151,7 +140,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, button->desc ? button->desc : "gpio_keys", - pdev); + bdata); if (error) { pr_err("gpio-keys: Unable to claim irq %d; error %d\n", irq, error); @@ -178,7 +167,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail2: while (--i >= 0) { - free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); + free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); if (pdata->buttons[i].debounce_interval) del_timer_sync(&ddata->data[i].timer); gpio_free(pdata->buttons[i].gpio); @@ -203,7 +192,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); - free_irq(irq, pdev); + free_irq(irq, &ddata->data[i]); if (pdata->buttons[i].debounce_interval) del_timer_sync(&ddata->data[i].timer); gpio_free(pdata->buttons[i].gpio); -- GitLab From ce25d7e90c7543f0046c3bdcdcc7594546c57dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 8 Aug 2008 12:14:36 -0400 Subject: [PATCH 0269/5416] Input: gpio-keys - simplify argument list for report_event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now this only saves a few instructions (for gpio_keys_report_event, gpio_keys_isr and gpio_check_button one instraction each on ARM using arm-linux-gnu-gcc 4.2.3---I assume this is similar for other arch/compiler combinations). Signed-off-by: Uwe Kleine-König Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index e2809d29d99..fe22ca34d57 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -37,9 +37,10 @@ struct gpio_keys_drvdata { struct gpio_button_data data[0]; }; -static void gpio_keys_report_event(struct gpio_keys_button *button, - struct input_dev *input) +static void gpio_keys_report_event(struct gpio_button_data *bdata) { + struct gpio_keys_button *button = bdata->button; + struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; @@ -51,7 +52,7 @@ static void gpio_check_button(unsigned long _data) { struct gpio_button_data *data = (struct gpio_button_data *)_data; - gpio_keys_report_event(data->button, data->input); + gpio_keys_report_event(data); } static irqreturn_t gpio_keys_isr(int irq, void *dev_id) @@ -65,7 +66,7 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(button->debounce_interval)); else - gpio_keys_report_event(button, bdata->input); + gpio_keys_report_event(bdata); return IRQ_HANDLED; } -- GitLab From d83d213d9fda671dfd84ea81182742f9e329a6b4 Mon Sep 17 00:00:00 2001 From: Sven Anders Date: Fri, 8 Aug 2008 16:31:31 -0400 Subject: [PATCH 0270/5416] Input: appletouch - prepare for geyser 3/4 handling Split complete function into separate functions for GEYSER1/2 and GEYSER 3/4. Signed-off-by: Sven Anders Signed-off-by: Johannes Berg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/appletouch.c | 266 +++++++++++++++++++++++-------- 1 file changed, 197 insertions(+), 69 deletions(-) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 1f41ae94f26..36ebe5c25ee 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -327,11 +327,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); } -static void atp_complete(struct urb *urb) +/* Check URB status and for correct length of data package */ + +#define ATP_URB_STATUS_SUCCESS 0 +#define ATP_URB_STATUS_ERROR 1 +#define ATP_URB_STATUS_ERROR_FATAL 2 + +static int atp_status_check(struct urb *urb) { - int x, y, x_z, y_z, x_f, y_f; - int retval, i, j; - int key; struct atp *dev = urb->context; switch (urb->status) { @@ -351,11 +354,12 @@ static void atp_complete(struct urb *urb) /* This urb is terminated, clean up */ dbg("atp_complete: urb shutting down with status: %d", urb->status); - return; + return ATP_URB_STATUS_ERROR_FATAL; + default: dbg("atp_complete: nonzero urb status received: %d", urb->status); - goto exit; + return ATP_URB_STATUS_ERROR; } /* drop incomplete datasets */ @@ -363,30 +367,33 @@ static void atp_complete(struct urb *urb) dprintk("appletouch: incomplete data package" " (first byte: %d, length: %d).\n", dev->data[0], dev->urb->actual_length); - goto exit; + return ATP_URB_STATUS_ERROR; } - /* reorder the sensors values */ - if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { - memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); + return ATP_URB_STATUS_SUCCESS; +} - /* - * The values are laid out like this: - * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... - * '-' is an unused value. - */ +/* + * USB interrupt callback functions + */ - /* read X values */ - for (i = 0, j = 19; i < 20; i += 2, j += 3) { - dev->xy_cur[i] = dev->data[j + 1]; - dev->xy_cur[i + 1] = dev->data[j + 2]; - } - /* read Y values */ - for (i = 0, j = 1; i < 9; i += 2, j += 3) { - dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; - dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; - } - } else if (dev->type == ATP_GEYSER2) { +/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */ + +static void atp_complete_geyser_1_2(struct urb *urb) +{ + int x, y, x_z, y_z, x_f, y_f; + int retval, i, j; + int key; + struct atp *dev = urb->context; + int status = atp_status_check(urb); + + if (status == ATP_URB_STATUS_ERROR_FATAL) + return; + else if (status == ATP_URB_STATUS_ERROR) + goto exit; + + /* reorder the sensors values */ + if (dev->type == ATP_GEYSER2) { memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); /* @@ -427,33 +434,146 @@ static void atp_complete(struct urb *urb) /* first sample */ dev->valid = true; dev->x_old = dev->y_old = -1; + + /* Store first sample */ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - if (dev->size_detect_done || - dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */ + /* Perform size detection, if not done already */ + if (!dev->size_detect_done) { + + /* 17" Powerbooks have extra X sensors */ + for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); + i < ATP_XSENSORS; i++) { + if (!dev->xy_cur[i]) + continue; + + printk(KERN_INFO + "appletouch: 17\" model detected.\n"); + + if (dev->type == ATP_GEYSER2) + input_set_abs_params(dev->input, ABS_X, + 0, + (20 - 1) * + ATP_XFACT - 1, + ATP_FUZZ, 0); + else + input_set_abs_params(dev->input, ABS_X, + 0, + (26 - 1) * + ATP_XFACT - 1, + ATP_FUZZ, 0); + break; + } + + dev->size_detect_done = 1; goto exit; + } + } - /* 17" Powerbooks have extra X sensors */ - for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); - i < ATP_XSENSORS; i++) { - if (!dev->xy_cur[i]) - continue; - - printk(KERN_INFO "appletouch: 17\" model detected.\n"); - if (dev->type == ATP_GEYSER2) - input_set_abs_params(dev->input, ABS_X, 0, - (20 - 1) * - ATP_XFACT - 1, - ATP_FUZZ, 0); - else - input_set_abs_params(dev->input, ABS_X, 0, - (ATP_XSENSORS - 1) * - ATP_XFACT - 1, - ATP_FUZZ, 0); - break; + for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { + /* accumulate the change */ + signed char change = dev->xy_old[i] - dev->xy_cur[i]; + dev->xy_acc[i] -= change; + + /* prevent down drifting */ + if (dev->xy_acc[i] < 0) + dev->xy_acc[i] = 0; + } + + memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); + + dbg_dump("accumulator", dev->xy_acc); + + x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, + ATP_XFACT, &x_z, &x_f); + y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, + ATP_YFACT, &y_z, &y_f); + key = dev->data[dev->datalen - 1] & 1; + + if (x && y) { + if (dev->x_old != -1) { + x = (dev->x_old * 3 + x) >> 2; + y = (dev->y_old * 3 + y) >> 2; + dev->x_old = x; + dev->y_old = y; + + if (debug > 1) + printk(KERN_DEBUG "appletouch: " + "X: %3d Y: %3d Xz: %3d Yz: %3d\n", + x, y, x_z, y_z); + + input_report_key(dev->input, BTN_TOUCH, 1); + input_report_abs(dev->input, ABS_X, x); + input_report_abs(dev->input, ABS_Y, y); + input_report_abs(dev->input, ABS_PRESSURE, + min(ATP_PRESSURE, x_z + y_z)); + atp_report_fingers(dev->input, max(x_f, y_f)); } + dev->x_old = x; + dev->y_old = y; + + } else if (!x && !y) { + + dev->x_old = dev->y_old = -1; + input_report_key(dev->input, BTN_TOUCH, 0); + input_report_abs(dev->input, ABS_PRESSURE, 0); + atp_report_fingers(dev->input, 0); + + /* reset the accumulator on release */ + memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); + } + + input_report_key(dev->input, BTN_LEFT, key); + input_sync(dev->input); + + exit: + retval = usb_submit_urb(dev->urb, GFP_ATOMIC); + if (retval) + err("atp_complete: usb_submit_urb failed with result %d", + retval); +} + +/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */ + +static void atp_complete_geyser_3_4(struct urb *urb) +{ + int x, y, x_z, y_z, x_f, y_f; + int retval, i, j; + int key; + struct atp *dev = urb->context; + int status = atp_status_check(urb); + + if (status == ATP_URB_STATUS_ERROR_FATAL) + return; + else if (status == ATP_URB_STATUS_ERROR) + goto exit; + + /* Reorder the sensors values: + * + * The values are laid out like this: + * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... + * '-' is an unused value. + */ + + /* read X values */ + for (i = 0, j = 19; i < 20; i += 2, j += 3) { + dev->xy_cur[i] = dev->data[j + 1]; + dev->xy_cur[i + 1] = dev->data[j + 2]; + } + /* read Y values */ + for (i = 0, j = 1; i < 9; i += 2, j += 3) { + dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; + dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; + } + + dbg_dump("sample", dev->xy_cur); + + if (!dev->valid) { + /* first sample */ + dev->valid = true; + dev->x_old = dev->y_old = -1; + memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - dev->size_detect_done = 1; goto exit; } @@ -514,28 +634,26 @@ static void atp_complete(struct urb *urb) input_sync(dev->input); /* - * Many Geysers will continue to send packets continually after + * Geysers 3/4 will continue to send packets continually after * the first touch unless reinitialised. Do so if it's been * idle for a while in order to avoid waking the kernel up - * several hundred times a second. Re-initialization does not - * work on Fountain touchpads. + * several hundred times a second. */ - if (dev->type != ATP_FOUNTAIN) { - /* - * Button must not be pressed when entering suspend, - * otherwise we will never release the button. - */ - if (!x && !y && !key) { - dev->idlecount++; - if (dev->idlecount == 10) { - dev->valid = false; - schedule_work(&dev->work); - /* Don't resubmit urb here, wait for reinit */ - return; - } - } else - dev->idlecount = 0; - } + + /* + * Button must not be pressed when entering suspend, + * otherwise we will never release the button. + */ + if (!x && !y && !key) { + dev->idlecount++; + if (dev->idlecount == 10) { + dev->valid = false; + schedule_work(&dev->work); + /* Don't resubmit urb here, wait for reinit */ + return; + } + } else + dev->idlecount = 0; exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); @@ -632,9 +750,19 @@ static int atp_probe(struct usb_interface *iface, if (!dev->data) goto err_free_urb; - usb_fill_int_urb(dev->urb, udev, - usb_rcvintpipe(udev, int_in_endpointAddr), - dev->data, dev->datalen, atp_complete, dev, 1); + /* Select the USB complete (callback) function */ + if (dev->type == ATP_FOUNTAIN || + dev->type == ATP_GEYSER1 || + dev->type == ATP_GEYSER2) + usb_fill_int_urb(dev->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), + dev->data, dev->datalen, + atp_complete_geyser_1_2, dev, 1); + else + usb_fill_int_urb(dev->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), + dev->data, dev->datalen, + atp_complete_geyser_3_4, dev, 1); error = atp_handle_geyser(dev); if (error) -- GitLab From 82a196f481661170b4982dc7e68a12e9253309d0 Mon Sep 17 00:00:00 2001 From: Sven Anders Date: Fri, 8 Aug 2008 16:31:33 -0400 Subject: [PATCH 0271/5416] Input: appletouch - handle geyser 3/4 status bits Implement support for status bits on Geyser 3/4. Signed-off-by: Sven Anders Signed-off-by: Johannes Berg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/appletouch.c | 53 +++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 36ebe5c25ee..079816e6b23 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table); #define ATP_GEYSER_MODE_REQUEST_INDEX 0 #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 +/** + * enum atp_status_bits - status bit meanings + * + * These constants represent the meaning of the status bits. + * (only Geyser 3/4) + * + * @ATP_STATUS_BUTTON: The button was pressed + * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad) + * @ATP_STATUS_FROM_RESET: Reset previously performed + */ +enum atp_status_bits { + ATP_STATUS_BUTTON = BIT(0), + ATP_STATUS_BASE_UPDATE = BIT(2), + ATP_STATUS_FROM_RESET = BIT(4), +}; + /* Structure to hold all of our device specific stuff */ struct atp { char phys[64]; struct usb_device *udev; /* usb device */ struct urb *urb; /* usb request block */ - signed char *data; /* transferred data */ + u8 *data; /* transferred data */ struct input_dev *input; /* input dev */ enum atp_touchpad_type type; /* type of touchpad */ bool open; @@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work) int retval; dprintk("appletouch: putting appletouch to sleep (reinit)\n"); - dev->idlecount = 0; - atp_geyser_init(udev); retval = usb_submit_urb(dev->urb, GFP_ATOMIC); @@ -488,7 +502,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) ATP_XFACT, &x_z, &x_f); y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, ATP_YFACT, &y_z, &y_f); - key = dev->data[dev->datalen - 1] & 1; + key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; if (x && y) { if (dev->x_old != -1) { @@ -568,34 +582,38 @@ static void atp_complete_geyser_3_4(struct urb *urb) dbg_dump("sample", dev->xy_cur); - if (!dev->valid) { - /* first sample */ - dev->valid = true; - dev->x_old = dev->y_old = -1; - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); + /* Just update the base values (i.e. touchpad in untouched state) */ + if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) { + dprintk(KERN_DEBUG "appletouch: updated base values\n"); + + memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); goto exit; } for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { - /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; - dev->xy_acc[i] -= change; + /* calculate the change */ + dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; + + /* this is a round-robin value, so couple with that */ + if (dev->xy_acc[i] > 127) + dev->xy_acc[i] -= 256; + + if (dev->xy_acc[i] < -127) + dev->xy_acc[i] += 256; /* prevent down drifting */ if (dev->xy_acc[i] < 0) dev->xy_acc[i] = 0; } - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - dbg_dump("accumulator", dev->xy_acc); x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, ATP_XFACT, &x_z, &x_f); y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, ATP_YFACT, &y_z, &y_f); - key = dev->data[dev->datalen - 1] & 1; + key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; if (x && y) { if (dev->x_old != -1) { @@ -647,7 +665,8 @@ static void atp_complete_geyser_3_4(struct urb *urb) if (!x && !y && !key) { dev->idlecount++; if (dev->idlecount == 10) { - dev->valid = false; + dev->x_old = dev->y_old = -1; + dev->idlecount = 0; schedule_work(&dev->work); /* Don't resubmit urb here, wait for reinit */ return; @@ -879,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message) struct atp *dev = usb_get_intfdata(iface); usb_kill_urb(dev->urb); - dev->valid = false; - return 0; } -- GitLab From 90936cfe6c8f7e90a6f8b0c5cb44d3a012dfd313 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:07:44 +0200 Subject: [PATCH 0272/5416] x86, tsc: fix section mismatch warning WARNING: vmlinux.o(.text+0x7950): Section mismatch in reference from the function native_calibrate_tsc() to the function .init.text:tsc_read_refs() The function native_calibrate_tsc() references the function __init tsc_read_refs(). This is often because native_calibrate_tsc lacks a __init annotation or the annotation of tsc_read_refs is wrong. tsc_read_refs is called from native_calibrate_tsc which is not __init and native_calibrate_tsc cannot be marked __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 7603c055390..46af7167673 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -104,7 +104,7 @@ __setup("notsc", notsc_setup); /* * Read TSC and the reference counters. Take care of SMI disturbance */ -static u64 __init tsc_read_refs(u64 *pm, u64 *hpet) +static u64 tsc_read_refs(u64 *pm, u64 *hpet) { u64 t1, t2; int i; -- GitLab From 85a14437ed24244c78f9a70d58b8299753b03c92 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:12:37 +0200 Subject: [PATCH 0273/5416] x86: fix MP_processor_info section mismatch warning WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x1fe7): Section mismatch in reference from the function MP_processor_info() to the variable .init.data:x86_quirks The function __cpuinit MP_processor_info() references a variable __initdata x86_quirks. If x86_quirks is only used by MP_processor_info then annotate x86_quirks with a matching annotation. MP_processor_info uses x86_quirks which is __init and is used only from smp_read_mpc and construct_default_ISA_mptable which are __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mpparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 6ae005ccaed..78509ee8cc7 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -49,7 +49,7 @@ static int __init mpf_checksum(unsigned char *mp, int len) return sum & 0xFF; } -static void __cpuinit MP_processor_info(struct mpc_config_processor *m) +static void __init MP_processor_info(struct mpc_config_processor *m) { int apicid; char *bootup_cpu = ""; -- GitLab From bafc1dae8215c862c2e6ae913ddadc20581e59b9 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:11:13 +0200 Subject: [PATCH 0274/5416] x86: mmconf: fix section mismatch warning WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x1591): Section mismatch in reference from the function init_amd() to the function .init.text:check_enable_amd_mmconf_dmi() The function __cpuinit init_amd() references a function __init check_enable_amd_mmconf_dmi(). If check_enable_amd_mmconf_dmi is only used by init_amd then annotate check_enable_amd_mmconf_dmi with a matching annotation. check_enable_amd_mmconf_dmi is only called from init_amd which is __cpuinit Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mmconf-fam10h_64.c | 2 +- include/asm-x86/mmconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index fdfdc550b36..efc2f361fe8 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata mmconf_dmi_table[] = { {} }; -void __init check_enable_amd_mmconf_dmi(void) +void __cpuinit check_enable_amd_mmconf_dmi(void) { dmi_check_system(mmconf_dmi_table); } diff --git a/include/asm-x86/mmconfig.h b/include/asm-x86/mmconfig.h index 95beda07c6f..e293ab81e85 100644 --- a/include/asm-x86/mmconfig.h +++ b/include/asm-x86/mmconfig.h @@ -3,7 +3,7 @@ #ifdef CONFIG_PCI_MMCONFIG extern void __cpuinit fam10h_check_enable_mmcfg(void); -extern void __init check_enable_amd_mmconf_dmi(void); +extern void __cpuinit check_enable_amd_mmconf_dmi(void); #else static inline void fam10h_check_enable_mmcfg(void) { } static inline void check_enable_amd_mmconf_dmi(void) { } -- GitLab From d406d21d90dce2e66c7eb4a44605aac947fe55fb Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 11 Aug 2008 00:09:38 +0200 Subject: [PATCH 0275/5416] x86: mpparse.c: fix section mismatch warning WARNING: vmlinux.o(.text+0x118f7): Section mismatch in reference from the function construct_ioapic_table() to the function .init.text:MP_bus_info() The function construct_ioapic_table() references the function __init MP_bus_info(). This is often because construct_ioapic_table lacks a __init annotation or the annotation of MP_bus_info is wrong. construct_ioapic_table is called only from construct_default_ISA_mptable which is __init Signed-off-by: Marcin Slusarz Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Signed-off-by: H. Peter Anvin --- arch/x86/kernel/mpparse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 78509ee8cc7..2c1963b3962 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -484,7 +484,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) } -static void construct_ioapic_table(int mpc_default_type) +static void __init construct_ioapic_table(int mpc_default_type) { struct mpc_config_ioapic ioapic; struct mpc_config_bus bus; @@ -529,7 +529,7 @@ static void construct_ioapic_table(int mpc_default_type) construct_default_ioirq_mptable(mpc_default_type); } #else -static inline void construct_ioapic_table(int mpc_default_type) { } +static inline void __init construct_ioapic_table(int mpc_default_type) { } #endif static inline void __init construct_default_ISA_mptable(int mpc_default_type) -- GitLab From 4c942654a4514d7d0a9b592a7d1b198a212e8a03 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 10 Aug 2008 20:57:45 +0800 Subject: [PATCH 0276/5416] arch/x86/kernel/acpi/boot.c: removed duplicated #include Removed duplicated include file in arch/x86/kernel/acpi/boot.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fa88a1d7129..d8d118935b0 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -58,7 +58,6 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_X86_64 #include -#include #else /* X86 */ -- GitLab From 8aeb4022633f7d0eca5e13a9622bd73df92bbf2a Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 10 Aug 2008 21:09:22 +0800 Subject: [PATCH 0277/5416] arch/x86/kernel/cpuid.c: removed duplicated #include Removed duplicated include file in arch/x86/kernel/cpuid.c. Signed-off-by: Huang Weiyi Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpuid.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 14b11b3be31..3fa4e926b51 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include -- GitLab From 67182ae1c42206e516f7efb292b745e826497b24 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 10 Aug 2008 18:35:38 -0700 Subject: [PATCH 0278/5416] rcu, debug: detect stalled grace periods this is a diagnostic patch for Classic RCU. The approach is to record a timestamp at the beginning of the grace period (in rcu_start_batch()), then have rcu_check_callbacks() complain if: 1. it is running on a CPU that has holding up grace periods for a long time (say one second). This will identify the culprit assuming that the culprit has not disabled hardware irqs, instruction execution, or some such. 2. it is running on a CPU that is not holding up grace periods, but grace periods have been held up for an even longer time (say two seconds). It is enabled via the default-off CONFIG_DEBUG_RCU_STALL kernel parameter. Rather than exponential backoff, it backs off to once per 30 seconds. My feeling upon thinking on it was that if you have stalled RCU grace periods for that long, a few extra printk() messages are probably the least of your worries... Signed-off-by: Paul E. McKenney Cc: Peter Zijlstra Cc: Yinghai Lu Cc: David Witbrodt Signed-off-by: Ingo Molnar --- include/linux/rcuclassic.h | 3 ++ kernel/rcuclassic.c | 80 ++++++++++++++++++++++++++++++++++++++ lib/Kconfig.debug | 13 +++++++ 3 files changed, 96 insertions(+) diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index 04c728147be..16589958b40 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h @@ -46,6 +46,9 @@ struct rcu_ctrlblk { long cur; /* Current batch number. */ long completed; /* Number of the last completed batch */ long pending; /* Number of the last pending batch */ +#ifdef CONFIG_DEBUG_RCU_STALL + unsigned long gp_check; /* Time grace period should end, in seconds. */ +#endif /* #ifdef CONFIG_DEBUG_RCU_STALL */ int signaled; diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index d4271146a9b..d7ec731de75 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key rcu_lock_key; @@ -286,6 +287,81 @@ static void rcu_do_batch(struct rcu_data *rdp) * rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace * period (if necessary). */ + +#ifdef CONFIG_DEBUG_RCU_STALL + +static inline void record_gp_check_time(struct rcu_ctrlblk *rcp) +{ + rcp->gp_check = get_seconds() + 3; +} +static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) +{ + int cpu; + long delta; + + /* Only let one CPU complain about others per time interval. */ + + spin_lock(&rcp->lock); + delta = get_seconds() - rcp->gp_check; + if (delta < 2L || + cpus_empty(rcp->cpumask)) { + spin_unlock(&rcp->lock); + return; + rcp->gp_check = get_seconds() + 30; + } + spin_unlock(&rcp->lock); + + /* OK, time to rat on our buddy... */ + + printk(KERN_ERR "RCU detected CPU stalls:"); + for_each_cpu_mask(cpu, rcp->cpumask) + printk(" %d", cpu); + printk(" (detected by %d, t=%lu/%lu)\n", + smp_processor_id(), get_seconds(), rcp->gp_check); +} +static void print_cpu_stall(struct rcu_ctrlblk *rcp) +{ + printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu)\n", + smp_processor_id(), get_seconds(), rcp->gp_check); + dump_stack(); + spin_lock(&rcp->lock); + if ((long)(get_seconds() - rcp->gp_check) >= 0L) + rcp->gp_check = get_seconds() + 30; + spin_unlock(&rcp->lock); +} +static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, + struct rcu_data *rdp) +{ + long delta; + + delta = get_seconds() - rcp->gp_check; + if (cpu_isset(smp_processor_id(), rcp->cpumask) && delta >= 0L) { + + /* We haven't checked in, so go dump stack. */ + + print_cpu_stall(rcp); + + } else if (!cpus_empty(rcp->cpumask) && delta >= 2L) { + + /* They had two seconds to dump stack, so complain. */ + + print_other_cpu_stall(rcp); + + } +} + +#else /* #ifdef CONFIG_DEBUG_RCU_STALL */ + +static inline void record_gp_check_time(struct rcu_ctrlblk *rcp) +{ +} +static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, + struct rcu_data *rdp) +{ +} + +#endif /* #else #ifdef CONFIG_DEBUG_RCU_STALL */ + /* * Register a new batch of callbacks, and start it up if there is currently no * active batch and the batch to be registered has not already occurred. @@ -296,6 +372,7 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp) if (rcp->cur != rcp->pending && rcp->completed == rcp->cur) { rcp->cur++; + record_gp_check_time(rcp); /* * Accessing nohz_cpu_mask before incrementing rcp->cur needs a @@ -489,6 +566,9 @@ static void rcu_process_callbacks(struct softirq_action *unused) static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + /* Check for CPU stalls, if enabled. */ + check_cpu_stall(rcp, rdp); + if (rdp->nxtlist) { /* * This cpu has pending rcu entries and the grace period diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index e1d4764435e..2fb6d90bf1e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -597,6 +597,19 @@ config RCU_TORTURE_TEST_RUNNABLE Say N here if you want the RCU torture tests to start only after being manually enabled via /proc. +config RCU_CPU_STALL + bool "Check for stalled CPUs delaying RCU grace periods" + depends on CLASSIC_RCU + default n + help + This option causes RCU to printk information on which + CPUs are delaying the current grace period, but only when + the grace period extends for excessive time periods. + + Say Y if you want RCU to perform such checks. + + Say N if you are unsure. + config KPROBES_SANITY_TEST bool "Kprobes sanity tests" depends on DEBUG_KERNEL -- GitLab From 78635fc739b1254f3e0362ac430edbdd2cff01dc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 11 Aug 2008 13:34:15 +0200 Subject: [PATCH 0279/5416] rcu, debug: detect stalled grace periods, cleanups small cleanups. Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index d7ec731de75..56b8712fe5a 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -294,6 +294,7 @@ static inline void record_gp_check_time(struct rcu_ctrlblk *rcp) { rcp->gp_check = get_seconds() + 3; } + static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) { int cpu; @@ -303,11 +304,9 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) spin_lock(&rcp->lock); delta = get_seconds() - rcp->gp_check; - if (delta < 2L || - cpus_empty(rcp->cpumask)) { + if (delta < 2L || cpus_empty(rcp->cpumask)) { spin_unlock(&rcp->lock); return; - rcp->gp_check = get_seconds() + 30; } spin_unlock(&rcp->lock); @@ -319,6 +318,7 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) printk(" (detected by %d, t=%lu/%lu)\n", smp_processor_id(), get_seconds(), rcp->gp_check); } + static void print_cpu_stall(struct rcu_ctrlblk *rcp) { printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu)\n", @@ -329,8 +329,8 @@ static void print_cpu_stall(struct rcu_ctrlblk *rcp) rcp->gp_check = get_seconds() + 30; spin_unlock(&rcp->lock); } -static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, - struct rcu_data *rdp) + +static void check_cpu_stall(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { long delta; @@ -341,12 +341,11 @@ static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, print_cpu_stall(rcp); - } else if (!cpus_empty(rcp->cpumask) && delta >= 2L) { - - /* They had two seconds to dump stack, so complain. */ - - print_other_cpu_stall(rcp); - + } else { + if (!cpus_empty(rcp->cpumask) && delta >= 2L) { + /* They had two seconds to dump stack, so complain. */ + print_other_cpu_stall(rcp); + } } } @@ -355,8 +354,9 @@ static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, static inline void record_gp_check_time(struct rcu_ctrlblk *rcp) { } -static inline void check_cpu_stall(struct rcu_ctrlblk *rcp, - struct rcu_data *rdp) + +static inline void +check_cpu_stall(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { } -- GitLab From b845b517b5e3706a3729f6ea83b88ab85f0725b0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 8 Aug 2008 21:47:09 +0200 Subject: [PATCH 0280/5416] printk: robustify printk Avoid deadlocks against rq->lock and xtime_lock by deferring the klogd wakeup by polling from the timer tick. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- include/linux/kernel.h | 4 ++++ kernel/printk.c | 19 +++++++++++++++++-- kernel/time/tick-sched.c | 2 +- kernel/timer.c | 1 + 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index aaa998f65c7..113ac8d0425 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -200,6 +200,8 @@ extern struct ratelimit_state printk_ratelimit_state; extern int printk_ratelimit(void); extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msec); +extern void printk_tick(void); +extern int printk_needs_cpu(int); #else static inline int vprintk(const char *s, va_list args) __attribute__ ((format (printf, 1, 0))); @@ -211,6 +213,8 @@ static inline int printk_ratelimit(void) { return 0; } static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ unsigned int interval_msec) \ { return false; } +static inline void printk_tick(void) { } +static inline int printk_needs_cpu(int) { return 0; } #endif extern void asmlinkage __attribute__((format(printf, 1, 2))) diff --git a/kernel/printk.c b/kernel/printk.c index b51b1567bb5..655cc2ca10c 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -982,10 +982,25 @@ int is_console_locked(void) return console_locked; } -void wake_up_klogd(void) +static DEFINE_PER_CPU(int, printk_pending); + +void printk_tick(void) { - if (!oops_in_progress && waitqueue_active(&log_wait)) + if (__get_cpu_var(printk_pending)) { + __get_cpu_var(printk_pending) = 0; wake_up_interruptible(&log_wait); + } +} + +int printk_needs_cpu(int cpu) +{ + return per_cpu(printk_pending, cpu); +} + +void wake_up_klogd(void) +{ + if (waitqueue_active(&log_wait)) + __get_cpu_var(printk_pending) = 1; } /** diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 825b4c00fe4..c13d4f18237 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -255,7 +255,7 @@ void tick_nohz_stop_sched_tick(int inidle) next_jiffies = get_next_timer_interrupt(last_jiffies); delta_jiffies = next_jiffies - last_jiffies; - if (rcu_needs_cpu(cpu)) + if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu)) delta_jiffies = 1; /* * Do not stop the tick, if we are only one off diff --git a/kernel/timer.c b/kernel/timer.c index 03bc7f1f159..510fe69351c 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -978,6 +978,7 @@ void update_process_times(int user_tick) run_local_timers(); if (rcu_pending(cpu)) rcu_check_callbacks(cpu, user_tick); + printk_tick(); scheduler_tick(); run_posix_cpu_timers(p); } -- GitLab From ced9cd40ac14111befd6b0c73ec90106c22a3fd7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 11 Aug 2008 14:38:12 +0200 Subject: [PATCH 0281/5416] printk: robustify printk, fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: include/linux/kernel.h: In function ‘printk_needs_cpu': include/linux/kernel.h:217: error: parameter name omitted Signed-off-by: Ingo Molnar --- include/linux/kernel.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 113ac8d0425..3652a456412 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -200,8 +200,6 @@ extern struct ratelimit_state printk_ratelimit_state; extern int printk_ratelimit(void); extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msec); -extern void printk_tick(void); -extern int printk_needs_cpu(int); #else static inline int vprintk(const char *s, va_list args) __attribute__ ((format (printf, 1, 0))); @@ -213,10 +211,11 @@ static inline int printk_ratelimit(void) { return 0; } static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ unsigned int interval_msec) \ { return false; } -static inline void printk_tick(void) { } -static inline int printk_needs_cpu(int) { return 0; } #endif +extern int printk_needs_cpu(int cpu); +extern void printk_tick(void); + extern void asmlinkage __attribute__((format(printf, 1, 2))) early_printk(const char *fmt, ...); -- GitLab From 2ae111cdd8d83ebf9de72e36e68a8c84b6ebbeea Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 11 Aug 2008 18:34:08 +0400 Subject: [PATCH 0282/5416] x86: apic interrupts - move assignments to irqinit_32.c, v2 64bit mode APIC interrupt handlers are set within irqinit_64.c. Lets do tha same for 32bit mode which would help in furter code merging. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 48 ---------------------------------- arch/x86/kernel/irqinit_32.c | 49 +++++++++++++++++++++++++++++++++++ arch/x86/mach-default/setup.c | 15 ----------- include/asm-x86/arch_hooks.h | 2 -- 4 files changed, 49 insertions(+), 65 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f93c18f5b79..9e341c9d941 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1354,54 +1354,6 @@ void smp_error_interrupt(struct pt_regs *regs) irq_exit(); } -#ifdef CONFIG_SMP -void __init smp_intr_init(void) -{ - /* - * IRQ0 must be given a fixed assignment and initialized, - * because it's used before the IO-APIC is set up. - */ - set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); - - /* - * The reschedule interrupt is a CPU-to-CPU reschedule-helper - * IPI, driven by wakeup. - */ - alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); - - /* IPI for invalidation */ - alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); - - /* IPI for generic function call */ - alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); - - /* IPI for single call function */ - set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, - call_function_single_interrupt); -} -#endif - -/* - * Initialize APIC interrupts - */ -void __init apic_intr_init(void) -{ -#ifdef CONFIG_SMP - smp_intr_init(); -#endif - /* self generated IPI for local APIC timer */ - alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); - - /* IPI vectors for APIC spurious and error interrupts */ - alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); - alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); - - /* thermal monitor LVT interrupt */ -#ifdef CONFIG_X86_MCE_P4THERMAL - alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); -#endif -} - /** * connect_bsp_APIC - attach the APIC to the interrupt system */ diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index d66914287ee..9200a1e2752 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c @@ -74,6 +74,15 @@ void __init init_ISA_irqs (void) } } +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + /* Overridden in paravirt.c */ void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); @@ -98,6 +107,46 @@ void __init native_init_IRQ(void) set_intr_gate(vector, interrupt[i]); } +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP) + /* + * IRQ0 must be given a fixed assignment and initialized, + * because it's used before the IO-APIC is set up. + */ + set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); + + /* + * The reschedule interrupt is a CPU-to-CPU reschedule-helper + * IPI, driven by wakeup. + */ + alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); + + /* IPI for invalidation */ + alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); + + /* IPI for generic function call */ + alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); + + /* IPI for single call function */ + set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt); +#endif + +#ifdef CONFIG_X86_LOCAL_APIC + /* self generated IPI for local APIC timer */ + alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); + + /* IPI vectors for APIC spurious and error interrupts */ + alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); + alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); +#endif + +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL) + /* thermal monitor LVT interrupt */ + alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); +#endif + + if (!acpi_ioapic) + setup_irq(2, &irq2); + /* setup after call gates are initialised (usually add in * the architecture specific gates) */ diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index 3d317836be9..b00f5ad10ca 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -36,15 +36,6 @@ void __init pre_intr_init_hook(void) init_ISA_irqs(); } -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { - .handler = no_action, - .mask = CPU_MASK_NONE, - .name = "cascade", -}; - /** * intr_init_hook - post gate setup interrupt initialisation * @@ -60,12 +51,6 @@ void __init intr_init_hook(void) if (x86_quirks->arch_intr_init()) return; } -#ifdef CONFIG_X86_LOCAL_APIC - apic_intr_init(); -#endif - - if (!acpi_ioapic) - setup_irq(2, &irq2); } /** diff --git a/include/asm-x86/arch_hooks.h b/include/asm-x86/arch_hooks.h index 72adc3a109c..de4596b24c2 100644 --- a/include/asm-x86/arch_hooks.h +++ b/include/asm-x86/arch_hooks.h @@ -12,8 +12,6 @@ /* these aren't arch hooks, they are generic routines * that can be used by the hooks */ extern void init_ISA_irqs(void); -extern void apic_intr_init(void); -extern void smp_intr_init(void); extern irqreturn_t timer_interrupt(int irq, void *dev_id); /* these are the defined hooks */ -- GitLab From 7c13e6a3d15a4ebcc3f40df5f4d19665479f8ca3 Mon Sep 17 00:00:00 2001 From: Dimitri Sivanich Date: Mon, 11 Aug 2008 10:46:46 -0500 Subject: [PATCH 0283/5416] x86: remove EXPERIMENTAL restriction from CONFIG_HOTPLUG_CPU This removes the EXPERIMENTAL restriction from CONFIG_HOTPLUG_CPU on the x86 architecture. Signed-off-by: Dimitri Sivanich Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3d0f2b6a5a1..7917962ab7f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1371,14 +1371,14 @@ config PHYSICAL_ALIGN Don't change this unless you know what you are doing. config HOTPLUG_CPU - bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER + bool "Support for hot-pluggable CPUs" + depends on SMP && HOTPLUG && !X86_VOYAGER ---help--- - Say Y here to experiment with turning CPUs off and on, and to - enable suspend on SMP systems. CPUs can be controlled through - /sys/devices/system/cpu. - Say N if you want to disable CPU hotplug and don't need to - suspend. + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + ( Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. config COMPAT_VDSO def_bool y -- GitLab From 012f09e7942716d5f4339f1fd9a831a485bb1d4a Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 16:23:08 +0200 Subject: [PATCH 0284/5416] x86: compile pat debugfs interface only if CONFIG_X86_PAT is set Recently I've run a kernel w/o PAT support and wondered why there was a file "x86/pat_memtype_list" in debugfs. Of course it's empty if PAT is disabled ... so just get rid of this interface if PAT is disabled. Signed-off-by: Andreas Herrmann Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 2fe30916d4b..647b1c4de71 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -492,7 +492,7 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) free_memtype(addr, addr + size); } -#if defined(CONFIG_DEBUG_FS) +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) /* get Nth element of the linked list */ static struct memtype *memtype_get_idx(loff_t pos) @@ -576,4 +576,4 @@ static int __init pat_memtype_list_init(void) late_initcall(pat_memtype_list_init); -#endif /* CONFIG_DEBUG_FS */ +#endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */ -- GitLab From 59f09ba2b62e6f89beeb4c8fc2c83fe14321dda9 Mon Sep 17 00:00:00 2001 From: Philipp Kohlbecher Date: Wed, 6 Aug 2008 15:25:26 +0200 Subject: [PATCH 0285/5416] x86: fix comment in protected mode header Comments in arch/x86/boot/compressed/head_32.S erroneously refer to the real mode pointer as the second and the heap area as the third argument to decompress_kernel(). In fact, these have been the first and second argument, respectively, since v2.6.20. This patch corrects the comments. It introduces no code changes. Signed-off-by: Philipp Kohlbecher Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/head_32.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index ba7736cf2ec..29c5fbf0839 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -137,14 +137,15 @@ relocated: */ movl output_len(%ebx), %eax pushl %eax + # push arguments for decompress_kernel: pushl %ebp # output address movl input_len(%ebx), %eax pushl %eax # input_len leal input_data(%ebx), %eax pushl %eax # input_data leal boot_heap(%ebx), %eax - pushl %eax # heap area as third argument - pushl %esi # real mode pointer as second arg + pushl %eax # heap area + pushl %esi # real mode pointer call decompress_kernel addl $20, %esp popl %ecx -- GitLab From 49800efcb17afdf973f33e8aa8807b7f83993cc6 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:27:30 +0200 Subject: [PATCH 0286/5416] x86: pda_init(): fix memory leak when using CPU hotplug pda->irqstackptr is allocated whenever a CPU is set online. But it is never freed. This results in a memory leak of 16K for each CPU offline/online cycle. Fix is to allocate pda->irqstackptr only once. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 6f9b8924bdc..8396fd7628a 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -493,17 +493,20 @@ void pda_init(int cpu) /* others are initialized in smpboot.c */ pda->pcurrent = &init_task; pda->irqstackptr = boot_cpu_stack; + pda->irqstackptr += IRQSTACKSIZE - 64; } else { - pda->irqstackptr = (char *) - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); - if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d", cpu); + if (!pda->irqstackptr) { + pda->irqstackptr = (char *) + __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); + if (!pda->irqstackptr) + panic("cannot allocate irqstack for cpu %d", + cpu); + pda->irqstackptr += IRQSTACKSIZE - 64; + } if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); } - - pda->irqstackptr += IRQSTACKSIZE-64; } char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + -- GitLab From b55793f7528ce1b73c25b3ac8a86a6cda2a0f9a4 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:29:37 +0200 Subject: [PATCH 0287/5416] x86: cpu_init(): fix memory leak when using CPU hotplug Exception stacks are allocated each time a CPU is set online. But the allocated space is never freed. Thus with one CPU hotplug offline/online cycle there is a memory leak of 24K (6 pages) for a CPU. Fix is to allocate exception stacks only once -- when the CPU is set online for the first time. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common_64.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 8396fd7628a..cc6efe86249 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -606,19 +606,22 @@ void __cpuinit cpu_init(void) /* * set up and load the per-CPU TSS */ - for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (!orig_ist->ist[0]) { static const unsigned int order[N_EXCEPTION_STACKS] = { - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, + [DEBUG_STACK - 1] = DEBUG_STACK_ORDER }; - if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); - if (!estacks) - panic("Cannot allocate exception stack %ld %d\n", - v, cpu); + for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (cpu) { + estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); + if (!estacks) + panic("Cannot allocate exception " + "stack %ld %d\n", v, cpu); + } + estacks += PAGE_SIZE << order[v]; + orig_ist->ist[v] = t->x86_tss.ist[v] = + (unsigned long)estacks; } - estacks += PAGE_SIZE << order[v]; - orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; } t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); -- GitLab From 99809963c99e1ed868d9ebeb4a5e7ee1cbe0309f Mon Sep 17 00:00:00 2001 From: Jeff Chua Date: Wed, 6 Aug 2008 19:09:53 +0800 Subject: [PATCH 0288/5416] x86: make sparsemem more available With CONFIG_X86_PC, I can set CONFIG_SPARSEMEM=y. With CONFIG_X86_GENERICARCH, CONFIG_SPARSEMEM depends on CONFIG_NUMA. I'm using the patch below to enable sparsemem instead of flatmem. System booted and is running. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7917962ab7f..e2305c7d881 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1035,7 +1035,7 @@ config HAVE_ARCH_ALLOC_REMAP config ARCH_FLATMEM_ENABLE def_bool y - depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA + depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && !NUMA config ARCH_DISCONTIGMEM_ENABLE def_bool y @@ -1051,7 +1051,7 @@ config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_GENERICARCH select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 -- GitLab From c1e817d03a7de57a963654c35e6e80af9a5dbff5 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 22 Jul 2008 22:58:03 +0100 Subject: [PATCH 0289/5416] GFS2: Fix debugfs glock file iterator Due to an incorrect iterator, some glocks were being missed from the glock dumps obtained via debugfs. This patch fixes the problem and ensures that we don't miss any glocks in future. Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 13391e54661..4cbb6957a0d 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1816,15 +1816,17 @@ restart: if (gl) { gi->gl = hlist_entry(gl->gl_list.next, struct gfs2_glock, gl_list); - if (gi->gl) - gfs2_glock_hold(gi->gl); + } else { + gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first, + struct gfs2_glock, gl_list); } + if (gi->gl) + gfs2_glock_hold(gi->gl); read_unlock(gl_lock_addr(gi->hash)); if (gl) gfs2_glock_put(gl); - if (gl && gi->gl == NULL) - gi->hash++; while (gi->gl == NULL) { + gi->hash++; if (gi->hash >= GFS2_GL_HASH_SIZE) return 1; read_lock(gl_lock_addr(gi->hash)); @@ -1833,7 +1835,6 @@ restart: if (gi->gl) gfs2_glock_hold(gi->gl); read_unlock(gl_lock_addr(gi->hash)); - gi->hash++; } if (gi->sdp != gi->gl->gl_sbd) -- GitLab From 9b8df98fc8973ad1c5f0d7c4cf71c7fb84fe22c5 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 8 Aug 2008 13:45:13 +0100 Subject: [PATCH 0290/5416] GFS2: Fix metafs mounts This patch is intended to fix the issues reported in bz #457798. Instead of having the metafs as a separate filesystem, it becomes a second root of gfs2. As a result it will appear as type gfs2 in /proc/mounts, but it is still possible (for backwards compatibility purposes) to mount it as type gfs2meta. A new mount flag "meta" is introduced so that its possible to tell the two cases apart in /proc/mounts. As a result it becomes possible to mount type gfs2 with -o meta and get the same result as mounting type gfs2meta. So it is possible to mount just the metafs on its own. Currently if you do this, its then impossible to mount the "normal" root of the gfs2 filesystem without first unmounting the metafs root. I'm not sure if thats a feature or a bug :-) Either way, this is a great improvement on the previous scheme and I've verified that it works ok with bind mounts on both the "normal" root and the metafs root in various combinations. There were also a bunch of functions in super.c which didn't belong there, so this moves them into ops_fstype.c where they can be static. Hopefully the mount/umount sequence is now more obvious as a result. Signed-off-by: Steven Whitehouse Cc: Alexander Viro --- fs/gfs2/incore.h | 7 +- fs/gfs2/mount.c | 7 + fs/gfs2/ops_fstype.c | 566 +++++++++++++++++++++++++++++-------------- fs/gfs2/ops_super.c | 57 ++++- fs/gfs2/super.c | 340 -------------------------- fs/gfs2/super.h | 6 - 6 files changed, 448 insertions(+), 535 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 448697a5c46..a1777a1927b 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -400,6 +400,7 @@ struct gfs2_args { int ar_quota; /* off/account/on */ int ar_suiddir; /* suiddir support */ int ar_data; /* ordered/writeback */ + int ar_meta; /* mount metafs */ }; struct gfs2_tune { @@ -461,7 +462,6 @@ struct gfs2_sb_host { struct gfs2_sbd { struct super_block *sd_vfs; - struct super_block *sd_vfs_meta; struct kobject sd_kobj; unsigned long sd_flags; /* SDF_... */ struct gfs2_sb_host sd_sb; @@ -499,7 +499,9 @@ struct gfs2_sbd { /* Inode Stuff */ - struct inode *sd_master_dir; + struct dentry *sd_master_dir; + struct dentry *sd_root_dir; + struct inode *sd_jindex; struct inode *sd_inum_inode; struct inode *sd_statfs_inode; @@ -634,7 +636,6 @@ struct gfs2_sbd { /* Debugging crud */ unsigned long sd_last_warning; - struct vfsmount *sd_gfs2mnt; struct dentry *debugfs_dir; /* debugfs directory */ struct dentry *debugfs_dentry_glocks; /* for debugfs */ }; diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index b941f9f9f95..df48333e6f0 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -42,6 +42,7 @@ enum { Opt_nosuiddir, Opt_data_writeback, Opt_data_ordered, + Opt_meta, Opt_err, }; @@ -66,6 +67,7 @@ static match_table_t tokens = { {Opt_nosuiddir, "nosuiddir"}, {Opt_data_writeback, "data=writeback"}, {Opt_data_ordered, "data=ordered"}, + {Opt_meta, "meta"}, {Opt_err, NULL} }; @@ -239,6 +241,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) case Opt_data_ordered: args->ar_data = GFS2_DATA_ORDERED; break; + case Opt_meta: + if (remount && args->ar_meta != 1) + goto cant_remount; + args->ar_meta = 1; + break; case Opt_err: default: fs_info(sdp, "unknown option: %s\n", o); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index b4d1d649063..a6225cce2cb 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -40,6 +40,45 @@ #define DO 0 #define UNDO 1 +static const u32 gfs2_old_fs_formats[] = { + 0 +}; + +static const u32 gfs2_old_multihost_formats[] = { + 0 +}; + +/** + * gfs2_tune_init - Fill a gfs2_tune structure with default values + * @gt: tune + * + */ + +static void gfs2_tune_init(struct gfs2_tune *gt) +{ + spin_lock_init(>->gt_spin); + + gt->gt_demote_secs = 300; + gt->gt_incore_log_blocks = 1024; + gt->gt_log_flush_secs = 60; + gt->gt_recoverd_secs = 60; + gt->gt_logd_secs = 1; + gt->gt_quotad_secs = 5; + gt->gt_quota_simul_sync = 64; + gt->gt_quota_warn_period = 10; + gt->gt_quota_scale_num = 1; + gt->gt_quota_scale_den = 1; + gt->gt_quota_cache_secs = 300; + gt->gt_quota_quantum = 60; + gt->gt_atime_quantum = 3600; + gt->gt_new_files_jdata = 0; + gt->gt_max_readahead = 1 << 18; + gt->gt_stall_secs = 600; + gt->gt_complain_secs = 10; + gt->gt_statfs_quantum = 30; + gt->gt_statfs_slow = 0; +} + static struct gfs2_sbd *init_sbd(struct super_block *sb) { struct gfs2_sbd *sdp; @@ -113,6 +152,272 @@ static void init_vfs(struct super_block *sb, unsigned noatime) sb->s_flags |= MS_NOATIME | MS_NODIRATIME; } +/** + * gfs2_check_sb - Check superblock + * @sdp: the filesystem + * @sb: The superblock + * @silent: Don't print a message if the check fails + * + * Checks the version code of the FS is one that we understand how to + * read and that the sizes of the various on-disk structures have not + * changed. + */ + +static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) +{ + unsigned int x; + + if (sb->sb_magic != GFS2_MAGIC || + sb->sb_type != GFS2_METATYPE_SB) { + if (!silent) + printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); + return -EINVAL; + } + + /* If format numbers match exactly, we're done. */ + + if (sb->sb_fs_format == GFS2_FORMAT_FS && + sb->sb_multihost_format == GFS2_FORMAT_MULTI) + return 0; + + if (sb->sb_fs_format != GFS2_FORMAT_FS) { + for (x = 0; gfs2_old_fs_formats[x]; x++) + if (gfs2_old_fs_formats[x] == sb->sb_fs_format) + break; + + if (!gfs2_old_fs_formats[x]) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_WARNING + "GFS2: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) { + for (x = 0; gfs2_old_multihost_formats[x]; x++) + if (gfs2_old_multihost_formats[x] == + sb->sb_multihost_format) + break; + + if (!gfs2_old_multihost_formats[x]) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_WARNING + "GFS2: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (!sdp->sd_args.ar_upgrade) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_INFO + "GFS2: Use the \"upgrade\" mount option to upgrade " + "the FS\n"); + printk(KERN_INFO "GFS2: See the manual for more details\n"); + return -EINVAL; + } + + return 0; +} + +static void end_bio_io_page(struct bio *bio, int error) +{ + struct page *page = bio->bi_private; + + if (!error) + SetPageUptodate(page); + else + printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); + unlock_page(page); +} + +static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) +{ + const struct gfs2_sb *str = buf; + + sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); + sb->sb_type = be32_to_cpu(str->sb_header.mh_type); + sb->sb_format = be32_to_cpu(str->sb_header.mh_format); + sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); + sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); + sb->sb_bsize = be32_to_cpu(str->sb_bsize); + sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); + sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr); + sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino); + sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr); + sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino); + + memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); + memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); +} + +/** + * gfs2_read_super - Read the gfs2 super block from disk + * @sdp: The GFS2 super block + * @sector: The location of the super block + * @error: The error code to return + * + * This uses the bio functions to read the super block from disk + * because we want to be 100% sure that we never read cached data. + * A super block is read twice only during each GFS2 mount and is + * never written to by the filesystem. The first time its read no + * locks are held, and the only details which are looked at are those + * relating to the locking protocol. Once locking is up and working, + * the sb is read again under the lock to establish the location of + * the master directory (contains pointers to journals etc) and the + * root directory. + * + * Returns: 0 on success or error + */ + +static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) +{ + struct super_block *sb = sdp->sd_vfs; + struct gfs2_sb *p; + struct page *page; + struct bio *bio; + + page = alloc_page(GFP_NOFS); + if (unlikely(!page)) + return -ENOBUFS; + + ClearPageUptodate(page); + ClearPageDirty(page); + lock_page(page); + + bio = bio_alloc(GFP_NOFS, 1); + if (unlikely(!bio)) { + __free_page(page); + return -ENOBUFS; + } + + bio->bi_sector = sector * (sb->s_blocksize >> 9); + bio->bi_bdev = sb->s_bdev; + bio_add_page(bio, page, PAGE_SIZE, 0); + + bio->bi_end_io = end_bio_io_page; + bio->bi_private = page; + submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); + wait_on_page_locked(page); + bio_put(bio); + if (!PageUptodate(page)) { + __free_page(page); + return -EIO; + } + p = kmap(page); + gfs2_sb_in(&sdp->sd_sb, p); + kunmap(page); + __free_page(page); + return 0; +} +/** + * gfs2_read_sb - Read super block + * @sdp: The GFS2 superblock + * @gl: the glock for the superblock (assumed to be held) + * @silent: Don't print message if mount fails + * + */ + +static int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) +{ + u32 hash_blocks, ind_blocks, leaf_blocks; + u32 tmp_blocks; + unsigned int x; + int error; + + error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); + if (error) { + if (!silent) + fs_err(sdp, "can't read superblock\n"); + return error; + } + + error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); + if (error) + return error; + + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - + GFS2_BASIC_BLOCK_SHIFT; + sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; + sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode)) / sizeof(u64); + sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_meta_header)) / sizeof(u64); + sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header); + sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2; + sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1; + sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64); + sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_meta_header)) / + sizeof(struct gfs2_quota_change); + + /* Compute maximum reservation required to add a entry to a directory */ + + hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH), + sdp->sd_jbsize); + + ind_blocks = 0; + for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) { + tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs); + ind_blocks += tmp_blocks; + } + + leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH; + + sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks; + + sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode); + sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs; + for (x = 2;; x++) { + u64 space, d; + u32 m; + + space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_heightsize[x - 1] || m) + break; + sdp->sd_heightsize[x] = space; + } + sdp->sd_max_height = x; + sdp->sd_heightsize[x] = ~0; + gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); + + sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode); + sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs; + for (x = 2;; x++) { + u64 space, d; + u32 m; + + space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_jheightsize[x - 1] || m) + break; + sdp->sd_jheightsize[x] = space; + } + sdp->sd_max_jheight = x; + sdp->sd_jheightsize[x] = ~0; + gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); + + return 0; +} + static int init_names(struct gfs2_sbd *sdp, int silent) { char *proto, *table; @@ -224,51 +529,59 @@ fail: return error; } -static inline struct inode *gfs2_lookup_root(struct super_block *sb, - u64 no_addr) +static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr, + u64 no_addr, const char *name) { - return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); + struct gfs2_sbd *sdp = sb->s_fs_info; + struct dentry *dentry; + struct inode *inode; + + inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); + if (IS_ERR(inode)) { + fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); + return PTR_ERR(inode); + } + dentry = d_alloc_root(inode); + if (!dentry) { + fs_err(sdp, "can't alloc %s dentry\n", name); + iput(inode); + return -ENOMEM; + } + dentry->d_op = &gfs2_dops; + *dptr = dentry; + return 0; } -static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) +static int init_sb(struct gfs2_sbd *sdp, int silent) { struct super_block *sb = sdp->sd_vfs; struct gfs2_holder sb_gh; u64 no_addr; - struct inode *inode; - int error = 0; + int ret; - if (undo) { - if (sb->s_root) { - dput(sb->s_root); - sb->s_root = NULL; - } - return 0; + ret = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops, + LM_ST_SHARED, 0, &sb_gh); + if (ret) { + fs_err(sdp, "can't acquire superblock glock: %d\n", ret); + return ret; } - error = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops, - LM_ST_SHARED, 0, &sb_gh); - if (error) { - fs_err(sdp, "can't acquire superblock glock: %d\n", error); - return error; - } - - error = gfs2_read_sb(sdp, sb_gh.gh_gl, silent); - if (error) { - fs_err(sdp, "can't read superblock: %d\n", error); + ret = gfs2_read_sb(sdp, sb_gh.gh_gl, silent); + if (ret) { + fs_err(sdp, "can't read superblock: %d\n", ret); goto out; } /* Set up the buffer cache and SB for real */ if (sdp->sd_sb.sb_bsize < bdev_hardsect_size(sb->s_bdev)) { - error = -EINVAL; + ret = -EINVAL; fs_err(sdp, "FS block size (%u) is too small for device " "block size (%u)\n", sdp->sd_sb.sb_bsize, bdev_hardsect_size(sb->s_bdev)); goto out; } if (sdp->sd_sb.sb_bsize > PAGE_SIZE) { - error = -EINVAL; + ret = -EINVAL; fs_err(sdp, "FS block size (%u) is too big for machine " "page size (%u)\n", sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); @@ -278,26 +591,21 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) /* Get the root inode */ no_addr = sdp->sd_sb.sb_root_dir.no_addr; - if (sb->s_type == &gfs2meta_fs_type) - no_addr = sdp->sd_sb.sb_master_dir.no_addr; - inode = gfs2_lookup_root(sb, no_addr); - if (IS_ERR(inode)) { - error = PTR_ERR(inode); - fs_err(sdp, "can't read in root inode: %d\n", error); + ret = gfs2_lookup_root(sb, &sdp->sd_root_dir, no_addr, "root"); + if (ret) goto out; - } - sb->s_root = d_alloc_root(inode); - if (!sb->s_root) { - fs_err(sdp, "can't get root dentry\n"); - error = -ENOMEM; - iput(inode); - } else - sb->s_root->d_op = &gfs2_dops; - + /* Get the master inode */ + no_addr = sdp->sd_sb.sb_master_dir.no_addr; + ret = gfs2_lookup_root(sb, &sdp->sd_master_dir, no_addr, "master"); + if (ret) { + dput(sdp->sd_root_dir); + goto out; + } + sb->s_root = dget(sdp->sd_args.ar_meta ? sdp->sd_master_dir : sdp->sd_root_dir); out: gfs2_glock_dq_uninit(&sb_gh); - return error; + return ret; } /** @@ -372,6 +680,7 @@ static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) static int init_journal(struct gfs2_sbd *sdp, int undo) { + struct inode *master = sdp->sd_master_dir->d_inode; struct gfs2_holder ji_gh; struct task_struct *p; struct gfs2_inode *ip; @@ -383,7 +692,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) goto fail_recoverd; } - sdp->sd_jindex = gfs2_lookup_simple(sdp->sd_master_dir, "jindex"); + sdp->sd_jindex = gfs2_lookup_simple(master, "jindex"); if (IS_ERR(sdp->sd_jindex)) { fs_err(sdp, "can't lookup journal index: %d\n", error); return PTR_ERR(sdp->sd_jindex); @@ -506,25 +815,17 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) { int error = 0; struct gfs2_inode *ip; - struct inode *inode; + struct inode *master = sdp->sd_master_dir->d_inode; if (undo) goto fail_qinode; - inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr); - if (IS_ERR(inode)) { - error = PTR_ERR(inode); - fs_err(sdp, "can't read in master directory: %d\n", error); - goto fail; - } - sdp->sd_master_dir = inode; - error = init_journal(sdp, undo); if (error) - goto fail_master; + goto fail; /* Read in the master inode number inode */ - sdp->sd_inum_inode = gfs2_lookup_simple(sdp->sd_master_dir, "inum"); + sdp->sd_inum_inode = gfs2_lookup_simple(master, "inum"); if (IS_ERR(sdp->sd_inum_inode)) { error = PTR_ERR(sdp->sd_inum_inode); fs_err(sdp, "can't read in inum inode: %d\n", error); @@ -533,7 +834,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) /* Read in the master statfs inode */ - sdp->sd_statfs_inode = gfs2_lookup_simple(sdp->sd_master_dir, "statfs"); + sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs"); if (IS_ERR(sdp->sd_statfs_inode)) { error = PTR_ERR(sdp->sd_statfs_inode); fs_err(sdp, "can't read in statfs inode: %d\n", error); @@ -541,7 +842,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) } /* Read in the resource index inode */ - sdp->sd_rindex = gfs2_lookup_simple(sdp->sd_master_dir, "rindex"); + sdp->sd_rindex = gfs2_lookup_simple(master, "rindex"); if (IS_ERR(sdp->sd_rindex)) { error = PTR_ERR(sdp->sd_rindex); fs_err(sdp, "can't get resource index inode: %d\n", error); @@ -552,7 +853,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) sdp->sd_rindex_uptodate = 0; /* Read in the quota inode */ - sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota"); + sdp->sd_quota_inode = gfs2_lookup_simple(master, "quota"); if (IS_ERR(sdp->sd_quota_inode)) { error = PTR_ERR(sdp->sd_quota_inode); fs_err(sdp, "can't get quota file inode: %d\n", error); @@ -571,8 +872,6 @@ fail_inum: iput(sdp->sd_inum_inode); fail_journal: init_journal(sdp, UNDO); -fail_master: - iput(sdp->sd_master_dir); fail: return error; } @@ -583,6 +882,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) char buf[30]; int error = 0; struct gfs2_inode *ip; + struct inode *master = sdp->sd_master_dir->d_inode; if (sdp->sd_args.ar_spectator) return 0; @@ -590,7 +890,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) if (undo) goto fail_qc_gh; - pn = gfs2_lookup_simple(sdp->sd_master_dir, "per_node"); + pn = gfs2_lookup_simple(master, "per_node"); if (IS_ERR(pn)) { error = PTR_ERR(pn); fs_err(sdp, "can't find per_node directory: %d\n", error); @@ -828,7 +1128,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) if (error) goto fail_lm; - error = init_sb(sdp, silent, DO); + error = init_sb(sdp, silent); if (error) goto fail_locking; @@ -869,7 +1169,11 @@ fail_per_node: fail_inodes: init_inodes(sdp, UNDO); fail_sb: - init_sb(sdp, 0, UNDO); + if (sdp->sd_root_dir) + dput(sdp->sd_root_dir); + if (sdp->sd_master_dir) + dput(sdp->sd_master_dir); + sb->s_root = NULL; fail_locking: init_locking(sdp, &mount_gh, UNDO); fail_lm: @@ -887,151 +1191,60 @@ fail: } static int gfs2_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data, struct vfsmount *mnt) + const char *dev_name, void *data, struct vfsmount *mnt) { - struct super_block *sb; - struct gfs2_sbd *sdp; - int error = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); - if (error) - goto out; - sb = mnt->mnt_sb; - sdp = sb->s_fs_info; - sdp->sd_gfs2mnt = mnt; -out: - return error; + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); } -static int fill_super_meta(struct super_block *sb, struct super_block *new, - void *data, int silent) +static struct super_block *get_gfs2_sb(const char *dev_name) { - struct gfs2_sbd *sdp = sb->s_fs_info; - struct inode *inode; - int error = 0; - - new->s_fs_info = sdp; - sdp->sd_vfs_meta = sb; - - init_vfs(new, SDF_NOATIME); - - /* Get the master inode */ - inode = igrab(sdp->sd_master_dir); - - new->s_root = d_alloc_root(inode); - if (!new->s_root) { - fs_err(sdp, "can't get root dentry\n"); - error = -ENOMEM; - iput(inode); - } else - new->s_root->d_op = &gfs2_dops; - - return error; -} - -static int set_bdev_super(struct super_block *s, void *data) -{ - s->s_bdev = data; - s->s_dev = s->s_bdev->bd_dev; - return 0; -} - -static int test_bdev_super(struct super_block *s, void *data) -{ - return s->s_bdev == data; -} - -static struct super_block* get_gfs2_sb(const char *dev_name) -{ - struct kstat stat; + struct super_block *sb; struct nameidata nd; - struct super_block *sb = NULL, *s; int error; error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); if (error) { - printk(KERN_WARNING "GFS2: path_lookup on %s returned error\n", - dev_name); - goto out; - } - error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); - - list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) { - if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || - (S_ISDIR(stat.mode) && - s == nd.path.dentry->d_inode->i_sb)) { - sb = s; - goto free_nd; - } + printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", + dev_name, error); + return NULL; } - - printk(KERN_WARNING "GFS2: Unrecognized block device or " - "mount point %s\n", dev_name); - -free_nd: + sb = nd.path.dentry->d_inode->i_sb; + if (sb && (sb->s_type == &gfs2_fs_type)) + atomic_inc(&sb->s_active); + else + sb = NULL; path_put(&nd.path); -out: return sb; } static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int error = 0; - struct super_block *sb = NULL, *new; + struct super_block *sb = NULL; struct gfs2_sbd *sdp; sb = get_gfs2_sb(dev_name); if (!sb) { printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); - error = -ENOENT; - goto error; + return -ENOENT; } sdp = sb->s_fs_info; - if (sdp->sd_vfs_meta) { - printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); - error = -EBUSY; - goto error; - } - down(&sb->s_bdev->bd_mount_sem); - new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev); - up(&sb->s_bdev->bd_mount_sem); - if (IS_ERR(new)) { - error = PTR_ERR(new); - goto error; - } - new->s_flags = flags; - strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); - sb_set_blocksize(new, sb->s_blocksize); - error = fill_super_meta(sb, new, data, flags & MS_SILENT ? 1 : 0); - if (error) { - up_write(&new->s_umount); - deactivate_super(new); - goto error; - } - - new->s_flags |= MS_ACTIVE; - - /* Grab a reference to the gfs2 mount point */ - atomic_inc(&sdp->sd_gfs2mnt->mnt_count); - return simple_set_mnt(mnt, new); -error: - return error; + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sdp->sd_master_dir); + return 0; } static void gfs2_kill_sb(struct super_block *sb) -{ - if (sb->s_fs_info) { - gfs2_delete_debugfs_file(sb->s_fs_info); - gfs2_meta_syncfs(sb->s_fs_info); - } - kill_block_super(sb); -} - -static void gfs2_kill_sb_meta(struct super_block *sb) { struct gfs2_sbd *sdp = sb->s_fs_info; - generic_shutdown_super(sb); - sdp->sd_vfs_meta = NULL; - atomic_dec(&sdp->sd_gfs2mnt->mnt_count); + gfs2_meta_syncfs(sdp); + dput(sdp->sd_root_dir); + dput(sdp->sd_master_dir); + sdp->sd_root_dir = NULL; + sdp->sd_master_dir = NULL; + shrink_dcache_sb(sb); + kill_block_super(sb); + gfs2_delete_debugfs_file(sdp); } struct file_system_type gfs2_fs_type = { @@ -1046,7 +1259,6 @@ struct file_system_type gfs2meta_fs_type = { .name = "gfs2meta", .fs_flags = FS_REQUIRES_DEV, .get_sb = gfs2_get_sb_meta, - .kill_sb = gfs2_kill_sb_meta, .owner = THIS_MODULE, }; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index f66ea0f7a35..8f332d26b5d 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -62,6 +62,39 @@ static int gfs2_write_inode(struct inode *inode, int sync) return 0; } +/** + * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one + * @sdp: the filesystem + * + * Returns: errno + */ + +static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) +{ + struct gfs2_holder t_gh; + int error; + + gfs2_quota_sync(sdp); + gfs2_statfs_sync(sdp); + + error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, + &t_gh); + if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + return error; + + gfs2_meta_syncfs(sdp); + gfs2_log_shutdown(sdp); + + clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); + + if (t_gh.gh_gl) + gfs2_glock_dq_uninit(&t_gh); + + gfs2_quota_cleanup(sdp); + + return error; +} + /** * gfs2_put_super - Unmount the filesystem * @sb: The VFS superblock @@ -73,12 +106,6 @@ static void gfs2_put_super(struct super_block *sb) struct gfs2_sbd *sdp = sb->s_fs_info; int error; - if (!sdp) - return; - - if (!strncmp(sb->s_type->name, "gfs2meta", 8)) - return; /* Nothing to do */ - /* Unfreeze the filesystem, if we need to */ mutex_lock(&sdp->sd_freeze_lock); @@ -101,7 +128,6 @@ static void gfs2_put_super(struct super_block *sb) /* Release stuff */ - iput(sdp->sd_master_dir); iput(sdp->sd_jindex); iput(sdp->sd_inum_inode); iput(sdp->sd_statfs_inode); @@ -152,6 +178,7 @@ static void gfs2_write_super(struct super_block *sb) * * Flushes the log to disk. */ + static int gfs2_sync_fs(struct super_block *sb, int wait) { sb->s_dirt = 0; @@ -295,6 +322,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) * inode's blocks, or alternatively pass the baton on to another * node for later deallocation. */ + static void gfs2_drop_inode(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); @@ -333,6 +361,16 @@ static void gfs2_clear_inode(struct inode *inode) } } +static int is_ancestor(const struct dentry *d1, const struct dentry *d2) +{ + do { + if (d1 == d2) + return 1; + d1 = d1->d_parent; + } while (!IS_ROOT(d1)); + return 0; +} + /** * gfs2_show_options - Show mount options for /proc/mounts * @s: seq_file structure @@ -346,6 +384,8 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; struct gfs2_args *args = &sdp->sd_args; + if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) + seq_printf(s, ",meta"); if (args->ar_lockproto[0]) seq_printf(s, ",lockproto=%s", args->ar_lockproto); if (args->ar_locktable[0]) @@ -414,6 +454,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) * conversion on the iopen lock, but we can change that later. This * is safe, just less efficient. */ + static void gfs2_delete_inode(struct inode *inode) { struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; @@ -478,8 +519,6 @@ out: clear_inode(inode); } - - static struct inode *gfs2_alloc_inode(struct super_block *sb) { struct gfs2_inode *ip; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ca831991cbc..c3ba3d9d0aa 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -33,313 +33,6 @@ #include "trans.h" #include "util.h" -static const u32 gfs2_old_fs_formats[] = { - 0 -}; - -static const u32 gfs2_old_multihost_formats[] = { - 0 -}; - -/** - * gfs2_tune_init - Fill a gfs2_tune structure with default values - * @gt: tune - * - */ - -void gfs2_tune_init(struct gfs2_tune *gt) -{ - spin_lock_init(>->gt_spin); - - gt->gt_demote_secs = 300; - gt->gt_incore_log_blocks = 1024; - gt->gt_log_flush_secs = 60; - gt->gt_recoverd_secs = 60; - gt->gt_logd_secs = 1; - gt->gt_quotad_secs = 5; - gt->gt_quota_simul_sync = 64; - gt->gt_quota_warn_period = 10; - gt->gt_quota_scale_num = 1; - gt->gt_quota_scale_den = 1; - gt->gt_quota_cache_secs = 300; - gt->gt_quota_quantum = 60; - gt->gt_atime_quantum = 3600; - gt->gt_new_files_jdata = 0; - gt->gt_max_readahead = 1 << 18; - gt->gt_stall_secs = 600; - gt->gt_complain_secs = 10; - gt->gt_statfs_quantum = 30; - gt->gt_statfs_slow = 0; -} - -/** - * gfs2_check_sb - Check superblock - * @sdp: the filesystem - * @sb: The superblock - * @silent: Don't print a message if the check fails - * - * Checks the version code of the FS is one that we understand how to - * read and that the sizes of the various on-disk structures have not - * changed. - */ - -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) -{ - unsigned int x; - - if (sb->sb_magic != GFS2_MAGIC || - sb->sb_type != GFS2_METATYPE_SB) { - if (!silent) - printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); - return -EINVAL; - } - - /* If format numbers match exactly, we're done. */ - - if (sb->sb_fs_format == GFS2_FORMAT_FS && - sb->sb_multihost_format == GFS2_FORMAT_MULTI) - return 0; - - if (sb->sb_fs_format != GFS2_FORMAT_FS) { - for (x = 0; gfs2_old_fs_formats[x]; x++) - if (gfs2_old_fs_formats[x] == sb->sb_fs_format) - break; - - if (!gfs2_old_fs_formats[x]) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_WARNING - "GFS2: I don't know how to upgrade this FS\n"); - return -EINVAL; - } - } - - if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) { - for (x = 0; gfs2_old_multihost_formats[x]; x++) - if (gfs2_old_multihost_formats[x] == - sb->sb_multihost_format) - break; - - if (!gfs2_old_multihost_formats[x]) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_WARNING - "GFS2: I don't know how to upgrade this FS\n"); - return -EINVAL; - } - } - - if (!sdp->sd_args.ar_upgrade) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_INFO - "GFS2: Use the \"upgrade\" mount option to upgrade " - "the FS\n"); - printk(KERN_INFO "GFS2: See the manual for more details\n"); - return -EINVAL; - } - - return 0; -} - - -static void end_bio_io_page(struct bio *bio, int error) -{ - struct page *page = bio->bi_private; - - if (!error) - SetPageUptodate(page); - else - printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); - unlock_page(page); -} - -static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) -{ - const struct gfs2_sb *str = buf; - - sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); - sb->sb_type = be32_to_cpu(str->sb_header.mh_type); - sb->sb_format = be32_to_cpu(str->sb_header.mh_format); - sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); - sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); - sb->sb_bsize = be32_to_cpu(str->sb_bsize); - sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); - sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr); - sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino); - sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr); - sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino); - - memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); - memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); -} - -/** - * gfs2_read_super - Read the gfs2 super block from disk - * @sdp: The GFS2 super block - * @sector: The location of the super block - * @error: The error code to return - * - * This uses the bio functions to read the super block from disk - * because we want to be 100% sure that we never read cached data. - * A super block is read twice only during each GFS2 mount and is - * never written to by the filesystem. The first time its read no - * locks are held, and the only details which are looked at are those - * relating to the locking protocol. Once locking is up and working, - * the sb is read again under the lock to establish the location of - * the master directory (contains pointers to journals etc) and the - * root directory. - * - * Returns: 0 on success or error - */ - -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) -{ - struct super_block *sb = sdp->sd_vfs; - struct gfs2_sb *p; - struct page *page; - struct bio *bio; - - page = alloc_page(GFP_NOFS); - if (unlikely(!page)) - return -ENOBUFS; - - ClearPageUptodate(page); - ClearPageDirty(page); - lock_page(page); - - bio = bio_alloc(GFP_NOFS, 1); - if (unlikely(!bio)) { - __free_page(page); - return -ENOBUFS; - } - - bio->bi_sector = sector * (sb->s_blocksize >> 9); - bio->bi_bdev = sb->s_bdev; - bio_add_page(bio, page, PAGE_SIZE, 0); - - bio->bi_end_io = end_bio_io_page; - bio->bi_private = page; - submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); - wait_on_page_locked(page); - bio_put(bio); - if (!PageUptodate(page)) { - __free_page(page); - return -EIO; - } - p = kmap(page); - gfs2_sb_in(&sdp->sd_sb, p); - kunmap(page); - __free_page(page); - return 0; -} - -/** - * gfs2_read_sb - Read super block - * @sdp: The GFS2 superblock - * @gl: the glock for the superblock (assumed to be held) - * @silent: Don't print message if mount fails - * - */ - -int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) -{ - u32 hash_blocks, ind_blocks, leaf_blocks; - u32 tmp_blocks; - unsigned int x; - int error; - - error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); - if (error) { - if (!silent) - fs_err(sdp, "can't read superblock\n"); - return error; - } - - error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); - if (error) - return error; - - sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - - GFS2_BASIC_BLOCK_SHIFT; - sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; - sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode)) / sizeof(u64); - sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_meta_header)) / sizeof(u64); - sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header); - sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2; - sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1; - sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64); - sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_meta_header)) / - sizeof(struct gfs2_quota_change); - - /* Compute maximum reservation required to add a entry to a directory */ - - hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH), - sdp->sd_jbsize); - - ind_blocks = 0; - for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) { - tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs); - ind_blocks += tmp_blocks; - } - - leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH; - - sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks; - - sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode); - sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs; - for (x = 2;; x++) { - u64 space, d; - u32 m; - - space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs; - d = space; - m = do_div(d, sdp->sd_inptrs); - - if (d != sdp->sd_heightsize[x - 1] || m) - break; - sdp->sd_heightsize[x] = space; - } - sdp->sd_max_height = x; - sdp->sd_heightsize[x] = ~0; - gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); - - sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode); - sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs; - for (x = 2;; x++) { - u64 space, d; - u32 m; - - space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs; - d = space; - m = do_div(d, sdp->sd_inptrs); - - if (d != sdp->sd_jheightsize[x - 1] || m) - break; - sdp->sd_jheightsize[x] = space; - } - sdp->sd_max_jheight = x; - sdp->sd_jheightsize[x] = ~0; - gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); - - return 0; -} - /** * gfs2_jindex_hold - Grab a lock on the jindex * @sdp: The GFS2 superblock @@ -581,39 +274,6 @@ fail: return error; } -/** - * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one - * @sdp: the filesystem - * - * Returns: errno - */ - -int gfs2_make_fs_ro(struct gfs2_sbd *sdp) -{ - struct gfs2_holder t_gh; - int error; - - gfs2_quota_sync(sdp); - gfs2_statfs_sync(sdp); - - error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, - &t_gh); - if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) - return error; - - gfs2_meta_syncfs(sdp); - gfs2_log_shutdown(sdp); - - clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); - - if (t_gh.gh_gl) - gfs2_glock_dq_uninit(&t_gh); - - gfs2_quota_cleanup(sdp); - - return error; -} - static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) { const struct gfs2_statfs_change *str = buf; diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 44361ecc44f..50a4c9b1215 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -12,11 +12,6 @@ #include "incore.h" -void gfs2_tune_init(struct gfs2_tune *gt); - -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); -int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); void gfs2_lm_unmount(struct gfs2_sbd *sdp); static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) @@ -40,7 +35,6 @@ int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename, struct gfs2_inode **ipp); int gfs2_make_fs_rw(struct gfs2_sbd *sdp); -int gfs2_make_fs_ro(struct gfs2_sbd *sdp); int gfs2_statfs_init(struct gfs2_sbd *sdp); void gfs2_statfs_change(struct gfs2_sbd *sdp, -- GitLab From 72dbf4790fc6736f9cb54424245114acf0b0038c Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Tue, 12 Aug 2008 13:39:29 -0500 Subject: [PATCH 0291/5416] GFS2: rm on multiple nodes causes panic This patch fixes a problem whereby simultaneous unlink, rmdir, rename and link operations (e.g. rm -fR *) from multiple nodes on the same GFS2 file system can cause kernel panics, hangs, and/or memory corruption. It also gets rid of all the non-rgrp calls to gfs2_glock_nq_m. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_inode.c | 56 ++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index e2c62f73a77..35f6f032a02 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -159,9 +159,13 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); - error = gfs2_glock_nq_m(2, ghs); + error = gfs2_glock_nq(ghs); /* parent */ if (error) - goto out; + goto out_parent; + + error = gfs2_glock_nq(ghs + 1); /* child */ + if (error) + goto out_child; error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC); if (error) @@ -245,8 +249,10 @@ out_alloc: if (alloc_required) gfs2_alloc_put(dip); out_gunlock: - gfs2_glock_dq_m(2, ghs); -out: + gfs2_glock_dq(ghs + 1); +out_child: + gfs2_glock_dq(ghs); +out_parent: gfs2_holder_uninit(ghs); gfs2_holder_uninit(ghs + 1); if (!error) { @@ -302,7 +308,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) error = gfs2_unlink_ok(dip, &dentry->d_name, ip); if (error) - goto out_rgrp; + goto out_gunlock; error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); if (error) @@ -316,6 +322,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) out_end_trans: gfs2_trans_end(sdp); +out_gunlock: gfs2_glock_dq(ghs + 2); out_rgrp: gfs2_holder_uninit(ghs + 2); @@ -485,7 +492,6 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) struct gfs2_holder ri_gh; int error; - error = gfs2_rindex_hold(sdp, &ri_gh); if (error) return error; @@ -495,9 +501,17 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); - error = gfs2_glock_nq_m(3, ghs); + error = gfs2_glock_nq(ghs); /* parent */ if (error) - goto out; + goto out_parent; + + error = gfs2_glock_nq(ghs + 1); /* child */ + if (error) + goto out_child; + + error = gfs2_glock_nq(ghs + 2); /* rgrp */ + if (error) + goto out_rgrp; error = gfs2_unlink_ok(dip, &dentry->d_name, ip); if (error) @@ -523,11 +537,15 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) gfs2_trans_end(sdp); out_gunlock: - gfs2_glock_dq_m(3, ghs); -out: - gfs2_holder_uninit(ghs); - gfs2_holder_uninit(ghs + 1); + gfs2_glock_dq(ghs + 2); +out_rgrp: gfs2_holder_uninit(ghs + 2); + gfs2_glock_dq(ghs + 1); +out_child: + gfs2_holder_uninit(ghs + 1); + gfs2_glock_dq(ghs); +out_parent: + gfs2_holder_uninit(ghs); gfs2_glock_dq_uninit(&ri_gh); return error; } @@ -639,9 +657,11 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); } - error = gfs2_glock_nq_m(num_gh, ghs); - if (error) - goto out_uninit; + for (x = 0; x < num_gh; x++) { + error = gfs2_glock_nq(ghs + x); + if (error) + goto out_gunlock; + } /* Check out the old directory */ @@ -804,10 +824,10 @@ out_alloc: if (alloc_required) gfs2_alloc_put(ndip); out_gunlock: - gfs2_glock_dq_m(num_gh, ghs); -out_uninit: - for (x = 0; x < num_gh; x++) + while (x--) { + gfs2_glock_dq(ghs + x); gfs2_holder_uninit(ghs + x); + } out_gunlock_r: if (dir_rename) gfs2_glock_dq_uninit(&r_gh); -- GitLab From e88ba01544f8b8cce64d08b2982715516793225c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 6 Aug 2008 13:18:26 +0100 Subject: [PATCH 0292/5416] ALSA: ASoC: Add WM8580 CODEC driver The WM8580 is an audio CODEC designed for DVD and surround sound applications, offering three stereo DACs and a stereo ADC. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm8580.c | 1055 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm8580.h | 42 ++ 4 files changed, 1103 insertions(+) create mode 100644 sound/soc/codecs/wm8580.c create mode 100644 sound/soc/codecs/wm8580.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d7bacf6c529..eb79c5cab47 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -5,6 +5,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AK4535 select SND_SOC_UDA1380 select SND_SOC_WM8510 + select SND_SOC_WM8580 select SND_SOC_WM8731 select SND_SOC_WM8750 select SND_SOC_WM8753 @@ -38,6 +39,9 @@ config SND_SOC_UDA1380 config SND_SOC_WM8510 tristate +config SND_SOC_WM8580 + tristate + config SND_SOC_WM8731 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 98808d945de..7c694ca6b85 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -3,6 +3,7 @@ snd-soc-ad1980-objs := ad1980.o snd-soc-ak4535-objs := ak4535.o snd-soc-uda1380-objs := uda1380.o snd-soc-wm8510-objs := wm8510.o +snd-soc-wm8580-objs := wm8580.o snd-soc-wm8731-objs := wm8731.o snd-soc-wm8750-objs := wm8750.o snd-soc-wm8753-objs := wm8753.o @@ -19,6 +20,7 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o +obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c new file mode 100644 index 00000000000..df1ffbe305b --- /dev/null +++ b/sound/soc/codecs/wm8580.c @@ -0,0 +1,1055 @@ +/* + * wm8580.c -- WM8580 ALSA Soc Audio driver + * + * Copyright 2008 Wolfson Microelectronics PLC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Notes: + * The WM8580 is a multichannel codec with S/PDIF support, featuring six + * DAC channels and two ADC channels. + * + * Currently only the primary audio interface is supported - S/PDIF and + * the secondary audio interfaces are not. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm8580.h" + +#define AUDIO_NAME "wm8580" +#define WM8580_VERSION "0.1" + +struct pll_state { + unsigned int in; + unsigned int out; +}; + +/* codec private data */ +struct wm8580_priv { + struct pll_state a; + struct pll_state b; +}; + +/* WM8580 register space */ +#define WM8580_PLLA1 0x00 +#define WM8580_PLLA2 0x01 +#define WM8580_PLLA3 0x02 +#define WM8580_PLLA4 0x03 +#define WM8580_PLLB1 0x04 +#define WM8580_PLLB2 0x05 +#define WM8580_PLLB3 0x06 +#define WM8580_PLLB4 0x07 +#define WM8580_CLKSEL 0x08 +#define WM8580_PAIF1 0x09 +#define WM8580_PAIF2 0x0A +#define WM8580_SAIF1 0x0B +#define WM8580_PAIF3 0x0C +#define WM8580_PAIF4 0x0D +#define WM8580_SAIF2 0x0E +#define WM8580_DAC_CONTROL1 0x0F +#define WM8580_DAC_CONTROL2 0x10 +#define WM8580_DAC_CONTROL3 0x11 +#define WM8580_DAC_CONTROL4 0x12 +#define WM8580_DAC_CONTROL5 0x13 +#define WM8580_DIGITAL_ATTENUATION_DACL1 0x14 +#define WM8580_DIGITAL_ATTENUATION_DACR1 0x15 +#define WM8580_DIGITAL_ATTENUATION_DACL2 0x16 +#define WM8580_DIGITAL_ATTENUATION_DACR2 0x17 +#define WM8580_DIGITAL_ATTENUATION_DACL3 0x18 +#define WM8580_DIGITAL_ATTENUATION_DACR3 0x19 +#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C +#define WM8580_ADC_CONTROL1 0x1D +#define WM8580_SPDTXCHAN0 0x1E +#define WM8580_SPDTXCHAN1 0x1F +#define WM8580_SPDTXCHAN2 0x20 +#define WM8580_SPDTXCHAN3 0x21 +#define WM8580_SPDTXCHAN4 0x22 +#define WM8580_SPDTXCHAN5 0x23 +#define WM8580_SPDMODE 0x24 +#define WM8580_INTMASK 0x25 +#define WM8580_GPO1 0x26 +#define WM8580_GPO2 0x27 +#define WM8580_GPO3 0x28 +#define WM8580_GPO4 0x29 +#define WM8580_GPO5 0x2A +#define WM8580_INTSTAT 0x2B +#define WM8580_SPDRXCHAN1 0x2C +#define WM8580_SPDRXCHAN2 0x2D +#define WM8580_SPDRXCHAN3 0x2E +#define WM8580_SPDRXCHAN4 0x2F +#define WM8580_SPDRXCHAN5 0x30 +#define WM8580_SPDSTAT 0x31 +#define WM8580_PWRDN1 0x32 +#define WM8580_PWRDN2 0x33 +#define WM8580_READBACK 0x34 +#define WM8580_RESET 0x35 + +/* PLLB4 (register 7h) */ +#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 +#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 +#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40 +#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60 + +#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180 +#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080 +#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100 +#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180 + +/* CLKSEL (register 8h) */ +#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03 +#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01 +#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02 + +/* AIF control 1 (registers 9h-bh) */ +#define WM8580_AIF_RATE_MASK 0x7 +#define WM8580_AIF_RATE_128 0x0 +#define WM8580_AIF_RATE_192 0x1 +#define WM8580_AIF_RATE_256 0x2 +#define WM8580_AIF_RATE_384 0x3 +#define WM8580_AIF_RATE_512 0x4 +#define WM8580_AIF_RATE_768 0x5 +#define WM8580_AIF_RATE_1152 0x6 + +#define WM8580_AIF_BCLKSEL_MASK 0x18 +#define WM8580_AIF_BCLKSEL_64 0x00 +#define WM8580_AIF_BCLKSEL_128 0x08 +#define WM8580_AIF_BCLKSEL_256 0x10 +#define WM8580_AIF_BCLKSEL_SYSCLK 0x18 + +#define WM8580_AIF_MS 0x20 + +#define WM8580_AIF_CLKSRC_MASK 0xc0 +#define WM8580_AIF_CLKSRC_PLLA 0x40 +#define WM8580_AIF_CLKSRC_PLLB 0x40 +#define WM8580_AIF_CLKSRC_MCLK 0xc0 + +/* AIF control 2 (registers ch-eh) */ +#define WM8580_AIF_FMT_MASK 0x03 +#define WM8580_AIF_FMT_RIGHTJ 0x00 +#define WM8580_AIF_FMT_LEFTJ 0x01 +#define WM8580_AIF_FMT_I2S 0x02 +#define WM8580_AIF_FMT_DSP 0x03 + +#define WM8580_AIF_LENGTH_MASK 0x0c +#define WM8580_AIF_LENGTH_16 0x00 +#define WM8580_AIF_LENGTH_20 0x04 +#define WM8580_AIF_LENGTH_24 0x08 +#define WM8580_AIF_LENGTH_32 0x0c + +#define WM8580_AIF_LRP 0x10 +#define WM8580_AIF_BCP 0x20 + +/* Powerdown Register 1 (register 32h) */ +#define WM8580_PWRDN1_PWDN 0x001 +#define WM8580_PWRDN1_ALLDACPD 0x040 + +/* Powerdown Register 2 (register 33h) */ +#define WM8580_PWRDN2_OSSCPD 0x001 +#define WM8580_PWRDN2_PLLAPD 0x002 +#define WM8580_PWRDN2_PLLBPD 0x004 +#define WM8580_PWRDN2_SPDIFPD 0x008 +#define WM8580_PWRDN2_SPDIFTXD 0x010 +#define WM8580_PWRDN2_SPDIFRXD 0x020 + +#define WM8580_DAC_CONTROL5_MUTEALL 0x10 + +/* + * wm8580 register cache + * We can't read the WM8580 register space when we + * are using 2 wire for device control, so we cache them instead. + */ +static const u16 wm8580_reg[] = { + 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ + 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ + 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ + 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ + 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ + 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ + 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ + 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ + 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ + 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ + 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ + 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ + 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ + 0x0000, 0x0000 /*R53*/ +}; + +/* + * read wm8580 register cache + */ +static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + return cache[reg]; +} + +/* + * write wm8580 register cache + */ +static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + cache[reg] = value; +} + +/* + * write to the WM8580 register space + */ +static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + + /* Registers are 9 bits wide */ + value &= 0x1ff; + + switch (reg) { + case WM8580_RESET: + /* Uncached */ + break; + default: + if (value == wm8580_read_reg_cache(codec, reg)) + return 0; + } + + /* data is + * D15..D9 WM8580 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8580_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +static inline unsigned int wm8580_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + default: + return wm8580_read_reg_cache(codec, reg); + } +} + +static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); + +static int wm8580_out_vu(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + int reg = kcontrol->private_value & 0xff; + int reg2 = (kcontrol->private_value >> 24) & 0xff; + int ret; + u16 val; + + /* Clear the register cache so we write without VU set */ + wm8580_write_reg_cache(codec, reg, 0); + wm8580_write_reg_cache(codec, reg2, 0); + + ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); + if (ret < 0) + return ret; + + /* Now write again with the volume update bit set */ + val = wm8580_read_reg_cache(codec, reg); + wm8580_write(codec, reg, val | 0x0100); + + val = wm8580_read_reg_cache(codec, reg2); + wm8580_write(codec, reg2, val | 0x0100); + + return 0; +} + +#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw_2r, \ + .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \ + .private_value = (reg_left) | ((shift) << 8) | \ + ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) } + +static const struct snd_kcontrol_new wm8580_snd_controls[] = { +SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL1, + WM8580_DIGITAL_ATTENUATION_DACR1, + 0, 0xff, 0, dac_tlv), +SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL2, + WM8580_DIGITAL_ATTENUATION_DACR2, + 0, 0xff, 0, dac_tlv), +SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL3, + WM8580_DIGITAL_ATTENUATION_DACR3, + 0, 0xff, 0, dac_tlv), + +SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), +SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), +SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0), + +SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4, 0, 1, 1, 0), +SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0), +SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0), + +SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0), +SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0), +SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0), +SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0), + +SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), +SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), +}; + +/* Add non-DAPM controls */ +static int wm8580_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&wm8580_snd_controls[i], + codec, NULL)); + if (err < 0) + return err; + } + return 0; +} +static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), +SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), +SND_SOC_DAPM_DAC("DAC3", "Playback", WM8580_PWRDN1, 4, 1), + +SND_SOC_DAPM_OUTPUT("VOUT1L"), +SND_SOC_DAPM_OUTPUT("VOUT1R"), +SND_SOC_DAPM_OUTPUT("VOUT2L"), +SND_SOC_DAPM_OUTPUT("VOUT2R"), +SND_SOC_DAPM_OUTPUT("VOUT3L"), +SND_SOC_DAPM_OUTPUT("VOUT3R"), + +SND_SOC_DAPM_ADC("ADC", "Capture", WM8580_PWRDN1, 1, 1), + +SND_SOC_DAPM_INPUT("AINL"), +SND_SOC_DAPM_INPUT("AINR"), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + { "VOUT1L", NULL, "DAC1" }, + { "VOUT1R", NULL, "DAC1" }, + + { "VOUT2L", NULL, "DAC2" }, + { "VOUT2R", NULL, "DAC2" }, + + { "VOUT3L", NULL, "DAC3" }, + { "VOUT3R", NULL, "DAC3" }, + + { "ADC", NULL, "AINL" }, + { "ADC", NULL, "AINR" }, +}; + +static int wm8580_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets, + ARRAY_SIZE(wm8580_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_new_widgets(codec); + return 0; +} + +/* PLL divisors */ +struct _pll_div { + u32 prescale:1; + u32 postscale:1; + u32 freqmode:2; + u32 n:4; + u32 k:24; +}; + +/* The size in bits of the pll divide */ +#define FIXED_PLL_SIZE (1 << 22) + +/* PLL rate to output rate divisions */ +static struct { + unsigned int div; + unsigned int freqmode; + unsigned int postscale; +} post_table[] = { + { 2, 0, 0 }, + { 4, 0, 1 }, + { 4, 1, 0 }, + { 8, 1, 1 }, + { 8, 2, 0 }, + { 16, 2, 1 }, + { 12, 3, 0 }, + { 24, 3, 1 } +}; + +static int pll_factors(struct _pll_div *pll_div, unsigned int target, + unsigned int source) +{ + u64 Kpart; + unsigned int K, Ndiv, Nmod; + int i; + + pr_debug("wm8580: PLL %dHz->%dHz\n", source, target); + + /* Scale the output frequency up; the PLL should run in the + * region of 90-100MHz. + */ + for (i = 0; i < ARRAY_SIZE(post_table); i++) { + if (target * post_table[i].div >= 90000000 && + target * post_table[i].div <= 100000000) { + pll_div->freqmode = post_table[i].freqmode; + pll_div->postscale = post_table[i].postscale; + target *= post_table[i].div; + break; + } + } + + if (i == ARRAY_SIZE(post_table)) { + printk(KERN_ERR "wm8580: Unable to scale output frequency " + "%u\n", target); + return -EINVAL; + } + + Ndiv = target / source; + + if (Ndiv < 5) { + source /= 2; + pll_div->prescale = 1; + Ndiv = target / source; + } else + pll_div->prescale = 0; + + if ((Ndiv < 5) || (Ndiv > 13)) { + printk(KERN_ERR + "WM8580 N=%d outside supported range\n", Ndiv); + return -EINVAL; + } + + pll_div->n = Ndiv; + Nmod = target % source; + Kpart = FIXED_PLL_SIZE * (long long)Nmod; + + do_div(Kpart, source); + + K = Kpart & 0xFFFFFFFF; + + pll_div->k = K; + + pr_debug("PLL %x.%x prescale %d freqmode %d postscale %d\n", + pll_div->n, pll_div->k, pll_div->prescale, pll_div->freqmode, + pll_div->postscale); + + return 0; +} + +static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, + int pll_id, unsigned int freq_in, unsigned int freq_out) +{ + int offset; + struct snd_soc_codec *codec = codec_dai->codec; + struct wm8580_priv *wm8580 = codec->private_data; + struct pll_state *state; + struct _pll_div pll_div; + unsigned int reg; + unsigned int pwr_mask; + int ret; + + /* GCC isn't able to work out the ifs below for initialising/using + * pll_div so suppress warnings. + */ + memset(&pll_div, 0, sizeof(pll_div)); + + switch (pll_id) { + case WM8580_PLLA: + state = &wm8580->a; + offset = 0; + pwr_mask = WM8580_PWRDN2_PLLAPD; + break; + case WM8580_PLLB: + state = &wm8580->b; + offset = 4; + pwr_mask = WM8580_PWRDN2_PLLBPD; + break; + default: + return -ENODEV; + } + + if (freq_in && freq_out) { + ret = pll_factors(&pll_div, freq_out, freq_in); + if (ret != 0) + return ret; + } + + state->in = freq_in; + state->out = freq_out; + + /* Always disable the PLL - it is not safe to leave it running + * while reprogramming it. + */ + reg = wm8580_read(codec, WM8580_PWRDN2); + wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); + + if (!freq_in || !freq_out) + return 0; + + wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); + wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); + wm8580_write(codec, WM8580_PLLA3 + offset, + (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); + + reg = wm8580_read(codec, WM8580_PLLA4 + offset); + reg &= ~0x3f; + reg |= pll_div.prescale | pll_div.postscale << 1 | + pll_div.freqmode << 4; + + wm8580_write(codec, WM8580_PLLA4 + offset, reg); + + /* All done, turn it on */ + reg = wm8580_read(codec, WM8580_PWRDN2); + wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); + + return 0; +} + +/* + * Set PCM DAI bit size and sample rate. + */ +static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai_link *dai = rtd->dai; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id); + + paifb &= ~WM8580_AIF_LENGTH_MASK; + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + paifb |= WM8580_AIF_LENGTH_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + paifb |= WM8580_AIF_LENGTH_24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + paifb |= WM8580_AIF_LENGTH_24; + break; + default: + return -EINVAL; + } + + wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb); + return 0; +} + +static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int aifa; + unsigned int aifb; + int can_invert_lrclk; + + aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); + aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); + + aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + aifa &= ~WM8580_AIF_MS; + break; + case SND_SOC_DAIFMT_CBM_CFM: + aifa |= WM8580_AIF_MS; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + can_invert_lrclk = 1; + aifb |= WM8580_AIF_FMT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + can_invert_lrclk = 1; + aifb |= WM8580_AIF_FMT_RIGHTJ; + break; + case SND_SOC_DAIFMT_LEFT_J: + can_invert_lrclk = 1; + aifb |= WM8580_AIF_FMT_LEFTJ; + break; + case SND_SOC_DAIFMT_DSP_A: + can_invert_lrclk = 0; + aifb |= WM8580_AIF_FMT_DSP; + break; + case SND_SOC_DAIFMT_DSP_B: + can_invert_lrclk = 0; + aifb |= WM8580_AIF_FMT_DSP; + aifb |= WM8580_AIF_LRP; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + + case SND_SOC_DAIFMT_IB_IF: + if (!can_invert_lrclk) + return -EINVAL; + aifb |= WM8580_AIF_BCP; + aifb |= WM8580_AIF_LRP; + break; + + case SND_SOC_DAIFMT_IB_NF: + aifb |= WM8580_AIF_BCP; + break; + + case SND_SOC_DAIFMT_NB_IF: + if (!can_invert_lrclk) + return -EINVAL; + aifb |= WM8580_AIF_LRP; + break; + + default: + return -EINVAL; + } + + wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); + wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); + + return 0; +} + +static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, + int div_id, int div) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int reg; + + switch (div_id) { + case WM8580_MCLK: + reg = wm8580_read(codec, WM8580_PLLB4); + reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; + + switch (div) { + case WM8580_CLKSRC_MCLK: + /* Input */ + break; + + case WM8580_CLKSRC_PLLA: + reg |= WM8580_PLLB4_MCLKOUTSRC_PLLA; + break; + case WM8580_CLKSRC_PLLB: + reg |= WM8580_PLLB4_MCLKOUTSRC_PLLB; + break; + + case WM8580_CLKSRC_OSC: + reg |= WM8580_PLLB4_MCLKOUTSRC_OSC; + break; + + default: + return -EINVAL; + } + wm8580_write(codec, WM8580_PLLB4, reg); + break; + + case WM8580_DAC_CLKSEL: + reg = wm8580_read(codec, WM8580_CLKSEL); + reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; + + switch (div) { + case WM8580_CLKSRC_MCLK: + break; + + case WM8580_CLKSRC_PLLA: + reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA; + break; + + case WM8580_CLKSRC_PLLB: + reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB; + break; + + default: + return -EINVAL; + } + wm8580_write(codec, WM8580_CLKSEL, reg); + break; + + case WM8580_CLKOUTSRC: + reg = wm8580_read(codec, WM8580_PLLB4); + reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; + + switch (div) { + case WM8580_CLKSRC_NONE: + break; + + case WM8580_CLKSRC_PLLA: + reg |= WM8580_PLLB4_CLKOUTSRC_PLLACLK; + break; + + case WM8580_CLKSRC_PLLB: + reg |= WM8580_PLLB4_CLKOUTSRC_PLLBCLK; + break; + + case WM8580_CLKSRC_OSC: + reg |= WM8580_PLLB4_CLKOUTSRC_OSCCLK; + break; + + default: + return -EINVAL; + } + wm8580_write(codec, WM8580_PLLB4, reg); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int reg; + + reg = wm8580_read(codec, WM8580_DAC_CONTROL5); + + if (mute) + reg |= WM8580_DAC_CONTROL5_MUTEALL; + else + reg &= ~WM8580_DAC_CONTROL5_MUTEALL; + + wm8580_write(codec, WM8580_DAC_CONTROL5, reg); + + return 0; +} + +static int wm8580_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + u16 reg; + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + case SND_SOC_BIAS_STANDBY: + break; + case SND_SOC_BIAS_OFF: + reg = wm8580_read(codec, WM8580_PWRDN1); + wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); + break; + } + codec->bias_level = level; + return 0; +} + +#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +struct snd_soc_dai wm8580_dai[] = { + { + .name = "WM8580 PAIFRX", + .id = 0, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 6, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = WM8580_FORMATS, + }, + .ops = { + .hw_params = wm8580_paif_hw_params, + }, + .dai_ops = { + .set_fmt = wm8580_set_paif_dai_fmt, + .set_clkdiv = wm8580_set_dai_clkdiv, + .set_pll = wm8580_set_dai_pll, + .digital_mute = wm8580_digital_mute, + }, + }, + { + .name = "WM8580 PAIFTX", + .id = 1, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = WM8580_FORMATS, + }, + .ops = { + .hw_params = wm8580_paif_hw_params, + }, + .dai_ops = { + .set_fmt = wm8580_set_paif_dai_fmt, + .set_clkdiv = wm8580_set_dai_clkdiv, + .set_pll = wm8580_set_dai_pll, + }, + }, +}; +EXPORT_SYMBOL_GPL(wm8580_dai); + +/* + * initialise the WM8580 driver + * register the mixer and dsp interfaces with the kernel + */ +static int wm8580_init(struct snd_soc_device *socdev) +{ + struct snd_soc_codec *codec = socdev->codec; + int ret = 0; + + codec->name = "WM8580"; + codec->owner = THIS_MODULE; + codec->read = wm8580_read_reg_cache; + codec->write = wm8580_write; + codec->set_bias_level = wm8580_set_bias_level; + codec->dai = wm8580_dai; + codec->num_dai = ARRAY_SIZE(wm8580_dai); + codec->reg_cache_size = ARRAY_SIZE(wm8580_reg); + codec->reg_cache = kmemdup(wm8580_reg, sizeof(wm8580_reg), + GFP_KERNEL); + + if (codec->reg_cache == NULL) + return -ENOMEM; + + /* Get the codec into a known state */ + wm8580_write(codec, WM8580_RESET, 0); + + /* Power up and get individual control of the DACs */ + wm8580_write(codec, WM8580_PWRDN1, wm8580_read(codec, WM8580_PWRDN1) & + ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD)); + + /* Make VMID high impedence */ + wm8580_write(codec, WM8580_ADC_CONTROL1, + wm8580_read(codec, WM8580_ADC_CONTROL1) & ~0x100); + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, + SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "wm8580: failed to create pcms\n"); + goto pcm_err; + } + + wm8580_add_controls(codec); + wm8580_add_widgets(codec); + + ret = snd_soc_register_card(socdev); + if (ret < 0) { + printk(KERN_ERR "wm8580: failed to register card\n"); + goto card_err; + } + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); + return ret; +} + +/* If the i2c layer weren't so broken, we could pass this kind of data + around */ +static struct snd_soc_device *wm8580_socdev; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + +/* + * WM8580 2 wire address is determined by GPIO5 + * state during powerup. + * low = 0x1a + * high = 0x1b + */ +static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; + +/* Magic definition of all other variables and things */ +I2C_CLIENT_INSMOD; + +static struct i2c_driver wm8580_i2c_driver; +static struct i2c_client client_template; + +static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct snd_soc_device *socdev = wm8580_socdev; + struct wm8580_setup_data *setup = socdev->codec_data; + struct snd_soc_codec *codec = socdev->codec; + struct i2c_client *i2c; + int ret; + + if (addr != setup->i2c_address) + return -ENODEV; + + client_template.adapter = adap; + client_template.addr = addr; + + i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); + if (i2c == NULL) { + kfree(codec); + return -ENOMEM; + } + i2c_set_clientdata(i2c, codec); + codec->control_data = i2c; + + ret = i2c_attach_client(i2c); + if (ret < 0) { + dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr); + goto err; + } + + ret = wm8580_init(socdev); + if (ret < 0) { + dev_err(&i2c->dev, "failed to initialise WM8580\n"); + goto err; + } + + return ret; + +err: + kfree(codec); + kfree(i2c); + return ret; +} + +static int wm8580_i2c_detach(struct i2c_client *client) +{ + struct snd_soc_codec *codec = i2c_get_clientdata(client); + i2c_detach_client(client); + kfree(codec->reg_cache); + kfree(client); + return 0; +} + +static int wm8580_i2c_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, wm8580_codec_probe); +} + +/* corgi i2c codec control layer */ +static struct i2c_driver wm8580_i2c_driver = { + .driver = { + .name = "WM8580 I2C Codec", + .owner = THIS_MODULE, + }, + .attach_adapter = wm8580_i2c_attach, + .detach_client = wm8580_i2c_detach, + .command = NULL, +}; + +static struct i2c_client client_template = { + .name = "WM8580", + .driver = &wm8580_i2c_driver, +}; +#endif + +static int wm8580_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct wm8580_setup_data *setup; + struct snd_soc_codec *codec; + struct wm8580_priv *wm8580; + int ret = 0; + + pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION); + + setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; + + wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); + if (wm8580 == NULL) { + kfree(codec); + return -ENOMEM; + } + + codec->private_data = wm8580; + socdev->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + wm8580_socdev = socdev; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (setup->i2c_address) { + normal_i2c[0] = setup->i2c_address; + codec->hw_write = (hw_write_t)i2c_master_send; + ret = i2c_add_driver(&wm8580_i2c_driver); + if (ret != 0) + printk(KERN_ERR "can't add i2c driver"); + } +#else + /* Add other interfaces here */ +#endif + return ret; +} + +/* power down chip */ +static int wm8580_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec->control_data) + wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8580_i2c_driver); +#endif + kfree(codec->private_data); + kfree(codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm8580 = { + .probe = wm8580_probe, + .remove = wm8580_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); + +MODULE_DESCRIPTION("ASoC WM8580 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h new file mode 100644 index 00000000000..589ddaba21d --- /dev/null +++ b/sound/soc/codecs/wm8580.h @@ -0,0 +1,42 @@ +/* + * wm8580.h -- audio driver for WM8580 + * + * Copyright 2008 Samsung Electronics. + * Author: Ryu Euiyoul + * ryu.real@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. + * + */ + +#ifndef _WM8580_H +#define _WM8580_H + +#define WM8580_PLLA 1 +#define WM8580_PLLB 2 + +#define WM8580_MCLK 1 +#define WM8580_DAC_CLKSEL 2 +#define WM8580_CLKOUTSRC 3 + +#define WM8580_CLKSRC_MCLK 1 +#define WM8580_CLKSRC_PLLA 2 +#define WM8580_CLKSRC_PLLB 3 +#define WM8580_CLKSRC_OSC 4 +#define WM8580_CLKSRC_NONE 5 + +struct wm8580_setup_data { + unsigned short i2c_address; +}; + +#define WM8580_DAI_PAIFRX 0 +#define WM8580_DAI_PAIFTX 1 + +extern struct snd_soc_dai wm8580_dai[]; +extern struct snd_soc_codec_device soc_codec_dev_wm8580; + +#endif + -- GitLab From 4f3ea08a129c15f64312cebfac1bfcc228f5caae Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 6 Aug 2008 15:01:01 -0500 Subject: [PATCH 0293/5416] ALSA: ASoC - fix DMA channel selection in Freescale MPC8610 sound drivers On the Freescale MPC8610, SSI1 is hard-coded to use DMA channels 0 and 1 for playback and capture, and SSI2 is hard-coded to use DMA channels 2 and 3. This patch fixes the fabric driver so that it uses the right channels. Signed-off-by: Timur Tabi Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/fsl/mpc8610_hpcd.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 4bdc9d8fc90..94f89debde1 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -68,10 +68,6 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, machine_data->dma_channel_id[1], 0); - guts_set_pmuxcr_dma(machine_data->guts, 1, 0, 0); - guts_set_pmuxcr_dma(machine_data->guts, 1, 3, 0); - guts_set_pmuxcr_dma(machine_data->guts, 0, 3, 0); - switch (machine_data->ssi_id) { case 0: clrsetbits_be32(&machine_data->guts->pmuxcr, @@ -230,6 +226,8 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, struct fsl_ssi_info ssi_info; struct fsl_dma_info dma_info; int ret = -ENODEV; + unsigned int playback_dma_channel; + unsigned int capture_dma_channel; machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); if (!machine_data) @@ -381,8 +379,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, goto error; } - /* Find the DMA channels to use. For now, we always use the first DMA - controller. */ + /* Find the DMA channels to use. Both SSIs need to use the same DMA + * controller, so let's use DMA#1. + */ for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") { iprop = of_get_property(dma_np, "cell-index", NULL); if (iprop && (*iprop == 0)) { @@ -397,14 +396,19 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, } machine_data->dma_id = *iprop; + /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA + * channels 2 and 3. This is just how the MPC8610 is wired + * internally. + */ + playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2; + capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3; + /* - * Find the DMA channels to use. For now, we always use DMA channel 0 - * for playback, and DMA channel 1 for capture. + * Find the DMA channels to use. */ while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) { iprop = of_get_property(dma_channel_np, "cell-index", NULL); - /* Is it DMA channel 0? */ - if (iprop && (*iprop == 0)) { + if (iprop && (*iprop == playback_dma_channel)) { /* dma_channel[0] and dma_irq[0] are for playback */ dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0); dma_info.dma_irq[0] = @@ -412,7 +416,7 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, machine_data->dma_channel_id[0] = *iprop; continue; } - if (iprop && (*iprop == 1)) { + if (iprop && (*iprop == capture_dma_channel)) { /* dma_channel[1] and dma_irq[1] are for capture */ dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0); dma_info.dma_irq[1] = -- GitLab From c534cc849097b84aae70c349770d982e20d0b16a Mon Sep 17 00:00:00 2001 From: roel kluin Date: Thu, 7 Aug 2008 15:56:22 -0400 Subject: [PATCH 0294/5416] ALSA: au88x0: clipping ceiling loop wrong in comment As is the clipping ceiling loop appears wrong anyways Signed-off-by: Roel Kluin Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/au88x0/au88x0_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 333c62de862..1900fa6bc51 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -427,7 +427,7 @@ static void vortex_mixer_init(vortex_t * vortex) /* Set clipping ceiling (this may be all wrong). */ /* - for (x = 0; x > 0x80; x++) { + for (x = 0; x < 0x80; x++) { hwwrite(vortex->mmio, VORTEX_MIXER_CLIP + (x << 2), 0x3ffff); } */ -- GitLab From 3caf8c080ef0bd0ccdc20bb57b150b6e40a86fd3 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Fri, 8 Aug 2008 16:39:21 +0200 Subject: [PATCH 0295/5416] ALSA: wss_lib: missing closing brace in (ifdeffed out) debug function. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/wss/wss_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 011da7a2315..6b7a0fc6f71 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -282,7 +282,7 @@ static void snd_wss_debug(struct snd_wss *chip) printk(KERN_DEBUG "CS4231 REGS: INDEX = 0x%02x " " STATUS = 0x%02x\n", - wss_inb(chip, CS4231P(REGSEL), + wss_inb(chip, CS4231P(REGSEL)), wss_inb(chip, CS4231P(STATUS))); printk(KERN_DEBUG " 0x00: left input = 0x%02x " -- GitLab From 5ef03460a6ffc1d3ee6b6f2abc6765d3e224cf89 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:06:01 +0200 Subject: [PATCH 0296/5416] ALSA: Introduce snd_BUG_ON() macro Introduced snd_BUG_ON() macro as a replacement of snd_assert() macro. snd_assert() is pretty ugly as it has the control flow in its argument. OTOH, snd_BUG_ON() behaves like a normal conditional, thus it's much easier to read the flow. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 41 +++++++++++++++++++ include/sound/core.h | 4 ++ 2 files changed, 45 insertions(+) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index e13c4e67029..df699e4323e 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -6173,6 +6173,47 @@ struct _snd_pcm_runtime { When no debug flag is set, this macro is ignored. + +
+ <function>snd_BUG_ON()</function> + + snd_BUG_ON() macro is similar with + WARN_ON() macro. For example, + + + + + + + + or it can be used as the condition, + + + + + + + + + + The macro takes an conditional expression to evaluate. + When CONFIG_SND_DEBUG, is set, the + expression is actually evaluated. If it's non-zero, it shows + the warning message such as + BUG? (xxx) + normally followed by stack trace. It returns the evaluated + value. + When no CONFIG_SND_DEBUG is set, this + macro always returns zero. + + +
+ diff --git a/include/sound/core.h b/include/sound/core.h index 1a4ff0bdcf6..938c36a0e87 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -28,6 +28,7 @@ #include /* struct rw_semaphore */ #include /* pm_message_t */ #include +#include /* number of supported soundcards */ #ifdef CONFIG_SND_DYNAMIC_MINORS @@ -405,11 +406,14 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) dump_stack(); \ } while (0) +#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond)) + #else /* !CONFIG_SND_DEBUG */ #define snd_printd(fmt, args...) /* nothing */ #define snd_assert(expr, args...) (void)(expr) #define snd_BUG() /* nothing */ +#define snd_BUG_ON(cond) ({/*(void)(cond);*/ 0;}) /* always false */ #endif /* CONFIG_SND_DEBUG */ -- GitLab From 7eaa943c8ed8e91e05d0f5d0dc7a18e3319b45cf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:09:09 +0200 Subject: [PATCH 0297/5416] ALSA: Kill snd_assert() in sound/core/* Kill snd_assert() in sound/core/*, either removed or replaced with if () with snd_BUG_ON(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 2 + sound/core/control.c | 50 +++++++----- sound/core/control_compat.c | 3 +- sound/core/device.c | 26 +++--- sound/core/hwdep.c | 16 ++-- sound/core/info.c | 23 ++++-- sound/core/info_oss.c | 6 +- sound/core/init.c | 3 +- sound/core/memalloc.c | 41 ++++------ sound/core/oss/copy.c | 30 ++++--- sound/core/oss/io.c | 24 ++++-- sound/core/oss/linear.c | 29 ++++--- sound/core/oss/mixer_oss.c | 18 ++-- sound/core/oss/mulaw.c | 27 +++--- sound/core/oss/pcm_oss.c | 52 ++++++++---- sound/core/oss/pcm_plugin.c | 38 ++++++--- sound/core/oss/rate.c | 42 ++++++---- sound/core/oss/route.c | 12 ++- sound/core/pcm.c | 34 ++++---- sound/core/pcm_compat.c | 3 +- sound/core/pcm_lib.c | 102 +++++++++++++---------- sound/core/pcm_memory.c | 14 ++-- sound/core/pcm_native.c | 127 +++++++++++++++-------------- sound/core/pcm_timer.c | 6 +- sound/core/rawmidi.c | 25 +++--- sound/core/rtctimer.c | 6 +- sound/core/seq/oss/seq_oss.c | 12 ++- sound/core/seq/oss/seq_oss_synth.c | 6 +- sound/core/seq/seq_clientmgr.c | 30 ++++--- sound/core/seq/seq_compat.c | 3 +- sound/core/seq/seq_device.c | 6 +- sound/core/seq/seq_fifo.c | 15 ++-- sound/core/seq/seq_memory.c | 12 ++- sound/core/seq/seq_midi.c | 15 ++-- sound/core/seq/seq_ports.c | 13 +-- sound/core/seq/seq_prioq.c | 4 +- sound/core/seq/seq_queue.c | 6 +- sound/core/seq/seq_timer.c | 24 ++++-- sound/core/sound.c | 12 ++- sound/core/sound_oss.c | 12 ++- sound/core/timer.c | 33 +++++--- sound/core/timer_compat.c | 9 +- 42 files changed, 583 insertions(+), 388 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 5dd8ea4a8c4..9ce74633e6f 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1015,4 +1015,6 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) (IEC958_AES1_CON_PCM_CODER<<8)|\ (IEC958_AES3_CON_FS_48000<<24)) +#define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime) + #endif /* __SOUND_PCM_H */ diff --git a/sound/core/control.c b/sound/core/control.c index 281b2e2ef0e..3c5e746d619 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -139,7 +139,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, struct snd_ctl_file *ctl; struct snd_kctl_event *ev; - snd_assert(card != NULL && id != NULL, return); + if (snd_BUG_ON(!card || !id)) + return; read_lock(&card->ctl_files_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) card->mixer_oss_change_count++; @@ -188,8 +189,8 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, struct snd_kcontrol *kctl; unsigned int idx; - snd_assert(control != NULL, return NULL); - snd_assert(control->count > 0, return NULL); + if (snd_BUG_ON(!control || !control->count)) + return NULL; kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); if (kctl == NULL) { snd_printk(KERN_ERR "Cannot allocate control instance\n"); @@ -218,8 +219,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, struct snd_kcontrol kctl; unsigned int access; - snd_assert(ncontrol != NULL, return NULL); - snd_assert(ncontrol->info != NULL, return NULL); + if (snd_BUG_ON(!ncontrol || !ncontrol->info)) + return NULL; memset(&kctl, 0, sizeof(kctl)); kctl.id.iface = ncontrol->iface; kctl.id.device = ncontrol->device; @@ -315,8 +316,8 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) if (! kcontrol) return err; - snd_assert(card != NULL, goto error); - snd_assert(kcontrol->info != NULL, goto error); + if (snd_BUG_ON(!card || !kcontrol->info)) + goto error; id = kcontrol->id; down_write(&card->controls_rwsem); if (snd_ctl_find_id(card, &id)) { @@ -367,7 +368,8 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) struct snd_ctl_elem_id id; unsigned int idx; - snd_assert(card != NULL && kcontrol != NULL, return -EINVAL); + if (snd_BUG_ON(!card || !kcontrol)) + return -EINVAL; list_del(&kcontrol->list); card->controls_count -= kcontrol->count; id = kcontrol->id; @@ -487,7 +489,8 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numi { struct snd_kcontrol *kctl; - snd_assert(card != NULL && numid != 0, return NULL); + if (snd_BUG_ON(!card || !numid)) + return NULL; list_for_each_entry(kctl, &card->controls, list) { if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) return kctl; @@ -514,7 +517,8 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, { struct snd_kcontrol *kctl; - snd_assert(card != NULL && id != NULL, return NULL); + if (snd_BUG_ON(!card || !id)) + return NULL; if (id->numid != 0) return snd_ctl_find_numid(card, id->numid); list_for_each_entry(kctl, &card->controls, list) { @@ -647,7 +651,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, #endif result = kctl->info(kctl, info); if (result >= 0) { - snd_assert(info->access == 0, ); + snd_BUG_ON(info->access); index_offset = snd_ctl_get_ioff(kctl, &info->id); vd = &kctl->vd[index_offset]; snd_ctl_build_ioff(&info->id, kctl, index_offset); @@ -1160,7 +1164,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg ctl = file->private_data; card = ctl->card; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; @@ -1222,7 +1227,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, ssize_t result = 0; ctl = file->private_data; - snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO); + if (snd_BUG_ON(!ctl || !ctl->card)) + return -ENXIO; if (!ctl->subscribed) return -EBADFD; if (count < sizeof(struct snd_ctl_event)) @@ -1328,7 +1334,8 @@ static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, { struct snd_kctl_ioctl *p; - snd_assert(fcn != NULL, return -EINVAL); + if (snd_BUG_ON(!fcn)) + return -EINVAL; down_write(&snd_ioctl_rwsem); list_for_each_entry(p, lists, list) { if (p->fioctl == fcn) { @@ -1404,9 +1411,11 @@ static int snd_ctl_dev_register(struct snd_device *device) int err, cardnum; char name[16]; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; cardnum = card->number; - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); + if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) + return -ENXIO; sprintf(name, "controlC%i", cardnum); if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, &snd_ctl_f_ops, card, name)) < 0) @@ -1423,9 +1432,11 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) struct snd_ctl_file *ctl; int err, cardnum; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; cardnum = card->number; - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); + if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) + return -ENXIO; down_read(&card->controls_rwsem); list_for_each_entry(ctl, &card->ctl_files, list) { @@ -1469,7 +1480,8 @@ int snd_ctl_create(struct snd_card *card) .dev_disconnect = snd_ctl_dev_disconnect, }; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 6101259ad86..368dc9c4aef 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -398,7 +398,8 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns int err; ctl = file->private_data; - snd_assert(ctl && ctl->card, return -ENXIO); + if (snd_BUG_ON(!ctl || !ctl->card)) + return -ENXIO; switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: diff --git a/sound/core/device.c b/sound/core/device.c index 202dac0e4d8..c58d8227254 100644 --- a/sound/core/device.c +++ b/sound/core/device.c @@ -45,9 +45,8 @@ int snd_device_new(struct snd_card *card, snd_device_type_t type, { struct snd_device *dev; - snd_assert(card != NULL, return -ENXIO); - snd_assert(device_data != NULL, return -ENXIO); - snd_assert(ops != NULL, return -ENXIO); + if (snd_BUG_ON(!card || !device_data || !ops)) + return -ENXIO; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { snd_printk(KERN_ERR "Cannot allocate device\n"); @@ -80,8 +79,8 @@ int snd_device_free(struct snd_card *card, void *device_data) { struct snd_device *dev; - snd_assert(card != NULL, return -ENXIO); - snd_assert(device_data != NULL, return -ENXIO); + if (snd_BUG_ON(!card || !device_data)) + return -ENXIO; list_for_each_entry(dev, &card->devices, list) { if (dev->device_data != device_data) continue; @@ -123,8 +122,8 @@ int snd_device_disconnect(struct snd_card *card, void *device_data) { struct snd_device *dev; - snd_assert(card != NULL, return -ENXIO); - snd_assert(device_data != NULL, return -ENXIO); + if (snd_BUG_ON(!card || !device_data)) + return -ENXIO; list_for_each_entry(dev, &card->devices, list) { if (dev->device_data != device_data) continue; @@ -159,8 +158,8 @@ int snd_device_register(struct snd_card *card, void *device_data) struct snd_device *dev; int err; - snd_assert(card != NULL, return -ENXIO); - snd_assert(device_data != NULL, return -ENXIO); + if (snd_BUG_ON(!card || !device_data)) + return -ENXIO; list_for_each_entry(dev, &card->devices, list) { if (dev->device_data != device_data) continue; @@ -188,7 +187,8 @@ int snd_device_register_all(struct snd_card *card) struct snd_device *dev; int err; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; list_for_each_entry(dev, &card->devices, list) { if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { if ((err = dev->ops->dev_register(dev)) < 0) @@ -208,7 +208,8 @@ int snd_device_disconnect_all(struct snd_card *card) struct snd_device *dev; int err = 0; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; list_for_each_entry(dev, &card->devices, list) { if (snd_device_disconnect(card, dev->device_data) < 0) err = -ENXIO; @@ -226,7 +227,8 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) int err; unsigned int range_low, range_high; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE; range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; __again: diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 6d6589f9389..195cafc5a55 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -353,9 +353,10 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, .dev_disconnect = snd_hwdep_dev_disconnect, }; - snd_assert(rhwdep != NULL, return -EINVAL); - *rhwdep = NULL; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; + if (rhwdep) + *rhwdep = NULL; hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); if (hwdep == NULL) { snd_printk(KERN_ERR "hwdep: cannot allocate\n"); @@ -374,13 +375,15 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, } init_waitqueue_head(&hwdep->open_wait); mutex_init(&hwdep->open_mutex); - *rhwdep = hwdep; + if (rhwdep) + *rhwdep = hwdep; return 0; } static int snd_hwdep_free(struct snd_hwdep *hwdep) { - snd_assert(hwdep != NULL, return -ENXIO); + if (!hwdep) + return 0; if (hwdep->private_free) hwdep->private_free(hwdep); kfree(hwdep); @@ -440,7 +443,8 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) { struct snd_hwdep *hwdep = device->device_data; - snd_assert(hwdep != NULL, return -ENXIO); + if (snd_BUG_ON(!hwdep)) + return -ENXIO; mutex_lock(®ister_mutex); if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) { mutex_unlock(®ister_mutex); diff --git a/sound/core/info.c b/sound/core/info.c index c67773ad929..527b207462b 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -217,7 +217,8 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, loff_t pos; data = file->private_data; - snd_assert(data != NULL, return -ENXIO); + if (snd_BUG_ON(!data)) + return -ENXIO; pos = *offset; if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) return -EIO; @@ -258,7 +259,8 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer loff_t pos; data = file->private_data; - snd_assert(data != NULL, return -ENXIO); + if (snd_BUG_ON(!data)) + return -ENXIO; entry = data->entry; pos = *offset; if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) @@ -614,7 +616,8 @@ int snd_info_card_create(struct snd_card *card) char str[8]; struct snd_info_entry *entry; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; sprintf(str, "card%i", card->number); if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL) @@ -636,7 +639,8 @@ int snd_info_card_register(struct snd_card *card) { struct proc_dir_entry *p; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; if (!strcmp(card->id, card->proc_root->name)) return 0; @@ -654,7 +658,8 @@ int snd_info_card_register(struct snd_card *card) */ void snd_info_card_disconnect(struct snd_card *card) { - snd_assert(card != NULL, return); + if (!card) + return; mutex_lock(&info_mutex); if (card->proc_root_link) { snd_remove_proc_entry(snd_proc_root, card->proc_root_link); @@ -671,7 +676,8 @@ void snd_info_card_disconnect(struct snd_card *card) */ int snd_info_card_free(struct snd_card *card) { - snd_assert(card != NULL, return -ENXIO); + if (!card) + return 0; snd_info_free_entry(card->proc_root); card->proc_root = NULL; return 0; @@ -849,7 +855,7 @@ static void snd_info_disconnect(struct snd_info_entry *entry) return; list_del_init(&entry->list); root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - snd_assert(root, return); + snd_BUG_ON(!root); snd_remove_proc_entry(root, entry->p); entry->p = NULL; } @@ -947,7 +953,8 @@ int snd_info_register(struct snd_info_entry * entry) { struct proc_dir_entry *root, *p = NULL; - snd_assert(entry != NULL, return -ENXIO); + if (snd_BUG_ON(!entry)) + return -ENXIO; root = entry->parent == NULL ? snd_proc_root : entry->parent->p; mutex_lock(&info_mutex); p = snd_create_proc_entry(entry->name, entry->mode, root); diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index e35789a9275..e4af138d651 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -43,8 +43,10 @@ int snd_oss_info_register(int dev, int num, char *string) { char *x; - snd_assert(dev >= 0 && dev < SNDRV_OSS_INFO_DEV_COUNT, return -ENXIO); - snd_assert(num >= 0 && num < SNDRV_CARDS, return -ENXIO); + if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT)) + return -ENXIO; + if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS)) + return -ENXIO; mutex_lock(&strings); if (string == NULL) { if ((x = snd_sndstat_strings[num][dev]) != NULL) { diff --git a/sound/core/init.c b/sound/core/init.c index df46bbc25dc..8af467df924 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -545,7 +545,8 @@ int snd_card_register(struct snd_card *card) { int err; - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; #ifndef CONFIG_SYSFS_DEPRECATED if (!card->card_dev) { card->card_dev = device_create_drvdata(sound_class, card->dev, diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index f5d6d8d1297..4a649976cc8 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -67,18 +67,6 @@ struct snd_mem_list { /* id for pre-allocated buffers */ #define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1 -#ifdef CONFIG_SND_DEBUG -#define __ASTRING__(x) #x -#define snd_assert(expr, args...) do {\ - if (!(expr)) {\ - printk(KERN_ERR "snd-malloc: BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\ - args;\ - }\ -} while (0) -#else -#define snd_assert(expr, args...) /**/ -#endif - /* * * Generic memory allocators @@ -111,8 +99,10 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags) int pg; void *res; - snd_assert(size > 0, return NULL); - snd_assert(gfp_flags != 0, return NULL); + if (WARN_ON(!size)) + return NULL; + if (WARN_ON(!gfp_flags)) + return NULL; gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ pg = get_order(size); if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) @@ -152,8 +142,8 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d void *res; gfp_t gfp_flags; - snd_assert(size > 0, return NULL); - snd_assert(dma != NULL, return NULL); + if (WARN_ON(!dma)) + return NULL; pg = get_order(size); gfp_flags = GFP_KERNEL | __GFP_COMP /* compound page lets parts be mapped */ @@ -189,8 +179,8 @@ static void *snd_malloc_sbus_pages(struct device *dev, size_t size, int pg; void *res; - snd_assert(size > 0, return NULL); - snd_assert(dma_addr != NULL, return NULL); + if (WARN_ON(!dma_addr)) + return NULL; pg = get_order(size); res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr); if (res != NULL) @@ -236,8 +226,10 @@ static void snd_free_sbus_pages(struct device *dev, size_t size, int snd_dma_alloc_pages(int type, struct device *device, size_t size, struct snd_dma_buffer *dmab) { - snd_assert(size > 0, return -ENXIO); - snd_assert(dmab != NULL, return -ENXIO); + if (WARN_ON(!size)) + return -ENXIO; + if (WARN_ON(!dmab)) + return -ENXIO; dmab->dev.type = type; dmab->dev.dev = device; @@ -292,9 +284,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, { int err; - snd_assert(size > 0, return -ENXIO); - snd_assert(dmab != NULL, return -ENXIO); - while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { if (err != -ENOMEM) return err; @@ -353,7 +342,8 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) { struct snd_mem_list *mem; - snd_assert(dmab, return 0); + if (WARN_ON(!dmab)) + return 0; mutex_lock(&list_mutex); list_for_each_entry(mem, &mem_list_head, list) { @@ -387,7 +377,8 @@ int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id) { struct snd_mem_list *mem; - snd_assert(dmab, return -EINVAL); + if (WARN_ON(!dmab)) + return -EINVAL; mem = kmalloc(sizeof(*mem), GFP_KERNEL); if (! mem) return -ENOMEM; diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c index 9ded30d0e97..05b58d4fc2b 100644 --- a/sound/core/oss/copy.c +++ b/sound/core/oss/copy.c @@ -32,17 +32,18 @@ static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin, unsigned int channel; unsigned int nchannels; - snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) + return -ENXIO; if (frames == 0) return 0; nchannels = plugin->src_format.channels; for (channel = 0; channel < nchannels; channel++) { - snd_assert(src_channels->area.first % 8 == 0 && - src_channels->area.step % 8 == 0, - return -ENXIO); - snd_assert(dst_channels->area.first % 8 == 0 && - dst_channels->area.step % 8 == 0, - return -ENXIO); + if (snd_BUG_ON(src_channels->area.first % 8 || + src_channels->area.step % 8)) + return -ENXIO; + if (snd_BUG_ON(dst_channels->area.first % 8 || + dst_channels->area.step % 8)) + return -ENXIO; if (!src_channels->enabled) { if (dst_channels->wanted) snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format); @@ -66,15 +67,20 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, struct snd_pcm_plugin *plugin; int width; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(src_format->format == dst_format->format, return -ENXIO); - snd_assert(src_format->rate == dst_format->rate, return -ENXIO); - snd_assert(src_format->channels == dst_format->channels, return -ENXIO); + if (snd_BUG_ON(src_format->format != dst_format->format)) + return -ENXIO; + if (snd_BUG_ON(src_format->rate != dst_format->rate)) + return -ENXIO; + if (snd_BUG_ON(src_format->channels != dst_format->channels)) + return -ENXIO; width = snd_pcm_format_physical_width(src_format->format); - snd_assert(width > 0, return -ENXIO); + if (snd_BUG_ON(width <= 0)) + return -ENXIO; err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format, 0, &plugin); diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c index f874f6ca365..6faa1d71920 100644 --- a/sound/core/oss/io.c +++ b/sound/core/oss/io.c @@ -39,14 +39,17 @@ static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin, struct snd_pcm_plugin_channel *dst_channels, snd_pcm_uframes_t frames) { - snd_assert(plugin != NULL, return -ENXIO); - snd_assert(src_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin)) + return -ENXIO; + if (snd_BUG_ON(!src_channels)) + return -ENXIO; if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { return pcm_write(plugin->plug, src_channels->area.addr, frames); } else { int channel, channels = plugin->dst_format.channels; void **bufs = (void**)plugin->extra_data; - snd_assert(bufs != NULL, return -ENXIO); + if (snd_BUG_ON(!bufs)) + return -ENXIO; for (channel = 0; channel < channels; channel++) { if (src_channels[channel].enabled) bufs[channel] = src_channels[channel].area.addr; @@ -62,14 +65,17 @@ static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin, struct snd_pcm_plugin_channel *dst_channels, snd_pcm_uframes_t frames) { - snd_assert(plugin != NULL, return -ENXIO); - snd_assert(dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin)) + return -ENXIO; + if (snd_BUG_ON(!dst_channels)) + return -ENXIO; if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { return pcm_read(plugin->plug, dst_channels->area.addr, frames); } else { int channel, channels = plugin->dst_format.channels; void **bufs = (void**)plugin->extra_data; - snd_assert(bufs != NULL, return -ENXIO); + if (snd_BUG_ON(!bufs)) + return -ENXIO; for (channel = 0; channel < channels; channel++) { if (dst_channels[channel].enabled) bufs[channel] = dst_channels[channel].area.addr; @@ -107,9 +113,11 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug, struct snd_pcm_plugin_format format; struct snd_pcm_plugin *plugin; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(plug != NULL && params != NULL, return -ENXIO); + if (snd_BUG_ON(!plug || !params)) + return -ENXIO; format.format = params_format(params); format.rate = params_rate(params); format.channels = params_channels(params); diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index da3dbd41669..4c1d1682719 100644 --- a/sound/core/oss/linear.c +++ b/sound/core/oss/linear.c @@ -92,7 +92,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, { struct linear_priv *data; - snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) + return -ENXIO; data = (struct linear_priv *)plugin->extra_data; if (frames == 0) return 0; @@ -100,12 +101,12 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, { unsigned int channel; for (channel = 0; channel < plugin->src_format.channels; channel++) { - snd_assert(src_channels[channel].area.first % 8 == 0 && - src_channels[channel].area.step % 8 == 0, - return -ENXIO); - snd_assert(dst_channels[channel].area.first % 8 == 0 && - dst_channels[channel].area.step % 8 == 0, - return -ENXIO); + if (snd_BUG_ON(src_channels[channel].area.first % 8 || + src_channels[channel].area.step % 8)) + return -ENXIO; + if (snd_BUG_ON(dst_channels[channel].area.first % 8 || + dst_channels[channel].area.step % 8)) + return -ENXIO; } } #endif @@ -154,13 +155,17 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, struct linear_priv *data; struct snd_pcm_plugin *plugin; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(src_format->rate == dst_format->rate, return -ENXIO); - snd_assert(src_format->channels == dst_format->channels, return -ENXIO); - snd_assert(snd_pcm_format_linear(src_format->format) && - snd_pcm_format_linear(dst_format->format), return -ENXIO); + if (snd_BUG_ON(src_format->rate != dst_format->rate)) + return -ENXIO; + if (snd_BUG_ON(src_format->channels != dst_format->channels)) + return -ENXIO; + if (snd_BUG_ON(!snd_pcm_format_linear(src_format->format) || + !snd_pcm_format_linear(dst_format->format))) + return -ENXIO; err = snd_pcm_plugin_build(plug, "linear format conversion", src_format, dst_format, diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 581aa2c60e6..4690b8b5681 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -257,8 +257,10 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) result = pslot->get_volume(fmixer, pslot, &left, &right); if (!pslot->stereo) right = left; - snd_assert(left >= 0 && left <= 100, return -EIO); - snd_assert(right >= 0 && right <= 100, return -EIO); + if (snd_BUG_ON(left < 0 || left > 100)) + return -EIO; + if (snd_BUG_ON(right < 0 || right > 100)) + return -EIO; if (result >= 0) { pslot->volume[0] = left; pslot->volume[1] = right; @@ -298,7 +300,8 @@ static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int int __user *p = argp; int tmp; - snd_assert(fmixer != NULL, return -ENXIO); + if (snd_BUG_ON(!fmixer)) + return -ENXIO; if (((cmd >> 8) & 0xff) == 'M') { switch (cmd) { case SOUND_MIXER_INFO: @@ -368,7 +371,8 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l { struct snd_mixer_oss_file fmixer; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; if (card->mixer_oss == NULL) return -ENXIO; memset(&fmixer, 0, sizeof(fmixer)); @@ -1284,9 +1288,11 @@ static int snd_mixer_oss_free1(void *private) struct snd_card *card; int idx; - snd_assert(mixer != NULL, return -ENXIO); + if (!mixer) + return 0; card = mixer->card; - snd_assert(mixer == card->mixer_oss, return -ENXIO); + if (snd_BUG_ON(mixer != card->mixer_oss)) + return -ENXIO; card->mixer_oss = NULL; for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) { struct snd_mixer_oss_slot *chn = &mixer->slots[idx]; diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index 77f96194a0e..f7649d4d950 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c @@ -252,19 +252,20 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin, { struct mulaw_priv *data; - snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) + return -ENXIO; if (frames == 0) return 0; #ifdef CONFIG_SND_DEBUG { unsigned int channel; for (channel = 0; channel < plugin->src_format.channels; channel++) { - snd_assert(src_channels[channel].area.first % 8 == 0 && - src_channels[channel].area.step % 8 == 0, - return -ENXIO); - snd_assert(dst_channels[channel].area.first % 8 == 0 && - dst_channels[channel].area.step % 8 == 0, - return -ENXIO); + if (snd_BUG_ON(src_channels[channel].area.first % 8 || + src_channels[channel].area.step % 8)) + return -ENXIO; + if (snd_BUG_ON(dst_channels[channel].area.first % 8 || + dst_channels[channel].area.step % 8)) + return -ENXIO; } } #endif @@ -305,11 +306,14 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, struct snd_pcm_plugin_format *format; mulaw_f func; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(src_format->rate == dst_format->rate, return -ENXIO); - snd_assert(src_format->channels == dst_format->channels, return -ENXIO); + if (snd_BUG_ON(src_format->rate != dst_format->rate)) + return -ENXIO; + if (snd_BUG_ON(src_format->channels != dst_format->channels)) + return -ENXIO; if (dst_format->format == SNDRV_PCM_FORMAT_MU_LAW) { format = src_format; @@ -323,7 +327,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, snd_BUG(); return -EINVAL; } - snd_assert(snd_pcm_format_linear(format->format) != 0, return -ENXIO); + if (snd_BUG_ON(!snd_pcm_format_linear(format->format))) + return -ENXIO; err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion", src_format, dst_format, diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4c601b192dd..1af62b8b86c 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -452,7 +452,8 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, } else { *params = *save; max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); - snd_assert(max >= 0, return -EINVAL); + if (max < 0) + return max; last = 1; } _end: @@ -461,7 +462,7 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, v = snd_pcm_hw_param_last(pcm, params, var, dir); else v = snd_pcm_hw_param_first(pcm, params, var, dir); - snd_assert(v >= 0, return -EINVAL); + snd_BUG_ON(v < 0); return v; } @@ -778,7 +779,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, while (oss_period_size * oss_periods > oss_buffer_size) oss_period_size /= 2; - snd_assert(oss_period_size >= 16, return -EINVAL); + if (oss_period_size < 16) + return -EINVAL; runtime->oss.period_bytes = oss_period_size; runtime->oss.period_frames = 1; runtime->oss.periods = oss_periods; @@ -895,7 +897,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } } err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0); - snd_assert(err >= 0, goto failure); + if (err < 0) + goto failure; if (direct) { memcpy(params, sparams, sizeof(*params)); @@ -958,11 +961,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size); err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL); - snd_assert(err >= 0, goto failure); + if (err < 0) + goto failure; err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS, runtime->oss.periods, NULL); - snd_assert(err >= 0, goto failure); + if (err < 0) + goto failure; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); @@ -1006,7 +1011,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) runtime->oss.periods = params_periods(sparams); oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); - snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure); + if (oss_period_size < 0) { + err = -EINVAL; + goto failure; + } #ifdef CONFIG_SND_PCM_OSS_PLUGINS if (runtime->oss.plugin_first) { err = snd_pcm_plug_alloc(substream, oss_period_size); @@ -1017,7 +1025,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) oss_period_size *= oss_frame_size; oss_buffer_size = oss_period_size * runtime->oss.periods; - snd_assert(oss_buffer_size >= 0, err = -EINVAL; goto failure); + if (oss_buffer_size < 0) { + err = -EINVAL; + goto failure; + } runtime->oss.period_bytes = oss_period_size; runtime->oss.buffer_bytes = oss_buffer_size; @@ -1069,7 +1080,8 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil return err; } } - snd_assert(asubstream != NULL, return -EIO); + if (!asubstream) + return -EIO; if (r_substream) *r_substream = asubstream; return 0; @@ -1764,7 +1776,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) err = snd_pcm_hw_refine(substream, params); format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); kfree(params); - snd_assert(err >= 0, return err); + if (err < 0) + return err; for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(&format_mask, fmt)) { int f = snd_pcm_oss_format_to(fmt); @@ -2250,7 +2263,8 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) { int cidx; - snd_assert(pcm_oss_file != NULL, return -ENXIO); + if (!pcm_oss_file) + return 0; for (cidx = 0; cidx < 2; ++cidx) { struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; if (substream) @@ -2271,8 +2285,8 @@ static int snd_pcm_oss_open_file(struct file *file, struct snd_pcm_substream *substream; unsigned int f_mode = file->f_mode; - snd_assert(rpcm_oss_file != NULL, return -EINVAL); - *rpcm_oss_file = NULL; + if (rpcm_oss_file) + *rpcm_oss_file = NULL; pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); if (pcm_oss_file == NULL) @@ -2312,7 +2326,8 @@ static int snd_pcm_oss_open_file(struct file *file, } file->private_data = pcm_oss_file; - *rpcm_oss_file = pcm_oss_file; + if (rpcm_oss_file) + *rpcm_oss_file = pcm_oss_file; return 0; } @@ -2321,7 +2336,8 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size) { unsigned int idx; - snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); + if (snd_BUG_ON(!task || !name || size < 2)) + return -EINVAL; for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) name[idx] = task->comm[idx]; name[idx] = '\0'; @@ -2415,7 +2431,8 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - snd_assert(substream != NULL, return -ENXIO); + if (snd_BUG_ON(!substream)) + return -ENXIO; pcm = substream->pcm; if (!pcm->card->shutdown) snd_pcm_oss_sync(pcm_oss_file); @@ -2448,7 +2465,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (substream != NULL) break; } - snd_assert(substream != NULL, return -ENXIO); + if (snd_BUG_ON(idx >= 2)) + return -ENXIO; return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); } #endif diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index bec94138205..6751daa3bb5 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -62,7 +62,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; size = frames * format->channels * width; - snd_assert((size % 8) == 0, return -ENXIO); + if (snd_BUG_ON(size % 8)) + return -ENXIO; size /= 8; if (plugin->buf_frames < frames) { vfree(plugin->buf); @@ -84,7 +85,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t c->area.step = format->channels * width; } } else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { - snd_assert((size % format->channels) == 0,); + if (snd_BUG_ON(size % format->channels)) + return -EINVAL; size /= format->channels; for (channel = 0; channel < format->channels; channel++, c++) { c->frames = frames; @@ -102,13 +104,15 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) { int err; - snd_assert(snd_pcm_plug_first(plug) != NULL, return -ENXIO); + if (snd_BUG_ON(!snd_pcm_plug_first(plug))) + return -ENXIO; if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) { struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug); while (plugin->next) { if (plugin->dst_frames) frames = plugin->dst_frames(plugin, frames); - snd_assert(frames > 0, return -ENXIO); + if (snd_BUG_ON(frames <= 0)) + return -ENXIO; plugin = plugin->next; err = snd_pcm_plugin_alloc(plugin, frames); if (err < 0) @@ -119,7 +123,8 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) while (plugin->prev) { if (plugin->src_frames) frames = plugin->src_frames(plugin, frames); - snd_assert(frames > 0, return -ENXIO); + if (snd_BUG_ON(frames <= 0)) + return -ENXIO; plugin = plugin->prev; err = snd_pcm_plugin_alloc(plugin, frames); if (err < 0) @@ -148,8 +153,10 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug, struct snd_pcm_plugin *plugin; unsigned int channels; - snd_assert(plug != NULL, return -ENXIO); - snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO); + if (snd_BUG_ON(!plug)) + return -ENXIO; + if (snd_BUG_ON(!src_format || !dst_format)) + return -ENXIO; plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL); if (plugin == NULL) return -ENOMEM; @@ -159,10 +166,10 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug, plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; plugin->src_format = *src_format; plugin->src_width = snd_pcm_format_physical_width(src_format->format); - snd_assert(plugin->src_width > 0, ); + snd_BUG_ON(plugin->src_width <= 0); plugin->dst_format = *dst_format; plugin->dst_width = snd_pcm_format_physical_width(dst_format->format); - snd_assert(plugin->dst_width > 0, ); + snd_BUG_ON(plugin->dst_width <= 0); if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) channels = src_format->channels; else @@ -194,7 +201,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; int stream = snd_pcm_plug_stream(plug); - snd_assert(plug != NULL, return -ENXIO); + if (snd_BUG_ON(!plug)) + return -ENXIO; if (drv_frames == 0) return 0; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -224,7 +232,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc snd_pcm_sframes_t frames; int stream = snd_pcm_plug_stream(plug); - snd_assert(plug != NULL, return -ENXIO); + if (snd_BUG_ON(!plug)) + return -ENXIO; if (clt_frames == 0) return 0; frames = clt_frames; @@ -540,7 +549,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu int width, nchannels, channel; int stream = snd_pcm_plug_stream(plug); - snd_assert(buf != NULL, return -ENXIO); + if (snd_BUG_ON(!buf)) + return -ENXIO; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { plugin = snd_pcm_plug_first(plug); format = &plugin->src_format; @@ -553,7 +563,9 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; nchannels = format->channels; - snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO); + if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && + format->channels > 1)) + return -ENXIO; for (channel = 0; channel < nchannels; channel++, v++) { v->frames = count; v->enabled = 1; diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 14dfb3175d8..a466443c4a2 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -185,7 +185,8 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_ struct rate_priv *data; snd_pcm_sframes_t res; - snd_assert(plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin)) + return -ENXIO; if (frames == 0) return 0; data = (struct rate_priv *)plugin->extra_data; @@ -217,7 +218,8 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_ struct rate_priv *data; snd_pcm_sframes_t res; - snd_assert(plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin)) + return -ENXIO; if (frames == 0) return 0; data = (struct rate_priv *)plugin->extra_data; @@ -252,19 +254,20 @@ static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames; struct rate_priv *data; - snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) + return -ENXIO; if (frames == 0) return 0; #ifdef CONFIG_SND_DEBUG { unsigned int channel; for (channel = 0; channel < plugin->src_format.channels; channel++) { - snd_assert(src_channels[channel].area.first % 8 == 0 && - src_channels[channel].area.step % 8 == 0, - return -ENXIO); - snd_assert(dst_channels[channel].area.first % 8 == 0 && - dst_channels[channel].area.step % 8 == 0, - return -ENXIO); + if (snd_BUG_ON(src_channels[channel].area.first % 8 || + src_channels[channel].area.step % 8)) + return -ENXIO; + if (snd_BUG_ON(dst_channels[channel].area.first % 8 || + dst_channels[channel].area.step % 8)) + return -ENXIO; } } #endif @@ -281,7 +284,8 @@ static int rate_action(struct snd_pcm_plugin *plugin, enum snd_pcm_plugin_action action, unsigned long udata) { - snd_assert(plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin)) + return -ENXIO; switch (action) { case INIT: case PREPARE: @@ -302,14 +306,20 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug, struct rate_priv *data; struct snd_pcm_plugin *plugin; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(src_format->channels == dst_format->channels, return -ENXIO); - snd_assert(src_format->channels > 0, return -ENXIO); - snd_assert(src_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO); - snd_assert(dst_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO); - snd_assert(src_format->rate != dst_format->rate, return -ENXIO); + if (snd_BUG_ON(src_format->channels != dst_format->channels)) + return -ENXIO; + if (snd_BUG_ON(src_format->channels <= 0)) + return -ENXIO; + if (snd_BUG_ON(src_format->format != SNDRV_PCM_FORMAT_S16)) + return -ENXIO; + if (snd_BUG_ON(dst_format->format != SNDRV_PCM_FORMAT_S16)) + return -ENXIO; + if (snd_BUG_ON(src_format->rate == dst_format->rate)) + return -ENXIO; err = snd_pcm_plugin_build(plug, "rate conversion", src_format, dst_format, diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index da7ab7a3e82..0dcc2870d53 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c @@ -54,7 +54,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, struct snd_pcm_plugin_channel *dvp; int format; - snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO); + if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) + return -ENXIO; if (frames == 0) return 0; @@ -90,10 +91,13 @@ int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, struct snd_pcm_plugin *plugin; int err; - snd_assert(r_plugin != NULL, return -ENXIO); + if (snd_BUG_ON(!r_plugin)) + return -ENXIO; *r_plugin = NULL; - snd_assert(src_format->rate == dst_format->rate, return -ENXIO); - snd_assert(src_format->format == dst_format->format, return -ENXIO); + if (snd_BUG_ON(src_format->rate != dst_format->rate)) + return -ENXIO; + if (snd_BUG_ON(src_format->format != dst_format->format)) + return -ENXIO; err = snd_pcm_plugin_build(plug, "route conversion", src_format, dst_format, 0, &plugin); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 517388b2eba..192a433a240 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -256,7 +256,6 @@ static char *snd_pcm_tstamp_mode_names[] = { static const char *snd_pcm_stream_name(int stream) { - snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL); return snd_pcm_stream_names[stream]; } @@ -272,7 +271,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) static const char *snd_pcm_tstamp_mode_name(int mode) { - snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL); return snd_pcm_tstamp_mode_names[mode]; } @@ -706,9 +704,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, .dev_disconnect = snd_pcm_dev_disconnect, }; - snd_assert(rpcm != NULL, return -EINVAL); - *rpcm = NULL; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; + if (rpcm) + *rpcm = NULL; pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) { snd_printk(KERN_ERR "Cannot allocate PCM\n"); @@ -732,7 +731,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, snd_pcm_free(pcm); return err; } - *rpcm = pcm; + if (rpcm) + *rpcm = pcm; return 0; } @@ -766,7 +766,8 @@ static int snd_pcm_free(struct snd_pcm *pcm) { struct snd_pcm_notify *notify; - snd_assert(pcm != NULL, return -ENXIO); + if (!pcm) + return 0; list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_unregister(pcm); } @@ -797,9 +798,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, int prefer_subdevice = -1; size_t size; - snd_assert(rsubstream != NULL, return -EINVAL); + if (snd_BUG_ON(!pcm || !rsubstream)) + return -ENXIO; *rsubstream = NULL; - snd_assert(pcm != NULL, return -ENXIO); pstr = &pcm->streams[stream]; if (pstr->substream == NULL || pstr->substream_count == 0) return -ENODEV; @@ -907,8 +908,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; + if (PCM_RUNTIME_CHECK(substream)) + return; runtime = substream->runtime; - snd_assert(runtime != NULL, return); if (runtime->private_free != NULL) runtime->private_free(runtime); snd_free_pages((void*)runtime->status, @@ -953,7 +955,8 @@ static int snd_pcm_dev_register(struct snd_device *device) struct snd_pcm *pcm = device->device_data; struct device *dev; - snd_assert(pcm != NULL && device != NULL, return -ENXIO); + if (snd_BUG_ON(!pcm || !device)) + return -ENXIO; mutex_lock(®ister_mutex); err = snd_pcm_add(pcm); if (err) { @@ -1043,10 +1046,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) { struct snd_pcm *pcm; - snd_assert(notify != NULL && - notify->n_register != NULL && - notify->n_unregister != NULL && - notify->n_disconnect, return -EINVAL); + if (snd_BUG_ON(!notify || + !notify->n_register || + !notify->n_unregister || + !notify->n_disconnect)) + return -EINVAL; mutex_lock(®ister_mutex); if (nfree) { list_del(¬ify->list); diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 49aa693fba8..36d7a599823 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -397,7 +397,8 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, snd_pcm_uframes_t boundary; int err; - snd_assert(runtime, return -EINVAL); + if (snd_BUG_ON(!runtime)) + return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 1533f0379e9..6ea5cfb8399 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -85,7 +85,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } frames = runtime->buffer_size - runtime->silence_filled; } - snd_assert(frames <= runtime->buffer_size, return); + if (snd_BUG_ON(frames > runtime->buffer_size)) + return; if (frames == 0) return; ofs = runtime->silence_start % runtime->buffer_size; @@ -96,7 +97,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram if (substream->ops->silence) { int err; err = substream->ops->silence(substream, -1, ofs, transfer); - snd_assert(err >= 0, ); + snd_BUG_ON(err < 0); } else { char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); @@ -108,7 +109,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram for (c = 0; c < channels; ++c) { int err; err = substream->ops->silence(substream, c, ofs, transfer); - snd_assert(err >= 0, ); + snd_BUG_ON(err < 0); } } else { size_t dma_csize = runtime->dma_bytes / channels; @@ -354,7 +355,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, { u_int64_t n = (u_int64_t) a * b; if (c == 0) { - snd_assert(n > 0, ); + snd_BUG_ON(!n); *r = 0; return UINT_MAX; } @@ -380,7 +381,8 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) { int changed = 0; - snd_assert(!snd_interval_empty(i), return -EINVAL); + if (snd_BUG_ON(snd_interval_empty(i))) + return -EINVAL; if (i->min < v->min) { i->min = v->min; i->openmin = v->openmin; @@ -423,7 +425,8 @@ EXPORT_SYMBOL(snd_interval_refine); static int snd_interval_refine_first(struct snd_interval *i) { - snd_assert(!snd_interval_empty(i), return -EINVAL); + if (snd_BUG_ON(snd_interval_empty(i))) + return -EINVAL; if (snd_interval_single(i)) return 0; i->max = i->min; @@ -435,7 +438,8 @@ static int snd_interval_refine_first(struct snd_interval *i) static int snd_interval_refine_last(struct snd_interval *i) { - snd_assert(!snd_interval_empty(i), return -EINVAL); + if (snd_BUG_ON(snd_interval_empty(i))) + return -EINVAL; if (snd_interval_single(i)) return 0; i->min = i->max; @@ -889,7 +893,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, c->private = private; k = 0; while (1) { - snd_assert(k < ARRAY_SIZE(c->deps), return -EINVAL); + if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) + return -EINVAL; c->deps[k++] = dep; if (dep < 0) break; @@ -1285,7 +1290,8 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - snd_assert(err >= 0, return err); + if (snd_BUG_ON(err < 0)) + return err; } return snd_pcm_hw_param_value(params, var, dir); } @@ -1330,7 +1336,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); - snd_assert(err >= 0, return err); + if (snd_BUG_ON(err < 0)) + return err; } return snd_pcm_hw_param_value(params, var, dir); } @@ -1368,7 +1375,8 @@ int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, err = snd_pcm_hw_param_first(pcm, params, *v, NULL); else err = snd_pcm_hw_param_last(pcm, params, *v, NULL); - snd_assert(err >= 0, return err); + if (snd_BUG_ON(err < 0)) + return err; } return 0; } @@ -1466,9 +1474,9 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime; unsigned long flags; - snd_assert(substream != NULL, return); + if (PCM_RUNTIME_CHECK(substream)) + return; runtime = substream->runtime; - snd_assert(runtime != NULL, return); if (runtime->transfer_ack_begin) runtime->transfer_ack_begin(substream); @@ -1567,7 +1575,6 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, return err; } else { char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - snd_assert(runtime->dma_area, return -EFAULT); if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) return -EFAULT; } @@ -1629,7 +1636,10 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; if (frames > cont) frames = cont; - snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL); + if (snd_BUG_ON(!frames)) { + snd_pcm_stream_unlock_irq(substream); + return -EINVAL; + } appl_ptr = runtime->control->appl_ptr; appl_ofs = appl_ptr % runtime->buffer_size; snd_pcm_stream_unlock_irq(substream); @@ -1669,18 +1679,30 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; } -snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) +/* sanity-check for read/write methods */ +static int pcm_sanity_check(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - int nonblock; - - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); - snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); + if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) + return -EINVAL; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; + return 0; +} + +snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) +{ + struct snd_pcm_runtime *runtime; + int nonblock; + int err; + err = pcm_sanity_check(substream); + if (err < 0) + return err; + runtime = substream->runtime; nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && @@ -1703,7 +1725,8 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, int channels = runtime->channels; int c; if (substream->ops->copy) { - snd_assert(substream->ops->silence != NULL, return -EINVAL); + if (snd_BUG_ON(!substream->ops->silence)) + return -EINVAL; for (c = 0; c < channels; ++c, ++bufs) { if (*bufs == NULL) { if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) @@ -1717,7 +1740,6 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, } else { /* default transfer behaviour */ size_t dma_csize = runtime->dma_bytes / channels; - snd_assert(runtime->dma_area, return -EFAULT); for (c = 0; c < channels; ++c, ++bufs) { char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); if (*bufs == NULL) { @@ -1738,14 +1760,12 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime; int nonblock; + int err; - snd_assert(substream != NULL, return -ENXIO); + err = pcm_sanity_check(substream); + if (err < 0) + return err; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); - snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) @@ -1769,7 +1789,6 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, return err; } else { char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - snd_assert(runtime->dma_area, return -EFAULT); if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) return -EFAULT; } @@ -1841,7 +1860,10 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; if (frames > cont) frames = cont; - snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL); + if (snd_BUG_ON(!frames)) { + snd_pcm_stream_unlock_irq(substream); + return -EINVAL; + } appl_ptr = runtime->control->appl_ptr; appl_ofs = appl_ptr % runtime->buffer_size; snd_pcm_stream_unlock_irq(substream); @@ -1879,14 +1901,12 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u { struct snd_pcm_runtime *runtime; int nonblock; + int err; - snd_assert(substream != NULL, return -ENXIO); + err = pcm_sanity_check(substream); + if (err < 0) + return err; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); - snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - nonblock = !!(substream->f_flags & O_NONBLOCK); if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) return -EINVAL; @@ -1916,7 +1936,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, } } else { snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; - snd_assert(runtime->dma_area, return -EFAULT); for (c = 0; c < channels; ++c, ++bufs) { char *hwbuf; char __user *buf; @@ -1938,11 +1957,12 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime; int nonblock; + int err; - snd_assert(substream != NULL, return -ENXIO); + err = pcm_sanity_check(substream); + if (err < 0) + return err; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); - snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index ff07b4a9992..859b1185e69 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -50,8 +50,6 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz struct snd_dma_buffer *dmab = &substream->dma_buffer; int err; - snd_assert(size > 0, return -EINVAL); - /* already reserved? */ if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) { if (dmab->bytes >= size) @@ -342,10 +340,12 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) struct snd_pcm_runtime *runtime; struct snd_dma_buffer *dmab = NULL; - snd_assert(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL); - snd_assert(substream != NULL, return -EINVAL); + if (PCM_RUNTIME_CHECK(substream)) + return -EINVAL; + if (snd_BUG_ON(substream->dma_buffer.dev.type == + SNDRV_DMA_TYPE_UNKNOWN)) + return -EINVAL; runtime = substream->runtime; - snd_assert(runtime != NULL, return -EINVAL); if (runtime->dma_buffer_p) { /* perphaps, we might free the large DMA memory region @@ -391,9 +391,9 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - snd_assert(substream != NULL, return -EINVAL); + if (PCM_RUNTIME_CHECK(substream)) + return -EINVAL; runtime = substream->runtime; - snd_assert(runtime != NULL, return -EINVAL); if (runtime->dma_area == NULL) return 0; if (runtime->dma_buffer_p != &substream->dma_buffer) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c487025d345..df2299a8cef 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -95,7 +95,6 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) struct snd_pcm *pcm = substream->pcm; struct snd_pcm_str *pstr = substream->pstr; - snd_assert(substream != NULL, return -ENXIO); memset(info, 0, sizeof(*info)); info->card = pcm->card->number; info->device = pcm->device; @@ -370,9 +369,9 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, unsigned int bits; snd_pcm_uframes_t frames; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_OPEN: @@ -490,9 +489,9 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime; int result = 0; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_SETUP: @@ -518,9 +517,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - snd_assert(runtime != NULL, return -ENXIO); snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_pcm_stream_unlock_irq(substream); @@ -622,11 +621,8 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream, struct snd_pcm_status __user * _status) { struct snd_pcm_status status; - struct snd_pcm_runtime *runtime; int res; - snd_assert(substream != NULL, return -ENXIO); - runtime = substream->runtime; memset(&status, 0, sizeof(status)); res = snd_pcm_status(substream, &status); if (res < 0) @@ -642,7 +638,6 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime; unsigned int channel; - snd_assert(substream != NULL, return -ENXIO); channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); @@ -1250,7 +1245,6 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state) int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL); if (err < 0) return err; - // snd_assert(runtime->status->hw_ptr < runtime->buffer_size, ); runtime->hw_ptr_base = 0; runtime->hw_ptr_interrupt = runtime->status->hw_ptr - runtime->status->hw_ptr % runtime->period_size; @@ -1421,7 +1415,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) int i, num_drecs; struct drain_rec *drec, drec_tmp, *d; - snd_assert(substream != NULL, return -ENXIO); card = substream->pcm->card; runtime = substream->runtime; @@ -1541,7 +1534,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) struct snd_card *card; int result = 0; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; card = substream->pcm->card; @@ -1934,33 +1928,41 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX; } err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, hw->channels_min, hw->channels_max); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, hw->rate_min, hw->rate_max); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, hw->period_bytes_min, hw->period_bytes_max); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, hw->periods_min, hw->periods_max); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, hw->period_bytes_min, hw->buffer_bytes_max); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return err; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, snd_pcm_hw_rule_buffer_bytes_max, substream, @@ -1971,7 +1973,8 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) /* FIXME: remove */ if (runtime->dma_bytes) { err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes); - snd_assert(err >= 0, return -EINVAL); + if (err < 0) + return -EINVAL; } if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) { @@ -2067,8 +2070,8 @@ static int snd_pcm_open_file(struct file *file, struct snd_pcm_str *str; int err; - snd_assert(rpcm_file != NULL, return -EINVAL); - *rpcm_file = NULL; + if (rpcm_file) + *rpcm_file = NULL; err = snd_pcm_open_substream(pcm, stream, file, &substream); if (err < 0) @@ -2086,7 +2089,8 @@ static int snd_pcm_open_file(struct file *file, substream->pcm_release = pcm_release_private; } file->private_data = pcm_file; - *rpcm_file = pcm_file; + if (rpcm_file) + *rpcm_file = pcm_file; return 0; } @@ -2170,7 +2174,8 @@ static int snd_pcm_release(struct inode *inode, struct file *file) pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (snd_BUG_ON(!substream)) + return -ENXIO; pcm = substream->pcm; fasync_helper(-1, file, 0, &substream->runtime->fasync); mutex_lock(&pcm->open_mutex); @@ -2493,8 +2498,6 @@ static int snd_pcm_common_ioctl1(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { - snd_assert(substream != NULL, return -ENXIO); - switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; @@ -2563,8 +2566,10 @@ static int snd_pcm_playback_ioctl1(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { - snd_assert(substream != NULL, return -ENXIO); - snd_assert(substream->stream == SNDRV_PCM_STREAM_PLAYBACK, return -EINVAL); + if (snd_BUG_ON(!substream)) + return -ENXIO; + if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) + return -EINVAL; switch (cmd) { case SNDRV_PCM_IOCTL_WRITEI_FRAMES: { @@ -2643,8 +2648,10 @@ static int snd_pcm_capture_ioctl1(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { - snd_assert(substream != NULL, return -ENXIO); - snd_assert(substream->stream == SNDRV_PCM_STREAM_CAPTURE, return -EINVAL); + if (snd_BUG_ON(!substream)) + return -ENXIO; + if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) + return -EINVAL; switch (cmd) { case SNDRV_PCM_IOCTL_READI_FRAMES: { @@ -2783,7 +2790,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; @@ -2806,21 +2814,17 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, result = -ENXIO; goto end); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - result = -EBADFD; - goto end; - } - if (!frame_aligned(runtime, count)) { - result = -EINVAL; - goto end; - } + if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + if (!frame_aligned(runtime, count)) + return -EINVAL; count = bytes_to_frames(runtime, count); result = snd_pcm_lib_write(substream, buf, count); if (result > 0) result = frames_to_bytes(runtime, result); - end: return result; } @@ -2838,7 +2842,8 @@ static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov, pcm_file = iocb->ki_filp->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; @@ -2872,17 +2877,14 @@ static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov, pcm_file = iocb->ki_filp->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, result = -ENXIO; goto end); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - result = -EBADFD; - goto end; - } + if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; if (nr_segs > 128 || nr_segs != runtime->channels || - !frame_aligned(runtime, iov->iov_len)) { - result = -EINVAL; - goto end; - } + !frame_aligned(runtime, iov->iov_len)) + return -EINVAL; frames = bytes_to_samples(runtime, iov->iov_len); bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); if (bufs == NULL) @@ -2893,7 +2895,6 @@ static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov, if (result > 0) result = frames_to_bytes(runtime, result); kfree(bufs); - end: return result; } @@ -2908,7 +2909,8 @@ static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; poll_wait(file, &runtime->sleep, wait); @@ -2946,7 +2948,8 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; runtime = substream->runtime; poll_wait(file, &runtime->sleep, wait); @@ -3016,7 +3019,6 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file if (!(area->vm_flags & VM_READ)) return -EINVAL; runtime = substream->runtime; - snd_assert(runtime != NULL, return -EAGAIN); size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) return -EINVAL; @@ -3056,7 +3058,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file if (!(area->vm_flags & VM_READ)) return -EINVAL; runtime = substream->runtime; - snd_assert(runtime != NULL, return -EAGAIN); size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) return -EINVAL; @@ -3188,7 +3189,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, return -EINVAL; } runtime = substream->runtime; - snd_assert(runtime != NULL, return -EAGAIN); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) @@ -3220,7 +3220,8 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, return -ENXIO); + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { @@ -3248,9 +3249,9 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) lock_kernel(); pcm_file = file->private_data; substream = pcm_file->substream; - snd_assert(substream != NULL, goto out); + if (PCM_RUNTIME_CHECK(substream)) + goto out; runtime = substream->runtime; - err = fasync_helper(fd, file, on, &runtime->fasync); out: unlock_kernel(); diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index 033a024d153..2c89c04f291 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c @@ -51,12 +51,14 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) mult = 1000000000; rate = runtime->rate; - snd_assert(rate != 0, return); + if (snd_BUG_ON(!rate)) + return; l = gcd(mult, rate); mult /= l; rate /= l; fsize = runtime->period_size; - snd_assert(fsize != 0, return); + if (snd_BUG_ON(!fsize)) + return; l = gcd(rate, fsize); rate /= l; fsize /= l; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b917a9f981c..c4995c9f573 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -470,8 +470,8 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) struct snd_rawmidi_substream *substream; struct snd_rawmidi_runtime *runtime; - snd_assert(rfile != NULL, return -ENXIO); - snd_assert(rfile->input != NULL || rfile->output != NULL, return -ENXIO); + if (snd_BUG_ON(!rfile)) + return -ENXIO; rmidi = rfile->rmidi; mutex_lock(&rmidi->open_mutex); if (rfile->input != NULL) { @@ -1100,7 +1100,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count) return -EINVAL; } spin_lock_irqsave(&runtime->lock, flags); - snd_assert(runtime->avail + count <= runtime->buffer_size, ); + snd_BUG_ON(runtime->avail + count > runtime->buffer_size); runtime->hw_ptr += count; runtime->hw_ptr %= runtime->buffer_size; runtime->avail += count; @@ -1141,8 +1141,10 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, long count1, result; struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_assert(kernelbuf != NULL || userbuf != NULL, return -EINVAL); - snd_assert(runtime->buffer != NULL, return -EINVAL); + if (snd_BUG_ON(!kernelbuf && !userbuf)) + return -EINVAL; + if (snd_BUG_ON(!runtime->buffer)) + return -EINVAL; result = 0; spin_lock_irqsave(&runtime->lock, flags); @@ -1420,9 +1422,10 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, .dev_disconnect = snd_rawmidi_dev_disconnect, }; - snd_assert(rrawmidi != NULL, return -EINVAL); - *rrawmidi = NULL; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; + if (rrawmidi) + *rrawmidi = NULL; rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL); if (rmidi == NULL) { snd_printk(KERN_ERR "rawmidi: cannot allocate\n"); @@ -1455,7 +1458,8 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, snd_rawmidi_free(rmidi); return err; } - *rrawmidi = rmidi; + if (rrawmidi) + *rrawmidi = rmidi; return 0; } @@ -1472,7 +1476,8 @@ static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream) static int snd_rawmidi_free(struct snd_rawmidi *rmidi) { - snd_assert(rmidi != NULL, return -ENXIO); + if (!rmidi) + return 0; snd_info_free_entry(rmidi->proc_entry); rmidi->proc_entry = NULL; diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 97b30fb4c36..51e64e30dd3 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -91,7 +91,8 @@ static int rtctimer_start(struct snd_timer *timer) { rtc_task_t *rtc = timer->private_data; - snd_assert(rtc != NULL, return -EINVAL); + if (snd_BUG_ON(!rtc)) + return -EINVAL; rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq); rtc_control(rtc, RTC_PIE_ON, 0); return 0; @@ -101,7 +102,8 @@ static int rtctimer_stop(struct snd_timer *timer) { rtc_task_t *rtc = timer->private_data; - snd_assert(rtc != NULL, return -EINVAL); + if (snd_BUG_ON(!rtc)) + return -EINVAL; rtc_control(rtc, RTC_PIE_OFF, 0); return 0; } diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 777796e9449..f25e3cc7ddf 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -164,7 +164,8 @@ odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { struct seq_oss_devinfo *dp; dp = file->private_data; - snd_assert(dp != NULL, return -EIO); + if (snd_BUG_ON(!dp)) + return -ENXIO; return snd_seq_oss_read(dp, buf, count); } @@ -174,7 +175,8 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs { struct seq_oss_devinfo *dp; dp = file->private_data; - snd_assert(dp != NULL, return -EIO); + if (snd_BUG_ON(!dp)) + return -ENXIO; return snd_seq_oss_write(dp, buf, count, file); } @@ -183,7 +185,8 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct seq_oss_devinfo *dp; dp = file->private_data; - snd_assert(dp != NULL, return -EIO); + if (snd_BUG_ON(!dp)) + return -ENXIO; return snd_seq_oss_ioctl(dp, cmd, arg); } @@ -198,7 +201,8 @@ odev_poll(struct file *file, poll_table * wait) { struct seq_oss_devinfo *dp; dp = file->private_data; - snd_assert(dp != NULL, return 0); + if (snd_BUG_ON(!dp)) + return -ENXIO; return snd_seq_oss_poll(dp, file, wait); } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index e024e4588b8..945a27c34a9 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -308,7 +308,8 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; - snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return); + if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) + return; for (i = 0; i < dp->max_synthdev; i++) { info = &dp->synths[i]; if (! info->opened) @@ -402,7 +403,8 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev) struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; - snd_assert(dev >= 0 && dev < dp->max_synthdev, return); + if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev)) + return; info = &dp->synths[dev]; if (! info->opened) return; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 7a1545d2d95..8ca2be339f3 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -266,7 +266,8 @@ static int seq_free_client1(struct snd_seq_client *client) { unsigned long flags; - snd_assert(client != NULL, return -EINVAL); + if (!client) + return 0; snd_seq_delete_all_ports(client); snd_seq_queue_client_leave(client->number); spin_lock_irqsave(&clients_lock, flags); @@ -403,7 +404,8 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, return -EFAULT; /* check client structures are in place */ - snd_assert(client != NULL, return -ENXIO); + if (snd_BUG_ON(!client)) + return -ENXIO; if (!client->accept_input || (fifo = client->data.user.fifo) == NULL) return -ENXIO; @@ -825,7 +827,8 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop) struct snd_seq_client *client; int result; - snd_assert(cell != NULL, return -EINVAL); + if (snd_BUG_ON(!cell)) + return -EINVAL; client = snd_seq_client_use_ptr(cell->event.source.client); if (client == NULL) { @@ -994,7 +997,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, return -ENXIO; /* check client structures are in place */ - snd_assert(client != NULL, return -ENXIO); + if (snd_BUG_ON(!client)) + return -ENXIO; if (!client->accept_output || client->pool == NULL) return -ENXIO; @@ -1076,7 +1080,8 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) unsigned int mask = 0; /* check client structures are in place */ - snd_assert(client != NULL, return -ENXIO); + if (snd_BUG_ON(!client)) + return -ENXIO; if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) && client->data.user.fifo) { @@ -2195,7 +2200,8 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg { struct snd_seq_client *client = file->private_data; - snd_assert(client != NULL, return -ENXIO); + if (snd_BUG_ON(!client)) + return -ENXIO; return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } @@ -2216,7 +2222,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, struct snd_seq_client *client; va_list args; - snd_assert(! in_interrupt(), return -EBUSY); + if (snd_BUG_ON(in_interrupt())) + return -EBUSY; if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD) return -EINVAL; @@ -2265,7 +2272,8 @@ int snd_seq_delete_kernel_client(int client) { struct snd_seq_client *ptr; - snd_assert(! in_interrupt(), return -EBUSY); + if (snd_BUG_ON(in_interrupt())) + return -EBUSY; ptr = clientptr(client); if (ptr == NULL) @@ -2288,7 +2296,8 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev, struct snd_seq_client *cptr; int result; - snd_assert(ev != NULL, return -EINVAL); + if (snd_BUG_ON(!ev)) + return -EINVAL; if (ev->type == SNDRV_SEQ_EVENT_NONE) return 0; /* ignore this */ @@ -2354,7 +2363,8 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, struct snd_seq_client *cptr; int result; - snd_assert(ev != NULL, return -EINVAL); + if (snd_BUG_ON(!ev)) + return -EINVAL; /* fill in client number */ ev->queue = SNDRV_SEQ_QUEUE_DIRECT; diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 9628c06e4ea..38693f47c26 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -92,7 +92,8 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l struct snd_seq_client *client = file->private_data; void __user *argp = compat_ptr(arg); - snd_assert(client != NULL, return -ENXIO); + if (snd_BUG_ON(!client)) + return -ENXIO; switch (cmd) { case SNDRV_SEQ_IOCTL_PVERSION: diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 05410e536a4..1f997675c89 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -187,7 +187,8 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, if (result) *result = NULL; - snd_assert(id != NULL, return -EINVAL); + if (snd_BUG_ON(!id)) + return -EINVAL; ops = find_driver(id, 1); if (ops == NULL) @@ -232,7 +233,8 @@ static int snd_seq_device_free(struct snd_seq_device *dev) { struct ops_list *ops; - snd_assert(dev != NULL, return -EINVAL); + if (snd_BUG_ON(!dev)) + return -EINVAL; ops = find_driver(dev->id, 0); if (ops == NULL) diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 3a94ed021bd..0d75afa786b 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -65,9 +65,11 @@ void snd_seq_fifo_delete(struct snd_seq_fifo **fifo) { struct snd_seq_fifo *f; - snd_assert(fifo != NULL, return); + if (snd_BUG_ON(!fifo)) + return; f = *fifo; - snd_assert(f != NULL, return); + if (snd_BUG_ON(!f)) + return; *fifo = NULL; snd_seq_fifo_clear(f); @@ -116,7 +118,8 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, unsigned long flags; int err; - snd_assert(f != NULL, return -EINVAL); + if (snd_BUG_ON(!f)) + return -EINVAL; snd_use_lock_use(&f->use_lock); err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */ @@ -174,7 +177,8 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, unsigned long flags; wait_queue_t wait; - snd_assert(f != NULL, return -EINVAL); + if (snd_BUG_ON(!f)) + return -EINVAL; *cellp = NULL; init_waitqueue_entry(&wait, current); @@ -233,7 +237,8 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) struct snd_seq_pool *newpool, *oldpool; struct snd_seq_event_cell *cell, *next, *oldhead; - snd_assert(f != NULL && f->pool != NULL, return -EINVAL); + if (snd_BUG_ON(!f || !f->pool)) + return -EINVAL; /* allocate new pool */ newpool = snd_seq_pool_new(poolsize); diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 0cf6ac47731..7fb55436287 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -187,9 +187,11 @@ void snd_seq_cell_free(struct snd_seq_event_cell * cell) unsigned long flags; struct snd_seq_pool *pool; - snd_assert(cell != NULL, return); + if (snd_BUG_ON(!cell)) + return; pool = cell->pool; - snd_assert(pool != NULL, return); + if (snd_BUG_ON(!pool)) + return; spin_lock_irqsave(&pool->lock, flags); free_cell(pool, cell); @@ -378,7 +380,8 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) struct snd_seq_event_cell *cellptr; unsigned long flags; - snd_assert(pool != NULL, return -EINVAL); + if (snd_BUG_ON(!pool)) + return -EINVAL; if (pool->ptr) /* should be atomic? */ return 0; @@ -414,7 +417,8 @@ int snd_seq_pool_done(struct snd_seq_pool *pool) struct snd_seq_event_cell *ptr; int max_count = 5 * HZ; - snd_assert(pool != NULL, return -EINVAL); + if (snd_BUG_ON(!pool)) + return -EINVAL; /* wait for closing all threads */ spin_lock_irqsave(&pool->lock, flags); diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 99b35360c50..4d26146a62c 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -116,7 +116,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i struct snd_rawmidi_runtime *runtime; int tmp; - snd_assert(substream != NULL || buf != NULL, return -EINVAL); + if (snd_BUG_ON(!substream || !buf)) + return -EINVAL; runtime = substream->runtime; if ((tmp = runtime->avail) < count) { snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp); @@ -135,7 +136,8 @@ static int event_process_midi(struct snd_seq_event *ev, int direct, struct snd_rawmidi_substream *substream; int len; - snd_assert(msynth != NULL, return -EINVAL); + if (snd_BUG_ON(!msynth)) + return -EINVAL; substream = msynth->output_rfile.output; if (substream == NULL) return -ENODEV; @@ -210,7 +212,8 @@ static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscri int err; struct seq_midisynth *msynth = private_data; - snd_assert(msynth->input_rfile.input != NULL, return -EINVAL); + if (snd_BUG_ON(!msynth->input_rfile.input)) + return -EINVAL; err = snd_rawmidi_kernel_release(&msynth->input_rfile); return err; } @@ -247,7 +250,8 @@ static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *in struct seq_midisynth *msynth = private_data; unsigned char buf = 0xff; /* MIDI reset */ - snd_assert(msynth->output_rfile.output != NULL, return -EINVAL); + if (snd_BUG_ON(!msynth->output_rfile.output)) + return -EINVAL; /* sending single MIDI reset message to shut the device up */ snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1); snd_rawmidi_drain_output(msynth->output_rfile.output); @@ -285,7 +289,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) int device = dev->device; unsigned int input_count = 0, output_count = 0; - snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL); + if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES)) + return -EINVAL; info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) return -ENOMEM; diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 1c32a53d6bd..3bf7d73ac52 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -130,7 +130,8 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int num = -1; /* sanity check */ - snd_assert(client, return NULL); + if (snd_BUG_ON(!client)) + return NULL; if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) { snd_printk(KERN_WARNING "too many ports for client %d\n", client->number); @@ -268,8 +269,8 @@ static int port_delete(struct snd_seq_client *client, if (port->private_free) port->private_free(port->private_data); - snd_assert(port->c_src.count == 0,); - snd_assert(port->c_dest.count == 0,); + snd_BUG_ON(port->c_src.count != 0); + snd_BUG_ON(port->c_dest.count != 0); kfree(port); return 0; @@ -336,7 +337,8 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) int snd_seq_set_port_info(struct snd_seq_client_port * port, struct snd_seq_port_info * info) { - snd_assert(port && info, return -EINVAL); + if (snd_BUG_ON(!port || !info)) + return -EINVAL; /* set port name */ if (info->name[0]) @@ -365,7 +367,8 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port, int snd_seq_get_port_info(struct snd_seq_client_port * port, struct snd_seq_port_info * info) { - snd_assert(port && info, return -EINVAL); + if (snd_BUG_ON(!port || !info)) + return -EINVAL; /* get port name */ strlcpy(info->name, port->name, sizeof(info->name)); diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 85969db576c..0101a8b99b7 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c @@ -153,8 +153,8 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, int count; int prior; - snd_assert(f, return -EINVAL); - snd_assert(cell, return -EINVAL); + if (snd_BUG_ON(!f || !cell)) + return -EINVAL; /* check flags */ prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK); diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 4a48c6ee8ee..e7a8e9e4edb 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -315,7 +315,8 @@ int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop) int dest, err; struct snd_seq_queue *q; - snd_assert(cell != NULL, return -EINVAL); + if (snd_BUG_ON(!cell)) + return -EINVAL; dest = cell->event.queue; /* destination queue */ q = queueptr(dest); if (q == NULL) @@ -734,7 +735,8 @@ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) { struct snd_seq_queue *q; - snd_assert(ev != NULL, return -EINVAL); + if (snd_BUG_ON(!ev)) + return -EINVAL; q = queueptr(ev->data.queue.queue); if (q == NULL) diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index d8fcd62e400..f745c317d6a 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -173,7 +173,8 @@ int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo) { unsigned long flags; - snd_assert(tmr, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; if (tempo <= 0) return -EINVAL; spin_lock_irqsave(&tmr->lock, flags); @@ -190,7 +191,8 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq) { unsigned long flags; - snd_assert(tmr, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; if (ppq <= 0) return -EINVAL; spin_lock_irqsave(&tmr->lock, flags); @@ -214,7 +216,8 @@ int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, { unsigned long flags; - snd_assert(tmr, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; spin_lock_irqsave(&tmr->lock, flags); tmr->tick.cur_tick = position; @@ -229,7 +232,8 @@ int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, { unsigned long flags; - snd_assert(tmr, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; snd_seq_sanity_real_time(&position); spin_lock_irqsave(&tmr->lock, flags); @@ -244,7 +248,8 @@ int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, { unsigned long flags; - snd_assert(tmr, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; /* FIXME */ if (base != SKEW_BASE) { @@ -265,7 +270,8 @@ int snd_seq_timer_open(struct snd_seq_queue *q) int err; tmr = q->timer; - snd_assert(tmr != NULL, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; if (tmr->timeri) return -EBUSY; sprintf(str, "sequencer queue %i", q->queue); @@ -302,7 +308,8 @@ int snd_seq_timer_close(struct snd_seq_queue *q) struct snd_seq_timer *tmr; tmr = q->timer; - snd_assert(tmr != NULL, return -EINVAL); + if (snd_BUG_ON(!tmr)) + return -EINVAL; if (tmr->timeri) { snd_timer_stop(tmr->timeri); snd_timer_close(tmr->timeri); @@ -328,7 +335,8 @@ static int initialize_timer(struct snd_seq_timer *tmr) unsigned long freq; t = tmr->timeri->timer; - snd_assert(t, return -EINVAL); + if (snd_BUG_ON(!t)) + return -EINVAL; freq = tmr->preferred_resolution; if (!freq) diff --git a/sound/core/sound.c b/sound/core/sound.c index 838dd9ee957..c0685e2f0af 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -206,20 +206,23 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) minor = type; break; case SNDRV_DEVICE_TYPE_CONTROL: - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; minor = SNDRV_MINOR(card->number, type); break; case SNDRV_DEVICE_TYPE_HWDEP: case SNDRV_DEVICE_TYPE_RAWMIDI: case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: case SNDRV_DEVICE_TYPE_PCM_CAPTURE: - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; minor = SNDRV_MINOR(card->number, type + dev); break; default: return -EINVAL; } - snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL); + if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS)) + return -EINVAL; return minor; } #endif @@ -247,7 +250,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, int minor; struct snd_minor *preg; - snd_assert(name, return -EINVAL); + if (snd_BUG_ON(!name)) + return -EINVAL; preg = kmalloc(sizeof *preg, GFP_KERNEL); if (preg == NULL) return -ENOMEM; diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 7be51546eb9..7fe12264ff8 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -64,7 +64,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) switch (type) { case SNDRV_OSS_DEVICE_TYPE_MIXER: - snd_assert(card != NULL && dev <= 1, return -EINVAL); + if (snd_BUG_ON(!card || dev < 0 || dev > 1)) + return -EINVAL; minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER)); break; case SNDRV_OSS_DEVICE_TYPE_SEQUENCER: @@ -74,11 +75,13 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) minor = SNDRV_MINOR_OSS_MUSIC; break; case SNDRV_OSS_DEVICE_TYPE_PCM: - snd_assert(card != NULL && dev <= 1, return -EINVAL); + if (snd_BUG_ON(!card || dev < 0 || dev > 1)) + return -EINVAL; minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM)); break; case SNDRV_OSS_DEVICE_TYPE_MIDI: - snd_assert(card != NULL && dev <= 1, return -EINVAL); + if (snd_BUG_ON(!card || dev < 0 || dev > 1)) + return -EINVAL; minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI)); break; case SNDRV_OSS_DEVICE_TYPE_DMFM: @@ -90,7 +93,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) default: return -EINVAL; } - snd_assert(minor >= 0 && minor < SNDRV_OSS_MINORS, return -EINVAL); + if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OSS_MINORS)) + return -EINVAL; return minor; } diff --git a/sound/core/timer.c b/sound/core/timer.c index 0af337efc64..b8ee49c1f85 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -306,7 +306,8 @@ int snd_timer_close(struct snd_timer_instance *timeri) struct snd_timer *timer = NULL; struct snd_timer_instance *slave, *tmp; - snd_assert(timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!timer)) + return -ENXIO; /* force to stop the timer */ snd_timer_stop(timeri); @@ -385,8 +386,9 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) do_posix_clock_monotonic_gettime(&tstamp); else getnstimeofday(&tstamp); - snd_assert(event >= SNDRV_TIMER_EVENT_START && - event <= SNDRV_TIMER_EVENT_PAUSE, return); + if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || + event > SNDRV_TIMER_EVENT_PAUSE)) + return; if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); @@ -474,7 +476,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, struct snd_timer *timer; unsigned long flags; - snd_assert(timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!timeri)) + return -ENXIO; if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { if (!keep_flag) { @@ -758,9 +761,10 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, .dev_disconnect = snd_timer_dev_disconnect, }; - snd_assert(tid != NULL, return -EINVAL); - snd_assert(rtimer != NULL, return -EINVAL); - *rtimer = NULL; + if (snd_BUG_ON(!tid)) + return -EINVAL; + if (rtimer) + *rtimer = NULL; timer = kzalloc(sizeof(*timer), GFP_KERNEL); if (timer == NULL) { snd_printk(KERN_ERR "timer: cannot allocate\n"); @@ -788,13 +792,15 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, return err; } } - *rtimer = timer; + if (rtimer) + *rtimer = timer; return 0; } static int snd_timer_free(struct snd_timer *timer) { - snd_assert(timer != NULL, return -ENXIO); + if (!timer) + return 0; mutex_lock(®ister_mutex); if (! list_empty(&timer->open_list_head)) { @@ -827,8 +833,8 @@ static int snd_timer_dev_register(struct snd_device *dev) struct snd_timer *timer = dev->device_data; struct snd_timer *timer1; - snd_assert(timer != NULL && timer->hw.start != NULL && - timer->hw.stop != NULL, return -ENXIO); + if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop)) + return -ENXIO; if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && !timer->hw.resolution && timer->hw.c_resolution == NULL) return -EINVAL; @@ -879,8 +885,9 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) return; - snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && - event <= SNDRV_TIMER_EVENT_MRESUME, return); + if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || + event > SNDRV_TIMER_EVENT_MRESUME)) + return; spin_lock_irqsave(&timer->lock, flags); if (event == SNDRV_TIMER_EVENT_MSTART || event == SNDRV_TIMER_EVENT_MCONTINUE || diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 5512f5373c5..e05802ae6e1 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -40,9 +40,11 @@ static int snd_timer_user_info_compat(struct file *file, struct snd_timer *t; tu = file->private_data; - snd_assert(tu->timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!tu->timeri)) + return -ENXIO; t = tu->timeri->timer; - snd_assert(t != NULL, return -ENXIO); + if (snd_BUG_ON(!t)) + return -ENXIO; memset(&info, 0, sizeof(info)); info.card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) @@ -71,7 +73,8 @@ static int snd_timer_user_status_compat(struct file *file, struct snd_timer_status status; tu = file->private_data; - snd_assert(tu->timeri != NULL, return -ENXIO); + if (snd_BUG_ON(!tu->timeri)) + return -ENXIO; memset(&status, 0, sizeof(status)); status.tstamp = tu->tstamp; status.resolution = snd_timer_resolution(tu->timeri); -- GitLab From 622207dc31895b4e82c39100db8635d885c795e2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:11:45 +0200 Subject: [PATCH 0298/5416] ALSA: Kill snd_assert() in sound/isa/* Kill snd_assert() in sound/isa/*, either removed or replaced with if () with snd_BUG_ON(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/isa/ad1816a/ad1816a_lib.c | 6 ++++-- sound/isa/cs423x/cs4236_lib.c | 3 ++- sound/isa/es1688/es1688_lib.c | 3 ++- sound/isa/gus/gus_main.c | 6 ++++-- sound/isa/gus/gus_mixer.c | 6 ++++-- sound/isa/gus/gus_pcm.c | 12 ++++++++---- sound/isa/opti9xx/miro.c | 3 ++- sound/isa/sb/emu8000.c | 3 ++- sound/isa/sb/emu8000_patch.c | 3 ++- sound/isa/sb/sb16_csp.c | 9 ++++++--- sound/isa/sb/sb16_main.c | 3 ++- sound/isa/sb/sb8_main.c | 8 ++++++-- sound/isa/sb/sb_common.c | 3 ++- sound/isa/sb/sb_mixer.c | 9 ++++++--- sound/isa/wavefront/wavefront_fx.c | 8 ++++---- sound/isa/wavefront/wavefront_midi.c | 24 ++++++++++++++++-------- sound/isa/wavefront/wavefront_synth.c | 7 ++++--- sound/isa/wss/wss_lib.c | 6 ++++-- 18 files changed, 80 insertions(+), 42 deletions(-) diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 4b8dfe2e3dc..3bfca7c59ba 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -394,7 +394,8 @@ static int snd_ad1816a_timer_open(struct snd_timer *timer) static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) { - snd_assert(timer != NULL, return 0); + if (snd_BUG_ON(!timer)) + return 0; return 10000; } @@ -961,7 +962,8 @@ int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip) unsigned int idx; int err; - snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->card)) + return -EINVAL; card = chip->card; diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 33e9cf178b8..6a85fdc53b6 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -967,7 +967,8 @@ int snd_cs4236_mixer(struct snd_wss *chip) int err; struct snd_kcontrol_new *kcontrol; - snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->card)) + return -EINVAL; card = chip->card; strcpy(card->mixername, snd_wss_chip_id(chip)); diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 1e1e575b1db..4fbb508a817 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -1009,7 +1009,8 @@ int snd_es1688_mixer(struct snd_es1688 *chip) int err; unsigned char reg, val; - snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->card)) + return -EINVAL; card = chip->card; diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index cccc16c8113..12eb98f2f93 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -276,9 +276,11 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) static unsigned char dmas[8] = {6, 1, 0, 2, 0, 3, 4, 5}; - snd_assert(gus != NULL, return -EINVAL); + if (snd_BUG_ON(!gus)) + return -EINVAL; card = gus->card; - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; gus->mix_cntrl_reg &= 0xf8; gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */ diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index ebdb3346930..0dd43414016 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c @@ -161,9 +161,11 @@ int snd_gf1_new_mixer(struct snd_gus_card * gus) unsigned int idx, max; int err; - snd_assert(gus != NULL, return -EINVAL); + if (snd_BUG_ON(!gus)) + return -EINVAL; card = gus->card; - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; if (gus->ics_flag) snd_component_add(card, "ICS2101"); diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 99731dc9732..38510aeb21c 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -352,8 +352,10 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); len = samples_to_bytes(runtime, count); - snd_assert(bpos <= pcmp->dma_size, return -EIO); - snd_assert(bpos + len <= pcmp->dma_size, return -EIO); + if (snd_BUG_ON(bpos > pcmp->dma_size)) + return -EIO; + if (snd_BUG_ON(bpos + len > pcmp->dma_size)) + return -EIO; if (copy_from_user(runtime->dma_area + bpos, src, len)) return -EFAULT; if (snd_gf1_pcm_use_dma && len > 32) { @@ -381,8 +383,10 @@ static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); len = samples_to_bytes(runtime, count); - snd_assert(bpos <= pcmp->dma_size, return -EIO); - snd_assert(bpos + len <= pcmp->dma_size, return -EIO); + if (snd_BUG_ON(bpos > pcmp->dma_size)) + return -EIO; + if (snd_BUG_ON(bpos + len > pcmp->dma_size)) + return -EIO; snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); if (snd_gf1_pcm_use_dma && len > 32) { return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 4641daa7844..440755cc001 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -675,7 +675,8 @@ static int __devinit snd_miro_mixer(struct snd_miro *miro) unsigned int idx; int err; - snd_assert(miro != NULL && miro->card != NULL, return -EINVAL); + if (snd_BUG_ON(!miro || !miro->card)) + return -EINVAL; card = miro->card; diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index b35be7d9a9f..96678d5d383 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -1023,7 +1023,8 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) { int i, err = 0; - snd_assert(emu != NULL && card != NULL, return -EINVAL); + if (snd_BUG_ON(!emu || !card)) + return -EINVAL; spin_lock_init(&emu->control_lock); diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 1be16c9700f..c99c6078be3 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -156,7 +156,8 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, struct snd_emu8000 *emu; emu = rec->hw; - snd_assert(sp != NULL, return -EINVAL); + if (snd_BUG_ON(!sp)) + return -EINVAL; if (sp->v.size == 0) return 0; diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 35f3d7b1653..49037d074c7 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -198,7 +198,8 @@ static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned i struct snd_sb_csp_start start_info; int err; - snd_assert(p != NULL, return -EINVAL); + if (snd_BUG_ON(!p)) + return -EINVAL; if (snd_sb_csp_check_version(p)) return -ENODEV; @@ -1046,7 +1047,8 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p) struct snd_card *card; int err; - snd_assert(p != NULL, return -EINVAL); + if (snd_BUG_ON(!p)) + return -EINVAL; card = p->chip->card; p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2; @@ -1071,7 +1073,8 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) struct snd_card *card; unsigned long flags; - snd_assert(p != NULL, return); + if (snd_BUG_ON(!p)) + return; card = p->chip->card; diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index f7e8192270a..2a6cc1cfe94 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -669,7 +669,8 @@ static int snd_sb16_capture_close(struct snd_pcm_substream *substream) static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what) { if (chip->dma8 < 0 || chip->dma16 < 0) { - snd_assert(what == 0, return -EINVAL); + if (snd_BUG_ON(what)) + return -EINVAL; return 0; } if (what == 0) { diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index fe03bb82053..658d55769c9 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -111,7 +111,9 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) switch (chip->hardware) { case SB_HW_PRO: if (runtime->channels > 1) { - snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL); + if (snd_BUG_ON(rate != SB8_RATE(11025) && + rate != SB8_RATE(22050))) + return -EINVAL; chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; break; } @@ -237,7 +239,9 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) switch (chip->hardware) { case SB_HW_PRO: if (runtime->channels > 1) { - snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL); + if (snd_BUG_ON(rate != SB8_RATE(11025) && + rate != SB8_RATE(22050))) + return -EINVAL; chip->capture_format = SB_DSP_HI_INPUT_AUTO; break; } diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index b432d9ae874..27a65150225 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -219,7 +219,8 @@ int snd_sbdsp_create(struct snd_card *card, .dev_free = snd_sbdsp_dev_free, }; - snd_assert(r_chip != NULL, return -EINVAL); + if (snd_BUG_ON(!r_chip)) + return -EINVAL; *r_chip = NULL; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 73d4572d136..406a431af91 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -792,7 +792,8 @@ int snd_sbmixer_new(struct snd_sb *chip) struct snd_card *card; int err; - snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->card)) + return -EINVAL; card = chip->card; @@ -925,7 +926,8 @@ static unsigned char als4000_saved_regs[] = { static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) { unsigned char *val = chip->saved_regs; - snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return); + if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) + return; for (; num_regs; num_regs--) *val++ = snd_sbmixer_read(chip, *regs++); } @@ -933,7 +935,8 @@ static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) { unsigned char *val = chip->saved_regs; - snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return); + if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) + return; for (; num_regs; num_regs--) snd_sbmixer_write(chip, *regs++, *val++); } diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 2efaa7f205a..dfc449a2194 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -180,11 +180,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, unsigned short *pd; int err = 0; - snd_assert(sdev->card != NULL, return -ENODEV); - card = sdev->card; - - snd_assert(card->private_data != NULL, return -ENODEV); + if (snd_BUG_ON(!card)) + return -ENODEV; + if (snd_BUG_ON(!card->private_data)) + return -ENODEV; acard = card->private_data; dev = &acard->wavefront; diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index a33384a55b0..f14a7c0b699 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -235,8 +235,10 @@ static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; - snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); - snd_assert(substream->rmidi->private_data != NULL, return -EIO); + if (snd_BUG_ON(!substream || !substream->rmidi)) + return -ENXIO; + if (snd_BUG_ON(!substream->rmidi->private_data)) + return -ENXIO; mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); @@ -257,8 +259,10 @@ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substrea snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; - snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); - snd_assert(substream->rmidi->private_data != NULL, return -EIO); + if (snd_BUG_ON(!substream || !substream->rmidi)) + return -ENXIO; + if (snd_BUG_ON(!substream->rmidi->private_data)) + return -ENXIO; mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); @@ -279,8 +283,10 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; - snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); - snd_assert(substream->rmidi->private_data != NULL, return -EIO); + if (snd_BUG_ON(!substream || !substream->rmidi)) + return -ENXIO; + if (snd_BUG_ON(!substream->rmidi->private_data)) + return -ENXIO; mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); @@ -300,8 +306,10 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre snd_wavefront_midi_t *midi; snd_wavefront_mpu_id mpu; - snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); - snd_assert(substream->rmidi->private_data != NULL, return -EIO); + if (snd_BUG_ON(!substream || !substream->rmidi)) + return -ENXIO; + if (snd_BUG_ON(!substream->rmidi->private_data)) + return -ENXIO; mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 0bb9b925660..4c410820a99 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1648,9 +1648,10 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, card = (struct snd_card *) hw->card; - snd_assert(card != NULL, return -ENODEV); - - snd_assert(card->private_data != NULL, return -ENODEV); + if (snd_BUG_ON(!card)) + return -ENODEV; + if (snd_BUG_ON(!card->private_data)) + return -ENODEV; acard = card->private_data; dev = &acard->wavefront; diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 6b7a0fc6f71..c5beec65936 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1946,7 +1946,8 @@ static int snd_wss_info_mux(struct snd_kcontrol *kcontrol, char **ptexts = texts; struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - snd_assert(chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip->card)) + return -EINVAL; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 2; uinfo->value.enumerated.items = 4; @@ -2262,7 +2263,8 @@ int snd_wss_mixer(struct snd_wss *chip) unsigned int idx; int err; - snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->pcm)) + return -EINVAL; card = chip->card; -- GitLab From da3cec35dd3c31d8706db4bf379372ce70d92118 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:12:14 +0200 Subject: [PATCH 0299/5416] ALSA: Kill snd_assert() in sound/pci/* Kill snd_assert() in sound/pci/*, either removed or replaced with if () with snd_BUG_ON(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ac97/ac97_codec.c | 19 +++-- sound/pci/ad1889.c | 6 +- sound/pci/ak4531_codec.c | 10 ++- sound/pci/atiixp.c | 10 ++- sound/pci/atiixp_modem.c | 10 ++- sound/pci/azt3328.c | 6 +- sound/pci/ca0106/ca_midi.c | 20 +++-- sound/pci/cmipci.c | 9 ++- sound/pci/cs4281.c | 13 +-- sound/pci/cs46xx/cs46xx_lib.c | 72 ++++++++++------- sound/pci/cs46xx/dsp_spos.c | 51 ++++++++---- sound/pci/cs46xx/dsp_spos_scb_lib.c | 115 ++++++++++++++++----------- sound/pci/echoaudio/darla20_dsp.c | 3 +- sound/pci/echoaudio/darla24_dsp.c | 8 +- sound/pci/echoaudio/echo3g_dsp.c | 9 ++- sound/pci/echoaudio/echoaudio.c | 8 +- sound/pci/echoaudio/echoaudio_3g.c | 11 ++- sound/pci/echoaudio/echoaudio_dsp.c | 21 +++-- sound/pci/echoaudio/echoaudio_gml.c | 6 +- sound/pci/echoaudio/gina20_dsp.c | 6 +- sound/pci/echoaudio/gina24_dsp.c | 11 ++- sound/pci/echoaudio/indigo_dsp.c | 8 +- sound/pci/echoaudio/indigodj_dsp.c | 8 +- sound/pci/echoaudio/indigoio_dsp.c | 8 +- sound/pci/echoaudio/layla20_dsp.c | 9 ++- sound/pci/echoaudio/layla24_dsp.c | 11 ++- sound/pci/echoaudio/mia_dsp.c | 13 +-- sound/pci/echoaudio/midi.c | 6 +- sound/pci/echoaudio/mona_dsp.c | 6 +- sound/pci/emu10k1/emu10k1_callback.c | 6 +- sound/pci/emu10k1/emu10k1_patch.c | 23 +++--- sound/pci/emu10k1/emu10k1x.c | 18 +++-- sound/pci/emu10k1/emufx.c | 6 +- sound/pci/emu10k1/emumpu401.c | 18 +++-- sound/pci/emu10k1/memory.c | 19 +++-- sound/pci/emu10k1/voice.c | 9 ++- sound/pci/es1938.c | 3 +- sound/pci/es1968.c | 6 +- sound/pci/hda/hda_codec.c | 21 +++-- sound/pci/hda/hda_generic.c | 3 +- sound/pci/hda/hda_intel.c | 3 +- sound/pci/hda/patch_realtek.c | 6 +- sound/pci/ice1712/ak4xxx.c | 3 +- sound/pci/ice1712/ews.c | 9 ++- sound/pci/ice1712/ice1712.c | 3 +- sound/pci/ice1712/ice1724.c | 3 +- sound/pci/ice1712/juli.c | 3 +- sound/pci/intel8x0.c | 4 +- sound/pci/intel8x0m.c | 3 +- sound/pci/korg1212/korg1212.c | 9 ++- sound/pci/maestro3.c | 10 ++- sound/pci/mixart/mixart.c | 4 +- sound/pci/mixart/mixart_core.c | 18 +++-- sound/pci/mixart/mixart_hwdep.c | 19 +++-- sound/pci/mixart/mixart_mixer.c | 8 +- sound/pci/nm256/nm256.c | 15 ++-- sound/pci/pcxhr/pcxhr.c | 6 +- sound/pci/pcxhr/pcxhr_core.c | 27 ++++--- sound/pci/pcxhr/pcxhr_hwdep.c | 15 ++-- sound/pci/riptide/riptide.c | 18 +++-- sound/pci/rme9652/hdsp.c | 25 +++--- sound/pci/rme9652/hdspm.c | 34 ++++---- sound/pci/rme9652/rme9652.c | 23 +++--- sound/pci/sonicvibes.c | 10 ++- sound/pci/trident/trident_main.c | 22 +++-- sound/pci/trident/trident_memory.c | 24 ++++-- sound/pci/via82xx.c | 8 +- sound/pci/via82xx_modem.c | 3 +- sound/pci/vx222/vx222_ops.c | 12 ++- sound/pci/ymfpci/ymfpci_main.c | 21 +++-- 70 files changed, 632 insertions(+), 361 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 171559c19b3..d0023e99bdf 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1890,8 +1890,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, .dev_free = snd_ac97_bus_dev_free, }; - snd_assert(card != NULL, return -EINVAL); - snd_assert(rbus != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (bus == NULL) return -ENOMEM; @@ -1906,7 +1906,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, snd_ac97_bus_free(bus); return err; } - *rbus = bus; + if (rbus) + *rbus = bus; return 0; } @@ -1991,10 +1992,14 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, .dev_disconnect = snd_ac97_dev_disconnect, }; - snd_assert(rac97 != NULL, return -EINVAL); - *rac97 = NULL; - snd_assert(bus != NULL && template != NULL, return -EINVAL); - snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL); + if (rac97) + *rac97 = NULL; + if (snd_BUG_ON(!bus || !template)) + return -EINVAL; + if (snd_BUG_ON(template->num >= 4)) + return -EINVAL; + if (bus->codec[template->num]) + return -EBUSY; card = bus->card; ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL); diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 39ec55b57b1..92f3a976ef2 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -549,7 +549,8 @@ snd_ad1889_playback_pointer(struct snd_pcm_substream *ss) ptr = ad1889_readl(chip, AD_DMA_WAVCA); ptr -= chip->wave.addr; - snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0); + if (snd_BUG_ON(ptr >= chip->wave.size)) + return 0; return bytes_to_frames(ss->runtime, ptr); } @@ -567,7 +568,8 @@ snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) ptr = ad1889_readl(chip, AD_DMA_ADCCA); ptr -= chip->ramc.addr; - snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0); + if (snd_BUG_ON(ptr >= chip->ramc.size)) + return 0; return bytes_to_frames(ss->runtime, ptr); } diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index 33d37b1c42f..0f819ddb3eb 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c @@ -392,9 +392,10 @@ int __devinit snd_ak4531_mixer(struct snd_card *card, .dev_free = snd_ak4531_dev_free, }; - snd_assert(rak4531 != NULL, return -EINVAL); - *rak4531 = NULL; - snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL); + if (snd_BUG_ON(!card || !_ak4531)) + return -EINVAL; + if (rak4531) + *rak4531 = NULL; ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL); if (ak4531 == NULL) return -ENOMEM; @@ -428,7 +429,8 @@ int __devinit snd_ak4531_mixer(struct snd_card *card, #if 0 snd_ak4531_dump(ak4531); #endif - *rak4531 = ak4531; + if (rak4531) + *rak4531 = ak4531; return 0; } diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 457228fb22a..ce1eb12768f 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -722,7 +722,9 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct atiixp_dma *dma = substream->runtime->private_data; int err = 0; - snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops->enable_transfer || + !dma->ops->flush_dma)) + return -EINVAL; spin_lock(&chip->reg_lock); switch (cmd) { @@ -1032,7 +1034,8 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; int err; - snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) + return -EINVAL; if (dma->opened) return -EBUSY; @@ -1064,7 +1067,8 @@ static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, { struct atiixp *chip = snd_pcm_substream_chip(substream); /* disable DMA bits */ - snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) + return -EINVAL; spin_lock_irq(&chip->reg_lock); dma->ops->enable_dma(chip, 0); spin_unlock_irq(&chip->reg_lock); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index d457a32a793..2f106306c7f 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -674,7 +674,9 @@ static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct atiixp_dma *dma = substream->runtime->private_data; int err = 0; - snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops->enable_transfer || + !dma->ops->flush_dma)) + return -EINVAL; spin_lock(&chip->reg_lock); switch(cmd) { @@ -865,7 +867,8 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, .mask = 0, }; - snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) + return -EINVAL; if (dma->opened) return -EBUSY; @@ -895,7 +898,8 @@ static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, { struct atiixp_modem *chip = snd_pcm_substream_chip(substream); /* disable DMA bits */ - snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL); + if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) + return -EINVAL; spin_lock_irq(&chip->reg_lock); dma->ops->enable_dma(chip, 0); spin_unlock_irq(&chip->reg_lock); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 22f18f3cfbc..333007c523a 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -816,7 +816,8 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) int err; snd_azf3328_dbgcallenter(); - snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->card)) + return -EINVAL; card = chip->card; @@ -1471,7 +1472,8 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, u8 val; unsigned long flags; - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; spin_lock_irqsave(&chip->reg_lock, flags); val = snd_azf3328_game_inb(chip, IDX_GAME_LEGACY_COMPATIBLE); diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 893ee4f1ea7..c7885117da3 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -125,7 +125,8 @@ static int ca_midi_input_open(struct snd_rawmidi_substream *substream) struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; - snd_assert(midi->dev_id, return -ENXIO); + if (snd_BUG_ON(!midi->dev_id)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= CA_MIDI_MODE_INPUT; midi->substream_input = substream; @@ -144,7 +145,8 @@ static int ca_midi_output_open(struct snd_rawmidi_substream *substream) struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; - snd_assert(midi->dev_id, return -ENXIO); + if (snd_BUG_ON(!midi->dev_id)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= CA_MIDI_MODE_OUTPUT; midi->substream_output = substream; @@ -163,7 +165,8 @@ static int ca_midi_input_close(struct snd_rawmidi_substream *substream) struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; - snd_assert(midi->dev_id, return -ENXIO); + if (snd_BUG_ON(!midi->dev_id)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->interrupt_disable(midi,midi->rx_enable); midi->midi_mode &= ~CA_MIDI_MODE_INPUT; @@ -181,7 +184,9 @@ static int ca_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; - snd_assert(midi->dev_id, return -ENXIO); + + if (snd_BUG_ON(!midi->dev_id)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); @@ -201,7 +206,9 @@ static int ca_midi_output_close(struct snd_rawmidi_substream *substream) static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ca_midi *midi = substream->rmidi->private_data; - snd_assert(midi->dev_id, return); + + if (snd_BUG_ON(!midi->dev_id)) + return; if (up) { midi->interrupt_enable(midi,midi->rx_enable); @@ -215,7 +222,8 @@ static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; - snd_assert(midi->dev_id, return); + if (snd_BUG_ON(!midi->dev_id)) + return; if (up) { int max = 4; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 9971b5b7735..1a74ca62c31 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2357,7 +2357,8 @@ static int snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, { struct cmipci_switch_args *args; args = (struct cmipci_switch_args *)kcontrol->private_value; - snd_assert(args != NULL, return -EINVAL); + if (snd_BUG_ON(!args)) + return -EINVAL; return _snd_cmipci_uswitch_get(kcontrol, ucontrol, args); } @@ -2401,7 +2402,8 @@ static int snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, { struct cmipci_switch_args *args; args = (struct cmipci_switch_args *)kcontrol->private_value; - snd_assert(args != NULL, return -EINVAL); + if (snd_BUG_ON(!args)) + return -EINVAL; return _snd_cmipci_uswitch_put(kcontrol, ucontrol, args); } @@ -2662,7 +2664,8 @@ static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_devic unsigned int idx; int err; - snd_assert(cm != NULL && cm->card != NULL, return -EINVAL); + if (snd_BUG_ON(!cm || !cm->card)) + return -EINVAL; card = cm->card; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 7556fd90d0e..ef9308f7c45 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -766,13 +766,13 @@ static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma, if (!capture) { if (dma->left_slot == chip->src_left_play_slot) { unsigned int val = snd_cs4281_rate(runtime->rate, NULL); - snd_assert(dma->right_slot == chip->src_right_play_slot, ); + snd_BUG_ON(dma->right_slot != chip->src_right_play_slot); snd_cs4281_pokeBA0(chip, BA0_DACSR, val); } } else { if (dma->left_slot == chip->src_left_rec_slot) { unsigned int val = snd_cs4281_rate(runtime->rate, NULL); - snd_assert(dma->right_slot == chip->src_right_rec_slot, ); + snd_BUG_ON(dma->right_slot != chip->src_right_rec_slot); snd_cs4281_pokeBA0(chip, BA0_ADCSR, val); } } @@ -1209,7 +1209,8 @@ static void snd_cs4281_gameport_trigger(struct gameport *gameport) { struct cs4281 *chip = gameport_get_port_data(gameport); - snd_assert(chip, return); + if (snd_BUG_ON(!chip)) + return; snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff); } @@ -1217,7 +1218,8 @@ static unsigned char snd_cs4281_gameport_read(struct gameport *gameport) { struct cs4281 *chip = gameport_get_port_data(gameport); - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; return snd_cs4281_peekBA0(chip, BA0_JSPT); } @@ -1228,7 +1230,8 @@ static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, struct cs4281 *chip = gameport_get_port_data(gameport); unsigned js1, js2, jst; - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; js1 = snd_cs4281_peekBA0(chip, BA0_JSC1); js2 = snd_cs4281_peekBA0(chip, BA0_JSC2); diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index e214e567dec..a10ab8283f9 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -90,9 +90,10 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, int count; unsigned short result,tmp; u32 offset = 0; - snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) || - (codec_index == CS46XX_SECONDARY_CODEC_INDEX), - return -EINVAL); + + if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && + codec_index != CS46XX_SECONDARY_CODEC_INDEX)) + return -EINVAL; chip->active_ctrl(chip, 1); @@ -212,9 +213,9 @@ static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97, unsigned short val; int codec_index = ac97->num; - snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || - codec_index == CS46XX_SECONDARY_CODEC_INDEX, - return 0xffff); + if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && + codec_index != CS46XX_SECONDARY_CODEC_INDEX)) + return 0xffff; val = snd_cs46xx_codec_read(chip, reg, codec_index); @@ -229,9 +230,9 @@ static void snd_cs46xx_codec_write(struct snd_cs46xx *chip, { int count; - snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) || - (codec_index == CS46XX_SECONDARY_CODEC_INDEX), - return); + if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && + codec_index != CS46XX_SECONDARY_CODEC_INDEX)) + return; chip->active_ctrl(chip, 1); @@ -294,9 +295,9 @@ static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97, struct snd_cs46xx *chip = ac97->private_data; int codec_index = ac97->num; - snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX || - codec_index == CS46XX_SECONDARY_CODEC_INDEX, - return); + if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && + codec_index != CS46XX_SECONDARY_CODEC_INDEX)) + return; snd_cs46xx_codec_write(chip, reg, val, codec_index); } @@ -315,7 +316,8 @@ int snd_cs46xx_download(struct snd_cs46xx *chip, unsigned int bank = offset >> 16; offset = offset & 0xffff; - snd_assert(!(offset & 3) && !(len & 3), return -EINVAL); + if (snd_BUG_ON((offset & 3) || (len & 3))) + return -EINVAL; dst = chip->region.idx[bank+1].remap_addr + offset; len /= sizeof(u32); @@ -343,7 +345,8 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned int bank = offset >> 16; offset = offset & 0xffff; - snd_assert(!(offset & 3) && !(len & 3), return -EINVAL); + if (snd_BUG_ON((offset & 3) || (len & 3))) + return -EINVAL; dst = chip->region.idx[bank+1].remap_addr + offset; len /= sizeof(u32); @@ -722,7 +725,9 @@ static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_subst struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); size_t ptr; struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; - snd_assert (cpcm->pcm_channel,return -ENXIO); + + if (snd_BUG_ON(!cpcm->pcm_channel)) + return -ENXIO; #ifdef CONFIG_SND_CS46XX_NEW_DSP ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); @@ -740,7 +745,8 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_sub struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; #ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_assert (cpcm->pcm_channel,return -ENXIO); + if (snd_BUG_ON(!cpcm->pcm_channel)) + return -ENXIO; ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); #else ptr = snd_cs46xx_peek(chip, BA1_PBA); @@ -908,7 +914,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, cpcm = runtime->private_data; #ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_assert (sample_rate != 0, return -ENXIO); + if (snd_BUG_ON(!sample_rate)) + return -ENXIO; mutex_lock(&chip->spos_mutex); @@ -917,7 +924,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, return -ENXIO; } - snd_assert (cpcm->pcm_channel != NULL); + snd_BUG_ON(!cpcm->pcm_channel); if (!cpcm->pcm_channel) { mutex_unlock(&chip->spos_mutex); return -ENXIO; @@ -952,7 +959,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { substream->ops = &snd_cs46xx_playback_iec958_ops; } else { - snd_assert(0); + snd_BUG(); } #else substream->ops = &snd_cs46xx_playback_ops; @@ -981,7 +988,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { substream->ops = &snd_cs46xx_playback_indirect_iec958_ops; } else { - snd_assert(0); + snd_BUG(); } #else substream->ops = &snd_cs46xx_playback_indirect_ops; @@ -1029,7 +1036,8 @@ static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream) cpcm = runtime->private_data; #ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_assert (cpcm->pcm_channel != NULL, return -ENXIO); + if (snd_BUG_ON(!cpcm->pcm_channel)) + return -ENXIO; pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 ); pfie &= ~0x0000f03f; @@ -1714,9 +1722,9 @@ static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97) { struct snd_cs46xx *chip = ac97->private_data; - snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) || - (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]), - return); + if (snd_BUG_ON(ac97 != chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] && + ac97 != chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) + return; if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) { chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL; @@ -1864,7 +1872,7 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, break; default: res = -EINVAL; - snd_assert(0, (void)0); + snd_BUG(); /* should never happen ... */ } return res; @@ -2236,7 +2244,7 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3); snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3); } else { - snd_assert(0); /* should never happen ... */ + snd_BUG(); /* should never happen ... */ } udelay(50); @@ -2553,7 +2561,8 @@ static void snd_cs46xx_gameport_trigger(struct gameport *gameport) { struct snd_cs46xx *chip = gameport_get_port_data(gameport); - snd_assert(chip, return); + if (snd_BUG_ON(!chip)) + return; snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); } @@ -2561,7 +2570,8 @@ static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport) { struct snd_cs46xx *chip = gameport_get_port_data(gameport); - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io); } @@ -2570,7 +2580,8 @@ static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, struct snd_cs46xx *chip = gameport_get_port_data(gameport); unsigned js1, js2, jst; - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1); js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2); @@ -2754,7 +2765,8 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) { int idx; - snd_assert(chip != NULL, return -EINVAL); + if (snd_BUG_ON(!chip)) + return -EINVAL; if (chip->active_ctrl) chip->active_ctrl(chip, 1); diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index ccc8bedb5b1..f4f0c8f5dad 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -63,7 +63,8 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 u32 mop_operands,mop_type,wide_op; struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert( ((size % 2) == 0), return -EINVAL); + if (snd_BUG_ON(size %2)) + return -EINVAL; while (i < size) { loval = data[i++]; @@ -289,7 +290,8 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) int i; struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert(ins != NULL, return); + if (snd_BUG_ON(!ins)) + return; mutex_lock(&chip->spos_mutex); for (i = 0; i < ins->nscb; ++i) { @@ -404,7 +406,8 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m /* if module has a code segment it must have symbol table */ - snd_assert(module->symbol_table.symbols != NULL ,return -ENOMEM); + if (snd_BUG_ON(!module->symbol_table.symbols)) + return -ENOMEM; if (add_symbols(chip,module)) { snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n"); return -ENOMEM; @@ -1369,7 +1372,8 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); - snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2); + if (snd_BUG_ON(chip->nr_ac97_codecs != 1 && chip->nr_ac97_codecs != 2)) + goto _fail_end; if (chip->nr_ac97_codecs == 1) { /* output on slot 5 and 11 @@ -1609,11 +1613,14 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST); - snd_assert(spdifo_scb_desc, return -EIO); + if (snd_BUG_ON(!spdifo_scb_desc)) + return -EIO; spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST); - snd_assert(spdifi_scb_desc, return -EIO); + if (snd_BUG_ON(!spdifi_scb_desc)) + return -EIO; async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB); - snd_assert(async_codec_scb_desc, return -EIO); + if (snd_BUG_ON(!async_codec_scb_desc)) + return -EIO; async_codec_scb_desc->parent_scb_ptr = NULL; async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc; @@ -1698,8 +1705,10 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) chip->active_ctrl(chip, 1); chip->amplifier_ctrl(chip, 1); - snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); - snd_assert (ins->spdif_in_src != NULL,return -EINVAL); + if (snd_BUG_ON(ins->asynch_rx_scb)) + return -EINVAL; + if (snd_BUG_ON(!ins->spdif_in_src)) + return -EINVAL; mutex_lock(&chip->spos_mutex); @@ -1754,8 +1763,10 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); - snd_assert (ins->spdif_in_src != NULL,return -EINVAL); + if (snd_BUG_ON(!ins->asynch_rx_scb)) + return -EINVAL; + if (snd_BUG_ON(!ins->spdif_in_src)) + return -EINVAL; mutex_lock(&chip->spos_mutex); @@ -1780,8 +1791,10 @@ int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->pcm_input == NULL,return -EINVAL); - snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); + if (snd_BUG_ON(ins->pcm_input)) + return -EINVAL; + if (snd_BUG_ON(!ins->ref_snoop_scb)) + return -EINVAL; mutex_lock(&chip->spos_mutex); ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, @@ -1795,7 +1808,8 @@ int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->pcm_input != NULL,return -EINVAL); + if (snd_BUG_ON(!ins->pcm_input)) + return -EINVAL; mutex_lock(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->pcm_input); @@ -1809,8 +1823,10 @@ int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->adc_input == NULL,return -EINVAL); - snd_assert (ins->codec_in_scb != NULL,return -EINVAL); + if (snd_BUG_ON(ins->adc_input)) + return -EINVAL; + if (snd_BUG_ON(!ins->codec_in_scb)) + return -EINVAL; mutex_lock(&chip->spos_mutex); ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, @@ -1824,7 +1840,8 @@ int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->adc_input != NULL,return -EINVAL); + if (snd_BUG_ON(!ins->adc_input)) + return -EINVAL; mutex_lock(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->adc_input); diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 2873cfe48c3..dd7c41b037b 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -46,8 +46,11 @@ static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * s struct dsp_spos_instance * ins = chip->dsp_spos_instance; int symbol_index = (int)(symbol - ins->symbol_table.symbols); - snd_assert(ins->symbol_table.nsymbols > 0,return); - snd_assert(symbol_index >= 0 && symbol_index < ins->symbol_table.nsymbols, return); + if (snd_BUG_ON(ins->symbol_table.nsymbols <= 0)) + return; + if (snd_BUG_ON(symbol_index < 0 || + symbol_index >= ins->symbol_table.nsymbols)) + return; ins->symbol_table.symbols[symbol_index].deleted = 1; @@ -116,8 +119,9 @@ static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor if ( scb->parent_scb_ptr ) { /* unlink parent SCB */ - snd_assert ((scb->parent_scb_ptr->sub_list_ptr == scb || - scb->parent_scb_ptr->next_scb_ptr == scb),return); + if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr != scb && + scb->parent_scb_ptr->next_scb_ptr != scb)) + return; if (scb->parent_scb_ptr->sub_list_ptr == scb) { @@ -140,7 +144,6 @@ static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor scb->next_scb_ptr = ins->the_null_scb; } } else { - /* snd_assert ( (scb->sub_list_ptr == ins->the_null_scb), return); */ scb->parent_scb_ptr->next_scb_ptr = scb->next_scb_ptr; if (scb->next_scb_ptr != ins->the_null_scb) { @@ -181,16 +184,17 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * unsigned long flags; /* check integrety */ - snd_assert ( (scb->index >= 0 && - scb->index < ins->nscb && - (ins->scbs + scb->index) == scb), return ); + if (snd_BUG_ON(scb->index < 0 || + scb->index >= ins->nscb || + (ins->scbs + scb->index) != scb)) + return; #if 0 /* can't remove a SCB with childs before removing childs first */ - snd_assert ( (scb->sub_list_ptr == ins->the_null_scb && - scb->next_scb_ptr == ins->the_null_scb), - goto _end); + if (snd_BUG_ON(scb->sub_list_ptr != ins->the_null_scb || + scb->next_scb_ptr != ins->the_null_scb)) + goto _end; #endif spin_lock_irqsave(&scb->lock, flags); @@ -198,7 +202,8 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * spin_unlock_irqrestore(&scb->lock, flags); cs46xx_dsp_proc_free_scb_desc(scb); - snd_assert (scb->scb_symbol != NULL, return ); + if (snd_BUG_ON(!scb->scb_symbol)) + return; remove_symbol (chip,scb->scb_symbol); ins->scbs[scb->index].deleted = 1; @@ -234,7 +239,6 @@ void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) snd_info_free_entry(scb->proc_info); scb->proc_info = NULL; - snd_assert (scb_info != NULL, return); kfree (scb_info); } } @@ -291,7 +295,8 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u unsigned long flags; - snd_assert (ins->the_null_scb != NULL,return NULL); + if (snd_BUG_ON(!ins->the_null_scb)) + return NULL; /* fill the data that will be wroten to DSP */ scb_data[SCBsubListPtr] = @@ -321,18 +326,20 @@ _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u #endif /* link to parent SCB */ if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) { - snd_assert ( (scb->parent_scb_ptr->next_scb_ptr == ins->the_null_scb), - return NULL); + if (snd_BUG_ON(scb->parent_scb_ptr->next_scb_ptr != + ins->the_null_scb)) + return NULL; scb->parent_scb_ptr->next_scb_ptr = scb; } else if (scb_child_type == SCB_ON_PARENT_SUBLIST_SCB) { - snd_assert ( (scb->parent_scb_ptr->sub_list_ptr == ins->the_null_scb), - return NULL); + if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr != + ins->the_null_scb)) + return NULL; scb->parent_scb_ptr->sub_list_ptr = scb; } else { - snd_assert (0,return NULL); + snd_BUG(); } spin_lock_irqsave(&chip->reg_lock, flags); @@ -675,7 +682,7 @@ cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, if (pass_through) { /* wont work with any other rate than the native DSP rate */ - snd_assert (rate == 48000); + snd_BUG_ON(rate != 48000); scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, dest,"DMAREADER",parent_scb, @@ -1142,7 +1149,8 @@ find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from) struct dsp_scb_descriptor * scb = from; while (scb->next_scb_ptr != ins->the_null_scb) { - snd_assert (scb->next_scb_ptr != NULL, return NULL); + if (snd_BUG_ON(!scb->next_scb_ptr)) + return NULL; scb = scb->next_scb_ptr; } @@ -1246,10 +1254,11 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, break; case DSP_PCM_S71_CHANNEL: /* TODO */ - snd_assert(0); + snd_BUG(); break; case DSP_IEC958_CHANNEL: - snd_assert (ins->asynch_tx_scb != NULL, return NULL); + if (snd_BUG_ON(!ins->asynch_tx_scb)) + return NULL; mixer_scb = ins->asynch_tx_scb; /* if sample rate is set to 48khz we pass @@ -1262,7 +1271,7 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, } break; default: - snd_assert (0); + snd_BUG(); return NULL; } /* default sample rate is 44100 */ @@ -1308,7 +1317,8 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, break; } } - snd_assert (src_index != -1,return NULL); + if (snd_BUG_ON(src_index == -1)) + return NULL; /* we need to create a new SRC SCB */ if (mixer_scb->sub_list_ptr == ins->the_null_scb) { @@ -1462,9 +1472,10 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, struct dsp_spos_instance * ins = chip->dsp_spos_instance; unsigned long flags; - snd_assert(pcm_channel->active, return ); - snd_assert(ins->npcm_channels > 0, return ); - snd_assert(pcm_channel->src_scb->ref_count > 0, return ); + if (snd_BUG_ON(!pcm_channel->active || + ins->npcm_channels <= 0 || + pcm_channel->src_scb->ref_count <= 0)) + return; spin_lock_irqsave(&chip->reg_lock, flags); pcm_channel->unlinked = 1; @@ -1479,8 +1490,9 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, if (!pcm_channel->src_scb->ref_count) { cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); - snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot < DSP_MAX_SRC_NR, - return ); + if (snd_BUG_ON(pcm_channel->src_slot < 0 || + pcm_channel->src_slot >= DSP_MAX_SRC_NR)) + return; ins->src_scb_slots[pcm_channel->src_slot] = 0; ins->nsrc_scb --; @@ -1490,11 +1502,11 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, struct dsp_pcm_channel_descriptor * pcm_channel) { - struct dsp_spos_instance * ins = chip->dsp_spos_instance; unsigned long flags; - snd_assert(pcm_channel->active,return -EIO); - snd_assert(ins->npcm_channels > 0,return -EIO); + if (snd_BUG_ON(!pcm_channel->active || + chip->dsp_spos_instance->npcm_channels <= 0)) + return -EIO; spin_lock(&pcm_channel->src_scb->lock); @@ -1537,7 +1549,7 @@ int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, src_scb->sub_list_ptr = pcm_channel->pcm_reader_scb; - snd_assert (pcm_channel->pcm_reader_scb->parent_scb_ptr == NULL, ; ); + snd_BUG_ON(pcm_channel->pcm_reader_scb->parent_scb_ptr); pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb; spin_lock_irqsave(&chip->reg_lock, flags); @@ -1564,7 +1576,8 @@ cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * s struct dsp_scb_descriptor * pcm_input; int insert_point; - snd_assert (ins->record_mixer_scb != NULL,return NULL); + if (snd_BUG_ON(!ins->record_mixer_scb)) + return NULL; if (ins->record_mixer_scb->sub_list_ptr != ins->the_null_scb) { parent = find_next_free_scb (chip,ins->record_mixer_scb->sub_list_ptr); @@ -1583,7 +1596,8 @@ cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * s int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) { - snd_assert (src->parent_scb_ptr != NULL, return -EINVAL ); + if (snd_BUG_ON(!src->parent_scb_ptr)) + return -EINVAL; /* mute SCB */ cs46xx_dsp_scb_set_volume (chip,src,0,0); @@ -1598,8 +1612,10 @@ int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_scb_descriptor * parent_scb; - snd_assert (src->parent_scb_ptr == NULL, return -EINVAL ); - snd_assert(ins->master_mix_scb !=NULL, return -EINVAL ); + if (snd_BUG_ON(src->parent_scb_ptr)) + return -EINVAL; + if (snd_BUG_ON(!ins->master_mix_scb)) + return -EINVAL; if (ins->master_mix_scb->sub_list_ptr != ins->the_null_scb) { parent_scb = find_next_free_scb (chip,ins->master_mix_scb->sub_list_ptr); @@ -1635,8 +1651,11 @@ int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip) return -EBUSY; } - snd_assert (ins->asynch_tx_scb == NULL, return -EINVAL); - snd_assert (ins->master_mix_scb->next_scb_ptr == ins->the_null_scb, return -EINVAL); + if (snd_BUG_ON(ins->asynch_tx_scb)) + return -EINVAL; + if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr != + ins->the_null_scb)) + return -EINVAL; /* reset output snooper sample buffer pointer */ snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2, @@ -1676,10 +1695,15 @@ int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip) } /* check integrety */ - snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL); - snd_assert (ins->spdif_pcm_input_scb != NULL,return -EINVAL); - snd_assert (ins->master_mix_scb->next_scb_ptr == ins->asynch_tx_scb, return -EINVAL); - snd_assert (ins->asynch_tx_scb->parent_scb_ptr == ins->master_mix_scb, return -EINVAL); + if (snd_BUG_ON(!ins->asynch_tx_scb)) + return -EINVAL; + if (snd_BUG_ON(!ins->spdif_pcm_input_scb)) + return -EINVAL; + if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr != ins->asynch_tx_scb)) + return -EINVAL; + if (snd_BUG_ON(ins->asynch_tx_scb->parent_scb_ptr != + ins->master_mix_scb)) + return -EINVAL; cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); @@ -1734,7 +1758,8 @@ int cs46xx_iec958_post_close (struct snd_cs46xx *chip) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL); + if (snd_BUG_ON(!ins->asynch_tx_scb)) + return -EINVAL; ins->spdif_status_out &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN; diff --git a/sound/pci/echoaudio/darla20_dsp.c b/sound/pci/echoaudio/darla20_dsp.c index 4159e3bc186..29043301ebb 100644 --- a/sound/pci/echoaudio/darla20_dsp.c +++ b/sound/pci/echoaudio/darla20_dsp.c @@ -34,7 +34,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Darla20\n")); - snd_assert((subdevice_id & 0xfff0) == DARLA20, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA20)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); diff --git a/sound/pci/echoaudio/darla24_dsp.c b/sound/pci/echoaudio/darla24_dsp.c index 79938eed7e9..60228731841 100644 --- a/sound/pci/echoaudio/darla24_dsp.c +++ b/sound/pci/echoaudio/darla24_dsp.c @@ -34,7 +34,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Darla24\n")); - snd_assert((subdevice_id & 0xfff0) == DARLA24, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA24)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -148,8 +149,9 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) static int set_input_clock(struct echoaudio *chip, u16 clock) { - snd_assert(clock == ECHO_CLOCK_INTERNAL || - clock == ECHO_CLOCK_ESYNC, return -EINVAL); + if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL && + clock != ECHO_CLOCK_ESYNC)) + return -EINVAL; chip->input_clock = clock; return set_sample_rate(chip, chip->sample_rate); } diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c index 48eb7c59911..417e25add82 100644 --- a/sound/pci/echoaudio/echo3g_dsp.c +++ b/sound/pci/echoaudio/echo3g_dsp.c @@ -47,7 +47,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) local_irq_enable(); DE_INIT(("init_hw() - Echo3G\n")); - snd_assert((subdevice_id & 0xfff0) == ECHO3G, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != ECHO3G)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -104,9 +105,11 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip)) < 0) return err; err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); + if (err < 0) + return err; err = set_phantom_power(chip, 0); - snd_assert(err >= 0, return err); + if (err < 0) + return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index e16dc92e82f..160d4705492 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -503,7 +503,7 @@ static int init_engine(struct snd_pcm_substream *substream, if (pipe->index >= 0) { DE_HWP(("hwp_ie free(%d)\n", pipe->index)); err = free_pipes(chip, pipe); - snd_assert(!err); + snd_BUG_ON(err); chip->substream[pipe->index] = NULL; } @@ -690,8 +690,10 @@ static int pcm_prepare(struct snd_pcm_substream *substream) return -EINVAL; } - snd_assert(pipe_index < px_num(chip), return -EINVAL); - snd_assert(is_pipe_allocated(chip, pipe_index), return -EINVAL); + if (snd_BUG_ON(pipe_index >= px_num(chip))) + return -EINVAL; + if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) + return -EINVAL; set_audio_format(chip, pipe_index, &format); return 0; } diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index 52a93318957..c3736bbd819 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -103,9 +103,11 @@ static int set_digital_mode(struct echoaudio *chip, u8 mode) int err, i, o; /* All audio channels must be closed before changing the digital mode */ - snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); + if (snd_BUG_ON(chip->pipe_alloc_mask)) + return -EAGAIN; - snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); + if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) + return -EINVAL; previous_mode = chip->digital_mode; err = dsp_set_digital_mode(chip, mode); @@ -267,8 +269,9 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) return 0; } - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); + if (snd_BUG_ON(rate >= 50000 && + chip->digital_mode == DIGITAL_MODE_ADAT)) + return -EINVAL; clock = 0; control_reg = le32_to_cpu(chip->comm_page->control_register); diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index e6c10077039..be0e18192de 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -474,7 +474,8 @@ static int load_firmware(struct echoaudio *chip) const struct firmware *fw; int box_type, err; - snd_assert(chip->dsp_code_to_load && chip->comm_page, return -EPERM); + if (snd_BUG_ON(!chip->dsp_code_to_load || !chip->comm_page)) + return -EPERM; /* See if the ASIC is present and working - only if the DSP is already loaded */ if (chip->dsp_code) { @@ -512,8 +513,8 @@ static int load_firmware(struct echoaudio *chip) /* Set the nominal level for an input or output bus (true = -10dBV, false = +4dBu) */ static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) { - snd_assert(index < num_busses_out(chip) + num_busses_in(chip), - return -EINVAL); + if (snd_BUG_ON(index >= num_busses_out(chip) + num_busses_in(chip))) + return -EINVAL; /* Wait for the handshake (OK even if ASIC is not loaded) */ if (wait_handshake(chip)) @@ -536,7 +537,8 @@ static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) /* Set the gain for a single physical output channel (dB). */ static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) { - snd_assert(channel < num_busses_out(chip), return -EINVAL); + if (snd_BUG_ON(channel >= num_busses_out(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; @@ -554,8 +556,9 @@ static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input, s8 gain) { - snd_assert(output < num_busses_out(chip) && - input < num_busses_in(chip), return -EINVAL); + if (snd_BUG_ON(output >= num_busses_out(chip) || + input >= num_busses_in(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; @@ -1065,8 +1068,10 @@ static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe) int i; DE_ACT(("free_pipes: Pipe %d\n", pipe->index)); - snd_assert(is_pipe_allocated(chip, pipe->index), return -EINVAL); - snd_assert(pipe->state == PIPE_STATE_STOPPED, return -EINVAL); + if (snd_BUG_ON(!is_pipe_allocated(chip, pipe->index))) + return -EINVAL; + if (snd_BUG_ON(pipe->state != PIPE_STATE_STOPPED)) + return -EINVAL; for (channel_mask = i = 0; i < pipe->interleave; i++) channel_mask |= 1 << (pipe->index + i); diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c index 3aa37e76eba..afa273330e8 100644 --- a/sound/pci/echoaudio/echoaudio_gml.c +++ b/sound/pci/echoaudio/echoaudio_gml.c @@ -112,9 +112,11 @@ static int set_digital_mode(struct echoaudio *chip, u8 mode) return -EIO; /* All audio channels must be closed before changing the digital mode */ - snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); + if (snd_BUG_ON(chip->pipe_alloc_mask)) + return -EAGAIN; - snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); + if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) + return -EINVAL; previous_mode = chip->digital_mode; err = dsp_set_digital_mode(chip, mode); diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c index 2757c896084..db6c952e9d7 100644 --- a/sound/pci/echoaudio/gina20_dsp.c +++ b/sound/pci/echoaudio/gina20_dsp.c @@ -38,7 +38,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Gina20\n")); - snd_assert((subdevice_id & 0xfff0) == GINA20, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -177,7 +178,8 @@ static int set_input_clock(struct echoaudio *chip, u16 clock) /* Set input bus gain (one unit is 0.5dB !) */ static int set_input_gain(struct echoaudio *chip, u16 input, int gain) { - snd_assert(input < num_busses_in(chip), return -EINVAL); + if (snd_BUG_ON(input >= num_busses_in(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c index 144fc567bec..2fef37a2a5b 100644 --- a/sound/pci/echoaudio/gina24_dsp.c +++ b/sound/pci/echoaudio/gina24_dsp.c @@ -43,7 +43,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Gina24\n")); - snd_assert((subdevice_id & 0xfff0) == GINA24, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -84,7 +85,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip)) < 0) return err; err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); + if (err < 0) + return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); @@ -163,8 +165,9 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) { u32 control_reg, clock; - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); + if (snd_BUG_ON(rate >= 50000 && + chip->digital_mode == DIGITAL_MODE_ADAT)) + return -EINVAL; /* Only set the clock for internal mode. */ if (chip->input_clock != ECHO_CLOCK_INTERNAL) { diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c index d6ac7734609..f05e39f7aad 100644 --- a/sound/pci/echoaudio/indigo_dsp.c +++ b/sound/pci/echoaudio/indigo_dsp.c @@ -39,7 +39,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Indigo\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -143,8 +144,9 @@ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, { int index; - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); + if (snd_BUG_ON(pipe >= num_pipes_out(chip) || + output >= num_busses_out(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c index 500e150b49f..90730a5ecb4 100644 --- a/sound/pci/echoaudio/indigodj_dsp.c +++ b/sound/pci/echoaudio/indigodj_dsp.c @@ -39,7 +39,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Indigo DJ\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO_DJ, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJ)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -143,8 +144,9 @@ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, { int index; - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); + if (snd_BUG_ON(pipe >= num_pipes_out(chip) || + output >= num_busses_out(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c index f3ad13d06be..a7e09ec2107 100644 --- a/sound/pci/echoaudio/indigoio_dsp.c +++ b/sound/pci/echoaudio/indigoio_dsp.c @@ -39,7 +39,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Indigo IO\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO_IO, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IO)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -114,8 +115,9 @@ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, { int index; - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); + if (snd_BUG_ON(pipe >= num_pipes_out(chip) || + output >= num_busses_out(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c index 990c9a60a0a..ede75c6ca0f 100644 --- a/sound/pci/echoaudio/layla20_dsp.c +++ b/sound/pci/echoaudio/layla20_dsp.c @@ -42,7 +42,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Layla20\n")); - snd_assert((subdevice_id & 0xfff0) == LAYLA20, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -155,7 +156,8 @@ static int load_asic(struct echoaudio *chip) static int set_sample_rate(struct echoaudio *chip, u32 rate) { - snd_assert(rate >= 8000 && rate <= 50000, return -EINVAL); + if (snd_BUG_ON(rate < 8000 || rate > 50000)) + return -EINVAL; /* Only set the clock for internal mode. Do not return failure, simply treat it as a non-event. */ @@ -252,7 +254,8 @@ static int set_output_clock(struct echoaudio *chip, u16 clock) /* Set input bus gain (one unit is 0.5dB !) */ static int set_input_gain(struct echoaudio *chip, u16 input, int gain) { - snd_assert(input < num_busses_in(chip), return -EINVAL); + if (snd_BUG_ON(input >= num_busses_in(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c index 97e42e11514..d61b5cbccca 100644 --- a/sound/pci/echoaudio/layla24_dsp.c +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -42,7 +42,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Layla24\n")); - snd_assert((subdevice_id & 0xfff0) == LAYLA24, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -73,7 +74,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) return err; err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); + if (err < 0) + return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); @@ -158,8 +160,9 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) { u32 control_reg, clock, base_rate; - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); + if (snd_BUG_ON(rate >= 50000 && + chip->digital_mode == DIGITAL_MODE_ADAT)) + return -EINVAL; /* Only set the clock for internal mode. */ if (chip->input_clock != ECHO_CLOCK_INTERNAL) { diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c index 891c7051909..227386602f9 100644 --- a/sound/pci/echoaudio/mia_dsp.c +++ b/sound/pci/echoaudio/mia_dsp.c @@ -42,7 +42,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Mia\n")); - snd_assert((subdevice_id & 0xfff0) == MIA, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -161,8 +162,9 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) static int set_input_clock(struct echoaudio *chip, u16 clock) { DE_ACT(("set_input_clock(%d)\n", clock)); - snd_assert(clock == ECHO_CLOCK_INTERNAL || clock == ECHO_CLOCK_SPDIF, - return -EINVAL); + if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL && + clock != ECHO_CLOCK_SPDIF)) + return -EINVAL; chip->input_clock = clock; return set_sample_rate(chip, chip->sample_rate); @@ -176,8 +178,9 @@ static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, { int index; - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); + if (snd_BUG_ON(pipe >= num_pipes_out(chip) || + output >= num_busses_out(chip))) + return -EINVAL; if (wait_handshake(chip)) return -EIO; diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index 91f5bff66d3..77bf2a83d99 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c @@ -59,7 +59,8 @@ static int enable_midi_input(struct echoaudio *chip, char enable) Returns how many actually written or < 0 on error */ static int write_midi(struct echoaudio *chip, u8 *data, int bytes) { - snd_assert(bytes > 0 && bytes < MIDI_OUT_BUFFER_SIZE, return -EINVAL); + if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE)) + return -EINVAL; if (wait_handshake(chip)) return -EIO; @@ -119,7 +120,8 @@ static int midi_service_irq(struct echoaudio *chip) /* The count is at index 0, followed by actual data */ count = le16_to_cpu(chip->comm_page->midi_input[0]); - snd_assert(count < MIDI_IN_BUFFER_SIZE, return 0); + if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE)) + return 0; /* Get the MIDI data from the comm page */ i = 1; diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c index c0b4bf0be7d..eaa619bd2a0 100644 --- a/sound/pci/echoaudio/mona_dsp.c +++ b/sound/pci/echoaudio/mona_dsp.c @@ -43,7 +43,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) int err; DE_INIT(("init_hw() - Mona\n")); - snd_assert((subdevice_id & 0xfff0) == MONA, return -ENODEV); + if (snd_BUG_ON((subdevice_id & 0xfff0) != MONA)) + return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); @@ -79,7 +80,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) return err; err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); + if (err < 0) + return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 45088ebcce5..0e649dcdbf6 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -145,7 +145,8 @@ terminate_voice(struct snd_emux_voice *vp) { struct snd_emu10k1 *hw; - snd_assert(vp, return); + if (snd_BUG_ON(!vp)) + return; hw = vp->hw; snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); if (vp->block) { @@ -325,7 +326,8 @@ start_voice(struct snd_emux_voice *vp) hw = vp->hw; ch = vp->ch; - snd_assert(ch >= 0, return -EINVAL); + if (snd_BUG_ON(ch < 0)) + return -EINVAL; chan = vp->chan; emem = (struct snd_emu10k1_memblk *)vp->block; diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c index 42bae6f7e9a..e10f027bde0 100644 --- a/sound/pci/emu10k1/emu10k1_patch.c +++ b/sound/pci/emu10k1/emu10k1_patch.c @@ -46,8 +46,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, struct snd_emu10k1 *emu; emu = rec->hw; - snd_assert(sp != NULL, return -EINVAL); - snd_assert(hdr != NULL, return -EINVAL); + if (snd_BUG_ON(!sp || !hdr)) + return -EINVAL; if (sp->v.size == 0) { snd_printd("emu: rom font for sample %d\n", sp->v.sample); @@ -104,7 +104,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, size = BLANK_HEAD_SIZE; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; - snd_assert(offset + size <= blocksize, return -EINVAL); + if (offset + size > blocksize) + return -EINVAL; snd_emu10k1_synth_bzero(emu, sp->block, offset, size); offset += size; @@ -112,7 +113,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, size = loopend; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; - snd_assert(offset + size <= blocksize, return -EINVAL); + if (offset + size > blocksize) + return -EINVAL; if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { snd_emu10k1_synth_free(emu, sp->block); sp->block = NULL; @@ -129,12 +131,14 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, int woffset; unsigned short *wblock = (unsigned short*)block; woffset = offset / 2; - snd_assert(offset + loopsize*2 <= blocksize, return -EINVAL); + if (offset + loopsize * 2 > blocksize) + return -EINVAL; for (i = 0; i < loopsize; i++) wblock[woffset + i] = wblock[woffset - i -1]; offset += loopsize * 2; } else { - snd_assert(offset + loopsize <= blocksize, return -EINVAL); + if (offset + loopsize > blocksize) + return -EINVAL; for (i = 0; i < loopsize; i++) block[offset + i] = block[offset - i -1]; offset += loopsize; @@ -154,7 +158,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, /* loopend -> sample end */ size = sp->v.size - loopend; - snd_assert(size >= 0, return -EINVAL); + if (size < 0) + return -EINVAL; if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) size *= 2; if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { @@ -212,8 +217,8 @@ snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, struct snd_emu10k1 *emu; emu = rec->hw; - snd_assert(sp != NULL, return -EINVAL); - snd_assert(hdr != NULL, return -EINVAL); + if (snd_BUG_ON(!sp || !hdr)) + return -EINVAL; if (sp->block) { snd_emu10k1_synth_free(emu, sp->block); diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 491a4a50f86..5ff4dbb62da 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1319,7 +1319,8 @@ static int snd_emu10k1x_midi_input_open(struct snd_rawmidi_substream *substream) unsigned long flags; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= EMU10K1X_MIDI_MODE_INPUT; midi->substream_input = substream; @@ -1345,7 +1346,8 @@ static int snd_emu10k1x_midi_output_open(struct snd_rawmidi_substream *substream unsigned long flags; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= EMU10K1X_MIDI_MODE_OUTPUT; midi->substream_output = substream; @@ -1372,7 +1374,8 @@ static int snd_emu10k1x_midi_input_close(struct snd_rawmidi_substream *substream int err = 0; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); snd_emu10k1x_intr_disable(emu, midi->rx_enable); midi->midi_mode &= ~EMU10K1X_MIDI_MODE_INPUT; @@ -1394,7 +1397,8 @@ static int snd_emu10k1x_midi_output_close(struct snd_rawmidi_substream *substrea int err = 0; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); snd_emu10k1x_intr_disable(emu, midi->tx_enable); midi->midi_mode &= ~EMU10K1X_MIDI_MODE_OUTPUT; @@ -1413,7 +1417,8 @@ static void snd_emu10k1x_midi_input_trigger(struct snd_rawmidi_substream *substr struct emu10k1x *emu; struct emu10k1x_midi *midi = substream->rmidi->private_data; emu = midi->emu; - snd_assert(emu, return); + if (snd_BUG_ON(!emu)) + return; if (up) snd_emu10k1x_intr_enable(emu, midi->rx_enable); @@ -1428,7 +1433,8 @@ static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *subst unsigned long flags; emu = midi->emu; - snd_assert(emu, return); + if (snd_BUG_ON(!emu)) + return; if (up) { int max = 4; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 71dc4c8865b..7dba08f0ab8 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -487,7 +487,8 @@ static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode, u32 op, u32 r, u32 a, u32 x, u32 y) { u_int32_t *code; - snd_assert(*ptr < 512, return); + if (snd_BUG_ON(*ptr >= 512)) + return; code = (u_int32_t __force *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff); @@ -503,7 +504,8 @@ static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode, u32 op, u32 r, u32 a, u32 x, u32 y) { u_int32_t *code; - snd_assert(*ptr < 1024, return); + if (snd_BUG_ON(*ptr >= 1024)) + return; code = (u_int32_t __force *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff); diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index c4d76d16661..8578c70c61f 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -157,7 +157,8 @@ static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) unsigned long flags; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; midi->substream_input = substream; @@ -183,7 +184,8 @@ static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) unsigned long flags; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; midi->substream_output = substream; @@ -210,7 +212,8 @@ static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) int err = 0; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); snd_emu10k1_intr_disable(emu, midi->rx_enable); midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; @@ -232,7 +235,8 @@ static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream int err = 0; emu = midi->emu; - snd_assert(emu, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); snd_emu10k1_intr_disable(emu, midi->tx_enable); midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; @@ -251,7 +255,8 @@ static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substre struct snd_emu10k1 *emu; struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; emu = midi->emu; - snd_assert(emu, return); + if (snd_BUG_ON(!emu)) + return; if (up) snd_emu10k1_intr_enable(emu, midi->rx_enable); @@ -266,7 +271,8 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr unsigned long flags; emu = midi->emu; - snd_assert(emu, return); + if (snd_BUG_ON(!emu)) + return; if (up) { int max = 4; diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 7d379f5131f..e8ad56ed34f 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -107,7 +107,8 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis list_for_each (pos, &emu->mapped_link_head) { struct snd_emu10k1_memblk *blk = get_emu10k1_memblk(pos, mapped_link); - snd_assert(blk->mapped_page >= 0, continue); + if (blk->mapped_page < 0) + continue; size = blk->mapped_page - page; if (size == npages) { *nextp = pos; @@ -300,10 +301,14 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst struct snd_emu10k1_memblk *blk; int page, err, idx; - snd_assert(emu, return NULL); - snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes < MAXPAGES * EMUPAGESIZE, return NULL); + if (snd_BUG_ON(!emu)) + return NULL; + if (snd_BUG_ON(runtime->dma_bytes <= 0 || + runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) + return NULL; hdr = emu->memhdr; - snd_assert(hdr, return NULL); + if (snd_BUG_ON(!hdr)) + return NULL; mutex_lock(&hdr->block_mutex); blk = search_empty(emu, runtime->dma_bytes); @@ -353,7 +358,8 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst */ int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk) { - snd_assert(emu && blk, return -EINVAL); + if (snd_BUG_ON(!emu || !blk)) + return -EINVAL; return snd_emu10k1_synth_free(emu, blk); } @@ -498,7 +504,8 @@ static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk * static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset) { char *ptr; - snd_assert(page >= 0 && page < emu->max_cache_pages, return NULL); + if (snd_BUG_ON(page < 0 || page >= emu->max_cache_pages)) + return NULL; ptr = emu->page_ptr_table[page]; if (! ptr) { printk(KERN_ERR "emu10k1: access to NULL ptr: page = %d\n", page); diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 958cb2a65a4..d7300a1aa26 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -111,8 +111,10 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number, unsigned long flags; int result; - snd_assert(rvoice != NULL, return -EINVAL); - snd_assert(number, return -EINVAL); + if (snd_BUG_ON(!rvoice)) + return -EINVAL; + if (snd_BUG_ON(!number)) + return -EINVAL; spin_lock_irqsave(&emu->voice_lock, flags); for (;;) { @@ -145,7 +147,8 @@ int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, { unsigned long flags; - snd_assert(pvoice != NULL, return -EINVAL); + if (snd_BUG_ON(!pvoice)) + return -EINVAL; spin_lock_irqsave(&emu->voice_lock, flags); pvoice->interrupt = NULL; pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 84fac1fbf10..4cd9a1faaec 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -860,7 +860,8 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, struct es1938 *chip = snd_pcm_substream_chip(substream); pos <<= chip->dma1_shift; count <<= chip->dma1_shift; - snd_assert(pos + count <= chip->dma1_size, return -EINVAL); + if (snd_BUG_ON(pos + count > chip->dma1_size)) + return -EINVAL; if (pos + count < chip->dma1_size) { if (copy_to_user(dst, runtime->dma_area + pos + 1, count)) return -EFAULT; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 1bf298d214b..20ee7599600 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -692,7 +692,8 @@ static void apu_data_set(struct es1968 *chip, u16 data) /* no spinlock */ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) { - snd_assert(channel < NR_APUS, return); + if (snd_BUG_ON(channel >= NR_APUS)) + return; #ifdef CONFIG_PM chip->apu_map[channel][reg] = data; #endif @@ -711,7 +712,8 @@ static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) { - snd_assert(channel < NR_APUS, return 0); + if (snd_BUG_ON(channel >= NR_APUS)) + return 0; reg |= (channel << 4); apu_index_set(chip, reg); return __maestro_read(chip, IDR0_DATA_PORT); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d2e1093f8e9..77fbcd4a69b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -211,7 +211,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, unsigned int shift, num_elems, mask; hda_nid_t prev_nid; - snd_assert(conn_list && max_conns > 0, return -EINVAL); + if (snd_BUG_ON(!conn_list || max_conns <= 0)) + return -EINVAL; parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); if (parm & AC_CLIST_LONG) { @@ -407,8 +408,10 @@ int __devinit snd_hda_bus_new(struct snd_card *card, .dev_free = snd_hda_bus_dev_free, }; - snd_assert(temp, return -EINVAL); - snd_assert(temp->ops.command && temp->ops.get_response, return -EINVAL); + if (snd_BUG_ON(!temp)) + return -EINVAL; + if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response)) + return -EINVAL; if (busp) *busp = NULL; @@ -588,8 +591,10 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, char component[13]; int err; - snd_assert(bus, return -EINVAL); - snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); + if (snd_BUG_ON(!bus)) + return -EINVAL; + if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) + return -EINVAL; if (bus->caddr_tbl[codec_addr]) { snd_printk(KERN_ERR "hda_codec: " @@ -2236,11 +2241,13 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, if (info->ops.close == NULL) info->ops.close = hda_pcm_default_open_close; if (info->ops.prepare == NULL) { - snd_assert(info->nid, return -EINVAL); + if (snd_BUG_ON(!info->nid)) + return -EINVAL; info->ops.prepare = hda_pcm_default_prepare; } if (info->ops.cleanup == NULL) { - snd_assert(info->nid, return -EINVAL); + if (snd_BUG_ON(!info->nid)) + return -EINVAL; info->ops.cleanup = hda_pcm_default_cleanup; } return 0; diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 59e4389c94a..0ca30894f7c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -174,7 +174,8 @@ static int build_afg_tree(struct hda_codec *codec) int i, nodes, err; hda_nid_t nid; - snd_assert(spec, return -EINVAL); + if (snd_BUG_ON(!spec)) + return -EINVAL; spec->def_amp_out_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_OUT_CAP); spec->def_amp_in_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_IN_CAP); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1c53e337ecb..b2bcd94cf7a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1646,7 +1646,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) return 0; - snd_assert(cpcm->name, return -EINVAL); + if (snd_BUG_ON(!cpcm->name)) + return -EINVAL; err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, cpcm->stream[0].substreams, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4bd26725355..7e5422f64ca 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2633,12 +2633,14 @@ static int alc_build_pcms(struct hda_codec *codec) info->name = spec->stream_name_analog; if (spec->stream_analog_playback) { - snd_assert(spec->multiout.dac_nids, return -EINVAL); + if (snd_BUG_ON(!spec->multiout.dac_nids)) + return -EINVAL; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; } if (spec->stream_analog_capture) { - snd_assert(spec->adc_nids, return -EINVAL); + if (snd_BUG_ON(!spec->adc_nids)) + return -EINVAL; info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; } diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index dab31b2756a..03391da8c8c 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c @@ -59,7 +59,8 @@ static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip, struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; struct snd_ice1712 *ice = ak->private_data[0]; - snd_assert(chip >= 0 && chip < 4, return); + if (snd_BUG_ON(chip < 0 || chip >= 4)) + return; tmp = snd_ice1712_gpio_read(ice); tmp |= priv->add_flags; diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 013fc4f0482..6fe35b81204 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -149,7 +149,8 @@ static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mas struct ews_spec *spec = ice->spec; unsigned char data, ndata; - snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL); + if (snd_BUG_ON(chip_mask < 0 || chip_mask > 0x0f)) + return -EINVAL; snd_i2c_lock(ice->i2c); if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) goto __error; @@ -685,7 +686,8 @@ static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, st int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned char data; - snd_assert(channel >= 0 && channel <= 7, return 0); + if (snd_BUG_ON(channel < 0 || channel > 7)) + return 0; snd_i2c_lock(ice->i2c); if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { snd_i2c_unlock(ice->i2c); @@ -705,7 +707,8 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned char data, ndata; - snd_assert(channel >= 0 && channel <= 7, return 0); + if (snd_BUG_ON(channel < 0 || channel > 7)) + return 0; snd_i2c_lock(ice->i2c); if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { snd_i2c_unlock(ice->i2c); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 29d449d73c9..05ffab65d16 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2416,7 +2416,8 @@ int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice) int err; struct snd_kcontrol *kctl; - snd_assert(ice->pcm_pro != NULL, return -EIO); + if (snd_BUG_ON(!ice->pcm_pro)) + return -EIO; err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice)); if (err < 0) return err; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index e596d777d9d..60119d220a6 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2250,7 +2250,8 @@ static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice) int err; struct snd_kcontrol *kctl; - snd_assert(ice->pcm != NULL, return -EIO); + if (snd_BUG_ON(!ice->pcm)) + return -EIO; err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice)); if (err < 0) diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index b4e0c16852a..21ff4de890b 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -208,7 +208,8 @@ static void juli_akm_write(struct snd_akm4xxx *ak, int chip, { struct snd_ice1712 *ice = ak->private_data[0]; - snd_assert(chip == 0, return); + if (snd_BUG_ON(chip)) + return; snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 048d99e25ab..78760996632 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2132,8 +2132,8 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, snd_intel8x0_codec_read_test(chip, codecs); chip->ac97_sdin[codecs] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; - snd_assert(chip->ac97_sdin[codecs] < 3, - chip->ac97_sdin[codecs] = 0); + if (snd_BUG_ON(chip->ac97_sdin[codecs] >= 3)) + chip->ac97_sdin[codecs] = 0; } else chip->ac97_sdin[codecs] = i; codecs++; diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index faf674e671a..93449e46456 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -306,7 +306,8 @@ static unsigned int get_ich_codec_bit(struct intel8x0m *chip, unsigned int codec static unsigned int codec_bit[3] = { ICH_PCR, ICH_SCR, ICH_TCR }; - snd_assert(codec < 3, return ICH_PCR); + if (snd_BUG_ON(codec >= 3)) + return ICH_PCR; return codec_bit[codec]; } diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 4a44c0f20f7..5f8006b4275 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1281,7 +1281,8 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", pos, offset, size, count); - snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL); + if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) + return -EINVAL; for (i=0; i < count; i++) { #if K1212_DEBUG_LEVEL > 0 @@ -1306,7 +1307,8 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", pos, offset, size); - snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL); + if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) + return -EINVAL; for (i=0; i < count; i++) { #if K1212_DEBUG_LEVEL > 0 @@ -1336,7 +1338,8 @@ static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *sr K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", pos, offset, size, count); - snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL); + if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) + return -EINVAL; for (i=0; i < count; i++) { #if K1212_DEBUG_LEVEL > 0 diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 0037be74fde..9ff3f9e3440 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1175,7 +1175,8 @@ snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) struct m3_dma *s = subs->runtime->private_data; int err = -EINVAL; - snd_assert(s != NULL, return -ENXIO); + if (snd_BUG_ON(!s)) + return -ENXIO; spin_lock(&chip->reg_lock); switch (cmd) { @@ -1487,7 +1488,8 @@ snd_m3_pcm_prepare(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; struct m3_dma *s = runtime->private_data; - snd_assert(s != NULL, return -ENXIO); + if (snd_BUG_ON(!s)) + return -ENXIO; if (runtime->format != SNDRV_PCM_FORMAT_U8 && runtime->format != SNDRV_PCM_FORMAT_S16_LE) @@ -1546,7 +1548,9 @@ snd_m3_pcm_pointer(struct snd_pcm_substream *subs) struct snd_m3 *chip = snd_pcm_substream_chip(subs); unsigned int ptr; struct m3_dma *s = subs->runtime->private_data; - snd_assert(s != NULL, return 0); + + if (snd_BUG_ON(!s)) + return 0; spin_lock(&chip->reg_lock); ptr = snd_m3_get_pointer(chip, s, subs); diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 3dd0c796327..2d0dce649a6 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -708,7 +708,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) pcm_number = MIXART_PCM_ANALOG; runtime->hw = snd_mixart_analog_caps; } else { - snd_assert ( pcm == chip->pcm_dig ); + snd_BUG_ON(pcm != chip->pcm_dig); pcm_number = MIXART_PCM_DIGITAL; runtime->hw = snd_mixart_digital_caps; } @@ -783,7 +783,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) pcm_number = MIXART_PCM_ANALOG; runtime->hw = snd_mixart_analog_caps; } else { - snd_assert ( pcm == chip->pcm_dig ); + snd_BUG_ON(pcm != chip->pcm_dig); pcm_number = MIXART_PCM_DIGITAL; runtime->hw = snd_mixart_digital_caps; } diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 785085e4835..b9a06c27939 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -56,8 +56,10 @@ static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame) if (tailptr == headptr) return 0; /* no message posted */ - snd_assert( tailptr >= MSG_OUTBOUND_POST_STACK, return 0); /* error */ - snd_assert( tailptr < (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE), return 0); /* error */ + if (tailptr < MSG_OUTBOUND_POST_STACK) + return 0; /* error */ + if (tailptr >= MSG_OUTBOUND_POST_STACK + MSG_BOUND_STACK_SIZE) + return 0; /* error */ *msg_frame = readl_be(MIXART_MEM(mgr, tailptr)); @@ -149,7 +151,8 @@ static int send_msg( struct mixart_mgr *mgr, u32 msg_frame_address; int err, i; - snd_assert(msg->size % 4 == 0, return -EINVAL); + if (snd_BUG_ON(msg->size % 4)) + return -EINVAL; err = 0; @@ -289,9 +292,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, wait_queue_t wait; long timeout; - snd_assert(notif_event != 0, return -EINVAL); - snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL); - snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL); + if (snd_BUG_ON(!notif_event)) + return -EINVAL; + if (snd_BUG_ON((notif_event & MSG_TYPE_MASK) != MSG_TYPE_NOTIFY)) + return -EINVAL; + if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK)) + return -EINVAL; mutex_lock(&mgr->msg_mutex); diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index f9860314613..3782b52bc0e 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -288,7 +288,9 @@ static int mixart_enum_physio(struct mixart_mgr *mgr) return -EINVAL; } - snd_assert(phys_io.nb_uid >= (MIXART_MAX_CARDS * 2), return -EINVAL); /* min 2 phys io per card (analog in + analog out) */ + /* min 2 phys io per card (analog in + analog out) */ + if (phys_io.nb_uid < MIXART_MAX_CARDS * 2) + return -EINVAL; for(k=0; knum_cards; k++) { mgr->chip[k]->uid_in_analog_physio = phys_io.uid[k]; @@ -363,8 +365,10 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw } /* check xilinx validity */ - snd_assert(((u32*)(dsp->data))[0]==0xFFFFFFFF, return -EINVAL); - snd_assert(dsp->size % 4 == 0, return -EINVAL); + if (((u32*)(dsp->data))[0] == 0xffffffff) + return -EINVAL; + if (dsp->size % 4) + return -EINVAL; /* set xilinx status to copying */ writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); @@ -462,8 +466,10 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw } /* check daughterboard xilinx validity */ - snd_assert(((u32*)(dsp->data))[0]==0xFFFFFFFF, return -EINVAL); - snd_assert(dsp->size % 4 == 0, return -EINVAL); + if (((u32*)(dsp->data))[0] == 0xffffffff) + return -EINVAL; + if (dsp->size % 4) + return -EINVAL; /* inform mixart about the size of the file */ writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_SIZE_OFFSET )); @@ -480,7 +486,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* get the address where to write the file */ val = readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET )); - snd_assert(val != 0, return -EINVAL); + if (!val) + return -EINVAL; /* copy daughterboard xilinx code */ memcpy_toio( MIXART_MEM( mgr, val), dsp->data, dsp->size); diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 6fdda1f70b2..3ba6174c3df 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -837,7 +837,7 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ } else { - snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); + snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); if(is_aes) stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */ else stored_volume = chip->digital_playback_volume[idx]; /* analog playback */ } @@ -863,7 +863,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem else /* analog capture */ stored_volume = chip->digital_capture_volume[0]; } else { - snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); + snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); if (is_aes) /* AES playback */ stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; else /* analog playback */ @@ -909,7 +909,7 @@ static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); + snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); mutex_lock(&chip->mgr->mixer_mutex); if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ idx += MIXART_PLAYBACK_STREAMS; @@ -926,7 +926,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; - snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); + snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); mutex_lock(&chip->mgr->mixer_mutex); j = idx; if (is_aes) diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 06d13e71711..50c9f8a0508 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -562,7 +562,8 @@ snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) struct nm256_stream *s = substream->runtime->private_data; int err = 0; - snd_assert(s != NULL, return -ENXIO); + if (snd_BUG_ON(!s)) + return -ENXIO; spin_lock(&chip->reg_lock); switch (cmd) { @@ -599,7 +600,8 @@ snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd) struct nm256_stream *s = substream->runtime->private_data; int err = 0; - snd_assert(s != NULL, return -ENXIO); + if (snd_BUG_ON(!s)) + return -ENXIO; spin_lock(&chip->reg_lock); switch (cmd) { @@ -635,7 +637,8 @@ static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; - snd_assert(s, return -ENXIO); + if (snd_BUG_ON(!s)) + return -ENXIO; s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size); s->period_size = frames_to_bytes(runtime, substream->runtime->period_size); s->periods = substream->runtime->periods; @@ -660,7 +663,8 @@ snd_nm256_playback_pointer(struct snd_pcm_substream *substream) struct nm256_stream *s = substream->runtime->private_data; unsigned long curp; - snd_assert(s, return 0); + if (snd_BUG_ON(!s)) + return 0; curp = snd_nm256_readl(chip, NM_PBUFFER_CURRP) - (unsigned long)s->buf; curp %= s->dma_size; return bytes_to_frames(substream->runtime, curp); @@ -673,7 +677,8 @@ snd_nm256_capture_pointer(struct snd_pcm_substream *substream) struct nm256_stream *s = substream->runtime->private_data; unsigned long curp; - snd_assert(s != NULL, return 0); + if (snd_BUG_ON(!s)) + return 0; curp = snd_nm256_readl(chip, NM_RBUFFER_CURRP) - (unsigned long)s->buf; curp %= s->dma_size; return bytes_to_frames(substream->runtime, curp); diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 2c7e2533679..0e06c6c9fcc 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -464,7 +464,8 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream) pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS); pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0); - snd_assert(subs->runtime->dma_bytes < 0x200000); /* max buffer size is 2 MByte */ + /* max buffer size is 2 MByte */ + snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000); rmh.cmd[1] = subs->runtime->dma_bytes * 8; /* size in bits */ rmh.cmd[2] = subs->runtime->dma_addr >> 24; /* most significant byte */ rmh.cmd[2] |= 1<<19; /* this is a circular buffer */ @@ -1228,7 +1229,8 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id return -ENOMEM; } - snd_assert(pci_id->driver_data < PCI_ID_LAST, return -ENODEV); + if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) + return -ENODEV; card_name = pcxhr_board_params[pci_id->driver_data].board_name; mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips; mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips; diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 000e6fed6e3..7143259cfe3 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -319,16 +319,20 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) const unsigned char *data; unsigned char dummy; /* check the length of boot image */ - snd_assert(dsp->size > 0, return -EINVAL); - snd_assert(dsp->size % 3 == 0, return -EINVAL); - snd_assert(dsp->data, return -EINVAL); + if (dsp->size <= 0) + return -EINVAL; + if (dsp->size % 3) + return -EINVAL; + if (snd_BUG_ON(!dsp->data)) + return -EINVAL; /* transfert data buffer from PC to DSP */ for (i = 0; i < dsp->size; i += 3) { data = dsp->data + i; if (i == 0) { /* test data header consistency */ len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]); - snd_assert((len==0) || (dsp->size == (len+2)*3), return -EINVAL); + if (len && dsp->size != (len + 2) * 3) + return -EINVAL; } /* wait DSP ready for new transfer */ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, @@ -389,7 +393,8 @@ int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot) unsigned char dummy; /* send the hostport address to the DSP (only the upper 24 bit !) */ - snd_assert((physaddr & 0xff) == 0, return -EINVAL); + if (snd_BUG_ON(physaddr & 0xff)) + return -EINVAL; PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX1, (physaddr >> 8)); err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_BOOT, 0); @@ -570,7 +575,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) u32 data; unsigned char reg; - snd_assert(rmh->cmd_lencmd_len >= PCXHR_SIZE_MAX_CMD)) + return -EINVAL; err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); if (err) { snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n"); @@ -677,7 +683,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) */ void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd) { - snd_assert(cmd < CMD_LAST_INDEX, return); + if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) + return; rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode; rmh->cmd_len = 1; rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length; @@ -690,17 +697,17 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, unsigned int param1, unsigned int param2, unsigned int param3) { - snd_assert(param1 <= MASK_FIRST_FIELD); + snd_BUG_ON(param1 > MASK_FIRST_FIELD); if (capture) rmh->cmd[0] |= 0x800; /* COMMAND_RECORD_MASK */ if (param1) rmh->cmd[0] |= (param1 << FIELD_SIZE); if (param2) { - snd_assert(param2 <= MASK_FIRST_FIELD); + snd_BUG_ON(param2 > MASK_FIRST_FIELD); rmh->cmd[0] |= param2; } if(param3) { - snd_assert(param3 <= MASK_DSP_WORD); + snd_BUG_ON(param3 > MASK_DSP_WORD); rmh->cmd[1] = param3; rmh->cmd_len = 2; } diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index d2f043278cf..96640d9c227 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -65,15 +65,18 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr) if (err) return err; /* test 8 or 12 phys out */ - snd_assert((rmh.stat[0] & MASK_FIRST_FIELD) == mgr->playback_chips*2, - return -EINVAL); + if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2) + return -EINVAL; /* test 8 or 2 phys in */ - snd_assert(((rmh.stat[0] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD) == - mgr->capture_chips * 2, return -EINVAL); + if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) != + mgr->capture_chips * 2) + return -EINVAL; /* test max nb substream per board */ - snd_assert((rmh.stat[1] & 0x5F) >= card_streams, return -EINVAL); + if ((rmh.stat[1] & 0x5F) < card_streams) + return -EINVAL; /* test max nb substream per pipe */ - snd_assert(((rmh.stat[1]>>7)&0x5F) >= PCXHR_PLAYBACK_STREAMS, return -EINVAL); + if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS) + return -EINVAL; pcxhr_init_rmh(&rmh, CMD_VERSION); /* firmware num for DSP */ diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 6a359624734..124f9a2f153 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -865,7 +865,8 @@ static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, struct riptideport *hwport; struct cmdport *cmdport = NULL; - snd_assert(cif, return -EINVAL); + if (snd_BUG_ON(!cif)) + return -EINVAL; hwport = cif->hwport; if (cif->errcnt > MAX_ERROR_COUNT) { @@ -1490,7 +1491,8 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream) int err = 0; snd_pcm_format_t format; - snd_assert(cif && data, return -EINVAL); + if (snd_BUG_ON(!cif || !data)) + return -EINVAL; snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id, runtime->channels, runtime->format, runtime->rate); @@ -1772,7 +1774,8 @@ snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg, union cmdret rptr = CMDRET_ZERO; int i = 0; - snd_assert(cif, return); + if (snd_BUG_ON(!cif)) + return; snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val); do { @@ -1790,7 +1793,8 @@ static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97, struct cmdif *cif = chip->cif; union cmdret rptr = CMDRET_ZERO; - snd_assert(cif, return 0); + if (snd_BUG_ON(!cif)) + return 0; if (SEND_RACR(cif, reg, &rptr) != 0) SEND_RACR(cif, reg, &rptr); @@ -1804,7 +1808,8 @@ static int snd_riptide_initialize(struct snd_riptide *chip) unsigned int device_id; int err; - snd_assert(chip, return -EINVAL); + if (snd_BUG_ON(!chip)) + return -EINVAL; cif = chip->cif; if (!cif) { @@ -1836,7 +1841,8 @@ static int snd_riptide_free(struct snd_riptide *chip) { struct cmdif *cif; - snd_assert(chip, return 0); + if (!chip) + return 0; if ((cif = chip->cif)) { SET_GRESET(cif->hwport); diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 4d6fbb36ab8..d723543bead 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -1036,7 +1036,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) n = DDS_NUMERATOR; div64_32(&n, rate, &r); /* n should be less than 2^32 for being written to FREQ register */ - snd_assert((n >> 32) == 0); + snd_BUG_ON(n >> 32); /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS value to write it after a reset */ hdsp->dds_value = n; @@ -3043,7 +3043,7 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); offset = ucontrol->id.index - 1; - snd_assert(offset >= 0); + snd_BUG_ON(offset < 0); switch (hdsp->io_type) { case Digiface: @@ -3767,7 +3767,8 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, { int mapped_channel; - snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL); + if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) + return NULL; if ((mapped_channel = hdsp->channel_map[channel]) < 0) return NULL; @@ -3784,10 +3785,12 @@ static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int chann struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_from_user(channel_buf + pos * 4, src, count * 4)) return -EFAULT; return count; @@ -3799,10 +3802,12 @@ static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channe struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) return -EFAULT; return count; @@ -3815,7 +3820,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, char *channel_buf; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; memset(channel_buf + pos * 4, 0, count * 4); return count; } @@ -3927,7 +3933,8 @@ static int snd_hdsp_channel_info(struct snd_pcm_substream *substream, struct hdsp *hdsp = snd_pcm_substream_chip(substream); int mapped_channel; - snd_assert(info->channel < hdsp->max_channels, return -EINVAL); + if (snd_BUG_ON(info->channel >= hdsp->max_channels)) + return -EINVAL; if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) return -EINVAL; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index ab423bc8234..83c92e6082a 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -845,7 +845,7 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) n = 110100480000000ULL; /* Value checked for AES32 and MADI */ div64_32(&n, rate, &r); /* n should be less than 2^32 for being written to FREQ register */ - snd_assert((n >> 32) == 0); + snd_BUG_ON(n >> 32); hdspm_write(hdspm, HDSPM_freqReg, (u32)n); } @@ -2617,8 +2617,8 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, channel = ucontrol->id.index - 1; - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return -EINVAL); + if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) + return -EINVAL; mapped_channel = hdspm->channel_map[channel]; if (mapped_channel < 0) @@ -2652,8 +2652,8 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, channel = ucontrol->id.index - 1; - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return -EINVAL); + if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) + return -EINVAL; mapped_channel = hdspm->channel_map[channel]; if (mapped_channel < 0) @@ -3496,8 +3496,8 @@ static char *hdspm_channel_buffer_location(struct hdspm * hdspm, { int mapped_channel; - snd_assert(channel >= 0 - || channel < HDSPM_MAX_CHANNELS, return NULL); + if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) + return NULL; mapped_channel = hdspm->channel_map[channel]; if (mapped_channel < 0) @@ -3520,14 +3520,15 @@ static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream, struct hdspm *hdspm = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, - return -EINVAL); + if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdspm_channel_buffer_location(hdspm, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; return copy_from_user(channel_buf + pos * 4, src, count * 4); } @@ -3539,13 +3540,14 @@ static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream, struct hdspm *hdspm = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, - return -EINVAL); + if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdspm_channel_buffer_location(hdspm, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; return copy_to_user(dst, channel_buf + pos * 4, count * 4); } @@ -3559,7 +3561,8 @@ static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream, channel_buf = hdspm_channel_buffer_location(hdspm, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; memset(channel_buf + pos * 4, 0, count * 4); return 0; } @@ -3744,7 +3747,8 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, struct hdspm *hdspm = snd_pcm_substream_chip(substream); int mapped_channel; - snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); + if (snd_BUG_ON(info->channel >= HDSPM_MAX_CHANNELS)) + return -EINVAL; mapped_channel = hdspm->channel_map[info->channel]; if (mapped_channel < 0) diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index a123f0e6ba2..2570907134d 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -595,8 +595,6 @@ static void rme9652_set_thru(struct snd_rme9652 *rme9652, int channel, int enabl } else { int mapped_channel; - snd_assert(channel == RME9652_NCHANNELS, return); - mapped_channel = rme9652->channel_map[channel]; if (enable) { @@ -1893,7 +1891,8 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, { int mapped_channel; - snd_assert(channel >= 0 || channel < RME9652_NCHANNELS, return NULL); + if (snd_BUG_ON(channel < 0 || channel >= RME9652_NCHANNELS)) + return NULL; if ((mapped_channel = rme9652->channel_map[channel]) < 0) { return NULL; @@ -1914,12 +1913,14 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int ch struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = rme9652_channel_buffer_location (rme9652, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_from_user(channel_buf + pos * 4, src, count * 4)) return -EFAULT; return count; @@ -1931,12 +1932,14 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int cha struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = rme9652_channel_buffer_location (rme9652, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) return -EFAULT; return count; @@ -1951,7 +1954,8 @@ static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int chann channel_buf = rme9652_channel_buffer_location (rme9652, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; memset(channel_buf + pos * 4, 0, count * 4); return count; } @@ -2053,7 +2057,8 @@ static int snd_rme9652_channel_info(struct snd_pcm_substream *substream, struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); int chn; - snd_assert(info->channel < RME9652_NCHANNELS, return -EINVAL); + if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS)) + return -EINVAL; if ((chn = rme9652->channel_map[info->channel]) < 0) { return -EINVAL; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 0d3d305b0a0..cd408b86c83 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -534,8 +534,8 @@ static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *param params->rate_den = 1; } else { snd_sonicvibes_pll(rate, &r, &m, &n); - snd_assert((SV_REFFREQUENCY % 16) == 0, return -EINVAL); - snd_assert((SV_ADCMULT % 512) == 0, return -EINVAL); + snd_BUG_ON(SV_REFFREQUENCY % 16); + snd_BUG_ON(SV_ADCMULT % 512); params->rate_num = (SV_REFFREQUENCY/16) * (n+2) * r; params->rate_den = (SV_ADCMULT/512) * (m+2); } @@ -849,7 +849,8 @@ static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, s if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0) return err; - snd_assert(pcm != NULL, return -EINVAL); + if (snd_BUG_ON(!pcm)) + return -EINVAL; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sonicvibes_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops); @@ -1089,7 +1090,8 @@ static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic) unsigned int idx; int err; - snd_assert(sonic != NULL && sonic->card != NULL, return -EINVAL); + if (snd_BUG_ON(!sonic || !sonic->card)) + return -EINVAL; card = sonic->card; strcpy(card->mixername, "S3 SonicVibes"); diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index a69b4206c69..c612b435ca2 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2931,7 +2931,8 @@ static int snd_trident_pcm_mixer_build(struct snd_trident *trident, { struct snd_trident_pcm_mixer *tmix; - snd_assert(trident != NULL && voice != NULL && substream != NULL, return -EINVAL); + if (snd_BUG_ON(!trident || !voice || !substream)) + return -EINVAL; tmix = &trident->pcm_mixer[substream->number]; tmix->voice = voice; tmix->vol = T4D_DEFAULT_PCM_VOL; @@ -2946,7 +2947,8 @@ static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_tr { struct snd_trident_pcm_mixer *tmix; - snd_assert(trident != NULL && substream != NULL, return -EINVAL); + if (snd_BUG_ON(!trident || !substream)) + return -EINVAL; tmix = &trident->pcm_mixer[substream->number]; tmix->voice = NULL; snd_trident_notify_pcm_change(trident, tmix, substream->number, 0); @@ -3131,7 +3133,8 @@ static unsigned char snd_trident_gameport_read(struct gameport *gameport) { struct snd_trident *chip = gameport_get_port_data(gameport); - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; return inb(TRID_REG(chip, GAMEPORT_LEGACY)); } @@ -3139,7 +3142,8 @@ static void snd_trident_gameport_trigger(struct gameport *gameport) { struct snd_trident *chip = gameport_get_port_data(gameport); - snd_assert(chip, return); + if (snd_BUG_ON(!chip)) + return; outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY)); } @@ -3148,7 +3152,8 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes struct snd_trident *chip = gameport_get_port_data(gameport); int i; - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf; @@ -3164,7 +3169,8 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode) { struct snd_trident *chip = gameport_get_port_data(gameport); - snd_assert(chip, return 0); + if (snd_BUG_ON(!chip)) + return 0; switch (mode) { case GAMEPORT_MODE_COOKED: @@ -3891,8 +3897,8 @@ static void snd_trident_clear_voices(struct snd_trident * trident, unsigned shor { unsigned int i, val, mask[2] = { 0, 0 }; - snd_assert(v_min <= 63, return); - snd_assert(v_max <= 63, return); + if (snd_BUG_ON(v_min > 63 || v_max > 63)) + return; for (i = v_min; i <= v_max; i++) mask[i >> 5] |= 1 << (i & 0x1f); if (mask[0]) { diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 3fd7f1b29b0..2fe3b1fab53 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -196,9 +196,13 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, int idx, page; struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); - snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL); + if (snd_BUG_ON(runtime->dma_bytes <= 0 || + runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES * + SNDRV_TRIDENT_PAGE_SIZE)) + return NULL; hdr = trident->tlb.memhdr; - snd_assert(hdr != NULL, return NULL); + if (snd_BUG_ON(!hdr)) + return NULL; @@ -245,9 +249,13 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, dma_addr_t addr; unsigned long ptr; - snd_assert(runtime->dma_bytes> 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL); + if (snd_BUG_ON(runtime->dma_bytes <= 0 || + runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES * + SNDRV_TRIDENT_PAGE_SIZE)) + return NULL; hdr = trident->tlb.memhdr; - snd_assert(hdr != NULL, return NULL); + if (snd_BUG_ON(!hdr)) + return NULL; mutex_lock(&hdr->block_mutex); blk = search_empty(hdr, runtime->dma_bytes); @@ -279,8 +287,8 @@ struct snd_util_memblk * snd_trident_alloc_pages(struct snd_trident *trident, struct snd_pcm_substream *substream) { - snd_assert(trident != NULL, return NULL); - snd_assert(substream != NULL, return NULL); + if (snd_BUG_ON(!trident || !substream)) + return NULL; if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG) return snd_trident_alloc_sg_pages(trident, substream); else @@ -297,8 +305,8 @@ int snd_trident_free_pages(struct snd_trident *trident, struct snd_util_memhdr *hdr; int page; - snd_assert(trident != NULL, return -EINVAL); - snd_assert(blk != NULL, return -EINVAL); + if (snd_BUG_ON(!trident || !blk)) + return -EINVAL; hdr = trident->tlb.memhdr; mutex_lock(&hdr->block_mutex); diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 6781be9e307..84ea35d8b25 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -824,7 +824,8 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr struct viadev *viadev = substream->runtime->private_data; unsigned int idx, ptr, count, res; - snd_assert(viadev->tbl_entries, return 0); + if (snd_BUG_ON(!viadev->tbl_entries)) + return 0; if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; @@ -855,7 +856,8 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst unsigned int idx, count, res; int status; - snd_assert(viadev->tbl_entries, return 0); + if (snd_BUG_ON(!viadev->tbl_entries)) + return 0; spin_lock(&chip->reg_lock); count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); @@ -1037,7 +1039,7 @@ static int snd_via8233_playback_prepare(struct snd_pcm_substream *substream) else rbits = (0x100000 / 48000) * runtime->rate + ((0x100000 % 48000) * runtime->rate) / 48000; - snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); + snd_BUG_ON(rbits & ~0xfffff); snd_via82xx_channel_reset(chip, viadev); snd_via82xx_set_table_ptr(chip, viadev); outb(chip->playback_volume[viadev->reg_offset / 0x10][0], diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 31f64ee3988..640c338ce0a 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -612,7 +612,8 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr struct viadev *viadev = substream->runtime->private_data; unsigned int idx, ptr, count, res; - snd_assert(viadev->tbl_entries, return 0); + if (snd_BUG_ON(!viadev->tbl_entries)) + return 0; if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 631f3a63999..7e87f398ff0 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -253,7 +253,8 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, int offset = pipe->hw_ptr; u32 *addr = (u32 *)(runtime->dma_area + offset); - snd_assert(count % 4 == 0, return); + if (snd_BUG_ON(count % 4)) + return; vx2_setup_pseudo_dma(chip, 1); @@ -291,7 +292,8 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, u32 *addr = (u32 *)(runtime->dma_area + offset); unsigned long port = vx2_reg_addr(chip, VX_DMA); - snd_assert(count % 4 == 0, return); + if (snd_BUG_ON(count % 4)) + return; vx2_setup_pseudo_dma(chip, 0); /* Transfer using pseudo-dma. @@ -675,7 +677,8 @@ static void vx2_write_akm(struct vx_core *chip, int reg, unsigned int data) a look up table, as there is no linear matching between the driver codec values and the real dBu value */ - snd_assert(data < sizeof(vx2_akm_gains_lut), return); + if (snd_BUG_ON(data >= sizeof(vx2_akm_gains_lut))) + return; switch (reg) { case XX_CODEC_LEVEL_LEFT_REGISTER: @@ -823,7 +826,8 @@ static void vx2_set_input_level(struct snd_vx222 *chip) preamp++; /* raise pre ampli + 18dB */ miclevel -= (18 * 2); /* lower level 18 dB (*2 because of 0.5 dB steps !) */ } - snd_assert(preamp < 4, return); + if (snd_BUG_ON(preamp >= 4)) + return; /* set pre-amp level */ chip->regSELMIC &= ~MICRO_SELECT_PREAMPLI_MASK; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 92d49aadf57..90d0d62bd0b 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -259,8 +259,10 @@ static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip, unsigned long flags; int result; - snd_assert(rvoice != NULL, return -EINVAL); - snd_assert(!pair || type == YMFPCI_PCM, return -EINVAL); + if (snd_BUG_ON(!rvoice)) + return -EINVAL; + if (snd_BUG_ON(pair && type != YMFPCI_PCM)) + return -EINVAL; spin_lock_irqsave(&chip->voice_lock, flags); for (;;) { @@ -278,7 +280,8 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic { unsigned long flags; - snd_assert(pvoice != NULL, return -EINVAL); + if (snd_BUG_ON(!pvoice)) + return -EINVAL; snd_ymfpci_hw_stop(chip); spin_lock_irqsave(&chip->voice_lock, flags); if (pvoice->number == chip->src441_used) { @@ -494,7 +497,8 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int u8 use_left, use_right; unsigned long flags; - snd_assert(voice != NULL, return); + if (snd_BUG_ON(!voice)) + return; if (runtime->channels == 1) { use_left = 1; use_right = 1; @@ -1813,7 +1817,8 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) } /* add S/PDIF control */ - snd_assert(chip->pcm_spdif != NULL, return -EIO); + if (snd_BUG_ON(!chip->pcm_spdif)) + return -ENXIO; if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip))) < 0) return err; kctl->id.device = chip->pcm_spdif->device; @@ -2133,7 +2138,8 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip) chip->work_base = ptr; chip->work_base_addr = ptr_addr; - snd_assert(ptr + chip->work_size == chip->work_ptr.area + chip->work_ptr.bytes, ); + snd_BUG_ON(ptr + chip->work_size != + chip->work_ptr.area + chip->work_ptr.bytes); snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr); snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, chip->bank_base_capture_addr); @@ -2168,7 +2174,8 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) { u16 ctrl; - snd_assert(chip != NULL, return -EINVAL); + if (snd_BUG_ON(!chip)) + return -EINVAL; if (chip->res_reg_area) { /* don't touch busy hardware */ snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); -- GitLab From 5e246b850df563224be26f1d409cf66fd6c968df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:12:47 +0200 Subject: [PATCH 0300/5416] ALSA: Kill snd_assert() in other places Kill snd_assert() in other places, either removed or replaced with if () with snd_BUG_ON(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- drivers/media/video/saa7134/saa7134-alsa.c | 13 +++--- include/sound/vx_core.h | 9 ----- sound/arm/sa11xx-uda1341.c | 5 ++- sound/drivers/dummy.c | 3 +- sound/drivers/opl3/opl3_lib.c | 6 ++- sound/drivers/opl3/opl3_midi.c | 6 ++- sound/drivers/opl3/opl3_oss.c | 15 ++++--- sound/drivers/opl3/opl3_synth.c | 3 +- sound/drivers/opl4/opl4_synth.c | 2 +- sound/drivers/vx/vx_cmd.c | 3 +- sound/drivers/vx/vx_core.c | 21 ++++++---- sound/drivers/vx/vx_hwdep.c | 6 ++- sound/drivers/vx/vx_mixer.c | 3 +- sound/drivers/vx/vx_pcm.c | 9 +++-- sound/drivers/vx/vx_uer.c | 6 ++- sound/i2c/cs8427.c | 15 ++++--- sound/i2c/i2c.c | 6 ++- sound/i2c/l3/uda1341.c | 3 +- sound/i2c/other/ak4114.c | 3 +- sound/i2c/other/ak4117.c | 3 +- sound/mips/au1x00.c | 6 ++- sound/parisc/harmony.c | 3 +- sound/pcmcia/vx/vxp_ops.c | 3 +- sound/ppc/awacs.c | 23 ++++------- sound/ppc/beep.c | 6 ++- sound/ppc/tumbler.c | 17 +++----- sound/sh/aica.c | 3 +- sound/sparc/amd7930.c | 19 +-------- sound/sparc/cs4231.c | 3 +- sound/sparc/dbri.c | 17 +++++--- sound/synth/emux/emux.c | 8 ++-- sound/synth/emux/emux_nrpn.c | 8 ++-- sound/synth/emux/emux_oss.c | 42 ++++++++++++------- sound/synth/emux/emux_seq.c | 15 ++++--- sound/synth/emux/emux_synth.c | 47 ++++++++++++---------- sound/synth/util_mem.c | 10 +++-- sound/usb/usbaudio.c | 12 ++++-- sound/usb/usbmixer.c | 3 +- 38 files changed, 217 insertions(+), 168 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 9929d20320b..26194a0ce92 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -488,10 +488,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, period_size = params_period_bytes(hw_params); periods = params_periods(hw_params); - snd_assert(period_size >= 0x100 && period_size <= 0x10000, - return -EINVAL); - snd_assert(periods >= 4, return -EINVAL); - snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL); + if (period_size < 0x100 || period_size > 0x10000) + return -EINVAL; + if (periods < 4) + return -EINVAL; + if (period_size * periods > 1024 * 1024) + return -EINVAL; dev = saa7134->dev; @@ -942,7 +944,8 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) unsigned int idx; int err; - snd_assert(chip != NULL, return -EINVAL); + if (snd_BUG_ON(!chip)) + return -EINVAL; strcpy(card->mixername, "SAA7134 Mixer"); for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) { diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index 4830651cc4c..5456343ebe4 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h @@ -235,37 +235,31 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev); */ static inline int vx_test_and_ack(struct vx_core *chip) { - snd_assert(chip->ops->test_and_ack, return -ENXIO); return chip->ops->test_and_ack(chip); } static inline void vx_validate_irq(struct vx_core *chip, int enable) { - snd_assert(chip->ops->validate_irq, return); chip->ops->validate_irq(chip, enable); } static inline unsigned char snd_vx_inb(struct vx_core *chip, int reg) { - snd_assert(chip->ops->in8, return 0); return chip->ops->in8(chip, reg); } static inline unsigned int snd_vx_inl(struct vx_core *chip, int reg) { - snd_assert(chip->ops->in32, return 0); return chip->ops->in32(chip, reg); } static inline void snd_vx_outb(struct vx_core *chip, int reg, unsigned char val) { - snd_assert(chip->ops->out8, return); chip->ops->out8(chip, reg, val); } static inline void snd_vx_outl(struct vx_core *chip, int reg, unsigned int val) { - snd_assert(chip->ops->out32, return); chip->ops->out32(chip, reg, val); } @@ -276,7 +270,6 @@ static inline void snd_vx_outl(struct vx_core *chip, int reg, unsigned int val) static inline void vx_reset_dsp(struct vx_core *chip) { - snd_assert(chip->ops->reset_dsp, return); chip->ops->reset_dsp(chip); } @@ -304,14 +297,12 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t static inline void vx_pseudo_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, struct vx_pipe *pipe, int count) { - snd_assert(chip->ops->dma_write, return); chip->ops->dma_write(chip, runtime, pipe, count); } static inline void vx_pseudo_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, struct vx_pipe *pipe, int count) { - snd_assert(chip->ops->dma_read, return); chip->ops->dma_read(chip, runtime, pipe, count); } diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index b9c51bf8cd7..8addb9d914c 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -442,7 +442,8 @@ static void audio_process_dma(struct audio_stream *s) /* we are requested to process synchronization DMA transfer */ if (s->tx_spin) { - snd_assert(s->stream_id == SNDRV_PCM_STREAM_PLAYBACK, return); + if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK)) + return; /* fill the xmit dma buffers and return */ #ifdef HH_VERSION sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE); @@ -472,7 +473,7 @@ static void audio_process_dma(struct audio_stream *s) continue; /* special case */ } else { offset = dma_size * s->period; - snd_assert(dma_size <= DMA_BUF_SIZE, ); + snd_BUG_ON(dma_size > DMA_BUF_SIZE); } #ifdef HH_VERSION ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 4e4c69e6cb4..c873243e671 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -565,7 +565,8 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) unsigned int idx; int err; - snd_assert(dummy != NULL, return -EINVAL); + if (snd_BUG_ON(!dummy)) + return -EINVAL; spin_lock_init(&dummy->mixer_lock); strcpy(card->mixername, "Dummy Mixer"); diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index ebe4359047c..780582340fe 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -139,7 +139,8 @@ static int snd_opl3_detect(struct snd_opl3 * opl3) * If we had an OPL4 chip, opl3->hardware would have been set * by the OPL4 driver; so we can assume OPL3 here. */ - snd_assert(opl3->r_port != 0, return -ENODEV); + if (snd_BUG_ON(!opl3->r_port)) + return -ENODEV; opl3->hardware = OPL3_HW_OPL3; } return 0; @@ -324,7 +325,8 @@ EXPORT_SYMBOL(snd_opl3_interrupt); static int snd_opl3_free(struct snd_opl3 *opl3) { - snd_assert(opl3 != NULL, return -ENXIO); + if (snd_BUG_ON(!opl3)) + return -ENXIO; if (opl3->private_free) opl3->private_free(opl3); snd_opl3_clear_patches(opl3); diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index cebcb8b78ac..16feafa2c51 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -617,7 +617,8 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) struct snd_opl3_voice *vp, *vp2; - snd_assert(voice < MAX_OPL3_VOICES, return); + if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) + return; vp = &opl3->voices[voice]; if (voice < MAX_OPL2_VOICES) { @@ -737,7 +738,8 @@ static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice) struct snd_opl3_voice *vp; - snd_assert(voice < MAX_OPL3_VOICES, return); + if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) + return; vp = &opl3->voices[voice]; if (vp->chan == NULL) diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 239347f2615..9a2271dc046 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -162,7 +162,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) struct snd_opl3 *opl3 = closure; int err; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; if ((err = snd_opl3_synth_setup(opl3)) < 0) return err; @@ -184,7 +185,8 @@ static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg) { struct snd_opl3 *opl3; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; opl3 = arg->private_data; snd_opl3_synth_cleanup(opl3); @@ -206,7 +208,8 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, char name[32]; int err, type; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; opl3 = arg->private_data; if (format == FM_PATCH) @@ -246,7 +249,8 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, { struct snd_opl3 *opl3; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; opl3 = arg->private_data; switch (cmd) { case SNDCTL_FM_LOAD_INSTR: @@ -271,7 +275,8 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg) { struct snd_opl3 *opl3; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; opl3 = arg->private_data; return 0; diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index fb64c890109..962bb9c8b9c 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -92,7 +92,8 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, struct snd_opl3 *opl3 = hw->private_data; void __user *argp = (void __user *)arg; - snd_assert(opl3 != NULL, return -EINVAL); + if (snd_BUG_ON(!opl3)) + return -EINVAL; switch (cmd) { /* get information */ diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c index 74f6e53eae0..49b9e240915 100644 --- a/sound/drivers/opl4/opl4_synth.c +++ b/sound/drivers/opl4/opl4_synth.c @@ -467,7 +467,7 @@ static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4) if (!list_empty(&opl4->off_voices)) return list_entry(opl4->off_voices.next, struct opl4_voice, list); /* then get the oldest key-on voice */ - snd_assert(!list_empty(&opl4->on_voices), ); + snd_BUG_ON(list_empty(&opl4->on_voices)); return list_entry(opl4->on_voices.next, struct opl4_voice, list); } diff --git a/sound/drivers/vx/vx_cmd.c b/sound/drivers/vx/vx_cmd.c index 9529e3bf286..23f4857f02c 100644 --- a/sound/drivers/vx/vx_cmd.c +++ b/sound/drivers/vx/vx_cmd.c @@ -99,7 +99,8 @@ static struct vx_cmd_info vx_dsp_cmds[] = { */ void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd) { - snd_assert(cmd < CMD_LAST_INDEX, return); + if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) + return; rmh->LgCmd = vx_dsp_cmds[cmd].length; rmh->LgStat = vx_dsp_cmds[cmd].st_length; rmh->DspStat = vx_dsp_cmds[cmd].st_type; diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 585af2eb143..473b07f6ae8 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -205,7 +205,8 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) if (size < 1) return 0; - snd_assert(size <= SIZE_MAX_STATUS, return -EINVAL); + if (snd_BUG_ON(size > SIZE_MAX_STATUS)) + return -EINVAL; for (i = 1; i <= size; i++) { /* trigger an irq MESS_WRITE_NEXT */ @@ -425,13 +426,16 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) int no_fillup = vx_has_new_dsp(chip); /* check the length of boot image */ - snd_assert(boot->size > 0, return -EINVAL); - snd_assert(boot->size % 3 == 0, return -EINVAL); + if (boot->size <= 0) + return -EINVAL; + if (boot->size % 3) + return -EINVAL; #if 0 { /* more strict check */ unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2]; - snd_assert(boot->size == (c + 2) * 3, return -EINVAL); + if (boot->size != (c + 2) * 3) + return -EINVAL; } #endif @@ -554,7 +558,8 @@ EXPORT_SYMBOL(snd_vx_irq_handler); */ static void vx_reset_board(struct vx_core *chip, int cold_reset) { - snd_assert(chip->ops->reset_board, return); + if (snd_BUG_ON(!chip->ops->reset_board)) + return; /* current source, later sync'ed with target */ chip->audio_source = VX_AUDIO_SRC_LINE; @@ -673,7 +678,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) unsigned int csum = 0; const unsigned char *image, *cptr; - snd_assert(dsp->size % 3 == 0, return -EINVAL); + if (dsp->size % 3) + return -EINVAL; vx_toggle_dac_mute(chip, 1); @@ -775,7 +781,8 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, { struct vx_core *chip; - snd_assert(card && hw && ops, return NULL); + if (snd_BUG_ON(!card || !hw || !ops)) + return NULL; chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL); if (! chip) { diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index efd22e92bce..8d6362e2d4c 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -141,7 +141,8 @@ static int vx_hwdep_dsp_status(struct snd_hwdep *hw, }; struct vx_core *vx = hw->private_data; - snd_assert(type_ids[vx->type], return -EINVAL); + if (snd_BUG_ON(!type_ids[vx->type])) + return -EINVAL; strcpy(info->id, type_ids[vx->type]); if (vx_is_pcmcia(vx)) info->num_dsps = 4; @@ -168,7 +169,8 @@ static int vx_hwdep_dsp_load(struct snd_hwdep *hw, int index, err; struct firmware *fw; - snd_assert(vx->ops->load_dsp, return -ENXIO); + if (snd_BUG_ON(!vx->ops->load_dsp)) + return -ENXIO; fw = kmalloc(sizeof(*fw), GFP_KERNEL); if (! fw) { diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 5a347321f8c..c71b8d148d7 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -34,7 +34,8 @@ static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int dat { unsigned long flags; - snd_assert(chip->ops->write_codec, return); + if (snd_BUG_ON(!chip->ops->write_codec)) + return; if (chip->chip_status & VX_STAT_IS_STALE) return; diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index fdbf86571b1..27de574c08f 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -587,7 +587,8 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs) return -EBUSY; audio = subs->pcm->device * 2; - snd_assert(audio < chip->audio_outs, return -EINVAL); + if (snd_BUG_ON(audio >= chip->audio_outs)) + return -EINVAL; /* playback pipe may have been already allocated for monitoring */ pipe = chip->playback_pipes[audio]; @@ -996,7 +997,8 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs) return -EBUSY; audio = subs->pcm->device * 2; - snd_assert(audio < chip->audio_ins, return -EINVAL); + if (snd_BUG_ON(audio >= chip->audio_ins)) + return -EINVAL; err = vx_alloc_pipe(chip, 1, audio, 2, &pipe); if (err < 0) return err; @@ -1214,7 +1216,8 @@ void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) } if (capture) continue; - snd_assert(p >= 0 && (unsigned int)p < chip->audio_outs,); + if (snd_BUG_ON(p < 0 || p >= chip->audio_outs)) + continue; pipe = chip->playback_pipes[p]; if (pipe && pipe->substream) { vx_pcm_playback_update(chip, pipe->substream, pipe); diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index fb8932af888..0e1ba9b4790 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c @@ -163,13 +163,15 @@ static int vx_calc_clock_from_freq(struct vx_core *chip, int freq) { int hexfreq; - snd_assert(freq > 0, return 0); + if (snd_BUG_ON(freq <= 0)) + return 0; hexfreq = (28224000 * 10) / freq; hexfreq = (hexfreq + 5) / 10; /* max freq = 55125 Hz */ - snd_assert(hexfreq > 0x00000200, return 0); + if (snd_BUG_ON(hexfreq <= 0x00000200)) + return 0; if (hexfreq <= 0x03ff) return hexfreq - 0x00000201; diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 9c3d361accf..020a5d51247 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -314,7 +314,8 @@ static void snd_cs8427_reset(struct snd_i2c_device *cs8427) unsigned long end_time; int data, aes3input = 0; - snd_assert(cs8427, return); + if (snd_BUG_ON(!cs8427)) + return; chip = cs8427->private_data; snd_i2c_lock(cs8427->bus); if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) == @@ -526,7 +527,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427, unsigned int idx; int err; - snd_assert(play_substream && cap_substream, return -EINVAL); + if (snd_BUG_ON(!play_substream || !cap_substream)) + return -EINVAL; for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) { kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427); if (kctl == NULL) @@ -543,7 +545,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427, chip->playback.substream = play_substream; chip->capture.substream = cap_substream; - snd_assert(chip->playback.pcm_ctl, return -EIO); + if (snd_BUG_ON(!chip->playback.pcm_ctl)) + return -EIO; return 0; } @@ -553,7 +556,8 @@ int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active) { struct cs8427 *chip; - snd_assert(cs8427, return -ENXIO); + if (snd_BUG_ON(!cs8427)) + return -ENXIO; chip = cs8427->private_data; if (active) memcpy(chip->playback.pcm_status, @@ -573,7 +577,8 @@ int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate) char *status; int err, reset; - snd_assert(cs8427, return -ENXIO); + if (snd_BUG_ON(!cs8427)) + return -ENXIO; chip = cs8427->private_data; status = chip->playback.pcm_status; snd_i2c_lock(cs8427->bus); diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index b1e74e40cba..5c0c77dd01c 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c @@ -49,7 +49,8 @@ static int snd_i2c_bus_free(struct snd_i2c_bus *bus) struct snd_i2c_bus *slave; struct snd_i2c_device *device; - snd_assert(bus != NULL, return -EINVAL); + if (snd_BUG_ON(!bus)) + return -EINVAL; while (!list_empty(&bus->devices)) { device = snd_i2c_device(bus->devices.next); snd_i2c_device_free(device); @@ -113,7 +114,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, struct snd_i2c_device *device; *rdevice = NULL; - snd_assert(bus != NULL, return -EINVAL); + if (snd_BUG_ON(!bus)) + return -EINVAL; device = kzalloc(sizeof(*device), GFP_KERNEL); if (device == NULL) return -ENOMEM; diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c index 1f4942ea141..9840eb43648 100644 --- a/sound/i2c/l3/uda1341.c +++ b/sound/i2c/l3/uda1341.c @@ -771,7 +771,8 @@ int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client ** struct l3_client *clnt; int idx, err; - snd_assert(card != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); if (clnt == NULL) diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index d20d893b3b6..0341451f814 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -475,7 +475,8 @@ int snd_ak4114_build(struct ak4114 *ak4114, unsigned int idx; int err; - snd_assert(cap_substream, return -EINVAL); + if (snd_BUG_ON(!cap_substream)) + return -EINVAL; ak4114->playback_substream = ply_substream; ak4114->capture_substream = cap_substream; for (idx = 0; idx < AK4114_CONTROLS; idx++) { diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index f350835ade9..2cad2d61251 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -431,7 +431,8 @@ int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substr unsigned int idx; int err; - snd_assert(cap_substream, return -EINVAL); + if (snd_BUG_ON(!cap_substream)) + return -EINVAL; ak4117->substream = cap_substream; for (idx = 0; idx < AK4117_CONTROLS; idx++) { kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117); diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index fbef38a9604..1881cec11e7 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -190,14 +190,16 @@ au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes, static void au1000_dma_stop(struct audio_stream *stream) { - snd_assert(stream->buffer, return); + if (snd_BUG_ON(!stream->buffer)) + return; disable_dma(stream->dma); } static void au1000_dma_start(struct audio_stream *stream) { - snd_assert(stream->buffer, return); + if (snd_BUG_ON(!stream->buffer)) + return; init_dma(stream->dma); if (get_dma_active_buffer(stream->dma) == 0) { diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 99f5483abf2..774372fe34a 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -868,7 +868,8 @@ snd_harmony_mixer_init(struct snd_harmony *h) struct snd_card *card = h->card; int idx, err; - snd_assert(h != NULL, return -EINVAL); + if (snd_BUG_ON(!h)) + reutrn -EINVAL; strcpy(card->mixername, "Harmony Gain control interface"); for (idx = 0; idx < HARMONY_CONTROLS; idx++) { diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 99bf2a65a6f..989e04abb52 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -408,7 +408,8 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, int offset = pipe->hw_ptr; unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); - snd_assert(count % 2 == 0, return); + if (snd_BUG_ON(count % 2)) + return; vx_setup_pseudo_dma(chip, 0); if (offset + count > pipe->buffer_bytes) { int length = pipe->buffer_bytes - offset; diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 106c48225bb..7bd33e6552a 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -319,7 +319,8 @@ static void awacs_amp_set_master(struct awacs_amp *amp, int vol) static void awacs_amp_free(struct snd_pmac *chip) { struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return); + if (!amp) + return; kfree(amp); chip->mixer_data = NULL; chip->mixer_free = NULL; @@ -345,8 +346,7 @@ static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); int index = kcontrol->private_value; struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); + ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31); ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31); return 0; @@ -359,8 +359,6 @@ static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol, int index = kcontrol->private_value; int vol[2]; struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32); @@ -375,8 +373,7 @@ static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); int index = kcontrol->private_value; struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); + ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1; ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) @@ -391,8 +388,6 @@ static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol, int index = kcontrol->private_value; int vol[2]; struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31); @@ -417,8 +412,7 @@ static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); int index = kcontrol->private_value; struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); + ucontrol->value.integer.value[0] = amp->amp_tone[index]; return 0; } @@ -430,8 +424,7 @@ static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol, int index = kcontrol->private_value; struct awacs_amp *amp = chip->mixer_data; unsigned int val; - snd_assert(amp, return -EINVAL); - snd_assert(index >= 0 && index <= 1, return -EINVAL); + val = ucontrol->value.integer.value[0]; if (val > 14) return -EINVAL; @@ -458,7 +451,7 @@ static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct awacs_amp *amp = chip->mixer_data; - snd_assert(amp, return -EINVAL); + ucontrol->value.integer.value[0] = amp->amp_master; return 0; } @@ -469,7 +462,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct awacs_amp *amp = chip->mixer_data; unsigned int val; - snd_assert(amp, return -EINVAL); + val = ucontrol->value.integer.value[0]; if (val > 99) return -EINVAL; diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index baa2a723737..89f5c328acf 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c @@ -185,7 +185,8 @@ static int snd_pmac_get_beep(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - snd_assert(chip->beep, return -ENXIO); + if (snd_BUG_ON(!chip->beep)) + return -ENXIO; ucontrol->value.integer.value[0] = chip->beep->volume; return 0; } @@ -195,7 +196,8 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); unsigned int oval, nval; - snd_assert(chip->beep, return -ENXIO); + if (snd_BUG_ON(!chip->beep)) + return -ENXIO; oval = chip->beep->volume; nval = ucontrol->value.integer.value[0]; if (nval > 100) diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 009df8dd37a..f746e15b848 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -263,7 +263,7 @@ static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix = chip->mixer_data; - snd_assert(mix, return -ENODEV); + ucontrol->value.integer.value[0] = mix->master_vol[0]; ucontrol->value.integer.value[1] = mix->master_vol[1]; return 0; @@ -277,7 +277,6 @@ static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol, unsigned int vol[2]; int change; - snd_assert(mix, return -ENODEV); vol[0] = ucontrol->value.integer.value[0]; vol[1] = ucontrol->value.integer.value[1]; if (vol[0] >= ARRAY_SIZE(master_volume_table) || @@ -299,7 +298,7 @@ static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix = chip->mixer_data; - snd_assert(mix, return -ENODEV); + ucontrol->value.integer.value[0] = mix->master_switch[0]; ucontrol->value.integer.value[1] = mix->master_switch[1]; return 0; @@ -312,7 +311,6 @@ static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol, struct pmac_tumbler *mix = chip->mixer_data; int change; - snd_assert(mix, return -ENODEV); change = mix->master_switch[0] != ucontrol->value.integer.value[0] || mix->master_switch[1] != ucontrol->value.integer.value[1]; if (change) { @@ -807,7 +805,6 @@ static int snapper_get_capture_source(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix = chip->mixer_data; - snd_assert(mix, return -ENODEV); ucontrol->value.enumerated.item[0] = mix->capture_source; return 0; } @@ -819,7 +816,6 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol, struct pmac_tumbler *mix = chip->mixer_data; int change; - snd_assert(mix, return -ENODEV); change = ucontrol->value.enumerated.item[0] != mix->capture_source; if (change) { mix->capture_source = !!ucontrol->value.enumerated.item[0]; @@ -978,7 +974,8 @@ static void device_change_handler(struct work_struct *work) return; mix = chip->mixer_data; - snd_assert(mix, return); + if (snd_BUG_ON(!mix)) + return; headphone = tumbler_detect_headphone(chip); lineout = tumbler_detect_lineout(chip); @@ -1033,7 +1030,8 @@ static void tumbler_update_automute(struct snd_pmac *chip, int do_notify) if (chip->auto_mute) { struct pmac_tumbler *mix; mix = chip->mixer_data; - snd_assert(mix, return); + if (snd_BUG_ON(!mix)) + return; mix->auto_mute_notify = do_notify; schedule_work(&device_change); } @@ -1227,8 +1225,6 @@ static void tumbler_resume(struct snd_pmac *chip) { struct pmac_tumbler *mix = chip->mixer_data; - snd_assert(mix, return); - mix->acs &= ~1; mix->master_switch[0] = mix->save_master_switch[0]; mix->master_switch[1] = mix->save_master_switch[1]; @@ -1275,7 +1271,6 @@ static int __init tumbler_init(struct snd_pmac *chip) { int irq; struct pmac_tumbler *mix = chip->mixer_data; - snd_assert(mix, return -EINVAL); if (tumbler_find_device("audio-hw-reset", "platform-do-hw-reset", diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 54df8baf916..55031d0a655 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -106,7 +106,8 @@ static void spu_memset(u32 toi, u32 what, int length) { int i; unsigned long flags; - snd_assert(length % 4 == 0, return); + if (snd_BUG_ON(length % 4)) + return; for (i = 0; i < length; i++) { if (!(i % 8)) spu_write_wait(); diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 0c63e0585b1..49acee0c484 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -765,7 +765,6 @@ static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd) /* playback count */ 1, /* capture count */ 1, &pcm)) < 0) return err; - snd_assert(pcm != NULL, return -EINVAL); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_amd7930_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_amd7930_capture_ops); @@ -788,13 +787,6 @@ static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd) static int snd_amd7930_info_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { - int type = kctl->private_value; - - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - (void) type; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; @@ -809,10 +801,6 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem int type = kctl->private_value; int *swval; - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - switch (type) { case VOLUME_MONITOR: swval = &amd->mgain; @@ -838,10 +826,6 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem int type = kctl->private_value; int *swval, change; - snd_assert(type == VOLUME_MONITOR || - type == VOLUME_CAPTURE || - type == VOLUME_PLAYBACK, return -EINVAL); - switch (type) { case VOLUME_MONITOR: swval = &amd->mgain; @@ -904,7 +888,8 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) struct snd_card *card; int idx, err; - snd_assert(amd != NULL && amd->card != NULL, return -EINVAL); + if (snd_BUG_ON(!amd || !amd->card)) + return -EINVAL; card = amd->card; strcpy(card->mixername, card->shortname); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 1c4797be72e..791d2fb821d 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1560,7 +1560,8 @@ static int __init snd_cs4231_mixer(struct snd_card *card) struct snd_cs4231 *chip = card->private_data; int err, idx; - snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); + if (snd_BUG_ON(!chip || !chip->pcm)) + return -EINVAL; strcpy(card->mixername, chip->pcm->name); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index ee2e1b4f355..c534a2a849f 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2223,7 +2223,6 @@ static int __devinit snd_dbri_pcm(struct snd_card *card) /* playback count */ 1, /* capture count */ 1, &pcm)) < 0) return err; - snd_assert(pcm != NULL, return -EINVAL); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); @@ -2263,9 +2262,10 @@ static int snd_cs4215_get_volume(struct snd_kcontrol *kcontrol, { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); struct dbri_streaminfo *info; - snd_assert(dbri != NULL, return -EINVAL); + + if (snd_BUG_ON(!dbri)) + return -EINVAL; info = &dbri->stream_info[kcontrol->private_value]; - snd_assert(info != NULL, return -EINVAL); ucontrol->value.integer.value[0] = info->left_gain; ucontrol->value.integer.value[1] = info->right_gain; @@ -2331,7 +2331,9 @@ static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 1; - snd_assert(dbri != NULL, return -EINVAL); + + if (snd_BUG_ON(!dbri)) + return -EINVAL; if (elem < 4) ucontrol->value.integer.value[0] = @@ -2356,7 +2358,9 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 1; int changed = 0; unsigned short val; - snd_assert(dbri != NULL, return -EINVAL); + + if (snd_BUG_ON(!dbri)) + return -EINVAL; val = (ucontrol->value.integer.value[0] & mask); if (invert == 1) @@ -2432,7 +2436,8 @@ static int __devinit snd_dbri_mixer(struct snd_card *card) int idx, err; struct snd_dbri *dbri; - snd_assert(card != NULL && card->private_data != NULL, return -EINVAL); + if (snd_BUG_ON(!card || !card->private_data)) + return -EINVAL; dbri = card->private_data; strcpy(card->mixername, card->shortname); diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index c89d2ea594b..f16a3fce459 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -93,10 +93,10 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch int err; struct snd_sf_callback sf_cb; - snd_assert(emu->hw != NULL, return -EINVAL); - snd_assert(emu->max_voices > 0, return -EINVAL); - snd_assert(card != NULL, return -EINVAL); - snd_assert(name != NULL, return -EINVAL); + if (snd_BUG_ON(!emu->hw || emu->max_voices <= 0)) + return -EINVAL; + if (snd_BUG_ON(!card || !name)) + return -EINVAL; emu->card = card; emu->name = kstrdup(name, GFP_KERNEL); diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c index c6917ba2c93..00fc005ecf6 100644 --- a/sound/synth/emux/emux_nrpn.c +++ b/sound/synth/emux/emux_nrpn.c @@ -289,8 +289,8 @@ snd_emux_nrpn(void *p, struct snd_midi_channel *chan, struct snd_emux_port *port; port = p; - snd_assert(port != NULL, return); - snd_assert(chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; if (chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 127 && chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] <= 26) { @@ -379,8 +379,8 @@ snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_emux *emu; port = p; - snd_assert(port != NULL, return); - snd_assert(chset != NULL, return); + if (snd_BUG_ON(!port || !chset)) + return; emu = port->emu; switch (parsed) { diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index f60a98ef7de..5c47b6c0926 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c @@ -114,7 +114,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) char tmpname[64]; emu = closure; - snd_assert(arg != NULL && emu != NULL, return -ENXIO); + if (snd_BUG_ON(!arg || !emu)) + return -ENXIO; mutex_lock(&emu->register_mutex); @@ -183,12 +184,15 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) struct snd_emux *emu; struct snd_emux_port *p; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; p = arg->private_data; - snd_assert(p != NULL, return -ENXIO); + if (snd_BUG_ON(!p)) + return -ENXIO; emu = p->emu; - snd_assert(emu != NULL, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; mutex_lock(&emu->register_mutex); snd_emux_sounds_off_all(p); @@ -212,12 +216,15 @@ snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, struct snd_emux_port *p; int rc; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; p = arg->private_data; - snd_assert(p != NULL, return -ENXIO); + if (snd_BUG_ON(!p)) + return -ENXIO; emu = p->emu; - snd_assert(emu != NULL, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; if (format == GUS_PATCH) rc = snd_soundfont_load_guspatch(emu->sflist, buf, count, @@ -252,12 +259,15 @@ snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned l struct snd_emux_port *p; struct snd_emux *emu; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; p = arg->private_data; - snd_assert(p != NULL, return -ENXIO); + if (snd_BUG_ON(!p)) + return -ENXIO; emu = p->emu; - snd_assert(emu != NULL, return -ENXIO); + if (snd_BUG_ON(!emu)) + return -ENXIO; switch (cmd) { case SNDCTL_SEQ_RESETSAMPLES: @@ -282,9 +292,11 @@ snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg) { struct snd_emux_port *p; - snd_assert(arg != NULL, return -ENXIO); + if (snd_BUG_ON(!arg)) + return -ENXIO; p = arg->private_data; - snd_assert(p != NULL, return -ENXIO); + if (snd_BUG_ON(!p)) + return -ENXIO; snd_emux_reset_port(p); return 0; } @@ -302,9 +314,11 @@ snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, void *private_dat unsigned char cmd, *data; p = private_data; - snd_assert(p != NULL, return -EINVAL); + if (snd_BUG_ON(!p)) + return -EINVAL; emu = p->emu; - snd_assert(emu != NULL, return -EINVAL); + if (snd_BUG_ON(!emu)) + return -EINVAL; if (ev->type != SNDRV_SEQ_EVENT_OSS) return snd_emux_event_input(ev, direct, private_data, atomic, hop); diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index d176cc01742..335aa2ce257 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -257,7 +257,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, struct snd_emux_port *port; port = private_data; - snd_assert(port != NULL && ev != NULL, return -EINVAL); + if (snd_BUG_ON(!port || !ev)) + return -EINVAL; snd_midi_process_event(&emux_ops, ev, &port->chset); @@ -308,9 +309,11 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) struct snd_emux *emu; p = private_data; - snd_assert(p != NULL, return -EINVAL); + if (snd_BUG_ON(!p)) + return -EINVAL; emu = p->emu; - snd_assert(emu != NULL, return -EINVAL); + if (snd_BUG_ON(!emu)) + return -EINVAL; mutex_lock(&emu->register_mutex); snd_emux_init_port(p); @@ -329,9 +332,11 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) struct snd_emux *emu; p = private_data; - snd_assert(p != NULL, return -EINVAL); + if (snd_BUG_ON(!p)) + return -EINVAL; emu = p->emu; - snd_assert(emu != NULL, return -EINVAL); + if (snd_BUG_ON(!emu)) + return -EINVAL; mutex_lock(&emu->register_mutex); snd_emux_sounds_off_all(p); diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index b343818dbb9..2cc6f6f7906 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -66,12 +66,12 @@ snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) struct snd_emux_port *port; port = p; - snd_assert(port != NULL && chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.get_voice != NULL, return); - snd_assert(emu->ops.trigger != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.get_voice || !emu->ops.trigger)) + return; key = note; /* remember the original note */ nvoices = get_zone(emu, port, ¬e, vel, chan, table); @@ -164,11 +164,12 @@ snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) struct snd_emux_port *port; port = p; - snd_assert(port != NULL && chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.release != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.release)) + return; spin_lock_irqsave(&emu->voice_lock, flags); for (ch = 0; ch < emu->max_voices; ch++) { @@ -242,11 +243,12 @@ snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) struct snd_emux_port *port; port = p; - snd_assert(port != NULL && chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.update != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.update)) + return; spin_lock_irqsave(&emu->voice_lock, flags); for (ch = 0; ch < emu->max_voices; ch++) { @@ -276,8 +278,8 @@ snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *cha return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.update != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.update)) + return; spin_lock_irqsave(&emu->voice_lock, flags); for (i = 0; i < emu->max_voices; i++) { @@ -303,8 +305,8 @@ snd_emux_update_port(struct snd_emux_port *port, int update) return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.update != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.update)) + return; spin_lock_irqsave(&emu->voice_lock, flags); for (i = 0; i < emu->max_voices; i++) { @@ -326,7 +328,8 @@ snd_emux_control(void *p, int type, struct snd_midi_channel *chan) struct snd_emux_port *port; port = p; - snd_assert(port != NULL && chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; switch (type) { case MIDI_CTL_MSB_MAIN_VOLUME: @@ -400,11 +403,12 @@ snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan) struct snd_emux_port *port; port = p; - snd_assert(port != NULL && chan != NULL, return); + if (snd_BUG_ON(!port || !chan)) + return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.terminate != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.terminate)) + return; terminate_note1(emu, note, chan, 1); } @@ -451,10 +455,11 @@ snd_emux_sounds_off_all(struct snd_emux_port *port) struct snd_emux_voice *vp; unsigned long flags; - snd_assert(port != NULL, return); + if (snd_BUG_ON(!port)) + return; emu = port->emu; - snd_assert(emu != NULL, return); - snd_assert(emu->ops.terminate != NULL, return); + if (snd_BUG_ON(!emu || !emu->ops.terminate)) + return; spin_lock_irqsave(&emu->voice_lock, flags); for (i = 0; i < emu->max_voices; i++) { diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c index deabe5f899c..c85522e3808 100644 --- a/sound/synth/util_mem.c +++ b/sound/synth/util_mem.c @@ -55,7 +55,8 @@ void snd_util_memhdr_free(struct snd_util_memhdr *hdr) { struct list_head *p; - snd_assert(hdr != NULL, return); + if (!hdr) + return; /* release all blocks */ while ((p = hdr->block.next) != &hdr->block) { list_del(p); @@ -74,8 +75,8 @@ __snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size) unsigned int units, prev_offset; struct list_head *p; - snd_assert(hdr != NULL, return NULL); - snd_assert(size > 0, return NULL); + if (snd_BUG_ON(!hdr || size <= 0)) + return NULL; /* word alignment */ units = size; @@ -161,7 +162,8 @@ __snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) */ int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) { - snd_assert(hdr && blk, return -EINVAL); + if (snd_BUG_ON(!hdr || !blk)) + return -EINVAL; mutex_lock(&hdr->block_mutex); __snd_util_mem_free(hdr, blk); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b8cfb7c2276..c91f18cdc8b 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -841,7 +841,8 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru return -EBADFD; for (i = 0; i < subs->nurbs; i++) { - snd_assert(subs->dataurb[i].urb, return -EINVAL); + if (snd_BUG_ON(!subs->dataurb[i].urb)) + return -EINVAL; if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) { snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i); goto __error; @@ -849,7 +850,8 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru } if (subs->syncpipe) { for (i = 0; i < SYNC_URBS; i++) { - snd_assert(subs->syncurb[i].urb, return -EINVAL); + if (snd_BUG_ON(!subs->syncurb[i].urb)) + return -EINVAL; if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) { snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i); goto __error; @@ -1321,10 +1323,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) int err; iface = usb_ifnum_to_if(dev, fmt->iface); - snd_assert(iface, return -EINVAL); + if (WARN_ON(!iface)) + return -EINVAL; alts = &iface->altsetting[fmt->altset_idx]; altsd = get_iface_desc(alts); - snd_assert(altsd->bAlternateSetting == fmt->altsetting, return -EINVAL); + if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) + return -EINVAL; if (fmt == subs->cur_audiofmt) return 0; diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 5f98bee0695..6621fad8c5f 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -1389,7 +1389,8 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl struct usb_mixer_elem_info *cval = kcontrol->private_data; char **itemlist = (char **)kcontrol->private_value; - snd_assert(itemlist, return -EINVAL); + if (snd_BUG_ON(!itemlist)) + return -EINVAL; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = cval->max; -- GitLab From 7cc6dffdae28058f5953fac5743b6abf705d4f05 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:14:55 +0200 Subject: [PATCH 0301/5416] ALSA: Kill snd_assert() definition Remove snd_assert() completely now. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 29 +------------------ include/sound/core.h | 19 ------------ 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index df699e4323e..b54cb5048df 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -6135,38 +6135,11 @@ struct _snd_pcm_runtime { -
- <function>snd_assert()</function> - - snd_assert() macro is similar with the - normal assert() macro. For example, - - - - - - - - - - The first argument is the expression to evaluate, and the - second argument is the action if it fails. When - CONFIG_SND_DEBUG, is set, it will show an - error message such as BUG? (xxx) - together with stack trace. - - - When no debug flag is set, this macro is ignored. - -
-
<function>snd_BUG()</function> It shows the BUG? message and - stack trace as well as snd_assert at the point. + stack trace as well as snd_BUG_ON at the point. It's useful to show that a fatal error happens there. diff --git a/include/sound/core.h b/include/sound/core.h index 938c36a0e87..b3d8ac7c832 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -368,8 +368,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #ifdef CONFIG_SND_DEBUG -#define __ASTRING__(x) #x - #ifdef CONFIG_SND_VERBOSE_PRINTK /** * snd_printd - debug printk @@ -384,22 +382,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #define snd_printd(fmt, args...) \ printk(fmt ,##args) #endif -/** - * snd_assert - run-time assertion macro - * @expr: expression - * - * This macro checks the expression in run-time and invokes the commands - * given in the rest arguments if the assertion is failed. - * When CONFIG_SND_DEBUG is not set, the expression is executed but - * not checked. - */ -#define snd_assert(expr, args...) do { \ - if (unlikely(!(expr))) { \ - snd_printk(KERN_ERR "BUG? (%s)\n", __ASTRING__(expr)); \ - dump_stack(); \ - args; \ - } \ -} while (0) #define snd_BUG() do { \ snd_printk(KERN_ERR "BUG?\n"); \ @@ -411,7 +393,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #else /* !CONFIG_SND_DEBUG */ #define snd_printd(fmt, args...) /* nothing */ -#define snd_assert(expr, args...) (void)(expr) #define snd_BUG() /* nothing */ #define snd_BUG_ON(cond) ({/*(void)(cond);*/ 0;}) /* always false */ -- GitLab From bdbecf50064b75ecce2e10ce2621de0d0fac7de6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:18:08 +0200 Subject: [PATCH 0302/5416] ALSA: Clean up snd_BUG() Use the standard WARN() macro for snd_BUG(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/core.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index b3d8ac7c832..f52ab6f3ca6 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -383,11 +383,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) printk(fmt ,##args) #endif -#define snd_BUG() do { \ - snd_printk(KERN_ERR "BUG?\n"); \ - dump_stack(); \ -} while (0) - +#define snd_BUG() WARN(1, "BUG?\n") #define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond)) #else /* !CONFIG_SND_DEBUG */ -- GitLab From faa09c932c5e1daf5fa40a0ff3d895ad57c5a61d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Mon, 11 Aug 2008 02:09:04 +0400 Subject: [PATCH 0303/5416] ALSA: ice1724/revo: simple clean up ice1724/revo: simple clean up Signed-off-by: Alexander Beregalov Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ice1712/revo.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index 4d2631434dc..5e1b156bfaa 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c @@ -524,16 +524,20 @@ static int __devinit revo_init(struct snd_ice1712 *ice) ak = ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ak) return -ENOMEM; - ice->akm_codecs = 2; switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_REVOLUTION71: ice->akm_codecs = 2; - if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front, &akm_revo_front_priv, ice)) < 0) + err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front, + &akm_revo_front_priv, ice); + if (err < 0) return err; - if ((err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo_surround, &akm_revo_surround_priv, ice)) < 0) + err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo_surround, + &akm_revo_surround_priv, ice); + if (err < 0) return err; /* unmute all codecs */ - snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); + snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, + VT1724_REVO_MUTE); break; case VT1724_SUBDEVICE_REVOLUTION51: ice->akm_codecs = 2; -- GitLab From 6e8d90cd3418f18f3913c8ae558eee1ba21e4d6c Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Mon, 11 Aug 2008 02:52:42 +0400 Subject: [PATCH 0304/5416] ALSA: sound/pci/Kconfig: update for ice1712/24 sound/pci/Kconfig: update for ice1712/24 Signed-off-by: Alexander Beregalov Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/Kconfig | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index db9e31fd061..4a7ebbc9676 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -657,8 +657,9 @@ config SND_ICE1712 Currently supported hardware is: M-Audio Delta 1010(LT), DiO 2496, 66, 44, 410, Audiophile 24/96; Digigram VX442; - TerraTec EWX 24/96, EWS 88MT, 88D, DMX 6Fire, Phase 88; - Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8. + TerraTec EWX 24/96, EWS 88MT/D, DMX 6Fire, Phase 88; + Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8; + Lionstracs Mediastation, Terrasoniq TS 88. To compile this driver as a module, choose M here: the module will be called snd-ice1712. @@ -673,9 +674,12 @@ config SND_ICE1724 ICE/VT1724/1720 (Envy24HT/PT) chips. Currently supported hardware is: AMP AUDIO2000; M-Audio - Revolution 7.1; TerraTec Aureon 5.1 Sky, 7.1 Space/Universe; - AudioTrak Prodigy 7.1; Pontis MS300; Albatron K8X800 Pro II; - Chaintech ZNF3-150/250. + Revolution 5.1, 7.1, Audiophile 192; TerraTec Aureon 5.1 Sky, + 7.1 Space/Universe, Phase 22/28; Onkyo SE-90PCI, SE-200PCI; + AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules + Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal + 192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS, + AV-710; Shuttle SN25P. To compile this driver as a module, choose M here: the module will be called snd-ice1724. -- GitLab From 963f803fb1bbce87f6049c22c737ae379e1047d3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Aug 2008 10:04:40 +0200 Subject: [PATCH 0305/5416] ALSA: hda - Don't reset SPDIF in each status change The SPDIF output is toggled at each time any SPDIF status bits are changed because of the known problems on some codecs. But, this also results in loosing the sync, and the problem is more obvious on HDMI output over SPDIF. Since the toggle is necessary only for some codecs, we should check whether this workaround is needed and skip if unnecessary. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 4 ++-- sound/pci/hda/hda_codec.h | 5 +++++ sound/pci/hda/patch_realtek.c | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 77fbcd4a69b..529bd5f6521 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2590,12 +2590,12 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, unsigned int stream_tag, unsigned int format) { /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ - if (codec->spdif_ctls & AC_DIG1_ENABLE) + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); /* turn on again (if needed) */ - if (codec->spdif_ctls & AC_DIG1_ENABLE) + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2f112626f24..aeee5816153 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -654,6 +654,11 @@ struct hda_codec { struct snd_hwdep *hwdep; /* assigned hwdep device */ + /* misc flags */ + unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each + * status change + * (e.g. Realtek codecs) + */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7e5422f64ca..8bff732958e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2670,6 +2670,8 @@ static int alc_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; } + /* FIXME: do we need this for all Realtek codec models? */ + codec->spdif_status_reset = 1; } /* If the use of more than one ADC is requested for the current -- GitLab From db3da6c135c6f5fffed7cca53381b52f2f2d7b53 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Aug 2008 18:08:54 +0200 Subject: [PATCH 0306/5416] ALSA: hda - initialize node 0x21 properly on AD1988 codecs The widget node 0x21 should be initialized as unmuted/full (0dB) as default. This will reduce additional manual work by user at the first time use. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_analog.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e8003d99f0b..b6d64cc0787 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2207,6 +2207,8 @@ static struct hda_verb ad1988_6stack_init_verbs[] = { {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Analog CD Input */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; @@ -2336,6 +2338,8 @@ static struct hda_verb ad1988_3stack_init_verbs[] = { {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; @@ -2409,6 +2413,8 @@ static struct hda_verb ad1988_laptop_init_verbs[] = { {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; -- GitLab From a2854dc5f0e1145a38e10c67064a776d84e56f5d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 13 Aug 2008 12:36:21 +0400 Subject: [PATCH 0307/5416] ALSA: sound/pci: supported cards update sound/pci: supported cards update Signed-off-by: Alexander Beregalov Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ice1712/delta.h | 1 + sound/pci/intel8x0.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index ea7116c304c..f7f14df81f2 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h @@ -31,6 +31,7 @@ "{MidiMan M Audio,Delta DiO 2496},"\ "{MidiMan M Audio,Delta 66},"\ "{MidiMan M Audio,Delta 44},"\ + "{MidiMan M Audio,Delta 410},"\ "{MidiMan M Audio,Audiophile 24/96},"\ "{Digigram,VX442},"\ "{Lionstracs,Mediastation}," diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 78760996632..73ad5899536 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -59,6 +59,12 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{SiS,SI7012}," "{NVidia,nForce Audio}," "{NVidia,nForce2 Audio}," + "{NVidia,nForce3 Audio}," + "{NVidia,MCP04}," + "{NVidia,MCP501}," + "{NVidia,CK804}," + "{NVidia,CK8}," + "{NVidia,CK8S}," "{AMD,AMD768}," "{AMD,AMD8111}," "{ALI,M5455}}"); -- GitLab From 6ef109050da99952b59397840e9b50cd6611e92a Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 13 Aug 2008 00:10:55 +0400 Subject: [PATCH 0308/5416] ALSA: ALSA-Configuration.txt: supported cards update ALSA-Configuration.txt: supported cards update Signed-off-by: Alexander Beregalov Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- .../sound/alsa/ALSA-Configuration.txt | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index b117e42a616..dd083b2a5bd 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -746,8 +746,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-hda-intel -------------------- - Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8), - ATI SB450, SB600, RS600, + Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10, + PCH, SCH), + ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620, + RV630, RV635, RV670, RV770, VIA VT8251/VT8237A, SIS966, ULI M5461 @@ -1166,6 +1168,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. * Event Electronics, EZ8 * Digigram VX442 * Lionstracs, Mediastaton + * Terrasoniq TS 88 model - Use the given board model, one of the following: delta1010, dio2496, delta66, delta44, audiophile, delta410, @@ -1200,7 +1203,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. * TerraTec Phase 22 * TerraTec Phase 28 * AudioTrak Prodigy 7.1 - * AudioTrak Prodigy 7.1LT + * AudioTrak Prodigy 7.1 LT + * AudioTrak Prodigy 7.1 XT + * AudioTrak Prodigy 7.1 HIFI + * AudioTrak Prodigy 7.1 HD2 * AudioTrak Prodigy 192 * Pontis MS300 * Albatron K8X800 Pro II @@ -1211,12 +1217,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. * Shuttle SN25P * Onkyo SE-90PCI * Onkyo SE-200PCI + * ESI Juli@ + * Hercules Fortissimo IV + * EGO-SYS WaveTerminal 192M model - Use the given board model, one of the following: revo51, revo71, amp2000, prodigy71, prodigy71lt, - prodigy192, aureon51, aureon71, universe, ap192, - k8x800, phase22, phase28, ms300, av710, se200pci, - se90pci + prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192, + juli, aureon51, aureon71, universe, ap192, k8x800, + phase22, phase28, ms300, av710, se200pci, se90pci, + fortissimo4, sn25p, WT192M This module supports multiple cards and autoprobe. @@ -1255,7 +1265,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for AC'97 motherboards from Intel and compatibles. * Intel i810/810E, i815, i820, i830, i84x, MX440 - ICH5, ICH6, ICH7, ESB2 + ICH5, ICH6, ICH7, 6300ESB, ESB2 * SiS 7012 (SiS 735) * NVidia NForce, NForce2, NForce3, MCP04, CK804 CK8, CK8S, MCP501 @@ -1951,6 +1961,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. * CHIC True Sound 4Dwave * Shark Predator4D-PCI * Jaton SonicWave 4D + * SiS SI7018 PCI Audio + * Hoontech SoundTrack Digital 4DWave NX pcm_channels - max channels (voices) reserved for PCM wavetable_size - max wavetable size in kB (4-?kb) -- GitLab From 26d809af6397ce5c37f5c44d89734d19cce1ad25 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 13 Aug 2008 12:46:26 +0200 Subject: [PATCH 0309/5416] x86: fix xsave build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix this build failure with certain glibc versions: In file included from /usr/include/bits/sigcontext.h:28, from /usr/include/signal.h:333, from Documentation/accounting/getdelays.c:24: /home/mingo/tip/usr/include/asm/sigcontext.h:191: error: expected specifier-qualifier-list before ‘u64’ Signed-off-by: Ingo Molnar --- include/asm-x86/sigcontext.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h index 899fe2f8abb..ee813f4fe5d 100644 --- a/include/asm-x86/sigcontext.h +++ b/include/asm-x86/sigcontext.h @@ -264,9 +264,9 @@ struct sigcontext { #endif /* !__i386__ */ struct _xsave_hdr { - u64 xstate_bv; - u64 reserved1[2]; - u64 reserved2[5]; + __u64 xstate_bv; + __u64 reserved1[2]; + __u64 reserved2[5]; }; /* -- GitLab From 34a1b9fc4995102ecbb3a980b348aebf168d8196 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Aug 2008 13:25:44 +0100 Subject: [PATCH 0310/5416] Fix date output in x86 microcode driver. The microcode stores its date in a uint32_t in some weird order approximating pdp-endian. Rather than printing it like that, print it properly in ISO standard form. Signed-off-by: David Woodhouse Cc: Shaohua Li Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index a61986e8b69..d2d9d74f4cb 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -339,8 +339,11 @@ static void apply_microcode(int cpu) return; } printk(KERN_INFO "microcode: CPU%d updated from revision " - "0x%x to 0x%x, date = %08x \n", - cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date); + "0x%x to 0x%x, date = %04x-%02x-%02x \n", + cpu_num, uci->rev, val[1], + uci->mc.mc_intel->hdr.date & 0xffff, + uci->mc.mc_intel->hdr.date >> 24, + (uci->mc.mc_intel->hdr.date >> 16) & 0xff); uci->rev = val[1]; } -- GitLab From ba443687f2eb70d23e0466d4b7c0c3366b5cb5fb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 13 Aug 2008 20:55:32 +0200 Subject: [PATCH 0311/5416] ALSA: hda - put all HDA codec IDs to components for precise hw detection Export HDA codec subvendor ID and revision ID to user space via the components variable. Our alsactl utility requires these values for the perfect hardware identification. Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 529bd5f6521..4f329115080 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -588,7 +588,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, struct hda_codec **codecp) { struct hda_codec *codec; - char component[13]; + char component[31]; int err; if (snd_BUG_ON(!bus)) @@ -693,7 +693,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, snd_hda_create_hwdep(codec); #endif - sprintf(component, "HDA:%08x", codec->vendor_id); + sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id); snd_component_add(codec->bus->card, component); if (codecp) -- GitLab From ee2b92a8201a40021ecd1aee6f0625dc03bacc54 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:13 -0700 Subject: [PATCH 0312/5416] x86, xsave: remove the redundant access_ok() in setup_rt_frame() save_i387_xstate() is already doing the required access_ok(). Remove the redundant access_ok() before it. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal_64.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 2621b98f5bf..6c581698ab5 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -208,9 +208,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; - if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) - goto give_sigsegv; - if (save_i387_xstate(fp) < 0) err |= -1; } else -- GitLab From ed405958057ca6a8c4c9178a7a3b1167fabb45f5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:14 -0700 Subject: [PATCH 0313/5416] x86, xsave: clear the user buffer before doing fxsave/xsave fxsave/xsave instructions will not touch all the bytes in the fxsave/xsave frame. Clear the user buffer before doing fxsave/xsave directly to user buffer during the sigcontext setup. This is essentially needed in the context of xsave(for example, some of the fields in the xsave header are not touched by the xsave and defined as must be zero). This will also present uniform and clean context to the user (from which user can safely do fxrstor/xrstor). Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 7415f3e38a5..bb097b1644d 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -92,6 +92,12 @@ int save_i387_xstate(void __user *buf) return 0; clear_used_math(); /* trigger finit */ if (task_thread_info(tsk)->status & TS_USEDFPU) { + /* + * Start with clearing the user buffer. This will present a + * clean context for the bytes not touched by the fxsave/xsave. + */ + __clear_user(buf, sig_xstate_size); + if (task_thread_info(tsk)->status & TS_XSAVE) err = xsave_user(buf); else -- GitLab From f65bc214e042916135256620f900e9599d65e0cb Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 13 Aug 2008 11:38:15 -0700 Subject: [PATCH 0314/5416] x86, xsave: use BUG_ON() instead of BUILD_BUG_ON() All these structure sizes are runtime determined. So use a runtime bug check. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index bb097b1644d..07713d64deb 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -82,8 +82,7 @@ int save_i387_xstate(void __user *buf) if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; - BUILD_BUG_ON(sizeof(struct user_i387_struct) != - sizeof(tsk->thread.xstate->fxsave)); + BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); -- GitLab From cf417141cbb3a4ceb5cca15b2c1f099bd0a6603c Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Mon, 11 Aug 2008 14:33:53 -0700 Subject: [PATCH 0315/5416] sched, cpuset: rework sched domains and CPU hotplug handling (v4) This is an updated version of my previous cpuset patch on top of the latest mainline git. The patch fixes CPU hotplug handling issues in the current cpusets code. Namely circular locking in rebuild_sched_domains() and unsafe access to the cpu_online_map in the cpuset cpu hotplug handler. This version includes changes suggested by Paul Jackson (naming, comments, style, etc). I also got rid of the separate workqueue thread because it is now safe to call get_online_cpus() from workqueue callbacks. Here are some more details: rebuild_sched_domains() is the only way to rebuild sched domains correctly based on the current cpuset settings. What this means is that we need to be able to call it from different contexts, like cpu hotplug for example. Also latest scheduler code in -tip now calls rebuild_sched_domains() directly from functions like arch_reinit_sched_domains(). In order to support that properly we need to rework cpuset locking rules to avoid circular dependencies, which is what this patch does. New lock nesting rules are explained in the comments. We can now safely call rebuild_sched_domains() from virtually any context. The only requirement is that it needs to be called under get_online_cpus(). This allows cpu hotplug handlers and the scheduler to call rebuild_sched_domains() directly. The rest of the cpuset code now offloads sched domains rebuilds to a workqueue (async_rebuild_sched_domains()). This version of the patch addresses comments from the previous review. I fixed all miss-formated comments and trailing spaces. I also factored out the code that builds domain masks and split up CPU and memory hotplug handling. This was needed to simplify locking, to avoid unsafe access to the cpu_online_map from mem hotplug handler, and in general to make things cleaner. The patch passes moderate testing (building kernel with -j 16, creating & removing domains and bringing cpus off/online at the same time) on the quad-core2 based machine. It passes lockdep checks, even with preemptable RCU enabled. This time I also tested in with suspend/resume path and everything is working as expected. Signed-off-by: Max Krasnyansky Acked-by: Paul Jackson Cc: menage@google.com Cc: a.p.zijlstra@chello.nl Cc: vegard.nossum@gmail.com Signed-off-by: Ingo Molnar --- kernel/cpuset.c | 312 ++++++++++++++++++++++++++++-------------------- 1 file changed, 182 insertions(+), 130 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d5ab79cf516..f227bc17269 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -14,6 +14,8 @@ * 2003-10-22 Updates by Stephen Hemminger. * 2004 May-July Rework by Paul Jackson. * 2006 Rework by Paul Menage to use generic cgroups + * 2008 Rework of the scheduler domains and CPU hotplug handling + * by Max Krasnyansky * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the Linux @@ -236,9 +238,11 @@ static struct cpuset top_cpuset = { static DEFINE_MUTEX(callback_mutex); -/* This is ugly, but preserves the userspace API for existing cpuset +/* + * This is ugly, but preserves the userspace API for existing cpuset * users. If someone tries to mount the "cpuset" filesystem, we - * silently switch it to mount "cgroup" instead */ + * silently switch it to mount "cgroup" instead + */ static int cpuset_get_sb(struct file_system_type *fs_type, int flags, const char *unused_dev_name, void *data, struct vfsmount *mnt) @@ -473,10 +477,9 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) } /* - * Helper routine for rebuild_sched_domains(). + * Helper routine for generate_sched_domains(). * Do cpusets a, b have overlapping cpus_allowed masks? */ - static int cpusets_overlap(struct cpuset *a, struct cpuset *b) { return cpus_intersects(a->cpus_allowed, b->cpus_allowed); @@ -518,26 +521,15 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) } /* - * rebuild_sched_domains() - * - * This routine will be called to rebuild the scheduler's dynamic - * sched domains: - * - if the flag 'sched_load_balance' of any cpuset with non-empty - * 'cpus' changes, - * - or if the 'cpus' allowed changes in any cpuset which has that - * flag enabled, - * - or if the 'sched_relax_domain_level' of any cpuset which has - * that flag enabled and with non-empty 'cpus' changes, - * - or if any cpuset with non-empty 'cpus' is removed, - * - or if a cpu gets offlined. - * - * This routine builds a partial partition of the systems CPUs - * (the set of non-overlappping cpumask_t's in the array 'part' - * below), and passes that partial partition to the kernel/sched.c - * partition_sched_domains() routine, which will rebuild the - * schedulers load balancing domains (sched domains) as specified - * by that partial partition. A 'partial partition' is a set of - * non-overlapping subsets whose union is a subset of that set. + * generate_sched_domains() + * + * This function builds a partial partition of the systems CPUs + * A 'partial partition' is a set of non-overlapping subsets whose + * union is a subset of that set. + * The output of this function needs to be passed to kernel/sched.c + * partition_sched_domains() routine, which will rebuild the scheduler's + * load balancing domains (sched domains) as specified by that partial + * partition. * * See "What is sched_load_balance" in Documentation/cpusets.txt * for a background explanation of this. @@ -547,13 +539,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) * domains when operating in the severe memory shortage situations * that could cause allocation failures below. * - * Call with cgroup_mutex held. May take callback_mutex during - * call due to the kfifo_alloc() and kmalloc() calls. May nest - * a call to the get_online_cpus()/put_online_cpus() pair. - * Must not be called holding callback_mutex, because we must not - * call get_online_cpus() while holding callback_mutex. Elsewhere - * the kernel nests callback_mutex inside get_online_cpus() calls. - * So the reverse nesting would risk an ABBA deadlock. + * Must be called with cgroup_lock held. * * The three key local variables below are: * q - a linked-list queue of cpuset pointers, used to implement a @@ -588,10 +574,10 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) * element of the partition (one sched domain) to be passed to * partition_sched_domains(). */ - -void rebuild_sched_domains(void) +static int generate_sched_domains(cpumask_t **domains, + struct sched_domain_attr **attributes) { - LIST_HEAD(q); /* queue of cpusets to be scanned*/ + LIST_HEAD(q); /* queue of cpusets to be scanned */ struct cpuset *cp; /* scans q */ struct cpuset **csa; /* array of all cpuset ptrs */ int csn; /* how many cpuset ptrs in csa so far */ @@ -601,23 +587,26 @@ void rebuild_sched_domains(void) int ndoms; /* number of sched domains in result */ int nslot; /* next empty doms[] cpumask_t slot */ - csa = NULL; + ndoms = 0; doms = NULL; dattr = NULL; + csa = NULL; /* Special case for the 99% of systems with one, full, sched domain */ if (is_sched_load_balance(&top_cpuset)) { - ndoms = 1; doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL); if (!doms) - goto rebuild; + goto done; + dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL); if (dattr) { *dattr = SD_ATTR_INIT; update_domain_attr_tree(dattr, &top_cpuset); } *doms = top_cpuset.cpus_allowed; - goto rebuild; + + ndoms = 1; + goto done; } csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL); @@ -680,61 +669,141 @@ restart: } } - /* Convert to */ + /* + * Now we know how many domains to create. + * Convert to and populate cpu masks. + */ doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL); - if (!doms) - goto rebuild; + if (!doms) { + ndoms = 0; + goto done; + } + + /* + * The rest of the code, including the scheduler, can deal with + * dattr==NULL case. No need to abort if alloc fails. + */ dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL); for (nslot = 0, i = 0; i < csn; i++) { struct cpuset *a = csa[i]; + cpumask_t *dp; int apn = a->pn; - if (apn >= 0) { - cpumask_t *dp = doms + nslot; - - if (nslot == ndoms) { - static int warnings = 10; - if (warnings) { - printk(KERN_WARNING - "rebuild_sched_domains confused:" - " nslot %d, ndoms %d, csn %d, i %d," - " apn %d\n", - nslot, ndoms, csn, i, apn); - warnings--; - } - continue; + if (apn < 0) { + /* Skip completed partitions */ + continue; + } + + dp = doms + nslot; + + if (nslot == ndoms) { + static int warnings = 10; + if (warnings) { + printk(KERN_WARNING + "rebuild_sched_domains confused:" + " nslot %d, ndoms %d, csn %d, i %d," + " apn %d\n", + nslot, ndoms, csn, i, apn); + warnings--; } + continue; + } - cpus_clear(*dp); - if (dattr) - *(dattr + nslot) = SD_ATTR_INIT; - for (j = i; j < csn; j++) { - struct cpuset *b = csa[j]; - - if (apn == b->pn) { - cpus_or(*dp, *dp, b->cpus_allowed); - b->pn = -1; - if (dattr) - update_domain_attr_tree(dattr - + nslot, b); - } + cpus_clear(*dp); + if (dattr) + *(dattr + nslot) = SD_ATTR_INIT; + for (j = i; j < csn; j++) { + struct cpuset *b = csa[j]; + + if (apn == b->pn) { + cpus_or(*dp, *dp, b->cpus_allowed); + if (dattr) + update_domain_attr_tree(dattr + nslot, b); + + /* Done with this partition */ + b->pn = -1; } - nslot++; } + nslot++; } BUG_ON(nslot != ndoms); -rebuild: - /* Have scheduler rebuild sched domains */ +done: + kfree(csa); + + *domains = doms; + *attributes = dattr; + return ndoms; +} + +/* + * Rebuild scheduler domains. + * + * Call with neither cgroup_mutex held nor within get_online_cpus(). + * Takes both cgroup_mutex and get_online_cpus(). + * + * Cannot be directly called from cpuset code handling changes + * to the cpuset pseudo-filesystem, because it cannot be called + * from code that already holds cgroup_mutex. + */ +static void do_rebuild_sched_domains(struct work_struct *unused) +{ + struct sched_domain_attr *attr; + cpumask_t *doms; + int ndoms; + get_online_cpus(); - partition_sched_domains(ndoms, doms, dattr); + + /* Generate domain masks and attrs */ + cgroup_lock(); + ndoms = generate_sched_domains(&doms, &attr); + cgroup_unlock(); + + /* Have scheduler rebuild the domains */ + partition_sched_domains(ndoms, doms, attr); + put_online_cpus(); +} -done: - kfree(csa); - /* Don't kfree(doms) -- partition_sched_domains() does that. */ - /* Don't kfree(dattr) -- partition_sched_domains() does that. */ +static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains); + +/* + * Rebuild scheduler domains, asynchronously via workqueue. + * + * If the flag 'sched_load_balance' of any cpuset with non-empty + * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset + * which has that flag enabled, or if any cpuset with a non-empty + * 'cpus' is removed, then call this routine to rebuild the + * scheduler's dynamic sched domains. + * + * The rebuild_sched_domains() and partition_sched_domains() + * routines must nest cgroup_lock() inside get_online_cpus(), + * but such cpuset changes as these must nest that locking the + * other way, holding cgroup_lock() for much of the code. + * + * So in order to avoid an ABBA deadlock, the cpuset code handling + * these user changes delegates the actual sched domain rebuilding + * to a separate workqueue thread, which ends up processing the + * above do_rebuild_sched_domains() function. + */ +static void async_rebuild_sched_domains(void) +{ + schedule_work(&rebuild_sched_domains_work); +} + +/* + * Accomplishes the same scheduler domain rebuild as the above + * async_rebuild_sched_domains(), however it directly calls the + * rebuild routine synchronously rather than calling it via an + * asynchronous work thread. + * + * This can only be called from code that is not holding + * cgroup_mutex (not nested in a cgroup_lock() call.) + */ +void rebuild_sched_domains(void) +{ + do_rebuild_sched_domains(NULL); } /** @@ -863,7 +932,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf) return retval; if (is_load_balanced) - rebuild_sched_domains(); + async_rebuild_sched_domains(); return 0; } @@ -1090,7 +1159,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val) if (val != cs->relax_domain_level) { cs->relax_domain_level = val; if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs)) - rebuild_sched_domains(); + async_rebuild_sched_domains(); } return 0; @@ -1131,7 +1200,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, mutex_unlock(&callback_mutex); if (cpus_nonempty && balance_flag_changed) - rebuild_sched_domains(); + async_rebuild_sched_domains(); return 0; } @@ -1492,6 +1561,9 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft) default: BUG(); } + + /* Unreachable but makes gcc happy */ + return 0; } static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft) @@ -1504,6 +1576,9 @@ static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft) default: BUG(); } + + /* Unrechable but makes gcc happy */ + return 0; } @@ -1692,15 +1767,9 @@ static struct cgroup_subsys_state *cpuset_create( } /* - * Locking note on the strange update_flag() call below: - * * 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(). The get_online_cpus() - * call in rebuild_sched_domains() must not be made while holding - * callback_mutex. Elsewhere the kernel nests callback_mutex inside - * get_online_cpus() calls. So the reverse nesting would risk an - * ABBA deadlock. + * will call async_rebuild_sched_domains(). */ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont) @@ -1719,7 +1788,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont) struct cgroup_subsys cpuset_subsys = { .name = "cpuset", .create = cpuset_create, - .destroy = cpuset_destroy, + .destroy = cpuset_destroy, .can_attach = cpuset_can_attach, .attach = cpuset_attach, .populate = cpuset_populate, @@ -1811,7 +1880,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to) } /* - * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs + * If CPU and/or memory hotplug handlers, below, unplug any CPUs * or memory nodes, we need to walk over the cpuset hierarchy, * removing that CPU or node from all cpusets. If this removes the * last CPU or node from a cpuset, then move the tasks in the empty @@ -1902,35 +1971,6 @@ static void scan_for_empty_cpusets(const struct cpuset *root) } } -/* - * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track - * cpu_online_map and node_states[N_HIGH_MEMORY]. Force the top cpuset to - * track what's online after any CPU or memory node hotplug or unplug event. - * - * Since there are two callers of this routine, one for CPU hotplug - * events and one for memory node hotplug events, we could have coded - * two separate routines here. We code it as a single common routine - * in order to minimize text size. - */ - -static void common_cpu_mem_hotplug_unplug(int rebuild_sd) -{ - cgroup_lock(); - - top_cpuset.cpus_allowed = cpu_online_map; - top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; - scan_for_empty_cpusets(&top_cpuset); - - /* - * Scheduler destroys domains on hotplug events. - * Rebuild them based on the current settings. - */ - if (rebuild_sd) - rebuild_sched_domains(); - - cgroup_unlock(); -} - /* * The top_cpuset tracks what CPUs and Memory Nodes are online, * period. This is necessary in order to make cpusets transparent @@ -1939,40 +1979,52 @@ static void common_cpu_mem_hotplug_unplug(int rebuild_sd) * * This routine ensures that top_cpuset.cpus_allowed tracks * cpu_online_map on each CPU hotplug (cpuhp) event. + * + * Called within get_online_cpus(). Needs to call cgroup_lock() + * before calling generate_sched_domains(). */ - -static int cpuset_handle_cpuhp(struct notifier_block *unused_nb, +static int cpuset_track_online_cpus(struct notifier_block *unused_nb, unsigned long phase, void *unused_cpu) { + struct sched_domain_attr *attr; + cpumask_t *doms; + int ndoms; + switch (phase) { - case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: - case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: case CPU_ONLINE: case CPU_ONLINE_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - common_cpu_mem_hotplug_unplug(1); break; + default: return NOTIFY_DONE; } + cgroup_lock(); + top_cpuset.cpus_allowed = cpu_online_map; + scan_for_empty_cpusets(&top_cpuset); + ndoms = generate_sched_domains(&doms, &attr); + cgroup_unlock(); + + /* Have scheduler rebuild the domains */ + partition_sched_domains(ndoms, doms, attr); + return NOTIFY_OK; } #ifdef CONFIG_MEMORY_HOTPLUG /* * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY]. - * Call this routine anytime after you change - * node_states[N_HIGH_MEMORY]. - * See also the previous routine cpuset_handle_cpuhp(). + * Call this routine anytime after node_states[N_HIGH_MEMORY] changes. + * See also the previous routine cpuset_track_online_cpus(). */ - void cpuset_track_online_nodes(void) { - common_cpu_mem_hotplug_unplug(0); + cgroup_lock(); + top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; + scan_for_empty_cpusets(&top_cpuset); + cgroup_unlock(); } #endif @@ -1987,7 +2039,7 @@ void __init cpuset_init_smp(void) top_cpuset.cpus_allowed = cpu_online_map; top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; - hotcpu_notifier(cpuset_handle_cpuhp, 0); + hotcpu_notifier(cpuset_track_online_cpus, 0); } /** -- GitLab From dbc74c65b3fd841985935f676388c82d6b85c485 Mon Sep 17 00:00:00 2001 From: Vesa-Matti Kari Date: Thu, 7 Aug 2008 03:18:20 +0300 Subject: [PATCH 0316/5416] selinux: Unify for- and while-loop style Replace "thing != NULL" comparisons with just "thing" to make the code look more uniform (mixed styles were used even in the same source file). Signed-off-by: Vesa-Matti Kari Acked-by: Stephen Smalley Signed-off-by: James Morris --- security/selinux/ss/avtab.c | 2 +- security/selinux/ss/conditional.c | 16 ++++++++-------- security/selinux/ss/ebitmap.c | 4 ++-- security/selinux/ss/hashtab.c | 6 +++--- security/selinux/ss/services.c | 8 ++++---- security/selinux/ss/sidtab.c | 12 ++++++------ 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index e8ae812d6af..1215b8e47db 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -229,7 +229,7 @@ void avtab_destroy(struct avtab *h) for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; kmem_cache_free(avtab_node_cachep, temp); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index f8c850a56ed..4a4e35cac22 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr) int s[COND_EXPR_MAXDEPTH]; int sp = -1; - for (cur = expr; cur != NULL; cur = cur->next) { + for (cur = expr; cur; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: if (sp == (COND_EXPR_MAXDEPTH - 1)) @@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) if (new_state == -1) printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ - for (cur = node->true_list; cur != NULL; cur = cur->next) { + for (cur = node->true_list; cur; cur = cur->next) { if (new_state <= 0) cur->node->key.specified &= ~AVTAB_ENABLED; else cur->node->key.specified |= AVTAB_ENABLED; } - for (cur = node->false_list; cur != NULL; cur = cur->next) { + for (cur = node->false_list; cur; cur = cur->next) { /* -1 or 1 */ if (new_state) cur->node->key.specified &= ~AVTAB_ENABLED; @@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p) static void cond_av_list_destroy(struct cond_av_list *list) { struct cond_av_list *cur, *next; - for (cur = list; cur != NULL; cur = next) { + for (cur = list; cur; cur = next) { next = cur->next; /* the avtab_ptr_t node is destroy by the avtab */ kfree(cur); @@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node) { struct cond_expr *cur_expr, *next_expr; - for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { + for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) { next_expr = cur_expr->next; kfree(cur_expr); } @@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list) if (list == NULL) return; - for (cur = list; cur != NULL; cur = next) { + for (cur = list; cur; cur = next) { next = cur->next; cond_node_destroy(cur); } @@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum goto err; } found = 0; - for (cur = other; cur != NULL; cur = cur->next) { + for (cur = other; cur; cur = cur->next) { if (cur->node == node_ptr) { found = 1; break; @@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi if (!ctab || !key || !avd) return; - for (node = avtab_search_node(ctab, key); node != NULL; + for (node = avtab_search_node(ctab, key); node; node = avtab_search_node_next(node, key->specified)) { if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index ddc275490af..68c7348d1ac 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, *catmap = c_iter; c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); - while (e_iter != NULL) { + while (e_iter) { for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { unsigned int delta, e_startbit, c_endbit; @@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, } } c_iter = c_iter->next; - } while (c_iter != NULL); + } while (c_iter); if (e_iter != NULL) ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; else diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 2e7788e1321..933e735bb18 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key) hvalue = h->hash_value(h, key); cur = h->htable[hvalue]; - while (cur != NULL && h->keycmp(h, key, cur->key) > 0) + while (cur && h->keycmp(h, key, cur->key) > 0) cur = cur->next; if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) @@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h) for (i = 0; i < h->size; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; kfree(temp); @@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h, for (i = 0; i < h->size; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { ret = apply(cur->key, cur->datum, args); if (ret) return ret; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b52f923ce68..5a0536bddc6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -356,7 +356,7 @@ static int context_struct_compute_av(struct context *scontext, avkey.source_type = i + 1; avkey.target_type = j + 1; for (node = avtab_search_node(&policydb.te_avtab, &avkey); - node != NULL; + node; node = avtab_search_node_next(node, avkey.specified)) { if (node->key.specified == AVTAB_ALLOWED) avd->allowed |= node->datum.data; @@ -1037,7 +1037,7 @@ static int security_compute_sid(u32 ssid, /* If no permanent rule, also check for enabled conditional rules */ if (!avdatum) { node = avtab_search_node(&policydb.te_cond_avtab, &avkey); - for (; node != NULL; node = avtab_search_node_next(node, specified)) { + for (; node; node = avtab_search_node_next(node, specified)) { if (node->key.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; @@ -2050,7 +2050,7 @@ int security_set_bools(int len, int *values) policydb.bool_val_to_struct[i]->state = 0; } - for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { + for (cur = policydb.cond_list; cur; cur = cur->next) { rc = evaluate_cond_node(&policydb, cur); if (rc) goto out; @@ -2102,7 +2102,7 @@ static int security_preserve_bools(struct policydb *p) if (booldatum) booldatum->state = bvalues[i]; } - for (cur = p->cond_list; cur != NULL; cur = cur->next) { + for (cur = p->cond_list; cur; cur = cur->next) { rc = evaluate_cond_node(p, cur); if (rc) goto out; diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index a81ded10412..e817989764c 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) hvalue = SIDTAB_HASH(sid); prev = NULL; cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) { + while (cur && sid > cur->sid) { prev = cur; cur = cur->next; } @@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) + while (cur && sid > cur->sid) cur = cur->next; if (force && cur && sid == cur->sid && cur->context.len) @@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) sid = SECINITSID_UNLABELED; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) + while (cur && sid > cur->sid) cur = cur->next; if (!cur || sid != cur->sid) return NULL; @@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s, for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { rc = apply(cur->sid, &cur->context, args); if (rc) goto out; @@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s, for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { if (context_cmp(&cur->context, context)) return cur->sid; cur = cur->next; @@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s) for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; context_destroy(&temp->context); -- GitLab From c1bc667e844c2677cdf927102ab384fe7b033762 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Thu, 7 Aug 2008 16:43:38 +0200 Subject: [PATCH 0317/5416] IPVS: Add genetlink interface definitions to ip_vs.h Add IPVS Generic Netlink interface definitions to include/linux/ip_vs.h. Signed-off-by: Julius Volz Signed-off-by: Simon Horman --- include/linux/ip_vs.h | 160 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h index ec6eb49af2d..0f434a28fb5 100644 --- a/include/linux/ip_vs.h +++ b/include/linux/ip_vs.h @@ -242,4 +242,164 @@ struct ip_vs_daemon_user { int syncid; }; +/* + * + * IPVS Generic Netlink interface definitions + * + */ + +/* Generic Netlink family info */ + +#define IPVS_GENL_NAME "IPVS" +#define IPVS_GENL_VERSION 0x1 + +struct ip_vs_flags { + __be32 flags; + __be32 mask; +}; + +/* Generic Netlink command attributes */ +enum { + IPVS_CMD_UNSPEC = 0, + + IPVS_CMD_NEW_SERVICE, /* add service */ + IPVS_CMD_SET_SERVICE, /* modify service */ + IPVS_CMD_DEL_SERVICE, /* delete service */ + IPVS_CMD_GET_SERVICE, /* get service info */ + + IPVS_CMD_NEW_DEST, /* add destination */ + IPVS_CMD_SET_DEST, /* modify destination */ + IPVS_CMD_DEL_DEST, /* delete destination */ + IPVS_CMD_GET_DEST, /* get destination info */ + + IPVS_CMD_NEW_DAEMON, /* start sync daemon */ + IPVS_CMD_DEL_DAEMON, /* stop sync daemon */ + IPVS_CMD_GET_DAEMON, /* get sync daemon status */ + + IPVS_CMD_SET_CONFIG, /* set config settings */ + IPVS_CMD_GET_CONFIG, /* get config settings */ + + IPVS_CMD_SET_INFO, /* only used in GET_INFO reply */ + IPVS_CMD_GET_INFO, /* get general IPVS info */ + + IPVS_CMD_ZERO, /* zero all counters and stats */ + IPVS_CMD_FLUSH, /* flush services and dests */ + + __IPVS_CMD_MAX, +}; + +#define IPVS_CMD_MAX (__IPVS_CMD_MAX - 1) + +/* Attributes used in the first level of commands */ +enum { + IPVS_CMD_ATTR_UNSPEC = 0, + IPVS_CMD_ATTR_SERVICE, /* nested service attribute */ + IPVS_CMD_ATTR_DEST, /* nested destination attribute */ + IPVS_CMD_ATTR_DAEMON, /* nested sync daemon attribute */ + IPVS_CMD_ATTR_TIMEOUT_TCP, /* TCP connection timeout */ + IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, /* TCP FIN wait timeout */ + IPVS_CMD_ATTR_TIMEOUT_UDP, /* UDP timeout */ + __IPVS_CMD_ATTR_MAX, +}; + +#define IPVS_CMD_ATTR_MAX (__IPVS_SVC_ATTR_MAX - 1) + +/* + * Attributes used to describe a service + * + * Used inside nested attribute IPVS_CMD_ATTR_SERVICE + */ +enum { + IPVS_SVC_ATTR_UNSPEC = 0, + IPVS_SVC_ATTR_AF, /* address family */ + IPVS_SVC_ATTR_PROTOCOL, /* virtual service protocol */ + IPVS_SVC_ATTR_ADDR, /* virtual service address */ + IPVS_SVC_ATTR_PORT, /* virtual service port */ + IPVS_SVC_ATTR_FWMARK, /* firewall mark of service */ + + IPVS_SVC_ATTR_SCHED_NAME, /* name of scheduler */ + IPVS_SVC_ATTR_FLAGS, /* virtual service flags */ + IPVS_SVC_ATTR_TIMEOUT, /* persistent timeout */ + IPVS_SVC_ATTR_NETMASK, /* persistent netmask */ + + IPVS_SVC_ATTR_STATS, /* nested attribute for service stats */ + __IPVS_SVC_ATTR_MAX, +}; + +#define IPVS_SVC_ATTR_MAX (__IPVS_SVC_ATTR_MAX - 1) + +/* + * Attributes used to describe a destination (real server) + * + * Used inside nested attribute IPVS_CMD_ATTR_DEST + */ +enum { + IPVS_DEST_ATTR_UNSPEC = 0, + IPVS_DEST_ATTR_ADDR, /* real server address */ + IPVS_DEST_ATTR_PORT, /* real server port */ + + IPVS_DEST_ATTR_FWD_METHOD, /* forwarding method */ + IPVS_DEST_ATTR_WEIGHT, /* destination weight */ + + IPVS_DEST_ATTR_U_THRESH, /* upper threshold */ + IPVS_DEST_ATTR_L_THRESH, /* lower threshold */ + + IPVS_DEST_ATTR_ACTIVE_CONNS, /* active connections */ + IPVS_DEST_ATTR_INACT_CONNS, /* inactive connections */ + IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */ + + IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */ + __IPVS_DEST_ATTR_MAX, +}; + +#define IPVS_DEST_ATTR_MAX (__IPVS_DEST_ATTR_MAX - 1) + +/* + * Attributes describing a sync daemon + * + * Used inside nested attribute IPVS_CMD_ATTR_DAEMON + */ +enum { + IPVS_DAEMON_ATTR_UNSPEC = 0, + IPVS_DAEMON_ATTR_STATE, /* sync daemon state (master/backup) */ + IPVS_DAEMON_ATTR_MCAST_IFN, /* multicast interface name */ + IPVS_DAEMON_ATTR_SYNC_ID, /* SyncID we belong to */ + __IPVS_DAEMON_ATTR_MAX, +}; + +#define IPVS_DAEMON_ATTR_MAX (__IPVS_DAEMON_ATTR_MAX - 1) + +/* + * Attributes used to describe service or destination entry statistics + * + * Used inside nested attributes IPVS_SVC_ATTR_STATS and IPVS_DEST_ATTR_STATS + */ +enum { + IPVS_STATS_ATTR_UNSPEC = 0, + IPVS_STATS_ATTR_CONNS, /* connections scheduled */ + IPVS_STATS_ATTR_INPKTS, /* incoming packets */ + IPVS_STATS_ATTR_OUTPKTS, /* outgoing packets */ + IPVS_STATS_ATTR_INBYTES, /* incoming bytes */ + IPVS_STATS_ATTR_OUTBYTES, /* outgoing bytes */ + + IPVS_STATS_ATTR_CPS, /* current connection rate */ + IPVS_STATS_ATTR_INPPS, /* current in packet rate */ + IPVS_STATS_ATTR_OUTPPS, /* current out packet rate */ + IPVS_STATS_ATTR_INBPS, /* current in byte rate */ + IPVS_STATS_ATTR_OUTBPS, /* current out byte rate */ + __IPVS_STATS_ATTR_MAX, +}; + +#define IPVS_STATS_ATTR_MAX (__IPVS_STATS_ATTR_MAX - 1) + +/* Attributes used in response to IPVS_CMD_GET_INFO command */ +enum { + IPVS_INFO_ATTR_UNSPEC = 0, + IPVS_INFO_ATTR_VERSION, /* IPVS version number */ + IPVS_INFO_ATTR_CONN_TAB_SIZE, /* size of connection hash table */ + __IPVS_INFO_ATTR_MAX, +}; + +#define IPVS_INFO_ATTR_MAX (__IPVS_INFO_ATTR_MAX - 1) + #endif /* _IP_VS_H */ -- GitLab From 9a812198ae49967f239789164c55ec3e72b7e0dd Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Thu, 14 Aug 2008 14:08:44 +0200 Subject: [PATCH 0318/5416] IPVS: Add genetlink interface implementation Add the implementation of the new Generic Netlink interface to IPVS and keep the old set/getsockopt interface for userspace backwards compatibility. Signed-off-by: Julius Volz Acked-by: Sven Wegener Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_ctl.c | 875 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 875 insertions(+) diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 6379705a8dc..d1dbd8b311b 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -2320,6 +2321,872 @@ static struct nf_sockopt_ops ip_vs_sockopts = { .owner = THIS_MODULE, }; +/* + * Generic Netlink interface + */ + +/* IPVS genetlink family */ +static struct genl_family ip_vs_genl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = IPVS_GENL_NAME, + .version = IPVS_GENL_VERSION, + .maxattr = IPVS_CMD_MAX, +}; + +/* Policy used for first-level command attributes */ +static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = { + [IPVS_CMD_ATTR_SERVICE] = { .type = NLA_NESTED }, + [IPVS_CMD_ATTR_DEST] = { .type = NLA_NESTED }, + [IPVS_CMD_ATTR_DAEMON] = { .type = NLA_NESTED }, + [IPVS_CMD_ATTR_TIMEOUT_TCP] = { .type = NLA_U32 }, + [IPVS_CMD_ATTR_TIMEOUT_TCP_FIN] = { .type = NLA_U32 }, + [IPVS_CMD_ATTR_TIMEOUT_UDP] = { .type = NLA_U32 }, +}; + +/* Policy used for attributes in nested attribute IPVS_CMD_ATTR_DAEMON */ +static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { + [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 }, + [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING, + .len = IP_VS_IFNAME_MAXLEN }, + [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 }, +}; + +/* Policy used for attributes in nested attribute IPVS_CMD_ATTR_SERVICE */ +static const struct nla_policy ip_vs_svc_policy[IPVS_SVC_ATTR_MAX + 1] = { + [IPVS_SVC_ATTR_AF] = { .type = NLA_U16 }, + [IPVS_SVC_ATTR_PROTOCOL] = { .type = NLA_U16 }, + [IPVS_SVC_ATTR_ADDR] = { .type = NLA_BINARY, + .len = sizeof(union nf_inet_addr) }, + [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 }, + [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 }, + [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING, + .len = IP_VS_SCHEDNAME_MAXLEN }, + [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY, + .len = sizeof(struct ip_vs_flags) }, + [IPVS_SVC_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPVS_SVC_ATTR_NETMASK] = { .type = NLA_U32 }, + [IPVS_SVC_ATTR_STATS] = { .type = NLA_NESTED }, +}; + +/* Policy used for attributes in nested attribute IPVS_CMD_ATTR_DEST */ +static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = { + [IPVS_DEST_ATTR_ADDR] = { .type = NLA_BINARY, + .len = sizeof(union nf_inet_addr) }, + [IPVS_DEST_ATTR_PORT] = { .type = NLA_U16 }, + [IPVS_DEST_ATTR_FWD_METHOD] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_WEIGHT] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_U_THRESH] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_L_THRESH] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_ACTIVE_CONNS] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 }, + [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED }, +}; + +static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, + struct ip_vs_stats *stats) +{ + struct nlattr *nl_stats = nla_nest_start(skb, container_type); + if (!nl_stats) + return -EMSGSIZE; + + spin_lock_bh(&stats->lock); + + NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, stats->conns); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, stats->inpkts); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, stats->outpkts); + NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, stats->inbytes); + NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, stats->outbytes); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, stats->cps); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, stats->inpps); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, stats->outpps); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, stats->inbps); + NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, stats->outbps); + + spin_unlock_bh(&stats->lock); + + nla_nest_end(skb, nl_stats); + + return 0; + +nla_put_failure: + spin_unlock_bh(&stats->lock); + nla_nest_cancel(skb, nl_stats); + return -EMSGSIZE; +} + +static int ip_vs_genl_fill_service(struct sk_buff *skb, + struct ip_vs_service *svc) +{ + struct nlattr *nl_service; + struct ip_vs_flags flags = { .flags = svc->flags, + .mask = ~0 }; + + nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE); + if (!nl_service) + return -EMSGSIZE; + + NLA_PUT_U16(skb, IPVS_SVC_ATTR_AF, AF_INET); + + if (svc->fwmark) { + NLA_PUT_U32(skb, IPVS_SVC_ATTR_FWMARK, svc->fwmark); + } else { + NLA_PUT_U16(skb, IPVS_SVC_ATTR_PROTOCOL, svc->protocol); + NLA_PUT(skb, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &svc->addr); + NLA_PUT_U16(skb, IPVS_SVC_ATTR_PORT, svc->port); + } + + NLA_PUT_STRING(skb, IPVS_SVC_ATTR_SCHED_NAME, svc->scheduler->name); + NLA_PUT(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags); + NLA_PUT_U32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ); + NLA_PUT_U32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask); + + if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &svc->stats)) + goto nla_put_failure; + + nla_nest_end(skb, nl_service); + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nl_service); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_service(struct sk_buff *skb, + struct ip_vs_service *svc, + struct netlink_callback *cb) +{ + void *hdr; + + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, + &ip_vs_genl_family, NLM_F_MULTI, + IPVS_CMD_NEW_SERVICE); + if (!hdr) + return -EMSGSIZE; + + if (ip_vs_genl_fill_service(skb, svc) < 0) + goto nla_put_failure; + + return genlmsg_end(skb, hdr); + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_services(struct sk_buff *skb, + struct netlink_callback *cb) +{ + int idx = 0, i; + int start = cb->args[0]; + struct ip_vs_service *svc; + + mutex_lock(&__ip_vs_mutex); + for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { + list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) { + if (++idx <= start) + continue; + if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { + idx--; + goto nla_put_failure; + } + } + } + + for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { + list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) { + if (++idx <= start) + continue; + if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { + idx--; + goto nla_put_failure; + } + } + } + +nla_put_failure: + mutex_unlock(&__ip_vs_mutex); + cb->args[0] = idx; + + return skb->len; +} + +static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, + struct nlattr *nla, int full_entry) +{ + struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1]; + struct nlattr *nla_af, *nla_port, *nla_fwmark, *nla_protocol, *nla_addr; + + /* Parse mandatory identifying service fields first */ + if (nla == NULL || + nla_parse_nested(attrs, IPVS_SVC_ATTR_MAX, nla, ip_vs_svc_policy)) + return -EINVAL; + + nla_af = attrs[IPVS_SVC_ATTR_AF]; + nla_protocol = attrs[IPVS_SVC_ATTR_PROTOCOL]; + nla_addr = attrs[IPVS_SVC_ATTR_ADDR]; + nla_port = attrs[IPVS_SVC_ATTR_PORT]; + nla_fwmark = attrs[IPVS_SVC_ATTR_FWMARK]; + + if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr)))) + return -EINVAL; + + /* For now, only support IPv4 */ + if (nla_get_u16(nla_af) != AF_INET) + return -EAFNOSUPPORT; + + if (nla_fwmark) { + usvc->protocol = IPPROTO_TCP; + usvc->fwmark = nla_get_u32(nla_fwmark); + } else { + usvc->protocol = nla_get_u16(nla_protocol); + nla_memcpy(&usvc->addr, nla_addr, sizeof(usvc->addr)); + usvc->port = nla_get_u16(nla_port); + usvc->fwmark = 0; + } + + /* If a full entry was requested, check for the additional fields */ + if (full_entry) { + struct nlattr *nla_sched, *nla_flags, *nla_timeout, + *nla_netmask; + struct ip_vs_flags flags; + struct ip_vs_service *svc; + + nla_sched = attrs[IPVS_SVC_ATTR_SCHED_NAME]; + nla_flags = attrs[IPVS_SVC_ATTR_FLAGS]; + nla_timeout = attrs[IPVS_SVC_ATTR_TIMEOUT]; + nla_netmask = attrs[IPVS_SVC_ATTR_NETMASK]; + + if (!(nla_sched && nla_flags && nla_timeout && nla_netmask)) + return -EINVAL; + + nla_memcpy(&flags, nla_flags, sizeof(flags)); + + /* prefill flags from service if it already exists */ + if (usvc->fwmark) + svc = __ip_vs_svc_fwm_get(usvc->fwmark); + else + svc = __ip_vs_service_get(usvc->protocol, usvc->addr, + usvc->port); + if (svc) { + usvc->flags = svc->flags; + ip_vs_service_put(svc); + } else + usvc->flags = 0; + + /* set new flags from userland */ + usvc->flags = (usvc->flags & ~flags.mask) | + (flags.flags & flags.mask); + + strlcpy(usvc->sched_name, nla_data(nla_sched), + sizeof(usvc->sched_name)); + usvc->timeout = nla_get_u32(nla_timeout); + usvc->netmask = nla_get_u32(nla_netmask); + } + + return 0; +} + +static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) +{ + struct ip_vs_service_user usvc; + int ret; + + ret = ip_vs_genl_parse_service(&usvc, nla, 0); + if (ret) + return ERR_PTR(ret); + + if (usvc.fwmark) + return __ip_vs_svc_fwm_get(usvc.fwmark); + else + return __ip_vs_service_get(usvc.protocol, usvc.addr, + usvc.port); +} + +static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) +{ + struct nlattr *nl_dest; + + nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST); + if (!nl_dest) + return -EMSGSIZE; + + NLA_PUT(skb, IPVS_DEST_ATTR_ADDR, sizeof(dest->addr), &dest->addr); + NLA_PUT_U16(skb, IPVS_DEST_ATTR_PORT, dest->port); + + NLA_PUT_U32(skb, IPVS_DEST_ATTR_FWD_METHOD, + atomic_read(&dest->conn_flags) & IP_VS_CONN_F_FWD_MASK); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_WEIGHT, atomic_read(&dest->weight)); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS, + atomic_read(&dest->activeconns)); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_INACT_CONNS, + atomic_read(&dest->inactconns)); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, + atomic_read(&dest->persistconns)); + + if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats)) + goto nla_put_failure; + + nla_nest_end(skb, nl_dest); + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nl_dest); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_dest(struct sk_buff *skb, struct ip_vs_dest *dest, + struct netlink_callback *cb) +{ + void *hdr; + + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, + &ip_vs_genl_family, NLM_F_MULTI, + IPVS_CMD_NEW_DEST); + if (!hdr) + return -EMSGSIZE; + + if (ip_vs_genl_fill_dest(skb, dest) < 0) + goto nla_put_failure; + + return genlmsg_end(skb, hdr); + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_dests(struct sk_buff *skb, + struct netlink_callback *cb) +{ + int idx = 0; + int start = cb->args[0]; + struct ip_vs_service *svc; + struct ip_vs_dest *dest; + struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; + + mutex_lock(&__ip_vs_mutex); + + /* Try to find the service for which to dump destinations */ + if (nlmsg_parse(cb->nlh, GENL_HDRLEN, attrs, + IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy)) + goto out_err; + + svc = ip_vs_genl_find_service(attrs[IPVS_CMD_ATTR_SERVICE]); + if (IS_ERR(svc) || svc == NULL) + goto out_err; + + /* Dump the destinations */ + list_for_each_entry(dest, &svc->destinations, n_list) { + if (++idx <= start) + continue; + if (ip_vs_genl_dump_dest(skb, dest, cb) < 0) { + idx--; + goto nla_put_failure; + } + } + +nla_put_failure: + cb->args[0] = idx; + ip_vs_service_put(svc); + +out_err: + mutex_unlock(&__ip_vs_mutex); + + return skb->len; +} + +static int ip_vs_genl_parse_dest(struct ip_vs_dest_user *udest, + struct nlattr *nla, int full_entry) +{ + struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; + struct nlattr *nla_addr, *nla_port; + + /* Parse mandatory identifying destination fields first */ + if (nla == NULL || + nla_parse_nested(attrs, IPVS_DEST_ATTR_MAX, nla, ip_vs_dest_policy)) + return -EINVAL; + + nla_addr = attrs[IPVS_DEST_ATTR_ADDR]; + nla_port = attrs[IPVS_DEST_ATTR_PORT]; + + if (!(nla_addr && nla_port)) + return -EINVAL; + + nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr)); + udest->port = nla_get_u16(nla_port); + + /* If a full entry was requested, check for the additional fields */ + if (full_entry) { + struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh, + *nla_l_thresh; + + nla_fwd = attrs[IPVS_DEST_ATTR_FWD_METHOD]; + nla_weight = attrs[IPVS_DEST_ATTR_WEIGHT]; + nla_u_thresh = attrs[IPVS_DEST_ATTR_U_THRESH]; + nla_l_thresh = attrs[IPVS_DEST_ATTR_L_THRESH]; + + if (!(nla_fwd && nla_weight && nla_u_thresh && nla_l_thresh)) + return -EINVAL; + + udest->conn_flags = nla_get_u32(nla_fwd) + & IP_VS_CONN_F_FWD_MASK; + udest->weight = nla_get_u32(nla_weight); + udest->u_threshold = nla_get_u32(nla_u_thresh); + udest->l_threshold = nla_get_u32(nla_l_thresh); + } + + return 0; +} + +static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __be32 state, + const char *mcast_ifn, __be32 syncid) +{ + struct nlattr *nl_daemon; + + nl_daemon = nla_nest_start(skb, IPVS_CMD_ATTR_DAEMON); + if (!nl_daemon) + return -EMSGSIZE; + + NLA_PUT_U32(skb, IPVS_DAEMON_ATTR_STATE, state); + NLA_PUT_STRING(skb, IPVS_DAEMON_ATTR_MCAST_IFN, mcast_ifn); + NLA_PUT_U32(skb, IPVS_DAEMON_ATTR_SYNC_ID, syncid); + + nla_nest_end(skb, nl_daemon); + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nl_daemon); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __be32 state, + const char *mcast_ifn, __be32 syncid, + struct netlink_callback *cb) +{ + void *hdr; + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, + &ip_vs_genl_family, NLM_F_MULTI, + IPVS_CMD_NEW_DAEMON); + if (!hdr) + return -EMSGSIZE; + + if (ip_vs_genl_fill_daemon(skb, state, mcast_ifn, syncid)) + goto nla_put_failure; + + return genlmsg_end(skb, hdr); + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +static int ip_vs_genl_dump_daemons(struct sk_buff *skb, + struct netlink_callback *cb) +{ + mutex_lock(&__ip_vs_mutex); + if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { + if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, + ip_vs_master_mcast_ifn, + ip_vs_master_syncid, cb) < 0) + goto nla_put_failure; + + cb->args[0] = 1; + } + + if ((ip_vs_sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) { + if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP, + ip_vs_backup_mcast_ifn, + ip_vs_backup_syncid, cb) < 0) + goto nla_put_failure; + + cb->args[1] = 1; + } + +nla_put_failure: + mutex_unlock(&__ip_vs_mutex); + + return skb->len; +} + +static int ip_vs_genl_new_daemon(struct nlattr **attrs) +{ + if (!(attrs[IPVS_DAEMON_ATTR_STATE] && + attrs[IPVS_DAEMON_ATTR_MCAST_IFN] && + attrs[IPVS_DAEMON_ATTR_SYNC_ID])) + return -EINVAL; + + return start_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]), + nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]), + nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID])); +} + +static int ip_vs_genl_del_daemon(struct nlattr **attrs) +{ + if (!attrs[IPVS_DAEMON_ATTR_STATE]) + return -EINVAL; + + return stop_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); +} + +static int ip_vs_genl_set_config(struct nlattr **attrs) +{ + struct ip_vs_timeout_user t; + + __ip_vs_get_timeouts(&t); + + if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]) + t.tcp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]); + + if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP_FIN]) + t.tcp_fin_timeout = + nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP_FIN]); + + if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]) + t.udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]); + + return ip_vs_set_timeout(&t); +} + +static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) +{ + struct ip_vs_service *svc = NULL; + struct ip_vs_service_user usvc; + struct ip_vs_dest_user udest; + int ret = 0, cmd; + int need_full_svc = 0, need_full_dest = 0; + + cmd = info->genlhdr->cmd; + + mutex_lock(&__ip_vs_mutex); + + if (cmd == IPVS_CMD_FLUSH) { + ret = ip_vs_flush(); + goto out; + } else if (cmd == IPVS_CMD_SET_CONFIG) { + ret = ip_vs_genl_set_config(info->attrs); + goto out; + } else if (cmd == IPVS_CMD_NEW_DAEMON || + cmd == IPVS_CMD_DEL_DAEMON) { + + struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1]; + + if (!info->attrs[IPVS_CMD_ATTR_DAEMON] || + nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX, + info->attrs[IPVS_CMD_ATTR_DAEMON], + ip_vs_daemon_policy)) { + ret = -EINVAL; + goto out; + } + + if (cmd == IPVS_CMD_NEW_DAEMON) + ret = ip_vs_genl_new_daemon(daemon_attrs); + else + ret = ip_vs_genl_del_daemon(daemon_attrs); + goto out; + } else if (cmd == IPVS_CMD_ZERO && + !info->attrs[IPVS_CMD_ATTR_SERVICE]) { + ret = ip_vs_zero_all(); + goto out; + } + + /* All following commands require a service argument, so check if we + * received a valid one. We need a full service specification when + * adding / editing a service. Only identifying members otherwise. */ + if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE) + need_full_svc = 1; + + ret = ip_vs_genl_parse_service(&usvc, + info->attrs[IPVS_CMD_ATTR_SERVICE], + need_full_svc); + if (ret) + goto out; + + /* Lookup the exact service by or fwmark */ + if (usvc.fwmark == 0) + svc = __ip_vs_service_get(usvc.protocol, usvc.addr, usvc.port); + else + svc = __ip_vs_svc_fwm_get(usvc.fwmark); + + /* Unless we're adding a new service, the service must already exist */ + if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) { + ret = -ESRCH; + goto out; + } + + /* Destination commands require a valid destination argument. For + * adding / editing a destination, we need a full destination + * specification. */ + if (cmd == IPVS_CMD_NEW_DEST || cmd == IPVS_CMD_SET_DEST || + cmd == IPVS_CMD_DEL_DEST) { + if (cmd != IPVS_CMD_DEL_DEST) + need_full_dest = 1; + + ret = ip_vs_genl_parse_dest(&udest, + info->attrs[IPVS_CMD_ATTR_DEST], + need_full_dest); + if (ret) + goto out; + } + + switch (cmd) { + case IPVS_CMD_NEW_SERVICE: + if (svc == NULL) + ret = ip_vs_add_service(&usvc, &svc); + else + ret = -EEXIST; + break; + case IPVS_CMD_SET_SERVICE: + ret = ip_vs_edit_service(svc, &usvc); + break; + case IPVS_CMD_DEL_SERVICE: + ret = ip_vs_del_service(svc); + break; + case IPVS_CMD_NEW_DEST: + ret = ip_vs_add_dest(svc, &udest); + break; + case IPVS_CMD_SET_DEST: + ret = ip_vs_edit_dest(svc, &udest); + break; + case IPVS_CMD_DEL_DEST: + ret = ip_vs_del_dest(svc, &udest); + break; + case IPVS_CMD_ZERO: + ret = ip_vs_zero_service(svc); + break; + default: + ret = -EINVAL; + } + +out: + if (svc) + ip_vs_service_put(svc); + mutex_unlock(&__ip_vs_mutex); + + return ret; +} + +static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) +{ + struct sk_buff *msg; + void *reply; + int ret, cmd, reply_cmd; + + cmd = info->genlhdr->cmd; + + if (cmd == IPVS_CMD_GET_SERVICE) + reply_cmd = IPVS_CMD_NEW_SERVICE; + else if (cmd == IPVS_CMD_GET_INFO) + reply_cmd = IPVS_CMD_SET_INFO; + else if (cmd == IPVS_CMD_GET_CONFIG) + reply_cmd = IPVS_CMD_SET_CONFIG; + else { + IP_VS_ERR("unknown Generic Netlink command\n"); + return -EINVAL; + } + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + mutex_lock(&__ip_vs_mutex); + + reply = genlmsg_put_reply(msg, info, &ip_vs_genl_family, 0, reply_cmd); + if (reply == NULL) + goto nla_put_failure; + + switch (cmd) { + case IPVS_CMD_GET_SERVICE: + { + struct ip_vs_service *svc; + + svc = ip_vs_genl_find_service(info->attrs[IPVS_CMD_ATTR_SERVICE]); + if (IS_ERR(svc)) { + ret = PTR_ERR(svc); + goto out_err; + } else if (svc) { + ret = ip_vs_genl_fill_service(msg, svc); + ip_vs_service_put(svc); + if (ret) + goto nla_put_failure; + } else { + ret = -ESRCH; + goto out_err; + } + + break; + } + + case IPVS_CMD_GET_CONFIG: + { + struct ip_vs_timeout_user t; + + __ip_vs_get_timeouts(&t); +#ifdef CONFIG_IP_VS_PROTO_TCP + NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, t.tcp_timeout); + NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, + t.tcp_fin_timeout); +#endif +#ifdef CONFIG_IP_VS_PROTO_UDP + NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_UDP, t.udp_timeout); +#endif + + break; + } + + case IPVS_CMD_GET_INFO: + NLA_PUT_U32(msg, IPVS_INFO_ATTR_VERSION, IP_VS_VERSION_CODE); + NLA_PUT_U32(msg, IPVS_INFO_ATTR_CONN_TAB_SIZE, + IP_VS_CONN_TAB_SIZE); + break; + } + + genlmsg_end(msg, reply); + ret = genlmsg_unicast(msg, info->snd_pid); + goto out; + +nla_put_failure: + IP_VS_ERR("not enough space in Netlink message\n"); + ret = -EMSGSIZE; + +out_err: + nlmsg_free(msg); +out: + mutex_unlock(&__ip_vs_mutex); + + return ret; +} + + +static struct genl_ops ip_vs_genl_ops[] __read_mostly = { + { + .cmd = IPVS_CMD_NEW_SERVICE, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_SET_SERVICE, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_DEL_SERVICE, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_GET_SERVICE, + .flags = GENL_ADMIN_PERM, + .doit = ip_vs_genl_get_cmd, + .dumpit = ip_vs_genl_dump_services, + .policy = ip_vs_cmd_policy, + }, + { + .cmd = IPVS_CMD_NEW_DEST, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_SET_DEST, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_DEL_DEST, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_GET_DEST, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .dumpit = ip_vs_genl_dump_dests, + }, + { + .cmd = IPVS_CMD_NEW_DAEMON, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_DEL_DAEMON, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_GET_DAEMON, + .flags = GENL_ADMIN_PERM, + .dumpit = ip_vs_genl_dump_daemons, + }, + { + .cmd = IPVS_CMD_SET_CONFIG, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_GET_CONFIG, + .flags = GENL_ADMIN_PERM, + .doit = ip_vs_genl_get_cmd, + }, + { + .cmd = IPVS_CMD_GET_INFO, + .flags = GENL_ADMIN_PERM, + .doit = ip_vs_genl_get_cmd, + }, + { + .cmd = IPVS_CMD_ZERO, + .flags = GENL_ADMIN_PERM, + .policy = ip_vs_cmd_policy, + .doit = ip_vs_genl_set_cmd, + }, + { + .cmd = IPVS_CMD_FLUSH, + .flags = GENL_ADMIN_PERM, + .doit = ip_vs_genl_set_cmd, + }, +}; + +static int __init ip_vs_genl_register(void) +{ + int ret, i; + + ret = genl_register_family(&ip_vs_genl_family); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(ip_vs_genl_ops); i++) { + ret = genl_register_ops(&ip_vs_genl_family, &ip_vs_genl_ops[i]); + if (ret) + goto err_out; + } + return 0; + +err_out: + genl_unregister_family(&ip_vs_genl_family); + return ret; +} + +static void ip_vs_genl_unregister(void) +{ + genl_unregister_family(&ip_vs_genl_family); +} + +/* End of Generic Netlink interface definitions */ + int __init ip_vs_control_init(void) { @@ -2334,6 +3201,13 @@ int __init ip_vs_control_init(void) return ret; } + ret = ip_vs_genl_register(); + if (ret) { + IP_VS_ERR("cannot register Generic Netlink interface.\n"); + nf_unregister_sockopt(&ip_vs_sockopts); + return ret; + } + proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops); proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops); @@ -2368,6 +3242,7 @@ void ip_vs_control_cleanup(void) unregister_sysctl_table(sysctl_header); proc_net_remove(&init_net, "ip_vs_stats"); proc_net_remove(&init_net, "ip_vs"); + ip_vs_genl_unregister(); nf_unregister_sockopt(&ip_vs_sockopts); LeaveFunction(2); } -- GitLab From 82dfb6f32219d8e6cf6b979a520cb2b11d977d4e Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Mon, 11 Aug 2008 19:36:06 +0000 Subject: [PATCH 0319/5416] ipvs: Only call init_service, update_service and done_service for schedulers if defined There are schedulers that only schedule based on data available in the service or destination structures and they don't need any persistent storage or initialization routine. These schedulers currently provide dummy functions for the init_service, update_service and/or done_service functions. For the init_service and done_service cases we already have code that only calls these functions, if the scheduler provides them. Do the same for the update_service case and remove the dummy functions from all schedulers. Signed-off-by: Sven Wegener Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_ctl.c | 21 ++++++++++++--------- net/ipv4/ipvs/ip_vs_lblc.c | 7 ------- net/ipv4/ipvs/ip_vs_lblcr.c | 7 ------- net/ipv4/ipvs/ip_vs_lc.c | 21 --------------------- net/ipv4/ipvs/ip_vs_nq.c | 24 ------------------------ net/ipv4/ipvs/ip_vs_rr.c | 7 ------- net/ipv4/ipvs/ip_vs_sed.c | 24 ------------------------ net/ipv4/ipvs/ip_vs_wlc.c | 24 ------------------------ 8 files changed, 12 insertions(+), 123 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index d1dbd8b311b..ede101eeec1 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -869,7 +869,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) svc->num_dests++; /* call the update_service function of its scheduler */ - svc->scheduler->update_service(svc); + if (svc->scheduler->update_service) + svc->scheduler->update_service(svc); write_unlock_bh(&__ip_vs_svc_lock); return 0; @@ -899,7 +900,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) svc->num_dests++; /* call the update_service function of its scheduler */ - svc->scheduler->update_service(svc); + if (svc->scheduler->update_service) + svc->scheduler->update_service(svc); write_unlock_bh(&__ip_vs_svc_lock); @@ -949,7 +951,8 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1); /* call the update_service, because server weight may be changed */ - svc->scheduler->update_service(svc); + if (svc->scheduler->update_service) + svc->scheduler->update_service(svc); write_unlock_bh(&__ip_vs_svc_lock); @@ -1012,12 +1015,12 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc, */ list_del(&dest->n_list); svc->num_dests--; - if (svcupd) { - /* - * Call the update_service function of its scheduler - */ - svc->scheduler->update_service(svc); - } + + /* + * Call the update_service function of its scheduler + */ + if (svcupd && svc->scheduler->update_service) + svc->scheduler->update_service(svc); } diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index 7a6a319f544..4a14d069f8a 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c @@ -388,12 +388,6 @@ static int ip_vs_lblc_done_svc(struct ip_vs_service *svc) } -static int ip_vs_lblc_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline struct ip_vs_dest * __ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph) { @@ -542,7 +536,6 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler = .n_list = LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list), .init_service = ip_vs_lblc_init_svc, .done_service = ip_vs_lblc_done_svc, - .update_service = ip_vs_lblc_update_svc, .schedule = ip_vs_lblc_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index c234e73968a..46b870385b8 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c @@ -572,12 +572,6 @@ static int ip_vs_lblcr_done_svc(struct ip_vs_service *svc) } -static int ip_vs_lblcr_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline struct ip_vs_dest * __ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph) { @@ -731,7 +725,6 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler = .n_list = LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list), .init_service = ip_vs_lblcr_init_svc, .done_service = ip_vs_lblcr_done_svc, - .update_service = ip_vs_lblcr_update_svc, .schedule = ip_vs_lblcr_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_lc.c b/net/ipv4/ipvs/ip_vs_lc.c index ebcdbf75ac6..2c3de1b6351 100644 --- a/net/ipv4/ipvs/ip_vs_lc.c +++ b/net/ipv4/ipvs/ip_vs_lc.c @@ -20,24 +20,6 @@ #include -static int ip_vs_lc_init_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int ip_vs_lc_done_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int ip_vs_lc_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline unsigned int ip_vs_lc_dest_overhead(struct ip_vs_dest *dest) { @@ -99,9 +81,6 @@ static struct ip_vs_scheduler ip_vs_lc_scheduler = { .refcnt = ATOMIC_INIT(0), .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list), - .init_service = ip_vs_lc_init_svc, - .done_service = ip_vs_lc_done_svc, - .update_service = ip_vs_lc_update_svc, .schedule = ip_vs_lc_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_nq.c b/net/ipv4/ipvs/ip_vs_nq.c index 92f3a677003..5330d5a2de1 100644 --- a/net/ipv4/ipvs/ip_vs_nq.c +++ b/net/ipv4/ipvs/ip_vs_nq.c @@ -37,27 +37,6 @@ #include -static int -ip_vs_nq_init_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_nq_done_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_nq_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline unsigned int ip_vs_nq_dest_overhead(struct ip_vs_dest *dest) { @@ -137,9 +116,6 @@ static struct ip_vs_scheduler ip_vs_nq_scheduler = .refcnt = ATOMIC_INIT(0), .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list), - .init_service = ip_vs_nq_init_svc, - .done_service = ip_vs_nq_done_svc, - .update_service = ip_vs_nq_update_svc, .schedule = ip_vs_nq_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_rr.c b/net/ipv4/ipvs/ip_vs_rr.c index 358110d17e5..f7492911753 100644 --- a/net/ipv4/ipvs/ip_vs_rr.c +++ b/net/ipv4/ipvs/ip_vs_rr.c @@ -32,12 +32,6 @@ static int ip_vs_rr_init_svc(struct ip_vs_service *svc) } -static int ip_vs_rr_done_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static int ip_vs_rr_update_svc(struct ip_vs_service *svc) { svc->sched_data = &svc->destinations; @@ -96,7 +90,6 @@ static struct ip_vs_scheduler ip_vs_rr_scheduler = { .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list), .init_service = ip_vs_rr_init_svc, - .done_service = ip_vs_rr_done_svc, .update_service = ip_vs_rr_update_svc, .schedule = ip_vs_rr_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_sed.c b/net/ipv4/ipvs/ip_vs_sed.c index 77663d84cbd..53f73bea66c 100644 --- a/net/ipv4/ipvs/ip_vs_sed.c +++ b/net/ipv4/ipvs/ip_vs_sed.c @@ -41,27 +41,6 @@ #include -static int -ip_vs_sed_init_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_sed_done_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_sed_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline unsigned int ip_vs_sed_dest_overhead(struct ip_vs_dest *dest) { @@ -139,9 +118,6 @@ static struct ip_vs_scheduler ip_vs_sed_scheduler = .refcnt = ATOMIC_INIT(0), .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list), - .init_service = ip_vs_sed_init_svc, - .done_service = ip_vs_sed_done_svc, - .update_service = ip_vs_sed_update_svc, .schedule = ip_vs_sed_schedule, }; diff --git a/net/ipv4/ipvs/ip_vs_wlc.c b/net/ipv4/ipvs/ip_vs_wlc.c index 9b0ef86bb1f..df7ad8d7476 100644 --- a/net/ipv4/ipvs/ip_vs_wlc.c +++ b/net/ipv4/ipvs/ip_vs_wlc.c @@ -25,27 +25,6 @@ #include -static int -ip_vs_wlc_init_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_wlc_done_svc(struct ip_vs_service *svc) -{ - return 0; -} - - -static int -ip_vs_wlc_update_svc(struct ip_vs_service *svc) -{ - return 0; -} - - static inline unsigned int ip_vs_wlc_dest_overhead(struct ip_vs_dest *dest) { @@ -127,9 +106,6 @@ static struct ip_vs_scheduler ip_vs_wlc_scheduler = .refcnt = ATOMIC_INIT(0), .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list), - .init_service = ip_vs_wlc_init_svc, - .done_service = ip_vs_wlc_done_svc, - .update_service = ip_vs_wlc_update_svc, .schedule = ip_vs_wlc_schedule, }; -- GitLab From a919cf4b6b499416b6e2247dbc79196c4325f2e6 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Thu, 14 Aug 2008 00:47:16 +0200 Subject: [PATCH 0320/5416] ipvs: Create init functions for estimator code Commit 8ab19ea36c5c5340ff598e4d15fc084eb65671dc ("ipvs: Fix possible deadlock in estimator code") fixed a deadlock condition, but that condition can only happen during unload of IPVS, because during normal operation there is at least our global stats structure in the estimator list. The mod_timer() and del_timer_sync() calls are actually initialization and cleanup code in disguise. Let's make it explicit and move them to their own init and cleanup function. Signed-off-by: Sven Wegener Signed-off-by: Simon Horman --- include/net/ip_vs.h | 2 ++ net/ipv4/ipvs/ip_vs_core.c | 8 ++++++-- net/ipv4/ipvs/ip_vs_est.c | 18 +++++++++++------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 7312c3dd309..a25ad243031 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -683,6 +683,8 @@ extern void ip_vs_sync_conn(struct ip_vs_conn *cp); /* * IPVS rate estimator prototypes (from ip_vs_est.c) */ +extern int ip_vs_estimator_init(void); +extern void ip_vs_estimator_cleanup(void); extern void ip_vs_new_estimator(struct ip_vs_stats *stats); extern void ip_vs_kill_estimator(struct ip_vs_stats *stats); extern void ip_vs_zero_estimator(struct ip_vs_stats *stats); diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index a7879eafc3b..9fbf0a6d739 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -1070,10 +1070,12 @@ static int __init ip_vs_init(void) { int ret; + ip_vs_estimator_init(); + ret = ip_vs_control_init(); if (ret < 0) { IP_VS_ERR("can't setup control.\n"); - goto cleanup_nothing; + goto cleanup_estimator; } ip_vs_protocol_init(); @@ -1106,7 +1108,8 @@ static int __init ip_vs_init(void) cleanup_protocol: ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); - cleanup_nothing: + cleanup_estimator: + ip_vs_estimator_cleanup(); return ret; } @@ -1117,6 +1120,7 @@ static void __exit ip_vs_cleanup(void) ip_vs_app_cleanup(); ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); + ip_vs_estimator_cleanup(); IP_VS_INFO("ipvs unloaded.\n"); } diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c index 5a20f93bd7f..4fb620ec208 100644 --- a/net/ipv4/ipvs/ip_vs_est.c +++ b/net/ipv4/ipvs/ip_vs_est.c @@ -124,8 +124,6 @@ void ip_vs_new_estimator(struct ip_vs_stats *stats) est->outbps = stats->outbps<<5; spin_lock_bh(&est_lock); - if (list_empty(&est_list)) - mod_timer(&est_timer, jiffies + 2 * HZ); list_add(&est->list, &est_list); spin_unlock_bh(&est_lock); } @@ -136,11 +134,6 @@ void ip_vs_kill_estimator(struct ip_vs_stats *stats) spin_lock_bh(&est_lock); list_del(&est->list); - while (list_empty(&est_list) && try_to_del_timer_sync(&est_timer) < 0) { - spin_unlock_bh(&est_lock); - cpu_relax(); - spin_lock_bh(&est_lock); - } spin_unlock_bh(&est_lock); } @@ -160,3 +153,14 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats) est->inbps = 0; est->outbps = 0; } + +int __init ip_vs_estimator_init(void) +{ + mod_timer(&est_timer, jiffies + 2 * HZ); + return 0; +} + +void ip_vs_estimator_cleanup(void) +{ + del_timer_sync(&est_timer); +} -- GitLab From 4a031b0e6acd8a8c23725ceb5db6a0aa5c4e231f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 15 Aug 2008 09:26:15 +1000 Subject: [PATCH 0321/5416] ipvs: rename __ip_vs_wlc_schedule in lblc and lblcr schedulers For the sake of clarity, rename __ip_vs_wlc_schedule() in lblc.c to __ip_vs_lblc_schedule() and the version in lblcr.c to __ip_vs_lblc_schedule(). I guess the original name stuck from a copy and paste. Cc: Sven Wegener Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_lblc.c | 6 +++--- net/ipv4/ipvs/ip_vs_lblcr.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index 4a14d069f8a..b9b334cccf3 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c @@ -389,7 +389,7 @@ static int ip_vs_lblc_done_svc(struct ip_vs_service *svc) static inline struct ip_vs_dest * -__ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph) +__ip_vs_lblc_schedule(struct ip_vs_service *svc, struct iphdr *iph) { struct ip_vs_dest *dest, *least; int loh, doh; @@ -488,7 +488,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) tbl = (struct ip_vs_lblc_table *)svc->sched_data; en = ip_vs_lblc_get(tbl, iph->daddr); if (en == NULL) { - dest = __ip_vs_wlc_schedule(svc, iph); + dest = __ip_vs_lblc_schedule(svc, iph); if (dest == NULL) { IP_VS_DBG(1, "no destination available\n"); return NULL; @@ -503,7 +503,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) if (!(dest->flags & IP_VS_DEST_F_AVAILABLE) || atomic_read(&dest->weight) <= 0 || is_overloaded(dest, svc)) { - dest = __ip_vs_wlc_schedule(svc, iph); + dest = __ip_vs_lblc_schedule(svc, iph); if (dest == NULL) { IP_VS_DBG(1, "no destination available\n"); return NULL; diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index 46b870385b8..f1c84503689 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c @@ -573,7 +573,7 @@ static int ip_vs_lblcr_done_svc(struct ip_vs_service *svc) static inline struct ip_vs_dest * -__ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph) +__ip_vs_lblcr_schedule(struct ip_vs_service *svc, struct iphdr *iph) { struct ip_vs_dest *dest, *least; int loh, doh; @@ -673,7 +673,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) tbl = (struct ip_vs_lblcr_table *)svc->sched_data; en = ip_vs_lblcr_get(tbl, iph->daddr); if (en == NULL) { - dest = __ip_vs_wlc_schedule(svc, iph); + dest = __ip_vs_lblcr_schedule(svc, iph); if (dest == NULL) { IP_VS_DBG(1, "no destination available\n"); return NULL; @@ -687,7 +687,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) } else { dest = ip_vs_dest_set_min(&en->set); if (!dest || is_overloaded(dest, svc)) { - dest = __ip_vs_wlc_schedule(svc, iph); + dest = __ip_vs_lblcr_schedule(svc, iph); if (dest == NULL) { IP_VS_DBG(1, "no destination available\n"); return NULL; -- GitLab From 8a8f2662c535e1dedced896cc68cb8473fd98fa0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Aug 2008 15:27:43 +0200 Subject: [PATCH 0322/5416] ALSA: Add missing description of usb-audio parameters Added the missing description of module parameters of usb-audio driver to ALSA-Configuration.txt. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- Documentation/sound/alsa/ALSA-Configuration.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index dd083b2a5bd..68bbc25ff39 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1978,12 +1978,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. vid - Vendor ID for the device (optional) pid - Product ID for the device (optional) + nrpacks - Max. number of packets per URB (default: 8) + async_unlink - Use async unlink mode (default: yes) device_setup - Device specific magic number (optional) - Influence depends on the device - Default: 0x0000 This module supports multiple devices, autoprobe and hotplugging. + NB: nrpacks parameter can be modified dynamically via sysfs. + Don't put the value over 20. Changing via sysfs has no sanity + check. + NB: async_unlink=0 would cause Oops. It remains just for + debugging purpose (if any). + Module snd-usb-caiaq -------------------- -- GitLab From 7a9b8063cf7d78d7de4f2555357101087548c699 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Aug 2008 15:40:53 +0200 Subject: [PATCH 0323/5416] ALSA: usb-audio - Add ignore_ctl_error parameter Added the ignore_ctl_error parameter to enable/disable the control-error handling for mixer interfaces. It was a hard-coded ifdef, and now you can change it more easily. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- Documentation/sound/alsa/ALSA-Configuration.txt | 5 +++++ sound/usb/usbaudio.c | 7 +++++-- sound/usb/usbaudio.h | 3 ++- sound/usb/usbmixer.c | 7 +++---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 68bbc25ff39..b33e030509f 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1983,6 +1983,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. device_setup - Device specific magic number (optional) - Influence depends on the device - Default: 0x0000 + ignore_ctl_error - Ignore any USB-controller regarding mixer + interface (default: no) This module supports multiple devices, autoprobe and hotplugging. @@ -1991,6 +1993,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. check. NB: async_unlink=0 would cause Oops. It remains just for debugging purpose (if any). + NB: ignore_ctl_error=1 may help when you get an error at accessing + the mixer element such as URB error -22. This happens on some + buggy USB device or the controller. Module snd-usb-caiaq -------------------- diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c91f18cdc8b..c5cf682c352 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -71,6 +71,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int nrpacks = 8; /* max. number of packets per urb */ static int async_unlink = 1; static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/ +static int ignore_ctl_error; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); @@ -88,7 +89,9 @@ module_param(async_unlink, bool, 0444); MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); module_param_array(device_setup, int, NULL, 0444); MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); - +module_param(ignore_ctl_error, bool, 0444); +MODULE_PARM_DESC(ignore_ctl_error, + "Ignore errors from USB controller for mixer interfaces."); /* * debug the h/w constraints @@ -3633,7 +3636,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, if (err > 0) { /* create normal USB audio interfaces */ if (snd_usb_create_streams(chip, ifnum) < 0 || - snd_usb_create_mixer(chip, ifnum) < 0) { + snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) { goto __error; } } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 140ba363414..f3ca77f08ea 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -223,7 +223,8 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); -int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif); +int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, + int ignore_error); void snd_usb_mixer_disconnect(struct list_head *p); int snd_usb_create_midi_interface(struct snd_usb_audio *chip, struct usb_interface *iface, diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 6621fad8c5f..a49246113e7 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -2014,7 +2014,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, } } -int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) +int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, + int ignore_error) { static struct snd_device_ops dev_ops = { .dev_free = snd_usb_mixer_dev_free @@ -2029,9 +2030,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) return -ENOMEM; mixer->chip = chip; mixer->ctrlif = ctrlif; -#ifdef IGNORE_CTL_ERROR - mixer->ignore_ctl_error = 1; -#endif + mixer->ignore_ctl_error = ignore_error; mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); if (!mixer->id_elems) { kfree(mixer); -- GitLab From 0072889a556373b12b687107ac6b24d2ea961ddf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Aug 2008 07:51:57 +0200 Subject: [PATCH 0324/5416] ALSA: fix a typo during snd_assert() removal Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index b8ee49c1f85..e582face89d 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -306,7 +306,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) struct snd_timer *timer = NULL; struct snd_timer_instance *slave, *tmp; - if (snd_BUG_ON(!timer)) + if (snd_BUG_ON(!timeri)) return -ENXIO; /* force to stop the timer */ -- GitLab From 4682eee0ed64a50668c8645f136972e53fcf5a0a Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Fri, 15 Aug 2008 07:43:24 +0200 Subject: [PATCH 0325/5416] ALSA: hda: dynamically create capture mux controls Dynamically create capture mux volume controls when a output amp is detected. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 52 +++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index fac6b3ca5fe..75112e4b796 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -795,7 +795,6 @@ static struct snd_kcontrol_new stac9200_mixer[] = { STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), { } /* end */ }; @@ -909,12 +908,9 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x0, 0x1a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), - /* analog pc-beep replaced with digital beep support */ /* HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT), @@ -932,11 +928,9 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x0, 0x1a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -944,7 +938,6 @@ static struct snd_kcontrol_new stac925x_mixer[] = { STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), { } /* end */ }; @@ -954,12 +947,9 @@ static struct snd_kcontrol_new stac9205_mixer[] = { HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x19, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x1A, 0x0, HDA_OUTPUT), - { } /* end */ }; @@ -968,11 +958,9 @@ static struct snd_kcontrol_new stac922x_mixer[] = { STAC_INPUT_SOURCE(2), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x13, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -983,15 +971,12 @@ static struct snd_kcontrol_new stac927x_mixer[] = { HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x16, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x2, 0x17, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -2352,7 +2337,8 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { }; /* add dynamic controls */ -static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char *name, unsigned long val) +static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, + int idx, const char *name, unsigned long val) { struct snd_kcontrol_new *knew; @@ -2372,6 +2358,7 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char knew = &spec->kctl_alloc[spec->num_kctl_used]; *knew = stac92xx_control_templates[type]; + knew->index = idx; knew->name = kstrdup(name, GFP_KERNEL); if (! knew->name) return -ENOMEM; @@ -2380,6 +2367,14 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char return 0; } + +/* add dynamic controls */ +static int stac92xx_add_control(struct sigmatel_spec *spec, int type, + const char *name, unsigned long val) +{ + return stac92xx_add_control_idx(spec, type, 0, name, val); +} + /* flag inputs as additional dynamic lineouts */ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) { @@ -2781,6 +2776,26 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, return 0; } +static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + int wcaps, nid, i, err = 0; + + for (i = 0; i < spec->num_muxes; i++) { + nid = spec->mux_nids[i]; + wcaps = get_wcaps(codec, nid); + + if (wcaps & AC_WCAP_OUT_AMP) { + err = stac92xx_add_control_idx(spec, + STAC_CTL_WIDGET_VOL, i, "Mux Capture Volume", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + if (err < 0) + return err; + } + } + return 0; +}; + /* labels for dmic mux inputs */ static const char *stac92xx_dmic_labels[5] = { "Analog Inputs", "Digital Mic 1", "Digital Mic 2", @@ -3079,6 +3094,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if ((err = stac92xx_auto_create_dmic_input_ctls(codec, &spec->autocfg)) < 0) return err; + if (spec->num_muxes > 0) { + err = stac92xx_auto_create_mux_input_ctls(codec); + if (err < 0) + return err; + } spec->multiout.max_channels = spec->multiout.num_dacs * 2; if (spec->multiout.max_channels > 2) -- GitLab From 8daaaa97d6420c7e8b02c12ce591bb29fd959c62 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Fri, 15 Aug 2008 07:45:52 +0200 Subject: [PATCH 0326/5416] ALSA: hda: 92HD75xx fixes Fixed several noise issues with DACs and ADCs on some 92HD75xxx based codecs with certain revision id's. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 87 ++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 75112e4b796..c72c748322a 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -145,6 +145,9 @@ struct sigmatel_spec { unsigned int gpio_data; unsigned int gpio_mute; + /* stream */ + unsigned int stream_delay; + /* analog loopback */ unsigned char aloopback_mask; unsigned char aloopback_shift; @@ -190,6 +193,7 @@ struct sigmatel_spec { unsigned int cur_dmux[2]; struct hda_input_mux *input_mux; unsigned int cur_mux[3]; + unsigned int powerdown_adcs; /* i/o switches */ unsigned int io_switch[2]; @@ -1996,6 +2000,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct sigmatel_spec *spec = codec->spec; + if (spec->stream_delay) + msleep(spec->stream_delay); return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, hinfo); } @@ -2059,9 +2065,14 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct sigmatel_spec *spec = codec->spec; + hda_nid_t nid = spec->adc_nids[substream->number]; - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); + if (spec->powerdown_adcs) { + msleep(40); + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + } + snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); return 0; } @@ -2070,8 +2081,12 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct sigmatel_spec *spec = codec->spec; + hda_nid_t nid = spec->adc_nids[substream->number]; - snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); + snd_hda_codec_cleanup_stream(codec, nid); + if (spec->powerdown_adcs) + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); return 0; } @@ -3296,6 +3311,12 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_sequence_write(codec, spec->init); + /* power down adcs initially */ + if (spec->powerdown_adcs) + for (i = 0; i < spec->num_adcs; i++) + snd_hda_codec_write_cache(codec, + spec->adc_nids[i], 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); /* set up pins */ if (spec->hp_detect) { /* Enable unsolicited responses on the HP widget */ @@ -3930,6 +3951,47 @@ again: return 0; } +#ifdef SND_HDA_NEEDS_RESUME +static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr) +{ + struct sigmatel_spec *spec = codec->spec; + int i; + snd_hda_codec_write_cache(codec, codec->afg, 0, + AC_VERB_SET_POWER_STATE, pwr); + + msleep(1); + for (i = 0; i < spec->num_adcs; i++) { + snd_hda_codec_write_cache(codec, + spec->adc_nids[i], 0, + AC_VERB_SET_POWER_STATE, pwr); + } +}; + +static int stac92hd71xx_resume(struct hda_codec *codec) +{ + stac92hd71xx_set_power_state(codec, AC_PWRST_D0); + return stac92xx_resume(codec); +} + +static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) +{ + stac92hd71xx_set_power_state(codec, AC_PWRST_D3); + return 0; +}; + +#endif + +static struct hda_codec_ops stac92hd71bxx_patch_ops = { + .build_controls = stac92xx_build_controls, + .build_pcms = stac92xx_build_pcms, + .init = stac92xx_init, + .free = stac92xx_free, + .unsol_event = stac92xx_unsol_event, +#ifdef SND_HDA_NEEDS_RESUME + .resume = stac92hd71xx_resume, + .suspend = stac92hd71xx_suspend, +#endif +}; static int patch_stac92hd71bxx(struct hda_codec *codec) { @@ -3941,6 +4003,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; + codec->patch_ops = stac92xx_patch_ops; spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); spec->pin_nids = stac92hd71bxx_pin_nids; @@ -3972,6 +4035,14 @@ again: spec->init = stac92hd71bxx_core_init; break; case 0x111d7608: /* 5 Port with Analog Mixer */ + if ((codec->revision_id & 0xf) == 0 || + (codec->revision_id & 0xf) == 1) { +#ifdef SND_HDA_NEEDS_RESUME + codec->patch_ops = stac92hd71bxx_patch_ops; +#endif + spec->stream_delay = 40; /* 40 milliseconds */ + } + /* no output amps */ spec->num_pwrs = 0; spec->mixer = stac92hd71bxx_analog_mixer; @@ -3981,6 +4052,13 @@ again: stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); break; case 0x111d7603: /* 6 Port with Analog Mixer */ + if ((codec->revision_id & 0xf) == 1) { +#ifdef SND_HDA_NEEDS_RESUME + codec->patch_ops = stac92hd71bxx_patch_ops; +#endif + spec->stream_delay = 40; /* 40 milliseconds */ + } + /* no output amps */ spec->num_pwrs = 0; /* fallthru */ @@ -3997,6 +4075,7 @@ again: spec->gpio_dir = 0x01; spec->gpio_data = 0x01; + spec->powerdown_adcs = 1; spec->digbeep_nid = 0x26; spec->mux_nids = stac92hd71bxx_mux_nids; spec->adc_nids = stac92hd71bxx_adc_nids; @@ -4029,8 +4108,6 @@ again: return err; } - codec->patch_ops = stac92xx_patch_ops; - return 0; }; -- GitLab From b76d69ed721e8365739c3bd5dd7891efbea88494 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 14 Aug 2008 17:25:37 -0700 Subject: [PATCH 0327/5416] x86_64: uml: fix rename header guard In unistd_64.h, the guard macro _ASM_X86_64_UNISTD_H_ is renamed to ASM_X86__UNISTD_64_H. This change should be applied to arch/um/sys-x86_64/syscall_table.c. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/um/sys-x86_64/syscall_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c index c128eb89700..32f5fbe2d0d 100644 --- a/arch/um/sys-x86_64/syscall_table.c +++ b/arch/um/sys-x86_64/syscall_table.c @@ -41,12 +41,12 @@ #define stub_rt_sigreturn sys_rt_sigreturn #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #include #undef __SYSCALL #define __SYSCALL(nr, sym) [ nr ] = sym, -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H typedef void (*sys_call_ptr_t)(void); -- GitLab From 54e8e21ed21ca8788aa75294067494abebf9d550 Mon Sep 17 00:00:00 2001 From: Daniel THOMPSON Date: Fri, 15 Aug 2008 10:53:38 +0100 Subject: [PATCH 0328/5416] sound: Fix esoteric double free in the dummy sound driver. The dummy driver uses runtime->private_free but still frees its pcm structures on error paths. This is esoteric because the error paths in question are unreachable. Thus the bug is only a problem when someone copies this code into other drivers. Signed-off-by: Daniel R Thompson Signed-off-by: Jaroslav Kysela --- sound/drivers/dummy.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index c873243e671..4f900d8b92c 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -354,6 +354,7 @@ static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream) if ((dpcm = new_pcm_stream(substream)) == NULL) return -ENOMEM; runtime->private_data = dpcm; + /* makes the infrastructure responsible for freeing dpcm */ runtime->private_free = snd_card_dummy_runtime_free; runtime->hw = snd_card_dummy_playback; if (substream->pcm->device & 1) { @@ -362,10 +363,8 @@ static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream) } if (substream->pcm->device & 2) runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - if ((err = add_playback_constraints(runtime)) < 0) { - kfree(dpcm); + if ((err = add_playback_constraints(runtime)) < 0) return err; - } return 0; } @@ -379,6 +378,7 @@ static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream) if ((dpcm = new_pcm_stream(substream)) == NULL) return -ENOMEM; runtime->private_data = dpcm; + /* makes the infrastructure responsible for freeing dpcm */ runtime->private_free = snd_card_dummy_runtime_free; runtime->hw = snd_card_dummy_capture; if (substream->pcm->device == 1) { @@ -387,10 +387,8 @@ static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream) } if (substream->pcm->device & 2) runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - if ((err = add_capture_constraints(runtime)) < 0) { - kfree(dpcm); + if ((err = add_capture_constraints(runtime)) < 0) return err; - } return 0; } -- GitLab From 1a11cb6427e65b7cfc9c3ec6eaecd2dba1f2d69a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 15 Aug 2008 12:59:02 +0200 Subject: [PATCH 0329/5416] ALSA: dummy driver - do not use assignment in if condition checkpatch.pl does not like assignment in if condition Signed-off-by: Jaroslav Kysela --- sound/drivers/dummy.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 4f900d8b92c..e5e749f3e0e 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -47,9 +47,11 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) { int err; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; - if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) + err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); + if (err) < 0) return err; return 0; } @@ -363,7 +365,8 @@ static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream) } if (substream->pcm->device & 2) runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - if ((err = add_playback_constraints(runtime)) < 0) + err = add_playback_constraints(runtime); + if (err < 0) return err; return 0; @@ -387,7 +390,8 @@ static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream) } if (substream->pcm->device & 2) runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - if ((err = add_capture_constraints(runtime)) < 0) + err = add_capture_constraints(runtime); + if (err < 0) return err; return 0; @@ -431,8 +435,9 @@ static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, - substreams, substreams, &pcm)) < 0) + err = snd_pcm_new(dummy->card, "Dummy PCM", device, + substreams, substreams, &pcm); + if (err < 0) return err; dummy->pcm = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops); @@ -569,7 +574,8 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) strcpy(card->mixername, "Dummy Mixer"); for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy)); + if (err < 0) return err; } return 0; @@ -593,10 +599,12 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) pcm_substreams[dev] = 1; if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; - if ((err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev])) < 0) + err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]); + if (err < 0) goto __nodev; } - if ((err = snd_card_dummy_new_mixer(dummy)) < 0) + err = snd_card_dummy_new_mixer(dummy); + if (err < 0) goto __nodev; strcpy(card->driver, "Dummy"); strcpy(card->shortname, "Dummy"); @@ -604,7 +612,8 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) == 0) { + err = snd_card_register(card); + if (err == 0) { platform_set_drvdata(devptr, card); return 0; } @@ -667,7 +676,8 @@ static int __init alsa_card_dummy_init(void) { int i, cards, err; - if ((err = platform_driver_register(&snd_dummy_driver)) < 0) + err = platform_driver_register(&snd_dummy_driver); + if (err < 0) return err; cards = 0; -- GitLab From 0fdeb15156536030d62b843ceeee3249d8b288d0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 15 Aug 2008 13:33:10 +0200 Subject: [PATCH 0330/5416] ALSA: release v1.0.18rc1 Signed-off-by: Jaroslav Kysela --- include/sound/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/version.h b/include/sound/version.h index 6b78aff273a..d7b3c76d21c 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h */ -#define CONFIG_SND_VERSION "1.0.17" +#define CONFIG_SND_VERSION "1.0.18rc1" #define CONFIG_SND_DATE "" -- GitLab From ed4e5ec177d20504c51aebb93db12d57716cde9c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:20 +0200 Subject: [PATCH 0331/5416] x86: apic - use SET_APIC_DEST_FIELD instead of hardcoded shift Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 69a876be506..77c5e5eb820 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -150,7 +150,7 @@ u32 safe_xapic_wait_icr_idle(void) void xapic_icr_write(u32 low, u32 id) { - apic_write(APIC_ICR2, id << 24); + apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); apic_write(APIC_ICR, low); } -- GitLab From 36fef0949c14445d231a68663e8a01860f7caca3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:20 +0200 Subject: [PATCH 0332/5416] x86: apic - unify disable_apic_timer Get rid of local_apic_timer_disabled and use disable_apic_timer instead. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 17 ++++++++++++----- arch/x86/kernel/apic_64.c | 16 +++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 12b154822bc..6af20dd12c9 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -63,7 +63,7 @@ int disable_apic; /* Local APIC timer verification ok */ static int local_apic_timer_verify_ok; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ -static int local_apic_timer_disabled; +static int disable_apic_timer __cpuinitdata; /* Local APIC timer works in C2 */ int local_apic_timer_c2_ok; EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); @@ -574,7 +574,7 @@ void __init setup_boot_APIC_clock(void) * timer as a dummy clock event source on SMP systems, so the * broadcast mechanism is used. On UP systems simply ignore it. */ - if (local_apic_timer_disabled) { + if (disable_apic_timer) { /* No broadcast on UP ! */ if (num_possible_cpus() > 1) { lapic_clockevent.mult = 1; @@ -1699,12 +1699,19 @@ static int __init parse_nolapic(char *arg) } early_param("nolapic", parse_nolapic); -static int __init parse_disable_lapic_timer(char *arg) +static int __init parse_disable_apic_timer(char *arg) { - local_apic_timer_disabled = 1; + disable_apic_timer = 1; return 0; } -early_param("nolapic_timer", parse_disable_lapic_timer); +early_param("noapictimer", parse_disable_apic_timer); + +static int __init parse_nolapic_timer(char *arg) +{ + disable_apic_timer = 1; + return 0; +} +early_param("nolapic_timer", parse_nolapic_timer); static int __init parse_lapic_timer_c2_ok(char *arg) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 77c5e5eb820..1e925be861e 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -45,6 +45,7 @@ #include #include +/* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer __cpuinitdata; static int apic_calibrate_pmtmr __initdata; int disable_apic; @@ -1583,14 +1584,19 @@ static int __init parse_lapic_timer_c2_ok(char *arg) } early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); -static __init int setup_noapictimer(char *str) +static int __init parse_disable_apic_timer(char *arg) { - if (str[0] != ' ' && str[0] != 0) - return 0; disable_apic_timer = 1; - return 1; + return 0; +} +early_param("noapictimer", parse_disable_apic_timer); + +static int __init parse_nolapic_timer(char *arg) +{ + disable_apic_timer = 1; + return 0; } -__setup("noapictimer", setup_noapictimer); +early_param("nolapic_timer", parse_nolapic_timer); static __init int setup_apicpmtimer(char *s) { -- GitLab From f07f4f9046121ac803bc2f0ded3d77b7c2ab481b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:21 +0200 Subject: [PATCH 0333/5416] x86: apic - unify __setup_APIC_LVTT To be able to unify this function we RE-introduce APIC_DIVISOR for 64bit mode. This snipped was eliminated in some time ago in a sake of clenup but now we need it again since it allow up to get rid of #ifdef(s). And lapic_is_integrated call is added in apic_64.c but since we always have APIC integrated on 64bit cpu compiler will ignore this call. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 1e925be861e..ac399d0f65c 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -244,6 +244,9 @@ int lapic_get_maxlvt(void) return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } +/* Clock divisor is set to 1 */ +#define APIC_DIVISOR 1 + /* * This function sets up the local APIC timer, with a timeout of * 'clocks' APIC bus clock. During calibration we actually call @@ -262,6 +265,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) lvtt_value = LOCAL_TIMER_VECTOR; if (!oneshot) lvtt_value |= APIC_LVT_TIMER_PERIODIC; + if (!lapic_is_integrated()) + lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); + if (!irqen) lvtt_value |= APIC_LVT_MASKED; @@ -276,7 +282,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | APIC_TDR_DIV_16); if (!oneshot) - apic_write(APIC_TMICT, clocks); + apic_write(APIC_TMICT, clocks / APIC_DIVISOR); } /* @@ -446,7 +452,7 @@ static int __init calibrate_APIC_clock(void) lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); - calibration_result = result / HZ; + calibration_result = (result * APIC_DIVISOR) / HZ; /* * Do a sanity check on the APIC calibration result -- GitLab From 9ce122c6e55c44ae9a4c4c777579b87d83e7f898 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:21 +0200 Subject: [PATCH 0334/5416] x86: apic - do not clear APIC twice in lapic_shutdown There is no need to clear APIC twice since disable_local_APIC will clear it anyway. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6af20dd12c9..a151d66f948 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -830,10 +830,11 @@ void lapic_shutdown(void) return; local_irq_save(flags); - clear_local_APIC(); if (enabled_via_apicbase) disable_local_APIC(); + else + clear_local_APIC(); local_irq_restore(flags); } -- GitLab From 64e474d168e3cf31e44890b4947644d361f84e43 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:22 +0200 Subject: [PATCH 0335/5416] x86: apic - get rid of local_apic_timer_verify_ok We are able to use clock_event_device as it's done in 64bit apic code so lets get rid of local_apic_timer_verify_ok variable. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index a151d66f948..7783c113be2 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -60,8 +60,6 @@ unsigned long mp_lapic_addr; static int force_enable_local_apic; int disable_apic; -/* Local APIC timer verification ok */ -static int local_apic_timer_verify_ok; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer __cpuinitdata; /* Local APIC timer works in C2 */ @@ -301,7 +299,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, unsigned int v; /* Lapic used for broadcast ? */ - if (!local_apic_timer_verify_ok) + if (evt->features & CLOCK_EVT_FEAT_DUMMY) return; local_irq_save(flags); @@ -514,7 +512,7 @@ static int __init calibrate_APIC_clock(void) return -1; } - local_apic_timer_verify_ok = 1; + levt->features &= ~CLOCK_EVT_FEAT_DUMMY; /* We trust the pm timer based calibration */ if (!pm_referenced) { @@ -548,11 +546,11 @@ static int __init calibrate_APIC_clock(void) if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); else - local_apic_timer_verify_ok = 0; + levt->features |= CLOCK_EVT_FEAT_DUMMY; } else local_irq_enable(); - if (!local_apic_timer_verify_ok) { + if (levt->features & CLOCK_EVT_FEAT_DUMMY) { printk(KERN_WARNING "APIC timer disabled due to verification failure.\n"); return -1; -- GitLab From c93baa1ae51cdba25a5f5ad37b2348e700e75daf Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:22 +0200 Subject: [PATCH 0336/5416] x86: apic - unify verify_local_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7783c113be2..7ef7c782a42 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -878,6 +878,12 @@ int __init verify_local_APIC(void) */ reg0 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); + apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); + reg1 = apic_read(APIC_ID); + apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); + apic_write(APIC_ID, reg0); + if (reg1 != (reg0 ^ APIC_ID_MASK)) + return 0; /* * The next two are just to see if we have sane values. -- GitLab From 296cb9511dcc3895fda84d0cd5b411bd926e4bb3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 13:51:23 +0200 Subject: [PATCH 0337/5416] x86: apic - unify sync_Arb_IDs Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 3 +-- arch/x86/kernel/apic_64.c | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 7ef7c782a42..d07488993ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -915,8 +915,7 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, - APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index ac399d0f65c..41aff346063 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -742,8 +742,11 @@ int __init verify_local_APIC(void) */ void __init sync_Arb_IDs(void) { - /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ - if (modern_apic()) + /* + * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not + * needed on AMD. + */ + if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; /* @@ -752,8 +755,7 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG - | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* -- GitLab From 293a17ebc944c958e24e6ffbd1d5a49abdbf489e Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Aug 2008 17:25:03 -0700 Subject: [PATCH 0338/5416] rcu: prevent console flood when one CPU sees another AWOL via RCU One small change needed to keep from flooding the console when one CPU notices that another is AWOL. Unless I am missing something subtle. Otherwise the cleanups look good! Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index 56b8712fe5a..dab2676d9d7 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -308,6 +308,7 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) spin_unlock(&rcp->lock); return; } + rcp->gp_check = get_seconds() + 30; spin_unlock(&rcp->lock); /* OK, time to rat on our buddy... */ -- GitLab From 1f7b94cd3d564901f9e04a8bc5832ae7bfd690a0 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 5 Aug 2008 09:21:44 -0700 Subject: [PATCH 0339/5416] rcu: classic RCU locking and memory-barrier cleanups This patch simplifies the locking and memory-barrier usage in the Classic RCU grace-period-detection mechanism, incorporating Lai Jiangshan's feedback from the earlier version (http://lkml.org/lkml/2008/8/1/400 and http://lkml.org/lkml/2008/8/3/43). Passed 10 hours of rcutorture concurrent with CPUs being put online and taken offline on a 128-hardware-thread Power machine. My apologies to whoever in the Eastern Hemisphere was planning to use this machine over the Western Hemisphere night, but it was sitting idle and... So this is ready for tip/core/rcu. This patch is in preparation for moving to a hierarchical algorithm to allow the very large SMP machines -- requested by some people at OLS, and there seem to have been a few recent patches in the 4096-CPU direction as well. The general idea is to move to a much more conservative concurrency design, then apply a hierarchy to reduce contention on the global lock by a few orders of magnitude (larger machines would see greater reductions). The reason for taking a conservative approach is that this code isn't on any fast path. Prototype in progress. This patch is against the linux-tip git tree (tip/core/rcu). If you wish to test this against 2.6.26, use the following set of patches: http://www.rdrop.com/users/paulmck/patches/2.6.26-ljsimp-1.patch http://www.rdrop.com/users/paulmck/patches/2.6.26-ljsimpfix-3.patch The first patch combines commits 5127bed588a2f8f3a1f732de2a8a190b7df5dce3 and 3cac97cbb14aed00d83eb33d4613b0fe3aaea863 from Lai Jiangshan , and the second patch contains my changes. Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 51 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index dab2676d9d7..5de126630b1 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -87,6 +87,7 @@ static void force_quiescent_state(struct rcu_data *rdp, int cpu; cpumask_t cpumask; set_need_resched(); + spin_lock(&rcp->lock); if (unlikely(!rcp->signaled)) { rcp->signaled = 1; /* @@ -112,6 +113,7 @@ static void force_quiescent_state(struct rcu_data *rdp, for_each_cpu_mask_nr(cpu, cpumask) smp_send_reschedule(cpu); } + spin_unlock(&rcp->lock); } #else static inline void force_quiescent_state(struct rcu_data *rdp, @@ -125,7 +127,9 @@ static void __call_rcu(struct rcu_head *head, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { long batch; - smp_mb(); /* reads the most recently updated value of rcu->cur. */ + + head->next = NULL; + smp_mb(); /* Read of rcu->cur must happen after any change by caller. */ /* * Determine the batch number of this callback. @@ -175,7 +179,6 @@ void call_rcu(struct rcu_head *head, unsigned long flags; head->func = func; - head->next = NULL; local_irq_save(flags); __call_rcu(head, &rcu_ctrlblk, &__get_cpu_var(rcu_data)); local_irq_restore(flags); @@ -204,7 +207,6 @@ void call_rcu_bh(struct rcu_head *head, unsigned long flags; head->func = func; - head->next = NULL; local_irq_save(flags); __call_rcu(head, &rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); local_irq_restore(flags); @@ -467,17 +469,17 @@ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list, static void __rcu_offline_cpu(struct rcu_data *this_rdp, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - /* if the cpu going offline owns the grace period + /* + * if the cpu going offline owns the grace period * we can block indefinitely waiting for it, so flush * it here */ spin_lock_bh(&rcp->lock); if (rcp->cur != rcp->completed) cpu_quiet(rdp->cpu, rcp); - spin_unlock_bh(&rcp->lock); - /* spin_lock implies smp_mb() */ rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail, rcp->cur + 1); rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail[2], rcp->cur + 1); + spin_unlock_bh(&rcp->lock); local_irq_disable(); this_rdp->qlen += rdp->qlen; @@ -511,16 +513,19 @@ static void rcu_offline_cpu(int cpu) static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + long completed_snap; + if (rdp->nxtlist) { local_irq_disable(); + completed_snap = ACCESS_ONCE(rcp->completed); /* * move the other grace-period-completed entries to * [rdp->nxtlist, *rdp->nxttail[0]) temporarily */ - if (!rcu_batch_before(rcp->completed, rdp->batch)) + if (!rcu_batch_before(completed_snap, rdp->batch)) rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2]; - else if (!rcu_batch_before(rcp->completed, rdp->batch - 1)) + else if (!rcu_batch_before(completed_snap, rdp->batch - 1)) rdp->nxttail[0] = rdp->nxttail[1]; /* @@ -561,8 +566,24 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, static void rcu_process_callbacks(struct softirq_action *unused) { + /* + * Memory references from any prior RCU read-side critical sections + * executed by the interrupted code must be see before any RCU + * grace-period manupulations below. + */ + + smp_mb(); /* See above block comment. */ + __rcu_process_callbacks(&rcu_ctrlblk, &__get_cpu_var(rcu_data)); __rcu_process_callbacks(&rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); + + /* + * Memory references from any later RCU read-side critical sections + * executed by the interrupted code must be see after any RCU + * grace-period manupulations above. + */ + + smp_mb(); /* See above block comment. */ } static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) @@ -571,13 +592,15 @@ static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) check_cpu_stall(rcp, rdp); if (rdp->nxtlist) { + long completed_snap = ACCESS_ONCE(rcp->completed); + /* * This cpu has pending rcu entries and the grace period * for them has completed. */ - if (!rcu_batch_before(rcp->completed, rdp->batch)) + if (!rcu_batch_before(completed_snap, rdp->batch)) return 1; - if (!rcu_batch_before(rcp->completed, rdp->batch - 1) && + if (!rcu_batch_before(completed_snap, rdp->batch - 1) && rdp->nxttail[0] != rdp->nxttail[1]) return 1; if (rdp->nxttail[0] != &rdp->nxtlist) @@ -628,6 +651,12 @@ int rcu_needs_cpu(int cpu) return !!rdp->nxtlist || !!rdp_bh->nxtlist || rcu_pending(cpu); } +/* + * Top-level function driving RCU grace-period detection, normally + * invoked from the scheduler-clock interrupt. This function simply + * increments counters that are read only from softirq by this same + * CPU, so there are no memory barriers required. + */ void rcu_check_callbacks(int cpu, int user) { if (user || @@ -671,6 +700,7 @@ void rcu_check_callbacks(int cpu, int user) static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + spin_lock(&rcp->lock); memset(rdp, 0, sizeof(*rdp)); rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2] = &rdp->nxtlist; rdp->donetail = &rdp->donelist; @@ -678,6 +708,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->qs_pending = 0; rdp->cpu = cpu; rdp->blimit = blimit; + spin_unlock(&rcp->lock); } static void __cpuinit rcu_online_cpu(int cpu) -- GitLab From 516cbf3730c49739629d66313b20bdc50c98aa2c Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 12 Aug 2008 12:52:36 -0700 Subject: [PATCH 0340/5416] x86, bootup: add built-in kernel command line for x86 (v2) Allow x86 to support a built-in kernel command line. The built-in command line can override the one provided by the boot loader, for those cases where the boot loader is broken or it is difficult to change the command line in the the boot loader. H. Peter Anvin wrote: > Ingo Molnar wrote: >> Best would be to make it really apparent in the code that nothing >> changes if this config option is not set. Preferably there should be >> no extra code at all in that case. >> > > I would like to see this: [...Nested ifdefs...] OK. This version changes absolutely nothing if CONFIG_CMDLINE_BOOL is not set (the default). Also, no space is appended even when CONFIG_CMDLINE_BOOL is set, but the builtin string is empty. This is less sloppy all the way around, IMHO. Note that I use the same option names as on other arches for this feature. [ mingo@elte.hu: build fix ] Signed-off-by: Tim Bird Cc: Matt Mackall Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 45 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 16 +++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ac2fb0641a0..fbcb79bbafd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1392,6 +1392,51 @@ config COMPAT_VDSO If unsure, say Y. +config CMDLINE_BOOL + bool "Built-in kernel command line" + default n + help + Allow for specifying boot arguments to the kernel at + build time. On some systems (e.g. embedded ones), it is + necessary or convenient to provide some or all of the + kernel boot arguments with the kernel itself (that is, + to not rely on the boot loader to provide them.) + + To compile command line arguments into the kernel, + set this option to 'Y', then fill in the + the boot arguments in CONFIG_CMDLINE. + + Systems with fully functional boot loaders (i.e. non-embedded) + should leave this option set to 'N'. + +config CMDLINE + string "Built-in kernel command string" + depends on CMDLINE_BOOL + default "" + help + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, it is appended to this string to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_OVERRIDE + bool "Built-in command line overrides boot loader arguments" + default n + depends on CMDLINE_BOOL + help + Set this option to 'Y' to have the kernel ignore the boot loader + command line, and use ONLY the built-in command line. + + This is used to work around broken boot loaders. This should + be set to 'N' under normal conditions. + endmenu config ARCH_ENABLE_MEMORY_HOTPLUG diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 68b48e3fbcb..2f31cddd27b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -223,6 +223,9 @@ unsigned long saved_video_mode; #define RAMDISK_LOAD_FLAG 0x4000 static char __initdata command_line[COMMAND_LINE_SIZE]; +#ifdef CONFIG_CMDLINE_BOOL +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; +#endif #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; @@ -673,6 +676,19 @@ void __init setup_arch(char **cmdline_p) bss_resource.start = virt_to_phys(&__bss_start); bss_resource.end = virt_to_phys(&__bss_stop)-1; +#ifdef CONFIG_CMDLINE_BOOL +#ifdef CONFIG_CMDLINE_OVERRIDE + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +#else + if (builtin_cmdline[0]) { + /* append boot loader cmdline to builtin */ + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + } +#endif +#endif + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; -- GitLab From 1ac2f7d55b7ee1613c90631e87fea22ec06781e5 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 4 Aug 2008 14:51:24 +0800 Subject: [PATCH 0341/5416] introduce two APIs for page attribute Introduce two APIs for page attribute. flushing tlb/cache in every page attribute is expensive. AGP gart usually will do a lot of operations to change a page to uc, new APIs can reduce flush. Signed-off-by: Shaohua Li Cc: airlied@linux.ie Cc: Andrew Morton Cc: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 58 +++++++++++++++++++++++++++++++----- include/asm-x86/cacheflush.h | 3 ++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 65c6e46bf05..2c5c18c2464 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -752,12 +752,12 @@ static inline int cache_attr(pgprot_t attr) (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); } -static int change_page_attr_set_clr(unsigned long addr, int numpages, +static int do_change_page_attr_set_clr(unsigned long addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr, - int force_split) + int force_split, int *tlb_flush) { struct cpa_data cpa; - int ret, cache, checkalias; + int ret, checkalias; /* * Check, if we are requested to change a not supported @@ -792,9 +792,22 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, /* * Check whether we really changed something: */ - if (!cpa.flushtlb) - goto out; + *tlb_flush = cpa.flushtlb; + cpa_fill_pool(NULL); + + return ret; +} + +static int change_page_attr_set_clr(unsigned long addr, int numpages, + pgprot_t mask_set, pgprot_t mask_clr, + int force_split) +{ + int cache, flush_cache = 0, ret; + ret = do_change_page_attr_set_clr(addr, numpages, mask_set, mask_clr, + force_split, &flush_cache); + if (!flush_cache) + goto out; /* * No need to flush, when we did not set any of the caching * attributes: @@ -811,10 +824,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, cpa_flush_range(addr, numpages, cache); else cpa_flush_all(cache); - out: - cpa_fill_pool(NULL); - return ret; } @@ -852,6 +862,30 @@ int set_memory_uc(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_uc); +int set_memory_uc_noflush(unsigned long addr, int numpages) +{ + int flush; + /* + * for now UC MINUS. see comments in ioremap_nocache() + */ + if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, + _PAGE_CACHE_UC_MINUS, NULL)) + return -EINVAL; + /* + * for now UC MINUS. see comments in ioremap_nocache() + */ + return do_change_page_attr_set_clr(addr, numpages, + __pgprot(_PAGE_CACHE_UC_MINUS), + __pgprot(0), 0, &flush); +} +EXPORT_SYMBOL(set_memory_uc_noflush); + +void set_memory_flush_all(void) +{ + cpa_flush_all(1); +} +EXPORT_SYMBOL(set_memory_flush_all); + int _set_memory_wc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, @@ -926,6 +960,14 @@ int set_pages_uc(struct page *page, int numpages) } EXPORT_SYMBOL(set_pages_uc); +int set_pages_uc_noflush(struct page *page, int numpages) +{ + unsigned long addr = (unsigned long)page_address(page); + + return set_memory_uc_noflush(addr, numpages); +} +EXPORT_SYMBOL(set_pages_uc_noflush); + int set_pages_wb(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index f4c0ab50d2c..57bac7b68c4 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -57,6 +57,8 @@ int _set_memory_uc(unsigned long addr, int numpages); int _set_memory_wc(unsigned long addr, int numpages); int _set_memory_wb(unsigned long addr, int numpages); int set_memory_uc(unsigned long addr, int numpages); +int set_memory_uc_noflush(unsigned long addr, int numpages); +void set_memory_flush_all(void); int set_memory_wc(unsigned long addr, int numpages); int set_memory_wb(unsigned long addr, int numpages); int set_memory_x(unsigned long addr, int numpages); @@ -87,6 +89,7 @@ int set_memory_4k(unsigned long addr, int numpages); */ int set_pages_uc(struct page *page, int numpages); +int set_pages_uc_noflush(struct page *page, int numpages); int set_pages_wb(struct page *page, int numpages); int set_pages_x(struct page *page, int numpages); int set_pages_nx(struct page *page, int numpages); -- GitLab From 466ae837424dcc538b1af2a0eaf53be32edcdbe7 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 4 Aug 2008 14:51:30 +0800 Subject: [PATCH 0342/5416] reduce tlb/cache flush times of agpgart memory allocation To reduce tlb/cache flush, makes agp memory allocation do one flush after all pages in a region are changed to uc. All agp drivers except agp-sgi uses agp_generic_alloc_page() for .agp_alloc_page, so the patch should work for them. agp-sgi is only for ia64, so not a problem too. Signed-off-by: Shaohua Li Cc: airlied@linux.ie Cc: Andrew Morton Cc: Arjan van de Ven Signed-off-by: Ingo Molnar --- drivers/char/agp/agp.h | 4 ++++ drivers/char/agp/generic.c | 4 +++- include/asm-x86/agp.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 81e14bea54b..395168fb17e 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -30,6 +30,10 @@ #define _AGP_BACKEND_PRIV_H 1 #include /* for flush_agp_cache() */ +#ifndef map_page_into_agp_noflush +#define map_page_into_agp_noflush(page) map_page_into_agp(page) +#define map_page_into_agp_global_flush() +#endif #define PFX "agpgart: " diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index eaa1a355bb3..bf239b8ecac 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -274,6 +274,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, new->memory[i] = virt_to_gart(addr); new->page_count++; } + map_page_into_agp_global_flush(); new->bridge = bridge; return new; @@ -1186,7 +1187,8 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) if (page == NULL) return NULL; - map_page_into_agp(page); + /* agp_allocate_memory will do flush */ + map_page_into_agp_noflush(page); get_page(page); atomic_inc(&agp_bridge->current_memory_agp); diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index e4004a9f6a9..181b9e984b3 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -15,6 +15,9 @@ #define map_page_into_agp(page) set_pages_uc(page, 1) #define unmap_page_from_agp(page) set_pages_wb(page, 1) +#define map_page_into_agp_noflush(page) set_pages_uc_noflush(page, 1) +#define map_page_into_agp_global_flush() set_memory_flush_all() + /* * Could use CLFLUSH here if the cpu supports it. But then it would * need to be called for each cacheline of the whole page so it may -- GitLab From 2bd455dbfebfd632a8dcf1d3d1612737986fde0a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 4 Aug 2008 11:26:38 +0800 Subject: [PATCH 0343/5416] x86: remove nesting CONFIG_HOTPLUG_CPU prefill_possible_map() is defined inside CONFIG_HOTPLUG_CPU, so the nesting CONFIG_HOTPLUG_CPU is just redundant. Signed-off-by: Li Zefan Signed-off-by: Ingo Molnar --- arch/x86/kernel/smpboot.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 332512767f4..d5e19c36204 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1271,16 +1271,13 @@ __init void prefill_possible_map(void) if (!num_processors) num_processors = 1; -#ifdef CONFIG_HOTPLUG_CPU if (additional_cpus == -1) { if (disabled_cpus > 0) additional_cpus = disabled_cpus; else additional_cpus = 0; } -#else - additional_cpus = 0; -#endif + possible = num_processors + additional_cpus; if (possible > NR_CPUS) possible = NR_CPUS; -- GitLab From 020878ac427aa053414602cef975c2b5a2e33bf8 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:23:36 +0200 Subject: [PATCH 0344/5416] x86: coding style fixes to arch/x86/boot/compressed/misc.c Before: total: 4 errors, 6 warnings, 439 lines checked After: total: 1 errors, 5 warnings, 441 lines checked Before -#include +#include paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/misc.o.* 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.after 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.before After -#include +#include paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/misc.o.* 59a2d264284be5e72b5af4f3a8ccfb47 /tmp/misc.o.after 8b2394e1fe519a9542e9a7e3e7b69c39 /tmp/misc.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/misc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 9fea7370647..2a3f77e52e2 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -251,7 +251,7 @@ static void __putstr(int error, const char *s) y--; } } else { - vidmem [(x + cols * y) * 2] = c; + vidmem[(x + cols * y) * 2] = c; if (++x >= cols) { x = 0; if (++y >= lines) { @@ -277,7 +277,8 @@ static void *memset(void *s, int c, unsigned n) int i; char *ss = s; - for (i = 0; i < n; i++) ss[i] = c; + for (i = 0; i < n; i++) + ss[i] = c; return s; } @@ -287,7 +288,8 @@ static void *memcpy(void *dest, const void *src, unsigned n) const char *s = src; char *d = dest; - for (i = 0; i < n; i++) d[i] = s[i]; + for (i = 0; i < n; i++) + d[i] = s[i]; return dest; } -- GitLab From 2070dae10f50ec244f58292436ace9a3f9dc1d71 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:24:06 +0200 Subject: [PATCH 0345/5416] x86: coding style fixes to arch/x86/kernel/bios_uv.c paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/bios_uv.o.* 9afe794594831166704744184e192ed8 /tmp/bios_uv.o.after 9afe794594831166704744184e192ed8 /tmp/bios_uv.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/kernel/bios_uv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index c639bd55391..fdd585f9c53 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c @@ -25,11 +25,11 @@ x86_bios_strerror(long status) { const char *str; switch (status) { - case 0: str = "Call completed without error"; break; - case -1: str = "Not implemented"; break; - case -2: str = "Invalid argument"; break; - case -3: str = "Call completed with error"; break; - default: str = "Unknown BIOS status code"; break; + case 0: str = "Call completed without error"; break; + case -1: str = "Not implemented"; break; + case -2: str = "Invalid argument"; break; + case -3: str = "Call completed with error"; break; + default: str = "Unknown BIOS status code"; break; } return str; } -- GitLab From 209b580fd8c3a42b69550c98de434671d41a4ebb Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:24:45 +0200 Subject: [PATCH 0346/5416] x86: coding style fixes to arch/x86/lib/strstr_32.c Before: total: 3 errors, 0 warnings, 31 lines checked After: total: 0 errors, 0 warnings, 31 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/strstr_32.o.* c96006ec3387862e5bacb139207a3098 /tmp/strstr_32.o.after c96006ec3387862e5bacb139207a3098 /tmp/strstr_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/lib/strstr_32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/strstr_32.c b/arch/x86/lib/strstr_32.c index 42e8a50303f..8e2d55f754b 100644 --- a/arch/x86/lib/strstr_32.c +++ b/arch/x86/lib/strstr_32.c @@ -23,9 +23,9 @@ __asm__ __volatile__( "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "2:" - :"=a" (__res), "=&c" (d0), "=&S" (d1) - :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) - :"dx", "di"); + : "=a" (__res), "=&c" (d0), "=&S" (d1) + : "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) + : "dx", "di"); return __res; } -- GitLab From 3492cdf0176bde5e35223a1388d59676bc67c145 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:25:13 +0200 Subject: [PATCH 0347/5416] x86: coding style fixes to arch/x86/lib/string_32.c Before: total: 21 errors, 0 warnings, 237 lines checked After: total: 0 errors, 0 warnings, 237 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/string_32.o.* c55d059ef1612b32a8bb2771a72ae0d5 /tmp/string_32.o.after c55d059ef1612b32a8bb2771a72ae0d5 /tmp/string_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/lib/string_32.c | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c index 94972e7c094..82004d2bf05 100644 --- a/arch/x86/lib/string_32.c +++ b/arch/x86/lib/string_32.c @@ -22,7 +22,7 @@ char *strcpy(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2) - :"0" (src), "1" (dest) : "memory"); + : "0" (src), "1" (dest) : "memory"); return dest; } EXPORT_SYMBOL(strcpy); @@ -42,7 +42,7 @@ char *strncpy(char *dest, const char *src, size_t count) "stosb\n" "2:" : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) - :"0" (src), "1" (dest), "2" (count) : "memory"); + : "0" (src), "1" (dest), "2" (count) : "memory"); return dest; } EXPORT_SYMBOL(strncpy); @@ -60,7 +60,7 @@ char *strcat(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu): "memory"); + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory"); return dest; } EXPORT_SYMBOL(strcat); @@ -105,9 +105,9 @@ int strcmp(const char *cs, const char *ct) "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" - :"=a" (res), "=&S" (d0), "=&D" (d1) - :"1" (cs), "2" (ct) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1) + : "1" (cs), "2" (ct) + : "memory"); return res; } EXPORT_SYMBOL(strcmp); @@ -130,9 +130,9 @@ int strncmp(const char *cs, const char *ct, size_t count) "3:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "4:" - :"=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs), "2" (ct), "3" (count) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + : "1" (cs), "2" (ct), "3" (count) + : "memory"); return res; } EXPORT_SYMBOL(strncmp); @@ -152,9 +152,9 @@ char *strchr(const char *s, int c) "movl $1,%1\n" "2:\tmovl %1,%0\n\t" "decl %0" - :"=a" (res), "=&S" (d0) - :"1" (s), "0" (c) - :"memory"); + : "=a" (res), "=&S" (d0) + : "1" (s), "0" (c) + : "memory"); return res; } EXPORT_SYMBOL(strchr); @@ -169,9 +169,9 @@ size_t strlen(const char *s) "scasb\n\t" "notl %0\n\t" "decl %0" - :"=c" (res), "=&D" (d0) - :"1" (s), "a" (0), "0" (0xffffffffu) - :"memory"); + : "=c" (res), "=&D" (d0) + : "1" (s), "a" (0), "0" (0xffffffffu) + : "memory"); return res; } EXPORT_SYMBOL(strlen); @@ -189,9 +189,9 @@ void *memchr(const void *cs, int c, size_t count) "je 1f\n\t" "movl $1,%0\n" "1:\tdecl %0" - :"=D" (res), "=&c" (d0) - :"a" (c), "0" (cs), "1" (count) - :"memory"); + : "=D" (res), "=&c" (d0) + : "a" (c), "0" (cs), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(memchr); @@ -228,9 +228,9 @@ size_t strnlen(const char *s, size_t count) "cmpl $-1,%1\n\t" "jne 1b\n" "3:\tsubl %2,%0" - :"=a" (res), "=&d" (d0) - :"c" (s), "1" (count) - :"memory"); + : "=a" (res), "=&d" (d0) + : "c" (s), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(strnlen); -- GitLab From d9336a9b47d57db835453968efbd0d5cedfe0260 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sat, 2 Aug 2008 21:25:43 +0200 Subject: [PATCH 0348/5416] x86: coding style fixes to arch/x86/kernel/paravirt_patch_32.c Before: total: 3 errors, 1 warnings, 49 lines checked After: total: 2 errors, 1 warnings, 49 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/paravirt_patch_32.o.* a78eea4264723e18c49dcfbe0ee0aae7 /tmp/paravirt_patch_32.o.after a78eea4264723e18c49dcfbe0ee0aae7 /tmp/paravirt_patch_32.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Ingo Molnar --- arch/x86/kernel/paravirt_patch_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c index 58262218781..9fe644f4861 100644 --- a/arch/x86/kernel/paravirt_patch_32.c +++ b/arch/x86/kernel/paravirt_patch_32.c @@ -23,7 +23,7 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, start = start_##ops##_##x; \ end = end_##ops##_##x; \ goto patch_site - switch(type) { + switch (type) { PATCH_SITE(pv_irq_ops, irq_disable); PATCH_SITE(pv_irq_ops, irq_enable); PATCH_SITE(pv_irq_ops, restore_fl); -- GitLab From ff9cf2ce7afe76435d66c898cc9dacaa68e79d41 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 1 Aug 2008 14:10:02 -0700 Subject: [PATCH 0349/5416] rcu: fixes to include/linux/rcupreempt.h Hello! Compared tip/core/rcu to my latest patchset, and found the following issues: o the memory barrier in rcu_exit_nohz() somehow got out of place (it is correct in mainline as of 2.6.26-rc7). o There is a duplicate declaration of rcu_dyntick_sched. The attached patch fixes these. Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- include/linux/rcupreempt.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index 0967f03b070..addb5e282f3 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h @@ -111,7 +111,6 @@ extern struct rcupreempt_trace *rcupreempt_trace_cpu(int cpu); struct softirq_action; #ifdef CONFIG_NO_HZ -DECLARE_PER_CPU(struct rcu_dyntick_sched, rcu_dyntick_sched); static inline void rcu_enter_nohz(void) { @@ -126,8 +125,8 @@ static inline void rcu_exit_nohz(void) { static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1); - smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ __get_cpu_var(rcu_dyntick_sched).dynticks++; + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ WARN_ON_RATELIMIT(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1), &rs); } -- GitLab From 34d7c2b38d124219b7034356716e3455c439acd3 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 1 Aug 2008 14:11:05 -0700 Subject: [PATCH 0350/5416] rcu: remove list_for_each_rcu() All of the in-tree uses of list_for_each_rcu() have been converted to list_for_each_entry_rcu(), so list_for_each_rcu() can now be removed. Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- Documentation/RCU/checklist.txt | 2 +- Documentation/RCU/whatisRCU.txt | 2 -- include/linux/rculist.h | 14 -------------- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt index cf5562cbe35..6e253407b3d 100644 --- a/Documentation/RCU/checklist.txt +++ b/Documentation/RCU/checklist.txt @@ -210,7 +210,7 @@ over a rather long period of time, but improvements are always welcome! number of updates per grace period. 9. All RCU list-traversal primitives, which include - rcu_dereference(), list_for_each_rcu(), list_for_each_entry_rcu(), + rcu_dereference(), list_for_each_entry_rcu(), list_for_each_continue_rcu(), and list_for_each_safe_rcu(), must be either within an RCU read-side critical section or must be protected by appropriate update-side locks. RCU diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index e04d643a9f5..96170824a71 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -786,8 +786,6 @@ RCU pointer/list traversal: list_for_each_entry_rcu hlist_for_each_entry_rcu - list_for_each_rcu (to be deprecated in favor of - list_for_each_entry_rcu) list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) diff --git a/include/linux/rculist.h b/include/linux/rculist.h index eb4443c7e05..e649bd3f2c9 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -198,20 +198,6 @@ static inline void list_splice_init_rcu(struct list_head *list, at->prev = last; } -/** - * list_for_each_rcu - iterate over an rcu-protected list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_rcu(pos, head) \ - for (pos = rcu_dereference((head)->next); \ - prefetch(pos->next), pos != (head); \ - pos = rcu_dereference(pos->next)) - #define __list_for_each_rcu(pos, head) \ for (pos = rcu_dereference((head)->next); \ pos != (head); \ -- GitLab From 07dd20e0324f4d3e33bde1944d4f7771a09c498c Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Fri, 1 Aug 2008 13:18:04 +0100 Subject: [PATCH 0351/5416] sched: reorder signal_struct to remove 8 bytes on 64 bit builds reorder structure to remove 8 bytes of padding on 64 bit builds Signed-off-by: Richard Kennedy Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index cfb0d87b99f..5a8058e44f5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -451,8 +451,8 @@ struct signal_struct { * - everyone except group_exit_task is stopped during signal delivery * of fatal signals, group_exit_task processes the signal. */ - struct task_struct *group_exit_task; int notify_count; + struct task_struct *group_exit_task; /* thread group stop support, overloads group_exit_code too */ int group_stop_count; -- GitLab From bee367ed066e26c14263d808136fba8eec3bd70a Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Fri, 1 Aug 2008 13:24:08 +0100 Subject: [PATCH 0352/5416] sched: reorder struct sched_rt_entity to remove padding on 64 bit builds remove 8 bytes of padding on 64 bit builds (also removes 8 bytes from task_struct) Signed-off-by: Richard Kennedy Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 5a8058e44f5..08a87b5f29e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1010,8 +1010,8 @@ struct sched_entity { struct sched_rt_entity { struct list_head run_list; - unsigned int time_slice; unsigned long timeout; + unsigned int time_slice; int nr_cpus_allowed; struct sched_rt_entity *back; -- GitLab From 3fb669dd6ec11e14819c0114a0e68a9ddcec65e1 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Fri, 1 Aug 2008 13:36:28 +0100 Subject: [PATCH 0353/5416] reorder struct prop_local_single to remove padding on 64 bit builds reorder structure to remove 8 bytes of padding on 64 bit builds (also removes 8 bytes from task_struct) Signed-off-by: Richard Kennedy Cc: peterz@infradead.org Signed-off-by: Ingo Molnar --- include/linux/proportions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/proportions.h b/include/linux/proportions.h index 5afc1b23346..cf793bbbd05 100644 --- a/include/linux/proportions.h +++ b/include/linux/proportions.h @@ -104,8 +104,8 @@ struct prop_local_single { * snapshot of the last seen global state * and a lock protecting this state */ - int shift; unsigned long period; + int shift; spinlock_t lock; /* protect the snapshot state */ }; -- GitLab From d33dcb9e7d272cc3171dcc3a21049902185ab03d Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Fri, 1 Aug 2008 12:46:45 +0200 Subject: [PATCH 0354/5416] x86: Microcode patch loader style corrections Style corrections to main microcode module. Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 28dba1a6e4a..39961bb8329 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -55,8 +55,8 @@ * in a single CPU package. * 1.10 28 Feb 2002 Asit K Mallick and * Tigran Aivazian , - * Serialize updates as required on HT processors due to speculative - * nature of implementation. + * Serialize updates as required on HT processors due to + * speculative nature of implementation. * 1.11 22 Mar 2002 Tigran Aivazian * Fix the panic when writing zero-length microcode chunk. * 1.12 29 Sep 2003 Nitin Kamble , @@ -71,7 +71,7 @@ * Thanks to Stuart Swales for pointing out this bug. */ -//#define DEBUG /* pr_debug */ +/*#define DEBUG pr_debug */ #include #include #include @@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(user_buffer); unsigned int user_buffer_size; /* it's size */ EXPORT_SYMBOL_GPL(user_buffer_size); -static int do_microcode_update (void) +static int do_microcode_update(void) { long cursor = 0; int error = 0; @@ -158,18 +158,20 @@ out: return error; } -static int microcode_open (struct inode *unused1, struct file *unused2) +static int microcode_open(struct inode *unused1, struct file *unused2) { cycle_kernel_lock(); return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) +static ssize_t microcode_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) { ssize_t ret; if ((len >> PAGE_SHIFT) > num_physpages) { - printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); + printk(KERN_ERR "microcode: too much data (max %ld pages)\n", + num_physpages); return -EINVAL; } @@ -201,7 +203,7 @@ static struct miscdevice microcode_dev = { .fops = µcode_fops, }; -static int __init microcode_dev_init (void) +static int __init microcode_dev_init(void) { int error; @@ -216,7 +218,7 @@ static int __init microcode_dev_init (void) return 0; } -static void microcode_dev_exit (void) +static void microcode_dev_exit(void) { misc_deregister(µcode_dev); } @@ -224,7 +226,7 @@ static void microcode_dev_exit (void) MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #else #define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while(0) +#define microcode_dev_exit() do { } while (0) #endif /* fake device for request_firmware */ @@ -451,7 +453,7 @@ int microcode_init(void *opaque, struct module *module) } EXPORT_SYMBOL_GPL(microcode_init); -void __exit microcode_exit (void) +void __exit microcode_exit(void) { microcode_dev_exit(); -- GitLab From 636a31781684d0f49208aa163f1a5a3a74210eb4 Mon Sep 17 00:00:00 2001 From: Peter Oruba Date: Fri, 1 Aug 2008 12:46:46 +0200 Subject: [PATCH 0355/5416] x86: Fixed NULL function pointer dereference in AMD microcode patch loader. Dereference took place in code part responsible for manual installation of microcode patches through /dev/cpu/microcode. Signed-off-by: Peter Oruba Cc: Peter Oruba Cc: Tigran Aivazian Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 39961bb8329..ad136ad99cb 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -127,7 +127,8 @@ static int do_microcode_update(void) old = current->cpus_allowed; while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { - error = microcode_ops->microcode_sanity_check(new_mc); + if (microcode_ops->microcode_sanity_check != NULL) + error = microcode_ops->microcode_sanity_check(new_mc); if (error) goto out; /* -- GitLab From 5843d9a4d0ba89719916c8f07fc9c57b7126be6d Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 1 Aug 2008 03:15:21 +0200 Subject: [PATCH 0356/5416] x86, pat: avoid highmem cache attribute aliasing Highmem code can leave ptes and tlb entries around for a given page even after kunmap, and after it has been freed. >From what I can gather, the PAT code may change the cache attributes of arbitrary physical addresses (ie. including highmem pages), which would result in aliases in the case that it operates on one of these lazy tlb highmem pages. Flushing kmaps should solve the problem. I've also just added code for conditional flushing if we haven't got any dangling highmem aliases -- this should help performance if we change page attributes frequently or systems that aren't using much highmem pages (eg. if < 4G RAM). Should be turned into 2 patches, but just for RFC... Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 3 +++ mm/highmem.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 2c5c18c2464..4adb33628de 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -777,6 +777,9 @@ static int do_change_page_attr_set_clr(unsigned long addr, int numpages, WARN_ON_ONCE(1); } + /* Must avoid aliasing mappings in the highmem code */ + kmap_flush_unused(); + cpa.vaddr = addr; cpa.numpages = numpages; cpa.mask_set = mask_set; diff --git a/mm/highmem.c b/mm/highmem.c index e16e1523b68..b36b83b920f 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -70,6 +70,7 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); static void flush_all_zero_pkmaps(void) { int i; + int need_flush = 0; flush_cache_kmaps(); @@ -101,8 +102,10 @@ static void flush_all_zero_pkmaps(void) &pkmap_page_table[i]); set_page_address(page, NULL); + need_flush = 1; } - flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); + if (need_flush) + flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); } /** -- GitLab From c9c3dddd8f9a05b25d4ce53e8e80cc0ea1759d18 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 1 Aug 2008 03:51:38 +0400 Subject: [PATCH 0357/5416] x86_64: remove empty lines from stack traces/oopses Signed-off-by: Alexey Dobriyan Cc: ak@suse.de Cc: akpm@osdl.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 3f18d73f420..8b5b3b81d43 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -339,9 +339,8 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, unsigned long bp, char *log_lvl) { - printk("\nCall Trace:\n"); + printk("Call Trace:\n"); dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); - printk("\n"); } void show_trace(struct task_struct *task, struct pt_regs *regs, @@ -386,6 +385,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, printk(" %016lx", *stack++); touch_nmi_watchdog(); } + printk("\n"); show_trace_log_lvl(task, regs, sp, bp, log_lvl); } @@ -443,7 +443,6 @@ void show_registers(struct pt_regs *regs) printk("Stack: "); show_stack_log_lvl(NULL, regs, (unsigned long *)sp, regs->bp, ""); - printk("\n"); printk(KERN_EMERG "Code: "); -- GitLab From dd0078f4f04d939950a792c493d7d97d7ce663b8 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 30 Jul 2008 14:20:54 -0400 Subject: [PATCH 0358/5416] rcu: just rename call_rcu_bh instead of making it a macro Seems that I found a box that has a config that passes call_rcu_bh as a function pointer (see net/sctp/sm_make_chunk.c), so declaring the call_rcu_bh has a macro function isn't good enough. This patch makes it just another name of call_rcu for rcupreempt. Signed-off-by: Steven Rostedt Reviewed-by: "Paul E. McKenney" Signed-off-by: Ingo Molnar --- include/linux/rcupreempt.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index addb5e282f3..3e05c09b54a 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h @@ -57,7 +57,13 @@ static inline void rcu_qsctr_inc(int cpu) rdssp->sched_qs++; } #define rcu_bh_qsctr_inc(cpu) -#define call_rcu_bh(head, rcu) call_rcu(head, rcu) + +/* + * Someone might want to pass call_rcu_bh as a function pointer. + * So this needs to just be a rename and not a macro function. + * (no parentheses) + */ +#define call_rcu_bh call_rcu /** * call_rcu_sched - Queue RCU callback for invocation after sched grace period. -- GitLab From 5802294f1b1895ee19a3d0ae72805da453afb9de Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 30 Jul 2008 14:20:55 -0400 Subject: [PATCH 0359/5416] rcu: trace fix possible mem-leak In the initialization of the RCU trace module, if rcupreempt_debugfs_init() fails, we never free the the trace buffer. This patch frees the trace buffer in case the debugfs fails. Signed-off-by: Steven Rostedt Reviewed-by: "Paul E. McKenney" Signed-off-by: Ingo Molnar --- kernel/rcupreempt_trace.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/rcupreempt_trace.c b/kernel/rcupreempt_trace.c index 5edf82c34bb..35c2d3360ec 100644 --- a/kernel/rcupreempt_trace.c +++ b/kernel/rcupreempt_trace.c @@ -308,11 +308,16 @@ out: static int __init rcupreempt_trace_init(void) { + int ret; + mutex_init(&rcupreempt_trace_mutex); rcupreempt_trace_buf = kmalloc(RCUPREEMPT_TRACE_BUF_SIZE, GFP_KERNEL); if (!rcupreempt_trace_buf) return 1; - return rcupreempt_debugfs_init(); + ret = rcupreempt_debugfs_init(); + if (ret) + kfree(rcupreempt_trace_buf); + return ret; } static void __exit rcupreempt_trace_cleanup(void) -- GitLab From 48e2bd56b1d1ae4b95fb21be778927b64d5c4235 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sat, 2 Aug 2008 12:50:37 -0300 Subject: [PATCH 0360/5416] x86: coding style fixes to arch/x86/kernel/traps_64.c Fix coding style of traps_64.c with improvements suggested by Ingo. Signed-off-by: Gustavo F. Padovan Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps_64.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index fe36d96ba70..5df5d2e97ec 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -84,8 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) void printk_address(unsigned long address, int reliable) { - printk(" [<%016lx>] %s%pS\n", address, reliable ? - "" : "? ", (void *) address); + printk(" [<%016lx>] %s%pS\n", + address, reliable ? "" : "? ", (void *) address); } static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -98,8 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", #if DEBUG_STKSZ > EXCEPTION_STKSZ - [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / - EXCEPTION_STKSZ - 2] = "#DB[?]" + [N_EXCEPTION_STACKS ... + N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; unsigned k; @@ -363,8 +363,10 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); - /* debugging aid: "show_stack(NULL, NULL);" prints the - back trace for this cpu. */ + /* + * debugging aid: "show_stack(NULL, NULL);" prints the + * back trace for this cpu. + */ if (sp == NULL) { if (task) -- GitLab From f88f07e0f0fd6376e081b10930d272a08fbf082f Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 14 Aug 2008 16:58:15 -0400 Subject: [PATCH 0361/5416] x86: alternatives : fix LOCK_PREFIX race with preemptible kernel and CPU hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a kernel thread is preempted in single-cpu mode right after the NOP (nop about to be turned into a lock prefix), then we CPU hotplug a CPU, and then the thread is scheduled back again, a SMP-unsafe atomic operation will be used on shared SMP variables, leading to corruption. No corruption would happen in the reverse case : going from SMP to UP is ok because we split a bit instruction into tiny pieces, which does not present this condition. Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment override prefix should fix this issue. Since the default of the atomic instructions is to use the DS segment anyway, it should not affect the behavior. The exception to this are references that use ESP/RSP and EBP/RBP as the base register (they will use the SS segment), however, in Linux (a) DS == SS at all times, and (b) we do not distinguish between segment violations reported as #SS as opposed to #GP, so there is no need to disassemble the instruction to figure out the suitable segment. This patch assumes that the 0x3E prefix will leave atomic operations as-is (thus assuming they normally touch data in the DS segment). Since there seem to be no obvious ill-use of other segment override prefixes for atomic operations, it should be safe. It can be verified with a quick grep -r LOCK_PREFIX include/asm-x86/ grep -A 1 -r LOCK_PREFIX arch/x86/ Taken from This source : AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions States "Instructions that Reference a Non-Stack Segment—If an instruction encoding references any base register other than rBP or rSP, or if an instruction contains an immediate offset, the default segment is the data segment (DS). These instructions can use the segment-override prefix to select one of the non-default segments, as shown in Table 1-5." Therefore, forcing the DS segment on the atomic operations, which already use the DS segment, should not change. This source : http://wiki.osdev.org/X86_Instruction_Encoding States "In 64-bit the CS, SS, DS and ES segment overrides are ignored." Confirmed by "AMD 64-Bit Technology" A.7 http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/x86-64_overview.pdf "In 64-bit mode, the DS, ES, SS and CS segment-override prefixes have no effect. These four prefixes are no longer treated as segment-override prefixes in the context of multipleprefix rules. Instead, they are treated as null prefixes." This patch applies to 2.6.27-rc2, but would also have to be applied to earlier kernels (2.6.26, 2.6.25, ...). Performance impact of the fix : tests done on "xaddq" and "xaddl" shows it actually improves performances on Intel Xeon, AMD64, Pentium M. It does not change the performance on Pentium II, Pentium 3 and Pentium 4. Xeon E5405 2.0GHz : NR_TESTS 10000000 test empty cycles : 162207948 test test 1-byte nop xadd cycles : 170755422 test test DS override prefix xadd cycles : 170000118 * test test LOCK xadd cycles : 472012134 AMD64 2.0GHz : NR_TESTS 10000000 test empty cycles : 146674549 test test 1-byte nop xadd cycles : 150273860 test test DS override prefix xadd cycles : 149982382 * test test LOCK xadd cycles : 270000690 Pentium 4 3.0GHz NR_TESTS 10000000 test empty cycles : 290001195 test test 1-byte nop xadd cycles : 310000560 test test DS override prefix xadd cycles : 310000575 * test test LOCK xadd cycles : 1050103740 Pentium M 2.0GHz NR_TESTS 10000000 test empty cycles : 180000523 test test 1-byte nop xadd cycles : 320000345 test test DS override prefix xadd cycles : 310000374 * test test LOCK xadd cycles : 480000357 Pentium 3 550MHz NR_TESTS 10000000 test empty cycles : 510000231 test test 1-byte nop xadd cycles : 620000128 test test DS override prefix xadd cycles : 620000110 * test test LOCK xadd cycles : 800000088 Pentium II 350MHz NR_TESTS 10000000 test empty cycles : 200833494 test test 1-byte nop xadd cycles : 340000130 test test DS override prefix xadd cycles : 340000126 * test test LOCK xadd cycles : 530000078 Speed test modules can be found at http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed-32.c http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed.c Macro-benchmarks 2.0GHz E5405 Core 2 dual Quad-Core Xeon Summary * replace smp lock prefixes with DS segment selector prefixes no lock prefix (s) with lock prefix (s) Speedup make -j1 kernel/ 33.94 +/- 0.07 34.91 +/- 0.27 2.8 % hackbench 50 2.99 +/- 0.01 3.74 +/- 0.01 25.1 % * replace smp lock prefixes with 0x90 nops no lock prefix (s) with lock prefix (s) Speedup make -j1 kernel/ 34.16 +/- 0.32 34.91 +/- 0.27 2.2 % hackbench 50 3.00 +/- 0.01 3.74 +/- 0.01 24.7 % Detail : 1 CPU, replace smp lock prefixes with DS segment selector prefixes make -j1 kernel/ real 0m34.067s user 0m30.630s sys 0m2.980s real 0m33.867s user 0m30.582s sys 0m3.024s real 0m33.939s user 0m30.738s sys 0m2.876s real 0m33.913s user 0m30.806s sys 0m2.808s avg : 33.94s std. dev. : 0.07s hackbench 50 Time: 2.978 Time: 2.982 Time: 3.010 Time: 2.984 Time: 2.982 avg : 2.99 std. dev. : 0.01 1 CPU, noreplace-smp make -j1 kernel/ real 0m35.326s user 0m30.630s sys 0m3.260s real 0m34.325s user 0m30.802s sys 0m3.084s real 0m35.568s user 0m30.722s sys 0m3.168s real 0m34.435s user 0m30.886s sys 0m2.996s avg.: 34.91s std. dev. : 0.27s hackbench 50 Time: 3.733 Time: 3.750 Time: 3.761 Time: 3.737 Time: 3.741 avg : 3.74 std. dev. : 0.01 1 CPU, replace smp lock prefixes with 0x90 nops make -j1 kernel/ real 0m34.139s user 0m30.782s sys 0m2.820s real 0m34.010s user 0m30.630s sys 0m2.976s real 0m34.777s user 0m30.658s sys 0m2.916s real 0m33.924s user 0m30.634s sys 0m2.924s real 0m33.962s user 0m30.774s sys 0m2.800s real 0m34.141s user 0m30.770s sys 0m2.828s avg : 34.16 std. dev. : 0.32 hackbench 50 Time: 2.999 Time: 2.994 Time: 3.004 Time: 2.991 Time: 2.988 avg : 3.00 std. dev. : 0.01 I did more runs (20 runs of each) to compare the nop case to the DS prefix case. Results in seconds. They actually does not seems to show a significant difference. NOP 34.155 33.955 34.012 35.299 35.679 34.141 33.995 35.016 34.254 33.957 33.957 34.008 35.013 34.494 33.893 34.295 34.314 34.854 33.991 34.132 DS 34.080 34.304 34.374 35.095 34.291 34.135 33.940 34.208 35.276 34.288 33.861 33.898 34.610 34.709 33.851 34.256 35.161 34.283 33.865 35.078 Used http://www.graphpad.com/quickcalcs/ttest1.cfm?Format=C to do the T-test (yeah, I'm lazy) : Group Group One (DS prefix) Group Two (nops) Mean 34.37815 34.37070 SD 0.46108 0.51905 SEM 0.10310 0.11606 N 20 20 P value and statistical significance: The two-tailed P value equals 0.9620 By conventional criteria, this difference is considered to be not statistically significant. Confidence interval: The mean of Group One minus Group Two equals 0.00745 95% confidence interval of this difference: From -0.30682 to 0.32172 Intermediate values used in calculations: t = 0.0480 df = 38 standard error of difference = 0.155 So, unless these calculus are completely bogus, the difference between the nop and the DS case seems not to be statistically significant. Signed-off-by: Mathieu Desnoyers Acked-by: H. Peter Anvin CC: Linus Torvalds CC: Jeremy Fitzhardinge CC: Roland McGrath CC: Ingo Molnar Cc: Steven Rostedt CC: Steven Rostedt CC: Thomas Gleixner CC: Peter Zijlstra CC: Andrew Morton CC: David Miller CC: Ulrich Drepper CC: Rusty Russell CC: Gregory Haskins CC: Arnaldo Carvalho de Melo CC: "Luis Claudio R. Goncalves" CC: Clark Williams CC: Christoph Lameter CC: Andi Kleen CC: Harvey Harrison Signed-off-by: H. Peter Anvin --- arch/x86/kernel/alternative.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb37b55..7ead11f3732 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -241,25 +241,25 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) continue; if (*ptr > text_end) continue; - text_poke(*ptr, ((unsigned char []){0xf0}), 1); /* add lock prefix */ + /* turn DS segment override prefix into lock prefix */ + text_poke(*ptr, ((unsigned char []){0xf0}), 1); }; } static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) { u8 **ptr; - char insn[1]; if (noreplace_smp) return; - add_nops(insn, 1); for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; if (*ptr > text_end) continue; - text_poke(*ptr, insn, 1); + /* turn lock prefix into DS segment override prefix */ + text_poke(*ptr, ((unsigned char []){0x3E}), 1); }; } -- GitLab From 1f49a2c2aeb22d5abc6d4ea574ff63d37ca55fbe Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 15 Aug 2008 12:45:09 -0400 Subject: [PATCH 0362/5416] x86: revert replace LOCK_PREFIX in futex.h Since we now use DS prefixes instead of NOP to remove LOCK prefixes, there are no longer any issues with instruction boundaries moving around. Depends on : x86 alternatives : fix LOCK_PREFIX race with preemptible kernel and CPU hotplug On Thu, 14 Aug 2008, Mathieu Desnoyers wrote: > > Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment > override prefix should fix this issue. Since the default of the atomic > instructions is to use the DS segment anyway, it should not affect the > behavior. Ok, so I think this is an _excellent_ patch, but I'd like to also then use LOCK_PREFIX in include/asm-x86/futex.h. See commit 9d55b9923a1b7ea8193b8875c57ec940dc2ff027. Linus Applies to 2.6.27-rc2 (and -rc3 unless hell broke loose in futex.h between rc2 and rc3). Signed-off-by: Mathieu Desnoyers CC: Linus Torvalds CC: H. Peter Anvin CC: Jeremy Fitzhardinge CC: Roland McGrath CC: Ingo Molnar Cc: Steven Rostedt CC: Steven Rostedt CC: Thomas Gleixner CC: Peter Zijlstra CC: Andrew Morton CC: David Miller CC: Ulrich Drepper CC: Rusty Russell CC: Gregory Haskins CC: Arnaldo Carvalho de Melo CC: "Luis Claudio R. Goncalves" CC: Clark Williams CC: Christoph Lameter CC: Andi Kleen CC: Harvey Harrison Signed-off-by: H. Peter Anvin --- include/asm-x86/futex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h index e7a76b37b33..d1b988ce080 100644 --- a/include/asm-x86/futex.h +++ b/include/asm-x86/futex.h @@ -25,7 +25,7 @@ asm volatile("1:\tmovl %2, %0\n" \ "\tmovl\t%0, %3\n" \ "\t" insn "\n" \ - "2:\tlock; cmpxchgl %3, %2\n" \ + "2:\t" LOCK_PREFIX "cmpxchgl %3, %2\n" \ "\tjnz\t1b\n" \ "3:\t.section .fixup,\"ax\"\n" \ "4:\tmov\t%5, %1\n" \ @@ -64,7 +64,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_ADD: - __futex_atomic_op1("lock; xaddl %0, %2", ret, oldval, + __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_OR: @@ -122,7 +122,7 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - asm volatile("1:\tlock; cmpxchgl %3, %1\n" + asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" "2:\t.section .fixup, \"ax\"\n" "3:\tmov %2, %0\n" "\tjmp 2b\n" -- GitLab From 5bbd4c3724008c93cf3efdfc38a3402e245ab506 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 15 Aug 2008 12:56:59 -0400 Subject: [PATCH 0363/5416] x86: spinlock use LOCK_PREFIX Since we are now using DS prefixes instead of NOP to remove LOCK prefixes, there is no longer any problems with instruction boundaries moving around. * Linus Torvalds (torvalds@linux-foundation.org) wrote: > > > On Thu, 14 Aug 2008, Mathieu Desnoyers wrote: > > > > Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment > > override prefix should fix this issue. Since the default of the atomic > > instructions is to use the DS segment anyway, it should not affect the > > behavior. > > Ok, so I think this is an _excellent_ patch, but I'd like to also then use > LOCK_PREFIX in include/asm-x86/futex.h. > > See commit 9d55b9923a1b7ea8193b8875c57ec940dc2ff027. > > Linus Unless there a rationale for this, I think these be changed to LOCK_PREFIX too. grep "lock ;" include/asm-x86/spinlock.h "lock ; cmpxchgw %w1,%2\n\t" asm volatile("lock ; xaddl %0, %1\n" "lock ; cmpxchgl %1,%2\n\t" Applies to 2.6.27-rc2. Signed-off-by: Mathieu Desnoyers Acked-by: Linus Torvalds CC: Linus Torvalds CC: H. Peter Anvin CC: Jeremy Fitzhardinge CC: Roland McGrath CC: Ingo Molnar Cc: Steven Rostedt CC: Steven Rostedt CC: Thomas Gleixner CC: Peter Zijlstra CC: Andrew Morton CC: David Miller CC: Ulrich Drepper CC: Rusty Russell CC: Gregory Haskins CC: Arnaldo Carvalho de Melo CC: "Luis Claudio R. Goncalves" CC: Clark Williams CC: Christoph Lameter CC: Andi Kleen CC: Harvey Harrison Signed-off-by: H. Peter Anvin --- include/asm-x86/spinlock.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h index 4f9a9861799..0b4d59a93d2 100644 --- a/include/asm-x86/spinlock.h +++ b/include/asm-x86/spinlock.h @@ -97,7 +97,7 @@ static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock) "jne 1f\n\t" "movw %w0,%w1\n\t" "incb %h1\n\t" - "lock ; cmpxchgw %w1,%2\n\t" + LOCK_PREFIX "cmpxchgw %w1,%2\n\t" "1:" "sete %b1\n\t" "movzbl %b1,%0\n\t" @@ -135,7 +135,7 @@ static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock) int inc = 0x00010000; int tmp; - asm volatile("lock ; xaddl %0, %1\n" + asm volatile(LOCK_PREFIX "xaddl %0, %1\n" "movzwl %w0, %2\n\t" "shrl $16, %0\n\t" "1:\t" @@ -162,7 +162,7 @@ static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock) "cmpl %0,%1\n\t" "jne 1f\n\t" "addl $0x00010000, %1\n\t" - "lock ; cmpxchgl %1,%2\n\t" + LOCK_PREFIX "cmpxchgl %1,%2\n\t" "1:" "sete %b1\n\t" "movzbl %b1,%0\n\t" -- GitLab From 6f6da97faf29f87b3980a6992fb8cab44b4c444d Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 23:05:19 +0400 Subject: [PATCH 0364/5416] x86: apic - sync_Arb_IDs style fixup No changes on binary level Signed-off-by: Cyrill Gorcunov Acked-by: Maciej W. Rozycki Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d07488993ee..60575c05151 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -909,13 +909,15 @@ void __init sync_Arb_IDs(void) */ if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; + /* * Wait for idle. */ apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | + APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 41aff346063..72e94ab0e36 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -755,7 +755,8 @@ void __init sync_Arb_IDs(void) apic_wait_icr_idle(); apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_write(APIC_ICR, APIC_DEST_ALLINC | + APIC_INT_LEVELTRIG | APIC_DM_INIT); } /* -- GitLab From 638c0411922540deaf8797cacf73513b17618405 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 15 Aug 2008 23:05:18 +0400 Subject: [PATCH 0365/5416] x86: apic - unify init_bsp_APIC - remove redundant read of APIC_LVR register in 64bit mode - APIC is always integrated for 64bit mode so gcc will eliminate lapic_is_integrated call Signed-off-by: Cyrill Gorcunov Acked-by: Maciej W. Rozycki Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 14 +++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 60575c05151..16d9721788c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -925,7 +925,7 @@ void __init sync_Arb_IDs(void) */ void __init init_bsp_APIC(void) { - unsigned long value; + unsigned int value; /* * Don't do the setup now if we have a SMP BIOS as the @@ -946,11 +946,13 @@ void __init init_bsp_APIC(void) value &= ~APIC_VECTOR_MASK; value |= APIC_SPIV_APIC_ENABLED; +#ifdef CONFIG_X86_32 /* This bit is reserved on P4/Xeon and should be cleared */ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15)) value &= ~APIC_SPIV_FOCUS_DISABLED; else +#endif value |= APIC_SPIV_FOCUS_DISABLED; value |= SPURIOUS_APIC_VECTOR; apic_write(APIC_SPIV, value); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 72e94ab0e36..99d18b8976a 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -773,8 +773,6 @@ void __init init_bsp_APIC(void) if (smp_found_config || !cpu_has_apic) return; - value = apic_read(APIC_LVR); - /* * Do not trust the local APIC being empty at bootup. */ @@ -786,7 +784,15 @@ void __init init_bsp_APIC(void) value = apic_read(APIC_SPIV); value &= ~APIC_VECTOR_MASK; value |= APIC_SPIV_APIC_ENABLED; - value |= APIC_SPIV_FOCUS_DISABLED; + +#ifdef CONFIG_X86_32 + /* This bit is reserved on P4/Xeon and should be cleared */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + (boot_cpu_data.x86 == 15)) + value &= ~APIC_SPIV_FOCUS_DISABLED; + else +#endif + value |= APIC_SPIV_FOCUS_DISABLED; value |= SPURIOUS_APIC_VECTOR; apic_write(APIC_SPIV, value); @@ -795,6 +801,8 @@ void __init init_bsp_APIC(void) */ apic_write(APIC_LVT0, APIC_DM_EXTINT); value = APIC_DM_NMI; + if (!lapic_is_integrated()) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; apic_write(APIC_LVT1, value); } -- GitLab From 6d341675f8e715464849e5d5563a72c1d39e800d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Va=C5=A1ut?= Date: Sat, 16 Aug 2008 15:35:57 +0100 Subject: [PATCH 0366/5416] [ARM] 5199/1: PalmLD: PCMCIA driver PCMCIA driver for Palm LifeDrive Signed-off-by: Marek Vasut Signed-off-by: Russell King --- drivers/pcmcia/Makefile | 3 +- drivers/pcmcia/pxa2xx_palmld.c | 151 +++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 drivers/pcmcia/pxa2xx_palmld.c diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 269a9e913ba..c6d89fd3dcf 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -72,5 +72,6 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o -pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o +pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o +pxa2xx_cs-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c new file mode 100644 index 00000000000..1736c67e547 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -0,0 +1,151 @@ +/* + * linux/drivers/pcmcia/pxa2xx_palmld.c + * + * Driver for Palm LifeDrive PCMCIA + * + * Copyright (C) 2006 Alex Osborne + * Copyright (C) 2007-2008 Marek Vasut + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +#include +#include +#include "soc_common.h" + +static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + int ret; + + ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR"); + if (ret) + goto err1; + ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0); + if (ret) + goto err2; + + ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST"); + if (ret) + goto err2; + ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1); + if (ret) + goto err3; + + ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY"); + if (ret) + goto err3; + ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY); + if (ret) + goto err4; + + skt->irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY); + return 0; + +err4: + gpio_free(GPIO_NR_PALMLD_PCMCIA_READY); +err3: + gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET); +err2: + gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER); +err1: + return ret; +} + +static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +{ + gpio_free(GPIO_NR_PALMLD_PCMCIA_READY); + gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET); + gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER); +} + +static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt, + struct pcmcia_state *state) +{ + state->detect = 1; /* always inserted */ + state->ready = !!gpio_get_value(GPIO_NR_PALMLD_PCMCIA_READY); + state->bvd1 = 1; + state->bvd2 = 1; + state->wrprot = 0; + state->vs_3v = 1; + state->vs_Xv = 0; +} + +static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, + const socket_state_t *state) +{ + gpio_set_value(GPIO_NR_PALMLD_PCMCIA_POWER, 1); + gpio_set_value(GPIO_NR_PALMLD_PCMCIA_RESET, + !!(state->flags & SS_RESET)); + + return 0; +} + +static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt) +{ +} + +static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +{ +} + +static struct pcmcia_low_level palmld_pcmcia_ops = { + .owner = THIS_MODULE, + + .first = 0, + .nr = 2, + + .hw_init = palmld_pcmcia_hw_init, + .hw_shutdown = palmld_pcmcia_hw_shutdown, + + .socket_state = palmld_pcmcia_socket_state, + .configure_socket = palmld_pcmcia_configure_socket, + + .socket_init = palmld_pcmcia_socket_init, + .socket_suspend = palmld_pcmcia_socket_suspend, +}; + +static struct platform_device *palmld_pcmcia_device; + +static int __init palmld_pcmcia_init(void) +{ + int ret; + + if (!machine_is_palmld()) + return -ENODEV; + + palmld_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); + if (!palmld_pcmcia_device) + return -ENOMEM; + + ret = platform_device_add_data(palmld_pcmcia_device, &palmld_pcmcia_ops, + sizeof(palmld_pcmcia_ops)); + + if (!ret) + ret = platform_device_add(palmld_pcmcia_device); + + if (ret) + platform_device_put(palmld_pcmcia_device); + + return ret; +} + +static void __exit palmld_pcmcia_exit(void) +{ + platform_device_unregister(palmld_pcmcia_device); +} + +module_init(palmld_pcmcia_init); +module_exit(palmld_pcmcia_exit); + +MODULE_AUTHOR("Alex Osborne ," + " Marek Vasut "); +MODULE_DESCRIPTION("PCMCIA support for Palm LifeDrive"); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); +MODULE_LICENSE("GPL"); -- GitLab From 6764014bc8bb4849f6a4f336477e873ad5861ed2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:50 +0400 Subject: [PATCH 0367/5416] x86: apic - unify clear_local_APIC - Remove redundant masking of APIC_LVTTHMR register in apic_32.c - Add masking of APIC_LVTTHMR register to apic_64.c. We use a bit complicated #ifdef here: CONFIG_X86_MCE_P4THERMAL is 32bit specific and X86_MCE_INTEL is 64bit specific so the appropriate config variable will be set by Kconfig. - the APIC_ESR register clearing in apic_64.c now uses not straightforward way but this is allowed tradeoff. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 +----- arch/x86/kernel/apic_64.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 16d9721788c..3131603a4d6 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -754,7 +754,7 @@ void clear_local_APIC(void) } /* lets not touch this if we didn't frob it */ -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) if (maxlvt >= 5) { v = apic_read(APIC_LVTTHMR); apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); @@ -771,10 +771,6 @@ void clear_local_APIC(void) if (maxlvt >= 4) apic_write(APIC_LVTPC, APIC_LVT_MASKED); -#ifdef CONFIG_X86_MCE_P4THERMAL - if (maxlvt >= 5) - apic_write(APIC_LVTTHMR, APIC_LVT_MASKED); -#endif /* Integrated APIC (!82489DX) ? */ if (lapic_is_integrated()) { if (maxlvt > 3) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 99d18b8976a..d834b758362 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -630,6 +630,13 @@ void clear_local_APIC(void) apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); } + /* lets not touch this if we didn't frob it */ +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) + if (maxlvt >= 5) { + v = apic_read(APIC_LVTTHMR); + apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); + } +#endif /* * Clean APIC state for other OSs: */ @@ -640,8 +647,14 @@ void clear_local_APIC(void) apic_write(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) apic_write(APIC_LVTPC, APIC_LVT_MASKED); - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); + + /* Integrated APIC (!82489DX) ? */ + if (lapic_is_integrated()) { + if (maxlvt > 3) + /* Clear ESR due to Pentium errata 3AP and 11AP */ + apic_write(APIC_ESR, 0); + apic_read(APIC_ESR); + } } /** -- GitLab From 92206c909ad1d4f9c355b4842722d5a355d6b76b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:51 +0400 Subject: [PATCH 0368/5416] x86: apic - unify lapic_resume Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 29 ++++++++++++++++++----------- arch/x86/kernel/apic_64.c | 19 +++++++++++++++---- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3131603a4d6..3d40213d3af 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1606,16 +1606,21 @@ static int lapic_resume(struct sys_device *dev) local_irq_save(flags); - /* - * Make sure the APICBASE points to the right address - * - * FIXME! This will be wrong if we ever support suspend on - * SMP! We'll need to do this as part of the CPU restore! - */ - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; - wrmsr(MSR_IA32_APICBASE, l, h); +#ifdef CONFIG_X86_64 + if (x2apic) + enable_x2apic(); + else +#endif + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + wrmsr(MSR_IA32_APICBASE, l, h); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); @@ -1625,7 +1630,7 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); #endif @@ -1639,7 +1644,9 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); + local_irq_restore(flags); + return 0; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d834b758362..e542a2d08de 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1412,13 +1412,22 @@ static int lapic_resume(struct sys_device *dev) maxlvt = lapic_get_maxlvt(); local_irq_save(flags); - if (!x2apic) { + +#ifdef CONFIG_X86_64 + if (x2apic) + enable_x2apic(); + else +#endif + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); - } else - enable_x2apic(); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); @@ -1428,7 +1437,7 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); -#ifdef CONFIG_X86_MCE_INTEL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); #endif @@ -1442,7 +1451,9 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); + local_irq_restore(flags); + return 0; } -- GitLab From 24968cfdd4c3cf61338495dd0f9bb8a6907d2087 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:52 +0400 Subject: [PATCH 0369/5416] x86: apic - unify lapic_suspend Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 +- arch/x86/kernel/apic_64.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3d40213d3af..6cb8aaaf10f 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1582,7 +1582,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); -#ifdef CONFIG_X86_MCE_P4THERMAL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); #endif diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index e542a2d08de..13dea935b4e 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1390,10 +1390,11 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); -#ifdef CONFIG_X86_MCE_INTEL +#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) if (maxlvt >= 5) apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); #endif + local_irq_save(flags); disable_local_APIC(); local_irq_restore(flags); -- GitLab From 274cfe5912eebe9d4e1a4c451fe617289a181fcf Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:53 +0400 Subject: [PATCH 0370/5416] x86: apic - rearrange functions and comments Rearrange functions and comments to find differences easier. Also use apic_printk in setup_boot_APIC_clock for 64bit mode. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 69 ++++++++++++++++++++++----------------- arch/x86/kernel/apic_64.c | 48 +++++++++++++++++++++------ 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6cb8aaaf10f..9e8702eebd4 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -251,6 +251,9 @@ int lapic_get_maxlvt(void) * this function twice on the boot CPU, once with a bogus timeout * value, second time for real. The other (noncalibrating) CPUs * call this function only once, with the real, calibrated value. + * + * We do reads before writes even if unnecessary, to get around the + * P5 APIC double write bug. */ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) { @@ -279,6 +282,36 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); } +/* + * Setup extended LVT, AMD specific (K8, family 10h) + * + * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and + * MCE interrupts are supported. Thus MCE offset must be set to 0. + */ + +#define APIC_EILVT_LVTOFF_MCE 0 +#define APIC_EILVT_LVTOFF_IBS 1 + +static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) +{ + unsigned long reg = (lvt_off << 4) + APIC_EILVT0; + unsigned int v = (mask << 16) | (msg_type << 8) | vector; + + apic_write(reg, v); +} + +u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) +{ + setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); + return APIC_EILVT_LVTOFF_MCE; +} + +u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) +{ + setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); + return APIC_EILVT_LVTOFF_IBS; +} + /* * Program the next event, relative to now */ @@ -298,7 +331,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, unsigned long flags; unsigned int v; - /* Lapic used for broadcast ? */ + /* Lapic used as dummy for broadcast ? */ if (evt->features & CLOCK_EVT_FEAT_DUMMY) return; @@ -680,35 +713,6 @@ int setup_profiling_timer(unsigned int multiplier) return -EINVAL; } -/* - * Setup extended LVT, AMD specific (K8, family 10h) - * - * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and - * MCE interrupts are supported. Thus MCE offset must be set to 0. - */ - -#define APIC_EILVT_LVTOFF_MCE 0 -#define APIC_EILVT_LVTOFF_IBS 1 - -static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) -{ - unsigned long reg = (lvt_off << 4) + APIC_EILVT0; - unsigned int v = (mask << 16) | (msg_type << 8) | vector; - apic_write(reg, v); -} - -u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) -{ - setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); - return APIC_EILVT_LVTOFF_MCE; -} - -u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) -{ - setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); - return APIC_EILVT_LVTOFF_IBS; -} - /* * Local APIC start and shutdown */ @@ -1542,6 +1546,11 @@ void __cpuinit generic_processor_info(int apicid, int version) #ifdef CONFIG_PM static struct { + /* + * 'active' is true if the local APIC was enabled by us and + * not the BIOS; this signifies that we are also responsible + * for disabling it before entering apm/acpi suspend + */ int active; /* r/w apic fields */ unsigned int apic_id; diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 13dea935b4e..46523c0cc6f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -81,6 +81,9 @@ static void lapic_timer_setup(enum clock_event_mode mode, static void lapic_timer_broadcast(cpumask_t mask); static void apic_pm_activate(void); +/* + * The local apic timer can be used for any function which is CPU local. + */ static struct clock_event_device lapic_clockevent = { .name = "lapic", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT @@ -127,6 +130,11 @@ static int modern_apic(void) return lapic_get_version() >= 0x14; } +/* + * Paravirt kernels also might be using these below ops. So we still + * use generic apic_read()/apic_write(), which might be pointing to different + * ops in PARAVIRT case. + */ void xapic_wait_icr_idle(void) { while (apic_read(APIC_ICR) & APIC_ICR_BUSY) @@ -175,7 +183,6 @@ static struct apic_ops xapic_ops = { }; struct apic_ops __read_mostly *apic_ops = &xapic_ops; - EXPORT_SYMBOL_GPL(apic_ops); static void x2apic_wait_icr_idle(void) @@ -244,6 +251,10 @@ int lapic_get_maxlvt(void) return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; } +/* + * Local APIC timer + */ + /* Clock divisor is set to 1 */ #define APIC_DIVISOR 1 @@ -257,7 +268,6 @@ int lapic_get_maxlvt(void) * We do reads before writes even if unnecessary, to get around the * P5 APIC double write bug. */ - static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) { unsigned int lvtt_value, tmp_value; @@ -474,10 +484,10 @@ static int __init calibrate_APIC_clock(void) void __init setup_boot_APIC_clock(void) { /* - * The local apic timer can be disabled via the kernel commandline. - * Register the lapic timer as a dummy clock event source on SMP - * systems, so the broadcast mechanism is used. On UP systems simply - * ignore it. + * The local apic timer can be disabled via the kernel + * commandline or from the CPU detection code. Register the lapic + * timer as a dummy clock event source on SMP systems, so the + * broadcast mechanism is used. On UP systems simply ignore it. */ if (disable_apic_timer) { printk(KERN_INFO "Disabling APIC timer\n"); @@ -489,7 +499,9 @@ void __init setup_boot_APIC_clock(void) return; } - printk(KERN_INFO "Using local APIC timer interrupts.\n"); + apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" + "calibrating APIC timer ...\n"); + if (calibrate_APIC_clock()) { /* No broadcast on UP ! */ if (num_possible_cpus() > 1) @@ -508,6 +520,7 @@ void __init setup_boot_APIC_clock(void) printk(KERN_WARNING "APIC timer registered as dummy," " due to nmi_watchdog=%d!\n", nmi_watchdog); + /* Setup the lapic or request the broadcast */ setup_APIC_timer(); } @@ -577,6 +590,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) irq_enter(); local_apic_timer_interrupt(); irq_exit(); + set_irq_regs(old_regs); } @@ -1248,6 +1262,13 @@ void __init connect_bsp_APIC(void) enable_apic_mode(); } +/** + * disconnect_bsp_APIC - detach the APIC from the interrupt system + * @virt_wire_setup: indicates, whether virtual wire mode is selected + * + * Virtual wire mode is necessary to deliver legacy interrupts even when the + * APIC is disabled. + */ void disconnect_bsp_APIC(int virt_wire_setup) { /* Go back to Virtual Wire compatibility mode */ @@ -1347,9 +1368,11 @@ int hard_smp_processor_id(void) #ifdef CONFIG_PM static struct { - /* 'active' is true if the local APIC was enabled by us and - not the BIOS; this signifies that we are also responsible - for disabling it before entering apm/acpi suspend */ + /* + * 'active' is true if the local APIC was enabled by us and + * not the BIOS; this signifies that we are also responsible + * for disabling it before entering apm/acpi suspend + */ int active; /* r/w apic fields */ unsigned int apic_id; @@ -1458,6 +1481,11 @@ static int lapic_resume(struct sys_device *dev) return 0; } +/* + * This device has no shutdown method - fully functioning local APICs + * are needed on every CPU up until machine_halt/restart/poweroff. + */ + static struct sysdev_class lapic_sysclass = { .name = "lapic", .resume = lapic_resume, -- GitLab From 9c803869f5f5e3d7ad94b2926474b2882e30073b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:54 +0400 Subject: [PATCH 0371/5416] x86: apic - unify lapic_is_integrated Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++++ arch/x86/kernel/apic_64.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 9e8702eebd4..41134d4e6a6 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -128,7 +128,11 @@ static inline int lapic_get_version(void) */ static inline int lapic_is_integrated(void) { +#ifdef CONFIG_X86_64 + return 1; +#else return APIC_INTEGRATED(lapic_get_version()); +#endif } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46523c0cc6f..18c0b8cd237 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -111,11 +111,15 @@ static inline int lapic_get_version(void) } /* - * Check, if the APIC is integrated or a seperate chip + * Check, if the APIC is integrated or a separate chip */ static inline int lapic_is_integrated(void) { +#ifdef CONFIG_X86_64 return 1; +#else + return APIC_INTEGRATED(lapic_get_version()); +#endif } /* -- GitLab From cf9768d7514d59b3179a886c4a47908d72e6cf76 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 16 Aug 2008 23:21:55 +0400 Subject: [PATCH 0372/5416] x86: apic - unify xapic_icr_read Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 18c0b8cd237..5e0738131e5 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -174,7 +174,7 @@ u64 xapic_icr_read(void) icr2 = apic_read(APIC_ICR2); icr1 = apic_read(APIC_ICR); - return (icr1 | ((u64)icr2 << 32)); + return icr1 | ((u64)icr2 << 32); } static struct apic_ops xapic_ops = { -- GitLab From ccdffb9a88b2907b159538d7bfd6256621db4f84 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 26 Jul 2008 14:26:06 +0200 Subject: [PATCH 0373/5416] r8169: get ethtool settings through the generic mii helper It avoids to report unsupported link capabilities with the fast-ethernet only 8101/8102. Signed-off-by: Francois Romieu Tested-by: Martin Capitanio Fixed-by: Ivan Vecera Cc: Edward Hsu --- drivers/net/r8169.c | 99 +++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a3e3895e503..dac2677eeed 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -370,8 +370,9 @@ struct ring_info { }; enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_WOL = (1 << 0), + RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_GMII = (1 << 2), }; struct rtl8169_private { @@ -406,13 +407,15 @@ struct rtl8169_private { struct vlan_group *vlgrp; #endif int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); - void (*get_settings)(struct net_device *, struct ethtool_cmd *); + int (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void __iomem *); void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); struct delayed_work task; unsigned features; + + struct mii_if_info mii; }; MODULE_AUTHOR("Realtek and the Linux r8169 crew "); @@ -482,6 +485,23 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) return value; } +static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, + int val) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + mdio_write(ioaddr, location, val); +} + +static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + return mdio_read(ioaddr, location); +} + static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) { RTL_W16(IntrMask, 0x0000); @@ -850,7 +870,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, #endif -static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) +static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; @@ -867,65 +887,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = SPEED_1000; cmd->duplex = DUPLEX_FULL; /* Always set */ + + return 0; } -static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) +static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u8 status; - - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP; - - cmd->autoneg = 1; - cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - cmd->advertising |= ADVERTISED_1000baseT_Full; - - status = RTL_R8(PHYstatus); - - if (status & _1000bpsF) - cmd->speed = SPEED_1000; - else if (status & _100bps) - cmd->speed = SPEED_100; - else if (status & _10bps) - cmd->speed = SPEED_10; - - if (status & TxFlowCtrl) - cmd->advertising |= ADVERTISED_Asym_Pause; - if (status & RxFlowCtrl) - cmd->advertising |= ADVERTISED_Pause; - - cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; + + return mii_ethtool_gset(&tp->mii, cmd); } static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); unsigned long flags; + int rc; spin_lock_irqsave(&tp->lock, flags); - tp->get_settings(dev, cmd); + rc = tp->get_settings(dev, cmd); spin_unlock_irqrestore(&tp->lock, flags); - return 0; + return rc; } static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, @@ -1513,7 +1497,7 @@ static const struct rtl_cfg_info { unsigned int align; u16 intr_event; u16 napi_event; - unsigned msi; + unsigned features; } rtl_cfg_infos [] = { [RTL_CFG_0] = { .hw_start = rtl_hw_start_8169, @@ -1522,7 +1506,7 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = 0 + .features = RTL_FEATURE_GMII }, [RTL_CFG_1] = { .hw_start = rtl_hw_start_8168, @@ -1531,7 +1515,7 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI + .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI }, [RTL_CFG_2] = { .hw_start = rtl_hw_start_8101, @@ -1540,7 +1524,7 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .msi = RTL_FEATURE_MSI + .features = RTL_FEATURE_MSI } }; @@ -1552,7 +1536,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, u8 cfg2; cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->msi) { + if (cfg->features & RTL_FEATURE_MSI) { if (pci_enable_msi(pdev)) { dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); } else { @@ -1578,6 +1562,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; const unsigned int region = cfg->region; struct rtl8169_private *tp; + struct mii_if_info *mii; struct net_device *dev; void __iomem *ioaddr; unsigned int i; @@ -1602,6 +1587,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->pci_dev = pdev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); + mii = &tp->mii; + mii->dev = dev; + mii->mdio_read = rtl_mdio_read; + mii->mdio_write = rtl_mdio_write; + mii->phy_id_mask = 0x1f; + mii->reg_num_mask = 0x1f; + mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); + /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pci_enable_device(pdev); if (rc < 0) { -- GitLab From 458a9f617adfb2fc5f38e7673339115c4ba3290f Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 2 Aug 2008 15:50:02 +0200 Subject: [PATCH 0374/5416] r8169: Tx performance tweak helper Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dac2677eeed..26fa6e0c6d9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2054,12 +2054,20 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } +static void rtl_tx_performance_tweak(struct pci_dev *pdev, u8 force) +{ + u8 ctl; + + pci_read_config_byte(pdev, 0x69, &ctl); + ctl = (ctl & ~0x70) | force; + pci_write_config_byte(pdev, 0x69, ctl); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; - u8 ctl; RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -2073,10 +2081,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); - /* Tx performance tweak. */ - pci_read_config_byte(pdev, 0x69, &ctl); - ctl = (ctl & ~0x70) | 0x50; - pci_write_config_byte(pdev, 0x69, ctl); + rtl_tx_performance_tweak(pdev, 0x50); RTL_W16(IntrMitigate, 0x5151); -- GitLab From 9c14ceafa5ca7f57225a43fb0785c56ddc7f1823 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 5 Jul 2008 00:21:15 +0200 Subject: [PATCH 0375/5416] r8169: use pci_find_capability for the PCI-E features Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 26fa6e0c6d9..ae149a93062 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -61,6 +61,7 @@ static const int multicast_filter_limit = 32; /* MAC address length */ #define MAC_ADDR_LEN 6 +#define MAX_READ_REQUEST_SHIFT 12 #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ @@ -412,6 +413,7 @@ struct rtl8169_private { void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); + int pcie_cap; struct delayed_work task; unsigned features; @@ -1663,6 +1665,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_res_4; } + tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (!tp->pcie_cap && netif_msg_probe(tp)) + dev_info(&pdev->dev, "no PCI Express capability\n"); + /* Unneeded ? Don't mess with Mrs. Murphy. */ rtl8169_irq_mask_and_ack(ioaddr); @@ -2054,13 +2060,19 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u8 force) +static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { - u8 ctl; + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8169_private *tp = netdev_priv(dev); + int cap = tp->pcie_cap; + + if (cap) { + u16 ctl; - pci_read_config_byte(pdev, 0x69, &ctl); - ctl = (ctl & ~0x70) | force; - pci_write_config_byte(pdev, 0x69, ctl); + pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); + ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); + } } static void rtl_hw_start_8168(struct net_device *dev) @@ -2081,7 +2093,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); - rtl_tx_performance_tweak(pdev, 0x50); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W16(IntrMitigate, 0x5151); @@ -2116,8 +2128,12 @@ static void rtl_hw_start_8101(struct net_device *dev) if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - pci_write_config_word(pdev, 0x68, 0x00); - pci_write_config_word(pdev, 0x69, 0x08); + int cap = tp->pcie_cap; + + if (cap) { + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_NOSNOOP_EN); + } } RTL_W8(Cfg9346, Cfg9346_Unlock); -- GitLab From f162a5d1b326d54b0be7e3100f69763d8a707721 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 1 Jun 2008 22:37:49 +0200 Subject: [PATCH 0376/5416] r8169: add 8168/8101 registers description Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 47 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index ae149a93062..600540e3670 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -197,9 +197,6 @@ enum rtl_registers { Config5 = 0x56, MultiIntr = 0x5c, PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, PHYstatus = 0x6c, RxMaxSize = 0xda, CPlusCmd = 0xe0, @@ -213,6 +210,32 @@ enum rtl_registers { FuncForceEvent = 0xfc, }; +enum rtl8110_registers { + TBICSR = 0x64, + TBI_ANAR = 0x68, + TBI_LPAR = 0x6a, +}; + +enum rtl8168_8101_registers { + CSIDR = 0x64, + CSIAR = 0x68, +#define CSIAR_FLAG 0x80000000 +#define CSIAR_WRITE_CMD 0x80000000 +#define CSIAR_BYTE_ENABLE 0x0f +#define CSIAR_BYTE_ENABLE_SHIFT 12 +#define CSIAR_ADDR_MASK 0x0fff + + EPHYAR = 0x80, +#define EPHYAR_FLAG 0x80000000 +#define EPHYAR_WRITE_CMD 0x80000000 +#define EPHYAR_REG_MASK 0x1f +#define EPHYAR_REG_SHIFT 16 +#define EPHYAR_DATA_MASK 0xffff + DBG_REG = 0xd1, +#define FIX_NAK_1 (1 << 4) +#define FIX_NAK_2 (1 << 3) +}; + enum rtl_register_content { /* InterruptStatusBits */ SYSErr = 0x8000, @@ -266,7 +289,13 @@ enum rtl_register_content { TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ /* Config1 register p.24 */ + LEDS1 = (1 << 7), + LEDS0 = (1 << 6), MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ + Speed_down = (1 << 4), + MEMMAP = (1 << 3), + IOMAP = (1 << 2), + VPD = (1 << 1), PMEnable = (1 << 0), /* Power Management Enable */ /* Config2 register p. 25 */ @@ -276,6 +305,7 @@ enum rtl_register_content { /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ + Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ /* Config5 register p.27 */ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ @@ -293,7 +323,16 @@ enum rtl_register_content { TBINwComplete = 0x01000000, /* CPlusCmd p.31 */ - PktCntrDisable = (1 << 7), // 8168 + EnableBist = (1 << 15), // 8168 8101 + Mac_dbgo_oe = (1 << 14), // 8168 8101 + Normal_mode = (1 << 13), // unused + Force_half_dup = (1 << 12), // 8168 8101 + Force_rxflow_en = (1 << 11), // 8168 8101 + Force_txflow_en = (1 << 10), // 8168 8101 + Cxpl_dbg_sel = (1 << 9), // 8168 8101 + ASF = (1 << 8), // 8168 8101 + PktCntrDisable = (1 << 7), // 8168 8101 + Mac_dbgo_sel = 0x001c, // 8168 RxVlan = (1 << 6), RxChkSum = (1 << 5), PCIDAC = (1 << 4), -- GitLab From dacf815434a4d5f5b45687873df46927c64cfb19 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 2 Aug 2008 20:44:13 +0200 Subject: [PATCH 0377/5416] r8169: add hw start helpers for the 8168 and the 8101 This commit triggers three 'defined but not used' warnings but I prefer avoiding to tie these helpers to a specific change in the hw start sequences of the 8168 or of the 8101. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 600540e3670..f4ad9ff2686 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -526,6 +526,11 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) return value; } +static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) +{ + mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); +} + static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, int val) { @@ -543,6 +548,72 @@ static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) return mdio_read(ioaddr, location); } +static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) +{ + unsigned int i; + + RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | + (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); + + for (i = 0; i < 100; i++) { + if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) + break; + udelay(10); + } +} + +static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) +{ + u16 value = 0xffff; + unsigned int i; + + RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); + + for (i = 0; i < 100; i++) { + if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { + value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; + break; + } + udelay(10); + } + + return value; +} + +static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) +{ + unsigned int i; + + RTL_W32(CSIDR, value); + RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | + CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); + + for (i = 0; i < 100; i++) { + if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) + break; + udelay(10); + } +} + +static u32 rtl_csi_read(void __iomem *ioaddr, int addr) +{ + u32 value = ~0x00; + unsigned int i; + + RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | + CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); + + for (i = 0; i < 100; i++) { + if (RTL_R32(CSIAR) & CSIAR_FLAG) { + value = RTL_R32(CSIDR); + break; + } + udelay(10); + } + + return value; +} + static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) { RTL_W16(IntrMask, 0x0000); @@ -2114,6 +2185,31 @@ static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) } } +static void rtl_csi_access_enable(void __iomem *ioaddr) +{ + u32 csi; + + csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; + rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); +} + +struct ephy_info { + unsigned int offset; + u16 mask; + u16 bits; +}; + +static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) +{ + u16 w; + + while (len-- > 0) { + w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; + rtl_ephy_write(ioaddr, e->offset, w); + e++; + } +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); -- GitLab From 2857ffb7b8913ef713533ac5783abd70a20529e4 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 2 Aug 2008 21:08:49 +0200 Subject: [PATCH 0378/5416] r8169: additional 8101 and 8102 support Signed-off-by: Ivan Vecera Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 124 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f4ad9ff2686..bbaf8a55080 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -96,6 +96,10 @@ enum mac_version { RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe + RTL_GIGA_MAC_VER_07 = 0x07, // 8102e + RTL_GIGA_MAC_VER_08 = 0x08, // 8102e + RTL_GIGA_MAC_VER_09 = 0x09, // 8102e + RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb @@ -122,6 +126,10 @@ static const struct { _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe + _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E + _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E + _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E + _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 @@ -837,8 +845,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, } } - /* The 8100e/8101e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || + /* The 8100e/8101e/8102e do Fast Ethernet only. */ + if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || + (tp->mac_version == RTL_GIGA_MAC_VER_08) || + (tp->mac_version == RTL_GIGA_MAC_VER_09) || + (tp->mac_version == RTL_GIGA_MAC_VER_10) || + (tp->mac_version == RTL_GIGA_MAC_VER_13) || (tp->mac_version == RTL_GIGA_MAC_VER_14) || (tp->mac_version == RTL_GIGA_MAC_VER_15) || (tp->mac_version == RTL_GIGA_MAC_VER_16)) { @@ -1212,8 +1224,17 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, /* 8101 family. */ + { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, + { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, + { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, + { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, + { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, + { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, + { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, + { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, + { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, /* FIXME: where did these entries come from ? -- FR */ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, @@ -1375,6 +1396,22 @@ static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } +static void rtl8102e_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init[] = { + { 0x1f, 0x0003 }, + { 0x08, 0x441d }, + { 0x01, 0x9100 }, + { 0x1f, 0x0000 } + }; + + mdio_write(ioaddr, 0x1f, 0x0000); + mdio_patch(ioaddr, 0x11, 1 << 12); + mdio_patch(ioaddr, 0x19, 1 << 13); + + rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); +} + static void rtl_hw_phy_config(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -1392,6 +1429,11 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_04: rtl8169sb_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_07: + case RTL_GIGA_MAC_VER_08: + case RTL_GIGA_MAC_VER_09: + rtl8102e_hw_phy_config(ioaddr); + break; case RTL_GIGA_MAC_VER_18: rtl8168cp_hw_phy_config(ioaddr); break; @@ -2255,6 +2297,70 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } +#define R810X_CPCMD_QUIRK_MASK (\ + EnableBist | \ + Mac_dbgo_oe | \ + Force_half_dup | \ + Force_half_dup | \ + Force_txflow_en | \ + Cxpl_dbg_sel | \ + ASF | \ + PktCntrDisable | \ + PCIDAC | \ + PCIMulRW) + +static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) +{ + static struct ephy_info e_info_8102e_1[] = { + { 0x01, 0, 0x6e65 }, + { 0x02, 0, 0x091f }, + { 0x03, 0, 0xc2f9 }, + { 0x06, 0, 0xafb5 }, + { 0x07, 0, 0x0e00 }, + { 0x19, 0, 0xec80 }, + { 0x01, 0, 0x2e65 }, + { 0x01, 0, 0x6e65 } + }; + u8 cfg1; + + rtl_csi_access_enable(ioaddr); + + RTL_W8(DBG_REG, FIX_NAK_1); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W8(Config1, + LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + + cfg1 = RTL_R8(Config1); + if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) + RTL_W8(Config1, cfg1 & ~LEDS0); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); + + rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); +} + +static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable(ioaddr); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); +} + +static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_hw_start_8102e_2(ioaddr, pdev); + + rtl_ephy_write(ioaddr, 0x03, 0xc2f9); +} + static void rtl_hw_start_8101(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2271,6 +2377,20 @@ static void rtl_hw_start_8101(struct net_device *dev) } } + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_07: + rtl_hw_start_8102e_1(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_08: + rtl_hw_start_8102e_3(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_09: + rtl_hw_start_8102e_2(ioaddr, pdev); + break; + } + RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(EarlyTxThres, EarlyTxThld); -- GitLab From cd95851785bcfe95fdf73689e8ecb5a1c5959231 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 17 Aug 2008 07:37:15 -0700 Subject: [PATCH 0379/5416] rcu: fix classic RCU locking cleanup lockdep problem On Fri, Aug 15, 2008 at 04:24:30PM +0200, Ingo Molnar wrote: > > Paul, > > one of your two recent RCU patches caused this lockdep splat in -tip > testing: > > -------------------> > Brought up 2 CPUs > Total of 2 processors activated (6850.87 BogoMIPS). > PM: Adding info for No Bus:platform > khelper used greatest stack depth: 3124 bytes left > > ================================= > [ INFO: inconsistent lock state ] > 2.6.27-rc3-tip #1 > --------------------------------- > inconsistent {softirq-on-W} -> {in-softirq-W} usage. > ksoftirqd/0/4 [HC0[0]:SC1[1]:HE1:SE0] takes: > (&rcu_ctrlblk.lock){-+..}, at: [] __rcu_process_callbacks+0x1ac/0x1f0 > {softirq-on-W} state was registered at: > [] __lock_acquire+0x3f4/0x5b0 > [] lock_acquire+0x89/0xc0 > [] _spin_lock+0x3b/0x70 > [] rcu_init_percpu_data+0x29/0x80 > [] rcu_cpu_notify+0xaf/0xd0 > [] notifier_call_chain+0x2d/0x60 > [] __raw_notifier_call_chain+0x1e/0x30 > [] _cpu_up+0x79/0x110 > [] cpu_up+0x4d/0x70 > [] kernel_init+0xb1/0x200 > [] kernel_thread_helper+0x7/0x10 > [] 0xffffffff > irq event stamp: 14 > hardirqs last enabled at (14): [] trace_hardirqs_on+0xb/0x10 > hardirqs last disabled at (13): [] trace_hardirqs_off+0xb/0x10 > softirqs last enabled at (0): [] copy_process+0x276/0x1190 > softirqs last disabled at (11): [] call_on_stack+0x1a/0x30 > > other info that might help us debug this: > no locks held by ksoftirqd/0/4. > > stack backtrace: > Pid: 4, comm: ksoftirqd/0 Not tainted 2.6.27-rc3-tip #1 > [] print_usage_bug+0x16c/0x1b0 > [] mark_lock+0xa75/0xb10 > [] ? sched_clock+0x15/0x30 > [] __lock_acquire+0x3ad/0x5b0 > [] lock_acquire+0x89/0xc0 > [] ? __rcu_process_callbacks+0x1ac/0x1f0 > [] _spin_lock+0x3b/0x70 > [] ? __rcu_process_callbacks+0x1ac/0x1f0 > [] __rcu_process_callbacks+0x1ac/0x1f0 > [] rcu_process_callbacks+0x26/0x50 > [] __do_softirq+0x95/0x120 > [] ? __do_softirq+0x0/0x120 > [] call_on_stack+0x1a/0x30 > [] ? ksoftirqd+0x96/0x110 > [] ? ksoftirqd+0x0/0x110 > [] ? kthread+0x47/0x80 > [] ? kthread+0x0/0x80 > [] ? kernel_thread_helper+0x7/0x10 > ======================= > calling init_cpufreq_transition_notifier_list+0x0/0x20 > initcall init_cpufreq_transition_notifier_list+0x0/0x20 returned 0 after 0 msecs > calling net_ns_init+0x0/0x190 > net_namespace: 676 bytes > initcall net_ns_init+0x0/0x190 returned 0 after 0 msecs > calling cpufreq_tsc+0x0/0x20 > initcall cpufreq_tsc+0x0/0x20 returned 0 after 0 msecs > calling reboot_init+0x0/0x20 > initcall reboot_init+0x0/0x20 returned 0 after 0 msecs > calling print_banner+0x0/0x10 > Booting paravirtualized kernel on bare hardware > > <----------------------- > > my guess is on: > > commit 1f7b94cd3d564901f9e04a8bc5832ae7bfd690a0 > Author: Paul E. McKenney > Date: Tue Aug 5 09:21:44 2008 -0700 > > rcu: classic RCU locking and memory-barrier cleanups > > Ingo Fixes a problem detected by lockdep in which rcu->lock was acquired both in irq context and in process context, but without disabling from process context. Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index 5de126630b1..fb1f1cc4514 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -700,7 +700,9 @@ void rcu_check_callbacks(int cpu, int user) static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - spin_lock(&rcp->lock); + long flags; + + spin_lock_irqsave(&rcp->lock, flags); memset(rdp, 0, sizeof(*rdp)); rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2] = &rdp->nxtlist; rdp->donetail = &rdp->donelist; @@ -708,7 +710,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->qs_pending = 0; rdp->cpu = cpu; rdp->blimit = blimit; - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } static void __cpuinit rcu_online_cpu(int cpu) -- GitLab From 7b22ff5344fda666e0938e5261ea7b9a3dfce497 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 18 Aug 2008 00:36:18 +0900 Subject: [PATCH 0380/5416] x86 gart: allocate size-aligned address for alloc_coherent, v2 This patch changes GART IOMMU to return a size aligned address wrt dma_alloc_coherent, as DMA-mapping.txt defines: The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary. Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index cdab6784907..4d8efb05428 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -82,7 +82,8 @@ AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static unsigned long alloc_iommu(struct device *dev, int size) +static unsigned long alloc_iommu(struct device *dev, int size, + unsigned long align_mask) { unsigned long offset, flags; unsigned long boundary_size; @@ -95,11 +96,12 @@ static unsigned long alloc_iommu(struct device *dev, int size) spin_lock_irqsave(&iommu_bitmap_lock, flags); offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, align_mask); if (offset == -1) { need_flush = 1; offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, + align_mask); } if (offset != -1) { next_bit = offset+size; @@ -236,10 +238,10 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) * Caller needs to check if the iommu is needed and flush. */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, - size_t size, int dir) + size_t size, int dir, unsigned long align_mask) { unsigned long npages = iommu_num_pages(phys_mem, size); - unsigned long iommu_page = alloc_iommu(dev, npages); + unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); int i; if (iommu_page == -1) { @@ -262,7 +264,11 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, static dma_addr_t gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) { - dma_addr_t map = dma_map_area(dev, paddr, size, dir); + dma_addr_t map; + unsigned long align_mask; + + align_mask = (1UL << get_order(size)) - 1; + map = dma_map_area(dev, paddr, size, dir, align_mask); flush_gart(); @@ -281,7 +287,8 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) if (!need_iommu(dev, paddr, size)) return paddr; - bus = gart_map_simple(dev, paddr, size, dir); + bus = dma_map_area(dev, paddr, size, dir, 0); + flush_gart(); return bus; } @@ -340,7 +347,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) gart_unmap_sg(dev, sg, i, dir); @@ -362,7 +369,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, int nelems, struct scatterlist *sout, unsigned long pages) { - unsigned long iommu_start = alloc_iommu(dev, pages); + unsigned long iommu_start = alloc_iommu(dev, pages, 0); unsigned long iommu_page = iommu_start; struct scatterlist *s; int i; -- GitLab From d5e629a6f88137fb77c4cc857be5ea7c3f27110d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 17 Aug 2008 21:12:27 -0700 Subject: [PATCH 0381/5416] x86: apic - unify lapic_resume - fix Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5e0738131e5..ad532dccd11 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1446,6 +1446,7 @@ static int lapic_resume(struct sys_device *dev) enable_x2apic(); else #endif + { /* * Make sure the APICBASE points to the right address * @@ -1456,6 +1457,7 @@ static int lapic_resume(struct sys_device *dev) l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + } apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); -- GitLab From ded00a56e99555c3f4000ef3eebfd5fe0d574565 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 17 Aug 2008 12:50:36 -0700 Subject: [PATCH 0382/5416] rcu: remove redundant ACCESS_ONCE definition from rcupreempt.c Remove the redundant definition of ACCESS_ONCE() from rcupreempt.c in favor of the one in compiler.h. Also merge the comment header from rcupreempt.c's definition into that in compiler.h. Signed-off-by: Paul E. McKenney Signed-off-by: Ingo Molnar --- include/linux/compiler.h | 4 +++- kernel/rcupreempt.c | 8 -------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c8bd2daf95e..8322141ee48 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -190,7 +190,9 @@ extern void __chk_io_ptr(const volatile void __iomem *); * ACCESS_ONCE() in different C statements. * * This macro does absolutely -nothing- to prevent the CPU from reordering, - * merging, or refetching absolutely anything at any time. + * merging, or refetching absolutely anything at any time. Its main intended + * use is to mediate communication between process-level code and irq/NMI + * handlers, all running on the same CPU. */ #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index 27827931ca0..ca4bbbe04aa 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c @@ -58,14 +58,6 @@ #include #include -/* - * Macro that prevents the compiler from reordering accesses, but does - * absolutely -nothing- to prevent CPUs from reordering. This is used - * only to mediate communication between mainline code and hardware - * interrupt and NMI handlers. - */ -#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) - /* * PREEMPT_RCU data structures. */ -- GitLab From 8bfcb3960fde049b863266dab8c3617bb5a541aa Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 18 Aug 2008 12:33:20 +0200 Subject: [PATCH 0383/5416] x86: make movsl_mask definition non-CPU specific movsl_mask is currently defined in arch/x86/kernel/cpu/intel.c, which contains code specific to Intel CPUs. However, movsl_mask is used in the non-CPU specific code in arch/x86/lib/usercopy_32.c, which breaks the compilation when support for Intel CPUs is compiled out. This patch solves this problem by moving movsl_mask's definition close to its users in arch/x86/lib/usercopy_32.c. Signed-off-by: Thomas Petazzoni Cc: michael@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 7 ------- arch/x86/lib/usercopy_32.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index b75f2569b8f..5c8959b8a42 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -23,13 +23,6 @@ #include #endif -#ifdef CONFIG_X86_INTEL_USERCOPY -/* - * Alignment at which movsl is preferred for bulk memory copies. - */ -struct movsl_mask movsl_mask __read_mostly; -#endif - static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) { /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 24e60944971..9e68075544f 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -14,6 +14,13 @@ #include #include +#ifdef CONFIG_X86_INTEL_USERCOPY +/* + * Alignment at which movsl is preferred for bulk memory copies. + */ +struct movsl_mask movsl_mask __read_mostly; +#endif + static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) { #ifdef CONFIG_X86_INTEL_USERCOPY -- GitLab From 774400a3ba23b63f4de39e67ce6c4e48935809dc Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 18 Aug 2008 12:33:21 +0200 Subject: [PATCH 0384/5416] x86: move cmpxchg fallbacks to a generic place arch/x86/kernel/cpu/intel.c defines a few fallback functions (cmpxchg_*()) that are used when the CPU doesn't support cmpxchg and/or cmpxchg64 natively. However, while defined in an Intel-specific file, these functions are also used for CPUs from other vendors when they don't support cmpxchg and/or cmpxchg64. This breaks the compilation when support for Intel CPUs is disabled. This patch moves these functions to a new arch/x86/kernel/cpu/cmpxchg.c file, unconditionally compiled when X86_32 is enabled. Signed-off-by: Thomas Petazzoni Cc: michael@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/cmpxchg.c | 72 +++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/intel.c | 64 ------------------------------- 3 files changed, 73 insertions(+), 65 deletions(-) create mode 100644 arch/x86/kernel/cpu/cmpxchg.c diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index ee76eaad300..25b4c063fbf 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -5,7 +5,7 @@ obj-y := intel_cacheinfo.o addon_cpuid_features.o obj-y += proc.o feature_names.o -obj-$(CONFIG_X86_32) += common.o bugs.o +obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o obj-$(CONFIG_X86_32) += amd.o obj-$(CONFIG_X86_64) += amd_64.o diff --git a/arch/x86/kernel/cpu/cmpxchg.c b/arch/x86/kernel/cpu/cmpxchg.c new file mode 100644 index 00000000000..2056ccf572c --- /dev/null +++ b/arch/x86/kernel/cpu/cmpxchg.c @@ -0,0 +1,72 @@ +/* + * cmpxchg*() fallbacks for CPU not supporting these instructions + */ + +#include +#include +#include + +#ifndef CONFIG_X86_CMPXCHG +unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) +{ + u8 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u8 *)ptr; + if (prev == old) + *(u8 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u8); + +unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) +{ + u16 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u16 *)ptr; + if (prev == old) + *(u16 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u16); + +unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) +{ + u32 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u32 *)ptr; + if (prev == old) + *(u32 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u32); +#endif + +#ifndef CONFIG_X86_CMPXCHG64 +unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new) +{ + u64 prev; + unsigned long flags; + + /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u64 *)ptr; + if (prev == old) + *(u64 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_486_u64); +#endif + diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 5c8959b8a42..77618c717d7 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -307,69 +307,5 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); -#ifndef CONFIG_X86_CMPXCHG -unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) -{ - u8 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u8 *)ptr; - if (prev == old) - *(u8 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u8); - -unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) -{ - u16 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u16 *)ptr; - if (prev == old) - *(u16 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u16); - -unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) -{ - u32 prev; - unsigned long flags; - - /* Poor man's cmpxchg for 386. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u32 *)ptr; - if (prev == old) - *(u32 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_386_u32); -#endif - -#ifndef CONFIG_X86_CMPXCHG64 -unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new) -{ - u64 prev; - unsigned long flags; - - /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */ - local_irq_save(flags); - prev = *(u64 *)ptr; - if (prev == old) - *(u64 *)ptr = new; - local_irq_restore(flags); - return prev; -} -EXPORT_SYMBOL(cmpxchg_486_u64); -#endif - /* arch_initcall(intel_cpu_init); */ -- GitLab From 8d02c2110b3fb8e2700b31596a582a2989fd72ba Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 5 Aug 2008 11:45:19 +0200 Subject: [PATCH 0385/5416] x86: configuration options to compile out x86 CPU support code This patch adds some configuration options that allow to compile out CPU vendor-specific code in x86 kernels (in arch/x86/kernel/cpu). The new configuration options are only visible when CONFIG_EMBEDDED is selected, as they are mostly interesting for space savings reasons. An example of size saving, on x86 with only Intel CPU support: text data bss dec hex filename 1125479 118760 212992 1457231 163c4f vmlinux.old 1121355 116536 212992 1450883 162383 vmlinux -4124 -2224 0 -6348 -18CC +/- However, I'm not exactly sure that the Kconfig wording is correct with regard to !64BIT / 64BIT. [ mingo@elte.hu: convert macro to inline ] Signed-off-by: Thomas Petazzoni Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 70 ++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/Makefile | 19 +++++----- include/asm-x86/bugs.h | 5 +++ 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2c518fbc52e..6156ac25ff8 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -415,3 +415,73 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) + +menuconfig PROCESSOR_SELECT + default y + bool "Supported processor vendors" if EMBEDDED + help + This lets you choose what x86 vendor support code your kernel + will include. + +config CPU_SUP_INTEL_32 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_INTEL_64 + default y + bool "Support Intel processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Intel processors + +config CPU_SUP_CYRIX_32 + default y + bool "Support Cyrix processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Cyrix processors + +config CPU_SUP_AMD_32 + default y + bool "Support AMD processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for AMD processors + +config CPU_SUP_AMD_64 + default y + bool "Support AMD processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for AMD processors + +config CPU_SUP_CENTAUR_32 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_CENTAUR_64 + default y + bool "Support Centaur processors" if PROCESSOR_SELECT + depends on 64BIT + help + This enables extended support for Centaur processors + +config CPU_SUP_TRANSMETA_32 + default y + bool "Support Transmeta processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for Transmeta processors + +config CPU_SUP_UMC_32 + default y + bool "Support UMC processors" if PROCESSOR_SELECT + depends on !64BIT + help + This enables extended support for UMC processors diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 25b4c063fbf..a0fc6c14438 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -7,15 +7,16 @@ obj-y += proc.o feature_names.o obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += common_64.o bugs_64.o -obj-$(CONFIG_X86_32) += amd.o -obj-$(CONFIG_X86_64) += amd_64.o -obj-$(CONFIG_X86_32) += cyrix.o -obj-$(CONFIG_X86_32) += centaur.o -obj-$(CONFIG_X86_64) += centaur_64.o -obj-$(CONFIG_X86_32) += transmeta.o -obj-$(CONFIG_X86_32) += intel.o -obj-$(CONFIG_X86_64) += intel_64.o -obj-$(CONFIG_X86_32) += umc.o + +obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o +obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o +obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o +obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o +obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o +obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o +obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o +obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o +obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ diff --git a/include/asm-x86/bugs.h b/include/asm-x86/bugs.h index 021cbdd5f25..00e4a0cd6f2 100644 --- a/include/asm-x86/bugs.h +++ b/include/asm-x86/bugs.h @@ -2,6 +2,11 @@ #define _ASM_X86_BUGS_H extern void check_bugs(void); + +#ifdef CONFIG_CPU_SUP_INTEL_32 int ppro_with_ram_bug(void); +#else +static inline int ppro_with_ram_bug(void) { return 0; } +#endif #endif /* _ASM_X86_BUGS_H */ -- GitLab From b6c8051311e1a14d229df05ea39d0a1b2ce90cdd Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:49 +0400 Subject: [PATCH 0386/5416] x86: apic - rearrange maxcpu definition Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++-- arch/x86/kernel/apic_64.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 41134d4e6a6..8d1febf05da 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -114,6 +114,8 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events); static int enabled_via_apicbase; static unsigned long apic_phys; +unsigned int __cpuinitdata maxcpus = NR_CPUS; + /* * Get the LAPIC version @@ -1459,8 +1461,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) } } -unsigned int __cpuinitdata maxcpus = NR_CPUS; - void __cpuinit generic_processor_info(int apicid, int version) { int cpu; diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index ad532dccd11..46acb9b47ae 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -98,10 +98,10 @@ static struct clock_event_device lapic_clockevent = { static DEFINE_PER_CPU(struct clock_event_device, lapic_events); static unsigned long apic_phys; +unsigned int __cpuinitdata maxcpus = NR_CPUS; unsigned long mp_lapic_addr; -unsigned int __cpuinitdata maxcpus = NR_CPUS; /* * Get the LAPIC version */ -- GitLab From f1ee37891dab6014f6b0ec77b18bc07e2369a55f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:50 +0400 Subject: [PATCH 0387/5416] x86: apic - unify setup_boot_APIC_clock Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 8d1febf05da..80db3e0426c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -612,6 +612,7 @@ void __init setup_boot_APIC_clock(void) * broadcast mechanism is used. On UP systems simply ignore it. */ if (disable_apic_timer) { + printk(KERN_INFO "Disabling APIC timer\n"); /* No broadcast on UP ! */ if (num_possible_cpus() > 1) { lapic_clockevent.mult = 1; -- GitLab From 990b183e58cb513a62492b6218987750e106cbfb Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:51 +0400 Subject: [PATCH 0388/5416] x86: apic - unify disable_local_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 +++- arch/x86/kernel/apic_64.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 80db3e0426c..13c4b79441d 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -796,7 +796,7 @@ void clear_local_APIC(void) */ void disable_local_APIC(void) { - unsigned long value; + unsigned int value; clear_local_APIC(); @@ -808,6 +808,7 @@ void disable_local_APIC(void) value &= ~APIC_SPIV_APIC_ENABLED; apic_write(APIC_SPIV, value); +#ifdef CONFIG_X86_32 /* * When LAPIC was disabled by the BIOS and enabled by the kernel, * restore the disabled state. @@ -819,6 +820,7 @@ void disable_local_APIC(void) l &= ~MSR_IA32_APICBASE_ENABLE; wrmsr(MSR_IA32_APICBASE, l, h); } +#endif } /* diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 46acb9b47ae..4fb903b2fc3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -691,6 +691,20 @@ void disable_local_APIC(void) value = apic_read(APIC_SPIV); value &= ~APIC_SPIV_APIC_ENABLED; apic_write(APIC_SPIV, value); + +#ifdef CONFIG_X86_32 + /* + * When LAPIC was disabled by the BIOS and enabled by the kernel, + * restore the disabled state. + */ + if (enabled_via_apicbase) { + unsigned int l, h; + + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_ENABLE; + wrmsr(MSR_IA32_APICBASE, l, h); + } +#endif } void lapic_shutdown(void) -- GitLab From fe4024dcb0c01e5399394d2807406a2c13fb1eb7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:52 +0400 Subject: [PATCH 0389/5416] x86: apic - unify lapic_shutdown Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 9 ++++++--- arch/x86/kernel/apic_64.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 13c4b79441d..d4efe86adc7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -838,10 +838,13 @@ void lapic_shutdown(void) local_irq_save(flags); - if (enabled_via_apicbase) - disable_local_APIC(); - else +#ifdef CONFIG_X86_32 + if (!enabled_via_apicbase) clear_local_APIC(); + else +#endif + disable_local_APIC(); + local_irq_restore(flags); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 4fb903b2fc3..48806546d49 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -707,6 +707,12 @@ void disable_local_APIC(void) #endif } +/* + * If Linux enabled the LAPIC against the BIOS default disable it down before + * re-entering the BIOS on shutdown. Otherwise the BIOS may get confused and + * not power-off. Additionally clear all LVT entries before disable_local_APIC + * for the case where Linux didn't enable the LAPIC. + */ void lapic_shutdown(void) { unsigned long flags; @@ -716,7 +722,13 @@ void lapic_shutdown(void) local_irq_save(flags); - disable_local_APIC(); +#ifdef CONFIG_X86_32 + if (!enabled_via_apicbase) + clear_local_APIC(); + else +#endif + disable_local_APIC(); + local_irq_restore(flags); } -- GitLab From 36c9d6742897fa414f51c4e9d0f20ab4e6bf942c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:53 +0400 Subject: [PATCH 0390/5416] x86: apic - unify connect_bsp_APIC Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 ++ arch/x86/kernel/apic_64.c | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d4efe86adc7..6d230e9d0a7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1387,6 +1387,7 @@ void smp_error_interrupt(struct pt_regs *regs) */ void __init connect_bsp_APIC(void) { +#ifdef CONFIG_X86_32 if (pic_mode) { /* * Do not trust the local APIC being empty at bootup. @@ -1401,6 +1402,7 @@ void __init connect_bsp_APIC(void) outb(0x70, 0x22); outb(0x01, 0x23); } +#endif enable_apic_mode(); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 48806546d49..5579e213b5d 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1285,10 +1285,26 @@ asmlinkage void smp_error_interrupt(void) } /** - * * connect_bsp_APIC - attach the APIC to the interrupt system - * */ + * connect_bsp_APIC - attach the APIC to the interrupt system + */ void __init connect_bsp_APIC(void) { +#ifdef CONFIG_X86_32 + if (pic_mode) { + /* + * Do not trust the local APIC being empty at bootup. + */ + clear_local_APIC(); + /* + * PIC mode, enable APIC mode in the IMCR, i.e. connect BSP's + * local APIC to INT and NMI lines. + */ + apic_printk(APIC_VERBOSE, "leaving PIC mode, " + "enabling APIC mode.\n"); + outb(0x70, 0x22); + outb(0x01, 0x23); + } +#endif enable_apic_mode(); } -- GitLab From c43da2f5e92fe3bcc256f0c0d6cb858368da5bd9 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:54 +0400 Subject: [PATCH 0391/5416] x86: apic - unify lapic_setup_esr We use 32bit code former for 64bit mode since it's much better implementation and easier to merge. Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 21 ++++++++-------- arch/x86/kernel/apic_64.c | 51 ++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6d230e9d0a7..3c1562afa27 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -983,6 +983,16 @@ static void __cpuinit lapic_setup_esr(void) { unsigned long oldvalue, value, maxlvt; if (lapic_is_integrated() && !esr_disable) { + if (esr_disable) { + /* + * Something untraceable is creating bad interrupts on + * secondary quads ... for the moment, just leave the + * ESR disabled - we can't do anything useful with the + * errors anyway - mbligh + */ + printk(KERN_INFO "Leaving ESR disabled.\n"); + return; + } /* !82489DX */ maxlvt = lapic_get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ @@ -1003,16 +1013,7 @@ static void __cpuinit lapic_setup_esr(void) "vector: 0x%08lx after: 0x%08lx\n", oldvalue, value); } else { - if (esr_disable) - /* - * Something untraceable is creating bad interrupts on - * secondary quads ... for the moment, just leave the - * ESR disabled - we can't do anything useful with the - * errors anyway - mbligh - */ - printk(KERN_INFO "Leaving ESR disabled.\n"); - else - printk(KERN_INFO "No ESR for 82489DX.\n"); + printk(KERN_INFO "No ESR for 82489DX.\n"); } } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5579e213b5d..d74abf7e92f 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -863,6 +863,45 @@ void __init init_bsp_APIC(void) apic_write(APIC_LVT1, value); } +static void __cpuinit lapic_setup_esr(void) +{ + unsigned long oldvalue, value, maxlvt; + if (lapic_is_integrated() && !esr_disable) { + if (esr_disable) { + /* + * Something untraceable is creating bad interrupts on + * secondary quads ... for the moment, just leave the + * ESR disabled - we can't do anything useful with the + * errors anyway - mbligh + */ + printk(KERN_INFO "Leaving ESR disabled.\n"); + return; + } + /* !82489DX */ + maxlvt = lapic_get_maxlvt(); + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ + apic_write(APIC_ESR, 0); + oldvalue = apic_read(APIC_ESR); + + /* enables sending errors */ + value = ERROR_APIC_VECTOR; + apic_write(APIC_LVTERR, value); + /* + * spec says clear errors after enabling vector. + */ + if (maxlvt > 3) + apic_write(APIC_ESR, 0); + value = apic_read(APIC_ESR); + if (value != oldvalue) + apic_printk(APIC_VERBOSE, "ESR value before enabling " + "vector: 0x%08lx after: 0x%08lx\n", + oldvalue, value); + } else { + printk(KERN_INFO "No ESR for 82489DX.\n"); + } +} + + /** * setup_local_APIC - setup the local APIC */ @@ -968,18 +1007,6 @@ void __cpuinit setup_local_APIC(void) preempt_enable(); } -static void __cpuinit lapic_setup_esr(void) -{ - unsigned maxlvt = lapic_get_maxlvt(); - - apic_write(APIC_LVTERR, ERROR_APIC_VECTOR); - /* - * spec says clear errors after enabling vector. - */ - if (maxlvt > 3) - apic_write(APIC_ESR, 0); -} - void __cpuinit end_local_APIC_setup(void) { lapic_setup_esr(); -- GitLab From c40aaec6868401671a0ca14ed77e9b2da2d1f223 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:55 +0400 Subject: [PATCH 0392/5416] x86: apic - unify __setup_APIC_LVTT Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 10 +++++++--- arch/x86/kernel/apic_64.c | 12 ++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3c1562afa27..65419c7d437 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -248,8 +248,12 @@ int lapic_get_maxlvt(void) * Local APIC timer */ -/* Clock divisor is set to 16 */ +/* Clock divisor */ +#ifdef CONFG_X86_64 +#define APIC_DIVISOR 1 +#else #define APIC_DIVISOR 16 +#endif /* * This function sets up the local APIC timer, with a timeout of @@ -281,8 +285,8 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) */ tmp_value = apic_read(APIC_TDCR); apic_write(APIC_TDCR, - (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | - APIC_TDR_DIV_16); + (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | + APIC_TDR_DIV_16); if (!oneshot) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index d74abf7e92f..fe57db9f3fb 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -259,8 +259,12 @@ int lapic_get_maxlvt(void) * Local APIC timer */ -/* Clock divisor is set to 1 */ +/* Clock divisor */ +#ifdef CONFG_X86_64 #define APIC_DIVISOR 1 +#else +#define APIC_DIVISOR 16 +#endif /* * This function sets up the local APIC timer, with a timeout of @@ -291,9 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) * Divide PICLK by 16 */ tmp_value = apic_read(APIC_TDCR); - apic_write(APIC_TDCR, (tmp_value - & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) - | APIC_TDR_DIV_16); + apic_write(APIC_TDCR, + (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | + APIC_TDR_DIV_16); if (!oneshot) apic_write(APIC_TMICT, clocks / APIC_DIVISOR); -- GitLab From c177b0bc03e0e11623e2099db42903fb0caf0fd3 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:56 +0400 Subject: [PATCH 0393/5416] x86: apic - unify disconnect_bsp_APIC - just #ifdef added Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 66 ++++++++++++++++++++------------------- arch/x86/kernel/apic_64.c | 23 ++++++++++++-- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 65419c7d437..3095bb71eae 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1420,6 +1420,7 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { +#ifdef CONFIG_X86_32 if (pic_mode) { /* * Put the board back into PIC mode (has an effect only on @@ -1431,47 +1432,48 @@ void disconnect_bsp_APIC(int virt_wire_setup) "entering PIC mode.\n"); outb(0x70, 0x22); outb(0x00, 0x23); - } else { - /* Go back to Virtual Wire compatibility mode */ - unsigned long value; + return; + } +#endif - /* For the spurious interrupt use vector F, and enable it */ - value = apic_read(APIC_SPIV); - value &= ~APIC_VECTOR_MASK; - value |= APIC_SPIV_APIC_ENABLED; - value |= 0xf; - apic_write(APIC_SPIV, value); + /* Go back to Virtual Wire compatibility mode */ + unsigned int value; - if (!virt_wire_setup) { - /* - * For LVT0 make it edge triggered, active high, - * external and enabled - */ - value = apic_read(APIC_LVT0); - value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | - APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | - APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); - value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; - value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); - apic_write(APIC_LVT0, value); - } else { - /* Disable LVT0 */ - apic_write(APIC_LVT0, APIC_LVT_MASKED); - } + /* For the spurious interrupt use vector F, and enable it */ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + value |= 0xf; + apic_write(APIC_SPIV, value); + if (!virt_wire_setup) { /* - * For LVT1 make it edge triggered, active high, nmi and - * enabled + * For LVT0 make it edge triggered, active high, + * external and enabled */ - value = apic_read(APIC_LVT1); - value &= ~( - APIC_MODE_MASK | APIC_SEND_PENDING | + value = apic_read(APIC_LVT0); + value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; - value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); - apic_write(APIC_LVT1, value); + value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); + apic_write(APIC_LVT0, value); + } else { + /* Disable LVT0 */ + apic_write(APIC_LVT0, APIC_LVT_MASKED); } + + /* + * For LVT1 make it edge triggered, active high, + * nmi and enabled + */ + value = apic_read(APIC_LVT1); + value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | + APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | + APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); + value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; + value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); + apic_write(APIC_LVT1, value); } void __cpuinit generic_processor_info(int apicid, int version) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index fe57db9f3fb..0d969103fce 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1348,8 +1348,24 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { +#ifdef CONFIG_X86_32 + if (pic_mode) { + /* + * Put the board back into PIC mode (has an effect only on + * certain older boards). Note that APIC interrupts, including + * IPIs, won't work beyond this point! The only exception are + * INIT IPIs. + */ + apic_printk(APIC_VERBOSE, "disabling APIC mode, " + "entering PIC mode.\n"); + outb(0x70, 0x22); + outb(0x00, 0x23); + return; + } +#endif + /* Go back to Virtual Wire compatibility mode */ - unsigned long value; + unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); @@ -1375,7 +1391,10 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT0, APIC_LVT_MASKED); } - /* For LVT1 make it edge triggered, active high, nmi and enabled */ + /* + * For LVT1 make it edge triggered, active high, + * nmi and enabled + */ value = apic_read(APIC_LVT1); value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | -- GitLab From 1b313f4a6d7bee7b2c034b3f1e203bc360a71cca Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:57 +0400 Subject: [PATCH 0394/5416] x86: apic - generic_processor_info - use physid_set instead of phys_cpu and physids_or - set phys_cpu_present_map bit AFTER check for allowed number of processors - add checking for APIC valid version in 64bit mode (mostly not needed but added for merging purpose) - add apic_version definition for 64bit mode which is used now Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 15 +++++++------- arch/x86/kernel/apic_64.c | 41 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3095bb71eae..c3a252b1a8b 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1480,7 +1480,6 @@ void __cpuinit generic_processor_info(int apicid, int version) { int cpu; cpumask_t tmp_map; - physid_mask_t phys_cpu; /* * Validate version @@ -1493,9 +1492,6 @@ void __cpuinit generic_processor_info(int apicid, int version) } apic_version[apicid] = version; - phys_cpu = apicid_to_cpu_present(apicid); - physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); - if (num_processors >= NR_CPUS) { printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." " Processor ignored.\n", NR_CPUS); @@ -1512,17 +1508,19 @@ void __cpuinit generic_processor_info(int apicid, int version) cpus_complement(tmp_map, cpu_present_map); cpu = first_cpu(tmp_map); - if (apicid == boot_cpu_physical_apicid) + physid_set(apicid, phys_cpu_present_map); + if (apicid == boot_cpu_physical_apicid) { /* * x86_bios_cpu_apicid is required to have processors listed * in same order as logical cpu numbers. Hence the first * entry is BSP, and so on. */ cpu = 0; - + } if (apicid > max_physical_apicid) max_physical_apicid = apicid; +#ifdef CONFIG_X86_32 /* * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y * but we need to work other dependencies like SMP_SUSPEND etc @@ -1542,7 +1540,9 @@ void __cpuinit generic_processor_info(int apicid, int version) def_to_bigsmp = 1; } } -#ifdef CONFIG_SMP +#endif + +#if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) /* are we being called early in kernel startup? */ if (early_per_cpu_ptr(x86_cpu_to_apicid)) { u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); @@ -1555,6 +1555,7 @@ void __cpuinit generic_processor_info(int apicid, int version) per_cpu(x86_bios_cpu_apicid, cpu) = apicid; } #endif + cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 0d969103fce..76c20773bed 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1215,6 +1215,8 @@ void __init init_apic_mappings(void) * This initializes the IO-APIC and APIC hardware if this is * a UP kernel. */ +int apic_version[MAX_APICS]; + int __init APIC_init_uniprocessor(void) { if (disable_apic) { @@ -1409,15 +1411,26 @@ void __cpuinit generic_processor_info(int apicid, int version) int cpu; cpumask_t tmp_map; + /* + * Validate version + */ + if (version == 0x0) { + printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! " + "fixing up to 0x10. (tell your hw vendor)\n", + version); + version = 0x10; + } + apic_version[apicid] = version; + if (num_processors >= NR_CPUS) { printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." - " Processor ignored.\n", NR_CPUS); + " Processor ignored.\n", NR_CPUS); return; } if (num_processors >= maxcpus) { printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." - " Processor ignored.\n", maxcpus); + " Processor ignored.\n", maxcpus); return; } @@ -1437,6 +1450,29 @@ void __cpuinit generic_processor_info(int apicid, int version) if (apicid > max_physical_apicid) max_physical_apicid = apicid; +#ifdef CONFIG_X86_32 + /* + * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y + * but we need to work other dependencies like SMP_SUSPEND etc + * before this can be done without some confusion. + * if (CPU_HOTPLUG_ENABLED || num_processors > 8) + * - Ashok Raj + */ + if (max_physical_apicid >= 8) { + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_INTEL: + if (!APIC_XAPIC(version)) { + def_to_bigsmp = 0; + break; + } + /* If P4 and above fall through */ + case X86_VENDOR_AMD: + def_to_bigsmp = 1; + } + } +#endif + +#if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) /* are we being called early in kernel startup? */ if (early_per_cpu_ptr(x86_cpu_to_apicid)) { u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); @@ -1448,6 +1484,7 @@ void __cpuinit generic_processor_info(int apicid, int version) per_cpu(x86_cpu_to_apicid, cpu) = apicid; per_cpu(x86_bios_cpu_apicid, cpu) = apicid; } +#endif cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); -- GitLab From fa6b95fc7c6f2f3eb1560e1f33cd13197546c5a0 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:58 +0400 Subject: [PATCH 0395/5416] x86: apic - unify end_local_APIC_setup Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 6 ++++-- arch/x86/kernel/apic_64.c | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index c3a252b1a8b..f1882329b9c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1155,13 +1155,15 @@ void __cpuinit setup_local_APIC(void) void __cpuinit end_local_APIC_setup(void) { - unsigned long value; - lapic_setup_esr(); + +#ifdef CONFIG_X86_32 + unsigned int value; /* Disable the local apic timer */ value = apic_read(APIC_LVTT); value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); apic_write(APIC_LVTT, value); +#endif setup_apic_nmi_watchdog(NULL); apic_pm_activate(); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 76c20773bed..eec10b34dc4 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1014,6 +1014,15 @@ void __cpuinit setup_local_APIC(void) void __cpuinit end_local_APIC_setup(void) { lapic_setup_esr(); + +#ifdef CONFIG_X86_32 + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); +#endif + setup_apic_nmi_watchdog(NULL); apic_pm_activate(); } -- GitLab From 0b23e8cf553f5e706b0057363f1319867bcd1a7d Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:45:59 +0400 Subject: [PATCH 0396/5416] x86: apic - unify local_apic_timer_interrupt Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++++ arch/x86/kernel/apic_64.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f1882329b9c..af227bce23b 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -685,7 +685,11 @@ static void local_apic_timer_interrupt(void) /* * the NMI deadlock-detector uses this. */ +#ifdef CONFIG_X86_64 + add_pda(apic_timer_irqs, 1); +#else per_cpu(irq_stat, cpu).apic_timer_irqs++; +#endif evt->event_handler(evt); } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index eec10b34dc4..a9ad2cb4ff9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -567,7 +567,11 @@ static void local_apic_timer_interrupt(void) /* * the NMI deadlock-detector uses this. */ +#ifdef CONFIG_X86_64 add_pda(apic_timer_irqs, 1); +#else + per_cpu(irq_stat, cpu).apic_timer_irqs++; +#endif evt->event_handler(evt); } -- GitLab From 79af9bec60e6e218a1e48e8830d603d64a7fc441 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:00 +0400 Subject: [PATCH 0397/5416] x86: apic - unify apic_set_verbosity Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 17 ++++++++++++--- arch/x86/kernel/apic_64.c | 46 +++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index af227bce23b..acbc4dea2ee 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1768,13 +1768,24 @@ early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); static int __init apic_set_verbosity(char *arg) { - if (!arg) + if (!arg) { +#ifdef CONFIG_X86_64 + skip_ioapic_setup = 0; + ioapic_force = 1; + return 0; +#endif return -EINVAL; + } - if (strcmp(arg, "debug") == 0) + if (strcmp("debug", arg) == 0) apic_verbosity = APIC_DEBUG; - else if (strcmp(arg, "verbose") == 0) + else if (strcmp("verbose", arg) == 0) apic_verbosity = APIC_VERBOSE; + else { + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug\n", arg); + return -EINVAL; + } return 0; } diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index a9ad2cb4ff9..999781810c0 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1759,27 +1759,6 @@ early_param("nox2apic", setup_nox2apic); /* * APIC command line parameters */ -static int __init apic_set_verbosity(char *str) -{ - if (str == NULL) { - skip_ioapic_setup = 0; - ioapic_force = 1; - return 0; - } - if (strcmp("debug", str) == 0) - apic_verbosity = APIC_DEBUG; - else if (strcmp("verbose", str) == 0) - apic_verbosity = APIC_VERBOSE; - else { - printk(KERN_WARNING "APIC Verbosity level %s not recognised" - " use apic=verbose or apic=debug\n", str); - return -EINVAL; - } - - return 0; -} -early_param("apic", apic_set_verbosity); - static __init int setup_disableapic(char *str) { disable_apic = 1; @@ -1824,6 +1803,31 @@ static __init int setup_apicpmtimer(char *s) } __setup("apicpmtimer", setup_apicpmtimer); +static int __init apic_set_verbosity(char *arg) +{ + if (!arg) { +#ifdef CONFIG_X86_64 + skip_ioapic_setup = 0; + ioapic_force = 1; + return 0; +#endif + return -EINVAL; + } + + if (strcmp("debug", arg) == 0) + apic_verbosity = APIC_DEBUG; + else if (strcmp("verbose", arg) == 0) + apic_verbosity = APIC_VERBOSE; + else { + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug\n", arg); + return -EINVAL; + } + + return 0; +} +early_param("apic", apic_set_verbosity); + static int __init lapic_insert_resource(void) { if (!apic_phys) -- GitLab From 789fa735712d726b5cfa5c6be57171b5637a4872 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:01 +0400 Subject: [PATCH 0398/5416] x86: apic - unify disableapic and nolapic setup handlers Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 11 +++++++++-- arch/x86/kernel/apic_64.c | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index acbc4dea2ee..5680bda62f7 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1737,13 +1737,20 @@ static int __init parse_lapic(char *arg) } early_param("lapic", parse_lapic); -static int __init parse_nolapic(char *arg) +static int __init setup_disableapic(char *arg) { disable_apic = 1; setup_clear_cpu_cap(X86_FEATURE_APIC); return 0; } -early_param("nolapic", parse_nolapic); +early_param("disableapic", setup_disableapic); + +/* same as disableapic, for compatibility */ +static int __init setup_nolapic(char *arg) +{ + return setup_disableapic(arg); +} +early_param("nolapic", setup_nolapic); static int __init parse_disable_apic_timer(char *arg) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 999781810c0..7a317180ba2 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1759,7 +1759,7 @@ early_param("nox2apic", setup_nox2apic); /* * APIC command line parameters */ -static __init int setup_disableapic(char *str) +static int __init setup_disableapic(char *arg) { disable_apic = 1; setup_clear_cpu_cap(X86_FEATURE_APIC); @@ -1768,9 +1768,9 @@ static __init int setup_disableapic(char *str) early_param("disableapic", setup_disableapic); /* same as disableapic, for compatibility */ -static __init int setup_nolapic(char *str) +static int __init setup_nolapic(char *arg) { - return setup_disableapic(str); + return setup_disableapic(arg); } early_param("nolapic", setup_nolapic); -- GitLab From 3415610b8e38b26b52a430b8846665c2d6bb3558 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:02 +0400 Subject: [PATCH 0399/5416] x86: apic - rearrange parse_lapic_timer_c2_ok Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 5680bda62f7..885e306420a 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1752,6 +1752,13 @@ static int __init setup_nolapic(char *arg) } early_param("nolapic", setup_nolapic); +static int __init parse_lapic_timer_c2_ok(char *arg) +{ + local_apic_timer_c2_ok = 1; + return 0; +} +early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); + static int __init parse_disable_apic_timer(char *arg) { disable_apic_timer = 1; @@ -1766,13 +1773,6 @@ static int __init parse_nolapic_timer(char *arg) } early_param("nolapic_timer", parse_nolapic_timer); -static int __init parse_lapic_timer_c2_ok(char *arg) -{ - local_apic_timer_c2_ok = 1; - return 0; -} -early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); - static int __init apic_set_verbosity(char *arg) { if (!arg) { -- GitLab From e75bedf415f300a08e9bbcc755784e488574a73e Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 20:46:03 +0400 Subject: [PATCH 0400/5416] x86: apic - lapic_resume 32bit - unification fix Just add parenthesis to be identical of current 64bit implementation (so diff will not complain). Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 885e306420a..e975562a76a 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1646,6 +1646,7 @@ static int lapic_resume(struct sys_device *dev) enable_x2apic(); else #endif + { /* * Make sure the APICBASE points to the right address * @@ -1656,6 +1657,7 @@ static int lapic_resume(struct sys_device *dev) l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + } apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); -- GitLab From 1b4ee4e4096d430c4c12516c1d30a6b0b4f9e9e4 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 18 Aug 2008 23:12:33 +0400 Subject: [PATCH 0401/5416] x86: apic - compilation warnings fix Signed-off-by: Cyrill Gorcunov Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 15 +++++++++------ arch/x86/kernel/apic_64.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index e975562a76a..b8d80c29165 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -1162,11 +1162,13 @@ void __cpuinit end_local_APIC_setup(void) lapic_setup_esr(); #ifdef CONFIG_X86_32 - unsigned int value; - /* Disable the local apic timer */ - value = apic_read(APIC_LVTT); - value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); - apic_write(APIC_LVTT, value); + { + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); + } #endif setup_apic_nmi_watchdog(NULL); @@ -1426,6 +1428,8 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { + unsigned int value; + #ifdef CONFIG_X86_32 if (pic_mode) { /* @@ -1443,7 +1447,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) #endif /* Go back to Virtual Wire compatibility mode */ - unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 7a317180ba2..37e037606f3 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -1020,11 +1020,13 @@ void __cpuinit end_local_APIC_setup(void) lapic_setup_esr(); #ifdef CONFIG_X86_32 - unsigned int value; - /* Disable the local apic timer */ - value = apic_read(APIC_LVTT); - value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); - apic_write(APIC_LVTT, value); + { + unsigned int value; + /* Disable the local apic timer */ + value = apic_read(APIC_LVTT); + value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, value); + } #endif setup_apic_nmi_watchdog(NULL); @@ -1363,6 +1365,8 @@ void __init connect_bsp_APIC(void) */ void disconnect_bsp_APIC(int virt_wire_setup) { + unsigned int value; + #ifdef CONFIG_X86_32 if (pic_mode) { /* @@ -1380,7 +1384,6 @@ void disconnect_bsp_APIC(int virt_wire_setup) #endif /* Go back to Virtual Wire compatibility mode */ - unsigned int value; /* For the spurious interrupt use vector F, and enable it */ value = apic_read(APIC_SPIV); -- GitLab From 467cd0529a480c9c25f06154b788d1d1ba77828a Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 18 Aug 2008 16:56:29 -0700 Subject: [PATCH 0402/5416] x86: early_printk.c trivial sparse fixes arch/x86/kernel/early_printk.c:404:13: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:404:13: expected restricted __le16 [assigned] [usertype] wValue arch/x86/kernel/early_printk.c:404:13: got int [signed] value arch/x86/kernel/early_printk.c:405:13: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:405:13: expected restricted __le16 [assigned] [usertype] wIndex arch/x86/kernel/early_printk.c:405:13: got int [signed] index arch/x86/kernel/early_printk.c:406:14: warning: incorrect type in assignment (different base types) arch/x86/kernel/early_printk.c:406:14: expected restricted __le16 [assigned] [usertype] wLength arch/x86/kernel/early_printk.c:406:14: got int [signed] size arch/x86/kernel/early_printk.c:845:16: warning: Using plain integer as NULL pointer arch/x86/kernel/early_printk.c:992:13: warning: symbol 'enable_debug_console' was not declared. Should it be static? Signed-off-by: Harvey Harrison Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 28155acf706..825e9136b02 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -401,9 +401,9 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, int request, /* Compute the control message */ req.bRequestType = requesttype; req.bRequest = request; - req.wValue = value; - req.wIndex = index; - req.wLength = size; + req.wValue = cpu_to_le16(value); + req.wIndex = cpu_to_le16(index); + req.wLength = cpu_to_le16(size); pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); addr = DBGP_EPADDR(devnum, 0); @@ -842,7 +842,7 @@ static int __init early_dbgp_init(char *s) ret = ehci_setup(); if (ret < 0) { dbgp_printk("ehci_setup failed\n"); - ehci_debug = 0; + ehci_debug = NULL; return -1; } @@ -989,7 +989,7 @@ static int __init setup_early_printk(char *buf) return 0; } -void __init enable_debug_console(char *buf) +static void __init enable_debug_console(char *buf) { #ifdef DBGP_DEBUG struct console *old_early_console = NULL; -- GitLab From e2fe16d91228a005811335fbc4fbad5d4f5b75af Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 15 Aug 2008 15:36:31 -0700 Subject: [PATCH 0403/5416] x86: boot: stub out unimplemented CPU feature words The CPU feature detection code in the boot code is somewhat minimal, and doesn't include all possible CPUID words. In particular, it doesn't contain the code for CPU feature words 2 (Transmeta), 3 (Linux-specific), 5 (VIA), or 7 (scattered). Zero them out, so we can still set those bits as known at compile time; in particular, this allows creating a Linux-specific NOPL flag and have it required (and therefore resolvable at compile time) in 64-bit mode. Signed-off-by: H. Peter Anvin --- arch/x86/boot/cpucheck.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 7804389ee00..19b14f7ef9f 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -46,12 +46,12 @@ static const u32 req_flags[NCAPINTS] = { REQUIRED_MASK0, REQUIRED_MASK1, - REQUIRED_MASK2, - REQUIRED_MASK3, + 0, /* REQUIRED_MASK2 not implemented in this file */ + 0, /* REQUIRED_MASK3 not implemented in this file */ REQUIRED_MASK4, - REQUIRED_MASK5, + 0, /* REQUIRED_MASK5 not implemented in this file */ REQUIRED_MASK6, - REQUIRED_MASK7, + 0, /* REQUIRED_MASK7 not implemented in this file */ }; #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) -- GitLab From 7e00df5818964298c9821365a6cb7a8304227c5c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:39:32 -0700 Subject: [PATCH 0404/5416] x86: add NOPL as a synthetic CPU feature bit The long noops ("NOPL") are supposed to be detected by family >= 6. Unfortunately, several non-Intel x86 implementations, both hardware and software, don't obey this dictum. Instead, probe for NOPL directly by executing a NOPL instruction and see if we get #UD. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 32 ++++++++++++++++++++++++- arch/x86/kernel/cpu/common_64.c | 36 +++++++++++++++++++++++++++++ arch/x86/kernel/cpu/feature_names.c | 3 ++- include/asm-x86/cpufeature.h | 11 +++++---- include/asm-x86/required-features.h | 8 ++++++- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa3..0785b3c8d04 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include @@ -341,6 +342,35 @@ static void __init early_cpu_detect(void) early_get_cap(c); } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { u32 tfms, xlvl; @@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) } init_scattered_cpuid_features(c); + detect_nopl(c); } - } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index dd6e3f15017..c3afba5a81a 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef CONFIG_X86_LOCAL_APIC #include @@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void) } } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + * + * Note: no 64-bit chip is known to lack these, but put the code here + * for consistency with 32 bits, and to make it utterly trivial to + * diagnose the problem should it ever surface. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); void __init early_cpu_init(void) @@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86_phys_bits = eax & 0xff; } + detect_nopl(c); + if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4ad4cb..c9017799497 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = { NULL, NULL, NULL, NULL, "constant_tsc", "up", NULL, "arch_perfmon", "pebs", "bts", NULL, NULL, - "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "rep_good", NULL, NULL, NULL, + "nopl", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 2f5a792b0ac..be8b2ad5d41 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -72,14 +72,15 @@ #define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */ #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */ +#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ +#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */ +#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */ #define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */ #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ -#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ +#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ +#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff --git a/include/asm-x86/required-features.h b/include/asm-x86/required-features.h index adec887dd7c..5c2ff4bc298 100644 --- a/include/asm-x86/required-features.h +++ b/include/asm-x86/required-features.h @@ -41,6 +41,12 @@ # define NEED_3DNOW 0 #endif +#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64) +# define NEED_NOPL (1<<(X86_FEATURE_NOPL & 31)) +#else +# define NEED_NOPL 0 +#endif + #ifdef CONFIG_X86_64 #define NEED_PSE 0 #define NEED_MSR (1<<(X86_FEATURE_MSR & 31)) @@ -67,7 +73,7 @@ #define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW) #define REQUIRED_MASK2 0 -#define REQUIRED_MASK3 0 +#define REQUIRED_MASK3 (NEED_NOPL) #define REQUIRED_MASK4 0 #define REQUIRED_MASK5 0 #define REQUIRED_MASK6 0 -- GitLab From f1c5d30e1d79bbfb60eaf189db862d3cb2bcac92 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:50:33 -0700 Subject: [PATCH 0405/5416] x86: use X86_FEATURE_NOPL in alternatives Use X86_FEATURE_NOPL to determine if it is safe to use P6 NOPs in alternatives. Also, replace table and loop with simple if statement. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/alternative.c | 36 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb37b55..65a0c1b4869 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = { extern char __vsyscall_0; const unsigned char *const *find_nop_table(void) { - return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || - boot_cpu_data.x86 < 6 ? k8_nops : p6_nops; + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return k8_nops; } #else /* CONFIG_X86_64 */ -static const struct nop { - int cpuid; - const unsigned char *const *noptable; -} noptypes[] = { - { X86_FEATURE_K8, k8_nops }, - { X86_FEATURE_K7, k7_nops }, - { X86_FEATURE_P4, p6_nops }, - { X86_FEATURE_P3, p6_nops }, - { -1, NULL } -}; - const unsigned char *const *find_nop_table(void) { - const unsigned char *const *noptable = intel_nops; - int i; - - for (i = 0; noptypes[i].cpuid >= 0; i++) { - if (boot_cpu_has(noptypes[i].cpuid)) { - noptable = noptypes[i].noptable; - break; - } - } - return noptable; + if (boot_cpu_has(X86_FEATURE_K8)) + return k8_nops; + else if (boot_cpu_has(X86_FEATURE_K7)) + return k7_nops; + else if (boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return intel_nops; } #endif /* CONFIG_X86_64 */ -- GitLab From 8df9676d6402563da91427e8d9f2da8a4598aede Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 18:13:33 -0700 Subject: [PATCH 0406/5416] x86: consistency cleanups Rename _ASM_MOV_UL to _ASM_MOV for consistency with other _ASM_ instructions (_ASM_ADD, _ASM_SUB and so on.) Add ASM_SP, _ASM_BP, _ASM_SI, and _ASM_DI for consistency with _ASM_[ABCD]X. Signed-off-by: H. Peter Anvin --- include/asm-x86/asm.h | 7 ++++++- include/asm-x86/resume-trace.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/asm-x86/asm.h b/include/asm-x86/asm.h index 97220321f39..56be78f582f 100644 --- a/include/asm-x86/asm.h +++ b/include/asm-x86/asm.h @@ -20,17 +20,22 @@ #define _ASM_PTR __ASM_SEL(.long, .quad) #define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8) -#define _ASM_MOV_UL __ASM_SIZE(mov) +#define _ASM_MOV __ASM_SIZE(mov) #define _ASM_INC __ASM_SIZE(inc) #define _ASM_DEC __ASM_SIZE(dec) #define _ASM_ADD __ASM_SIZE(add) #define _ASM_SUB __ASM_SIZE(sub) #define _ASM_XADD __ASM_SIZE(xadd) + #define _ASM_AX __ASM_REG(ax) #define _ASM_BX __ASM_REG(bx) #define _ASM_CX __ASM_REG(cx) #define _ASM_DX __ASM_REG(dx) +#define _ASM_SP __ASM_REG(sp) +#define _ASM_BP __ASM_REG(bp) +#define _ASM_SI __ASM_REG(si) +#define _ASM_DI __ASM_REG(di) /* Exception table entry */ # define _ASM_EXTABLE(from,to) \ diff --git a/include/asm-x86/resume-trace.h b/include/asm-x86/resume-trace.h index 8d9f0b41ee8..e219b4c9119 100644 --- a/include/asm-x86/resume-trace.h +++ b/include/asm-x86/resume-trace.h @@ -7,7 +7,7 @@ do { \ if (pm_trace_enabled) { \ const void *tracedata; \ - asm volatile(_ASM_MOV_UL " $1f,%0\n" \ + asm volatile(_ASM_MOV " $1f,%0\n" \ ".section .tracedata,\"a\"\n" \ "1:\t.word %c1\n\t" \ _ASM_PTR " %c2\n" \ -- GitLab From 20211e4d344729f4d4c93da37a590fc1c3a1fd9b Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 18 Aug 2008 21:25:38 +0200 Subject: [PATCH 0407/5416] x86: Coding style fixes to arch/x86/oprofile/op_model_p4.c A coding style patch to arch/x86/oprofile/op_model_p4.c that removes 87 errors and 4 warnings. Before: total: 89 errors, 13 warnings, 722 lines checked After: total: 2 errors, 9 warnings, 721 lines checked Compile tested, binary verified as follow: paolo@paolo-desktop:~/linux.trees.git$ size /tmp/op_model_p4.o.* text data bss dec hex filename 2691 968 32 3691 e6b /tmp/op_model_p4.o.after 2691 968 32 3691 e6b /tmp/op_model_p4.o.before paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/op_model_p4.o.* 8c1c9823bab33333e1f7f76574e62561 /tmp/op_model_p4.o.after 8c1c9823bab33333e1f7f76574e62561 /tmp/op_model_p4.o.before Signed-off-by: Paolo Ciarrocchi Cc: robert.richter@amd.com Signed-off-by: Ingo Molnar --- arch/x86/oprofile/op_model_p4.c | 175 ++++++++++++++++---------------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 56b4757a1f4..43ac5af338d 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -10,11 +10,12 @@ #include #include +#include +#include #include -#include #include #include -#include + #include "op_x86_model.h" #include "op_counter.h" @@ -40,7 +41,7 @@ static unsigned int num_controls = NUM_CONTROLS_NON_HT; static inline void setup_num_counters(void) { #ifdef CONFIG_SMP - if (smp_num_siblings == 2){ + if (smp_num_siblings == 2) { num_counters = NUM_COUNTERS_HT2; num_controls = NUM_CONTROLS_HT2; } @@ -86,7 +87,7 @@ struct p4_event_binding { #define CTR_FLAME_2 (1 << 6) #define CTR_IQ_5 (1 << 7) -static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { +static struct p4_counter_binding p4_counters[NUM_COUNTERS_NON_HT] = { { CTR_BPU_0, MSR_P4_BPU_PERFCTR0, MSR_P4_BPU_CCCR0 }, { CTR_MS_0, MSR_P4_MS_PERFCTR0, MSR_P4_MS_CCCR0 }, { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 }, @@ -97,32 +98,32 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } }; -#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT +#define NUM_UNUSED_CCCRS (NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT) /* p4 event codes in libop/op_event.h are indices into this table. */ static struct p4_event_binding p4_events[NUM_EVENTS] = { - + { /* BRANCH_RETIRED */ - 0x05, 0x06, + 0x05, 0x06, { {CTR_IQ_4, MSR_P4_CRU_ESCR2}, {CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, - + { /* MISPRED_BRANCH_RETIRED */ - 0x04, 0x03, + 0x04, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - + { /* TC_DELIVER_MODE */ 0x01, 0x01, - { { CTR_MS_0, MSR_P4_TC_ESCR0}, + { { CTR_MS_0, MSR_P4_TC_ESCR0}, { CTR_MS_2, MSR_P4_TC_ESCR1} } }, - + { /* BPU_FETCH_REQUEST */ - 0x00, 0x03, + 0x00, 0x03, { { CTR_BPU_0, MSR_P4_BPU_ESCR0}, { CTR_BPU_2, MSR_P4_BPU_ESCR1} } }, @@ -146,7 +147,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* LOAD_PORT_REPLAY */ - 0x02, 0x04, + 0x02, 0x04, { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } }, @@ -170,43 +171,43 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* BSQ_CACHE_REFERENCE */ - 0x07, 0x0c, + 0x07, 0x0c, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { CTR_BPU_2, MSR_P4_BSU_ESCR1} } }, { /* IOQ_ALLOCATION */ - 0x06, 0x03, + 0x06, 0x03, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { 0, 0 } } }, { /* IOQ_ACTIVE_ENTRIES */ - 0x06, 0x1a, + 0x06, 0x1a, { { CTR_BPU_2, MSR_P4_FSB_ESCR1}, { 0, 0 } } }, { /* FSB_DATA_ACTIVITY */ - 0x06, 0x17, + 0x06, 0x17, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, { /* BSQ_ALLOCATION */ - 0x07, 0x05, + 0x07, 0x05, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { 0, 0 } } }, { /* BSQ_ACTIVE_ENTRIES */ 0x07, 0x06, - { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, + { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, { 0, 0 } } }, { /* X87_ASSIST */ - 0x05, 0x03, + 0x05, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -216,21 +217,21 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_SP_UOP */ - 0x01, 0x08, + 0x01, 0x08, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_DP_UOP */ - 0x01, 0x0c, + 0x01, 0x0c, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* SCALAR_SP_UOP */ - 0x01, 0x0a, + 0x01, 0x0a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, @@ -242,31 +243,31 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* 64BIT_MMX_UOP */ - 0x01, 0x02, + 0x01, 0x02, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* 128BIT_MMX_UOP */ - 0x01, 0x1a, + 0x01, 0x1a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* X87_FP_UOP */ - 0x01, 0x04, + 0x01, 0x04, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* X87_SIMD_MOVES_UOP */ - 0x01, 0x2e, + 0x01, 0x2e, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* MACHINE_CLEAR */ - 0x05, 0x02, + 0x05, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -276,9 +277,9 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, - + { /* TC_MS_XFER */ - 0x00, 0x05, + 0x00, 0x05, { { CTR_MS_0, MSR_P4_MS_ESCR0}, { CTR_MS_2, MSR_P4_MS_ESCR1} } }, @@ -308,7 +309,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* INSTR_RETIRED */ - 0x04, 0x02, + 0x04, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, @@ -319,14 +320,14 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - { /* UOP_TYPE */ - 0x02, 0x02, + { /* UOP_TYPE */ + 0x02, 0x02, { { CTR_IQ_4, MSR_P4_RAT_ESCR0}, { CTR_IQ_5, MSR_P4_RAT_ESCR1} } }, { /* RETIRED_MISPRED_BRANCH_TYPE */ - 0x02, 0x05, + 0x02, 0x05, { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, { CTR_MS_2, MSR_P4_TBPU_ESCR1} } }, @@ -349,8 +350,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1)) #define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25)) #define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9)) -#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) -#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) +#define ESCR_READ(escr, high, ev, i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) +#define ESCR_WRITE(escr, high, ev, i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) #define CCCR_RESERVED_BITS 0x38030FFF #define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) @@ -360,15 +361,15 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27)) #define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12)) #define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12)) -#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) -#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) +#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31)) #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31))) -#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0) -#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0) -#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0) -#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0) +#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) +#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) +#define CTR_READ(l, h, i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h)); } while (0) +#define CTR_WRITE(l, i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1); } while (0) #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000)) @@ -380,7 +381,7 @@ static unsigned int get_stagger(void) #ifdef CONFIG_SMP int cpu = smp_processor_id(); return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); -#endif +#endif return 0; } @@ -395,25 +396,23 @@ static unsigned long reset_value[NUM_COUNTERS_NON_HT]; static void p4_fill_in_addresses(struct op_msrs * const msrs) { - unsigned int i; + unsigned int i; unsigned int addr, cccraddr, stag; setup_num_counters(); stag = get_stagger(); /* initialize some registers */ - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) msrs->counters[i].addr = 0; - } - for (i = 0; i < num_controls; ++i) { + for (i = 0; i < num_controls; ++i) msrs->controls[i].addr = 0; - } - + /* the counter & cccr registers we pay attention to */ for (i = 0; i < num_counters; ++i) { addr = p4_counters[VIRT_CTR(stag, i)].counter_address; cccraddr = p4_counters[VIRT_CTR(stag, i)].cccr_address; - if (reserve_perfctr_nmi(addr)){ + if (reserve_perfctr_nmi(addr)) { msrs->counters[i].addr = addr; msrs->controls[i].addr = cccraddr; } @@ -447,22 +446,22 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_MS_ESCR0 + stag; - addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { + addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_IX_ESCR0 + stag; - addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { + addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } /* there are 2 remaining non-contiguously located ESCRs */ - if (num_counters == NUM_COUNTERS_NON_HT) { + if (num_counters == NUM_COUNTERS_NON_HT) { /* standard non-HT CPUs handle both remaining ESCRs*/ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5)) msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; @@ -498,20 +497,20 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) unsigned int stag; stag = get_stagger(); - + /* convert from counter *number* to counter *bit* */ counter_bit = 1 << VIRT_CTR(stag, ctr); - + /* find our event binding structure. */ if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { - printk(KERN_ERR - "oprofile: P4 event code 0x%lx out of range\n", + printk(KERN_ERR + "oprofile: P4 event code 0x%lx out of range\n", counter_config[ctr].event); return; } - + ev = &(p4_events[counter_config[ctr].event - 1]); - + for (i = 0; i < maxbind; i++) { if (ev->bindings[i].virt_counter & counter_bit) { @@ -526,25 +525,24 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) ESCR_SET_OS_1(escr, counter_config[ctr].kernel); } ESCR_SET_EVENT_SELECT(escr, ev->event_select); - ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); + ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); ESCR_WRITE(escr, high, ev, i); - + /* modify CCCR */ CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); CCCR_CLEAR(cccr); CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); - if (stag == 0) { + if (stag == 0) CCCR_SET_PMI_OVF_0(cccr); - } else { + else CCCR_SET_PMI_OVF_1(cccr); - } CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); return; } } - printk(KERN_ERR + printk(KERN_ERR "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n", counter_config[ctr].event, stag, ctr); } @@ -559,14 +557,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); - if (! MISC_PMC_ENABLED_P(low)) { + if (!MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } /* clear the cccrs we will use */ for (i = 0 ; i < num_counters ; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); @@ -576,14 +574,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) /* clear all escrs (including those outside our concern) */ for (i = num_counters; i < num_controls; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; wrmsr(msrs->controls[i].addr, 0, 0); } /* setup all counters */ for (i = 0 ; i < num_counters ; ++i) { - if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs,i))) { + if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs, i))) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); @@ -603,11 +601,11 @@ static int p4_check_ctrs(struct pt_regs * const regs, stag = get_stagger(); for (i = 0; i < num_counters; ++i) { - - if (!reset_value[i]) + + if (!reset_value[i]) continue; - /* + /* * there is some eccentricity in the hardware which * requires that we perform 2 extra corrections: * @@ -616,24 +614,24 @@ static int p4_check_ctrs(struct pt_regs * const regs, * * - write the counter back twice to ensure it gets * updated properly. - * + * * the former seems to be related to extra NMIs happening * during the current NMI; the latter is reported as errata * N15 in intel doc 249199-029, pentium 4 specification * update, though their suggested work-around does not * appear to solve the problem. */ - + real = VIRT_CTR(stag, i); CCCR_READ(low, high, real); - CTR_READ(ctr, high, real); + CTR_READ(ctr, high, real); if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) { oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); CCCR_CLEAR_OVF(low); CCCR_WRITE(low, high, real); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); } } @@ -683,15 +681,16 @@ static void p4_shutdown(struct op_msrs const * const msrs) int i; for (i = 0 ; i < num_counters ; ++i) { - if (CTR_IS_RESERVED(msrs,i)) + if (CTR_IS_RESERVED(msrs, i)) release_perfctr_nmi(msrs->counters[i].addr); } - /* some of the control registers are specially reserved in + /* + * some of the control registers are specially reserved in * conjunction with the counter registers (hence the starting offset). * This saves a few bits. */ for (i = num_counters ; i < num_controls ; ++i) { - if (CTRL_IS_RESERVED(msrs,i)) + if (CTRL_IS_RESERVED(msrs, i)) release_evntsel_nmi(msrs->controls[i].addr); } } -- GitLab From eff9b713ee3540ddab862095aaf4b1511a6758bc Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 18 Aug 2008 17:51:08 -0700 Subject: [PATCH 0408/5416] rcu: fix locking cleanup fallout Given that the rcp->lock is now acquired from call_rcu(), which can be invoked from irq-disable regions, all acquisitions need to disable irqs. The following patch fixes this. Although I don't have any reason to believe that this is the cause of Yinghai's oops, it does need to be fixed. Signed-off-by: Paul E. McKenney Cc: Yinghai Lu Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index fb1f1cc4514..c6b6cf55f3e 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -86,8 +86,10 @@ static void force_quiescent_state(struct rcu_data *rdp, { int cpu; cpumask_t cpumask; + unsigned long flags; + set_need_resched(); - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); if (unlikely(!rcp->signaled)) { rcp->signaled = 1; /* @@ -113,7 +115,7 @@ static void force_quiescent_state(struct rcu_data *rdp, for_each_cpu_mask_nr(cpu, cpumask) smp_send_reschedule(cpu); } - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } #else static inline void force_quiescent_state(struct rcu_data *rdp, @@ -301,17 +303,18 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) { int cpu; long delta; + unsigned long flags; /* Only let one CPU complain about others per time interval. */ - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); delta = get_seconds() - rcp->gp_check; if (delta < 2L || cpus_empty(rcp->cpumask)) { spin_unlock(&rcp->lock); return; } rcp->gp_check = get_seconds() + 30; - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); /* OK, time to rat on our buddy... */ @@ -324,13 +327,15 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) static void print_cpu_stall(struct rcu_ctrlblk *rcp) { + unsigned long flags; + printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu)\n", smp_processor_id(), get_seconds(), rcp->gp_check); dump_stack(); - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); if ((long)(get_seconds() - rcp->gp_check) >= 0L) rcp->gp_check = get_seconds() + 30; - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } static void check_cpu_stall(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) @@ -413,6 +418,8 @@ static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp) static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + unsigned long flags; + if (rdp->quiescbatch != rcp->cur) { /* start new grace period: */ rdp->qs_pending = 1; @@ -436,7 +443,7 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, return; rdp->qs_pending = 0; - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); /* * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync * during cpu startup. Ignore the quiescent state. @@ -444,7 +451,7 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, if (likely(rdp->quiescbatch == rcp->cur)) cpu_quiet(rdp->cpu, rcp); - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } @@ -469,21 +476,22 @@ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list, static void __rcu_offline_cpu(struct rcu_data *this_rdp, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + unsigned long flags; + /* * if the cpu going offline owns the grace period * we can block indefinitely waiting for it, so flush * it here */ - spin_lock_bh(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); if (rcp->cur != rcp->completed) cpu_quiet(rdp->cpu, rcp); rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail, rcp->cur + 1); rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail[2], rcp->cur + 1); - spin_unlock_bh(&rcp->lock); + spin_unlock(&rcp->lock); - local_irq_disable(); this_rdp->qlen += rdp->qlen; - local_irq_enable(); + local_irq_restore(flags); } static void rcu_offline_cpu(int cpu) @@ -550,12 +558,12 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, if (rcu_batch_after(rdp->batch, rcp->pending)) { /* and start it/schedule start if it's a new batch */ - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); if (rcu_batch_after(rdp->batch, rcp->pending)) { rcp->pending = rdp->batch; rcu_start_batch(rcp); } - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } } -- GitLab From 39ac50d0c79747b186c1268d9a488f8c1d256be7 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Mon, 18 Aug 2008 00:52:08 +0200 Subject: [PATCH 0409/5416] ipvs: Fix race conditions in lblc scheduler We can't access the cache entry outside of our critical read-locked region, because someone may free that entry. And we also need to check in the critical region wether the destination is still available, i.e. it's not in the trash. If we drop our reference counter, the destination can be purged from the trash at any time. Our caller only guarantees that no destination is moved to the trash, while we are scheduling. Also there is no need for our own rwlock, there is already one in the service structure for use in the schedulers. Signed-off-by: Sven Wegener Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_lblc.c | 204 +++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 108 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index b9b334cccf3..d2a43aa3fe4 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c @@ -96,7 +96,6 @@ struct ip_vs_lblc_entry { * IPVS lblc hash table */ struct ip_vs_lblc_table { - rwlock_t lock; /* lock for this table */ struct list_head bucket[IP_VS_LBLC_TAB_SIZE]; /* hash bucket */ atomic_t entries; /* number of entries */ int max_size; /* maximum size of entries */ @@ -123,31 +122,6 @@ static ctl_table vs_vars_table[] = { static struct ctl_table_header * sysctl_header; -/* - * new/free a ip_vs_lblc_entry, which is a mapping of a destionation - * IP address to a server. - */ -static inline struct ip_vs_lblc_entry * -ip_vs_lblc_new(__be32 daddr, struct ip_vs_dest *dest) -{ - struct ip_vs_lblc_entry *en; - - en = kmalloc(sizeof(struct ip_vs_lblc_entry), GFP_ATOMIC); - if (en == NULL) { - IP_VS_ERR("ip_vs_lblc_new(): no memory\n"); - return NULL; - } - - INIT_LIST_HEAD(&en->list); - en->addr = daddr; - - atomic_inc(&dest->refcnt); - en->dest = dest; - - return en; -} - - static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) { list_del(&en->list); @@ -173,55 +147,66 @@ static inline unsigned ip_vs_lblc_hashkey(__be32 addr) * Hash an entry in the ip_vs_lblc_table. * returns bool success. */ -static int +static void ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en) { - unsigned hash; - - if (!list_empty(&en->list)) { - IP_VS_ERR("ip_vs_lblc_hash(): request for already hashed, " - "called from %p\n", __builtin_return_address(0)); - return 0; - } + unsigned hash = ip_vs_lblc_hashkey(en->addr); - /* - * Hash by destination IP address - */ - hash = ip_vs_lblc_hashkey(en->addr); - - write_lock(&tbl->lock); list_add(&en->list, &tbl->bucket[hash]); atomic_inc(&tbl->entries); - write_unlock(&tbl->lock); - - return 1; } /* - * Get ip_vs_lblc_entry associated with supplied parameters. + * Get ip_vs_lblc_entry associated with supplied parameters. Called under read + * lock */ static inline struct ip_vs_lblc_entry * ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr) { - unsigned hash; + unsigned hash = ip_vs_lblc_hashkey(addr); struct ip_vs_lblc_entry *en; - hash = ip_vs_lblc_hashkey(addr); + list_for_each_entry(en, &tbl->bucket[hash], list) + if (en->addr == addr) + return en; - read_lock(&tbl->lock); + return NULL; +} - list_for_each_entry(en, &tbl->bucket[hash], list) { - if (en->addr == addr) { - /* HIT */ - read_unlock(&tbl->lock); - return en; + +/* + * Create or update an ip_vs_lblc_entry, which is a mapping of a destination IP + * address to a server. Called under write lock. + */ +static inline struct ip_vs_lblc_entry * +ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, __be32 daddr, + struct ip_vs_dest *dest) +{ + struct ip_vs_lblc_entry *en; + + en = ip_vs_lblc_get(tbl, daddr); + if (!en) { + en = kmalloc(sizeof(*en), GFP_ATOMIC); + if (!en) { + IP_VS_ERR("ip_vs_lblc_new(): no memory\n"); + return NULL; } - } - read_unlock(&tbl->lock); + en->addr = daddr; + en->lastuse = jiffies; - return NULL; + atomic_inc(&dest->refcnt); + en->dest = dest; + + ip_vs_lblc_hash(tbl, en); + } else if (en->dest != dest) { + atomic_dec(&en->dest->refcnt); + atomic_inc(&dest->refcnt); + en->dest = dest; + } + + return en; } @@ -230,30 +215,29 @@ ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr) */ static void ip_vs_lblc_flush(struct ip_vs_lblc_table *tbl) { - int i; struct ip_vs_lblc_entry *en, *nxt; + int i; for (i=0; ilock); list_for_each_entry_safe(en, nxt, &tbl->bucket[i], list) { ip_vs_lblc_free(en); atomic_dec(&tbl->entries); } - write_unlock(&tbl->lock); } } -static inline void ip_vs_lblc_full_check(struct ip_vs_lblc_table *tbl) +static inline void ip_vs_lblc_full_check(struct ip_vs_service *svc) { + struct ip_vs_lblc_table *tbl = svc->sched_data; + struct ip_vs_lblc_entry *en, *nxt; unsigned long now = jiffies; int i, j; - struct ip_vs_lblc_entry *en, *nxt; for (i=0, j=tbl->rover; ilock); + write_lock(&svc->sched_lock); list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) { if (time_before(now, en->lastuse + sysctl_ip_vs_lblc_expiration)) @@ -262,7 +246,7 @@ static inline void ip_vs_lblc_full_check(struct ip_vs_lblc_table *tbl) ip_vs_lblc_free(en); atomic_dec(&tbl->entries); } - write_unlock(&tbl->lock); + write_unlock(&svc->sched_lock); } tbl->rover = j; } @@ -281,17 +265,16 @@ static inline void ip_vs_lblc_full_check(struct ip_vs_lblc_table *tbl) */ static void ip_vs_lblc_check_expire(unsigned long data) { - struct ip_vs_lblc_table *tbl; + struct ip_vs_service *svc = (struct ip_vs_service *) data; + struct ip_vs_lblc_table *tbl = svc->sched_data; unsigned long now = jiffies; int goal; int i, j; struct ip_vs_lblc_entry *en, *nxt; - tbl = (struct ip_vs_lblc_table *)data; - if ((tbl->counter % COUNT_FOR_FULL_EXPIRATION) == 0) { /* do full expiration check */ - ip_vs_lblc_full_check(tbl); + ip_vs_lblc_full_check(svc); tbl->counter = 1; goto out; } @@ -308,7 +291,7 @@ static void ip_vs_lblc_check_expire(unsigned long data) for (i=0, j=tbl->rover; ilock); + write_lock(&svc->sched_lock); list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) { if (time_before(now, en->lastuse + ENTRY_TIMEOUT)) continue; @@ -317,7 +300,7 @@ static void ip_vs_lblc_check_expire(unsigned long data) atomic_dec(&tbl->entries); goal--; } - write_unlock(&tbl->lock); + write_unlock(&svc->sched_lock); if (goal <= 0) break; } @@ -336,15 +319,14 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) /* * Allocate the ip_vs_lblc_table for this service */ - tbl = kmalloc(sizeof(struct ip_vs_lblc_table), GFP_ATOMIC); + tbl = kmalloc(sizeof(*tbl), GFP_ATOMIC); if (tbl == NULL) { IP_VS_ERR("ip_vs_lblc_init_svc(): no memory\n"); return -ENOMEM; } svc->sched_data = tbl; IP_VS_DBG(6, "LBLC hash table (memory=%Zdbytes) allocated for " - "current service\n", - sizeof(struct ip_vs_lblc_table)); + "current service\n", sizeof(*tbl)); /* * Initialize the hash buckets @@ -352,7 +334,6 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) for (i=0; ibucket[i]); } - rwlock_init(&tbl->lock); tbl->max_size = IP_VS_LBLC_TAB_SIZE*16; tbl->rover = 0; tbl->counter = 1; @@ -361,9 +342,8 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) * Hook periodic timer for garbage collection */ setup_timer(&tbl->periodic_timer, ip_vs_lblc_check_expire, - (unsigned long)tbl); - tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL; - add_timer(&tbl->periodic_timer); + (unsigned long)svc); + mod_timer(&tbl->periodic_timer, jiffies + CHECK_EXPIRE_INTERVAL); return 0; } @@ -380,9 +360,9 @@ static int ip_vs_lblc_done_svc(struct ip_vs_service *svc) ip_vs_lblc_flush(tbl); /* release the table itself */ - kfree(svc->sched_data); + kfree(tbl); IP_VS_DBG(6, "LBLC hash table (memory=%Zdbytes) released\n", - sizeof(struct ip_vs_lblc_table)); + sizeof(*tbl)); return 0; } @@ -478,46 +458,54 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) static struct ip_vs_dest * ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) { - struct ip_vs_dest *dest; - struct ip_vs_lblc_table *tbl; - struct ip_vs_lblc_entry *en; + struct ip_vs_lblc_table *tbl = svc->sched_data; struct iphdr *iph = ip_hdr(skb); + struct ip_vs_dest *dest = NULL; + struct ip_vs_lblc_entry *en; IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n"); - tbl = (struct ip_vs_lblc_table *)svc->sched_data; + /* First look in our cache */ + read_lock(&svc->sched_lock); en = ip_vs_lblc_get(tbl, iph->daddr); - if (en == NULL) { - dest = __ip_vs_lblc_schedule(svc, iph); - if (dest == NULL) { - IP_VS_DBG(1, "no destination available\n"); - return NULL; - } - en = ip_vs_lblc_new(iph->daddr, dest); - if (en == NULL) { - return NULL; - } - ip_vs_lblc_hash(tbl, en); - } else { - dest = en->dest; - if (!(dest->flags & IP_VS_DEST_F_AVAILABLE) - || atomic_read(&dest->weight) <= 0 - || is_overloaded(dest, svc)) { - dest = __ip_vs_lblc_schedule(svc, iph); - if (dest == NULL) { - IP_VS_DBG(1, "no destination available\n"); - return NULL; - } - atomic_dec(&en->dest->refcnt); - atomic_inc(&dest->refcnt); - en->dest = dest; - } + if (en) { + /* We only hold a read lock, but this is atomic */ + en->lastuse = jiffies; + + /* + * If the destination is not available, i.e. it's in the trash, + * we must ignore it, as it may be removed from under our feet, + * if someone drops our reference count. Our caller only makes + * sure that destinations, that are not in the trash, are not + * moved to the trash, while we are scheduling. But anyone can + * free up entries from the trash at any time. + */ + + if (en->dest->flags & IP_VS_DEST_F_AVAILABLE) + dest = en->dest; + } + read_unlock(&svc->sched_lock); + + /* If the destination has a weight and is not overloaded, use it */ + if (dest && atomic_read(&dest->weight) > 0 && !is_overloaded(dest, svc)) + goto out; + + /* No cache entry or it is invalid, time to schedule */ + dest = __ip_vs_lblc_schedule(svc, iph); + if (!dest) { + IP_VS_DBG(1, "no destination available\n"); + return NULL; } - en->lastuse = jiffies; + /* If we fail to create a cache entry, we'll just use the valid dest */ + write_lock(&svc->sched_lock); + ip_vs_lblc_new(tbl, iph->daddr, dest); + write_unlock(&svc->sched_lock); + +out: IP_VS_DBG(6, "LBLC: destination IP address %u.%u.%u.%u " "--> server %u.%u.%u.%u:%d\n", - NIPQUAD(en->addr), + NIPQUAD(iph->daddr), NIPQUAD(dest->addr), ntohs(dest->port)); -- GitLab From f728bafb5698076dd35bca35ee6cfe52ea1b8ab2 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Tue, 19 Aug 2008 08:16:19 +0200 Subject: [PATCH 0410/5416] ipvs: Fix race conditions in lblcr scheduler We can't access the cache entry outside of our critical read-locked region, because someone may free that entry. Also getting an entry under read lock, then locking for write and trying to delete that entry looks fishy, but should be no problem here, because we're only comparing a pointer. Also there is no need for our own rwlock, there is already one in the service structure for use in the schedulers. Signed-off-by: Sven Wegener Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_lblcr.c | 229 ++++++++++++++++++------------------ 1 file changed, 114 insertions(+), 115 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index f1c84503689..375a1ffb6b6 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c @@ -106,7 +106,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) return NULL; } - e = kmalloc(sizeof(struct ip_vs_dest_list), GFP_ATOMIC); + e = kmalloc(sizeof(*e), GFP_ATOMIC); if (e == NULL) { IP_VS_ERR("ip_vs_dest_set_insert(): no memory\n"); return NULL; @@ -116,11 +116,9 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) e->dest = dest; /* link it to the list */ - write_lock(&set->lock); e->next = set->list; set->list = e; atomic_inc(&set->size); - write_unlock(&set->lock); set->lastmod = jiffies; return e; @@ -131,7 +129,6 @@ ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) { struct ip_vs_dest_list *e, **ep; - write_lock(&set->lock); for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { if (e->dest == dest) { /* HIT */ @@ -144,7 +141,6 @@ ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) } ep = &e->next; } - write_unlock(&set->lock); } static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) @@ -174,7 +170,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) if (set == NULL) return NULL; - read_lock(&set->lock); /* select the first destination server, whose weight > 0 */ for (e=set->list; e!=NULL; e=e->next) { least = e->dest; @@ -188,7 +183,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) goto nextstage; } } - read_unlock(&set->lock); return NULL; /* find the destination with the weighted least load */ @@ -207,7 +201,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) loh = doh; } } - read_unlock(&set->lock); IP_VS_DBG(6, "ip_vs_dest_set_min: server %d.%d.%d.%d:%d " "activeconns %d refcnt %d weight %d overhead %d\n", @@ -229,7 +222,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) if (set == NULL) return NULL; - read_lock(&set->lock); /* select the first destination server, whose weight > 0 */ for (e=set->list; e!=NULL; e=e->next) { most = e->dest; @@ -239,7 +231,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) goto nextstage; } } - read_unlock(&set->lock); return NULL; /* find the destination with the weighted most load */ @@ -256,7 +247,6 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) moh = doh; } } - read_unlock(&set->lock); IP_VS_DBG(6, "ip_vs_dest_set_max: server %d.%d.%d.%d:%d " "activeconns %d refcnt %d weight %d overhead %d\n", @@ -284,7 +274,6 @@ struct ip_vs_lblcr_entry { * IPVS lblcr hash table */ struct ip_vs_lblcr_table { - rwlock_t lock; /* lock for this table */ struct list_head bucket[IP_VS_LBLCR_TAB_SIZE]; /* hash bucket */ atomic_t entries; /* number of entries */ int max_size; /* maximum size of entries */ @@ -311,32 +300,6 @@ static ctl_table vs_vars_table[] = { static struct ctl_table_header * sysctl_header; -/* - * new/free a ip_vs_lblcr_entry, which is a mapping of a destination - * IP address to a server. - */ -static inline struct ip_vs_lblcr_entry *ip_vs_lblcr_new(__be32 daddr) -{ - struct ip_vs_lblcr_entry *en; - - en = kmalloc(sizeof(struct ip_vs_lblcr_entry), GFP_ATOMIC); - if (en == NULL) { - IP_VS_ERR("ip_vs_lblcr_new(): no memory\n"); - return NULL; - } - - INIT_LIST_HEAD(&en->list); - en->addr = daddr; - - /* initilize its dest set */ - atomic_set(&(en->set.size), 0); - en->set.list = NULL; - rwlock_init(&en->set.lock); - - return en; -} - - static inline void ip_vs_lblcr_free(struct ip_vs_lblcr_entry *en) { list_del(&en->list); @@ -358,55 +321,68 @@ static inline unsigned ip_vs_lblcr_hashkey(__be32 addr) * Hash an entry in the ip_vs_lblcr_table. * returns bool success. */ -static int +static void ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en) { - unsigned hash; - - if (!list_empty(&en->list)) { - IP_VS_ERR("ip_vs_lblcr_hash(): request for already hashed, " - "called from %p\n", __builtin_return_address(0)); - return 0; - } + unsigned hash = ip_vs_lblcr_hashkey(en->addr); - /* - * Hash by destination IP address - */ - hash = ip_vs_lblcr_hashkey(en->addr); - - write_lock(&tbl->lock); list_add(&en->list, &tbl->bucket[hash]); atomic_inc(&tbl->entries); - write_unlock(&tbl->lock); - - return 1; } /* - * Get ip_vs_lblcr_entry associated with supplied parameters. + * Get ip_vs_lblcr_entry associated with supplied parameters. Called under + * read lock. */ static inline struct ip_vs_lblcr_entry * ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr) { - unsigned hash; + unsigned hash = ip_vs_lblcr_hashkey(addr); struct ip_vs_lblcr_entry *en; - hash = ip_vs_lblcr_hashkey(addr); + list_for_each_entry(en, &tbl->bucket[hash], list) + if (en->addr == addr) + return en; + + return NULL; +} - read_lock(&tbl->lock); - list_for_each_entry(en, &tbl->bucket[hash], list) { - if (en->addr == addr) { - /* HIT */ - read_unlock(&tbl->lock); - return en; +/* + * Create or update an ip_vs_lblcr_entry, which is a mapping of a destination + * IP address to a server. Called under write lock. + */ +static inline struct ip_vs_lblcr_entry * +ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, __be32 daddr, + struct ip_vs_dest *dest) +{ + struct ip_vs_lblcr_entry *en; + + en = ip_vs_lblcr_get(tbl, daddr); + if (!en) { + en = kmalloc(sizeof(*en), GFP_ATOMIC); + if (!en) { + IP_VS_ERR("ip_vs_lblcr_new(): no memory\n"); + return NULL; } + + en->addr = daddr; + en->lastuse = jiffies; + + /* initilize its dest set */ + atomic_set(&(en->set.size), 0); + en->set.list = NULL; + rwlock_init(&en->set.lock); + + ip_vs_lblcr_hash(tbl, en); } - read_unlock(&tbl->lock); + write_lock(&en->set.lock); + ip_vs_dest_set_insert(&en->set, dest); + write_unlock(&en->set.lock); - return NULL; + return en; } @@ -418,19 +394,18 @@ static void ip_vs_lblcr_flush(struct ip_vs_lblcr_table *tbl) int i; struct ip_vs_lblcr_entry *en, *nxt; + /* No locking required, only called during cleanup. */ for (i=0; ilock); list_for_each_entry_safe(en, nxt, &tbl->bucket[i], list) { ip_vs_lblcr_free(en); - atomic_dec(&tbl->entries); } - write_unlock(&tbl->lock); } } -static inline void ip_vs_lblcr_full_check(struct ip_vs_lblcr_table *tbl) +static inline void ip_vs_lblcr_full_check(struct ip_vs_service *svc) { + struct ip_vs_lblcr_table *tbl = svc->sched_data; unsigned long now = jiffies; int i, j; struct ip_vs_lblcr_entry *en, *nxt; @@ -438,7 +413,7 @@ static inline void ip_vs_lblcr_full_check(struct ip_vs_lblcr_table *tbl) for (i=0, j=tbl->rover; ilock); + write_lock(&svc->sched_lock); list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) { if (time_after(en->lastuse+sysctl_ip_vs_lblcr_expiration, now)) @@ -447,7 +422,7 @@ static inline void ip_vs_lblcr_full_check(struct ip_vs_lblcr_table *tbl) ip_vs_lblcr_free(en); atomic_dec(&tbl->entries); } - write_unlock(&tbl->lock); + write_unlock(&svc->sched_lock); } tbl->rover = j; } @@ -466,17 +441,16 @@ static inline void ip_vs_lblcr_full_check(struct ip_vs_lblcr_table *tbl) */ static void ip_vs_lblcr_check_expire(unsigned long data) { - struct ip_vs_lblcr_table *tbl; + struct ip_vs_service *svc = (struct ip_vs_service *) data; + struct ip_vs_lblcr_table *tbl = svc->sched_data; unsigned long now = jiffies; int goal; int i, j; struct ip_vs_lblcr_entry *en, *nxt; - tbl = (struct ip_vs_lblcr_table *)data; - if ((tbl->counter % COUNT_FOR_FULL_EXPIRATION) == 0) { /* do full expiration check */ - ip_vs_lblcr_full_check(tbl); + ip_vs_lblcr_full_check(svc); tbl->counter = 1; goto out; } @@ -493,7 +467,7 @@ static void ip_vs_lblcr_check_expire(unsigned long data) for (i=0, j=tbl->rover; ilock); + write_lock(&svc->sched_lock); list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) { if (time_before(now, en->lastuse+ENTRY_TIMEOUT)) continue; @@ -502,7 +476,7 @@ static void ip_vs_lblcr_check_expire(unsigned long data) atomic_dec(&tbl->entries); goal--; } - write_unlock(&tbl->lock); + write_unlock(&svc->sched_lock); if (goal <= 0) break; } @@ -520,15 +494,14 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc) /* * Allocate the ip_vs_lblcr_table for this service */ - tbl = kmalloc(sizeof(struct ip_vs_lblcr_table), GFP_ATOMIC); + tbl = kmalloc(sizeof(*tbl), GFP_ATOMIC); if (tbl == NULL) { IP_VS_ERR("ip_vs_lblcr_init_svc(): no memory\n"); return -ENOMEM; } svc->sched_data = tbl; IP_VS_DBG(6, "LBLCR hash table (memory=%Zdbytes) allocated for " - "current service\n", - sizeof(struct ip_vs_lblcr_table)); + "current service\n", sizeof(*tbl)); /* * Initialize the hash buckets @@ -536,7 +509,6 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc) for (i=0; ibucket[i]); } - rwlock_init(&tbl->lock); tbl->max_size = IP_VS_LBLCR_TAB_SIZE*16; tbl->rover = 0; tbl->counter = 1; @@ -545,9 +517,8 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc) * Hook periodic timer for garbage collection */ setup_timer(&tbl->periodic_timer, ip_vs_lblcr_check_expire, - (unsigned long)tbl); - tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL; - add_timer(&tbl->periodic_timer); + (unsigned long)svc); + mod_timer(&tbl->periodic_timer, jiffies + CHECK_EXPIRE_INTERVAL); return 0; } @@ -564,9 +535,9 @@ static int ip_vs_lblcr_done_svc(struct ip_vs_service *svc) ip_vs_lblcr_flush(tbl); /* release the table itself */ - kfree(svc->sched_data); + kfree(tbl); IP_VS_DBG(6, "LBLCR hash table (memory=%Zdbytes) released\n", - sizeof(struct ip_vs_lblcr_table)); + sizeof(*tbl)); return 0; } @@ -663,50 +634,78 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) static struct ip_vs_dest * ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) { - struct ip_vs_dest *dest; - struct ip_vs_lblcr_table *tbl; - struct ip_vs_lblcr_entry *en; + struct ip_vs_lblcr_table *tbl = svc->sched_data; struct iphdr *iph = ip_hdr(skb); + struct ip_vs_dest *dest = NULL; + struct ip_vs_lblcr_entry *en; IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n"); - tbl = (struct ip_vs_lblcr_table *)svc->sched_data; + /* First look in our cache */ + read_lock(&svc->sched_lock); en = ip_vs_lblcr_get(tbl, iph->daddr); - if (en == NULL) { - dest = __ip_vs_lblcr_schedule(svc, iph); - if (dest == NULL) { - IP_VS_DBG(1, "no destination available\n"); - return NULL; - } - en = ip_vs_lblcr_new(iph->daddr); - if (en == NULL) { - return NULL; - } - ip_vs_dest_set_insert(&en->set, dest); - ip_vs_lblcr_hash(tbl, en); - } else { + if (en) { + /* We only hold a read lock, but this is atomic */ + en->lastuse = jiffies; + + /* Get the least loaded destination */ + read_lock(&en->set.lock); dest = ip_vs_dest_set_min(&en->set); - if (!dest || is_overloaded(dest, svc)) { - dest = __ip_vs_lblcr_schedule(svc, iph); - if (dest == NULL) { - IP_VS_DBG(1, "no destination available\n"); - return NULL; - } - ip_vs_dest_set_insert(&en->set, dest); - } + read_unlock(&en->set.lock); + + /* More than one destination + enough time passed by, cleanup */ if (atomic_read(&en->set.size) > 1 && - jiffies-en->set.lastmod > sysctl_ip_vs_lblcr_expiration) { + time_after(jiffies, en->set.lastmod + + sysctl_ip_vs_lblcr_expiration)) { struct ip_vs_dest *m; + + write_lock(&en->set.lock); m = ip_vs_dest_set_max(&en->set); if (m) ip_vs_dest_set_erase(&en->set, m); + write_unlock(&en->set.lock); + } + + /* If the destination is not overloaded, use it */ + if (dest && !is_overloaded(dest, svc)) { + read_unlock(&svc->sched_lock); + goto out; + } + + /* The cache entry is invalid, time to schedule */ + dest = __ip_vs_lblcr_schedule(svc, iph); + if (!dest) { + IP_VS_DBG(1, "no destination available\n"); + read_unlock(&svc->sched_lock); + return NULL; } + + /* Update our cache entry */ + write_lock(&en->set.lock); + ip_vs_dest_set_insert(&en->set, dest); + write_unlock(&en->set.lock); + } + read_unlock(&svc->sched_lock); + + if (dest) + goto out; + + /* No cache entry, time to schedule */ + dest = __ip_vs_lblcr_schedule(svc, iph); + if (!dest) { + IP_VS_DBG(1, "no destination available\n"); + return NULL; } - en->lastuse = jiffies; + /* If we fail to create a cache entry, we'll just use the valid dest */ + write_lock(&svc->sched_lock); + ip_vs_lblcr_new(tbl, iph->daddr, dest); + write_unlock(&svc->sched_lock); + +out: IP_VS_DBG(6, "LBLCR: destination IP address %u.%u.%u.%u " "--> server %u.%u.%u.%u:%d\n", - NIPQUAD(en->addr), + NIPQUAD(iph->daddr), NIPQUAD(dest->addr), ntohs(dest->port)); -- GitLab From f329bdd439aa24d03dca75cdb3027372ddf691b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 19 Aug 2008 10:56:33 +0300 Subject: [PATCH 0411/5416] mpu401: reindent misindented spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: Jaroslav Kysela --- sound/oss/mpu401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index a690ca57adb..6c0a770ed05 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c @@ -1015,7 +1015,7 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner) mpu401_chk_version(m, devc); if (devc->version == 0) mpu401_chk_version(m, devc); - spin_unlock_irqrestore(&devc->lock,flags); + spin_unlock_irqrestore(&devc->lock, flags); } if (devc->version != 0) -- GitLab From ad67ef6848a1608b0430003e11e7af1ce706e341 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:40 +0300 Subject: [PATCH 0412/5416] ARM: OMAP2: Powerdomain: Add base OMAP2/3 powerdomain code This patch creates an interface to the powerdomain registers in the PRM/CM modules on OMAP2/3. This interface is intended to be used by PM code, e.g., pm.c; not by device drivers directly. Each powerdomain will be defined in later patches as static structures. Also defined are dependencies between powerdomains, used for adding and removing PM_WKDEP and CM_SLEEPDEP bits. The powerdomain structures are linked into a list at boot by pwrdm_register(), similar to the OMAP clock code. The patch adds a Kconfig option, CONFIG_OMAP_DEBUG_POWERDOMAIN, which when enabled will emit verbose debug messages via pr_debug(). Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/clock34xx.c | 27 +- arch/arm/mach-omap2/powerdomain.c | 909 ++++++++++++++++++ arch/arm/plat-omap/Kconfig | 12 + arch/arm/plat-omap/include/mach/powerdomain.h | 139 +++ 5 files changed, 1078 insertions(+), 11 deletions(-) create mode 100644 arch/arm/mach-omap2/powerdomain.c create mode 100644 arch/arm/plat-omap/include/mach/powerdomain.h diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 93ee990618e..1001d42048e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \ - devices.o serial.o gpmc.o timer-gp.o + devices.o serial.o gpmc.o timer-gp.o powerdomain.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 3ff74952f83..dff7a72fefc 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -62,11 +62,14 @@ static void omap3_dpll_recalc(struct clk *clk) static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits) { const struct dpll_data *dd; + u32 v; dd = clk->dpll_data; - cm_rmw_reg_bits(dd->enable_mask, clken_bits << __ffs(dd->enable_mask), - dd->control_reg); + v = __raw_readl(dd->control_reg); + v &= ~dd->enable_mask; + v |= clken_bits << __ffs(dd->enable_mask); + __raw_writel(v, dd->control_reg); } /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ @@ -82,7 +85,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state) state <<= dd->idlest_bit; idlest_mask = 1 << dd->idlest_bit; - while (((cm_read_reg(dd->idlest_reg) & idlest_mask) != state) && + while (((__raw_readl(dd->idlest_reg) & idlest_mask) != state) && i < MAX_DPLL_WAIT_TRIES) { i++; udelay(1); @@ -285,7 +288,7 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk) dd = clk->dpll_data; - v = cm_read_reg(dd->autoidle_reg); + v = __raw_readl(dd->autoidle_reg); v &= dd->autoidle_mask; v >>= __ffs(dd->autoidle_mask); @@ -304,6 +307,7 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk) static void omap3_dpll_allow_idle(struct clk *clk) { const struct dpll_data *dd; + u32 v; if (!clk || !clk->dpll_data) return; @@ -315,9 +319,10 @@ static void omap3_dpll_allow_idle(struct clk *clk) * by writing 0x5 instead of 0x1. Add some mechanism to * optionally enter this mode. */ - cm_rmw_reg_bits(dd->autoidle_mask, - DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask), - dd->autoidle_reg); + v = __raw_readl(dd->autoidle_reg); + v &= ~dd->autoidle_mask; + v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); + __raw_writel(v, dd->autoidle_reg); } /** @@ -329,15 +334,17 @@ static void omap3_dpll_allow_idle(struct clk *clk) static void omap3_dpll_deny_idle(struct clk *clk) { const struct dpll_data *dd; + u32 v; if (!clk || !clk->dpll_data) return; dd = clk->dpll_data; - cm_rmw_reg_bits(dd->autoidle_mask, - DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask), - dd->autoidle_reg); + v = __raw_readl(dd->autoidle_reg); + v &= ~dd->autoidle_mask; + v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); + __raw_writel(v, dd->autoidle_reg); } /* Clock control for DPLL outputs */ diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c new file mode 100644 index 00000000000..1ec003832ef --- /dev/null +++ b/arch/arm/mach-omap2/powerdomain.c @@ -0,0 +1,909 @@ +/* + * OMAP powerdomain control + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2008 Nokia Corporation + * + * Written by Paul Walmsley + * + * 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. + */ +#ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN +# define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cm.h" +#include "cm-regbits-34xx.h" +#include "prm.h" +#include "prm-regbits-34xx.h" + +#include +#include + +/* pwrdm_list contains all registered struct powerdomains */ +static LIST_HEAD(pwrdm_list); + +/* + * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to + * protect pwrdm_clkdms[] during clkdm add/del ops + */ +static DEFINE_RWLOCK(pwrdm_rwlock); + + +/* Private functions */ + +static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask) +{ + u32 v; + + v = prm_read_mod_reg(domain, idx); + v &= mask; + v >>= __ffs(mask); + + return v; +} + +static struct powerdomain *_pwrdm_lookup(const char *name) +{ + struct powerdomain *pwrdm, *temp_pwrdm; + + pwrdm = NULL; + + list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { + if (!strcmp(name, temp_pwrdm->name)) { + pwrdm = temp_pwrdm; + break; + } + } + + return pwrdm; +} + +/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */ +static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm, + struct pwrdm_dep *deps) +{ + struct pwrdm_dep *pd; + + if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip)) + return ERR_PTR(-EINVAL); + + for (pd = deps; pd; pd++) { + + if (!omap_chip_is(pd->omap_chip)) + continue; + + if (!pd->pwrdm && pd->pwrdm_name) + pd->pwrdm = pwrdm_lookup(pd->pwrdm_name); + + if (pd->pwrdm == pwrdm) + break; + + } + + if (!pd) + return ERR_PTR(-ENOENT); + + return pd->pwrdm; +} + + +/* Public functions */ + +/** + * pwrdm_init - set up the powerdomain layer + * + * Loop through the list of powerdomains, registering all that are + * available on the current CPU. If pwrdm_list is supplied and not + * null, all of the referenced powerdomains will be registered. No + * return value. + */ +void pwrdm_init(struct powerdomain **pwrdm_list) +{ + struct powerdomain **p = NULL; + + if (pwrdm_list) + for (p = pwrdm_list; *p; p++) + pwrdm_register(*p); +} + +/** + * pwrdm_register - register a powerdomain + * @pwrdm: struct powerdomain * to register + * + * Adds a powerdomain to the internal powerdomain list. Returns + * -EINVAL if given a null pointer, -EEXIST if a powerdomain is + * already registered by the provided name, or 0 upon success. + */ +int pwrdm_register(struct powerdomain *pwrdm) +{ + unsigned long flags; + int ret = -EINVAL; + + if (!pwrdm) + return -EINVAL; + + if (!omap_chip_is(pwrdm->omap_chip)) + return -EINVAL; + + write_lock_irqsave(&pwrdm_rwlock, flags); + if (_pwrdm_lookup(pwrdm->name)) { + ret = -EEXIST; + goto pr_unlock; + } + + list_add(&pwrdm->node, &pwrdm_list); + + pr_debug("powerdomain: registered %s\n", pwrdm->name); + ret = 0; + +pr_unlock: + write_unlock_irqrestore(&pwrdm_rwlock, flags); + + return ret; +} + +/** + * pwrdm_unregister - unregister a powerdomain + * @pwrdm: struct powerdomain * to unregister + * + * Removes a powerdomain from the internal powerdomain list. Returns + * -EINVAL if pwrdm argument is NULL. + */ +int pwrdm_unregister(struct powerdomain *pwrdm) +{ + unsigned long flags; + + if (!pwrdm) + return -EINVAL; + + write_lock_irqsave(&pwrdm_rwlock, flags); + list_del(&pwrdm->node); + write_unlock_irqrestore(&pwrdm_rwlock, flags); + + pr_debug("powerdomain: unregistered %s\n", pwrdm->name); + + return 0; +} + +/** + * pwrdm_lookup - look up a powerdomain by name, return a pointer + * @name: name of powerdomain + * + * Find a registered powerdomain by its name. Returns a pointer to the + * struct powerdomain if found, or NULL otherwise. + */ +struct powerdomain *pwrdm_lookup(const char *name) +{ + struct powerdomain *pwrdm; + unsigned long flags; + + if (!name) + return NULL; + + read_lock_irqsave(&pwrdm_rwlock, flags); + pwrdm = _pwrdm_lookup(name); + read_unlock_irqrestore(&pwrdm_rwlock, flags); + + return pwrdm; +} + +/** + * pwrdm_for_each - call function on each registered clockdomain + * @fn: callback function * + * + * Call the supplied function for each registered powerdomain. The + * callback function can return anything but 0 to bail out early from + * the iterator. The callback function is called with the pwrdm_rwlock + * held for reading, so no powerdomain structure manipulation + * functions should be called from the callback, although hardware + * powerdomain control functions are fine. Returns the last return + * value of the callback function, which should be 0 for success or + * anything else to indicate failure; or -EINVAL if the function + * pointer is null. + */ +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) +{ + struct powerdomain *temp_pwrdm; + unsigned long flags; + int ret = 0; + + if (!fn) + return -EINVAL; + + read_lock_irqsave(&pwrdm_rwlock, flags); + list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { + ret = (*fn)(temp_pwrdm); + if (ret) + break; + } + read_unlock_irqrestore(&pwrdm_rwlock, flags); + + return ret; +} + +/** + * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1 + * @pwrdm1: wake this struct powerdomain * up (dependent) + * @pwrdm2: when this struct powerdomain * wakes up (source) + * + * When the powerdomain represented by pwrdm2 wakes up (due to an + * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP, + * this feature is designed to reduce wakeup latency of the dependent + * powerdomain. Returns -EINVAL if presented with invalid powerdomain + * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or + * 0 upon success. + */ +int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear wake up of " + "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); + return IS_ERR(p); + } + + pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n", + pwrdm1->name, pwrdm2->name); + + prm_set_mod_reg_bits((1 << pwrdm2->dep_bit), + pwrdm1->prcm_offs, PM_WKDEP); + + return 0; +} + +/** + * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1 + * @pwrdm1: wake this struct powerdomain * up (dependent) + * @pwrdm2: when this struct powerdomain * wakes up (source) + * + * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2 + * wakes up. Returns -EINVAL if presented with invalid powerdomain + * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or + * 0 upon success. + */ +int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear wake up of " + "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); + return IS_ERR(p); + } + + pr_debug("powerdomain: hardware will no longer wake up %s after %s " + "wakes up\n", pwrdm1->name, pwrdm2->name); + + prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit), + pwrdm1->prcm_offs, PM_WKDEP); + + return 0; +} + +/** + * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1 + * @pwrdm1: wake this struct powerdomain * up (dependent) + * @pwrdm2: when this struct powerdomain * wakes up (source) + * + * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be + * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL + * if either powerdomain pointer is invalid; or -ENOENT if the hardware + * is incapable. + * + * REVISIT: Currently this function only represents software-controllable + * wakeup dependencies. Wakeup dependencies fixed in hardware are not + * yet handled here. + */ +int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear wake up of " + "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); + return IS_ERR(p); + } + + return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP, + (1 << pwrdm2->dep_bit)); +} + +/** + * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) + * @pwrdm2: when this struct powerdomain * is active (source) + * + * Prevent pwrdm1 from automatically going inactive (and then to + * retention or off) if pwrdm2 is still active. Returns -EINVAL if + * presented with invalid powerdomain pointers or called on a machine + * that does not support software-configurable hardware sleep dependencies, + * -ENOENT if the specified dependency cannot be set in hardware, or + * 0 upon success. + */ +int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + if (!cpu_is_omap34xx()) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear sleep " + "dependency affecting %s from %s\n", pwrdm1->name, + pwrdm2->name); + return IS_ERR(p); + } + + pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n", + pwrdm1->name, pwrdm2->name); + + cm_set_mod_reg_bits((1 << pwrdm2->dep_bit), + pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP); + + return 0; +} + +/** + * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) + * @pwrdm2: when this struct powerdomain * is active (source) + * + * Allow pwrdm1 to automatically go inactive (and then to retention or + * off), independent of the activity state of pwrdm2. Returns -EINVAL + * if presented with invalid powerdomain pointers or called on a machine + * that does not support software-configurable hardware sleep dependencies, + * -ENOENT if the specified dependency cannot be cleared in hardware, or + * 0 upon success. + */ +int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + if (!cpu_is_omap34xx()) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear sleep " + "dependency affecting %s from %s\n", pwrdm1->name, + pwrdm2->name); + return IS_ERR(p); + } + + pr_debug("powerdomain: will no longer prevent %s from sleeping if " + "%s is active\n", pwrdm1->name, pwrdm2->name); + + cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit), + pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP); + + return 0; +} + +/** + * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) + * @pwrdm2: when this struct powerdomain * is active (source) + * + * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will + * not be allowed to automatically go inactive if pwrdm2 is active; + * 0 if pwrdm1's automatic power state inactivity transition is independent + * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called + * on a machine that does not support software-configurable hardware sleep + * dependencies; or -ENOENT if the hardware is incapable. + * + * REVISIT: Currently this function only represents software-controllable + * sleep dependencies. Sleep dependencies fixed in hardware are not + * yet handled here. + */ +int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) +{ + struct powerdomain *p; + + if (!pwrdm1) + return -EINVAL; + + if (!cpu_is_omap34xx()) + return -EINVAL; + + p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); + if (IS_ERR(p)) { + pr_debug("powerdomain: hardware cannot set/clear sleep " + "dependency affecting %s from %s\n", pwrdm1->name, + pwrdm2->name); + return IS_ERR(p); + } + + return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP, + (1 << pwrdm2->dep_bit)); +} + +/** + * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain + * @pwrdm: struct powerdomain * + * + * Return the number of controllable memory banks in powerdomain pwrdm, + * starting with 1. Returns -EINVAL if the powerdomain pointer is null. + */ +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + return pwrdm->banks; +} + +/** + * pwrdm_set_next_pwrst - set next powerdomain power state + * @pwrdm: struct powerdomain * to set + * @pwrst: one of the PWRDM_POWER_* macros + * + * Set the powerdomain pwrdm's next power state to pwrst. The powerdomain + * may not enter this state immediately if the preconditions for this state + * have not been satisfied. Returns -EINVAL if the powerdomain pointer is + * null or if the power state is invalid for the powerdomin, or returns 0 + * upon success. + */ +int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) +{ + if (!pwrdm) + return -EINVAL; + + if (!(pwrdm->pwrsts & (1 << pwrst))) + return -EINVAL; + + pr_debug("powerdomain: setting next powerstate for %s to %0x\n", + pwrdm->name, pwrst); + + prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, + (pwrst << OMAP_POWERSTATE_SHIFT), + pwrdm->prcm_offs, PM_PWSTCTRL); + + return 0; +} + +/** + * pwrdm_read_next_pwrst - get next powerdomain power state + * @pwrdm: struct powerdomain * to get power state + * + * Return the powerdomain pwrdm's next power state. Returns -EINVAL + * if the powerdomain pointer is null or returns the next power state + * upon success. + */ +int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, + OMAP_POWERSTATE_MASK); +} + +/** + * pwrdm_read_pwrst - get current powerdomain power state + * @pwrdm: struct powerdomain * to get power state + * + * Return the powerdomain pwrdm's current power state. Returns -EINVAL + * if the powerdomain pointer is null or returns the current power state + * upon success. + */ +int pwrdm_read_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, + OMAP_POWERSTATEST_MASK); +} + +/** + * pwrdm_read_prev_pwrst - get previous powerdomain power state + * @pwrdm: struct powerdomain * to get previous power state + * + * Return the powerdomain pwrdm's previous power state. Returns -EINVAL + * if the powerdomain pointer is null or returns the previous power state + * upon success. + */ +int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, + OMAP3430_LASTPOWERSTATEENTERED_MASK); +} + +/** + * pwrdm_set_logic_retst - set powerdomain logic power state upon retention + * @pwrdm: struct powerdomain * to set + * @pwrst: one of the PWRDM_POWER_* macros + * + * Set the next power state that the logic portion of the powerdomain + * pwrdm will enter when the powerdomain enters retention. This will + * be either RETENTION or OFF, if supported. Returns -EINVAL if the + * powerdomain pointer is null or the target power state is not not + * supported, or returns 0 upon success. + */ +int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) +{ + if (!pwrdm) + return -EINVAL; + + if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst))) + return -EINVAL; + + pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", + pwrdm->name, pwrst); + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE, + (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)), + pwrdm->prcm_offs, PM_PWSTCTRL); + + return 0; +} + +/** + * pwrdm_set_mem_onst - set memory power state while powerdomain ON + * @pwrdm: struct powerdomain * to set + * @bank: memory bank number to set (0-3) + * @pwrst: one of the PWRDM_POWER_* macros + * + * Set the next power state that memory bank x of the powerdomain + * pwrdm will enter when the powerdomain enters the ON state. Bank + * will be a number from 0 to 3, and represents different types of + * memory, depending on the powerdomain. Returns -EINVAL if the + * powerdomain pointer is null or the target power state is not not + * supported for this memory bank, -EEXIST if the target memory bank + * does not exist or is not controllable, or returns 0 upon success. + */ +int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) +{ + u32 m; + + if (!pwrdm) + return -EINVAL; + + if (pwrdm->banks < (bank + 1)) + return -EEXIST; + + if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst))) + return -EINVAL; + + pr_debug("powerdomain: setting next memory powerstate for domain %s " + "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + switch (bank) { + case 0: + m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK; + break; + case 1: + m = OMAP3430_L1FLATMEMONSTATE_MASK; + break; + case 2: + m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK; + break; + case 3: + m = OMAP3430_L2FLATMEMONSTATE_MASK; + break; + default: + WARN_ON(1); /* should never happen */ + return -EEXIST; + } + + prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), + pwrdm->prcm_offs, PM_PWSTCTRL); + + return 0; +} + +/** + * pwrdm_set_mem_retst - set memory power state while powerdomain in RET + * @pwrdm: struct powerdomain * to set + * @bank: memory bank number to set (0-3) + * @pwrst: one of the PWRDM_POWER_* macros + * + * Set the next power state that memory bank x of the powerdomain + * pwrdm will enter when the powerdomain enters the RETENTION state. + * Bank will be a number from 0 to 3, and represents different types + * of memory, depending on the powerdomain. pwrst will be either + * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain + * pointer is null or the target power state is not not supported for + * this memory bank, -EEXIST if the target memory bank does not exist + * or is not controllable, or returns 0 upon success. + */ +int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) +{ + u32 m; + + if (!pwrdm) + return -EINVAL; + + if (pwrdm->banks < (bank + 1)) + return -EEXIST; + + if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst))) + return -EINVAL; + + pr_debug("powerdomain: setting next memory powerstate for domain %s " + "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + switch (bank) { + case 0: + m = OMAP3430_SHAREDL1CACHEFLATRETSTATE; + break; + case 1: + m = OMAP3430_L1FLATMEMRETSTATE; + break; + case 2: + m = OMAP3430_SHAREDL2CACHEFLATRETSTATE; + break; + case 3: + m = OMAP3430_L2FLATMEMRETSTATE; + break; + default: + WARN_ON(1); /* should never happen */ + return -EEXIST; + } + + prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, + PM_PWSTCTRL); + + return 0; +} + +/** + * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state + * @pwrdm: struct powerdomain * to get current logic retention power state + * + * Return the current power state that the logic portion of + * powerdomain pwrdm will enter + * Returns -EINVAL if the powerdomain pointer is null or returns the + * current logic retention power state upon success. + */ +int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, + OMAP3430_LOGICSTATEST); +} + +/** + * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state + * @pwrdm: struct powerdomain * to get previous logic power state + * + * Return the powerdomain pwrdm's logic power state. Returns -EINVAL + * if the powerdomain pointer is null or returns the previous logic + * power state upon success. + */ +int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, + OMAP3430_LASTLOGICSTATEENTERED); +} + +/** + * pwrdm_read_mem_pwrst - get current memory bank power state + * @pwrdm: struct powerdomain * to get current memory bank power state + * @bank: memory bank number (0-3) + * + * Return the powerdomain pwrdm's current memory power state for bank + * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if + * the target memory bank does not exist or is not controllable, or + * returns the current memory power state upon success. + */ +int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) +{ + u32 m; + + if (!pwrdm) + return -EINVAL; + + if (pwrdm->banks < (bank + 1)) + return -EEXIST; + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + switch (bank) { + case 0: + m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK; + break; + case 1: + m = OMAP3430_L1FLATMEMSTATEST_MASK; + break; + case 2: + m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK; + break; + case 3: + m = OMAP3430_L2FLATMEMSTATEST_MASK; + break; + default: + WARN_ON(1); /* should never happen */ + return -EEXIST; + } + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m); +} + +/** + * pwrdm_read_prev_mem_pwrst - get previous memory bank power state + * @pwrdm: struct powerdomain * to get previous memory bank power state + * @bank: memory bank number (0-3) + * + * Return the powerdomain pwrdm's previous memory power state for bank + * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if + * the target memory bank does not exist or is not controllable, or + * returns the previous memory power state upon success. + */ +int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) +{ + u32 m; + + if (!pwrdm) + return -EINVAL; + + if (pwrdm->banks < (bank + 1)) + return -EEXIST; + + /* + * The register bit names below may not correspond to the + * actual names of the bits in each powerdomain's register, + * but the type of value returned is the same for each + * powerdomain. + */ + switch (bank) { + case 0: + m = OMAP3430_LASTMEM1STATEENTERED_MASK; + break; + case 1: + m = OMAP3430_LASTMEM2STATEENTERED_MASK; + break; + case 2: + m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; + break; + case 3: + m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; + break; + default: + WARN_ON(1); /* should never happen */ + return -EEXIST; + } + + return prm_read_mod_bits_shift(pwrdm->prcm_offs, + OMAP3430_PM_PREPWSTST, m); +} + +/** + * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm + * @pwrdm: struct powerdomain * to clear + * + * Clear the powerdomain's previous power state register. Clears the + * entire register, including logic and memory bank previous power states. + * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon + * success. + */ +int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) +{ + if (!pwrdm) + return -EINVAL; + + /* + * XXX should get the powerdomain's current state here; + * warn & fail if it is not ON. + */ + + pr_debug("powerdomain: clearing previous power state reg for %s\n", + pwrdm->name); + + prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); + + return 0; +} + +/** + * pwrdm_wait_transition - wait for powerdomain power transition to finish + * @pwrdm: struct powerdomain * to wait for + * + * If the powerdomain pwrdm is in the process of a state transition, + * spin until it completes the power transition, or until an iteration + * bailout value is reached. Returns -EINVAL if the powerdomain + * pointer is null, -EAGAIN if the bailout value was reached, or + * returns 0 upon success. + */ +int pwrdm_wait_transition(struct powerdomain *pwrdm) +{ + u32 c = 0; + + if (!pwrdm) + return -EINVAL; + + /* + * REVISIT: pwrdm_wait_transition() may be better implemented + * via a callback and a periodic timer check -- how long do we expect + * powerdomain transitions to take? + */ + + /* XXX Is this udelay() value meaningful? */ + while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) & + OMAP_INTRANSITION) && + (c++ < PWRDM_TRANSITION_BAILOUT)) + udelay(1); + + if (c >= PWRDM_TRANSITION_BAILOUT) { + printk(KERN_ERR "powerdomain: waited too long for " + "powerdomain %s to complete transition\n", pwrdm->name); + return -EAGAIN; + } + + pr_debug("powerdomain: completed transition in %d loops\n", c); + + return 0; +} + + diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index b917206ee90..e815fa35f7f 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -29,6 +29,18 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS || LEDS_OMAP_DEBUG +config OMAP_DEBUG_POWERDOMAIN + bool "Emit debug messages from powerdomain layer" + depends on ARCH_OMAP2 || ARCH_OMAP3 + default n + help + Say Y here if you want to compile in powerdomain layer + debugging messages for OMAP2/3. These messages can + provide more detail as to why some powerdomain calls + may be failing, and will also emit a descriptive message + for every powerdomain register write. However, the + extra detail costs some memory. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h new file mode 100644 index 00000000000..c8f52c6f8b7 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -0,0 +1,139 @@ +/* + * OMAP2/3 powerdomain control + * + * Copyright (C) 2007-8 Texas Instruments, Inc. + * Copyright (C) 2007-8 Nokia Corporation + * + * Written by Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ASM_ARM_ARCH_OMAP_POWERDOMAIN +#define ASM_ARM_ARCH_OMAP_POWERDOMAIN + +#include +#include + +#include + +#include + + +/* Powerdomain basic power states */ +#define PWRDM_POWER_OFF 0x0 +#define PWRDM_POWER_RET 0x1 +#define PWRDM_POWER_INACTIVE 0x2 +#define PWRDM_POWER_ON 0x3 + +/* Powerdomain allowable state bitfields */ +#define PWRSTS_OFF_ON ((1 << PWRDM_POWER_OFF) | \ + (1 << PWRDM_POWER_ON)) + +#define PWRSTS_OFF_RET ((1 << PWRDM_POWER_OFF) | \ + (1 << PWRDM_POWER_RET)) + +#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON)) + + +/* + * Number of memory banks that are power-controllable. On OMAP3430, the + * maximum is 4. + */ +#define PWRDM_MAX_MEM_BANKS 4 + +/* XXX A completely arbitrary number. What is reasonable here? */ +#define PWRDM_TRANSITION_BAILOUT 100000 + +struct powerdomain; + +/* Encodes dependencies between powerdomains - statically defined */ +struct pwrdm_dep { + + /* Powerdomain name */ + const char *pwrdm_name; + + /* Powerdomain pointer - resolved by the powerdomain code */ + struct powerdomain *pwrdm; + + /* Flags to mark OMAP chip restrictions, etc. */ + const struct omap_chip_id omap_chip; + +}; + +struct powerdomain { + + /* Powerdomain name */ + const char *name; + + /* the address offset from CM_BASE/PRM_BASE */ + const s16 prcm_offs; + + /* Used to represent the OMAP chip types containing this pwrdm */ + const struct omap_chip_id omap_chip; + + /* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */ + const u8 dep_bit; + + /* Powerdomains that can be told to wake this powerdomain up */ + struct pwrdm_dep *wkdep_srcs; + + /* Powerdomains that can be told to keep this pwrdm from inactivity */ + struct pwrdm_dep *sleepdep_srcs; + + /* Possible powerdomain power states */ + const u8 pwrsts; + + /* Possible logic power states when pwrdm in RETENTION */ + const u8 pwrsts_logic_ret; + + /* Number of software-controllable memory banks in this powerdomain */ + const u8 banks; + + /* Possible memory bank pwrstates when pwrdm in RETENTION */ + const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS]; + + /* Possible memory bank pwrstates when pwrdm is ON */ + const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; + + struct list_head node; + +}; + + +void pwrdm_init(struct powerdomain **pwrdm_list); + +int pwrdm_register(struct powerdomain *pwrdm); +int pwrdm_unregister(struct powerdomain *pwrdm); +struct powerdomain *pwrdm_lookup(const char *name); + +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); + +int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); +int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); +int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); +int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); +int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); +int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); + +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); + +int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); +int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); +int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm); +int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm); + +int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst); +int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); +int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); + +int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm); +int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm); +int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank); +int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank); + +int pwrdm_wait_transition(struct powerdomain *pwrdm); + +#endif -- GitLab From 9717100f77538bbee54d2b5c293fd829b252d2a6 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:40 +0300 Subject: [PATCH 0413/5416] ARM: OMAP2: Powerdomain: Add OMAP2/3 common powerdomains Add powerdomains common to both OMAP2 and OMAP3 (WKUP and GFX/SGX). Modify mach-omap2/io.c to initialize the powerdomain code on boot. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/io.c | 5 + arch/arm/mach-omap2/powerdomains.h | 147 +++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm.h | 3 +- 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-omap2/powerdomains.h diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 987351f07d7..5f73cf0bb7e 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -24,6 +24,10 @@ #include #include +#include + +#include "powerdomains.h" + extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); @@ -101,6 +105,7 @@ void __init omap2_map_common_io(void) void __init omap2_init_common_hw(void) { omap2_mux_init(); + pwrdm_init(powerdomains_omap); omap2_clk_init(); /* * Need to Fix this for 2430 diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h new file mode 100644 index 00000000000..1936df23559 --- /dev/null +++ b/arch/arm/mach-omap2/powerdomains.h @@ -0,0 +1,147 @@ +/* + * OMAP2/3 common powerdomain definitions + * + * Copyright (C) 2007-8 Texas Instruments, Inc. + * Copyright (C) 2007-8 Nokia Corporation + * + * Written by Paul Walmsley + * Debugging and integration fixes by Jouni Högander + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS + +/* + * This file contains all of the powerdomains that have some element + * of software control for the OMAP24xx and OMAP34XX chips. + * + * A few notes: + * + * This is not an exhaustive listing of powerdomains on the chips; only + * powerdomains that can be controlled in software. + * + * A useful validation rule for struct powerdomain: + * Any powerdomain referenced by a wkdep_srcs or sleepdep_srcs array + * must have a dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really + * just software-controllable dependencies. Non-software-controllable + * dependencies do exist, but they are not encoded below (yet). + * + * 24xx does not support programmable sleep dependencies (SLEEPDEP) + * + */ + +/* + * The names for the DSP/IVA2 powerdomains are confusing. + * + * Most OMAP chips have an on-board DSP. + * + * On the 2420, this is a 'C55 DSP called, simply, the DSP. Its + * powerdomain is called the "DSP power domain." On the 2430, the + * on-board DSP is a 'C64 DSP, now called the IVA2 or IVA2.1. Its + * powerdomain is still called the "DSP power domain." On the 3430, + * the DSP is a 'C64 DSP like the 2430, also known as the IVA2; but + * its powerdomain is now called the "IVA2 power domain." + * + * The 2420 also has something called the IVA, which is a separate ARM + * core, and has nothing to do with the DSP/IVA2. + * + * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM + * address offset is different between the C55 and C64 DSPs. + * + * The overly-specific dep_bit names are due to a bit name collision + * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift + * value are the same for all powerdomains: 2 + */ + +/* + * XXX should dep_bit be a mask, so we can test to see if it is 0 as a + * sanity check? + * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE + */ + +#include + +#include "prcm-common.h" +#include "prm.h" +#include "cm.h" + +/* OMAP2/3-common powerdomains and wakeup dependencies */ + +/* + * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP + * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE + * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE + */ +static struct pwrdm_dep gfx_sgx_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | + CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | + CHIP_IS_OMAP3430) + }, + { NULL }, +}; + +/* + * OMAP2/3 common powerdomains + */ + +/* XXX add sleepdeps for this powerdomain : 3430 */ + +/* + * The GFX powerdomain is not present on 3430ES2, but currently we do not + * have a macro to filter it out at compile-time. + */ +static struct powerdomain gfx_pwrdm = { + .name = "gfx_pwrdm", + .prcm_offs = GFX_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | + CHIP_IS_OMAP3430ES1), + .wkdep_srcs = gfx_sgx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +static struct powerdomain wkup_pwrdm = { + .name = "wkup_pwrdm", + .prcm_offs = WKUP_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), + .dep_bit = OMAP_EN_WKUP_SHIFT, +}; + + + +/* As powerdomains are added or removed above, this list must also be changed */ +static struct powerdomain *powerdomains_omap[] __initdata = { + + &gfx_pwrdm, + &wkup_pwrdm, + + NULL +}; + + +#endif diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index bbf41fc8e9a..eb9982fb21d 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -305,7 +305,8 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx) * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM, * PM_WKDEP_PER */ -#define OMAP_EN_WKUP (1 << 4) +#define OMAP_EN_WKUP_SHIFT 4 +#define OMAP_EN_WKUP_MASK (1 << 4) /* * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX, -- GitLab From fe6a58f8f50500a4c9a82da4a9bdae41c1500fa0 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:42 +0300 Subject: [PATCH 0414/5416] ARM: OMAP2: Powerdomain: Add OMAP2 powerdomains Add OMAP2-specific powerdomains. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomains.h | 14 ++ arch/arm/mach-omap2/powerdomains24xx.h | 200 +++++++++++++++++++++++++ arch/arm/mach-omap2/prm-regbits-24xx.h | 12 +- 3 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-omap2/powerdomains24xx.h diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h index 1936df23559..325e2ba0406 100644 --- a/arch/arm/mach-omap2/powerdomains.h +++ b/arch/arm/mach-omap2/powerdomains.h @@ -98,6 +98,10 @@ static struct pwrdm_dep gfx_sgx_wkdeps[] = { { NULL }, }; + +#include "powerdomains24xx.h" + + /* * OMAP2/3 common powerdomains */ @@ -140,6 +144,16 @@ static struct powerdomain *powerdomains_omap[] __initdata = { &gfx_pwrdm, &wkup_pwrdm, +#ifdef CONFIG_ARCH_OMAP24XX + &dsp_pwrdm, + &mpu_24xx_pwrdm, + &core_24xx_pwrdm, +#endif + +#ifdef CONFIG_ARCH_OMAP2430 + &mdm_pwrdm, +#endif + NULL }; diff --git a/arch/arm/mach-omap2/powerdomains24xx.h b/arch/arm/mach-omap2/powerdomains24xx.h new file mode 100644 index 00000000000..9f08dc3f7fd --- /dev/null +++ b/arch/arm/mach-omap2/powerdomains24xx.h @@ -0,0 +1,200 @@ +/* + * OMAP24XX powerdomain definitions + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2008 Nokia Corporation + * + * Written by Paul Walmsley + * Debugging and integration fixes by Jouni Högander + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX + +/* + * N.B. If powerdomains are added or removed from this file, update + * the array in mach-omap2/powerdomains.h. + */ + +#include + +#include "prcm-common.h" +#include "prm.h" +#include "prm-regbits-24xx.h" +#include "cm.h" +#include "cm-regbits-24xx.h" + +/* 24XX powerdomains and dependencies */ + +#ifdef CONFIG_ARCH_OMAP24XX + + +/* Wakeup dependency source arrays */ + +/* + * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP + * 2430 PM_WKDEP_MDM: same as above + */ +static struct pwrdm_dep dsp_mdm_24xx_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { NULL }, +}; + +/* + * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP + * 2430 adds MDM + */ +static struct pwrdm_dep mpu_24xx_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "dsp_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "mdm_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430) + }, + { NULL }, +}; + +/* + * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP + * 2430 adds MDM + */ +static struct pwrdm_dep core_24xx_wkdeps[] = { + { + .pwrdm_name = "dsp_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "gfx_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX) + }, + { + .pwrdm_name = "mdm_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430) + }, + { NULL }, +}; + + +/* Powerdomains */ + +static struct powerdomain dsp_pwrdm = { + .name = "dsp_pwrdm", + .prcm_offs = OMAP24XX_DSP_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), + .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT, + .wkdep_srcs = dsp_mdm_24xx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, + }, +}; + +static struct powerdomain mpu_24xx_pwrdm = { + .name = "mpu_pwrdm", + .prcm_offs = MPU_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), + .dep_bit = OMAP24XX_EN_MPU_SHIFT, + .wkdep_srcs = mpu_24xx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, + }, +}; + +static struct powerdomain core_24xx_pwrdm = { + .name = "core_pwrdm", + .prcm_offs = CORE_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), + .wkdep_srcs = core_24xx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .dep_bit = OMAP24XX_EN_CORE_SHIFT, + .banks = 3, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* MEM1RETSTATE */ + [1] = PWRSTS_OFF_RET, /* MEM2RETSTATE */ + [2] = PWRSTS_OFF_RET, /* MEM3RETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ + [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ + [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */ + }, +}; + +#endif /* CONFIG_ARCH_OMAP24XX */ + + + +/* + * 2430-specific powerdomains + */ + +#ifdef CONFIG_ARCH_OMAP2430 + +/* XXX 2430 KILLDOMAINWKUP bit? No current users apparently */ + +/* Another case of bit name collisions between several registers: EN_MDM */ +static struct powerdomain mdm_pwrdm = { + .name = "mdm_pwrdm", + .prcm_offs = OMAP2430_MDM_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT, + .wkdep_srcs = dsp_mdm_24xx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +#endif /* CONFIG_ARCH_OMAP2430 */ + + +#endif diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h index c6d17a3378e..4002051c20b 100644 --- a/arch/arm/mach-omap2/prm-regbits-24xx.h +++ b/arch/arm/mach-omap2/prm-regbits-24xx.h @@ -29,8 +29,10 @@ #define OMAP24XX_WKUP1_EN (1 << 0) /* PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_DSP, PM_WKDEP_MDM shared bits */ -#define OMAP24XX_EN_MPU (1 << 1) -#define OMAP24XX_EN_CORE (1 << 0) +#define OMAP24XX_EN_MPU_SHIFT 1 +#define OMAP24XX_EN_MPU_MASK (1 << 1) +#define OMAP24XX_EN_CORE_SHIFT 0 +#define OMAP24XX_EN_CORE_MASK (1 << 0) /* * PM_PWSTCTRL_MPU, PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM @@ -140,8 +142,10 @@ /* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" instead */ /* PM_WKDEP_MPU specific bits */ -#define OMAP2430_PM_WKDEP_MPU_EN_MDM (1 << 5) -#define OMAP24XX_PM_WKDEP_MPU_EN_DSP (1 << 2) +#define OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT 5 +#define OMAP2430_PM_WKDEP_MPU_EN_MDM_MASK (1 << 5) +#define OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT 2 +#define OMAP24XX_PM_WKDEP_MPU_EN_DSP_MASK (1 << 2) /* PM_EVGENCTRL_MPU specific bits */ -- GitLab From ecb24aa129c6d4b2152571f856320aa7dea41676 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:43 +0300 Subject: [PATCH 0415/5416] ARM: OMAP: Powerdomain: Add OMAP3 powerdomains Add OMAP3-specific powerdomains. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomains.h | 30 ++- arch/arm/mach-omap2/powerdomains34xx.h | 327 +++++++++++++++++++++++++ arch/arm/mach-omap2/prcm-common.h | 3 +- arch/arm/mach-omap2/prm-regbits-34xx.h | 11 +- 4 files changed, 364 insertions(+), 7 deletions(-) create mode 100644 arch/arm/mach-omap2/powerdomains34xx.h diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h index 325e2ba0406..1e151faebbd 100644 --- a/arch/arm/mach-omap2/powerdomains.h +++ b/arch/arm/mach-omap2/powerdomains.h @@ -98,16 +98,28 @@ static struct pwrdm_dep gfx_sgx_wkdeps[] = { { NULL }, }; +/* + * 3430: CM_SLEEPDEP_CAM: MPU + * 3430ES1: CM_SLEEPDEP_GFX: MPU + * 3430ES2: CM_SLEEPDEP_SGX: MPU + */ +static struct pwrdm_dep cam_gfx_sleepdeps[] = { + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + #include "powerdomains24xx.h" +#include "powerdomains34xx.h" /* * OMAP2/3 common powerdomains */ -/* XXX add sleepdeps for this powerdomain : 3430 */ - /* * The GFX powerdomain is not present on 3430ES2, but currently we do not * have a macro to filter it out at compile-time. @@ -118,6 +130,7 @@ static struct powerdomain gfx_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430ES1), .wkdep_srcs = gfx_sgx_wkdeps, + .sleepdep_srcs = cam_gfx_sleepdeps, .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRDM_POWER_RET, .banks = 1, @@ -154,6 +167,19 @@ static struct powerdomain *powerdomains_omap[] __initdata = { &mdm_pwrdm, #endif +#ifdef CONFIG_ARCH_OMAP34XX + &iva2_pwrdm, + &mpu_34xx_pwrdm, + &neon_pwrdm, + &core_34xx_pwrdm, + &cam_pwrdm, + &dss_pwrdm, + &per_pwrdm, + &emu_pwrdm, + &sgx_pwrdm, + &usbhost_pwrdm, +#endif + NULL }; diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h new file mode 100644 index 00000000000..f573f710839 --- /dev/null +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -0,0 +1,327 @@ +/* + * OMAP34XX powerdomain definitions + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2008 Nokia Corporation + * + * Written by Paul Walmsley + * Debugging and integration fixes by Jouni Högander + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX + +/* + * N.B. If powerdomains are added or removed from this file, update + * the array in mach-omap2/powerdomains.h. + */ + +#include + +#include "prcm-common.h" +#include "prm.h" +#include "prm-regbits-34xx.h" +#include "cm.h" +#include "cm-regbits-34xx.h" + +/* + * 34XX-specific powerdomains, dependencies + */ + +#ifdef CONFIG_ARCH_OMAP34XX + +/* + * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP + * (USBHOST is ES2 only) + */ +static struct pwrdm_dep per_usbhost_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + +/* + * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER + */ +static struct pwrdm_dep mpu_34xx_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "dss_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "per_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + +/* + * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER + */ +static struct pwrdm_dep iva2_wkdeps[] = { + { + .pwrdm_name = "core_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "dss_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "per_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + + +/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */ +static struct pwrdm_dep cam_dss_wkdeps[] = { + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + +/* 3430: PM_WKDEP_NEON: MPU */ +static struct pwrdm_dep neon_wkdeps[] = { + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + + +/* Sleep dependency source arrays for 34xx-specific pwrdms - 34XX only */ + +/* + * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA + * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA + */ +static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = { + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL }, +}; + + +/* + * Powerdomains + */ + +static struct powerdomain iva2_pwrdm = { + .name = "iva2_pwrdm", + .prcm_offs = OMAP3430_IVA2_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT, + .wkdep_srcs = iva2_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .banks = 4, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, + [1] = PWRSTS_OFF_RET, + [2] = PWRSTS_OFF_RET, + [3] = PWRSTS_OFF_RET, + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, + [1] = PWRDM_POWER_ON, + [2] = PWRSTS_OFF_ON, + [3] = PWRDM_POWER_ON, + }, +}; + +static struct powerdomain mpu_34xx_pwrdm = { + .name = "mpu_pwrdm", + .prcm_offs = MPU_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .dep_bit = OMAP3430_EN_MPU_SHIFT, + .wkdep_srcs = mpu_34xx_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, + }, + .pwrsts_mem_on = { + [0] = PWRSTS_OFF_ON, + }, +}; + +/* No wkdeps or sleepdeps for 34xx core apparently */ +static struct powerdomain core_34xx_pwrdm = { + .name = "core_pwrdm", + .prcm_offs = CORE_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .pwrsts = PWRSTS_OFF_RET_ON, + .dep_bit = OMAP3430_EN_CORE_SHIFT, + .banks = 2, + .pwrsts_mem_ret = { + [0] = PWRSTS_OFF_RET, /* MEM1RETSTATE */ + [1] = PWRSTS_OFF_RET, /* MEM2RETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ + [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ + }, +}; + +/* Another case of bit name collisions between several registers: EN_DSS */ +static struct powerdomain dss_pwrdm = { + .name = "dss_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .prcm_offs = OMAP3430_DSS_MOD, + .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT, + .wkdep_srcs = cam_dss_wkdeps, + .sleepdep_srcs = dss_per_usbhost_sleepdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +static struct powerdomain sgx_pwrdm = { + .name = "sgx_pwrdm", + .prcm_offs = OMAP3430ES2_SGX_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .wkdep_srcs = gfx_sgx_wkdeps, + .sleepdep_srcs = cam_gfx_sleepdeps, + /* XXX This is accurate for 3430 SGX, but what about GFX? */ + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +static struct powerdomain cam_pwrdm = { + .name = "cam_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .prcm_offs = OMAP3430_CAM_MOD, + .wkdep_srcs = cam_dss_wkdeps, + .sleepdep_srcs = cam_gfx_sleepdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +static struct powerdomain per_pwrdm = { + .name = "per_pwrdm", + .prcm_offs = OMAP3430_PER_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .dep_bit = OMAP3430_EN_PER_SHIFT, + .wkdep_srcs = per_usbhost_wkdeps, + .sleepdep_srcs = dss_per_usbhost_sleepdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_OFF_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +static struct powerdomain emu_pwrdm = { + .name = "emu_pwrdm", + .prcm_offs = OMAP3430_EMU_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct powerdomain neon_pwrdm = { + .name = "neon_pwrdm", + .prcm_offs = OMAP3430_NEON_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .wkdep_srcs = neon_wkdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, +}; + +static struct powerdomain usbhost_pwrdm = { + .name = "usbhost_pwrdm", + .prcm_offs = OMAP3430ES2_USBHOST_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .wkdep_srcs = per_usbhost_wkdeps, + .sleepdep_srcs = dss_per_usbhost_sleepdeps, + .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRDM_POWER_RET, + .banks = 1, + .pwrsts_mem_ret = { + [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + }, + .pwrsts_mem_on = { + [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + }, +}; + +#endif /* CONFIG_ARCH_OMAP34XX */ + + +#endif diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 54c32f48213..4a32822ff3f 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -312,7 +312,8 @@ #define OMAP3430_ST_GPT2 (1 << 3) /* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */ -#define OMAP3430_EN_CORE (1 << 0) +#define OMAP3430_EN_CORE_SHIFT 0 +#define OMAP3430_EN_CORE_MASK (1 << 0) #endif diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index b4686bc345c..5b5ecfe6c99 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h @@ -68,7 +68,8 @@ #define OMAP3430_VPINIDLE (1 << 0) /* PM_WKDEP_IVA2, PM_WKDEP_MPU shared bits */ -#define OMAP3430_EN_PER (1 << 7) +#define OMAP3430_EN_PER_SHIFT 7 +#define OMAP3430_EN_PER_MASK (1 << 7) /* PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE shared bits */ #define OMAP3430_MEMORYCHANGE (1 << 3) @@ -77,7 +78,7 @@ #define OMAP3430_LOGICSTATEST (1 << 2) /* PM_PREPWSTST_IVA2, PM_PREPWSTST_CORE shared bits */ -#define OMAP3430_LASTLOGICSTATEENTERED (1 << 2) +#define OMAP3430_LASTLOGICSTATEENTERED (1 << 2) /* * PM_PREPWSTST_IVA2, PM_PREPWSTST_MPU, PM_PREPWSTST_CORE, @@ -278,8 +279,10 @@ #define OMAP3430_EMULATION_MPU_RST (1 << 11) /* PM_WKDEP_MPU specific bits */ -#define OMAP3430_PM_WKDEP_MPU_EN_DSS (1 << 5) -#define OMAP3430_PM_WKDEP_MPU_EN_IVA2 (1 << 2) +#define OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT 5 +#define OMAP3430_PM_WKDEP_MPU_EN_DSS_MASK (1 << 5) +#define OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT 2 +#define OMAP3430_PM_WKDEP_MPU_EN_IVA2_MASK (1 << 2) /* PM_EVGENCTRL_MPU */ #define OMAP3430_OFFLOADMODE_SHIFT 3 -- GitLab From d459bfe01f523983a822de8c2d3fe0bd2f2c194e Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:43 +0300 Subject: [PATCH 0416/5416] ARM: OMAP2: Clockdomain: Add base OMAP2/3 clockdomain code This patch creates an interface to the clockdomain registers in the PRM/CM modules on OMAP2/3. This interface is intended to be used by PM code, e.g., pm.c; not by device drivers directly. The patch also adds clockdomain usecount tracking. This is intended to be called whenever the first clock in a clockdomain is enabled, or when the last enabled clock in a clockdomain is disabled. If the clockdomain is in software-supervised mode, the code will force-wakeup or force-sleep the clockdomain. If the clockdomain is in hardware-supervised mode, the first clock enable will add sleep and wakeup dependencies on a user-selectable set of parent domains (usually MPU & IVA2), and the disable will remove them. Each clockdomain will be defined in later patches as static structures. The clockdomain structures are linked into a list at boot by clkdm_register(), similar to the OMAP clock code. The patch adds a Kconfig option, CONFIG_OMAP_DEBUG_CLOCKDOMAIN, which when enabled will emit verbose debug messages via pr_debug(). Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 3 +- arch/arm/mach-omap2/clockdomain.c | 603 ++++++++++++++++++ arch/arm/plat-omap/Kconfig | 12 + arch/arm/plat-omap/include/mach/clockdomain.h | 106 +++ 4 files changed, 723 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-omap2/clockdomain.c create mode 100644 arch/arm/plat-omap/include/mach/clockdomain.h diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 1001d42048e..e7cf1b4357c 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,8 @@ # Common support obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \ - devices.o serial.o gpmc.o timer-gp.o powerdomain.o + devices.o serial.o gpmc.o timer-gp.o powerdomain.o \ + clockdomain.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c new file mode 100644 index 00000000000..f867d8f1d0e --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain.c @@ -0,0 +1,603 @@ +/* + * OMAP2/3 clockdomain framework functions + * + * Copyright (C) 2008 Texas Instruments, Inc. + * Copyright (C) 2008 Nokia Corporation + * + * Written by Paul Walmsley and Jouni Högander + * + * 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. + */ +#ifdef CONFIG_OMAP_DEBUG_CLOCKDOMAIN +# define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "prm.h" +#include "prm-regbits-24xx.h" +#include "cm.h" + +#include +#include + +/* clkdm_list contains all registered struct clockdomains */ +static LIST_HEAD(clkdm_list); + +/* clkdm_mutex protects clkdm_list add and del ops */ +static DEFINE_MUTEX(clkdm_mutex); + +/* array of powerdomain deps to be added/removed when clkdm in hwsup mode */ +static struct clkdm_pwrdm_autodep *autodeps; + + +/* Private functions */ + +/* + * _autodep_lookup - resolve autodep pwrdm names to pwrdm pointers; store + * @autodep: struct clkdm_pwrdm_autodep * to resolve + * + * Resolve autodep powerdomain names to powerdomain pointers via + * pwrdm_lookup() and store the pointers in the autodep structure. An + * "autodep" is a powerdomain sleep/wakeup dependency that is + * automatically added and removed whenever clocks in the associated + * clockdomain are enabled or disabled (respectively) when the + * clockdomain is in hardware-supervised mode. Meant to be called + * once at clockdomain layer initialization, since these should remain + * fixed for a particular architecture. No return value. + */ +static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep) +{ + struct powerdomain *pwrdm; + + if (!autodep) + return; + + if (!omap_chip_is(autodep->omap_chip)) + return; + + pwrdm = pwrdm_lookup(autodep->pwrdm_name); + if (!pwrdm) { + pr_debug("clockdomain: _autodep_lookup: powerdomain %s " + "does not exist\n", autodep->pwrdm_name); + WARN_ON(1); + return; + } + autodep->pwrdm = pwrdm; + + return; +} + +/* + * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable + * @clkdm: struct clockdomain * + * + * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' + * in hardware-supervised mode. Meant to be called from clock framework + * when a clock inside clockdomain 'clkdm' is enabled. No return value. + */ +static void _clkdm_add_autodeps(struct clockdomain *clkdm) +{ + struct clkdm_pwrdm_autodep *autodep; + + for (autodep = autodeps; autodep->pwrdm_name; autodep++) { + if (!autodep->pwrdm) + continue; + + pr_debug("clockdomain: adding %s sleepdep/wkdep for " + "pwrdm %s\n", autodep->pwrdm_name, + clkdm->pwrdm->name); + + pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm); + pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm); + } +} + +/* + * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm + * @clkdm: struct clockdomain * + * + * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' + * in hardware-supervised mode. Meant to be called from clock framework + * when a clock inside clockdomain 'clkdm' is disabled. No return value. + */ +static void _clkdm_del_autodeps(struct clockdomain *clkdm) +{ + struct clkdm_pwrdm_autodep *autodep; + + for (autodep = autodeps; autodep->pwrdm_name; autodep++) { + if (!autodep->pwrdm) + continue; + + pr_debug("clockdomain: removing %s sleepdep/wkdep for " + "pwrdm %s\n", autodep->pwrdm_name, + clkdm->pwrdm->name); + + pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm); + pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm); + } +} + + +static struct clockdomain *_clkdm_lookup(const char *name) +{ + struct clockdomain *clkdm, *temp_clkdm; + + if (!name) + return NULL; + + clkdm = NULL; + + list_for_each_entry(temp_clkdm, &clkdm_list, node) { + if (!strcmp(name, temp_clkdm->name)) { + clkdm = temp_clkdm; + break; + } + } + + return clkdm; +} + + +/* Public functions */ + +/** + * clkdm_init - set up the clockdomain layer + * @clkdms: optional pointer to an array of clockdomains to register + * @init_autodeps: optional pointer to an array of autodeps to register + * + * Set up internal state. If a pointer to an array of clockdomains + * was supplied, loop through the list of clockdomains, register all + * that are available on the current platform. Similarly, if a + * pointer to an array of clockdomain-powerdomain autodependencies was + * provided, register those. No return value. + */ +void clkdm_init(struct clockdomain **clkdms, + struct clkdm_pwrdm_autodep *init_autodeps) +{ + struct clockdomain **c = NULL; + struct clkdm_pwrdm_autodep *autodep = NULL; + + if (clkdms) + for (c = clkdms; *c; c++) + clkdm_register(*c); + + autodeps = init_autodeps; + if (autodeps) + for (autodep = autodeps; autodep->pwrdm_name; autodep++) + _autodep_lookup(autodep); +} + +/** + * clkdm_register - register a clockdomain + * @clkdm: struct clockdomain * to register + * + * Adds a clockdomain to the internal clockdomain list. + * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is + * already registered by the provided name, or 0 upon success. + */ +int clkdm_register(struct clockdomain *clkdm) +{ + int ret = -EINVAL; + struct powerdomain *pwrdm; + + if (!clkdm || !clkdm->name) + return -EINVAL; + + if (!omap_chip_is(clkdm->omap_chip)) + return -EINVAL; + + pwrdm = pwrdm_lookup(clkdm->pwrdm_name); + if (!pwrdm) { + pr_debug("clockdomain: clkdm_register %s: powerdomain %s " + "does not exist\n", clkdm->name, clkdm->pwrdm_name); + return -EINVAL; + } + clkdm->pwrdm = pwrdm; + + mutex_lock(&clkdm_mutex); + /* Verify that the clockdomain is not already registered */ + if (_clkdm_lookup(clkdm->name)) { + ret = -EEXIST; + goto cr_unlock; + }; + + list_add(&clkdm->node, &clkdm_list); + + pr_debug("clockdomain: registered %s\n", clkdm->name); + ret = 0; + +cr_unlock: + mutex_unlock(&clkdm_mutex); + + return ret; +} + +/** + * clkdm_unregister - unregister a clockdomain + * @clkdm: struct clockdomain * to unregister + * + * Removes a clockdomain from the internal clockdomain list. Returns + * -EINVAL if clkdm argument is NULL. + */ +int clkdm_unregister(struct clockdomain *clkdm) +{ + if (!clkdm) + return -EINVAL; + + mutex_lock(&clkdm_mutex); + list_del(&clkdm->node); + mutex_unlock(&clkdm_mutex); + + pr_debug("clockdomain: unregistered %s\n", clkdm->name); + + return 0; +} + +/** + * clkdm_lookup - look up a clockdomain by name, return a pointer + * @name: name of clockdomain + * + * Find a registered clockdomain by its name. Returns a pointer to the + * struct clockdomain if found, or NULL otherwise. + */ +struct clockdomain *clkdm_lookup(const char *name) +{ + struct clockdomain *clkdm, *temp_clkdm; + + if (!name) + return NULL; + + clkdm = NULL; + + mutex_lock(&clkdm_mutex); + list_for_each_entry(temp_clkdm, &clkdm_list, node) { + if (!strcmp(name, temp_clkdm->name)) { + clkdm = temp_clkdm; + break; + } + } + mutex_unlock(&clkdm_mutex); + + return clkdm; +} + +/** + * clkdm_for_each - call function on each registered clockdomain + * @fn: callback function * + * + * Call the supplied function for each registered clockdomain. + * The callback function can return anything but 0 to bail + * out early from the iterator. The callback function is called with + * the clkdm_mutex held, so no clockdomain structure manipulation + * functions should be called from the callback, although hardware + * clockdomain control functions are fine. Returns the last return + * value of the callback function, which should be 0 for success or + * anything else to indicate failure; or -EINVAL if the function pointer + * is null. + */ +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) +{ + struct clockdomain *clkdm; + int ret = 0; + + if (!fn) + return -EINVAL; + + mutex_lock(&clkdm_mutex); + list_for_each_entry(clkdm, &clkdm_list, node) { + ret = (*fn)(clkdm); + if (ret) + break; + } + mutex_unlock(&clkdm_mutex); + + return ret; +} + + +/* Hardware clockdomain control */ + +/** + * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode + * @clk: struct clk * of a clockdomain + * + * Return the clockdomain's current state transition mode from the + * corresponding domain CM_CLKSTCTRL register. Returns -EINVAL if clk + * is NULL or the current mode upon success. + */ +static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm) +{ + u32 v; + + if (!clkdm) + return -EINVAL; + + v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + v &= clkdm->clktrctrl_mask; + v >>= __ffs(clkdm->clktrctrl_mask); + + return v; +} + +/** + * omap2_clkdm_sleep - force clockdomain sleep transition + * @clkdm: struct clockdomain * + * + * Instruct the CM to force a sleep transition on the specified + * clockdomain 'clkdm'. Returns -EINVAL if clk is NULL or if + * clockdomain does not support software-initiated sleep; 0 upon + * success. + */ +int omap2_clkdm_sleep(struct clockdomain *clkdm) +{ + if (!clkdm) + return -EINVAL; + + if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { + pr_debug("clockdomain: %s does not support forcing " + "sleep via software\n", clkdm->name); + return -EINVAL; + } + + pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); + + if (cpu_is_omap24xx()) { + + cm_set_mod_reg_bits(OMAP24XX_FORCESTATE, + clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); + + } else if (cpu_is_omap34xx()) { + + u32 v = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP << + __ffs(clkdm->clktrctrl_mask)); + + cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, + clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + + } else { + BUG(); + }; + + return 0; +} + +/** + * omap2_clkdm_wakeup - force clockdomain wakeup transition + * @clkdm: struct clockdomain * + * + * Instruct the CM to force a wakeup transition on the specified + * clockdomain 'clkdm'. Returns -EINVAL if clkdm is NULL or if the + * clockdomain does not support software-controlled wakeup; 0 upon + * success. + */ +int omap2_clkdm_wakeup(struct clockdomain *clkdm) +{ + if (!clkdm) + return -EINVAL; + + if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) { + pr_debug("clockdomain: %s does not support forcing " + "wakeup via software\n", clkdm->name); + return -EINVAL; + } + + pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); + + if (cpu_is_omap24xx()) { + + cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE, + clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); + + } else if (cpu_is_omap34xx()) { + + u32 v = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP << + __ffs(clkdm->clktrctrl_mask)); + + cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, + clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + + } else { + BUG(); + }; + + return 0; +} + +/** + * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm + * @clkdm: struct clockdomain * + * + * Allow the hardware to automatically switch the clockdomain into + * active or idle states, as needed by downstream clocks. If the + * clockdomain has any downstream clocks enabled in the clock + * framework, wkdep/sleepdep autodependencies are added; this is so + * device drivers can read and write to the device. No return value. + */ +void omap2_clkdm_allow_idle(struct clockdomain *clkdm) +{ + u32 v; + + if (!clkdm) + return; + + if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) { + pr_debug("clock: automatic idle transitions cannot be enabled " + "on clockdomain %s\n", clkdm->name); + return; + } + + pr_debug("clockdomain: enabling automatic idle transitions for %s\n", + clkdm->name); + + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_add_autodeps(clkdm); + + if (cpu_is_omap24xx()) + v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; + else if (cpu_is_omap34xx()) + v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; + else + BUG(); + + + cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, + v << __ffs(clkdm->clktrctrl_mask), + clkdm->pwrdm->prcm_offs, + CM_CLKSTCTRL); +} + +/** + * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm + * @clkdm: struct clockdomain * + * + * Prevent the hardware from automatically switching the clockdomain + * into inactive or idle states. If the clockdomain has downstream + * clocks enabled in the clock framework, wkdep/sleepdep + * autodependencies are removed. No return value. + */ +void omap2_clkdm_deny_idle(struct clockdomain *clkdm) +{ + u32 v; + + if (!clkdm) + return; + + if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) { + pr_debug("clockdomain: automatic idle transitions cannot be " + "disabled on %s\n", clkdm->name); + return; + } + + pr_debug("clockdomain: disabling automatic idle transitions for %s\n", + clkdm->name); + + if (cpu_is_omap24xx()) + v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; + else if (cpu_is_omap34xx()) + v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; + else + BUG(); + + cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, + v << __ffs(clkdm->clktrctrl_mask), + clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_del_autodeps(clkdm); +} + + +/* Clockdomain-to-clock framework interface code */ + +/** + * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm + * @clkdm: struct clockdomain * + * @clk: struct clk * of the enabled downstream clock + * + * Increment the usecount of this clockdomain 'clkdm' and ensure that + * it is awake. Intended to be called by clk_enable() code. If the + * clockdomain is in software-supervised idle mode, force the + * clockdomain to wake. If the clockdomain is in hardware-supervised + * idle mode, add clkdm-pwrdm autodependencies, to ensure that devices + * in the clockdomain can be read from/written to by on-chip processors. + * Returns -EINVAL if passed null pointers; returns 0 upon success or + * if the clockdomain is in hwsup idle mode. + */ +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) +{ + int v; + + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream clocks for debugging purposes? + */ + + if (!clkdm || !clk) + return -EINVAL; + + if (atomic_inc_return(&clkdm->usecount) > 1) + return 0; + + /* Clockdomain now has one enabled downstream clock */ + + pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, + clk->name); + + v = omap2_clkdm_clktrctrl_read(clkdm); + + if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || + (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + _clkdm_add_autodeps(clkdm); + else + omap2_clkdm_wakeup(clkdm); + + return 0; +} + +/** + * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm + * @clkdm: struct clockdomain * + * @clk: struct clk * of the disabled downstream clock + * + * Decrement the usecount of this clockdomain 'clkdm'. Intended to be + * called by clk_disable() code. If the usecount goes to 0, put the + * clockdomain to sleep (software-supervised mode) or remove the + * clkdm-pwrdm autodependencies (hardware-supervised mode). Returns + * -EINVAL if passed null pointers; -ERANGE if the clkdm usecount + * underflows and debugging is enabled; or returns 0 upon success or + * if the clockdomain is in hwsup idle mode. + */ +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) +{ + int v; + + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream clocks for debugging purposes? + */ + + if (!clkdm || !clk) + return -EINVAL; + +#ifdef DEBUG + if (atomic_read(&clkdm->usecount) == 0) { + WARN_ON(1); /* underflow */ + return -ERANGE; + } +#endif + + if (atomic_dec_return(&clkdm->usecount) > 0) + return 0; + + /* All downstream clocks of this clockdomain are now disabled */ + + pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, + clk->name); + + v = omap2_clkdm_clktrctrl_read(clkdm); + + if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || + (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + _clkdm_del_autodeps(clkdm); + else + omap2_clkdm_sleep(clkdm); + + return 0; +} + diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index e815fa35f7f..ef62bf21e17 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -41,6 +41,18 @@ config OMAP_DEBUG_POWERDOMAIN for every powerdomain register write. However, the extra detail costs some memory. +config OMAP_DEBUG_CLOCKDOMAIN + bool "Emit debug messages from clockdomain layer" + depends on ARCH_OMAP2 || ARCH_OMAP3 + default n + help + Say Y here if you want to compile in clockdomain layer + debugging messages for OMAP2/3. These messages can + provide more detail as to why some clockdomain calls + may be failing, and will also emit a descriptive message + for every clockdomain register write. However, the + extra detail costs some memory. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h new file mode 100644 index 00000000000..1f51f017378 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/clockdomain.h @@ -0,0 +1,106 @@ +/* + * linux/include/asm-arm/arch-omap/clockdomain.h + * + * OMAP2/3 clockdomain framework functions + * + * Copyright (C) 2008 Texas Instruments, Inc. + * Copyright (C) 2008 Nokia Corporation + * + * Written by Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H +#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H + +#include +#include +#include + +/* Clockdomain capability flags */ +#define CLKDM_CAN_FORCE_SLEEP (1 << 0) +#define CLKDM_CAN_FORCE_WAKEUP (1 << 1) +#define CLKDM_CAN_ENABLE_AUTO (1 << 2) +#define CLKDM_CAN_DISABLE_AUTO (1 << 3) + +#define CLKDM_CAN_HWSUP (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO) +#define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) +#define CLKDM_CAN_HWSUP_SWSUP (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP) + +/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */ +#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO 0x0 +#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO 0x1 + +/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */ +#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO 0x0 +#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP 0x1 +#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP 0x2 +#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO 0x3 + +/* + * struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps + * and sleepdeps added when a powerdomain should stay active in hwsup mode; + * and conversely, removed when the powerdomain should be allowed to go + * inactive in hwsup mode. + */ +struct clkdm_pwrdm_autodep { + + /* Name of the powerdomain to add a wkdep/sleepdep on */ + const char *pwrdm_name; + + /* Powerdomain pointer (looked up at clkdm_init() time) */ + struct powerdomain *pwrdm; + + /* OMAP chip types that this clockdomain dep is valid on */ + const struct omap_chip_id omap_chip; + +}; + +struct clockdomain { + + /* Clockdomain name */ + const char *name; + + /* Powerdomain enclosing this clockdomain */ + const char *pwrdm_name; + + /* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */ + const u16 clktrctrl_mask; + + /* Clockdomain capability flags */ + const u8 flags; + + /* OMAP chip types that this clockdomain is valid on */ + const struct omap_chip_id omap_chip; + + /* Usecount tracking */ + atomic_t usecount; + + /* Powerdomain pointer assigned at clkdm_register() */ + struct powerdomain *pwrdm; + + struct list_head node; + +}; + +void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps); +int clkdm_register(struct clockdomain *clkdm); +int clkdm_unregister(struct clockdomain *clkdm); +struct clockdomain *clkdm_lookup(const char *name); + +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)); +struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); + +void omap2_clkdm_allow_idle(struct clockdomain *clkdm); +void omap2_clkdm_deny_idle(struct clockdomain *clkdm); + +int omap2_clkdm_wakeup(struct clockdomain *clkdm); +int omap2_clkdm_sleep(struct clockdomain *clkdm); + +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); + +#endif -- GitLab From 8420bb13630032097be911a039cb64b5f62c01da Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:44 +0300 Subject: [PATCH 0417/5416] ARM: OMAP2: Clockdomain: Connect clockdomain code to powerdomain code Thie patch adds code to the powerdomain layer to track the clockdomains associated with each powerdomain. It also modifies the clockdomain code to register clockdomains with their corresponding powerdomain when the clockdomain is registered. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clockdomain.c | 4 + arch/arm/mach-omap2/powerdomain.c | 136 ++++++++++++++++++ arch/arm/plat-omap/include/mach/powerdomain.h | 16 +++ 3 files changed, 156 insertions(+) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index f867d8f1d0e..b6ff5aa4726 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -219,6 +219,8 @@ int clkdm_register(struct clockdomain *clkdm) list_add(&clkdm->node, &clkdm_list); + pwrdm_add_clkdm(pwrdm, clkdm); + pr_debug("clockdomain: registered %s\n", clkdm->name); ret = 0; @@ -240,6 +242,8 @@ int clkdm_unregister(struct clockdomain *clkdm) if (!clkdm) return -EINVAL; + pwrdm_del_clkdm(clkdm->pwrdm, clkdm); + mutex_lock(&clkdm_mutex); list_del(&clkdm->node); mutex_unlock(&clkdm_mutex); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 1ec003832ef..9a803492b28 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -33,6 +33,7 @@ #include #include +#include /* pwrdm_list contains all registered struct powerdomains */ static LIST_HEAD(pwrdm_list); @@ -236,6 +237,141 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) return ret; } +/** + * pwrdm_add_clkdm - add a clockdomain to a powerdomain + * @pwrdm: struct powerdomain * to add the clockdomain to + * @clkdm: struct clockdomain * to associate with a powerdomain + * + * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'. This + * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if + * presented with invalid pointers; -ENOMEM if memory could not be allocated; + * or 0 upon success. + */ +int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) +{ + unsigned long flags; + int i; + int ret = -EINVAL; + + if (!pwrdm || !clkdm) + return -EINVAL; + + pr_debug("powerdomain: associating clockdomain %s with powerdomain " + "%s\n", clkdm->name, pwrdm->name); + + write_lock_irqsave(&pwrdm_rwlock, flags); + + for (i = 0; i < PWRDM_MAX_CLKDMS; i++) { + if (!pwrdm->pwrdm_clkdms[i]) + break; +#ifdef DEBUG + if (pwrdm->pwrdm_clkdms[i] == clkdm) { + ret = -EINVAL; + goto pac_exit; + } +#endif + } + + if (i == PWRDM_MAX_CLKDMS) { + pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for " + "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name); + WARN_ON(1); + ret = -ENOMEM; + goto pac_exit; + } + + pwrdm->pwrdm_clkdms[i] = clkdm; + + ret = 0; + +pac_exit: + write_unlock_irqrestore(&pwrdm_rwlock, flags); + + return ret; +} + +/** + * pwrdm_del_clkdm - remove a clockdomain from a powerdomain + * @pwrdm: struct powerdomain * to add the clockdomain to + * @clkdm: struct clockdomain * to associate with a powerdomain + * + * Dissociate the clockdomain 'clkdm' from the powerdomain + * 'pwrdm'. Returns -EINVAL if presented with invalid pointers; + * -ENOENT if the clkdm was not associated with the powerdomain, or 0 + * upon success. + */ +int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) +{ + unsigned long flags; + int ret = -EINVAL; + int i; + + if (!pwrdm || !clkdm) + return -EINVAL; + + pr_debug("powerdomain: dissociating clockdomain %s from powerdomain " + "%s\n", clkdm->name, pwrdm->name); + + write_lock_irqsave(&pwrdm_rwlock, flags); + + for (i = 0; i < PWRDM_MAX_CLKDMS; i++) + if (pwrdm->pwrdm_clkdms[i] == clkdm) + break; + + if (i == PWRDM_MAX_CLKDMS) { + pr_debug("powerdomain: clkdm %s not associated with pwrdm " + "%s ?!\n", clkdm->name, pwrdm->name); + ret = -ENOENT; + goto pdc_exit; + } + + pwrdm->pwrdm_clkdms[i] = NULL; + + ret = 0; + +pdc_exit: + write_unlock_irqrestore(&pwrdm_rwlock, flags); + + return ret; +} + +/** + * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm + * @pwrdm: struct powerdomain * to iterate over + * @fn: callback function * + * + * Call the supplied function for each clockdomain in the powerdomain + * 'pwrdm'. The callback function can return anything but 0 to bail + * out early from the iterator. The callback function is called with + * the pwrdm_rwlock held for reading, so no powerdomain structure + * manipulation functions should be called from the callback, although + * hardware powerdomain control functions are fine. Returns -EINVAL + * if presented with invalid pointers; or passes along the last return + * value of the callback function, which should be 0 for success or + * anything else to indicate failure. + */ +int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, + int (*fn)(struct powerdomain *pwrdm, + struct clockdomain *clkdm)) +{ + unsigned long flags; + int ret = 0; + int i; + + if (!fn) + return -EINVAL; + + read_lock_irqsave(&pwrdm_rwlock, flags); + + for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++) + ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]); + + read_unlock_irqrestore(&pwrdm_rwlock, flags); + + return ret; +} + + /** * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1 * @pwrdm1: wake this struct powerdomain * up (dependent) diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index c8f52c6f8b7..5fa666fa9be 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -44,9 +44,16 @@ */ #define PWRDM_MAX_MEM_BANKS 4 +/* + * Maximum number of clockdomains that can be associated with a powerdomain. + * CORE powerdomain is probably the worst case. + */ +#define PWRDM_MAX_CLKDMS 3 + /* XXX A completely arbitrary number. What is reasonable here? */ #define PWRDM_TRANSITION_BAILOUT 100000 +struct clockdomain; struct powerdomain; /* Encodes dependencies between powerdomains - statically defined */ @@ -98,6 +105,9 @@ struct powerdomain { /* Possible memory bank pwrstates when pwrdm is ON */ const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; + /* Clockdomains in this powerdomain */ + struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; + struct list_head node; }; @@ -111,6 +121,12 @@ struct powerdomain *pwrdm_lookup(const char *name); int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); +int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); +int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); +int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, + int (*fn)(struct powerdomain *pwrdm, + struct clockdomain *clkdm)); + int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2); -- GitLab From 801954d3debb87af9fa7f9187cb1100175d76ac7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:44 +0300 Subject: [PATCH 0418/5416] ARM: OMAP2: Clockdomain: Encode OMAP2/3 clockdomains Add clockdomain definitions for OMAP24xx and OMAP34xx chips. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clockdomains.h | 298 ++++++++++++++++++++++++++ arch/arm/mach-omap2/cm-regbits-24xx.h | 24 ++- arch/arm/mach-omap2/cm-regbits-34xx.h | 42 +++- arch/arm/mach-omap2/io.c | 4 + 4 files changed, 349 insertions(+), 19 deletions(-) create mode 100644 arch/arm/mach-omap2/clockdomains.h diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h new file mode 100644 index 00000000000..a2763203713 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomains.h @@ -0,0 +1,298 @@ +/* + * OMAP2/3 clockdomains + * + * Copyright (C) 2008 Texas Instruments, Inc. + * Copyright (C) 2008 Nokia Corporation + * + * Written by Paul Walmsley + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H +#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H + +#include + +/* + * OMAP2/3-common clockdomains + */ + +/* This is an implicit clockdomain - it is never defined as such in TRM */ +static struct clockdomain wkup_clkdm = { + .name = "wkup_clkdm", + .pwrdm_name = "wkup_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), +}; + +/* + * 2420-only clockdomains + */ + +#if defined(CONFIG_ARCH_OMAP2420) + +static struct clockdomain mpu_2420_clkdm = { + .name = "mpu_clkdm", + .pwrdm_name = "mpu_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), +}; + +static struct clockdomain iva1_2420_clkdm = { + .name = "iva1_clkdm", + .pwrdm_name = "dsp_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), +}; + +#endif /* CONFIG_ARCH_OMAP2420 */ + + +/* + * 2430-only clockdomains + */ + +#if defined(CONFIG_ARCH_OMAP2430) + +static struct clockdomain mpu_2430_clkdm = { + .name = "mpu_clkdm", + .pwrdm_name = "mpu_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), +}; + +static struct clockdomain mdm_clkdm = { + .name = "mdm_clkdm", + .pwrdm_name = "mdm_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), +}; + +#endif /* CONFIG_ARCH_OMAP2430 */ + + +/* + * 24XX-only clockdomains + */ + +#if defined(CONFIG_ARCH_OMAP24XX) + +static struct clockdomain dsp_clkdm = { + .name = "dsp_clkdm", + .pwrdm_name = "dsp_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), +}; + +static struct clockdomain gfx_24xx_clkdm = { + .name = "gfx_clkdm", + .pwrdm_name = "gfx_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), +}; + +static struct clockdomain core_l3_24xx_clkdm = { + .name = "core_l3_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), +}; + +static struct clockdomain core_l4_24xx_clkdm = { + .name = "core_l4_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), +}; + +static struct clockdomain dss_24xx_clkdm = { + .name = "dss_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), +}; + +#endif /* CONFIG_ARCH_OMAP24XX */ + + +/* + * 34xx clockdomains + */ + +#if defined(CONFIG_ARCH_OMAP34XX) + +static struct clockdomain mpu_34xx_clkdm = { + .name = "mpu_clkdm", + .pwrdm_name = "mpu_pwrdm", + .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain neon_clkdm = { + .name = "neon_clkdm", + .pwrdm_name = "neon_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain iva2_clkdm = { + .name = "iva2_clkdm", + .pwrdm_name = "iva2_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain gfx_3430es1_clkdm = { + .name = "gfx_clkdm", + .pwrdm_name = "gfx_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1), +}; + +static struct clockdomain sgx_clkdm = { + .name = "sgx_clkdm", + .pwrdm_name = "sgx_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), +}; + +static struct clockdomain d2d_clkdm = { + .name = "d2d_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1), +}; + +static struct clockdomain core_l3_34xx_clkdm = { + .name = "core_l3_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain core_l4_34xx_clkdm = { + .name = "core_l4_clkdm", + .pwrdm_name = "core_pwrdm", + .flags = CLKDM_CAN_HWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain dss_34xx_clkdm = { + .name = "dss_clkdm", + .pwrdm_name = "dss_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain cam_clkdm = { + .name = "cam_clkdm", + .pwrdm_name = "cam_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain usbhost_clkdm = { + .name = "usbhost_clkdm", + .pwrdm_name = "usbhost_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), +}; + +static struct clockdomain per_clkdm = { + .name = "per_clkdm", + .pwrdm_name = "per_pwrdm", + .flags = CLKDM_CAN_HWSUP_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain emu_clkdm = { + .name = "emu_clkdm", + .pwrdm_name = "emu_pwrdm", + .flags = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP, + .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +#endif /* CONFIG_ARCH_OMAP34XX */ + +/* + * Clockdomain-powerdomain hwsup dependencies (34XX only) + */ + +static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = { + { + .pwrdm_name = "mpu_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { + .pwrdm_name = "iva2_pwrdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) + }, + { NULL } +}; + +/* + * + */ + +static struct clockdomain *clockdomains_omap[] = { + + &wkup_clkdm, + +#ifdef CONFIG_ARCH_OMAP2420 + &mpu_2420_clkdm, + &iva1_2420_clkdm, +#endif + +#ifdef CONFIG_ARCH_OMAP2430 + &mpu_2430_clkdm, + &mdm_clkdm, +#endif + +#ifdef CONFIG_ARCH_OMAP24XX + &dsp_clkdm, + &gfx_24xx_clkdm, + &core_l3_24xx_clkdm, + &core_l4_24xx_clkdm, + &dss_24xx_clkdm, +#endif + +#ifdef CONFIG_ARCH_OMAP34XX + &mpu_34xx_clkdm, + &neon_clkdm, + &iva2_clkdm, + &gfx_3430es1_clkdm, + &sgx_clkdm, + &d2d_clkdm, + &core_l3_34xx_clkdm, + &core_l4_34xx_clkdm, + &dss_34xx_clkdm, + &cam_clkdm, + &usbhost_clkdm, + &per_clkdm, + &emu_clkdm, +#endif + + NULL, +}; + +#endif diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h index 20ac3810067..1098ecfab86 100644 --- a/arch/arm/mach-omap2/cm-regbits-24xx.h +++ b/arch/arm/mach-omap2/cm-regbits-24xx.h @@ -63,7 +63,8 @@ #define OMAP24XX_CLKSEL_MPU_MASK (0x1f << 0) /* CM_CLKSTCTRL_MPU */ -#define OMAP24XX_AUTOSTATE_MPU (1 << 0) +#define OMAP24XX_AUTOSTATE_MPU_SHIFT 0 +#define OMAP24XX_AUTOSTATE_MPU_MASK (1 << 0) /* CM_FCLKEN1_CORE specific bits*/ #define OMAP24XX_EN_TV_SHIFT 2 @@ -238,9 +239,12 @@ #define OMAP24XX_CLKSEL_GPT2_MASK (0x3 << 2) /* CM_CLKSTCTRL_CORE */ -#define OMAP24XX_AUTOSTATE_DSS (1 << 2) -#define OMAP24XX_AUTOSTATE_L4 (1 << 1) -#define OMAP24XX_AUTOSTATE_L3 (1 << 0) +#define OMAP24XX_AUTOSTATE_DSS_SHIFT 2 +#define OMAP24XX_AUTOSTATE_DSS_MASK (1 << 2) +#define OMAP24XX_AUTOSTATE_L4_SHIFT 1 +#define OMAP24XX_AUTOSTATE_L4_MASK (1 << 1) +#define OMAP24XX_AUTOSTATE_L3_SHIFT 0 +#define OMAP24XX_AUTOSTATE_L3_MASK (1 << 0) /* CM_FCLKEN_GFX */ #define OMAP24XX_EN_3D_SHIFT 2 @@ -255,7 +259,8 @@ /* CM_CLKSEL_GFX specific bits */ /* CM_CLKSTCTRL_GFX */ -#define OMAP24XX_AUTOSTATE_GFX (1 << 0) +#define OMAP24XX_AUTOSTATE_GFX_SHIFT 0 +#define OMAP24XX_AUTOSTATE_GFX_MASK (1 << 0) /* CM_FCLKEN_WKUP specific bits */ @@ -367,8 +372,10 @@ #define OMAP24XX_CLKSEL_DSP_MASK (0x1f << 0) /* CM_CLKSTCTRL_DSP */ -#define OMAP2420_AUTOSTATE_IVA (1 << 8) -#define OMAP24XX_AUTOSTATE_DSP (1 << 0) +#define OMAP2420_AUTOSTATE_IVA_SHIFT 8 +#define OMAP2420_AUTOSTATE_IVA_MASK (1 << 8) +#define OMAP24XX_AUTOSTATE_DSP_SHIFT 0 +#define OMAP24XX_AUTOSTATE_DSP_MASK (1 << 0) /* CM_FCLKEN_MDM */ /* 2430 only */ @@ -396,6 +403,7 @@ /* CM_CLKSTCTRL_MDM */ /* 2430 only */ -#define OMAP2430_AUTOSTATE_MDM (1 << 0) +#define OMAP2430_AUTOSTATE_MDM_SHIFT 0 +#define OMAP2430_AUTOSTATE_MDM_MASK (1 << 0) #endif diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index ee4c0ca1a70..219f5c8d965 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -96,7 +96,8 @@ #define OMAP3430_CLKTRCTRL_IVA2_MASK (0x3 << 0) /* CM_CLKSTST_IVA2 */ -#define OMAP3430_CLKACTIVITY_IVA2 (1 << 0) +#define OMAP3430_CLKACTIVITY_IVA2_SHIFT 0 +#define OMAP3430_CLKACTIVITY_IVA2_MASK (1 << 0) /* CM_REVISION specific bits */ @@ -140,7 +141,8 @@ #define OMAP3430_CLKTRCTRL_MPU_MASK (0x3 << 0) /* CM_CLKSTST_MPU */ -#define OMAP3430_CLKACTIVITY_MPU (1 << 0) +#define OMAP3430_CLKACTIVITY_MPU_SHIFT 0 +#define OMAP3430_CLKACTIVITY_MPU_MASK (1 << 0) /* CM_FCLKEN1_CORE specific bits */ @@ -300,9 +302,12 @@ #define OMAP3430_CLKTRCTRL_L3_MASK (0x3 << 0) /* CM_CLKSTST_CORE */ -#define OMAP3430ES1_CLKACTIVITY_D2D (1 << 2) -#define OMAP3430_CLKACTIVITY_L4 (1 << 1) -#define OMAP3430_CLKACTIVITY_L3 (1 << 0) +#define OMAP3430ES1_CLKACTIVITY_D2D_SHIFT 2 +#define OMAP3430ES1_CLKACTIVITY_D2D_MASK (1 << 2) +#define OMAP3430_CLKACTIVITY_L4_SHIFT 1 +#define OMAP3430_CLKACTIVITY_L4_MASK (1 << 1) +#define OMAP3430_CLKACTIVITY_L3_SHIFT 0 +#define OMAP3430_CLKACTIVITY_L3_MASK (1 << 0) /* CM_FCLKEN_GFX */ #define OMAP3430ES1_EN_3D (1 << 2) @@ -323,7 +328,8 @@ #define OMAP3430ES1_CLKTRCTRL_GFX_MASK (0x3 << 0) /* CM_CLKSTST_GFX */ -#define OMAP3430ES1_CLKACTIVITY_GFX (1 << 0) +#define OMAP3430ES1_CLKACTIVITY_GFX_SHIFT 0 +#define OMAP3430ES1_CLKACTIVITY_GFX_MASK (1 << 0) /* CM_FCLKEN_SGX */ #define OMAP3430ES2_EN_SGX_SHIFT 1 @@ -333,6 +339,14 @@ #define OMAP3430ES2_CLKSEL_SGX_SHIFT 0 #define OMAP3430ES2_CLKSEL_SGX_MASK (0x7 << 0) +/* CM_CLKSTCTRL_SGX */ +#define OMAP3430ES2_CLKTRCTRL_SGX_SHIFT 0 +#define OMAP3430ES2_CLKTRCTRL_SGX_MASK (0x3 << 0) + +/* CM_CLKSTST_SGX */ +#define OMAP3430ES2_CLKACTIVITY_SGX_SHIFT 0 +#define OMAP3430ES2_CLKACTIVITY_SGX_MASK (1 << 0) + /* CM_FCLKEN_WKUP specific bits */ #define OMAP3430ES2_EN_USIMOCP_SHIFT 9 @@ -498,7 +512,8 @@ #define OMAP3430_CLKTRCTRL_DSS_MASK (0x3 << 0) /* CM_CLKSTST_DSS */ -#define OMAP3430_CLKACTIVITY_DSS (1 << 0) +#define OMAP3430_CLKACTIVITY_DSS_SHIFT 0 +#define OMAP3430_CLKACTIVITY_DSS_MASK (1 << 0) /* CM_FCLKEN_CAM specific bits */ @@ -522,7 +537,8 @@ #define OMAP3430_CLKTRCTRL_CAM_MASK (0x3 << 0) /* CM_CLKSTST_CAM */ -#define OMAP3430_CLKACTIVITY_CAM (1 << 0) +#define OMAP3430_CLKACTIVITY_CAM_SHIFT 0 +#define OMAP3430_CLKACTIVITY_CAM_MASK (1 << 0) /* CM_FCLKEN_PER specific bits */ @@ -598,7 +614,8 @@ #define OMAP3430_CLKTRCTRL_PER_MASK (0x3 << 0) /* CM_CLKSTST_PER */ -#define OMAP3430_CLKACTIVITY_PER (1 << 0) +#define OMAP3430_CLKACTIVITY_PER_SHIFT 0 +#define OMAP3430_CLKACTIVITY_PER_MASK (1 << 0) /* CM_CLKSEL1_EMU */ #define OMAP3430_DIV_DPLL4_SHIFT 24 @@ -623,7 +640,8 @@ #define OMAP3430_CLKTRCTRL_EMU_MASK (0x3 << 0) /* CM_CLKSTST_EMU */ -#define OMAP3430_CLKACTIVITY_EMU (1 << 0) +#define OMAP3430_CLKACTIVITY_EMU_SHIFT 0 +#define OMAP3430_CLKACTIVITY_EMU_MASK (1 << 0) /* CM_CLKSEL2_EMU specific bits */ #define OMAP3430_CORE_DPLL_EMU_MULT_SHIFT 8 @@ -673,6 +691,8 @@ #define OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT 0 #define OMAP3430ES2_CLKTRCTRL_USBHOST_MASK (3 << 0) - +/* CM_CLKSTST_USBHOST */ +#define OMAP3430ES2_CLKACTIVITY_USBHOST_SHIFT 0 +#define OMAP3430ES2_CLKACTIVITY_USBHOST_MASK (1 << 0) #endif diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 5f73cf0bb7e..371e5409fef 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -28,6 +28,9 @@ #include "powerdomains.h" +#include +#include "clockdomains.h" + extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); @@ -106,6 +109,7 @@ void __init omap2_init_common_hw(void) { omap2_mux_init(); pwrdm_init(powerdomains_omap); + clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); omap2_clk_init(); /* * Need to Fix this for 2430 -- GitLab From d1b03f615ae7ede957551dd26bf8929bdc2bb786 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:44 +0300 Subject: [PATCH 0419/5416] ARM: OMAP2: Clockdomain: Associate clocks with clockdomains Associate each OMAP24xx clock in arch/arm/mach-omap2/clock24xx.h with a clockdomain. Also move the L4 clock up higher in the file in preparation to define the SSI L4 iclk. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock24xx.h | 238 +++++++++++++++++++----- arch/arm/plat-omap/include/mach/clock.h | 3 + 2 files changed, 190 insertions(+), 51 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index be4e25554e0..242a19d86cc 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -626,6 +626,7 @@ static struct clk func_32k_ck = { .rate = 32000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .recalc = &propagate_rate, }; @@ -634,17 +635,19 @@ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .enable = &omap2_enable_osc_ck, .disable = &omap2_disable_osc_ck, .recalc = &omap2_osc_clk_recalc, }; -/* With out modem likely 12MHz, with modem likely 13MHz */ +/* Without modem likely 12MHz, with modem likely 13MHz */ static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */ .name = "sys_ck", /* ~ ref_clk also */ .parent = &osc_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .recalc = &omap2_sys_clk_recalc, }; @@ -653,6 +656,7 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ .rate = 54000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .recalc = &propagate_rate, }; @@ -684,6 +688,7 @@ static struct clk dpll_ck = { .dpll_data = &dpll_dd, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "wkup_clkdm", .recalc = &omap2_dpllcore_recalc, .set_rate = &omap2_reprogram_dpllcore, }; @@ -694,6 +699,7 @@ static struct clk apll96_ck = { .rate = 96000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT, .enable = &omap2_clk_fixed_enable, @@ -707,6 +713,7 @@ static struct clk apll54_ck = { .rate = 54000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT, .enable = &omap2_clk_fixed_enable, @@ -741,6 +748,7 @@ static struct clk func_54m_ck = { .parent = &apll54_ck, /* can also be alt_clk */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_54M_SOURCE, @@ -753,6 +761,7 @@ static struct clk core_ck = { .parent = &dpll_ck, /* can also be 32k */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -779,6 +788,7 @@ static struct clk func_96m_ck = { .parent = &apll96_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP2430_96M_SOURCE, @@ -811,6 +821,7 @@ static struct clk func_48m_ck = { .parent = &apll96_ck, /* 96M or Alt */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_48M_SOURCE, @@ -826,6 +837,7 @@ static struct clk func_12m_ck = { .fixed_div = 4, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .recalc = &omap2_fixed_divisor_recalc, }; @@ -878,6 +890,7 @@ static struct clk sys_clkout_src = { .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT, .init = &omap2_init_clksel_parent, @@ -908,6 +921,7 @@ static struct clk sys_clkout = { .parent = &sys_clkout_src, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK, .clksel = sys_clkout_clksel, @@ -921,6 +935,7 @@ static struct clk sys_clkout2_src = { .name = "sys_clkout2_src", .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | RATE_PROPAGATES, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP2420_CLKOUT2_EN_SHIFT, .init = &omap2_init_clksel_parent, @@ -942,6 +957,7 @@ static struct clk sys_clkout2 = { .name = "sys_clkout2", .parent = &sys_clkout2_src, .flags = CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK, + .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP2420_CLKOUT2_DIV_MASK, .clksel = sys_clkout2_clksel, @@ -954,6 +970,7 @@ static struct clk emul_ck = { .name = "emul_ck", .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKEMUL_CTRL, .enable_bit = OMAP24XX_EMULATION_EN_SHIFT, .recalc = &followparent_recalc, @@ -990,12 +1007,13 @@ static struct clk mpu_ck = { /* Control cpu */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED | DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .clkdm_name = "mpu_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL), .clksel_mask = OMAP24XX_CLKSEL_MPU_MASK, .clksel = mpu_clksel, .recalc = &omap2_clksel_recalc, - .round_rate = &omap2_clksel_round_rate, + .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate }; @@ -1031,6 +1049,7 @@ static struct clk dsp_fck = { .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .clkdm_name = "dsp_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), @@ -1054,10 +1073,7 @@ static const struct clksel dsp_irate_ick_clksel[] = { { .parent = NULL } }; -/* - * This clock does not exist as such in the TRM, but is added to - * separate source selection from XXX - */ +/* This clock does not exist as such in the TRM. */ static struct clk dsp_irate_ick = { .name = "dsp_irate_ick", .parent = &dsp_fck, @@ -1089,11 +1105,17 @@ static struct clk iva2_1_ick = { .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, }; +/* + * The IVA1 is an ARM7 core on the 2420 that has nothing to do with + * the C54x, but which is contained in the DSP powerdomain. Does not + * exist on later OMAPs. + */ static struct clk iva1_ifck = { .name = "iva1_ifck", .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP, + .clkdm_name = "iva1_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP2420_EN_IVA_COP_SHIFT, .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), @@ -1109,6 +1131,7 @@ static struct clk iva1_mpu_int_ifck = { .name = "iva1_mpu_int_ifck", .parent = &iva1_ifck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "iva1_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT, .fixed_div = 2, @@ -1156,6 +1179,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED | DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .clkdm_name = "core_l3_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L3_MASK, .clksel = core_l3_clksel, @@ -1177,11 +1201,13 @@ static const struct clksel usb_l4_ick_clksel[] = { { .parent = NULL }, }; +/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP24XX_EN_USB_SHIFT, .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), @@ -1192,11 +1218,43 @@ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .set_rate = &omap2_clksel_set_rate }; +/* + * L4 clock management domain + * + * This domain contains lots of interface clocks from the L4 interface, some + * functional clocks. Fixed APLL functional source clocks are managed in + * this domain. + */ +static const struct clksel_rate l4_core_l3_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_24XX }, + { .div = 0 } +}; + +static const struct clksel l4_clksel[] = { + { .parent = &core_l3_ck, .rates = l4_core_l3_rates }, + { .parent = NULL } +}; + +static struct clk l4_ck = { /* used both as an ick and fck */ + .name = "l4_ck", + .parent = &core_l3_ck, + .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | + ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES, + .clkdm_name = "core_l4_clkdm", + .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), + .clksel_mask = OMAP24XX_CLKSEL_L4_MASK, + .clksel = l4_clksel, + .recalc = &omap2_clksel_recalc, + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap2_clksel_set_rate +}; + /* * SSI is in L3 management domain, its direct parent is core not l3, * many core power domain entities are grouped into the L3 clock * domain. - * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK + * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK * * ssr = core/1/2/3/4/5, sst = 1/2 ssr. */ @@ -1221,6 +1279,7 @@ static struct clk ssi_ssr_sst_fck = { .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_SSI_SHIFT, .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), @@ -1231,6 +1290,7 @@ static struct clk ssi_ssr_sst_fck = { .set_rate = &omap2_clksel_set_rate }; + /* * GFX clock domain * Clocks: @@ -1254,6 +1314,7 @@ static struct clk gfx_3d_fck = { .name = "gfx_3d_fck", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_3D_SHIFT, .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), @@ -1268,6 +1329,7 @@ static struct clk gfx_2d_fck = { .name = "gfx_2d_fck", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_2D_SHIFT, .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), @@ -1282,6 +1344,7 @@ static struct clk gfx_ick = { .name = "gfx_ick", /* From l3 */ .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), .enable_bit = OMAP_EN_GFX_SHIFT, .recalc = &followparent_recalc, @@ -1311,6 +1374,7 @@ static struct clk mdm_ick = { /* used both as a ick and fck */ .name = "mdm_ick", .parent = &core_ck, .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, + .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN), .enable_bit = OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT, .clksel_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL), @@ -1325,51 +1389,12 @@ static struct clk mdm_osc_ck = { .name = "mdm_osc_ck", .parent = &osc_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN), .enable_bit = OMAP2430_EN_OSC_SHIFT, .recalc = &followparent_recalc, }; -/* - * L4 clock management domain - * - * This domain contains lots of interface clocks from the L4 interface, some - * functional clocks. Fixed APLL functional source clocks are managed in - * this domain. - */ -static const struct clksel_rate l4_core_l3_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE }, - { .div = 2, .val = 2, .flags = RATE_IN_24XX }, - { .div = 0 } -}; - -static const struct clksel l4_clksel[] = { - { .parent = &core_l3_ck, .rates = l4_core_l3_rates }, - { .parent = NULL } -}; - -static struct clk l4_ck = { /* used both as an ick and fck */ - .name = "l4_ck", - .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES, - .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), - .clksel_mask = OMAP24XX_CLKSEL_L4_MASK, - .clksel = l4_clksel, - .recalc = &omap2_clksel_recalc, - .round_rate = &omap2_clksel_round_rate, - .set_rate = &omap2_clksel_set_rate -}; - -static struct clk ssi_l4_ick = { - .name = "ssi_l4_ick", - .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), - .enable_bit = OMAP24XX_EN_SSI_SHIFT, - .recalc = &followparent_recalc, -}; - /* * DSS clock domain * CLOCKs: @@ -1409,6 +1434,7 @@ static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", .parent = &l4_ck, /* really both l3 and l4 */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_DSS1_SHIFT, .recalc = &followparent_recalc, @@ -1419,6 +1445,7 @@ static struct clk dss1_fck = { .parent = &core_ck, /* Core or sys */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, + .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_DSS1_SHIFT, .init = &omap2_init_clksel_parent, @@ -1451,6 +1478,7 @@ static struct clk dss2_fck = { /* Alt clk used in power management */ .parent = &sys_ck, /* fixed at sys_ck or 48MHz */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, + .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_DSS2_SHIFT, .init = &omap2_init_clksel_parent, @@ -1464,6 +1492,7 @@ static struct clk dss_54m_fck = { /* Alt clk used in power management */ .name = "dss_54m_fck", /* 54m tv clk */ .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_TV_SHIFT, .recalc = &followparent_recalc, @@ -1491,6 +1520,7 @@ static struct clk gpt1_ick = { .name = "gpt1_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, .recalc = &followparent_recalc, @@ -1500,6 +1530,7 @@ static struct clk gpt1_fck = { .name = "gpt1_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, .init = &omap2_init_clksel_parent, @@ -1515,6 +1546,7 @@ static struct clk gpt2_ick = { .name = "gpt2_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT2_SHIFT, .recalc = &followparent_recalc, @@ -1524,6 +1556,7 @@ static struct clk gpt2_fck = { .name = "gpt2_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT2_SHIFT, .init = &omap2_init_clksel_parent, @@ -1537,6 +1570,7 @@ static struct clk gpt3_ick = { .name = "gpt3_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT3_SHIFT, .recalc = &followparent_recalc, @@ -1546,6 +1580,7 @@ static struct clk gpt3_fck = { .name = "gpt3_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT3_SHIFT, .init = &omap2_init_clksel_parent, @@ -1559,6 +1594,7 @@ static struct clk gpt4_ick = { .name = "gpt4_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT4_SHIFT, .recalc = &followparent_recalc, @@ -1568,6 +1604,7 @@ static struct clk gpt4_fck = { .name = "gpt4_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT4_SHIFT, .init = &omap2_init_clksel_parent, @@ -1581,6 +1618,7 @@ static struct clk gpt5_ick = { .name = "gpt5_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT5_SHIFT, .recalc = &followparent_recalc, @@ -1590,6 +1628,7 @@ static struct clk gpt5_fck = { .name = "gpt5_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT5_SHIFT, .init = &omap2_init_clksel_parent, @@ -1603,6 +1642,7 @@ static struct clk gpt6_ick = { .name = "gpt6_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT6_SHIFT, .recalc = &followparent_recalc, @@ -1612,6 +1652,7 @@ static struct clk gpt6_fck = { .name = "gpt6_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT6_SHIFT, .init = &omap2_init_clksel_parent, @@ -1634,6 +1675,7 @@ static struct clk gpt7_fck = { .name = "gpt7_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, .init = &omap2_init_clksel_parent, @@ -1647,6 +1689,7 @@ static struct clk gpt8_ick = { .name = "gpt8_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT8_SHIFT, .recalc = &followparent_recalc, @@ -1656,6 +1699,7 @@ static struct clk gpt8_fck = { .name = "gpt8_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT8_SHIFT, .init = &omap2_init_clksel_parent, @@ -1669,6 +1713,7 @@ static struct clk gpt9_ick = { .name = "gpt9_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT9_SHIFT, .recalc = &followparent_recalc, @@ -1678,6 +1723,7 @@ static struct clk gpt9_fck = { .name = "gpt9_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT9_SHIFT, .init = &omap2_init_clksel_parent, @@ -1691,6 +1737,7 @@ static struct clk gpt10_ick = { .name = "gpt10_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT10_SHIFT, .recalc = &followparent_recalc, @@ -1700,6 +1747,7 @@ static struct clk gpt10_fck = { .name = "gpt10_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT10_SHIFT, .init = &omap2_init_clksel_parent, @@ -1713,6 +1761,7 @@ static struct clk gpt11_ick = { .name = "gpt11_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT11_SHIFT, .recalc = &followparent_recalc, @@ -1722,6 +1771,7 @@ static struct clk gpt11_fck = { .name = "gpt11_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT11_SHIFT, .init = &omap2_init_clksel_parent, @@ -1735,6 +1785,7 @@ static struct clk gpt12_ick = { .name = "gpt12_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT12_SHIFT, .recalc = &followparent_recalc, @@ -1744,6 +1795,7 @@ static struct clk gpt12_fck = { .name = "gpt12_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT12_SHIFT, .init = &omap2_init_clksel_parent, @@ -1758,6 +1810,7 @@ static struct clk mcbsp1_ick = { .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT, .recalc = &followparent_recalc, @@ -1768,6 +1821,7 @@ static struct clk mcbsp1_fck = { .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT, .recalc = &followparent_recalc, @@ -1778,6 +1832,7 @@ static struct clk mcbsp2_ick = { .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT, .recalc = &followparent_recalc, @@ -1788,6 +1843,7 @@ static struct clk mcbsp2_fck = { .id = 2, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT, .recalc = &followparent_recalc, @@ -1798,6 +1854,7 @@ static struct clk mcbsp3_ick = { .id = 3, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP3_SHIFT, .recalc = &followparent_recalc, @@ -1808,6 +1865,7 @@ static struct clk mcbsp3_fck = { .id = 3, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP3_SHIFT, .recalc = &followparent_recalc, @@ -1818,6 +1876,7 @@ static struct clk mcbsp4_ick = { .id = 4, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP4_SHIFT, .recalc = &followparent_recalc, @@ -1828,6 +1887,7 @@ static struct clk mcbsp4_fck = { .id = 4, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP4_SHIFT, .recalc = &followparent_recalc, @@ -1838,6 +1898,7 @@ static struct clk mcbsp5_ick = { .id = 5, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP5_SHIFT, .recalc = &followparent_recalc, @@ -1848,6 +1909,7 @@ static struct clk mcbsp5_fck = { .id = 5, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP5_SHIFT, .recalc = &followparent_recalc, @@ -1857,6 +1919,7 @@ static struct clk mcspi1_ick = { .name = "mcspi_ick", .id = 1, .parent = &l4_ck, + .clkdm_name = "core_l4_clkdm", .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT, @@ -1868,6 +1931,7 @@ static struct clk mcspi1_fck = { .id = 1, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT, .recalc = &followparent_recalc, @@ -1878,6 +1942,7 @@ static struct clk mcspi2_ick = { .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT, .recalc = &followparent_recalc, @@ -1888,6 +1953,7 @@ static struct clk mcspi2_fck = { .id = 2, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT, .recalc = &followparent_recalc, @@ -1898,6 +1964,7 @@ static struct clk mcspi3_ick = { .id = 3, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCSPI3_SHIFT, .recalc = &followparent_recalc, @@ -1908,6 +1975,7 @@ static struct clk mcspi3_fck = { .id = 3, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCSPI3_SHIFT, .recalc = &followparent_recalc, @@ -1917,6 +1985,7 @@ static struct clk uart1_ick = { .name = "uart1_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_UART1_SHIFT, .recalc = &followparent_recalc, @@ -1926,6 +1995,7 @@ static struct clk uart1_fck = { .name = "uart1_fck", .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_UART1_SHIFT, .recalc = &followparent_recalc, @@ -1935,6 +2005,7 @@ static struct clk uart2_ick = { .name = "uart2_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_UART2_SHIFT, .recalc = &followparent_recalc, @@ -1944,6 +2015,7 @@ static struct clk uart2_fck = { .name = "uart2_fck", .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_UART2_SHIFT, .recalc = &followparent_recalc, @@ -1953,6 +2025,7 @@ static struct clk uart3_ick = { .name = "uart3_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP24XX_EN_UART3_SHIFT, .recalc = &followparent_recalc, @@ -1962,6 +2035,7 @@ static struct clk uart3_fck = { .name = "uart3_fck", .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_UART3_SHIFT, .recalc = &followparent_recalc, @@ -1971,6 +2045,7 @@ static struct clk gpios_ick = { .name = "gpios_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, .recalc = &followparent_recalc, @@ -1980,6 +2055,7 @@ static struct clk gpios_fck = { .name = "gpios_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, .recalc = &followparent_recalc, @@ -1989,6 +2065,7 @@ static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, .recalc = &followparent_recalc, @@ -1998,6 +2075,7 @@ static struct clk mpu_wdt_fck = { .name = "mpu_wdt_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, .recalc = &followparent_recalc, @@ -2006,31 +2084,40 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, + .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | + ENABLE_ON_INIT, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT, .recalc = &followparent_recalc, }; + static struct clk wdt1_ick = { .name = "wdt1_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_WDT1_SHIFT, .recalc = &followparent_recalc, }; + static struct clk omapctrl_ick = { .name = "omapctrl_ick", .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, + .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | + ENABLE_ON_INIT, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT, .recalc = &followparent_recalc, }; + static struct clk icr_ick = { .name = "icr_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP2430_EN_ICR_SHIFT, .recalc = &followparent_recalc, @@ -2040,15 +2127,22 @@ static struct clk cam_ick = { .name = "cam_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_CAM_SHIFT, .recalc = &followparent_recalc, }; +/* + * cam_fck controls both CAM_MCLK and CAM_FCLK. It should probably be + * split into two separate clocks, since the parent clocks are different + * and the clockdomains are also different. + */ static struct clk cam_fck = { .name = "cam_fck", .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_CAM_SHIFT, .recalc = &followparent_recalc, @@ -2058,6 +2152,7 @@ static struct clk mailboxes_ick = { .name = "mailboxes_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT, .recalc = &followparent_recalc, @@ -2067,6 +2162,7 @@ static struct clk wdt4_ick = { .name = "wdt4_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_WDT4_SHIFT, .recalc = &followparent_recalc, @@ -2076,6 +2172,7 @@ static struct clk wdt4_fck = { .name = "wdt4_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_WDT4_SHIFT, .recalc = &followparent_recalc, @@ -2085,6 +2182,7 @@ static struct clk wdt3_ick = { .name = "wdt3_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_WDT3_SHIFT, .recalc = &followparent_recalc, @@ -2094,6 +2192,7 @@ static struct clk wdt3_fck = { .name = "wdt3_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_WDT3_SHIFT, .recalc = &followparent_recalc, @@ -2103,6 +2202,7 @@ static struct clk mspro_ick = { .name = "mspro_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MSPRO_SHIFT, .recalc = &followparent_recalc, @@ -2112,6 +2212,7 @@ static struct clk mspro_fck = { .name = "mspro_fck", .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MSPRO_SHIFT, .recalc = &followparent_recalc, @@ -2121,6 +2222,7 @@ static struct clk mmc_ick = { .name = "mmc_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_MMC_SHIFT, .recalc = &followparent_recalc, @@ -2130,6 +2232,7 @@ static struct clk mmc_fck = { .name = "mmc_fck", .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_MMC_SHIFT, .recalc = &followparent_recalc, @@ -2139,6 +2242,7 @@ static struct clk fac_ick = { .name = "fac_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_FAC_SHIFT, .recalc = &followparent_recalc, @@ -2148,6 +2252,7 @@ static struct clk fac_fck = { .name = "fac_fck", .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_FAC_SHIFT, .recalc = &followparent_recalc, @@ -2157,6 +2262,7 @@ static struct clk eac_ick = { .name = "eac_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_EAC_SHIFT, .recalc = &followparent_recalc, @@ -2166,6 +2272,7 @@ static struct clk eac_fck = { .name = "eac_fck", .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_EAC_SHIFT, .recalc = &followparent_recalc, @@ -2175,6 +2282,7 @@ static struct clk hdq_ick = { .name = "hdq_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_HDQ_SHIFT, .recalc = &followparent_recalc, @@ -2184,6 +2292,7 @@ static struct clk hdq_fck = { .name = "hdq_fck", .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_HDQ_SHIFT, .recalc = &followparent_recalc, @@ -2194,6 +2303,7 @@ static struct clk i2c2_ick = { .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_I2C2_SHIFT, .recalc = &followparent_recalc, @@ -2204,6 +2314,7 @@ static struct clk i2c2_fck = { .id = 2, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_I2C2_SHIFT, .recalc = &followparent_recalc, @@ -2214,6 +2325,7 @@ static struct clk i2chs2_fck = { .id = 2, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_I2CHS2_SHIFT, .recalc = &followparent_recalc, @@ -2224,6 +2336,7 @@ static struct clk i2c1_ick = { .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_I2C1_SHIFT, .recalc = &followparent_recalc, @@ -2234,6 +2347,7 @@ static struct clk i2c1_fck = { .id = 1, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_I2C1_SHIFT, .recalc = &followparent_recalc, @@ -2244,6 +2358,7 @@ static struct clk i2chs1_fck = { .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_I2CHS1_SHIFT, .recalc = &followparent_recalc, @@ -2252,7 +2367,9 @@ static struct clk i2chs1_fck = { static struct clk gpmc_fck = { .name = "gpmc_fck", .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, + .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | + ENABLE_ON_INIT, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2260,6 +2377,7 @@ static struct clk sdma_fck = { .name = "sdma_fck", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2267,6 +2385,7 @@ static struct clk sdma_ick = { .name = "sdma_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2274,6 +2393,7 @@ static struct clk vlynq_ick = { .name = "vlynq_ick", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_VLYNQ_SHIFT, .recalc = &followparent_recalc, @@ -2308,6 +2428,7 @@ static struct clk vlynq_fck = { .name = "vlynq_fck", .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | DELAYED_APP, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_VLYNQ_SHIFT, .init = &omap2_init_clksel_parent, @@ -2323,6 +2444,7 @@ static struct clk sdrc_ick = { .name = "sdrc_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | ENABLE_ON_INIT, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP2430_EN_SDRC_SHIFT, .recalc = &followparent_recalc, @@ -2332,6 +2454,7 @@ static struct clk des_ick = { .name = "des_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_DES_SHIFT, .recalc = &followparent_recalc, @@ -2341,6 +2464,7 @@ static struct clk sha_ick = { .name = "sha_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_SHA_SHIFT, .recalc = &followparent_recalc, @@ -2350,6 +2474,7 @@ static struct clk rng_ick = { .name = "rng_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_RNG_SHIFT, .recalc = &followparent_recalc, @@ -2359,6 +2484,7 @@ static struct clk aes_ick = { .name = "aes_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_AES_SHIFT, .recalc = &followparent_recalc, @@ -2368,6 +2494,7 @@ static struct clk pka_ick = { .name = "pka_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_PKA_SHIFT, .recalc = &followparent_recalc, @@ -2377,6 +2504,7 @@ static struct clk usb_fck = { .name = "usb_fck", .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_USB_SHIFT, .recalc = &followparent_recalc, @@ -2386,6 +2514,7 @@ static struct clk usbhs_ick = { .name = "usbhs_ick", .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_USBHS_SHIFT, .recalc = &followparent_recalc, @@ -2396,6 +2525,7 @@ static struct clk mmchs1_ick = { .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MMCHS1_SHIFT, .recalc = &followparent_recalc, @@ -2406,6 +2536,7 @@ static struct clk mmchs1_fck = { .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHS1_SHIFT, .recalc = &followparent_recalc, @@ -2416,6 +2547,7 @@ static struct clk mmchs2_ick = { .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MMCHS2_SHIFT, .recalc = &followparent_recalc, @@ -2435,6 +2567,7 @@ static struct clk gpio5_ick = { .name = "gpio5_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_GPIO5_SHIFT, .recalc = &followparent_recalc, @@ -2444,6 +2577,7 @@ static struct clk gpio5_fck = { .name = "gpio5_fck", .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_GPIO5_SHIFT, .recalc = &followparent_recalc, @@ -2453,6 +2587,7 @@ static struct clk mdm_intc_ick = { .name = "mdm_intc_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT, .recalc = &followparent_recalc, @@ -2463,6 +2598,7 @@ static struct clk mmchsdb1_fck = { .id = 1, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT, .recalc = &followparent_recalc, @@ -2473,6 +2609,7 @@ static struct clk mmchsdb2_fck = { .id = 2, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT, .recalc = &followparent_recalc, @@ -2551,7 +2688,6 @@ static struct clk *onchip_24xx_clks[] __initdata = { &usb_l4_ick, /* L4 domain clocks */ &l4_ck, /* used as both core_l4 and wu_l4 */ - &ssi_l4_ick, /* virtual meta-group clock */ &virt_prcm_set, /* general l4 interface ck, multi-parent functional clk */ diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 92f7c7238fc..719298554ed 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -15,6 +15,7 @@ struct module; struct clk; +struct clockdomain; #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) @@ -79,6 +80,8 @@ struct clk { u32 clksel_mask; const struct clksel *clksel; struct dpll_data *dpll_data; + const char *clkdm_name; + struct clockdomain *clkdm; #else __u8 rate_offset; __u8 src_offset; -- GitLab From 333943ba9e1716a3751af82f2dcc7620b83091ed Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Aug 2008 11:08:45 +0300 Subject: [PATCH 0420/5416] ARM: OMAP2: Clockdomain: Integrate OMAP3 clocks with clockdomain code This patch integrates the OMAP3 clock tree with the clockdomain code. This patch: - marks OMAP34xx clocks with their corresponding clockdomain. - adds code to convert the clockdomain name to a clockdomain pointer in the struct clk during clk_register(). - modifies OMAP2 clock usecounting to call into the clockdomain code when clocks are enabled or disabled. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock.c | 46 ++++++- arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock34xx.c | 4 +- arch/arm/mach-omap2/clock34xx.h | 196 ++++++++++++++++++++++++++--- arch/arm/mach-omap2/clockdomains.h | 9 +- 5 files changed, 232 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 1d891e4a693..aa9b37370d4 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -62,9 +63,35 @@ u8 cpu_mask; /*------------------------------------------------------------------------- - * Omap2 specific clock functions + * OMAP2/3 specific clock functions *-------------------------------------------------------------------------*/ +/** + * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk + * @clk: OMAP clock struct ptr to use + * + * Convert a clockdomain name stored in a struct clk 'clk' into a + * clockdomain pointer, and save it into the struct clk. Intended to be + * called during clk_register(). No return value. + */ +void omap2_init_clk_clkdm(struct clk *clk) +{ + struct clockdomain *clkdm; + + if (!clk->clkdm_name) + return; + + clkdm = clkdm_lookup(clk->clkdm_name); + if (clkdm) { + pr_debug("clock: associated clk %s to clkdm %s\n", + clk->name, clk->clkdm_name); + clk->clkdm = clkdm; + } else { + pr_debug("clock: could not associate clk %s to " + "clkdm %s\n", clk->name, clk->clkdm_name); + } +} + /** * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware * @clk: OMAP clock struct ptr to use @@ -308,6 +335,9 @@ void omap2_clk_disable(struct clk *clk) _omap2_clk_disable(clk); if (likely((u32)clk->parent)) omap2_clk_disable(clk->parent); + if (clk->clkdm) + omap2_clkdm_clk_disable(clk->clkdm, clk); + } } @@ -324,11 +354,19 @@ int omap2_clk_enable(struct clk *clk) return ret; } + if (clk->clkdm) + omap2_clkdm_clk_enable(clk->clkdm, clk); + ret = _omap2_clk_enable(clk); - if (unlikely(ret != 0) && clk->parent) { - omap2_clk_disable(clk->parent); - clk->usecount--; + if (unlikely(ret != 0)) { + if (clk->clkdm) + omap2_clkdm_clk_disable(clk->clkdm, clk); + + if (clk->parent) { + omap2_clk_disable(clk->parent); + clk->usecount--; + } } } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 626e5fa93b6..ea55f286f47 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -36,6 +36,7 @@ void omap2_clk_disable_unused(struct clk *clk); #endif void omap2_clksel_recalc(struct clk *clk); +void omap2_init_clk_clkdm(struct clk *clk); void omap2_init_clksel_parent(struct clk *clk); u32 omap2_clksel_get_divisor(struct clk *clk); u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate, diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index dff7a72fefc..0bf661df664 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -489,8 +489,10 @@ int __init omap2_clk_init(void) for (clkp = onchip_34xx_clks; clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks); clkp++) { - if ((*clkp)->flags & cpu_clkflg) + if ((*clkp)->flags & cpu_clkflg) { clk_register(*clkp); + omap2_init_clk_clkdm(*clkp); + } } /* REVISIT: Not yet ready for OMAP3 */ diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index ec664457a11..bb01e201481 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -478,7 +478,7 @@ static struct clk dpll3_m2_ck = { }; static const struct clksel core_ck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll3_m2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -495,7 +495,7 @@ static struct clk core_ck = { }; static const struct clksel dpll3_m2x2_ck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll3_x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -541,7 +541,7 @@ static struct clk dpll3_m3x2_ck = { }; static const struct clksel emu_core_alwon_ck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -633,7 +633,7 @@ static struct clk dpll4_m2x2_ck = { }; static const struct clksel omap_96m_alwon_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -659,7 +659,7 @@ static struct clk omap_96m_fck = { }; static const struct clksel cm_96m_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -701,7 +701,7 @@ static struct clk dpll4_m3x2_ck = { }; static const struct clksel virt_omap_54m_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -911,7 +911,7 @@ static struct clk dpll5_m2_ck = { }; static const struct clksel omap_120m_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll5_m2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -919,13 +919,13 @@ static const struct clksel omap_120m_fck_clksel[] = { static struct clk omap_120m_fck = { .name = "omap_120m_fck", .parent = &dpll5_m2_ck, - .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), - .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, - .clksel = omap_120m_fck_clksel, + .init = &omap2_init_clksel_parent, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), + .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, + .clksel = omap_120m_fck_clksel, .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, - .recalc = &omap2_clksel_recalc, + .recalc = &omap2_clksel_recalc, }; /* CM EXTERNAL CLOCK OUTPUTS */ @@ -1034,7 +1034,7 @@ static struct clk dpll1_fck = { * called 'dpll1_fck' */ static const struct clksel mpu_clksel[] = { - { .parent = &dpll1_fck, .rates = dpll_bypass_rates }, + { .parent = &dpll1_fck, .rates = dpll_bypass_rates }, { .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -1048,6 +1048,7 @@ static struct clk mpu_ck = { .clksel = mpu_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "mpu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1075,6 +1076,8 @@ static struct clk arm_fck = { .recalc = &omap2_clksel_recalc, }; +/* XXX What about neon_clkdm ? */ + /* * REVISIT: This clock is never specifically defined in the 3430 TRM, * although it is referenced - so this is a guess @@ -1107,7 +1110,7 @@ static struct clk dpll2_fck = { */ static const struct clksel iva2_clksel[] = { - { .parent = &dpll2_fck, .rates = dpll_bypass_rates }, + { .parent = &dpll2_fck, .rates = dpll_bypass_rates }, { .parent = &dpll2_m2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -1123,6 +1126,7 @@ static struct clk iva2_ck = { .clksel_mask = OMAP3430_ST_IVA2_CLK_MASK, .clksel = iva2_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .clkdm_name = "iva2_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1137,6 +1141,7 @@ static struct clk l3_ick = { .clksel = div2_core_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1154,6 +1159,7 @@ static struct clk l4_ick = { .clksel = div2_l3_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1193,33 +1199,40 @@ static struct clk gfx_l3_fck = { .clksel_mask = OMAP_CLKSEL_GFX_MASK, .clksel = gfx_l3_clksel, .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES, + .clkdm_name = "gfx_3430es1_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk gfx_l3_ick = { .name = "gfx_l3_ick", .parent = &l3_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), .enable_bit = OMAP_EN_GFX_SHIFT, .flags = CLOCK_IN_OMAP3430ES1, + .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; static struct clk gfx_cg1_ck = { .name = "gfx_cg1_ck", .parent = &gfx_l3_fck, /* REVISIT: correct? */ + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES1_EN_2D_SHIFT, .flags = CLOCK_IN_OMAP3430ES1, + .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; static struct clk gfx_cg2_ck = { .name = "gfx_cg2_ck", .parent = &gfx_l3_fck, /* REVISIT: correct? */ + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES1_EN_3D_SHIFT, .flags = CLOCK_IN_OMAP3430ES1, + .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -1252,15 +1265,18 @@ static struct clk sgx_fck = { .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK, .clksel = sgx_clksel, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "sgx_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk sgx_ick = { .name = "sgx_ick", .parent = &l3_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_SGX_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "sgx_clkdm", .recalc = &followparent_recalc, }; @@ -1269,9 +1285,11 @@ static struct clk sgx_ick = { static struct clk d2d_26m_fck = { .name = "d2d_26m_fck", .parent = &sys_ck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES1_EN_D2D_SHIFT, .flags = CLOCK_IN_OMAP3430ES1, + .clkdm_name = "d2d_clkdm", .recalc = &followparent_recalc, }; @@ -1291,6 +1309,7 @@ static struct clk gpt10_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1304,6 +1323,7 @@ static struct clk gpt11_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1341,6 +1361,7 @@ static struct clk core_96m_fck = { .parent = &omap_96m_fck, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1351,6 +1372,7 @@ static struct clk mmchs3_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1361,6 +1383,7 @@ static struct clk mmchs2_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1370,6 +1393,7 @@ static struct clk mspro_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1380,6 +1404,7 @@ static struct clk mmchs1_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1390,16 +1415,18 @@ static struct clk i2c3_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; static struct clk i2c2_fck = { .name = "i2c_fck", - .id = 2, + .id = 2, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1410,6 +1437,7 @@ static struct clk i2c1_fck = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1443,6 +1471,7 @@ static struct clk mcbsp5_fck = { .clksel_mask = OMAP2_MCBSP5_CLKS_MASK, .clksel = mcbsp_15_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1456,6 +1485,7 @@ static struct clk mcbsp1_fck = { .clksel_mask = OMAP2_MCBSP1_CLKS_MASK, .clksel = mcbsp_15_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1466,6 +1496,7 @@ static struct clk core_48m_fck = { .parent = &omap_48m_fck, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1543,6 +1574,7 @@ static struct clk core_12m_fck = { .parent = &omap_12m_fck, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1581,6 +1613,7 @@ static struct clk ssi_ssr_fck = { .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, .clksel = ssi_ssr_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1596,11 +1629,17 @@ static struct clk ssi_sst_fck = { /* CORE_L3_ICK based clocks */ +/* + * XXX must add clk_enable/clk_disable for these if standard code won't + * handle it + */ static struct clk core_l3_ick = { .name = "core_l3_ick", .parent = &l3_ick, + .init = &omap2_init_clk_clkdm, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1610,6 +1649,7 @@ static struct clk hsotgusb_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1619,6 +1659,7 @@ static struct clk sdrc_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SDRC_SHIFT, .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1627,6 +1668,7 @@ static struct clk gpmc_fck = { .parent = &core_l3_ick, .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK | ENABLE_ON_INIT, + .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1654,8 +1696,10 @@ static struct clk pka_ick = { static struct clk core_l4_ick = { .name = "core_l4_ick", .parent = &l4_ick, + .init = &omap2_init_clk_clkdm, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1665,6 +1709,7 @@ static struct clk usbtll_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1675,6 +1720,7 @@ static struct clk mmchs3_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1685,6 +1731,7 @@ static struct clk icr_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_ICR_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1694,6 +1741,7 @@ static struct clk aes2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_AES2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1703,6 +1751,7 @@ static struct clk sha12_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SHA12_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1712,6 +1761,7 @@ static struct clk des2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_DES2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1722,6 +1772,7 @@ static struct clk mmchs2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1732,6 +1783,7 @@ static struct clk mmchs1_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1741,6 +1793,7 @@ static struct clk mspro_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1750,6 +1803,7 @@ static struct clk hdq_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1760,6 +1814,7 @@ static struct clk mcspi4_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1770,6 +1825,7 @@ static struct clk mcspi3_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1780,6 +1836,7 @@ static struct clk mcspi2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1790,6 +1847,7 @@ static struct clk mcspi1_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1800,6 +1858,7 @@ static struct clk i2c3_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1810,6 +1869,7 @@ static struct clk i2c2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1820,6 +1880,7 @@ static struct clk i2c1_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1829,6 +1890,7 @@ static struct clk uart2_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1838,6 +1900,7 @@ static struct clk uart1_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1847,6 +1910,7 @@ static struct clk gpt11_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT11_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1856,6 +1920,7 @@ static struct clk gpt10_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT10_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1866,6 +1931,7 @@ static struct clk mcbsp5_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1876,6 +1942,7 @@ static struct clk mcbsp1_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1885,6 +1952,7 @@ static struct clk fac_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, .flags = CLOCK_IN_OMAP3430ES1, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1894,6 +1962,7 @@ static struct clk mailboxes_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1913,6 +1982,7 @@ static struct clk ssi_l4_ick = { .parent = &l4_ick, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1922,6 +1992,7 @@ static struct clk ssi_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1996,7 +2067,7 @@ static struct clk des1_ick = { /* DSS */ static const struct clksel dss1_alwon_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -2011,33 +2082,40 @@ static struct clk dss1_alwon_fck = { .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = dss1_alwon_fck_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "dss_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk dss_tv_fck = { .name = "dss_tv_fck", .parent = &omap_54m_fck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_TV_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; static struct clk dss_96m_fck = { .name = "dss_96m_fck", .parent = &omap_96m_fck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_TV_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; static struct clk dss2_alwon_fck = { .name = "dss2_alwon_fck", .parent = &sys_ck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_DSS2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; @@ -2045,16 +2123,18 @@ static struct clk dss_ick = { /* Handles both L3 and L4 clocks */ .name = "dss_ick", .parent = &l4_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; /* CAM */ static const struct clksel cam_mclk_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, + { .parent = &sys_ck, .rates = dpll_bypass_rates }, { .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates }, { .parent = NULL } }; @@ -2069,24 +2149,29 @@ static struct clk cam_mclk = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "cam_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk cam_l3_ick = { .name = "cam_l3_ick", .parent = &l3_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "cam_clkdm", .recalc = &followparent_recalc, }; static struct clk cam_l4_ick = { .name = "cam_l4_ick", .parent = &l4_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "cam_clkdm", .recalc = &followparent_recalc, }; @@ -2095,45 +2180,55 @@ static struct clk cam_l4_ick = { static struct clk usbhost_120m_fck = { .name = "usbhost_120m_fck", .parent = &omap_120m_fck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; static struct clk usbhost_48m_fck = { .name = "usbhost_48m_fck", .parent = &omap_48m_fck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; static struct clk usbhost_l3_ick = { .name = "usbhost_l3_ick", .parent = &l3_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; static struct clk usbhost_l4_ick = { .name = "usbhost_l4_ick", .parent = &l4_ick, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; static struct clk usbhost_sar_fck = { .name = "usbhost_sar_fck", .parent = &osc_sys_ck, + .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL), .enable_bit = OMAP3430ES2_SAVEANDRESTORE_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; @@ -2175,6 +2270,7 @@ static struct clk usim_fck = { .recalc = &omap2_clksel_recalc, }; +/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */ static struct clk gpt1_fck = { .name = "gpt1_fck", .init = &omap2_init_clksel_parent, @@ -2184,13 +2280,16 @@ static struct clk gpt1_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk wkup_32k_fck = { .name = "wkup_32k_fck", + .init = &omap2_init_clk_clkdm, .parent = &omap_32k_fck, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2200,6 +2299,7 @@ static struct clk gpio1_fck = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2209,6 +2309,7 @@ static struct clk wdt2_fck = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2216,6 +2317,7 @@ static struct clk wkup_l4_ick = { .name = "wkup_l4_ick", .parent = &sys_ck, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2227,6 +2329,7 @@ static struct clk usim_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, .flags = CLOCK_IN_OMAP3430ES2, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2236,6 +2339,7 @@ static struct clk wdt2_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2245,6 +2349,7 @@ static struct clk wdt1_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2254,6 +2359,7 @@ static struct clk gpio1_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2263,15 +2369,18 @@ static struct clk omap_32ksync_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; +/* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_ick = { .name = "gpt12_ick", .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT12_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2281,6 +2390,7 @@ static struct clk gpt1_ick = { .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT1_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2291,16 +2401,20 @@ static struct clk gpt1_ick = { static struct clk per_96m_fck = { .name = "per_96m_fck", .parent = &omap_96m_alwon_fck, + .init = &omap2_init_clk_clkdm, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; static struct clk per_48m_fck = { .name = "per_48m_fck", .parent = &omap_48m_fck, + .init = &omap2_init_clk_clkdm, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2310,6 +2424,7 @@ static struct clk uart3_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2322,6 +2437,7 @@ static struct clk gpt2_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2334,6 +2450,7 @@ static struct clk gpt3_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2346,6 +2463,7 @@ static struct clk gpt4_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2358,6 +2476,7 @@ static struct clk gpt5_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2370,6 +2489,7 @@ static struct clk gpt6_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2382,6 +2502,7 @@ static struct clk gpt7_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2394,6 +2515,7 @@ static struct clk gpt8_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2406,12 +2528,14 @@ static struct clk gpt9_fck = { .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK, .clksel = omap343x_gpt_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk per_32k_alwon_fck = { .name = "per_32k_alwon_fck", .parent = &omap_32k_fck, + .clkdm_name = "per_clkdm", .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, .recalc = &followparent_recalc, }; @@ -2422,6 +2546,7 @@ static struct clk gpio6_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2431,6 +2556,7 @@ static struct clk gpio5_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2440,6 +2566,7 @@ static struct clk gpio4_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2449,6 +2576,7 @@ static struct clk gpio3_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2458,6 +2586,7 @@ static struct clk gpio2_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2467,6 +2596,7 @@ static struct clk wdt3_fck = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2475,6 +2605,7 @@ static struct clk per_l4_ick = { .parent = &l4_ick, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2484,6 +2615,7 @@ static struct clk gpio6_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2493,6 +2625,7 @@ static struct clk gpio5_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2502,6 +2635,7 @@ static struct clk gpio4_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2511,6 +2645,7 @@ static struct clk gpio3_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2520,6 +2655,7 @@ static struct clk gpio2_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2529,6 +2665,7 @@ static struct clk wdt3_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2538,6 +2675,7 @@ static struct clk uart3_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2547,6 +2685,7 @@ static struct clk gpt9_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT9_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2556,6 +2695,7 @@ static struct clk gpt8_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT8_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2565,6 +2705,7 @@ static struct clk gpt7_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT7_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2574,6 +2715,7 @@ static struct clk gpt6_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT6_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2583,6 +2725,7 @@ static struct clk gpt5_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT5_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2592,6 +2735,7 @@ static struct clk gpt4_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT4_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2601,6 +2745,7 @@ static struct clk gpt3_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2610,6 +2755,7 @@ static struct clk gpt2_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2620,6 +2766,7 @@ static struct clk mcbsp2_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2630,6 +2777,7 @@ static struct clk mcbsp3_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2640,12 +2788,13 @@ static struct clk mcbsp4_ick = { .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; static const struct clksel mcbsp_234_clksel[] = { { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates }, - { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, + { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, { .parent = NULL } }; @@ -2659,6 +2808,7 @@ static struct clk mcbsp2_fck = { .clksel_mask = OMAP2_MCBSP2_CLKS_MASK, .clksel = mcbsp_234_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2672,6 +2822,7 @@ static struct clk mcbsp3_fck = { .clksel_mask = OMAP2_MCBSP3_CLKS_MASK, .clksel = mcbsp_234_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2685,6 +2836,7 @@ static struct clk mcbsp4_fck = { .clksel_mask = OMAP2_MCBSP4_CLKS_MASK, .clksel = mcbsp_234_clksel, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2732,6 +2884,7 @@ static struct clk emu_src_ck = { .clksel_mask = OMAP3430_MUX_CTRL_MASK, .clksel = emu_src_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2755,6 +2908,7 @@ static struct clk pclk_fck = { .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, .clksel = pclk_emu_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2777,6 +2931,7 @@ static struct clk pclkx2_fck = { .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, .clksel = pclkx2_emu_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2792,6 +2947,7 @@ static struct clk atclk_fck = { .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, .clksel = atclk_emu_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2802,6 +2958,7 @@ static struct clk traceclk_src_fck = { .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, .clksel = emu_src_clksel, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2824,6 +2981,7 @@ static struct clk traceclk_fck = { .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK, .clksel = traceclk_clksel, .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED, + .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2853,11 +3011,13 @@ static struct clk sr_l4_ick = { .name = "sr_l4_ick", .parent = &l4_ick, .flags = CLOCK_IN_OMAP343X, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; /* SECURE_32K_FCK clocks */ +/* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_fck = { .name = "gpt12_fck", .parent = &secure_32k_fck, diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index a2763203713..cd86dcc7b42 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -168,12 +168,19 @@ static struct clockdomain sgx_clkdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), }; +/* + * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but + * then that information was removed from the 34xx ES2+ TRM. It is + * unclear whether the core is still there, but the clockdomain logic + * is there, and must be programmed to an appropriate state if the + * CORE clockdomain is to become inactive. + */ static struct clockdomain d2d_clkdm = { .name = "d2d_clkdm", .pwrdm_name = "core_pwrdm", .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; static struct clockdomain core_l3_34xx_clkdm = { -- GitLab From 5955902fb5c31f6a784ddb7aa16079a2bec588f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=B6gander=20Jouni?= Date: Tue, 19 Aug 2008 11:08:45 +0300 Subject: [PATCH 0421/5416] ARM: OMAP2: Clock: Combine 34xx l3_icks and l4_icks E.g dss_l3_ick and dss_l4_ick have same gating control. Having own clock for both of them causes race condition between enable / disable. This patch combines this kind of clocks and names new clock as _ick. Signed-off-by: Jouni Hogander Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock34xx.h | 62 +++++++++++++-------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index bb01e201481..c38a8a09692 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1189,27 +1189,34 @@ static const struct clksel gfx_l3_clksel[] = { { .parent = NULL } }; -static struct clk gfx_l3_fck = { - .name = "gfx_l3_fck", +/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */ +static struct clk gfx_l3_ck = { + .name = "gfx_l3_ck", .parent = &l3_ick, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), .enable_bit = OMAP_EN_GFX_SHIFT, + .flags = CLOCK_IN_OMAP3430ES1, + .recalc = &followparent_recalc, +}; + +static struct clk gfx_l3_fck = { + .name = "gfx_l3_fck", + .parent = &gfx_l3_ck, + .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), .clksel_mask = OMAP_CLKSEL_GFX_MASK, .clksel = gfx_l3_clksel, - .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES, + .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES | + PARENT_CONTROLS_CLOCK, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk gfx_l3_ick = { .name = "gfx_l3_ick", - .parent = &l3_ick, - .init = &omap2_init_clk_clkdm, - .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), - .enable_bit = OMAP_EN_GFX_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, + .parent = &gfx_l3_ck, + .flags = CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -2153,19 +2160,9 @@ static struct clk cam_mclk = { .recalc = &omap2_clksel_recalc, }; -static struct clk cam_l3_ick = { - .name = "cam_l3_ick", - .parent = &l3_ick, - .init = &omap2_init_clk_clkdm, - .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), - .enable_bit = OMAP3430_EN_CAM_SHIFT, - .flags = CLOCK_IN_OMAP343X, - .clkdm_name = "cam_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk cam_l4_ick = { - .name = "cam_l4_ick", +static struct clk cam_ick = { + /* Handles both L3 and L4 clocks */ + .name = "cam_ick", .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), @@ -2199,19 +2196,9 @@ static struct clk usbhost_48m_fck = { .recalc = &followparent_recalc, }; -static struct clk usbhost_l3_ick = { - .name = "usbhost_l3_ick", - .parent = &l3_ick, - .init = &omap2_init_clk_clkdm, - .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), - .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, - .clkdm_name = "usbhost_clkdm", - .recalc = &followparent_recalc, -}; - -static struct clk usbhost_l4_ick = { - .name = "usbhost_l4_ick", +static struct clk usbhost_ick = { + /* Handles both L3 and L4 clocks */ + .name = "usbhost_ick", .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), @@ -3093,6 +3080,7 @@ static struct clk *onchip_34xx_clks[] __initdata = { &l3_ick, &l4_ick, &rm_ick, + &gfx_l3_ck, &gfx_l3_fck, &gfx_l3_ick, &gfx_cg1_ck, @@ -3174,12 +3162,10 @@ static struct clk *onchip_34xx_clks[] __initdata = { &dss2_alwon_fck, &dss_ick, &cam_mclk, - &cam_l3_ick, - &cam_l4_ick, + &cam_ick, &usbhost_120m_fck, &usbhost_48m_fck, - &usbhost_l3_ick, - &usbhost_l4_ick, + &usbhost_ick, &usbhost_sar_fck, &usim_fck, &gpt1_fck, -- GitLab From 0c925d79234fe77589d8ff3861f9f8bb9e7fc3f6 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Mon, 18 Aug 2008 21:49:51 -0700 Subject: [PATCH 0422/5416] rcuclassic: fix compilation NG fix: CC kernel/rcuclassic.o kernel/rcuclassic.c: In function '__rcu_process_callbacks': kernel/rcuclassic.c:561: error: 'flags' undeclared (first use in this function) kernel/rcuclassic.c:561: error: (Each undeclared identifier is reported only once kernel/rcuclassic.c:561: error: for each function it appears in.) Declare missing variable flags. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- kernel/rcuclassic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index c6b6cf55f3e..01e761a6b38 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -557,6 +557,8 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, local_irq_enable(); if (rcu_batch_after(rdp->batch, rcp->pending)) { + unsigned long flags; + /* and start it/schedule start if it's a new batch */ spin_lock_irqsave(&rcp->lock, flags); if (rcu_batch_after(rdp->batch, rcp->pending)) { -- GitLab From db0badc58e948b810c7a75cfcc48845e2949ee37 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 18 Aug 2008 13:40:18 +0200 Subject: [PATCH 0423/5416] udf: Fix lock inversion between iprune_mutex and alloc_mutex (v2) A memory allocation inside alloc_mutex must not recurse back into the filesystem itself because that leads to lock inversion between iprune_mutex and alloc_mutex (and thus to deadlocks - see traces below). alloc_mutex is actually needed only to update allocation statistics in the superblock so we can drop it before we start allocating memory for the inode. tar D ffff81015b9c8c90 0 6614 6612 ffff8100d5a21a20 0000000000000086 0000000000000000 00000000ffff0000 ffff81015b9c8c90 ffff81015b8f0cd0 ffff81015b9c8ee0 0000000000000000 0000000000000003 0000000000000000 0000000000000000 0000000000000000 Call Trace: [] __mutex_lock_slowpath+0x64/0x9b [] mutex_lock+0xa/0xb [] shrink_icache_memory+0x38/0x200 [] shrink_slab+0xe3/0x15b [] try_to_free_pages+0x221/0x30d [] isolate_pages_global+0x0/0x31 [] __alloc_pages_internal+0x252/0x3ab [] cache_alloc_refill+0x22e/0x47b [] kmem_cache_alloc+0x3b/0x61 [] cache_alloc_refill+0x2fe/0x47b [] __kmalloc+0x76/0x9c [] :udf:udf_new_inode+0x202/0x2e2 [] :udf:udf_create+0x2f/0x16d [] :udf:udf_lookup+0xa6/0xad ... kswapd0 D ffff81015b9d9270 0 125 2 ffff81015b903c28 0000000000000046 ffffffff8028cbb0 00000000fffffffb ffff81015b9d9270 ffff81015b8f0cd0 ffff81015b9d94c0 000000000271b490 ffffe2000271b458 ffffe2000271b420 ffffe20002728dc8 ffffe20002728d90 Call Trace: [] __set_page_dirty+0xeb/0xf5 [] get_dirty_limits+0x1d/0x22f [] __mutex_lock_slowpath+0x64/0x9b [] mutex_lock+0xa/0xb [] :udf:udf_bitmap_free_blocks+0x47/0x1eb [] :udf:udf_discard_prealloc+0xc6/0x172 [] :udf:udf_clear_inode+0x1e/0x48 [] clear_inode+0x6d/0xc4 [] dispose_list+0x56/0xee [] shrink_icache_memory+0x1d0/0x200 [] shrink_slab+0xe3/0x15b [] kswapd+0x346/0x447 ... Reported-by: Tibor Tajti Reviewed-by: Ingo Oeser Signed-off-by: Jan Kara --- fs/udf/ialloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index eb9cfa23dc3..c4943c8988c 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -111,6 +111,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(sbi->s_lvid_bh); } + mutex_unlock(&sbi->s_alloc_mutex); inode->i_mode = mode; inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { @@ -145,7 +146,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) if (!iinfo->i_ext.i_data) { iput(inode); *err = -ENOMEM; - mutex_unlock(&sbi->s_alloc_mutex); return NULL; } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) @@ -158,7 +158,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) iinfo->i_crtime = current_fs_time(inode->i_sb); insert_inode_hash(inode); mark_inode_dirty(inode); - mutex_unlock(&sbi->s_alloc_mutex); if (DQUOT_ALLOC_INODE(inode)) { DQUOT_DROP(inode); -- GitLab From 97e1cfb08616987878f91a46cefdd7fc5fa3dba1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 18 Aug 2008 13:44:48 +0200 Subject: [PATCH 0424/5416] udf: Fix error paths in udf_new_inode() I case we failed to allocate memory for inode when creating it, we did not properly free block already allocated for this inode. Move memory allocation before the block allocation which fixes this issue (thanks for the idea go to Ingo Oeser ). Also remove a few superfluous initializations already done in udf_alloc_inode(). Reviewed-by: Ingo Oeser Signed-off-by: Jan Kara --- fs/udf/ialloc.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index c4943c8988c..a4f2b3ce45b 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -76,11 +76,24 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) *err = -ENOSPC; iinfo = UDF_I(inode); - iinfo->i_unique = 0; - iinfo->i_lenExtents = 0; - iinfo->i_next_alloc_block = 0; - iinfo->i_next_alloc_goal = 0; - iinfo->i_strat4096 = 0; + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { + iinfo->i_efe = 1; + if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) + sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; + iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct extendedFileEntry), + GFP_KERNEL); + } else { + iinfo->i_efe = 0; + iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct fileEntry), + GFP_KERNEL); + } + if (!iinfo->i_ext.i_data) { + iput(inode); + *err = -ENOMEM; + return NULL; + } block = udf_new_block(dir->i_sb, NULL, dinfo->i_location.partitionReferenceNum, @@ -130,24 +143,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) iinfo->i_lenEAttr = 0; iinfo->i_lenAlloc = 0; iinfo->i_use = 0; - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { - iinfo->i_efe = 1; - if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) - sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry), - GFP_KERNEL); - } else { - iinfo->i_efe = 0; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct fileEntry), - GFP_KERNEL); - } - if (!iinfo->i_ext.i_data) { - iput(inode); - *err = -ENOMEM; - return NULL; - } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) -- GitLab From af4491e51632d01fbc2b856ffa9ebcd4b38db68c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 19 Aug 2008 12:33:02 +0200 Subject: [PATCH 0425/5416] sched: rt-bandwidth for user grouping interface rt_runtime is a signed value Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/user.c b/kernel/user.c index 865ecf57a09..39d6159fae4 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -169,7 +169,7 @@ static ssize_t cpu_rt_runtime_show(struct kobject *kobj, { struct user_struct *up = container_of(kobj, struct user_struct, kobj); - return sprintf(buf, "%lu\n", sched_group_rt_runtime(up->tg)); + return sprintf(buf, "%ld\n", sched_group_rt_runtime(up->tg)); } static ssize_t cpu_rt_runtime_store(struct kobject *kobj, @@ -180,7 +180,7 @@ static ssize_t cpu_rt_runtime_store(struct kobject *kobj, unsigned long rt_runtime; int rc; - sscanf(buf, "%lu", &rt_runtime); + sscanf(buf, "%ld", &rt_runtime); rc = sched_group_set_rt_runtime(up->tg, rt_runtime); -- GitLab From 6f0d5c390e4206dcb3804a5072a048fdb7d2b428 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 19 Aug 2008 12:33:03 +0200 Subject: [PATCH 0426/5416] sched: rt-bandwidth accounting fix It fixes an accounting bug where we would continue accumulating runtime even though the bandwidth control is disabled. This would lead to very long throttle periods once bandwidth control gets turned on again. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/sched_rt.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 998ba54b454..77340b04a53 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -438,9 +438,6 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) { u64 runtime = sched_rt_runtime(rt_rq); - if (runtime == RUNTIME_INF) - return 0; - if (rt_rq->rt_throttled) return rt_rq_throttled(rt_rq); @@ -491,9 +488,11 @@ static void update_curr_rt(struct rq *rq) rt_rq = rt_rq_of_se(rt_se); spin_lock(&rt_rq->rt_runtime_lock); - rt_rq->rt_time += delta_exec; - if (sched_rt_runtime_exceeded(rt_rq)) - resched_task(curr); + if (sched_rt_runtime(rt_rq) != RUNTIME_INF) { + rt_rq->rt_time += delta_exec; + if (sched_rt_runtime_exceeded(rt_rq)) + resched_task(curr); + } spin_unlock(&rt_rq->rt_runtime_lock); } } -- GitLab From 0b148fa04852859972abbf848177b92daeef138a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 19 Aug 2008 12:33:04 +0200 Subject: [PATCH 0427/5416] sched: rt-bandwidth group disable fixes More extensive disable of bandwidth control. It allows sysctl_sched_rt_runtime to disable full group bandwidth control. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/sched.c | 9 ++++++++- kernel/sched_rt.c | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 9a1ddb84e26..c1bee5fb815 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -204,11 +204,13 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; } +static inline int rt_bandwidth_enabled(void); + static void start_rt_bandwidth(struct rt_bandwidth *rt_b) { ktime_t now; - if (rt_b->rt_runtime == RUNTIME_INF) + if (rt_bandwidth_enabled() && rt_b->rt_runtime == RUNTIME_INF) return; if (hrtimer_active(&rt_b->rt_period_timer)) @@ -839,6 +841,11 @@ static inline u64 global_rt_runtime(void) return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC; } +static inline int rt_bandwidth_enabled(void) +{ + return sysctl_sched_rt_runtime >= 0; +} + #ifndef prepare_arch_switch # define prepare_arch_switch(next) do { } while (0) #endif diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 77340b04a53..94daace5ee1 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -386,7 +386,7 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) int i, idle = 1; cpumask_t span; - if (rt_b->rt_runtime == RUNTIME_INF) + if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) return 1; span = sched_rt_period_mask(); @@ -484,6 +484,9 @@ static void update_curr_rt(struct rq *rq) curr->se.exec_start = rq->clock; cpuacct_charge(curr, delta_exec); + if (!rt_bandwidth_enabled()) + return; + for_each_sched_rt_entity(rt_se) { rt_rq = rt_rq_of_se(rt_se); -- GitLab From eb755805f21bd5ded84026e167b7a90887ac42e5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 19 Aug 2008 12:33:05 +0200 Subject: [PATCH 0428/5416] sched: extract walk_tg_tree() Extract walk_tg_tree() and make it a little more generic so we can use it in the schedulablity test. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/sched.c | 79 +++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index c1bee5fb815..8c019a19d05 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1387,38 +1387,24 @@ static inline void dec_cpu_load(struct rq *rq, unsigned long load) update_load_sub(&rq->load, load); } -#ifdef CONFIG_SMP -static unsigned long source_load(int cpu, int type); -static unsigned long target_load(int cpu, int type); -static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); - -static unsigned long cpu_avg_load_per_task(int cpu) -{ - struct rq *rq = cpu_rq(cpu); - - if (rq->nr_running) - rq->avg_load_per_task = rq->load.weight / rq->nr_running; - - return rq->avg_load_per_task; -} - -#ifdef CONFIG_FAIR_GROUP_SCHED - -typedef void (*tg_visitor)(struct task_group *, int, struct sched_domain *); +#if (defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)) +typedef int (*tg_visitor)(struct task_group *, void *); /* * Iterate the full tree, calling @down when first entering a node and @up when * leaving it for the final time. */ -static void -walk_tg_tree(tg_visitor down, tg_visitor up, int cpu, struct sched_domain *sd) +static int walk_tg_tree(tg_visitor down, tg_visitor up, void *data) { struct task_group *parent, *child; + int ret; rcu_read_lock(); parent = &root_task_group; down: - (*down)(parent, cpu, sd); + ret = (*down)(parent, data); + if (ret) + goto out_unlock; list_for_each_entry_rcu(child, &parent->children, siblings) { parent = child; goto down; @@ -1426,14 +1412,42 @@ down: up: continue; } - (*up)(parent, cpu, sd); + ret = (*up)(parent, data); + if (ret) + goto out_unlock; child = parent; parent = parent->parent; if (parent) goto up; +out_unlock: rcu_read_unlock(); + + return ret; +} + +static int tg_nop(struct task_group *tg, void *data) +{ + return 0; } +#endif + +#ifdef CONFIG_SMP +static unsigned long source_load(int cpu, int type); +static unsigned long target_load(int cpu, int type); +static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); + +static unsigned long cpu_avg_load_per_task(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + if (rq->nr_running) + rq->avg_load_per_task = rq->load.weight / rq->nr_running; + + return rq->avg_load_per_task; +} + +#ifdef CONFIG_FAIR_GROUP_SCHED static void __set_se_shares(struct sched_entity *se, unsigned long shares); @@ -1493,11 +1507,11 @@ __update_group_shares_cpu(struct task_group *tg, int cpu, * This needs to be done in a bottom-up fashion because the rq weight of a * parent group depends on the shares of its child groups. */ -static void -tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) +static int tg_shares_up(struct task_group *tg, void *data) { unsigned long rq_weight = 0; unsigned long shares = 0; + struct sched_domain *sd = data; int i; for_each_cpu_mask(i, sd->span) { @@ -1522,6 +1536,8 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) __update_group_shares_cpu(tg, i, shares, rq_weight); spin_unlock_irqrestore(&rq->lock, flags); } + + return 0; } /* @@ -1529,10 +1545,10 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) * 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 void -tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) +static int tg_load_down(struct task_group *tg, void *data) { unsigned long load; + long cpu = (long)data; if (!tg->parent) { load = cpu_rq(cpu)->load.weight; @@ -1543,11 +1559,8 @@ tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) } tg->cfs_rq[cpu]->h_load = load; -} -static void -tg_nop(struct task_group *tg, int cpu, struct sched_domain *sd) -{ + return 0; } static void update_shares(struct sched_domain *sd) @@ -1557,7 +1570,7 @@ static void update_shares(struct sched_domain *sd) if (elapsed >= (s64)(u64)sysctl_sched_shares_ratelimit) { sd->last_update = now; - walk_tg_tree(tg_nop, tg_shares_up, 0, sd); + walk_tg_tree(tg_nop, tg_shares_up, sd); } } @@ -1568,9 +1581,9 @@ static void update_shares_locked(struct rq *rq, struct sched_domain *sd) spin_lock(&rq->lock); } -static void update_h_load(int cpu) +static void update_h_load(long cpu) { - walk_tg_tree(tg_load_down, tg_nop, cpu, NULL); + walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); } #else -- GitLab From 9a7e0b180da21885988d47558671cf580279f9d6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 19 Aug 2008 12:33:06 +0200 Subject: [PATCH 0429/5416] sched: rt-bandwidth fixes The last patch allows sysctl_sched_rt_runtime to disable bandwidth accounting for the group scheduler - however it doesn't deal with sched_setscheduler(), which will keep tasks out of groups that have no assigned runtime. If we relax this, we get into the situation where RT tasks can get into a group when we disable bandwidth control, and then starve them by enabling it again. Rework the schedulability code to check for this condition and fail to turn on bandwidth control with -EBUSY when this situation is found. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/sched.c | 125 +++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 8c019a19d05..e41bdae2778 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -300,9 +300,9 @@ static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp; static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity); static DEFINE_PER_CPU(struct rt_rq, init_rt_rq) ____cacheline_aligned_in_smp; #endif /* CONFIG_RT_GROUP_SCHED */ -#else /* !CONFIG_FAIR_GROUP_SCHED */ +#else /* !CONFIG_USER_SCHED */ #define root_task_group init_task_group -#endif /* CONFIG_FAIR_GROUP_SCHED */ +#endif /* CONFIG_USER_SCHED */ /* task_group_lock serializes add/remove of task groups and also changes to * a task group's cpu shares. @@ -1387,7 +1387,7 @@ static inline void dec_cpu_load(struct rq *rq, unsigned long load) update_load_sub(&rq->load, load); } -#if (defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)) +#if (defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)) || defined(SCHED_RT_GROUP_SCHED) typedef int (*tg_visitor)(struct task_group *, void *); /* @@ -5082,7 +5082,8 @@ recheck: * Do not allow realtime tasks into groups that have no runtime * assigned. */ - if (rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0) + if (rt_bandwidth_enabled() && rt_policy(policy) && + task_group(p)->rt_bandwidth.rt_runtime == 0) return -EPERM; #endif @@ -8707,73 +8708,77 @@ static DEFINE_MUTEX(rt_constraints_mutex); static unsigned long to_ratio(u64 period, u64 runtime) { if (runtime == RUNTIME_INF) - return 1ULL << 16; + return 1ULL << 20; - return div64_u64(runtime << 16, period); + return div64_u64(runtime << 20, period); } -#ifdef CONFIG_CGROUP_SCHED -static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) +/* Must be called with tasklist_lock held */ +static inline int tg_has_rt_tasks(struct task_group *tg) { - struct task_group *tgi, *parent = tg->parent; - unsigned long total = 0; + struct task_struct *g, *p; - if (!parent) { - if (global_rt_period() < period) - return 0; + do_each_thread(g, p) { + if (rt_task(p) && rt_rq_of_se(&p->rt)->tg == tg) + return 1; + } while_each_thread(g, p); - return to_ratio(period, runtime) < - to_ratio(global_rt_period(), global_rt_runtime()); - } + return 0; +} - if (ktime_to_ns(parent->rt_bandwidth.rt_period) < period) - return 0; +struct rt_schedulable_data { + struct task_group *tg; + u64 rt_period; + u64 rt_runtime; +}; - rcu_read_lock(); - list_for_each_entry_rcu(tgi, &parent->children, siblings) { - if (tgi == tg) - continue; +static int tg_schedulable(struct task_group *tg, void *data) +{ + struct rt_schedulable_data *d = data; + struct task_group *child; + unsigned long total, sum = 0; + u64 period, runtime; + + period = ktime_to_ns(tg->rt_bandwidth.rt_period); + runtime = tg->rt_bandwidth.rt_runtime; - total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period), - tgi->rt_bandwidth.rt_runtime); + if (tg == d->tg) { + period = d->rt_period; + runtime = d->rt_runtime; } - rcu_read_unlock(); - return total + to_ratio(period, runtime) <= - to_ratio(ktime_to_ns(parent->rt_bandwidth.rt_period), - parent->rt_bandwidth.rt_runtime); -} -#elif defined CONFIG_USER_SCHED -static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) -{ - struct task_group *tgi; - unsigned long total = 0; - unsigned long global_ratio = - to_ratio(global_rt_period(), global_rt_runtime()); + if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg)) + return -EBUSY; - rcu_read_lock(); - list_for_each_entry_rcu(tgi, &task_groups, list) { - if (tgi == tg) - continue; + total = to_ratio(period, runtime); - total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period), - tgi->rt_bandwidth.rt_runtime); + list_for_each_entry_rcu(child, &tg->children, siblings) { + period = ktime_to_ns(child->rt_bandwidth.rt_period); + runtime = child->rt_bandwidth.rt_runtime; + + if (child == d->tg) { + period = d->rt_period; + runtime = d->rt_runtime; + } + + sum += to_ratio(period, runtime); } - rcu_read_unlock(); - return total + to_ratio(period, runtime) < global_ratio; + if (sum > total) + return -EINVAL; + + return 0; } -#endif -/* Must be called with tasklist_lock held */ -static inline int tg_has_rt_tasks(struct task_group *tg) +static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) { - struct task_struct *g, *p; - do_each_thread(g, p) { - if (rt_task(p) && rt_rq_of_se(&p->rt)->tg == tg) - return 1; - } while_each_thread(g, p); - return 0; + struct rt_schedulable_data data = { + .tg = tg, + .rt_period = period, + .rt_runtime = runtime, + }; + + return walk_tg_tree(tg_schedulable, tg_nop, &data); } static int tg_set_bandwidth(struct task_group *tg, @@ -8783,14 +8788,9 @@ static int tg_set_bandwidth(struct task_group *tg, mutex_lock(&rt_constraints_mutex); read_lock(&tasklist_lock); - if (rt_runtime == 0 && tg_has_rt_tasks(tg)) { - err = -EBUSY; + err = __rt_schedulable(tg, rt_period, rt_runtime); + if (err) goto unlock; - } - if (!__rt_schedulable(tg, rt_period, rt_runtime)) { - err = -EINVAL; - goto unlock; - } spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock); tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period); @@ -8867,8 +8867,9 @@ static int sched_rt_global_constraints(void) rt_runtime = tg->rt_bandwidth.rt_runtime; mutex_lock(&rt_constraints_mutex); - if (!__rt_schedulable(tg, rt_period, rt_runtime)) - ret = -EINVAL; + read_lock(&tasklist_lock); + ret = __rt_schedulable(tg, rt_period, rt_runtime); + read_unlock(&tasklist_lock); mutex_unlock(&rt_constraints_mutex); return ret; -- GitLab From 7dc964148c2850e5df84fc17807ba48edb628c88 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Tue, 19 Aug 2008 12:14:21 +0100 Subject: [PATCH 0430/5416] [ARM] eseries: Split machine definitions This patchset breaks out the e-series machine definitions into one-per-machine. Signed-off-by: Ian Molton --- arch/arm/mach-pxa/Makefile | 10 ++- arch/arm/mach-pxa/e330.c | 36 +++++++++ arch/arm/mach-pxa/e350.c | 36 +++++++++ arch/arm/mach-pxa/e400.c | 60 ++++++++++++++ arch/arm/mach-pxa/e740.c | 81 +++++++++++++++++++ arch/arm/mach-pxa/e750.c | 36 +++++++++ arch/arm/mach-pxa/e800.c | 36 +++++++++ arch/arm/mach-pxa/eseries.c | 151 +----------------------------------- arch/arm/mach-pxa/eseries.h | 3 + 9 files changed, 295 insertions(+), 154 deletions(-) create mode 100644 arch/arm/mach-pxa/e330.c create mode 100644 arch/arm/mach-pxa/e350.c create mode 100644 arch/arm/mach-pxa/e400.c create mode 100644 arch/arm/mach-pxa/e740.c create mode 100644 arch/arm/mach-pxa/e750.c create mode 100644 arch/arm/mach-pxa/e800.c create mode 100644 arch/arm/mach-pxa/eseries.h diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 99ecbe7f850..38db581b9fc 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -38,10 +38,12 @@ obj-$(CONFIG_MACH_TOSA) += tosa.o obj-$(CONFIG_MACH_EM_X270) += em-x270.o obj-$(CONFIG_MACH_MAGICIAN) += magician.o obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o eseries_udc.o -obj-$(CONFIG_MACH_E740) += e740_lcd.o -obj-$(CONFIG_MACH_E750) += e750_lcd.o -obj-$(CONFIG_MACH_E400) += e400_lcd.o -obj-$(CONFIG_MACH_E800) += e800_lcd.o +obj-$(CONFIG_MACH_E330) += e330.o +obj-$(CONFIG_MACH_E350) += e350.o +obj-$(CONFIG_MACH_E740) += e740.o e740_lcd.o +obj-$(CONFIG_MACH_E750) += e750.o e750_lcd.o +obj-$(CONFIG_MACH_E400) += e400.o e400_lcd.o +obj-$(CONFIG_MACH_E800) += e800.o e800_lcd.o obj-$(CONFIG_MACH_PALMTX) += palmtx.o ifeq ($(CONFIG_MACH_ZYLONITE),y) diff --git a/arch/arm/mach-pxa/e330.c b/arch/arm/mach-pxa/e330.c new file mode 100644 index 00000000000..2f4555e2fb9 --- /dev/null +++ b/arch/arm/mach-pxa/e330.c @@ -0,0 +1,36 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +MACHINE_START(E330, "Toshiba e330") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/e350.c b/arch/arm/mach-pxa/e350.c new file mode 100644 index 00000000000..5d58deb7eff --- /dev/null +++ b/arch/arm/mach-pxa/e350.c @@ -0,0 +1,36 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +MACHINE_START(E350, "Toshiba e350") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/e400.c b/arch/arm/mach-pxa/e400.c new file mode 100644 index 00000000000..405e6dcfc3c --- /dev/null +++ b/arch/arm/mach-pxa/e400.c @@ -0,0 +1,60 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +static unsigned long e400_pin_config[] __initdata = { + /* Chip selects */ + GPIO15_nCS_1, /* CS1 - Flash */ + GPIO80_nCS_4, /* CS4 - TMIO */ + + /* Clocks */ + GPIO12_32KHz, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* wakeup */ + GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, +}; + +static void __init e400_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(e400_pin_config)); +} + +MACHINE_START(E400, "Toshiba e400") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .init_machine = e400_init, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c new file mode 100644 index 00000000000..560a8a2ebff --- /dev/null +++ b/arch/arm/mach-pxa/e740.c @@ -0,0 +1,81 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +static unsigned long e740_pin_config[] __initdata = { + /* Chip selects */ + GPIO15_nCS_1, /* CS1 - Flash */ + GPIO79_nCS_3, /* CS3 - IMAGEON */ + GPIO80_nCS_4, /* CS4 - TMIO */ + + /* Clocks */ + GPIO12_32KHz, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* PC Card */ + GPIO8_GPIO, /* CD0 */ + GPIO44_GPIO, /* CD1 */ + GPIO11_GPIO, /* IRQ0 */ + GPIO6_GPIO, /* IRQ1 */ + GPIO27_GPIO, /* RST0 */ + GPIO24_GPIO, /* RST1 */ + GPIO20_GPIO, /* PWR0 */ + GPIO23_GPIO, /* PWR1 */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO52_nPCE_1, + GPIO53_nPCE_2, + GPIO54_nPSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + + /* wakeup */ + GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, +}; + +static void __init e740_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config)); +} + +MACHINE_START(E740, "Toshiba e740") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .init_machine = e740_init, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c new file mode 100644 index 00000000000..bb6f814d564 --- /dev/null +++ b/arch/arm/mach-pxa/e750.c @@ -0,0 +1,36 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +MACHINE_START(E750, "Toshiba e750") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c new file mode 100644 index 00000000000..77ebe91c3e6 --- /dev/null +++ b/arch/arm/mach-pxa/e800.c @@ -0,0 +1,36 @@ +/* + * Hardware definitions for the Toshiba eseries PDAs + * + * Copyright (c) 2003 Ian Molton + * + * 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 "generic.h" +#include "eseries.h" + +MACHINE_START(E800, "Toshiba e800") + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index 001a252bd51..1872faa11a2 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -22,65 +22,8 @@ #include "generic.h" -static unsigned long e740_pin_config[] __initdata = { - /* Chip selects */ - GPIO15_nCS_1, /* CS1 - Flash */ - GPIO79_nCS_3, /* CS3 - IMAGEON */ - GPIO80_nCS_4, /* CS4 - TMIO */ - - /* Clocks */ - GPIO12_32KHz, - - /* BTUART */ - GPIO42_BTUART_RXD, - GPIO43_BTUART_TXD, - GPIO44_BTUART_CTS, - GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ - - /* PC Card */ - GPIO8_GPIO, /* CD0 */ - GPIO44_GPIO, /* CD1 */ - GPIO11_GPIO, /* IRQ0 */ - GPIO6_GPIO, /* IRQ1 */ - GPIO27_GPIO, /* RST0 */ - GPIO24_GPIO, /* RST1 */ - GPIO20_GPIO, /* PWR0 */ - GPIO23_GPIO, /* PWR1 */ - GPIO48_nPOE, - GPIO49_nPWE, - GPIO50_nPIOR, - GPIO51_nPIOW, - GPIO52_nPCE_1, - GPIO53_nPCE_2, - GPIO54_nPSKTSEL, - GPIO55_nPREG, - GPIO56_nPWAIT, - GPIO57_nIOIS16, - - /* wakeup */ - GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, -}; - -static unsigned long e400_pin_config[] __initdata = { - /* Chip selects */ - GPIO15_nCS_1, /* CS1 - Flash */ - GPIO80_nCS_4, /* CS4 - TMIO */ - - /* Clocks */ - GPIO12_32KHz, - - /* BTUART */ - GPIO42_BTUART_RXD, - GPIO43_BTUART_TXD, - GPIO44_BTUART_CTS, - GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ - - /* wakeup */ - GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, -}; - /* Only e800 has 128MB RAM */ -static void __init eseries_fixup(struct machine_desc *desc, +void __init eseries_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) { mi->nr_banks=1; @@ -92,95 +35,3 @@ static void __init eseries_fixup(struct machine_desc *desc, mi->bank[0].size = (64*1024*1024); } -static void __init e740_init(void) -{ - pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config)); -} - -static void __init e400_init(void) -{ - pxa2xx_mfp_config(ARRAY_AND_SIZE(e400_pin_config)); -} - -/* e-series machine definitions */ - -#ifdef CONFIG_MACH_E330 -MACHINE_START(E330, "Toshiba e330") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_E350 -MACHINE_START(E350, "Toshiba e350") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_E740 -MACHINE_START(E740, "Toshiba e740") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .init_machine = e740_init, - .timer = &pxa_timer, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_E750 -MACHINE_START(E750, "Toshiba e750") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_E400 -MACHINE_START(E400, "Toshiba e400") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .init_machine = e400_init, - .timer = &pxa_timer, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_E800 -MACHINE_START(E800, "Toshiba e800") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, -MACHINE_END -#endif - diff --git a/arch/arm/mach-pxa/eseries.h b/arch/arm/mach-pxa/eseries.h new file mode 100644 index 00000000000..bc74e21d054 --- /dev/null +++ b/arch/arm/mach-pxa/eseries.h @@ -0,0 +1,3 @@ +void __init eseries_fixup(struct machine_desc *desc, + struct tag *tags, char **cmdline, struct meminfo *mi); + -- GitLab From 0ec3cf69304d2e35ad29da3aa9ab43c3dd97677c Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Tue, 19 Aug 2008 13:01:28 +0100 Subject: [PATCH 0431/5416] [ARM] eseries: move LCD defs into machine files This patch removes the seperate files used for the LCD definitions on e-series and places the definitions into the machine specific files. Signed-off-by: Ian Molton --- arch/arm/mach-pxa/Makefile | 8 +- arch/arm/mach-pxa/e400.c | 32 +++++++ arch/arm/mach-pxa/e400_lcd.c | 56 ------------ arch/arm/mach-pxa/e740.c | 86 +++++++++++++++++++ arch/arm/mach-pxa/e740_lcd.c | 123 --------------------------- arch/arm/mach-pxa/e750.c | 88 +++++++++++++++++++ arch/arm/mach-pxa/e750_lcd.c | 109 ------------------------ arch/arm/mach-pxa/e800.c | 139 ++++++++++++++++++++++++++++++ arch/arm/mach-pxa/e800_lcd.c | 159 ----------------------------------- 9 files changed, 349 insertions(+), 451 deletions(-) delete mode 100644 arch/arm/mach-pxa/e400_lcd.c delete mode 100644 arch/arm/mach-pxa/e740_lcd.c delete mode 100644 arch/arm/mach-pxa/e750_lcd.c delete mode 100644 arch/arm/mach-pxa/e800_lcd.c diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 38db581b9fc..b536a50c150 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -40,10 +40,10 @@ obj-$(CONFIG_MACH_MAGICIAN) += magician.o obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o eseries_udc.o obj-$(CONFIG_MACH_E330) += e330.o obj-$(CONFIG_MACH_E350) += e350.o -obj-$(CONFIG_MACH_E740) += e740.o e740_lcd.o -obj-$(CONFIG_MACH_E750) += e750.o e750_lcd.o -obj-$(CONFIG_MACH_E400) += e400.o e400_lcd.o -obj-$(CONFIG_MACH_E800) += e800.o e800_lcd.o +obj-$(CONFIG_MACH_E740) += e740.o +obj-$(CONFIG_MACH_E750) += e750.o +obj-$(CONFIG_MACH_E400) += e400.o +obj-$(CONFIG_MACH_E800) += e800.o obj-$(CONFIG_MACH_PALMTX) += palmtx.o ifeq ($(CONFIG_MACH_ZYLONITE),y) diff --git a/arch/arm/mach-pxa/e400.c b/arch/arm/mach-pxa/e400.c index 405e6dcfc3c..0bcf9ece3d3 100644 --- a/arch/arm/mach-pxa/e400.c +++ b/arch/arm/mach-pxa/e400.c @@ -17,12 +17,41 @@ #include #include +#include #include #include +#include + #include "generic.h" #include "eseries.h" +/* ------------------------ E400 LCD definitions ------------------------ */ + +static struct pxafb_mode_info e400_pxafb_mode_info = { + .pixclock = 140703, + .xres = 240, + .yres = 320, + .bpp = 16, + .hsync_len = 4, + .left_margin = 28, + .right_margin = 8, + .vsync_len = 3, + .upper_margin = 5, + .lower_margin = 6, + .sync = 0, +}; + +static struct pxafb_mach_info e400_pxafb_mach_info = { + .modes = &e400_pxafb_mode_info, + .num_modes = 1, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = 0, + .pxafb_backlight_power = NULL, +}; + +/* ------------------------ E400 MFP config ----------------------------- */ + static unsigned long e400_pin_config[] __initdata = { /* Chip selects */ GPIO15_nCS_1, /* CS1 - Flash */ @@ -41,9 +70,12 @@ static unsigned long e400_pin_config[] __initdata = { GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, }; +/* ---------------------------------------------------------------------- */ + static void __init e400_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(e400_pin_config)); + set_pxa_fb_info(&e400_pxafb_mach_info); } MACHINE_START(E400, "Toshiba e400") diff --git a/arch/arm/mach-pxa/e400_lcd.c b/arch/arm/mach-pxa/e400_lcd.c deleted file mode 100644 index 263884165f5..00000000000 --- a/arch/arm/mach-pxa/e400_lcd.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * e400_lcd.c - * - * (c) 2005 Ian Molton - * - * 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 - -static struct pxafb_mode_info e400_pxafb_mode_info = { - .pixclock = 140703, - .xres = 240, - .yres = 320, - .bpp = 16, - .hsync_len = 4, - .left_margin = 28, - .right_margin = 8, - .vsync_len = 3, - .upper_margin = 5, - .lower_margin = 6, - .sync = 0, -}; - -static struct pxafb_mach_info e400_pxafb_mach_info = { - .modes = &e400_pxafb_mode_info, - .num_modes = 1, - .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - .lccr3 = 0, - .pxafb_backlight_power = NULL, -}; - -static int __init e400_lcd_init(void) -{ - if (!machine_is_e400()) - return -ENODEV; - - set_pxa_fb_info(&e400_pxafb_mach_info); - return 0; -} - -module_init(e400_lcd_init); - -MODULE_AUTHOR("Ian Molton "); -MODULE_DESCRIPTION("e400 lcd driver"); -MODULE_LICENSE("GPLv2"); - diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c index 560a8a2ebff..ef0c3c80e79 100644 --- a/arch/arm/mach-pxa/e740.c +++ b/arch/arm/mach-pxa/e740.c @@ -12,6 +12,11 @@ #include #include +#include +#include +#include + +#include -!Finclude/net/mac80211.h ieee80211_if_types !Finclude/net/mac80211.h ieee80211_if_init_conf !Finclude/net/mac80211.h ieee80211_if_conf @@ -177,8 +176,7 @@ usage should require reading the full document. functions/definitions !Finclude/net/mac80211.h ieee80211_rx_status !Finclude/net/mac80211.h mac80211_rx_flags -!Finclude/net/mac80211.h ieee80211_tx_control -!Finclude/net/mac80211.h ieee80211_tx_status_flags +!Finclude/net/mac80211.h ieee80211_tx_info !Finclude/net/mac80211.h ieee80211_rx !Finclude/net/mac80211.h ieee80211_rx_irqsafe !Finclude/net/mac80211.h ieee80211_tx_status @@ -189,12 +187,11 @@ usage should require reading the full document. !Finclude/net/mac80211.h ieee80211_ctstoself_duration !Finclude/net/mac80211.h ieee80211_generic_frame_duration !Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb -!Finclude/net/mac80211.h ieee80211_get_hdrlen +!Finclude/net/mac80211.h ieee80211_hdrlen !Finclude/net/mac80211.h ieee80211_wake_queue !Finclude/net/mac80211.h ieee80211_stop_queue -!Finclude/net/mac80211.h ieee80211_start_queues -!Finclude/net/mac80211.h ieee80211_stop_queues !Finclude/net/mac80211.h ieee80211_wake_queues +!Finclude/net/mac80211.h ieee80211_stop_queues @@ -230,8 +227,7 @@ usage should require reading the full document. Multiple queues and QoS support TBD !Finclude/net/mac80211.h ieee80211_tx_queue_params -!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data -!Finclude/net/mac80211.h ieee80211_tx_queue +!Finclude/net/mac80211.h ieee80211_tx_queue_stats -- GitLab From c1b6cf4ee0fb8a3698c563e101a60f9ee4910de0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 11:05:39 +0200 Subject: [PATCH 1900/5416] mac80211: remove beacon counters The beacon counters mac80211 keeps are only used for debugfs, unfortunately, they are incorrect for many hardware designs, namely any design that has a beacon template. Hence, remove the counters so we don't create the impression they are usable. This also allows removing the beacon MESH #ifdef again. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 6 ------ net/mac80211/ieee80211_i.h | 5 ----- net/mac80211/tx.c | 9 --------- 3 files changed, 20 deletions(-) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 1b33cad24ab..2a451562377 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -173,7 +173,6 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC); IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); -IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC); static ssize_t ieee80211_if_fmt_flags( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -192,7 +191,6 @@ __IEEE80211_IF_FILE(flags); /* AP attributes */ IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); -IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); static ssize_t ieee80211_if_fmt_num_buffered_multicast( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -265,7 +263,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(auth_alg, sta); DEBUGFS_ADD(auth_transaction, sta); DEBUGFS_ADD(flags, sta); - DEBUGFS_ADD(num_beacons_sta, sta); } static void add_ap_files(struct ieee80211_sub_if_data *sdata) @@ -276,7 +273,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(num_sta_ps, ap); DEBUGFS_ADD(dtim_count, ap); - DEBUGFS_ADD(num_beacons, ap); DEBUGFS_ADD(num_buffered_multicast, ap); } @@ -398,7 +394,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_DEL(auth_alg, sta); DEBUGFS_DEL(auth_transaction, sta); DEBUGFS_DEL(flags, sta); - DEBUGFS_DEL(num_beacons_sta, sta); } static void del_ap_files(struct ieee80211_sub_if_data *sdata) @@ -409,7 +404,6 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_DEL(num_sta_ps, ap); DEBUGFS_DEL(dtim_count, ap); - DEBUGFS_DEL(num_beacons, ap); DEBUGFS_DEL(num_buffered_multicast, ap); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6bd6a6306da..3912fba6d3d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -229,7 +229,6 @@ struct ieee80211_if_ap { struct sk_buff_head ps_bc_buf; atomic_t num_sta_ps; /* number of stations in PS mode */ int dtim_count; - int num_beacons; /* number of TXed beacon frames for this BSS */ }; struct ieee80211_if_wds { @@ -352,7 +351,6 @@ struct ieee80211_if_sta { u32 supp_rates_bits[IEEE80211_NUM_BANDS]; int wmm_last_param_set; - int num_beacons; /* number of TXed beacon frames by this STA */ }; struct ieee80211_if_mesh { @@ -388,7 +386,6 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; - int num_beacons; }; #ifdef CONFIG_MAC80211_MESH @@ -484,7 +481,6 @@ struct ieee80211_sub_if_data { struct dentry *auth_alg; struct dentry *auth_transaction; struct dentry *flags; - struct dentry *num_beacons_sta; struct dentry *force_unicast_rateidx; struct dentry *max_ratectrl_rateidx; } sta; @@ -492,7 +488,6 @@ struct ieee80211_sub_if_data { struct dentry *drop_unencrypted; struct dentry *num_sta_ps; struct dentry *dtim_count; - struct dentry *num_beacons; struct dentry *force_unicast_rateidx; struct dentry *max_ratectrl_rateidx; struct dentry *num_buffered_multicast; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c12f361d718..d136a371e6b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1864,7 +1864,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct rate_selection rsel; struct beacon_data *beacon; struct ieee80211_supported_band *sband; - int *num_beacons; enum ieee80211_band band = local->hw.conf.channel->band; sband = local->hw.wiphy->bands[band]; @@ -1912,8 +1911,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, if (beacon->tail) memcpy(skb_put(skb, beacon->tail_len), beacon->tail, beacon->tail_len); - - num_beacons = &ap->num_beacons; } else goto out; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { @@ -1931,8 +1928,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - num_beacons = &ifsta->num_beacons; -#ifdef CONFIG_MAC80211_MESH } else if (ieee80211_vif_is_mesh(&sdata->vif)) { struct ieee80211_mgmt *mgmt; u8 *pos; @@ -1960,9 +1955,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, *pos++ = 0x0; mesh_mgmt_ies_add(skb, sdata); - - num_beacons = &sdata->u.mesh.num_beacons; -#endif } else { WARN_ON(1); goto out; @@ -1999,7 +1991,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; info->control.retry_limit = 1; - (*num_beacons)++; out: rcu_read_unlock(); return skb; -- GitLab From 538df283c185c477dbdafafa9652c33e9742de75 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 15:22:53 +0200 Subject: [PATCH 1901/5416] mac80211: remove debug frame dumping You can just pull up a monitor interface to get much more detailed information, or, when debugging a driver, insert dump code into the driver (which usually you will have to do anyway to dump the driver-specific information). Hence this option is useless. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 13 ------------- net/mac80211/tx.c | 42 ------------------------------------------ 2 files changed, 55 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 80d693392b0..8427518e4f2 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -179,19 +179,6 @@ config MAC80211_VERBOSE_MPL_DEBUG Do not select this option. -config MAC80211_LOWTX_FRAME_DUMP - bool "Debug frame dumping" - depends on MAC80211_DEBUG_MENU - ---help--- - Selecting this option will cause the stack to - print a message for each frame that is handed - to the lowlevel driver for transmission. This - message includes all MAC addresses and the - frame control field. - - If unsure, say N and insert the debugging code - you require into the driver you are debugging. - config MAC80211_DEBUG_COUNTERS bool "Extra statistics for TX/RX debugging" depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d136a371e6b..20d683641b4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -38,43 +38,6 @@ /* misc utils */ -#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP -static void ieee80211_dump_frame(const char *ifname, const char *title, - const struct sk_buff *skb) -{ - const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; - DECLARE_MAC_BUF(mac); - - printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); - if (skb->len < 4) { - printk("\n"); - return; - } - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (hdrlen > skb->len) - hdrlen = skb->len; - if (hdrlen >= 4) - printk(" FC=0x%04x DUR=0x%04x", - le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); - if (hdrlen >= 10) - printk(" A1=%s", print_mac(mac, hdr->addr1)); - if (hdrlen >= 16) - printk(" A2=%s", print_mac(mac, hdr->addr2)); - if (hdrlen >= 24) - printk(" A3=%s", print_mac(mac, hdr->addr3)); - if (hdrlen >= 30) - printk(" A4=%s", print_mac(mac, hdr->addr4)); - printk("\n"); -} -#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ -static inline void ieee80211_dump_frame(const char *ifname, const char *title, - struct sk_buff *skb) -{ -} -#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ - static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, int next_frag_len) { @@ -1068,8 +1031,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, return IEEE80211_TX_AGAIN; info = IEEE80211_SKB_CB(skb); - ieee80211_dump_frame(wiphy_name(local->hw.wiphy), - "TX to low-level driver", skb); ret = local->ops->tx(local_to_hw(local), skb); if (ret) return IEEE80211_TX_AGAIN; @@ -1099,9 +1060,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; } - ieee80211_dump_frame(wiphy_name(local->hw.wiphy), - "TX to low-level driver", - tx->extra_frag[i]); ret = local->ops->tx(local_to_hw(local), tx->extra_frag[i]); if (ret) -- GitLab From e16ce63c893ff7ccb314d2fbdafbbc915b64d173 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 12 Sep 2008 13:44:08 -0700 Subject: [PATCH 1902/5416] mac80211 : Fix mode change hard_start_xmit function When monitor mode is changed to BSS or IBSS, data trasnfer can not happen because proper transmit function is not assigend for BSS ,IBSS mode. This patch fixes this problem by assigning the ieee80211_subif_start_xmit to device's hard_start_xmit function. Signed-off-by: Abhijeet Kolekar Acked-by: Zhu Yi Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a7ef0289fbd..a72fbebb8ea 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -624,6 +624,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, /* and set some type-dependent values */ sdata->vif.type = type; + sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; -- GitLab From 75d31cf19fe8f86b4612561c94dfbb6d8a472ba3 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Fri, 12 Sep 2008 22:28:18 +0100 Subject: [PATCH 1903/5416] orinoco: Fix compile warnings Use min_t to avoid warnings when the typesafe version is used. Explicitly cast u64s to unsigned long long when being passed to printk. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index ec0451cbb8e..9a2fcc0163d 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -4777,14 +4777,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev, encoding->flags |= IW_ENCODE_DISABLED; break; case IW_ENCODE_ALG_WEP: - ext->key_len = min(le16_to_cpu(priv->keys[idx].len), - (u16) max_key_len); + ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len), + max_key_len); memcpy(ext->key, priv->keys[idx].data, ext->key_len); encoding->flags |= IW_ENCODE_ENABLED; break; case IW_ENCODE_ALG_TKIP: - ext->key_len = min((u16) sizeof(struct orinoco_tkip_key), - (u16) max_key_len); + ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key), + max_key_len); memcpy(ext->key, &priv->tkip_key[idx], ext->key_len); encoding->flags |= IW_ENCODE_ENABLED; break; @@ -5686,9 +5686,9 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev, /* Timestamp */ iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, - "tsf=%016llx", - le64_to_cpu(bss->timestamp)); + iwe.u.data.length = + snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx", + (unsigned long long) le64_to_cpu(bss->timestamp)); if (iwe.u.data.length) current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, custom); -- GitLab From 29bdc88384c2b24e37e5760df0dc898546083d6b Mon Sep 17 00:00:00 2001 From: Vladimir Sokolovsky Date: Mon, 15 Sep 2008 14:25:23 -0700 Subject: [PATCH 1904/5416] IB/mlx4: Fix up fast register page list format Byte swap the addresses in the page list for fast register work requests to big endian to match what the HCA expectx. Also, the addresses must have the "present" bit set so that the HCA knows it can access them. Otherwise the HCA will fault the first time it accesses the memory region. Signed-off-by: Vladimir Sokolovsky Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/qp.c | 6 ++++++ drivers/net/mlx4/mr.c | 2 -- include/linux/mlx4/device.h | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index f29dbb767e8..9559248f265 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1342,6 +1342,12 @@ static __be32 convert_access(int acc) static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr) { struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list); + int i; + + for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i) + wr->wr.fast_reg.page_list->page_list[i] = + cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] | + MLX4_MTT_FLAG_PRESENT); fseg->flags = convert_access(wr->wr.fast_reg.access_flags); fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey); diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 644adf074a3..d1dd5b48dbd 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -71,8 +71,6 @@ struct mlx4_mpt_entry { #define MLX4_MPT_PD_FLAG_RAE (1 << 28) #define MLX4_MPT_PD_FLAG_EN_INV (3 << 24) -#define MLX4_MTT_FLAG_PRESENT 1 - #define MLX4_MPT_STATUS_SW 0xF0 #define MLX4_MPT_STATUS_HW 0x00 diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 655ea0d1ee1..b2f94446831 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -141,6 +141,10 @@ enum { MLX4_STAT_RATE_OFFSET = 5 }; +enum { + MLX4_MTT_FLAG_PRESENT = 1 +}; + static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) { return (major << 32) | (minor << 16) | subminor; -- GitLab From 375da53b8e5e3ff2330b66b377e07a6151a93fe5 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 15 Sep 2008 17:25:54 -0400 Subject: [PATCH 1905/5416] libertas: correct "limited range of data type" warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/libertas/wext.o drivers/net/wireless/libertas/wext.c: In function ‘lbs_get_rts’: drivers/net/wireless/libertas/wext.c:307: warning: comparison is always false due to limited range of data type Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/wext.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 1156be53df3..11297dcf9fc 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -281,7 +281,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, if (vwrq->disabled) val = MRVDRV_RTS_MAX_VALUE; - if (val < MRVDRV_RTS_MIN_VALUE || val > MRVDRV_RTS_MAX_VALUE) + if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */ return -EINVAL; ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val); @@ -304,8 +304,7 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, goto out; vwrq->value = val; - vwrq->disabled = ((val < MRVDRV_RTS_MIN_VALUE) - || (val > MRVDRV_RTS_MAX_VALUE)); + vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */ vwrq->fixed = 1; out: -- GitLab From 5649b7c30316a51792808422ac03ee825d26aa5e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 09:29:09 +0200 Subject: [PATCH 1906/5416] x86: add DMI quirk for AMI BIOS which corrupts address 0xc000 during resume Alan Jenkins and Andy Wettstein reported a suspend/resume memory corruption bug and extensively documented it here: http://bugzilla.kernel.org/show_bug.cgi?id=11237 The bug is that the BIOS overwrites 1K of memory at 0xc000 physical, without registering it in e820 as reserved or giving the kernel any idea about this. Detect AMI BIOSen and reserve that 1K. We paint this bug around with a very broad brush (reserving that 1K on all AMI BIOS systems), as the bug was extremely hard to find and needed several weeks and lots of debugging and patching. The bug was found via the CONFIG_X86_CHECK_BIOS_CORRUPTION=y debug feature, if similar bugs are suspected then this feature can be enabled on other systems as well to scan low memory for corrupted memory. Reported-by: Alan Jenkins Reported-by: Andy Wettstein Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ec7e56c1b98..3109ca37a67 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -729,6 +729,29 @@ void start_periodic_check_for_corruption(void) } #endif +static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE + "%s detected: BIOS corrupts 0xc000, working it around.\n", + d->ident); + + reserve_early(0xc000, 0xc400, "BIOS quirk"); + + return 0; +} + +/* List of systems that have known low memory corruption BIOS problems */ +static struct dmi_system_id __initdata bad_bios_dmi_table[] = { + { + .callback = dmi_low_memory_corruption, + .ident = "AMI BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + }, + }, + {} +}; + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -752,6 +775,8 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Command line: %s\n", boot_command_line); #endif + dmi_check_system(bad_bios_dmi_table); + early_cpu_init(); early_ioremap_init(); @@ -1037,3 +1062,5 @@ void __init setup_arch(char **cmdline_p) #endif #endif } + + -- GitLab From 1e22436eba84edfec9c25e5a25d09062c4f91ca9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 09:58:02 +0200 Subject: [PATCH 1907/5416] x86: reserve low 64K on AMI and Phoenix BIOS boxen there's multiple reports about suspend/resume related low memory corruption in this bugzilla: http://bugzilla.kernel.org/show_bug.cgi?id=11237 the common pattern is that the corruption is caused by the BIOS, and that it affects some portion of the first 64K of physical RAM. So add a DMI quirk This will waste 64K RAM on 'good' systems too, but without knowing the exact nature of this BIOS memory corruption this is the safest approach. This might as well solve a wide range of suspend/resume breakages under Linux. Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 3109ca37a67..33719544a22 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -732,10 +732,10 @@ void start_periodic_check_for_corruption(void) static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) { printk(KERN_NOTICE - "%s detected: BIOS corrupts 0xc000, working it around.\n", + "%s detected: BIOS may corrupt low RAM, working it around.\n", d->ident); - reserve_early(0xc000, 0xc400, "BIOS quirk"); + reserve_early(0x0, 0x10000, "BIOS quirk"); return 0; } @@ -749,6 +749,13 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), }, }, + { + .callback = dmi_low_memory_corruption, + .ident = "Phoenix BIOS", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + }, + }, {} }; -- GitLab From a83479545d0e693da0886fd28d041d3a5c1bc966 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Mon, 15 Sep 2008 20:50:54 -0400 Subject: [PATCH 1908/5416] [MIPS] VR41xx: unsigned irq cannot be negative Signed-off-by: Roel Kluin Acked-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- arch/mips/vr41xx/common/irq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index cba36a247e3..92dd1a0ca35 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -72,6 +72,7 @@ static void irq_dispatch(unsigned int irq) cascade = irq_cascade + irq; if (cascade->get_irq != NULL) { unsigned int source_irq = irq; + int ret; desc = irq_desc + source_irq; if (desc->chip->mask_ack) desc->chip->mask_ack(source_irq); @@ -79,8 +80,9 @@ static void irq_dispatch(unsigned int irq) desc->chip->mask(source_irq); desc->chip->ack(source_irq); } - irq = cascade->get_irq(irq); - if (irq < 0) + ret = cascade->get_irq(irq); + irq = ret; + if (ret < 0) atomic_inc(&irq_err_count); else irq_dispatch(irq); -- GitLab From fc38151947477596aa27df6c4306ad6008dc6711 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 16 Sep 2008 10:07:34 +0200 Subject: [PATCH 1909/5416] x86: add X86_RESERVE_LOW_64K This bugzilla: http://bugzilla.kernel.org/show_bug.cgi?id=11237 Documents a wide range of systems where the BIOS utilizes the first 64K of physical memory during suspend/resume and other hardware events. Currently we reserve this memory on all AMI and Phoenix BIOS systems. Life is too short to hunt subtle memory corruption problems like this, so we try to be robust by default. Still, allow this to be overriden: allow users who want that first 64K of memory to be available to the kernel disable the quirk, via CONFIG_X86_RESERVE_LOW_64K=n. Also, allow the early reservation to overlap with other early reservations. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 20 ++++++++++++++++++++ arch/x86/kernel/setup.c | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7820d447bb8..633f25dd9ee 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1089,6 +1089,26 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK Set whether the default state of memory_corruption_check is on or off. +config X86_RESERVE_LOW_64K + bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" + default y + help + Reserve the first 64K of physical RAM on BIOSes that are known + to potentially corrupt that memory range. A numbers of BIOSes are + known to utilize this area during suspend/resume, so it must not + be used by the kernel. + + Set this to N if you are absolutely sure that you trust the BIOS + to get all its memory reservations and usages right. + + If you have doubts about the BIOS (e.g. suspend/resume does not + work or there's kernel crashes after certain hardware hotplug + events) and it's not AMI or Phoenix, then you might want to enable + X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical + corruption patterns. + + Say Y if unsure. + config MATH_EMULATION bool prompt "Math emulation" if X86_32 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 33719544a22..786c1886ae5 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -735,13 +735,14 @@ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) "%s detected: BIOS may corrupt low RAM, working it around.\n", d->ident); - reserve_early(0x0, 0x10000, "BIOS quirk"); + reserve_early_overlap_ok(0x0, 0x10000, "BIOS quirk"); return 0; } /* List of systems that have known low memory corruption BIOS problems */ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { +#ifdef CONFIG_X86_RESERVE_LOW_64K { .callback = dmi_low_memory_corruption, .ident = "AMI BIOS", @@ -757,6 +758,7 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { }, }, {} +#endif }; /* -- GitLab From e14d4af0c87af0be7f2d0e204e1922cf4fa3c19e Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 14 Jun 2008 21:02:04 +0200 Subject: [PATCH 1910/5416] powerpc: Add support for the MPC852 based mgsuvd board from keymile. Supported SMC1 (serial console), SCC3 Ethernet (10Mbps hdx). Signed-off-by: Heiko Schocher Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/mgsuvd.dts | 163 +++++ arch/powerpc/configs/mgsuvd_defconfig | 872 ++++++++++++++++++++++++++ arch/powerpc/platforms/8xx/Kconfig | 6 + arch/powerpc/platforms/8xx/Makefile | 1 + arch/powerpc/platforms/8xx/mgsuvd.c | 92 +++ 5 files changed, 1134 insertions(+) create mode 100644 arch/powerpc/boot/dts/mgsuvd.dts create mode 100644 arch/powerpc/configs/mgsuvd_defconfig create mode 100644 arch/powerpc/platforms/8xx/mgsuvd.c diff --git a/arch/powerpc/boot/dts/mgsuvd.dts b/arch/powerpc/boot/dts/mgsuvd.dts new file mode 100644 index 00000000000..e4fc53ab42b --- /dev/null +++ b/arch/powerpc/boot/dts/mgsuvd.dts @@ -0,0 +1,163 @@ +/* + * MGSUVD Device Tree Source + * + * Copyright 2008 DENX Software Engineering GmbH + * Heiko Schocher + * + * 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. + */ + +/dts-v1/; +/ { + model = "MGSUVD"; + compatible = "keymile,mgsuvd"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,852@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <16>; + i-cache-line-size = <16>; + d-cache-size = <8192>; + i-cache-size = <8192>; + timebase-frequency = <0>; /* Filled in by u-boot */ + bus-frequency = <0>; /* Filled in by u-boot */ + clock-frequency = <0>; /* Filled in by u-boot */ + interrupts = <15 2>; /* decrementer interrupt */ + interrupt-parent = <&PIC>; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 0x4000000>; /* Filled in by u-boot */ + }; + + localbus@fff00100 { + compatible = "fsl,mpc852-localbus", "fsl,pq1-localbus", "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + reg = <0xfff00100 0x40>; + + ranges = <0 0 0xf0000000 0x01000000>; /* Filled in by u-boot */ + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x1000000>; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <1>; + device-width = <1>; + partition@0 { + label = "u-boot"; + reg = <0 0x80000>; + }; + partition@80000 { + label = "env"; + reg = <0x80000 0x20000>; + }; + partition@a0000 { + label = "kernel"; + reg = <0xa0000 0x1e0000>; + }; + partition@280000 { + label = "dtb"; + reg = <0x280000 0x20000>; + }; + partition@2a0000 { + label = "root"; + reg = <0x2a0000 0x500000>; + }; + partition@7a0000 { + label = "user"; + reg = <0x7a0000 0x860000>; + }; + }; + }; + + soc@fff00000 { + compatible = "fsl,mpc852", "fsl,pq1-soc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + ranges = <0 0xfff00000 0x00004000>; + + PIC: interrupt-controller@0 { + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 24>; + compatible = "fsl,mpc852-pic", "fsl,pq1-pic"; + }; + + cpm@9c0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc852-cpm", "fsl,cpm1", "simple-bus"; + interrupts = <0>; /* cpm error interrupt */ + interrupt-parent = <&CPM_PIC>; + reg = <0x9c0 10>; + ranges; + + muram@2000 { + compatible = "fsl,cpm-muram"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x2000 0x2000>; + + data@0 { + compatible = "fsl,cpm-muram-data"; + reg = <0x800 0x1800>; + }; + }; + + brg@9f0 { + compatible = "fsl,mpc852-brg", + "fsl,cpm1-brg", + "fsl,cpm-brg"; + reg = <0x9f0 0x10>; + clock-frequency = <0>; /* Filled in by u-boot */ + }; + + CPM_PIC: interrupt-controller@930 { + interrupt-controller; + #interrupt-cells = <1>; + interrupts = <5 2 0 2>; + interrupt-parent = <&PIC>; + reg = <0x930 0x20>; + compatible = "fsl,cpm1-pic"; + }; + + /* MON-1 */ + serial@a80 { + device_type = "serial"; + compatible = "fsl,cpm1-smc-uart"; + reg = <0xa80 0x10 0x3fc0 0x40>; + interrupts = <4>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-brg = <1>; + fsl,cpm-command = <0x0090>; + current-speed = <0>; /* Filled in by u-boot */ + }; + + ethernet@a40 { + device_type = "network"; + compatible = "fsl,mpc866-scc-enet", + "fsl,cpm1-scc-enet"; + reg = <0xa40 0x18 0x3e00 0x100>; + local-mac-address = [ 00 00 00 00 00 00 ]; /* Filled in by u-boot */ + interrupts = <28>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-command = <0x80>; + fixed-link = <0 0 10 0 0>; + }; + }; + }; +}; diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig new file mode 100644 index 00000000000..3cd6ce4be82 --- /dev/null +++ b/arch/powerpc/configs/mgsuvd_defconfig @@ -0,0 +1,872 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.26-rc2 +# Wed May 21 13:30:33 2008 +# +# CONFIG_PPC64 is not set + +# +# Processor support +# +# CONFIG_6xx is not set +# CONFIG_PPC_85xx is not set +CONFIG_PPC_8xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_8xx=y +# CONFIG_PPC_MM_SLICES is not set +CONFIG_NOT_COHERENT_CACHE=y +CONFIG_PPC32=y +CONFIG_WORD_SIZE=32 +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set +CONFIG_IRQ_PER_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +# CONFIG_ARCH_NO_VIRT_TO_BUS is not set +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +# CONFIG_BUG is not set +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +# CONFIG_BASE_FULL is not set +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +# CONFIG_EPOLL is not set +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=1 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# Platform support +# +# CONFIG_PPC_MPC512x is not set +# CONFIG_PPC_MPC5121 is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +CONFIG_CPM1=y +# CONFIG_MPC8XXFADS is not set +# CONFIG_MPC86XADS is not set +# CONFIG_MPC885ADS is not set +# CONFIG_PPC_EP88XC is not set +# CONFIG_PPC_ADDER875 is not set +CONFIG_PPC_MGSUVD=y + +# +# MPC8xx CPM Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +CONFIG_8xx_CPU6=y +CONFIG_8xx_CPU15=y +# CONFIG_NO_UCODE_PATCH is not set +# CONFIG_USB_SOF_UCODE_PATCH is not set +# CONFIG_I2C_SPI_UCODE_PATCH is not set +CONFIG_I2C_SPI_SMC1_UCODE_PATCH=y +CONFIG_UCODE_PATCH=y +# CONFIG_PQ2ADS is not set +# CONFIG_IPIC is not set +# CONFIG_MPIC is not set +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_INDIRECT_IO is not set +# CONFIG_GENERIC_IOMAP is not set +# CONFIG_CPU_FREQ is not set +CONFIG_PPC_CPM_NEW_BINDING=y +# CONFIG_FSL_ULI1575 is not set +CONFIG_CPM=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +# CONFIG_SCHED_HRTICK is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MATH_EMULATION=y +# CONFIG_IOMMU_HELPER is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_HAS_WALK_MEMORY=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_PROC_DEVICETREE is not set +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_FSL_SOC=y +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCI_QSPAN is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_HAS_RAPIDIO is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_PAGE_OFFSET=0xc0000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_PHYSICAL_START=0x00000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xfd000000 +CONFIG_CONSISTENT_SIZE=0x00200000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_CFI_FLAGADM is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +CONFIG_OF_DEVICE=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +CONFIG_FS_ENET=y +CONFIG_FS_ENET_HAS_SCC=y +# CONFIG_FS_ENET_HAS_FEC is not set +# CONFIG_FS_ENET_MDIO_FEC is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +# CONFIG_SERIAL_CPM_SMC2 is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SAMPLES is not set +# CONFIG_IRQSTACKS is not set +# CONFIG_VIRQ_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_PPC_CLOCK is not set +CONFIG_PPC_LIB_RHEAP=y +# CONFIG_VIRTUALIZATION is not set diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 71d7562e190..48a920a98e7 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -49,6 +49,12 @@ config PPC_ADDER875 This enables support for the Analogue & Micro Adder 875 board. +config PPC_MGSUVD + bool "MGSUVD" + select CPM1 + help + This enables support for the Keymile MGSUVD board. + endchoice menu "Freescale Ethernet driver platform-specific options" diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile index 7b71d9c8fb4..bdbfd749601 100644 --- a/arch/powerpc/platforms/8xx/Makefile +++ b/arch/powerpc/platforms/8xx/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o obj-$(CONFIG_PPC_EP88XC) += ep88xc.o obj-$(CONFIG_PPC_ADDER875) += adder875.o +obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o diff --git a/arch/powerpc/platforms/8xx/mgsuvd.c b/arch/powerpc/platforms/8xx/mgsuvd.c new file mode 100644 index 00000000000..ca3cb071772 --- /dev/null +++ b/arch/powerpc/platforms/8xx/mgsuvd.c @@ -0,0 +1,92 @@ +/* + * + * Platform setup for the Keymile mgsuvd board + * + * Heiko Schocher + * + * Copyright 2008 DENX Software Engineering GmbH + * + * 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 "mpc8xx.h" + +struct cpm_pin { + int port, pin, flags; +}; + +static __initdata struct cpm_pin mgsuvd_pins[] = { + /* SMC1 */ + {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */ + {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ + + /* SCC3 */ + {CPM_PORTA, 10, CPM_PIN_INPUT}, + {CPM_PORTA, 11, CPM_PIN_INPUT}, + {CPM_PORTA, 3, CPM_PIN_INPUT}, + {CPM_PORTA, 2, CPM_PIN_INPUT}, + {CPM_PORTC, 13, CPM_PIN_INPUT}, +}; + +static void __init init_ioports(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mgsuvd_pins); i++) { + struct cpm_pin *pin = &mgsuvd_pins[i]; + cpm1_set_pin(pin->port, pin->pin, pin->flags); + } + + setbits16(&mpc8xx_immr->im_ioport.iop_pcso, 0x300); + cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RX); + cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_TX); + cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX); +} + +static void __init mgsuvd_setup_arch(void) +{ + cpm_reset(); + init_ioports(); +} + +static __initdata struct of_device_id of_bus_ids[] = { + { .compatible = "simple-bus" }, + {}, +}; + +static int __init declare_of_platform_devices(void) +{ + of_platform_bus_probe(NULL, of_bus_ids, NULL); + return 0; +} +machine_device_initcall(mgsuvd, declare_of_platform_devices); + +static int __init mgsuvd_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + return of_flat_dt_is_compatible(root, "keymile,mgsuvd"); +} + +define_machine(mgsuvd) { + .name = "MGSUVD", + .probe = mgsuvd_probe, + .setup_arch = mgsuvd_setup_arch, + .init_IRQ = mpc8xx_pics_init, + .get_irq = mpc8xx_get_irq, + .restart = mpc8xx_restart, + .calibrate_decr = mpc8xx_calibrate_decr, + .set_rtc_time = mpc8xx_set_rtc_time, + .get_rtc_time = mpc8xx_get_rtc_time, +}; -- GitLab From 637166337ca29459581bd2943072a9f1268fb982 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 18 Jun 2008 10:38:32 +0200 Subject: [PATCH 1911/5416] powerpc: Add support for mpc8247 based board MGCOGE from keymile. Signed-off-by: Heiko Schocher Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/mgcoge.dts | 174 +++++ arch/powerpc/configs/mgcoge_defconfig | 900 ++++++++++++++++++++++++++ arch/powerpc/platforms/82xx/Kconfig | 8 + arch/powerpc/platforms/82xx/Makefile | 1 + arch/powerpc/platforms/82xx/mgcoge.c | 129 ++++ 5 files changed, 1212 insertions(+) create mode 100644 arch/powerpc/boot/dts/mgcoge.dts create mode 100644 arch/powerpc/configs/mgcoge_defconfig create mode 100644 arch/powerpc/platforms/82xx/mgcoge.c diff --git a/arch/powerpc/boot/dts/mgcoge.dts b/arch/powerpc/boot/dts/mgcoge.dts new file mode 100644 index 00000000000..633255a9755 --- /dev/null +++ b/arch/powerpc/boot/dts/mgcoge.dts @@ -0,0 +1,174 @@ +/* + * Device Tree for the MGCOGE plattform from keymile + * + * Copyright 2008 DENX Software Engineering GmbH + * Heiko Schocher + * + * 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. + */ + +/dts-v1/; +/ { + model = "MGCOGE"; + compatible = "keymile,mgcoge"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + ethernet0 = ð0; + serial0 = &smc2; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8247@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <32>; + i-cache-line-size = <32>; + d-cache-size = <16384>; + i-cache-size = <16384>; + timebase-frequency = <0>; /* Filled in by U-Boot */ + clock-frequency = <0>; /* Filled in by U-Boot */ + bus-frequency = <0>; /* Filled in by U-Boot */ + }; + }; + + localbus@f0010100 { + compatible = "fsl,mpc8247-localbus", + "fsl,pq2-localbus", + "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + reg = <0xf0010100 0x40>; + + ranges = <0 0 0xfe000000 0x00400000 + 5 0 0x50000000 0x20000000 + >; /* Filled in by U-Boot */ + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0 0x0 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <1>; + device-width = <1>; + partition@0 { + label = "u-boot"; + reg = <0 0x40000>; + }; + partition@40000 { + label = "env"; + reg = <0x40000 0x20000>; + }; + partition@60000 { + label = "kernel"; + reg = <0x60000 0x220000>; + }; + partition@280000 { + label = "dtb"; + reg = <0x280000 0x20000>; + }; + }; + + flash@5,0 { + compatible = "cfi-flash"; + reg = <5 0x0 0x2000000>; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <2>; + device-width = <2>; + partition@0 { + label = "ramdisk"; + reg = <0 0x7a0000>; + }; + partition@7a0000 { + label = "user"; + reg = <0x7a0000 0x1860000>; + }; + }; + }; + + memory { + device_type = "memory"; + reg = <0 0>; /* Filled in by U-Boot */ + }; + + soc@f0000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc8247-immr", "fsl,pq2-soc", "simple-bus"; + ranges = <0x00000000 0xf0000000 0x00053000>; + + // Temporary until code stops depending on it. + device_type = "soc"; + + cpm@119c0 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + compatible = "fsl,mpc8247-cpm", "fsl,cpm2", + "simple-bus"; + reg = <0x119c0 0x30>; + ranges; + + muram { + compatible = "fsl,cpm-muram"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x10000>; + + data@0 { + compatible = "fsl,cpm-muram-data"; + reg = <0x80 0x1f80 0x9800 0x800>; + }; + }; + + brg@119f0 { + compatible = "fsl,mpc8247-brg", + "fsl,cpm2-brg", + "fsl,cpm-brg"; + reg = <0x119f0 0x10 0x115f0 0x10>; + }; + + /* Monitor port/SMC2 */ + smc2: serial@11a90 { + device_type = "serial"; + compatible = "fsl,mpc8247-smc-uart", + "fsl,cpm2-smc-uart"; + reg = <0x11a90 0x20 0x88fc 0x02>; + interrupts = <5 8>; + interrupt-parent = <&PIC>; + fsl,cpm-brg = <2>; + fsl,cpm-command = <0x21200000>; + current-speed = <0>; /* Filled in by U-Boot */ + }; + + eth0: ethernet@11a60 { + device_type = "network"; + compatible = "fsl,mpc8247-scc-enet", + "fsl,cpm2-scc-enet"; + reg = <0x11a60 0x20 0x8300 0x100 0x11390 1>; + local-mac-address = [ 00 00 00 00 00 00 ]; /* Filled in by U-Boot */ + interrupts = <43 8>; + interrupt-parent = <&PIC>; + linux,network-index = <0>; + fsl,cpm-command = <0xce00000>; + fixed-link = <0 0 10 0 0>; + }; + + }; + + PIC: interrupt-controller@10c00 { + #interrupt-cells = <2>; + interrupt-controller; + reg = <0x10c00 0x80>; + compatible = "fsl,mpc8247-pic", "fsl,pq2-pic"; + }; + }; +}; diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig new file mode 100644 index 00000000000..cc9eaba8c9c --- /dev/null +++ b/arch/powerpc/configs/mgcoge_defconfig @@ -0,0 +1,900 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.26-rc2 +# Thu May 22 08:18:47 2008 +# +# CONFIG_PPC64 is not set + +# +# Processor support +# +CONFIG_6xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_PPC_MM_SLICES is not set +# CONFIG_SMP is not set +CONFIG_PPC32=y +CONFIG_WORD_SIZE=32 +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set +CONFIG_IRQ_PER_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +# CONFIG_ARCH_NO_VIRT_TO_BUS is not set +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +# CONFIG_DEFAULT_UIMAGE is not set +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_CLASSIC_RCU=y + +# +# Platform support +# +# CONFIG_PPC_MULTIPLATFORM is not set +CONFIG_PPC_82xx=y +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_MPC512x is not set +# CONFIG_PPC_MPC5121 is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_MPC8272_ADS is not set +# CONFIG_PQ2FADS is not set +# CONFIG_EP8248E is not set +CONFIG_MGCOGE=y +# CONFIG_PQ2ADS is not set +CONFIG_8260=y +CONFIG_8272=y +# CONFIG_IPIC is not set +# CONFIG_MPIC is not set +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_INDIRECT_IO is not set +# CONFIG_GENERIC_IOMAP is not set +# CONFIG_CPU_FREQ is not set +CONFIG_CPM2=y +CONFIG_PPC_CPM_NEW_BINDING=y +# CONFIG_FSL_ULI1575 is not set +CONFIG_CPM=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_IOMMU_HELPER is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_HAS_WALK_MEMORY=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_FSL_SOC=y +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set +# CONFIG_HAS_RAPIDIO is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_PAGE_OFFSET=0xc0000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_PHYSICAL_START=0x00000000 +CONFIG_TASK_SIZE=0xc0000000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +CONFIG_OF_DEVICE=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +CONFIG_FS_ENET=y +CONFIG_FS_ENET_HAS_SCC=y +# CONFIG_FS_ENET_HAS_FCC is not set +# CONFIG_FS_ENET_MDIO_FCC is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_HFSPLUS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUGGER is not set +# CONFIG_KGDB_CONSOLE is not set +# CONFIG_IRQSTACKS is not set +# CONFIG_VIRQ_DEBUG is not set +CONFIG_BDI_SWITCH=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_PCBC=y + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_PPC_CLOCK is not set +CONFIG_PPC_LIB_RHEAP=y +# CONFIG_VIRTUALIZATION is not set diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 75eb1ede549..30f008b2f92 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig @@ -38,6 +38,14 @@ config EP8248E This board is also resold by Freescale as the QUICCStart MPC8248 Evaluation System and/or the CWH-PPC-8248N-VE. +config MGCOGE + bool "Keymile MGCOGE" + select 8272 + select 8260 + select FSL_SOC + help + This enables support for the Keymile MGCOGE board. + endif config PQ2ADS diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile index 6cd5cd59bf2..d982793f4db 100644 --- a/arch/powerpc/platforms/82xx/Makefile +++ b/arch/powerpc/platforms/82xx/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_CPM2) += pq2.o obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o obj-$(CONFIG_PQ2FADS) += pq2fads.o obj-$(CONFIG_EP8248E) += ep8248e.o +obj-$(CONFIG_MGCOGE) += mgcoge.o diff --git a/arch/powerpc/platforms/82xx/mgcoge.c b/arch/powerpc/platforms/82xx/mgcoge.c new file mode 100644 index 00000000000..c2af169c1d1 --- /dev/null +++ b/arch/powerpc/platforms/82xx/mgcoge.c @@ -0,0 +1,129 @@ +/* + * Keymile mgcoge support + * Copyright 2008 DENX Software Engineering GmbH + * Author: Heiko Schocher + * + * based on code from: + * Copyright 2007 Freescale Semiconductor, Inc. + * Author: Scott Wood + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pq2.h" + +static void __init mgcoge_pic_init(void) +{ + struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic"); + if (!np) { + printk(KERN_ERR "PIC init: can not find cpm-pic node\n"); + return; + } + + cpm2_pic_init(np); + of_node_put(np); +} + +struct cpm_pin { + int port, pin, flags; +}; + +static __initdata struct cpm_pin mgcoge_pins[] = { + + /* SMC2 */ + {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {1, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, + + /* SCC4 */ + {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {3, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {3, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {3, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {4, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, + {4, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, +}; + +static void __init init_ioports(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mgcoge_pins); i++) { + const struct cpm_pin *pin = &mgcoge_pins[i]; + cpm2_set_pin(pin->port - 1, pin->pin, pin->flags); + } + + cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8); + cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX); + cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX); +} + +static void __init mgcoge_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mgcoge_setup_arch()", 0); + + cpm2_reset(); + + /* When this is set, snooping CPM DMA from RAM causes + * machine checks. See erratum SIU18. + */ + clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP); + + init_ioports(); + + if (ppc_md.progress) + ppc_md.progress("mgcoge_setup_arch(), finish", 0); +} + +static __initdata struct of_device_id of_bus_ids[] = { + { .compatible = "simple-bus", }, + {}, +}; + +static int __init declare_of_platform_devices(void) +{ + of_platform_bus_probe(NULL, of_bus_ids, NULL); + + return 0; +} +machine_device_initcall(mgcoge, declare_of_platform_devices); + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mgcoge_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + return of_flat_dt_is_compatible(root, "keymile,mgcoge"); +} + +define_machine(mgcoge) +{ + .name = "Keymile MGCOGE", + .probe = mgcoge_probe, + .setup_arch = mgcoge_setup_arch, + .init_IRQ = mgcoge_pic_init, + .get_irq = cpm2_get_irq, + .calibrate_decr = generic_calibrate_decr, + .restart = pq2_restart, + .progress = udbg_progress, +}; -- GitLab From 7cfc4e5e7f9b5fa598aa69b5344b6fd0539f71d6 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 4 Aug 2008 08:27:52 -0500 Subject: [PATCH 1912/5416] serial/cpm_uart: Remove dead Kconfig options With the change to device tree based setup we no longer need the explicit Kconfig options for each SCC{1,4} or SMC{1,2} port. Signed-off-by: Kumar Gala --- drivers/serial/Kconfig | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 77cb34270fc..b87b1cf9df6 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1136,42 +1136,6 @@ config SERIAL_CPM_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_CPM_SCC1 - bool "Support for SCC1 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SCC1 as a serial port - -config SERIAL_CPM_SCC2 - bool "Support for SCC2 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SCC2 as a serial port - -config SERIAL_CPM_SCC3 - bool "Support for SCC3 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SCC3 as a serial port - -config SERIAL_CPM_SCC4 - bool "Support for SCC4 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SCC4 as a serial port - -config SERIAL_CPM_SMC1 - bool "Support for SMC1 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SMC1 as a serial port - -config SERIAL_CPM_SMC2 - bool "Support for SMC2 serial port" - depends on SERIAL_CPM=y - help - Select this option to use SMC2 as a serial port - config SERIAL_SGI_L1_CONSOLE bool "SGI Altix L1 serial console support" depends on IA64_GENERIC || IA64_SGI_SN2 -- GitLab From 307db95882fdfba372a0639e8e238cf8c542f430 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 14 Aug 2008 21:13:42 +0400 Subject: [PATCH 1913/5416] powerpc/83xx: mpc836x_mds: add support for the nor flash This patch adds the localbus node, moves the bcsr node into the localbus node, and adds the flash node. Also enable MTD support in the defconfig. Signed-off-by: Anton Vorontsov Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/mpc836x_mds.dts | 23 +++++- .../configs/83xx/mpc836x_mds_defconfig | 79 ++++++++++++++++++- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index a3b76a70995..ada8446ab3c 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -52,9 +52,26 @@ reg = <0x00000000 0x10000000>; }; - bcsr@f8000000 { - device_type = "board-control"; - reg = <0xf8000000 0x8000>; + localbus@e0005000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus", + "simple-bus"; + reg = <0xe0005000 0xd8>; + ranges = <0 0 0xfe000000 0x02000000 + 1 0 0xf8000000 0x00008000>; + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x2000000>; + bank-width = <2>; + device-width = <1>; + }; + + bcsr@1,0 { + device_type = "board-control"; + reg = <1 0 0x8000>; + }; }; soc8360@e0000000 { diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig index e029e9e1462..cf2706a5f34 100644 --- a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig +++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig @@ -383,7 +383,84 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_OF_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set CONFIG_OF_DEVICE=y CONFIG_OF_I2C=y # CONFIG_PARPORT is not set -- GitLab From 82331ab15f14786f3d8e874efb76462685e3bfa0 Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Thu, 21 Aug 2008 13:50:22 -0500 Subject: [PATCH 1914/5416] powerpc/85xx: fix build warning, remove silly cast This fixes a build warning when PHYS_64BIT is enabled, and removes an unnecessary cast to phys_addr_t (the variable being cast is already a phys_addr_t) Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala --- arch/powerpc/mm/fsl_booke_mmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index ce10e2b1b90..23cee39534f 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c @@ -202,7 +202,7 @@ adjust_total_lowmem(void) cam_max_size = max_lowmem_size; /* adjust lowmem size to max_lowmem_size */ - ram = min(max_lowmem_size, (phys_addr_t)total_lowmem); + ram = min(max_lowmem_size, total_lowmem); /* Calculate CAM values */ __cam0 = 1UL << 2 * (__ilog2(ram) / 2); @@ -225,7 +225,8 @@ adjust_total_lowmem(void) printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb," " CAM2=%ldMb residual: %ldMb\n", __cam0 >> 20, __cam1 >> 20, __cam2 >> 20, - (total_lowmem - __cam0 - __cam1 - __cam2) >> 20); + (long int)((total_lowmem - __cam0 - __cam1 - __cam2) + >> 20)); __max_low_memory = __cam0 + __cam1 + __cam2; __initial_memory_limit_addr = memstart_addr + __max_low_memory; } -- GitLab From 40d3057ac036f2501c1930728a6179be4fca577b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 27 Jun 2008 09:33:59 -0500 Subject: [PATCH 1915/5416] math-emu: Fix compiler warnings Fix warnings of the form: arch/powerpc/math-emu/fsubs.c:15: warning: 'R_f1' may be used uninitialized in this function arch/powerpc/math-emu/fsubs.c:15: warning: 'R_f0' may be used uninitialized in this function Signed-off-by: Kumar Gala --- include/math-emu/op-2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/math-emu/op-2.h b/include/math-emu/op-2.h index e193fb08fd5..4f26ecc1411 100644 --- a/include/math-emu/op-2.h +++ b/include/math-emu/op-2.h @@ -25,7 +25,7 @@ #ifndef __MATH_EMU_OP_2_H__ #define __MATH_EMU_OP_2_H__ -#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 +#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0 = 0, X##_f1 = 0 #define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) #define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) #define _FP_FRAC_HIGH_2(X) (X##_f1) -- GitLab From 48d6c64311ddb6417b901639530ccbc47bdc7635 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 27 Jun 2008 09:39:00 -0500 Subject: [PATCH 1916/5416] math-emu: Add support for reporting exact invalid exception Some architectures (like powerpc) provide status information on the exact type of invalid exception. This is pretty straight forward as we already report invalid exceptions via FP_SET_EXCEPTION. We add new flags (FP_EX_INVALID_*) the architecture code can define if it wants the exact invalid exception reported. We had to split out the INF/INF and 0/0 cases for divide to allow reporting the two invalid forms properly. Signed-off-by: Kumar Gala Acked-by: David S. Miller --- include/math-emu/op-common.h | 12 ++++++++---- include/math-emu/soft-fp.h | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index bb46e7645d5..cc1ec396f8d 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -73,7 +73,7 @@ do { \ X##_c = FP_CLS_NAN; \ /* Check for signaling NaN */ \ if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ - FP_SET_EXCEPTION(FP_EX_INVALID); \ + FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN); \ } \ break; \ } \ @@ -324,7 +324,7 @@ do { \ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ - FP_SET_EXCEPTION(FP_EX_INVALID); \ + FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI); \ break; \ } \ /* FALLTHRU */ \ @@ -431,7 +431,7 @@ do { \ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION(FP_EX_INVALID); \ + FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\ break; \ \ default: \ @@ -490,11 +490,15 @@ do { \ break; \ \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION(FP_EX_INVALID); \ + FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\ break; \ \ default: \ diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index a6f873b45f9..3f284bc0318 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -51,6 +51,25 @@ #ifndef FP_EX_INVALID #define FP_EX_INVALID 0 #endif +#ifndef FP_EX_INVALID_SNAN +#define FP_EX_INVALID_SNAN 0 +#endif +/* inf - inf */ +#ifndef FP_EX_INVALID_ISI +#define FP_EX_INVALID_ISI 0 +#endif +/* inf / inf */ +#ifndef FP_EX_INVALID_IDI +#define FP_EX_INVALID_IDI 0 +#endif +/* 0 / 0 */ +#ifndef FP_EX_INVALID_ZDZ +#define FP_EX_INVALID_ZDZ 0 +#endif +/* inf * 0 */ +#ifndef FP_EX_INVALID_IMZ +#define FP_EX_INVALID_IMZ 0 +#endif #ifndef FP_EX_OVERFLOW #define FP_EX_OVERFLOW 0 #endif -- GitLab From 66576a87dda18cede6a728685366c9c0fedd1742 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 3 Sep 2008 16:02:25 -0400 Subject: [PATCH 1917/5416] powerpc/sbc8560: fix compile warning on CPM pin array This is just a parallel of a5dc66e2ab2e2cf641346b056a69a67cfcf9458c applied to the sbc8560 board. Signed-off-by: Paul Gortmaker Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/sbc8560.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c index 6509ade7166..e0cf0602d8b 100644 --- a/arch/powerpc/platforms/85xx/sbc8560.c +++ b/arch/powerpc/platforms/85xx/sbc8560.c @@ -156,7 +156,7 @@ static void __init init_ioports(void) int i; for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) { - struct cpm_pin *pin = &sbc8560_pins[i]; + const struct cpm_pin *pin = &sbc8560_pins[i]; cpm2_set_pin(pin->port, pin->pin, pin->flags); } -- GitLab From 54508214cf2f88ad1288e8836032545e0357ebde Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Tue, 16 Sep 2008 10:57:47 +0100 Subject: [PATCH 1918/5416] powerpc: Board support for GE Fanuc SBC610 Support for the SBC610 VPX Single Board Computer from GE Fanuc (PowerPC MPC8641D). This is the basic board support for GE Fanuc's SBC610, a 6U single board computer, based on Freescale's MPC8641D. Signed-off-by: Martyn Welch Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/gef_sbc610.dts | 260 +++++++++++++++++++++++ arch/powerpc/platforms/86xx/Kconfig | 9 +- arch/powerpc/platforms/86xx/Makefile | 1 + arch/powerpc/platforms/86xx/gef_sbc610.c | 149 +++++++++++++ 4 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/boot/dts/gef_sbc610.dts create mode 100644 arch/powerpc/platforms/86xx/gef_sbc610.c diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts new file mode 100644 index 00000000000..80b79e4adc7 --- /dev/null +++ b/arch/powerpc/boot/dts/gef_sbc610.dts @@ -0,0 +1,260 @@ +/* + * GE Fanuc SBC610 Device Tree Source + * + * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Based on: SBS CM6 Device Tree Source + * Copyright 2007 SBS Technologies GmbH & Co. KG + * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source) + * Copyright 2006 Freescale Semiconductor Inc. + */ + +/* + * Compiled with dtc -I dts -O dtb -o gef_sbc610.dtb gef_sbc610.dts + */ + +/dts-v1/; + +/ { + model = "GEF_SBC610"; + compatible = "gef,sbc610"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + ethernet0 = &enet0; + ethernet1 = &enet1; + serial0 = &serial0; + serial1 = &serial1; + pci0 = &pci0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8641@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <32>; // 32 bytes + i-cache-line-size = <32>; // 32 bytes + d-cache-size = <32768>; // L1, 32K + i-cache-size = <32768>; // L1, 32K + timebase-frequency = <0>; // From uboot + bus-frequency = <0>; // From uboot + clock-frequency = <0>; // From uboot + }; + PowerPC,8641@1 { + device_type = "cpu"; + reg = <1>; + d-cache-line-size = <32>; // 32 bytes + i-cache-line-size = <32>; // 32 bytes + d-cache-size = <32768>; // L1, 32K + i-cache-size = <32768>; // L1, 32K + timebase-frequency = <0>; // From uboot + bus-frequency = <0>; // From uboot + clock-frequency = <0>; // From uboot + }; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x40000000>; // set by uboot + }; + + soc@fef00000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + compatible = "simple-bus"; + ranges = <0x0 0xfef00000 0x00100000>; + reg = <0xfef00000 0x100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c1: i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl-i2c"; + reg = <0x3000 0x100>; + interrupts = <0x2b 0x2>; + interrupt-parent = <&mpic>; + dfsrr; + + eti@6b { + compatible = "dallas,ds1682"; + reg = <0x6b>; + }; + }; + + i2c2: i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <0x2b 0x2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + dma@21300 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma"; + reg = <0x21300 0x4>; + ranges = <0x0 0x21100 0x200>; + cell-index = <0>; + dma-channel@0 { + compatible = "fsl,mpc8641-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x0 0x80>; + cell-index = <0>; + interrupt-parent = <&mpic>; + interrupts = <20 2>; + }; + dma-channel@80 { + compatible = "fsl,mpc8641-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x80 0x80>; + cell-index = <1>; + interrupt-parent = <&mpic>; + interrupts = <21 2>; + }; + dma-channel@100 { + compatible = "fsl,mpc8641-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x100 0x80>; + cell-index = <2>; + interrupt-parent = <&mpic>; + interrupts = <22 2>; + }; + dma-channel@180 { + compatible = "fsl,mpc8641-dma-channel", + "fsl,eloplus-dma-channel"; + reg = <0x180 0x80>; + cell-index = <3>; + interrupt-parent = <&mpic>; + interrupts = <23 2>; + }; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,gianfar-mdio"; + reg = <0x24520 0x20>; + + phy0: ethernet-phy@0 { + interrupt-parent = <&mpic>; + interrupts = <0x0 0x1>; + reg = <1>; + }; + phy2: ethernet-phy@2 { + interrupt-parent = <&mpic>; + interrupts = <0x0 0x1>; + reg = <3>; + }; + }; + + enet0: ethernet@24000 { + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <0x24000 0x1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>; + interrupt-parent = <&mpic>; + phy-handle = <&phy0>; + phy-connection-type = "gmii"; + }; + + enet1: ethernet@26000 { + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <0x26000 0x1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>; + interrupt-parent = <&mpic>; + phy-handle = <&phy2>; + phy-connection-type = "gmii"; + }; + + serial0: serial@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + interrupts = <0x2a 0x2>; + interrupt-parent = <&mpic>; + }; + + serial1: serial@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + interrupts = <0x1c 0x2>; + interrupt-parent = <&mpic>; + }; + + mpic: pic@40000 { + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + }; + + global-utilities@e0000 { + compatible = "fsl,mpc8641-guts"; + reg = <0xe0000 0x1000>; + fsl,has-rstcr; + }; + }; + + pci0: pcie@fef08000 { + compatible = "fsl,mpc8641-pcie"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0xfef08000 0x1000>; + bus-range = <0x0 0xff>; + ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000 + 0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>; + clock-frequency = <33333333>; + interrupt-parent = <&mpic>; + interrupts = <0x18 0x2>; + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; + interrupt-map = < + 0x0000 0x0 0x0 0x1 &mpic 0x0 0x1 + 0x0000 0x0 0x0 0x2 &mpic 0x1 0x1 + 0x0000 0x0 0x0 0x3 &mpic 0x2 0x1 + 0x0000 0x0 0x0 0x4 &mpic 0x3 0x1 + >; + + pcie@0 { + reg = <0 0 0 0 0>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + ranges = <0x02000000 0x0 0x80000000 + 0x02000000 0x0 0x80000000 + 0x0 0x40000000 + + 0x01000000 0x0 0x00000000 + 0x01000000 0x0 0x00000000 + 0x0 0x00400000>; + }; + }; +}; diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 9355a526943..77dd797a258 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -31,6 +31,13 @@ config MPC8610_HPCD help This option enables support for the MPC8610 HPCD board. +config GEF_SBC610 + bool "GE Fanuc SBC610" + select DEFAULT_UIMAGE + select HAS_RAPIDIO + help + This option enables support for GE Fanuc's SBC610. + endif config MPC8641 @@ -39,7 +46,7 @@ config MPC8641 select FSL_PCI if PCI select PPC_UDBG_16550 select MPIC - default y if MPC8641_HPCN || SBC8641D + default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 config MPC8610 bool diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 8fee37dec79..cb9fc8f4360 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o obj-$(CONFIG_SBC8641D) += sbc8641d.o obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o +obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c new file mode 100644 index 00000000000..3543a9e6761 --- /dev/null +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -0,0 +1,149 @@ +/* + * GE Fanuc SBC610 board support + * + * Author: Martyn Welch + * + * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines) + * Copyright 2006 Freescale Semiconductor Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "mpc86xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG (fmt...) do { printk(KERN_ERR "SBC610: " fmt); } while (0) +#else +#define DBG (fmt...) do { } while (0) +#endif + +static void __init gef_sbc610_setup_arch(void) +{ +#ifdef CONFIG_PCI + struct device_node *np; + + for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") { + fsl_add_bridge(np, 1); + } +#endif + + printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC610 6U VPX SBC\n"); + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif +} + + +static void gef_sbc610_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + uint memsize = total_memory; + const char *model = ""; + uint svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n"); + + root = of_find_node_by_path("/"); + if (root) + model = of_get_property(root, "model", NULL); + seq_printf(m, "Machine\t\t: %s\n", model); + of_node_put(root); + + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + * + * This function is called to determine whether the BSP is compatible with the + * supplied device-tree, which is assumed to be the correct one for the actual + * board. It is expected thati, in the future, a kernel may support multiple + * boards. + */ +static int __init gef_sbc610_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "gef,sbc610")) + return 1; + + return 0; +} + +static long __init mpc86xx_time_init(void) +{ + unsigned int temp; + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + temp = mfspr(SPRN_HID0); + temp |= HID0_TBEN; + mtspr(SPRN_HID0, temp); + asm volatile("isync"); + + return 0; +} + +static __initdata struct of_device_id of_bus_ids[] = { + { .compatible = "simple-bus", }, + {}, +}; + +static int __init declare_of_platform_devices(void) +{ + printk(KERN_DEBUG "Probe platform devices\n"); + of_platform_bus_probe(NULL, of_bus_ids, NULL); + + return 0; +} +machine_device_initcall(gef_sbc610, declare_of_platform_devices); + +define_machine(gef_sbc610) { + .name = "GE Fanuc SBC610", + .probe = gef_sbc610_probe, + .setup_arch = gef_sbc610_setup_arch, + .init_IRQ = mpc86xx_init_irq, + .show_cpuinfo = gef_sbc610_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif +}; -- GitLab From 1a9314a0f6f71cf13ddf9e58f1d4f507a5265056 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Tue, 16 Sep 2008 10:57:52 +0100 Subject: [PATCH 1919/5416] powerpc: Default configuration for GE Fanuc SBC610 Support for the SBC610 VPX Single Board Computer from GE Fanuc (PowerPC MPC8641D). This is the default config file for GE Fanuc's SBC610, a 6U single board computer, based on Freescale's MPC8641D. Signed-off-by: Martyn Welch Signed-off-by: Kumar Gala --- .../powerpc/configs/86xx/gef_sbc610_defconfig | 1654 +++++++++++++++++ 1 file changed, 1654 insertions(+) create mode 100644 arch/powerpc/configs/86xx/gef_sbc610_defconfig diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig new file mode 100644 index 00000000000..f589489449d --- /dev/null +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig @@ -0,0 +1,1654 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.26-rc5 +# Wed Jun 11 12:06:53 2008 +# +# CONFIG_PPC64 is not set + +# +# Processor support +# +CONFIG_6xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_PPC_MM_SLICES is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PPC32=y +CONFIG_WORD_SIZE=32 +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set +CONFIG_IRQ_PER_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +# CONFIG_ARCH_NO_VIRT_TO_BUS is not set +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFAULT_UIMAGE=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y + +# +# Platform support +# +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_86xx=y +# CONFIG_PPC_MPC512x is not set +# CONFIG_PPC_MPC5121 is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_PQ2ADS is not set +# CONFIG_MPC8641_HPCN is not set +# CONFIG_SBC8641D is not set +# CONFIG_MPC8610_HPCD is not set +CONFIG_GEF_SBC610=y +CONFIG_MPC8641=y +# CONFIG_IPIC is not set +CONFIG_MPIC=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_INDIRECT_IO is not set +# CONFIG_GENERIC_IOMAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_FSL_ULI1575 is not set + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +# CONFIG_SCHED_HRTICK is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +# CONFIG_PREEMPT_RCU is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +# CONFIG_IOMMU_HELPER is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_HAS_WALK_MEMORY=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_PROC_DEVICETREE is not set +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_FSL_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIEASPM is not set +CONFIG_ARCH_SUPPORTS_MSI=y +# CONFIG_PCI_MSI is not set +CONFIG_PCI_LEGACY=y +CONFIG_PCI_DEBUG=y +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set +CONFIG_HAS_RAPIDIO=y +# CONFIG_RAPIDIO is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_PAGE_OFFSET=0xc0000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_PHYSICAL_START=0x00000000 +CONFIG_TASK_SIZE=0xc0000000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +# CONFIG_IP_NF_MATCH_AH is not set +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_MH is not set +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +# CONFIG_IP6_NF_TARGET_REJECT is not set +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_RAW=m + +# +# Bridge: Netfilter Configuration +# +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +# CONFIG_NET_SCH_RR is not set +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_OF_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_LE_BYTE_SWAP=y +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +CONFIG_OF_DEVICE=y +CONFIG_OF_I2C=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_SRP is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_SATA_PMP=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_FSL is not set +CONFIG_ATA_SFF=y +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +CONFIG_SATA_SIL=y +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_SCH is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_ENABLED is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +# CONFIG_PPPOL2TP is not set +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLHC=m +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +# CONFIG_NET_FC is not set +CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_PLATFORM is not set + +# +# Miscellaneous I2C Chip support +# +CONFIG_DS1682=y +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +CONFIG_SENSORS_LM90=y +CONFIG_SENSORS_LM92=y +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_HCD_PPC_OF is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PPC_OF is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ATM is not set +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +# CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PPC is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_BIND34 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_DEBUGGER=y +# CONFIG_XMON is not set +# CONFIG_IRQSTACKS is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_SECURITY_ROOTPLUG is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_PPC_CLOCK is not set +# CONFIG_VIRTUALIZATION is not set -- GitLab From e1f4f59d1ab9ebac44830d6ae450fb358ac559d3 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Tue, 16 Sep 2008 14:27:13 +0100 Subject: [PATCH 1920/5416] PCI: Fix pcie_aspm=force pcie_aspm=force did not work because aspm_force was being double negated leading to the sanity check failing. Moving a bracket should fix this. Acked-by: Alan Cox Signed-off-by: Sitsofe Wheeler Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 9a7c9e1408a..851f5b83cdb 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -527,7 +527,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) */ pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP, ®32); - if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) { + if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { printk("Pre-1.1 PCIe device detected, " "disable ASPM for %s. It can be enabled forcedly" " with 'pcie_aspm=force'\n", pci_name(pdev)); -- GitLab From cd72ad3f57c400baa2ddb78b4fc2781cf68ffb6f Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sun, 14 Sep 2008 11:52:44 -0400 Subject: [PATCH 1921/5416] Input: bcm5974 - switch back to normal mode when closing Staying in multi-touch mode after closing the device sometimes makes the keyboard drop keys or repeat keys irratically. The conjecture is that some internal buffer starts to overflow, resulting in undefined behavior. Switching back to normal mode when closing the device makes the problem go away. Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 18f4d7f6ce6..2998a6ac9ae 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -351,8 +351,9 @@ static int report_tp_state(struct bcm5974 *dev, int size) #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 +#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 -static int bcm5974_wellspring_mode(struct bcm5974 *dev) +static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) { char *data = kmalloc(8, GFP_KERNEL); int retval = 0, size; @@ -377,7 +378,9 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev) } /* apply the mode switch */ - data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE; + data[0] = on ? + BCM5974_WELLSPRING_MODE_VENDOR_VALUE : + BCM5974_WELLSPRING_MODE_NORMAL_VALUE; /* write configuration */ size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), @@ -392,7 +395,8 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev) goto out; } - dprintk(2, "bcm5974: switched to wellspring mode.\n"); + dprintk(2, "bcm5974: switched to %s mode.\n", + on ? "wellspring" : "normal"); out: kfree(data); @@ -481,7 +485,7 @@ exit: */ static int bcm5974_start_traffic(struct bcm5974 *dev) { - if (bcm5974_wellspring_mode(dev)) { + if (bcm5974_wellspring_mode(dev, true)) { dprintk(1, "bcm5974: mode switch failed\n"); goto error; } @@ -504,6 +508,7 @@ static void bcm5974_pause_traffic(struct bcm5974 *dev) { usb_kill_urb(dev->tp_urb); usb_kill_urb(dev->bt_urb); + bcm5974_wellspring_mode(dev, false); } /* -- GitLab From ba0593bf553c450a03dbc5f8c1f0ff58b778a0c8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 16 Sep 2008 09:29:40 -0700 Subject: [PATCH 1922/5416] x86: completely disable NOPL on 32 bits Completely disable NOPL on 32 bits. It turns out that Microsoft Virtual PC is so broken it can't even reliably *fail* in the presence of NOPL. This leaves the infrastructure in place but disables it unconditionally. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8aab8517642..4e456bd955b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -344,31 +344,15 @@ static void __init early_cpu_detect(void) /* * The NOPL instruction is supposed to exist on all CPUs with - * family >= 6, unfortunately, that's not true in practice because + * family >= 6; unfortunately, that's not true in practice because * of early VIA chips and (more importantly) broken virtualizers that - * are not easy to detect. Hence, probe for it based on first - * principles. + * are not easy to detect. In the latter case it doesn't even *fail* + * reliably, so probing for it doesn't even work. Disable it completely + * unless we can find a reliable way to detect all the broken cases. */ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) { - const u32 nopl_signature = 0x888c53b1; /* Random number */ - u32 has_nopl = nopl_signature; - clear_cpu_cap(c, X86_FEATURE_NOPL); - if (c->x86 >= 6) { - asm volatile("\n" - "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ - "2:\n" - " .section .fixup,\"ax\"\n" - "3: xor %0,%0\n" - " jmp 2b\n" - " .previous\n" - _ASM_EXTABLE(1b,3b) - : "+a" (has_nopl)); - - if (has_nopl == nopl_signature) - set_cpu_cap(c, X86_FEATURE_NOPL); - } } static void __cpuinit generic_identify(struct cpuinfo_x86 *c) -- GitLab From f26fd5d6e5006eae75a389c7ce74ed16761d094b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 16 Sep 2008 09:32:18 -0700 Subject: [PATCH 1923/5416] [S390] cio: Fix driver_data handling for ccwgroup devices. Since 16f7f9564c3ae190954f2ec55f385a268b93ac4d, we've seen oopses when grouping/ungrouping devices: Unable to handle kernel pointer dereference at virtual kernel address 0000000000 114000 Oops: 0004 [#1] PREEMPT SMP Modules linked in: bonding qeth_l2 dm_multipath sunrpc qeth_l3 dm_mod qeth chsc_ sch ccwgroup CPU: 1 Not tainted 2.6.26-29.x.20080815-s390xdefault #1 Process iperf (pid: 24412, task: 000000003f446038, ksp: 000000003c929e08) Krnl PSW : 0404d00180000000 000003e00006f6e6 (qeth_irq+0xda/0xb28 [qeth]) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3 Krnl GPRS: 0000000000000000 000003e000000003 0000000000000000 0000000000114ccc 000000003fb82e48 000003e00006f60c 000000000000000c 000000003ce72100 0000000000114944 000000003fb82e48 0000000000114ccc 000000003fe8fd28 000003e000066000 000003e000076128 000000003fe8fdb8 000000003fe8fd28 Krnl Code: 000003e00006f6da: bf3f2024 icm %r3,15,36(%r2) 000003e00006f6de: a774023c brc 7,3e00006fb56 000003e00006f6e2: a7280000 lhi %r2,0 >000003e00006f6e6: 5020a1a0 st %r2,416(%r10) 000003e00006f6ea: 58109000 l %r1,0(%r9) 000003e00006f6ee: a7111000 tmll %r1,4096 000003e00006f6f2: a77400f9 brc 7,3e00006f8e4 000003e00006f6f6: 8810000c srl %r1,12 Call Trace: ([<000000003fe8fd20>] 0x3fe8fd20) [<000000000033bf2a>] ccw_device_call_handler+0xb2/0xd8 [<0000000000339e1c>] ccw_device_irq+0x124/0x164 [<0000000000339758>] io_subchannel_irq+0x8c/0x118 [<00000000003309ba>] do_IRQ+0x192/0x1bc [<0000000000114f66>] io_return+0x0/0x8 [<00000000001149cc>] sysc_do_svc+0x0/0x22 ([<0000000000114a18>] sysc_noemu+0x10/0x16) [<00000200002e047c>] 0x200002e047c Last Breaking-Event-Address: [<000003e00006f6d6>] qeth_irq+0xca/0xb28 [qeth] The problem is that dev->driver_data for a ccw device is NULL, while it should point to the ccwgroup device it is a member of. This happened due to incorrect cleanup if creating a ccwgroup device failed because the ccw devices were already grouped. Fix this by setting cdev[i] to NULL in the error handling of ccwgroup_create_from_string() after we give up our reference and by checking if the driver_data points to the ccwgroup device in ccwgroup_release() just to be really sure. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e0ce65fca4e..9a50f245774 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -113,7 +113,8 @@ ccwgroup_release (struct device *dev) for (i = 0; i < gdev->count; i++) { if (gdev->cdev[i]) { - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); + if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) + dev_set_drvdata(&gdev->cdev[i]->dev, NULL); put_device(&gdev->cdev[i]->dev); } } @@ -296,6 +297,7 @@ error: if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) dev_set_drvdata(&gdev->cdev[i]->dev, NULL); put_device(&gdev->cdev[i]->dev); + gdev->cdev[i] = NULL; } mutex_unlock(&gdev->reg_mutex); put_device(&gdev->dev); -- GitLab From 9adb8c1d4f0ac78b3469e377ce5f8a846cbaedaf Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Tue, 16 Sep 2008 09:32:19 -0700 Subject: [PATCH 1924/5416] [S390] cio: fix orb initialization in cio_start_key The functions cio_tm_start_key and cio_start_key use the same private orb structure of a subchannel, so the orb needs to be cleared of old data before it is used again. A respective memset is missing from cio_start_key and hereby added. Signed-off-by: Stefan Weinhuber Acked-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5954b905e3c..326f4cc7f92 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -174,6 +174,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ CIO_TRACE_EVENT(4, sch->dev.bus_id); orb = &to_io_private(sch)->orb; + memset(orb, 0, sizeof(union orb)); /* sch is always under 2G. */ orb->cmd.intparm = (u32)(addr_t)sch; orb->cmd.fmt = 1; -- GitLab From f948cc6ab9e61a8e88d70ee9aafc690e6d26f92c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Sep 2008 09:53:42 -0700 Subject: [PATCH 1925/5416] sparc64: Fix OOPS in psycho_pcierr_intr_other(). We no longer put the top-level PCI controller device into the PCI layer device list. So pbm->pci_bus->self is always NULL. Therefore, use direct PCI config space accesses to get at the PCI controller's PCI_STATUS register. Tested by Meelis Roos. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index e205ade69cf..f85b6bebb0b 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -575,7 +575,7 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm { unsigned long csr_reg, csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; - u16 stat; + u16 stat, *addr; if (is_pbm_a) { csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; @@ -597,7 +597,9 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm printk("%s: PCI SERR signal asserted.\n", pbm->name); ret = IRQ_HANDLED; } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_STATUS); + pci_config_read16(addr, &stat); if (stat & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | @@ -605,7 +607,7 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm PCI_STATUS_SIG_SYSTEM_ERROR)) { printk("%s: PCI bus error, PCI_STATUS[%04x]\n", pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); + pci_config_write16(addr, 0xffff); ret = IRQ_HANDLED; } return ret; -- GitLab From 998564789137921acae9e367b61c5a1dc295653d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 16 Sep 2008 11:17:03 +0200 Subject: [PATCH 1926/5416] x86 setup: drop SWAP_DEV Impact: None (cleanup) SWAP_DEV is unused since 2.6.23-rc1. The comment was already incorrect since (at least) 2.6.12. Signed-off-by: Paul Bolle Signed-off-by: H. Peter Anvin --- arch/x86/boot/header.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index af86e431acf..b993062e9a5 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -30,7 +30,6 @@ SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ /* to be loaded */ ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ #ifndef SVGA_MODE #define SVGA_MODE ASK_VGA -- GitLab From 1577e4b70a04cce39f296cc714da5ad5d272105a Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Tue, 16 Sep 2008 14:19:25 -0400 Subject: [PATCH 1927/5416] Input: jornada720_ts - fix build error ( LONG() usage ) This patch removes the usage of LONG() which is deprecated; we also replace BIT() with BIT_MASK(). signed-off-by: Kristoffer Ericson Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/jornada720_ts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 1aca108b103..b7f1260738a 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -119,8 +119,8 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev) input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); -- GitLab From f1eaf16a9e843aa915b86594b60ec6cd66c9eac7 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Wed, 27 Aug 2008 12:32:25 +0200 Subject: [PATCH 1928/5416] powerpc/cpm1: Fix race condition in CPM1 GPIO library. The CPM1 GPIO library code uses the non thread-safe clrbits32/setbits32 macros. This patch protects them with a spinlock. Based on the CPM2 patch from Laurent Pinchart , commit 639d64456e20cbfc866b18dc03cf9f9babc9c7cd. Signed-off-by: Jochen Friedrich Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/cpm1.c | 74 ++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 4a04823e842..490473ce810 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -546,15 +546,11 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) return !!(in_be16(&iop->dat) & pin_mask); } -static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) +static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, + int value) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; - unsigned long flags; - u16 pin_mask = 1 << (15 - gpio); - - spin_lock_irqsave(&cpm1_gc->lock, flags); if (value) cpm1_gc->cpdata |= pin_mask; @@ -562,6 +558,18 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) cpm1_gc->cpdata &= ~pin_mask; out_be16(&iop->dat, cpm1_gc->cpdata); +} + +static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + unsigned long flags; + u16 pin_mask = 1 << (15 - gpio); + + spin_lock_irqsave(&cpm1_gc->lock, flags); + + __cpm1_gpio16_set(mm_gc, pin_mask, value); spin_unlock_irqrestore(&cpm1_gc->lock, flags); } @@ -569,14 +577,17 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; - u16 pin_mask; + unsigned long flags; + u16 pin_mask = 1 << (15 - gpio); - pin_mask = 1 << (15 - gpio); + spin_lock_irqsave(&cpm1_gc->lock, flags); setbits16(&iop->dir, pin_mask); + __cpm1_gpio16_set(mm_gc, pin_mask, val); - cpm1_gpio16_set(gc, gpio, val); + spin_unlock_irqrestore(&cpm1_gc->lock, flags); return 0; } @@ -584,13 +595,17 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; - u16 pin_mask; + unsigned long flags; + u16 pin_mask = 1 << (15 - gpio); - pin_mask = 1 << (15 - gpio); + spin_lock_irqsave(&cpm1_gc->lock, flags); clrbits16(&iop->dir, pin_mask); + spin_unlock_irqrestore(&cpm1_gc->lock, flags); + return 0; } @@ -655,15 +670,11 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) return !!(in_be32(&iop->dat) & pin_mask); } -static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) +static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, + int value) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; - unsigned long flags; - u32 pin_mask = 1 << (31 - gpio); - - spin_lock_irqsave(&cpm1_gc->lock, flags); if (value) cpm1_gc->cpdata |= pin_mask; @@ -671,6 +682,18 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) cpm1_gc->cpdata &= ~pin_mask; out_be32(&iop->dat, cpm1_gc->cpdata); +} + +static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + unsigned long flags; + u32 pin_mask = 1 << (31 - gpio); + + spin_lock_irqsave(&cpm1_gc->lock, flags); + + __cpm1_gpio32_set(mm_gc, pin_mask, value); spin_unlock_irqrestore(&cpm1_gc->lock, flags); } @@ -678,14 +701,17 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; - u32 pin_mask; + unsigned long flags; + u32 pin_mask = 1 << (31 - gpio); - pin_mask = 1 << (31 - gpio); + spin_lock_irqsave(&cpm1_gc->lock, flags); setbits32(&iop->dir, pin_mask); + __cpm1_gpio32_set(mm_gc, pin_mask, val); - cpm1_gpio32_set(gc, gpio, val); + spin_unlock_irqrestore(&cpm1_gc->lock, flags); return 0; } @@ -693,13 +719,17 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; - u32 pin_mask; + unsigned long flags; + u32 pin_mask = 1 << (31 - gpio); - pin_mask = 1 << (31 - gpio); + spin_lock_irqsave(&cpm1_gc->lock, flags); clrbits32(&iop->dir, pin_mask); + spin_unlock_irqrestore(&cpm1_gc->lock, flags); + return 0; } -- GitLab From 9843099ff46467461d6476a827f6f9701682dbac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Sep 2008 11:44:00 -0700 Subject: [PATCH 1929/5416] sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace. Based upon a report by Meelis Roos. Any function call can try to access the current thread register via the _mcount hooks when the kernel is built with -pg (via ftrace or STACK_DEBUG). That can't be setup properly very early on during the bootup of other cpus for sun4u and some early sun4v systems. So add notrace markers to these specific functions, so that _mcount doesn't get invoked too early. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 5 +++-- arch/sparc64/kernel/traps.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 23963882bc1..7495bc77468 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -866,7 +867,7 @@ static void kill_prom_timer(void) : "g1", "g2"); } -void init_irqwork_curcpu(void) +void notrace init_irqwork_curcpu(void) { int cpu = hard_smp_processor_id(); @@ -897,7 +898,7 @@ static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type } } -void __cpuinit sun4v_register_mondo_queues(int this_cpu) +void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) { struct trap_per_cpu *tb = &trap_block[this_cpu]; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3d924121c79..c824df13f58 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -2453,7 +2454,7 @@ struct trap_per_cpu trap_block[NR_CPUS]; /* This can get invoked before sched_init() so play it super safe * and use hard_smp_processor_id(). */ -void init_cur_cpu_trap(struct thread_info *t) +void notrace init_cur_cpu_trap(struct thread_info *t) { int cpu = hard_smp_processor_id(); struct trap_per_cpu *p = &trap_block[cpu]; -- GitLab From d7ffd5076d4407d54b25bc4b25f3002f74fbafde Mon Sep 17 00:00:00 2001 From: Faisal Latif Date: Tue, 16 Sep 2008 11:56:26 -0700 Subject: [PATCH 1930/5416] RDMA/nes: Fix client side QP destroy Fix QP not being destroyed properly on the client, which leads to userspace programs hanging on exit. This is a missing chunk from the connection management rewrite in commit 6492cdf3 ("RDMA/nes: CM connection setup/teardown rework"). Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_cm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 9f0b964b2c9..499d3cf83e1 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1956,13 +1956,6 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, return ret; cleanup_retrans_entry(cm_node); cm_node->state = NES_CM_STATE_CLOSED; - ret = send_fin(cm_node, NULL); - - if (cm_node->accept_pend) { - BUG_ON(!cm_node->listener); - atomic_dec(&cm_node->listener->pend_accepts_cnt); - BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); - } ret = send_reset(cm_node, NULL); return ret; @@ -2383,6 +2376,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) atomic_inc(&cm_disconnects); cm_event.event = IW_CM_EVENT_DISCONNECT; if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { + issued_disconnect_reset = 1; cm_event.status = IW_CM_EVENT_STATUS_RESET; nes_debug(NES_DBG_CM, "Generating a CM " "Disconnect Event (status reset) for " @@ -2508,7 +2502,6 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) nes_debug(NES_DBG_CM, "Call close API\n"); g_cm_core->api->close(g_cm_core, nesqp->cm_node); - nesqp->cm_node = NULL; } return ret; @@ -2837,6 +2830,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) cm_node->apbvt_set = 1; nesqp->cm_node = cm_node; cm_node->nesqp = nesqp; + nes_add_ref(&nesqp->ibqp); return 0; } @@ -3167,7 +3161,6 @@ static void cm_event_connect_error(struct nes_cm_event *event) if (ret) printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " "ret=%d\n", __func__, __LINE__, ret); - nes_rem_ref(&nesqp->ibqp); cm_id->rem_ref(cm_id); rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); -- GitLab From e8224e4b804b4fd26723191c1891101a5959bb8a Mon Sep 17 00:00:00 2001 From: Yossi Etigin Date: Tue, 16 Sep 2008 11:57:45 -0700 Subject: [PATCH 1931/5416] IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop() Taking rtnl_lock in ipoib_mcast_join_complete() causes a deadlock with ipoib_stop(). We avoid it by scheduling the piece of code that takes the lock on ipoib_workqueue instead of executing it directly. This works because we only flush the ipoib_workqueue with the RTNL not held. The deadlock happens because ipoib_stop() calls ipoib_ib_dev_down() which calls ipoib_mcast_dev_flush(), which calls ipoib_mcast_free(), which calls ipoib_mcast_leave(). The latter calls ib_sa_free_multicast(), and this waits until the multicast completion handler finishes. This handler is ipoib_mcast_join_complete(), which waits for the rtnl_lock(), which was already taken by ipoib_stop(). This bug was introduced in commit a77a57a1 ("IPoIB: Fix deadlock on RTNL in ipoib_stop()"). Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 2 ++ drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 + .../infiniband/ulp/ipoib/ipoib_multicast.c | 31 +++++++++++++------ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b0ffc9abe8c..05eb41b8ab6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -293,6 +293,7 @@ struct ipoib_dev_priv { struct delayed_work pkey_poll_task; struct delayed_work mcast_task; + struct work_struct carrier_on_task; struct work_struct flush_light; struct work_struct flush_normal; struct work_struct flush_heavy; @@ -464,6 +465,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); void ipoib_dev_cleanup(struct net_device *dev); void ipoib_mcast_join_task(struct work_struct *work); +void ipoib_mcast_carrier_on_task(struct work_struct *work); void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); void ipoib_mcast_restart_task(struct work_struct *work); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7e9e218738f..1b1df5cc411 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1075,6 +1075,7 @@ static void ipoib_setup(struct net_device *dev) INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); + INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ac33c8f3ea8..aae28620a6e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -366,6 +366,21 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast) return ret; } +void ipoib_mcast_carrier_on_task(struct work_struct *work) +{ + struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, + carrier_on_task); + + /* + * Take rtnl_lock to avoid racing with ipoib_stop() and + * turning the carrier back on while a device is being + * removed. + */ + rtnl_lock(); + netif_carrier_on(priv->dev); + rtnl_unlock(); +} + static int ipoib_mcast_join_complete(int status, struct ib_sa_multicast *multicast) { @@ -392,16 +407,12 @@ static int ipoib_mcast_join_complete(int status, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); - if (mcast == priv->broadcast) { - /* - * Take RTNL lock here to avoid racing with - * ipoib_stop() and turning the carrier back - * on while a device is being removed. - */ - rtnl_lock(); - netif_carrier_on(dev); - rtnl_unlock(); - } + /* + * Defer carrier on work to ipoib_workqueue to avoid a + * deadlock on rtnl_lock here. + */ + if (mcast == priv->broadcast) + queue_work(ipoib_workqueue, &priv->carrier_on_task); return 0; } -- GitLab From 5f0319a79043457d2555f059fac68c1d840ce381 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 16 Sep 2008 14:05:16 -0400 Subject: [PATCH 1932/5416] cifs: clean up variables in cifs_unlink Change parameters to cifs_unlink to match the ones used in the generic VFS. Add some local variables to cut down on the amount of struct dereferencing that needs to be done, and eliminate some unneeded NULL pointer checks on the parent directory inode. Finally, rename pTcon to "tcon" to more closely match standard kernel coding style. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.h | 2 +- fs/cifs/inode.c | 90 ++++++++++++++++++++++-------------------------- 2 files changed, 42 insertions(+), 50 deletions(-) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 135c965c413..f7b4a5cd837 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -41,7 +41,7 @@ extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *); extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *); -extern int cifs_unlink(struct inode *, struct dentry *); +extern int cifs_unlink(struct inode *dir, struct dentry *dentry); extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t); extern int cifs_mkdir(struct inode *, struct dentry *, int); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9c548f11010..511c5261679 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -665,40 +665,34 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) return inode; } -int cifs_unlink(struct inode *inode, struct dentry *direntry) +int cifs_unlink(struct inode *dir, struct dentry *dentry) { int rc = 0; int xid; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; char *full_path = NULL; + struct inode *inode = dentry->d_inode; struct cifsInodeInfo *cifsInode; + struct super_block *sb = dir->i_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + struct cifsTconInfo *tcon = cifs_sb->tcon; FILE_BASIC_INFO *pinfo_buf; - cFYI(1, ("cifs_unlink, inode = 0x%p", inode)); + cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); xid = GetXid(); - if (inode) - cifs_sb = CIFS_SB(inode->i_sb); - else - cifs_sb = CIFS_SB(direntry->d_sb); - pTcon = cifs_sb->tcon; - - /* Unlink can be called from rename so we can not grab the sem here - since we deadlock otherwise */ -/* mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/ - full_path = build_path_from_dentry(direntry); -/* mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/ + /* Unlink can be called from rename so we can not take the + * sb->s_vfs_rename_mutex here */ + full_path = build_path_from_dentry(dentry); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } - if ((pTcon->ses->capabilities & CAP_UNIX) && + if ((tcon->ses->capabilities & CAP_UNIX) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(pTcon->fsUnixInfo.Capability))) { - rc = CIFSPOSIXDelFile(xid, pTcon, full_path, + le64_to_cpu(tcon->fsUnixInfo.Capability))) { + rc = CIFSPOSIXDelFile(xid, tcon, full_path, SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, ("posix del rc %d", rc)); @@ -706,31 +700,31 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) goto psx_del_no_retry; } - rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls, + rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); psx_del_no_retry: if (!rc) { - if (direntry->d_inode) - drop_nlink(direntry->d_inode); + if (inode) + drop_nlink(inode); } else if (rc == -ENOENT) { - d_drop(direntry); + d_drop(dentry); } else if (rc == -ETXTBSY) { int oplock = 0; __u16 netfid; - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { - CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, + CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - CIFSSMBClose(xid, pTcon, netfid); - if (direntry->d_inode) - drop_nlink(direntry->d_inode); + CIFSSMBClose(xid, tcon, netfid); + if (inode) + drop_nlink(inode); } } else if (rc == -EACCES) { /* try only if r/o attribute set in local lookup data? */ @@ -738,8 +732,8 @@ psx_del_no_retry: if (pinfo_buf) { /* ATTRS set to normal clears r/o bit */ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); - if (!(pTcon->ses->flags & CIFS_SES_NT4)) - rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, + if (!(tcon->ses->flags & CIFS_SES_NT4)) + rc = CIFSSMBSetPathInfo(xid, tcon, full_path, pinfo_buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -750,7 +744,7 @@ psx_del_no_retry: if (rc == -EOPNOTSUPP) { int oplock = 0; __u16 netfid; - /* rc = CIFSSMBSetAttrLegacy(xid, pTcon, + /* rc = CIFSSMBSetAttrLegacy(xid, tcon, full_path, (__u16)ATTR_NORMAL, cifs_sb->local_nls); @@ -761,7 +755,7 @@ psx_del_no_retry: /* BB could scan to see if we already have it open and pass in pid of opener to function */ - rc = CIFSSMBOpen(xid, pTcon, full_path, + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 0, &netfid, &oplock, NULL, @@ -769,28 +763,28 @@ psx_del_no_retry: cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { - rc = CIFSSMBSetFileInfo(xid, pTcon, + rc = CIFSSMBSetFileInfo(xid, tcon, pinfo_buf, netfid, current->tgid); - CIFSSMBClose(xid, pTcon, netfid); + CIFSSMBClose(xid, tcon, netfid); } } kfree(pinfo_buf); } if (rc == 0) { - rc = CIFSSMBDelFile(xid, pTcon, full_path, + rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { - if (direntry->d_inode) - drop_nlink(direntry->d_inode); + if (inode) + drop_nlink(inode); } else if (rc == -ETXTBSY) { int oplock = 0; __u16 netfid; - rc = CIFSSMBOpen(xid, pTcon, full_path, + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, @@ -799,30 +793,28 @@ psx_del_no_retry: cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { - CIFSSMBRenameOpenFile(xid, pTcon, + CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - CIFSSMBClose(xid, pTcon, netfid); - if (direntry->d_inode) - drop_nlink(direntry->d_inode); + CIFSSMBClose(xid, tcon, netfid); + if (inode) + drop_nlink(inode); } /* BB if rc = -ETXTBUSY goto the rename logic BB */ } } } - if (direntry->d_inode) { - cifsInode = CIFS_I(direntry->d_inode); - cifsInode->time = 0; /* will force revalidate to get info - when needed */ - direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); - } if (inode) { - inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); cifsInode = CIFS_I(inode); - cifsInode->time = 0; /* force revalidate of dir as well */ + cifsInode->time = 0; /* will force revalidate to get info + when needed */ + inode->i_ctime = current_fs_time(sb); } + dir->i_ctime = dir->i_mtime = current_fs_time(sb); + cifsInode = CIFS_I(dir); + cifsInode->time = 0; /* force revalidate of dir as well */ kfree(full_path); FreeXid(xid); -- GitLab From 2344abbcbdb82140050e8be29d3d55e4f6fe860b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 16 Sep 2008 11:32:50 -0700 Subject: [PATCH 1933/5416] clockevents: make device shutdown robust The device shut down does not cleanup the next_event variable of the clock event device. So when the device is reactivated the possible stale next_event value can prevent the device to be reprogrammed as it claims to wait on a event already. This is the root cause of the resurfacing suspend/resume problem, where systems need key press to come back to life. Fix this by setting next_event to KTIME_MAX when the device is shut down. Use a separate function for shutdown which takes care of that and only keep the direct set mode call in the broadcast code, where we can not touch the next_event value. Signed-off-by: Thomas Gleixner --- kernel/time/clockevents.c | 12 +++++++++++- kernel/time/tick-broadcast.c | 9 ++++----- kernel/time/tick-common.c | 4 ++-- kernel/time/tick-internal.h | 2 ++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 1876b526c77..f8d968063ce 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -71,6 +71,16 @@ void clockevents_set_mode(struct clock_event_device *dev, } } +/** + * clockevents_shutdown - shutdown the device and clear next_event + * @dev: device to shutdown + */ +void clockevents_shutdown(struct clock_event_device *dev) +{ + clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); + dev->next_event.tv64 = KTIME_MAX; +} + /** * clockevents_program_event - Reprogram the clock event device. * @expires: absolute expiry time (monotonic clock) @@ -206,7 +216,7 @@ void clockevents_exchange_device(struct clock_event_device *old, if (new) { BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); - clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(new); } local_irq_restore(flags); } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2f5a38294bf..f1f3eee2811 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -236,8 +236,7 @@ static void tick_do_broadcast_on_off(void *why) if (!cpu_isset(cpu, tick_broadcast_mask)) { cpu_set(cpu, tick_broadcast_mask); if (td->mode == TICKDEV_MODE_PERIODIC) - clockevents_set_mode(dev, - CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(dev); } if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) tick_broadcast_force = 1; @@ -254,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why) if (cpus_empty(tick_broadcast_mask)) { if (!bc_stopped) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); } else if (bc_stopped) { if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) tick_broadcast_start_periodic(bc); @@ -306,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup) if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { if (bc && cpus_empty(tick_broadcast_mask)) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); } spin_unlock_irqrestore(&tick_broadcast_lock, flags); @@ -321,7 +320,7 @@ void tick_suspend_broadcast(void) bc = tick_broadcast_device.evtdev; if (bc) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); spin_unlock_irqrestore(&tick_broadcast_lock, flags); } diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index c4777193d56..019315ebf9d 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -249,7 +249,7 @@ static int tick_check_new_device(struct clock_event_device *newdev) * not give it back to the clockevents layer ! */ if (tick_is_broadcast_device(curdev)) { - clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(curdev); curdev = NULL; } clockevents_exchange_device(curdev, newdev); @@ -311,7 +311,7 @@ static void tick_suspend(void) unsigned long flags; spin_lock_irqsave(&tick_device_lock, flags); - clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(td->evtdev); spin_unlock_irqrestore(&tick_device_lock, flags); } diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 0ffc2918ea6..6e9db9734aa 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -10,6 +10,8 @@ extern int tick_do_timer_cpu __read_mostly; extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); extern void tick_handle_periodic(struct clock_event_device *dev); +extern void clockevents_shutdown(struct clock_event_device *dev); + /* * NO_HZ / high resolution timer shared code */ -- GitLab From 612f9d338a6060f814ef35b7108b43407a5df423 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 9 Sep 2008 14:43:39 -0500 Subject: [PATCH 1934/5416] powerpc: Fix interrupt values for DMA2 in MPC8610 HPCD device tree For Freescale 8xxx devices that use an MPIC, the interrupt numbers in the device tree must be 16 greater than the values documented in the reference manual. In these chips, the MPIC is wired to use the first 16 numbers for external interrupts, but the documentation numbers internal interrupts from 0. In the MPC8610 HPCD device tree, the interrupt properties for the DMA channels for DMA2 were not the adjusted values. This fixes that. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/boot/dts/mpc8610_hpcd.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 3b3a1062cb2..584a4f184eb 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -281,7 +281,7 @@ cell-index = <0>; reg = <0x0 0x80>; interrupt-parent = <&mpic>; - interrupts = <60 2>; + interrupts = <76 2>; }; dma-channel@1 { compatible = "fsl,mpc8610-dma-channel", @@ -289,7 +289,7 @@ cell-index = <1>; reg = <0x80 0x80>; interrupt-parent = <&mpic>; - interrupts = <61 2>; + interrupts = <77 2>; }; dma-channel@2 { compatible = "fsl,mpc8610-dma-channel", @@ -297,7 +297,7 @@ cell-index = <2>; reg = <0x100 0x80>; interrupt-parent = <&mpic>; - interrupts = <62 2>; + interrupts = <78 2>; }; dma-channel@3 { compatible = "fsl,mpc8610-dma-channel", @@ -305,7 +305,7 @@ cell-index = <3>; reg = <0x180 0x80>; interrupt-parent = <&mpic>; - interrupts = <63 2>; + interrupts = <79 2>; }; }; -- GitLab From 97fc0555dae8f4d437c8672c14d7191962429be4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 16 Sep 2008 15:09:26 -0700 Subject: [PATCH 1935/5416] x86 setup: handle more than 8 CPU flag words Checkin e38e05a85828dac23540cd007df5f20985388afc added a 9th CPU flag word, but didn't adjust the boot code to match. This patch adds the necessary boot code support. Note: due to a typo in an #if statement, it didn't trigger the #error this was supposed to do. Signed-off-by: H. Peter Anvin --- arch/x86/boot/cpu.c | 17 +++++++++-------- arch/x86/boot/mkcpustr.c | 38 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/arch/x86/boot/cpu.c b/arch/x86/boot/cpu.c index 75298fe2edc..6ec6bb6e995 100644 --- a/arch/x86/boot/cpu.c +++ b/arch/x86/boot/cpu.c @@ -59,17 +59,18 @@ int validate_cpu(void) u32 e = err_flags[i]; for (j = 0; j < 32; j++) { - int n = (i << 5)+j; - if (*msg_strs < n) { + if (msg_strs[0] < i || + (msg_strs[0] == i && msg_strs[1] < j)) { /* Skip to the next string */ - do { - msg_strs++; - } while (*msg_strs); - msg_strs++; + msg_strs += 2; + while (*msg_strs++) + ; } if (e & 1) { - if (*msg_strs == n && msg_strs[1]) - printf("%s ", msg_strs+1); + if (msg_strs[0] == i && + msg_strs[1] == j && + msg_strs[2]) + printf("%s ", msg_strs+2); else printf("%d:%d ", i, j); } diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c index 4589caa3e9d..8ef60f20b37 100644 --- a/arch/x86/boot/mkcpustr.c +++ b/arch/x86/boot/mkcpustr.c @@ -17,31 +17,31 @@ #include "../kernel/cpu/capflags.c" -#if NCAPFLAGS > 8 -# error "Need to adjust the boot code handling of CPUID strings" -#endif - int main(void) { - int i; + int i, j; const char *str; printf("static const char x86_cap_strs[] = \n"); - for (i = 0; i < NCAPINTS*32; i++) { - str = x86_cap_flags[i]; - - if (i == NCAPINTS*32-1) { - /* The last entry must be unconditional; this - also consumes the compiler-added null character */ - if (!str) - str = ""; - printf("\t\"\\x%02x\"\"%s\"\n", i, str); - } else if (str) { - printf("#if REQUIRED_MASK%d & (1 << %d)\n" - "\t\"\\x%02x\"\"%s\\0\"\n" - "#endif\n", - i >> 5, i & 31, i, str); + for (i = 0; i < NCAPINTS; i++) { + for (j = 0; j < 32; j++) { + str = x86_cap_flags[i*32+j]; + + if (i == NCAPINTS-1 && j == 31) { + /* The last entry must be unconditional; this + also consumes the compiler-added null + character */ + if (!str) + str = ""; + printf("\t\"\\x%02x\\x%02x\"\"%s\"\n", + i, j, str); + } else if (str) { + printf("#if REQUIRED_MASK%d & (1 << %d)\n" + "\t\"\\x%02x\\x%02x\"\"%s\\0\"\n" + "#endif\n", + i, j, i, j, str); + } } } printf("\t;\n"); -- GitLab From b08508c40adf3fd1330aabc4f37d3254179776c4 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Tue, 26 Aug 2008 08:20:34 -0700 Subject: [PATCH 1936/5416] PCI: fix compiler warnings in pci_get_subsys() pci_get_subsys() changed in 2.6.26 so that the from pointer is modified when the call is being invoked, so fix up the 'const' marking of it that the compiler is complaining about. Reported-by: Rufus & Azrael Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jesse Barnes --- drivers/pci/search.c | 6 +++--- include/linux/pci.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 3b3b5f17879..4edfc4731bd 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -162,7 +162,7 @@ EXPORT_SYMBOL(pci_find_slot); * time. */ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from) + struct pci_dev *from) { struct pci_dev *pdev; @@ -263,7 +263,7 @@ static int match_pci_dev_by_id(struct device *dev, void *data) * this file. */ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, - const struct pci_dev *from) + struct pci_dev *from) { struct device *dev; struct device *dev_start = NULL; @@ -303,7 +303,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, */ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) + struct pci_dev *from) { struct pci_dev *pdev; struct pci_device_id *id; diff --git a/include/linux/pci.h b/include/linux/pci.h index c0e14008a3c..98dc6243a70 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -534,7 +534,7 @@ extern void pci_sort_breadthfirst(void); #ifdef CONFIG_PCI_LEGACY struct pci_dev __deprecated *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from); + struct pci_dev *from); struct pci_dev __deprecated *pci_find_slot(unsigned int bus, unsigned int devfn); #endif /* CONFIG_PCI_LEGACY */ @@ -550,7 +550,7 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from); struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from); + struct pci_dev *from); struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn); struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn); struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); @@ -816,7 +816,7 @@ _PCI_NOP_ALL(write,) static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from) + struct pci_dev *from) { return NULL; } @@ -838,7 +838,7 @@ static inline struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) + struct pci_dev *from) { return NULL; } -- GitLab From 388e57b2759672a3e3ede0d2f7e95124b417b0a3 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 16 Sep 2008 23:50:58 +0000 Subject: [PATCH 1937/5416] [CIFS] use common code for turning off ATTR_READONLY in cifs_unlink We already have a cifs_set_file_info function that can flip DOS attribute bits. Have cifs_unlink call it to handle turning ATTR_HIDDEN on and ATTR_READONLY off when an unlink attempt returns -EACCES. This also removes a level of indentation from cifs_unlink. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 306 ++++++++++++++++++++++-------------------------- 1 file changed, 139 insertions(+), 167 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 511c5261679..8dbc7c90309 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -665,6 +665,101 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) return inode; } +static int +cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, + char *full_path, __u32 dosattr) +{ + int rc; + int oplock = 0; + __u16 netfid; + __u32 netpid; + bool set_time = false; + struct cifsFileInfo *open_file; + struct cifsInodeInfo *cifsInode = CIFS_I(inode); + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsTconInfo *pTcon = cifs_sb->tcon; + FILE_BASIC_INFO info_buf; + + if (attrs->ia_valid & ATTR_ATIME) { + set_time = true; + info_buf.LastAccessTime = + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); + } else + info_buf.LastAccessTime = 0; + + if (attrs->ia_valid & ATTR_MTIME) { + set_time = true; + info_buf.LastWriteTime = + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); + } else + info_buf.LastWriteTime = 0; + + /* + * Samba throws this field away, but windows may actually use it. + * Do not set ctime unless other time stamps are changed explicitly + * (i.e. by utimes()) since we would then have a mix of client and + * server times. + */ + if (set_time && (attrs->ia_valid & ATTR_CTIME)) { + cFYI(1, ("CIFS - CTIME changed")); + info_buf.ChangeTime = + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); + } else + info_buf.ChangeTime = 0; + + info_buf.CreationTime = 0; /* don't change */ + info_buf.Attributes = cpu_to_le32(dosattr); + + /* + * If the file is already open for write, just use that fileid + */ + open_file = find_writable_file(cifsInode); + if (open_file) { + netfid = open_file->netfid; + netpid = open_file->pid; + goto set_via_filehandle; + } + + /* + * NT4 apparently returns success on this call, but it doesn't + * really work. + */ + if (!(pTcon->ses->flags & CIFS_SES_NT4)) { + rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, + &info_buf, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc != -EOPNOTSUPP && rc != -EINVAL) + goto out; + } + + cFYI(1, ("calling SetFileInfo since SetPathInfo for " + "times not supported by this server")); + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, + SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, + CREATE_NOT_DIR, &netfid, &oplock, + NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + + if (rc != 0) { + if (rc == -EIO) + rc = -EINVAL; + goto out; + } + + netpid = current->tgid; + +set_via_filehandle: + rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); + if (open_file == NULL) + CIFSSMBClose(xid, pTcon, netfid); + else + atomic_dec(&open_file->wrtPending); +out: + return rc; +} + int cifs_unlink(struct inode *dir, struct dentry *dentry) { int rc = 0; @@ -675,7 +770,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) struct super_block *sb = dir->i_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifsTconInfo *tcon = cifs_sb->tcon; - FILE_BASIC_INFO *pinfo_buf; + struct iattr *attrs; + __u32 dosattr; cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); @@ -728,84 +824,55 @@ psx_del_no_retry: } } else if (rc == -EACCES) { /* try only if r/o attribute set in local lookup data? */ - pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); - if (pinfo_buf) { - /* ATTRS set to normal clears r/o bit */ - pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); - if (!(tcon->ses->flags & CIFS_SES_NT4)) - rc = CIFSSMBSetPathInfo(xid, tcon, full_path, - pinfo_buf, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - else - rc = -EOPNOTSUPP; - - if (rc == -EOPNOTSUPP) { - int oplock = 0; - __u16 netfid; - /* rc = CIFSSMBSetAttrLegacy(xid, tcon, - full_path, - (__u16)ATTR_NORMAL, - cifs_sb->local_nls); - For some strange reason it seems that NT4 eats the - old setattr call without actually setting the - attributes so on to the third attempted workaround - */ - - /* BB could scan to see if we already have it open - and pass in pid of opener to function */ - rc = CIFSSMBOpen(xid, tcon, full_path, - FILE_OPEN, SYNCHRONIZE | - FILE_WRITE_ATTRIBUTES, 0, - &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - rc = CIFSSMBSetFileInfo(xid, tcon, - pinfo_buf, - netfid, - current->tgid); - CIFSSMBClose(xid, tcon, netfid); - } - } - kfree(pinfo_buf); + attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); + if (attrs == NULL) { + rc = -ENOMEM; + goto out_reval; } + + /* try to reset dos attributes */ + cifsInode = CIFS_I(inode); + dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; + if (dosattr == 0) + dosattr |= ATTR_NORMAL; + dosattr |= ATTR_HIDDEN; + + rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); + kfree(attrs); + if (rc != 0) + goto out_reval; + rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { - rc = CIFSSMBDelFile(xid, tcon, full_path, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (!rc) { + if (inode) + drop_nlink(inode); + } else if (rc == -ETXTBSY) { + int oplock = 0; + __u16 netfid; + + rc = CIFSSMBOpen(xid, tcon, full_path, + FILE_OPEN, DELETE, + CREATE_NOT_DIR | + CREATE_DELETE_ON_CLOSE, + &netfid, &oplock, NULL, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc == 0) { + CIFSSMBRenameOpenFile(xid, tcon, + netfid, NULL, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFSSMBClose(xid, tcon, netfid); if (inode) drop_nlink(inode); - } else if (rc == -ETXTBSY) { - int oplock = 0; - __u16 netfid; - - rc = CIFSSMBOpen(xid, tcon, full_path, - FILE_OPEN, DELETE, - CREATE_NOT_DIR | - CREATE_DELETE_ON_CLOSE, - &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - CIFSSMBRenameOpenFile(xid, tcon, - netfid, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - CIFSSMBClose(xid, tcon, netfid); - if (inode) - drop_nlink(inode); - } - /* BB if rc = -ETXTBUSY goto the rename logic BB */ } + /* BB if rc = -ETXTBUSY goto the rename logic BB */ } } +out_reval: if (inode) { cifsInode = CIFS_I(inode); cifsInode->time = 0; /* will force revalidate to get info @@ -1498,101 +1565,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, return rc; } -static int -cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, - char *full_path, __u32 dosattr) -{ - int rc; - int oplock = 0; - __u16 netfid; - __u32 netpid; - bool set_time = false; - struct cifsFileInfo *open_file; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsTconInfo *pTcon = cifs_sb->tcon; - FILE_BASIC_INFO info_buf; - - if (attrs->ia_valid & ATTR_ATIME) { - set_time = true; - info_buf.LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); - } else - info_buf.LastAccessTime = 0; - - if (attrs->ia_valid & ATTR_MTIME) { - set_time = true; - info_buf.LastWriteTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); - } else - info_buf.LastWriteTime = 0; - - /* - * Samba throws this field away, but windows may actually use it. - * Do not set ctime unless other time stamps are changed explicitly - * (i.e. by utimes()) since we would then have a mix of client and - * server times. - */ - if (set_time && (attrs->ia_valid & ATTR_CTIME)) { - cFYI(1, ("CIFS - CTIME changed")); - info_buf.ChangeTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); - } else - info_buf.ChangeTime = 0; - - info_buf.CreationTime = 0; /* don't change */ - info_buf.Attributes = cpu_to_le32(dosattr); - - /* - * If the file is already open for write, just use that fileid - */ - open_file = find_writable_file(cifsInode); - if (open_file) { - netfid = open_file->netfid; - netpid = open_file->pid; - goto set_via_filehandle; - } - - /* - * NT4 apparently returns success on this call, but it doesn't - * really work. - */ - if (!(pTcon->ses->flags & CIFS_SES_NT4)) { - rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, - &info_buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != -EOPNOTSUPP && rc != -EINVAL) - goto out; - } - - cFYI(1, ("calling SetFileInfo since SetPathInfo for " - "times not supported by this server")); - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, - CREATE_NOT_DIR, &netfid, &oplock, - NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (rc != 0) { - if (rc == -EIO) - rc = -EINVAL; - goto out; - } - - netpid = current->tgid; - -set_via_filehandle: - rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); - if (open_file == NULL) - CIFSSMBClose(xid, pTcon, netfid); - else - atomic_dec(&open_file->wrtPending); -out: - return rc; -} - static int cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) { -- GitLab From 9e691ed68d94ab3047e028736641445b4cf74d67 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 17 Sep 2008 10:10:41 +1000 Subject: [PATCH 1938/5416] ipvs: only unlock in ip_vs_edit_service() if already locked Jumping to out unlocks __ip_vs_svc_lock, but that lock is not taken until after code that may jump to out. This problem was detected by sparse. make C=1 CHECK net/ipv4/ipvs/ip_vs_ctl.c net/ipv4/ipvs/ip_vs_ctl.c:1332:2: warning: context imbalance in 'ip_vs_edit_service' - unexpected unlock Acked-by: Sven Wegener Acked-by: Julius Volz Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_ctl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 993a83fb0d5..60ca24b9ec0 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -1305,7 +1305,7 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) */ if ((ret = ip_vs_unbind_scheduler(svc))) { old_sched = sched; - goto out; + goto out_unlock; } /* @@ -1324,12 +1324,13 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) */ ip_vs_bind_scheduler(svc, old_sched); old_sched = sched; - goto out; + goto out_unlock; } } - out: + out_unlock: write_unlock_bh(&__ip_vs_svc_lock); + out: if (old_sched) ip_vs_scheduler_put(old_sched); -- GitLab From dff630ddad3884b99fae3ad92f5eccbf26618679 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 17 Sep 2008 10:10:42 +1000 Subject: [PATCH 1939/5416] ipvs: supply a valid 0 address to ip_vs_conn_new() ip_vs_conn_new expects a union nf_inet_addr as the type for its address parameters, not a plain integer. This problem was detected by sparse. make C=1 CHECK net/ipv4/ipvs/ip_vs_core.c net/ipv4/ipvs/ip_vs_core.c:469:9: warning: Using plain integer as NULL pointer Acked-by: Sven Wegener Acked-by: Julius Volz Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 80a4fcf33a5..ece748dbd0c 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -457,6 +457,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) { int ret, cs; struct ip_vs_conn *cp; + union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; ip_vs_service_put(svc); @@ -465,7 +466,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, cp = ip_vs_conn_new(svc->af, iph.protocol, &iph.saddr, pptr[0], &iph.daddr, pptr[1], - 0, 0, + &daddr, 0, IP_VS_CONN_F_BYPASS, NULL); if (cp == NULL) -- GitLab From 563e94f072714657a82a59a3bf81a719a6a25591 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 17 Sep 2008 10:10:42 +1000 Subject: [PATCH 1940/5416] ipvs: add __aquire/__release annotations to ip_vs_info_seq_start/ip_vs_info_seq_stop This teaches sparse that the following are not problems: make C=1 CHECK net/ipv4/ipvs/ip_vs_ctl.c net/ipv4/ipvs/ip_vs_ctl.c:1793:14: warning: context imbalance in 'ip_vs_info_seq_start' - wrong count at exit net/ipv4/ipvs/ip_vs_ctl.c:1842:13: warning: context imbalance in 'ip_vs_info_seq_stop' - unexpected unlock Acked-by: Sven Wegener Acked-by: Julius Volz Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_ctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 60ca24b9ec0..771551d8fba 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -1787,6 +1787,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) } static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos) +__acquires(__ip_vs_svc_lock) { read_lock_bh(&__ip_vs_svc_lock); @@ -1840,6 +1841,7 @@ static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void ip_vs_info_seq_stop(struct seq_file *seq, void *v) +__releases(__ip_vs_svc_lock) { read_unlock_bh(&__ip_vs_svc_lock); } -- GitLab From d286600e199aa2f1058a1f883d234e73626304d2 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Tue, 16 Sep 2008 11:11:11 -0400 Subject: [PATCH 1941/5416] ipvs: change some __constant_htons() to htons() Change __contant_htons() to htons() in the IPVS code when not in an initializer. -Brian Signed-off-by: Brian Haley Acked-by: Julius Volz Signed-off-by: Simon Horman --- net/ipv4/ipvs/ip_vs_proto.c | 2 +- net/ipv4/ipvs/ip_vs_proto_ah_esp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c index b06da1c3445..0791f9e08fe 100644 --- a/net/ipv4/ipvs/ip_vs_proto.c +++ b/net/ipv4/ipvs/ip_vs_proto.c @@ -237,7 +237,7 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp, const char *msg) { #ifdef CONFIG_IP_VS_IPV6 - if (skb->protocol == __constant_htons(ETH_P_IPV6)) + if (skb->protocol == htons(ETH_P_IPV6)) ip_vs_tcpudp_debug_packet_v6(pp, skb, offset, msg); else #endif diff --git a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c index 2b18a78d039..80ab0c8e5b4 100644 --- a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c +++ b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c @@ -167,7 +167,7 @@ ah_esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb, int offset, const char *msg) { #ifdef CONFIG_IP_VS_IPV6 - if (skb->protocol == __constant_htons(ETH_P_IPV6)) + if (skb->protocol == htons(ETH_P_IPV6)) ah_esp_debug_packet_v6(pp, skb, offset, msg); else #endif -- GitLab From e95926d05d028a6bf0ab60b21b484c3d622fdcd1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 16 Sep 2008 19:32:30 -0700 Subject: [PATCH 1942/5416] Revert "b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support" This reverts commit bc19d6e0b74ef03a3baf035412c95192b54dfc6f, which as Larry Finger reports causes the radio LED on his system to no longer respond to rfkill switch events. Reported-by: Larry Finger Requested-by: John W. Linville Signed-off-by: Linus Torvalds --- drivers/net/wireless/b43/rfkill.c | 18 ------------------ drivers/net/wireless/b43legacy/rfkill.c | 18 ------------------ 2 files changed, 36 deletions(-) diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index fec5645944a..34ae125d538 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -43,23 +43,6 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) return 0; } -/* Update the rfkill state */ -static void b43_rfkill_update_state(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (!dev->radio_hw_enable) { - rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; - return; - } - - if (!dev->phy.radio_on) - rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - else - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - -} - /* The poll callback for the hardware button. */ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) { @@ -77,7 +60,6 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; report_change = 1; - b43_rfkill_update_state(dev); b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); } diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 476add97e97..b32bf6a94f1 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -44,23 +44,6 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) return 0; } -/* Update the rfkill state */ -static void b43legacy_rfkill_update_state(struct b43legacy_wldev *dev) -{ - struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); - - if (!dev->radio_hw_enable) { - rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; - return; - } - - if (!dev->phy.radio_on) - rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - else - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - -} - /* The poll callback for the hardware button. */ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) { @@ -78,7 +61,6 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; report_change = 1; - b43legacy_rfkill_update_state(dev); b43legacyinfo(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); } -- GitLab From 49f276be7ce12d90b6941a000b09e61b68e6c4f2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 16 Sep 2008 16:04:12 -0700 Subject: [PATCH 1943/5416] hpplus: fix build regression This fixes kernel regression for 2.6.27-rc in http://bugzilla.kernel.org/show_bug.cgi?id=11547 The change to split 8390 into old isa and non-isa versions overlooked this driver. Signed-off-by: Stephen Hemminger Signed-off-by: Linus Torvalds --- drivers/net/hp-plus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 8239939554b..fbbd3e660c2 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -139,7 +139,7 @@ static int __init do_hpp_probe(struct net_device *dev) #ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = alloc_eip_netdev(); int err; if (!dev) @@ -284,7 +284,7 @@ hpp_open(struct net_device *dev) int option_reg; int retval; - if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) { return retval; } @@ -302,7 +302,7 @@ hpp_open(struct net_device *dev) /* Select the operational page. */ outw(Perf_Page, ioaddr + HP_PAGING); - ei_open(dev); + eip_open(dev); return 0; } @@ -313,7 +313,7 @@ hpp_close(struct net_device *dev) int option_reg = inw(ioaddr + HPP_OPTION); free_irq(dev->irq, dev); - ei_close(dev); + eip_close(dev); outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset, ioaddr + HPP_OPTION); -- GitLab From ef3d7714f6b75b51825ad0384b5ce48358427e50 Mon Sep 17 00:00:00 2001 From: David Miller Date: Tue, 16 Sep 2008 15:00:11 -0700 Subject: [PATCH 1944/5416] Fix PNP build failure, bugzilla #11276 This fill fix the following regression list entry: Bug-Entry : http://bugzilla.kernel.org/show_bug.cgi?id=11276 Subject : build error: CONFIG_OPTIMIZE_INLINING=y causes gcc 4.2 to do stupid things Submitter : Randy Dunlap Date : 2008-08-06 17:18 (38 days old) References : http://marc.info/?l=linux-kernel&m=121804329014332&w=4 http://lkml.org/lkml/2008/7/22/353 Handled-By : Bjorn Helgaas Patch : http://lkml.org/lkml/2008/7/22/364 with what I believe is a better fix than the one referenced in the regression entry above. These PNP header interfaces try to work in such a way that you can reference some of them even if PNP is not enabled, and the compiler was expected to optimize everything away. Which is mostly fine, except that there was one interface for which there was not provided an inline "NOP" implementation. Once we add that, all of these compile failures cannot handle any more. pnp: Provide NOP inline implementation of pnp_get_resource() when !PNP Fixes kernel bugzilla #11276. Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds --- include/linux/pnp.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 1ce54b63085..be764e514e3 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -21,7 +21,14 @@ struct pnp_dev; /* * Resource Management */ +#ifdef CONFIG_PNP struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int); +#else +static inline struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned int type, unsigned int num) +{ + return NULL; +} +#endif static inline int pnp_resource_valid(struct resource *res) { -- GitLab From 45e9c0de2e86485f8b6633fd64ab19cfbff167f6 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 15 Sep 2008 16:43:18 -0700 Subject: [PATCH 1945/5416] warn: Turn the netdev timeout WARN_ON() into a WARN() this patch turns the netdev timeout WARN_ON_ONCE() into a WARN_ONCE(), so that the device and driver names are inside the warning message. This helps automated tools like kerneloops.org to collect the data and do statistics, as well as making it more likely that humans cut-n-paste the important message as part of a bugreport. Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- include/asm-generic/bug.h | 10 ++++++++++ net/sched/sch_generic.c | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index a3f738cffdb..edc6ba82e09 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -97,6 +97,16 @@ extern void warn_slowpath(const char *file, const int line, unlikely(__ret_warn_once); \ }) +#define WARN_ONCE(condition, format...) ({ \ + static int __warned; \ + int __ret_warn_once = !!(condition); \ + \ + if (unlikely(__ret_warn_once)) \ + if (WARN(!__warned, format)) \ + __warned = 1; \ + unlikely(__ret_warn_once); \ +}) + #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON((condition) && __ratelimit(state)) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 9634091ee2f..ec0a0839ce5 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -215,10 +215,9 @@ static void dev_watchdog(unsigned long arg) time_after(jiffies, (dev->trans_start + dev->watchdog_timeo))) { char drivername[64]; - printk(KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", + WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", dev->name, netdev_drivername(dev, drivername, 64)); dev->tx_timeout(dev); - WARN_ON_ONCE(1); } if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + -- GitLab From 31bd61f2bb79e098117d823e054342b03aa87668 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:45:37 +1000 Subject: [PATCH 1946/5416] [XFS] Move memory allocations for log tracing out of the critical path Memory allocations for log->l_grant_trace and iclog->ic_trace are done on demand when the first event is logged. In xlog_state_get_iclog_space() we call xlog_trace_iclog() under a spinlock and allocating memory here can cause us to sleep with a spinlock held and deadlock the system. For the log grant tracing we use KM_NOSLEEP but that means we can lose trace entries. Since there is no locking to serialize the log grant tracing we could race and have multiple allocations and leak memory. So move the allocations to where we initialize the log/iclog structures. Use KM_NOFS to avoid recursing into the filesystem and drop log->l_trace since it's not even used. SGI-PV: 983738 SGI-Modid: xfs-linux-melb:xfs-kern:31896a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_log.c | 60 ++++++++++++++++++++++++++++--------------- fs/xfs/xfs_log_priv.h | 1 - 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ccba14eb9db..7812bd036e2 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -124,16 +124,27 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, STATIC int xlog_iclogs_empty(xlog_t *log); #if defined(XFS_LOG_TRACE) + +#define XLOG_TRACE_LOGGRANT_SIZE 2048 +#define XLOG_TRACE_ICLOG_SIZE 256 + +void +xlog_trace_loggrant_alloc(xlog_t *log) +{ + log->l_grant_trace = ktrace_alloc(XLOG_TRACE_LOGGRANT_SIZE, KM_NOFS); +} + +void +xlog_trace_loggrant_dealloc(xlog_t *log) +{ + ktrace_free(log->l_grant_trace); +} + void xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) { unsigned long cnts; - if (!log->l_grant_trace) { - log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP); - if (!log->l_grant_trace) - return; - } /* ticket counts are 1 byte each */ cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8; @@ -156,11 +167,21 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) (void *)((unsigned long)tic->t_unit_res)); } +void +xlog_trace_iclog_alloc(xlog_in_core_t *iclog) +{ + iclog->ic_trace = ktrace_alloc(XLOG_TRACE_ICLOG_SIZE, KM_NOFS); +} + +void +xlog_trace_iclog_dealloc(xlog_in_core_t *iclog) +{ + ktrace_free(iclog->ic_trace); +} + void xlog_trace_iclog(xlog_in_core_t *iclog, uint state) { - if (!iclog->ic_trace) - iclog->ic_trace = ktrace_alloc(256, KM_NOFS); ktrace_enter(iclog->ic_trace, (void *)((unsigned long)state), (void *)((unsigned long)current_pid()), @@ -170,8 +191,15 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state) (void *)NULL, (void *)NULL); } #else + +#define xlog_trace_loggrant_alloc(log) +#define xlog_trace_loggrant_dealloc(log) #define xlog_trace_loggrant(log,tic,string) + +#define xlog_trace_iclog_alloc(iclog) +#define xlog_trace_iclog_dealloc(iclog) #define xlog_trace_iclog(iclog,state) + #endif /* XFS_LOG_TRACE */ @@ -1231,6 +1259,7 @@ xlog_alloc_log(xfs_mount_t *mp, spin_lock_init(&log->l_grant_lock); sv_init(&log->l_flush_wait, 0, "flush_wait"); + xlog_trace_loggrant_alloc(log); /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); @@ -1285,6 +1314,8 @@ xlog_alloc_log(xfs_mount_t *mp, sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); + xlog_trace_iclog_alloc(iclog); + iclogp = &iclog->ic_next; } *iclogp = log->l_iclog; /* complete ring */ @@ -1565,11 +1596,7 @@ xlog_dealloc_log(xlog_t *log) sv_destroy(&iclog->ic_force_wait); sv_destroy(&iclog->ic_write_wait); xfs_buf_free(iclog->ic_bp); -#ifdef XFS_LOG_TRACE - if (iclog->ic_trace != NULL) { - ktrace_free(iclog->ic_trace); - } -#endif + xlog_trace_iclog_dealloc(iclog); next_iclog = iclog->ic_next; kmem_free(iclog); iclog = next_iclog; @@ -1578,14 +1605,7 @@ xlog_dealloc_log(xlog_t *log) spinlock_destroy(&log->l_grant_lock); xfs_buf_free(log->l_xbuf); -#ifdef XFS_LOG_TRACE - if (log->l_trace != NULL) { - ktrace_free(log->l_trace); - } - if (log->l_grant_trace != NULL) { - ktrace_free(log->l_grant_trace); - } -#endif + xlog_trace_loggrant_dealloc(log); log->l_mp->m_log = NULL; kmem_free(log); } /* xlog_dealloc_log */ diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index c8a5b22ee3e..e7d8f84443f 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -448,7 +448,6 @@ typedef struct log { int l_grant_write_bytes; #ifdef XFS_LOG_TRACE - struct ktrace *l_trace; struct ktrace *l_grant_trace; #endif -- GitLab From 6efdf281777eb07fac28ac2b2d7df1e619ee6da1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 17 Sep 2008 16:49:33 +1000 Subject: [PATCH 1947/5416] [XFS] Fix regression introduced by remount fixup Logically we would return an error in xfs_fs_remount code to prevent users from believing they might have changed mount options using remount which can't be changed. But unfortunately mount(8) adds all options from mtab and fstab to the mount arguments in some cases so we can't blindly reject options, but have to check for each specified option if it actually differs from the currently set option and only reject it if that's the case. Until that is implemented we return success for every remount request, and silently ignore all options that we can't actually change. SGI-PV: 985710 SGI-Modid: xfs-linux-melb:xfs-kern:31908a Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 73c65f19e54..18d3c848783 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1302,9 +1302,29 @@ xfs_fs_remount( mp->m_flags &= ~XFS_MOUNT_BARRIER; break; default: + /* + * Logically we would return an error here to prevent + * users from believing they might have changed + * mount options using remount which can't be changed. + * + * But unfortunately mount(8) adds all options from + * mtab and fstab to the mount arguments in some cases + * so we can't blindly reject options, but have to + * check for each specified option if it actually + * differs from the currently set option and only + * reject it if that's the case. + * + * Until that is implemented we return success for + * every remount request, and silently ignore all + * options that we can't actually change. + */ +#if 0 printk(KERN_INFO "XFS: mount option \"%s\" not supported for remount\n", p); return -EINVAL; +#else + return 0; +#endif } } -- GitLab From 364f358a734ddcd827c662ccbfa58ee3ac510762 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:50:14 +1000 Subject: [PATCH 1948/5416] [XFS] Prevent direct I/O from mapping extents beyond eof With the help from some tracing I found that we try to map extents beyond eof when doing a direct I/O read. It appears that the way to inform the generic direct I/O path (ie do_direct_IO()) that we have breached eof is to return an unmapped buffer from xfs_get_blocks_direct(). This will cause do_direct_IO() to jump to the hole handling code where is will check for eof and then abort. This problem was found because a direct I/O read was trying to map beyond eof and was encountering delayed allocations. The delayed allocations beyond eof are speculative allocations and they didn't get converted when the direct I/O flushed the file because there was only enough space in the current AG to convert and write out the dirty pages within eof. Note that xfs_iomap_write_allocate() wont necessarily convert all the delayed allocation passed to it - it will return after allocating the first extent - so if the delayed allocation extends beyond eof then it will stay that way. SGI-PV: 983683 SGI-Modid: xfs-linux-melb:xfs-kern:31929a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_aops.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index f42f80a3b1f..a44d68eb50b 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1338,6 +1338,10 @@ __xfs_get_blocks( offset = (xfs_off_t)iblock << inode->i_blkbits; ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); size = bh_result->b_size; + + if (!create && direct && offset >= i_size_read(inode)) + return 0; + error = xfs_iomap(XFS_I(inode), offset, size, create ? flags : BMAPI_READ, &iomap, &niomap); if (error) -- GitLab From b5b8c9acd547244eb2b7d0280ba38b9dd01971cc Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 17 Sep 2008 16:50:50 +1000 Subject: [PATCH 1949/5416] [XFS] Fix barrier status change detection. The current code in xlog_iodone() uses the wrong macro to check if the barrier has been cleared due to an EOPNOTSUPP error form the lower layer. SGI-PV: 986143 SGI-Modid: xfs-linux-melb:xfs-kern:31984a Signed-off-by: David Chinner Signed-off-by: Nathaniel W. Turner Signed-off-by: Peter Leckie Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7812bd036e2..503ea89e8b9 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1037,7 +1037,7 @@ xlog_iodone(xfs_buf_t *bp) * layer, it means the underlyin device no longer supports * barrier I/O. Warn loudly and turn off barriers. */ - if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) { + if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; xfs_fs_cmn_err(CE_WARN, l->l_mp, "xlog_iodone: Barriers are no longer supported" -- GitLab From f9114eba1eb08ee75fd0f1eee780f0290fb3c043 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 17 Sep 2008 16:51:21 +1000 Subject: [PATCH 1950/5416] [XFS] Prevent lockdep false positives when locking two inodes. If we call xfs_lock_two_inodes() to grab both the iolock and the ilock, then drop the ilocks on both inodes, then grab them again (as xfs_swap_extents() does) then lockdep will report a locking order problem. This is a false positive. To avoid this, disallow xfs_lock_two_inodes() fom locking both inode locks at once - force calers to make two separate calls. This means that nested dropping and regaining of the ilocks will retain the same lockdep subclass and so lockdep will not see anything wrong with this code. SGI-PV: 986238 SGI-Modid: xfs-linux-melb:xfs-kern:31999a Signed-off-by: David Chinner Signed-off-by: Christoph Hellwig Signed-off-by: Peter Leckie Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_dfrag.c | 9 ++++++++- fs/xfs/xfs_vnodeops.c | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 760f4c5b516..75b0cd4da0e 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -149,7 +149,14 @@ xfs_swap_extents( sbp = &sxp->sx_stat; - xfs_lock_two_inodes(ip, tip, lock_flags); + /* + * we have to do two separate lock calls here to keep lockdep + * happy. If we try to get all the locks in one call, lock will + * report false positives when we drop the ILOCK and regain them + * below. + */ + xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); + xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); locked = 1; /* Verify that both files have the same format */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index aa238c8fbd7..98a0aecafdd 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1838,6 +1838,12 @@ again: #endif } +/* + * xfs_lock_two_inodes() can only be used to lock one type of lock + * at a time - the iolock or the ilock, but not both at once. If + * we lock both at once, lockdep will report false positives saying + * we have violated locking orders. + */ void xfs_lock_two_inodes( xfs_inode_t *ip0, @@ -1848,6 +1854,8 @@ xfs_lock_two_inodes( int attempts = 0; xfs_log_item_t *lp; + if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) + ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0); ASSERT(ip0->i_ino != ip1->i_ino); if (ip0->i_ino > ip1->i_ino) { -- GitLab From e1f5dbd7077eebec794452a516cb02f1669b036d Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:52:13 +1000 Subject: [PATCH 1951/5416] [XFS] Fix use-after-free with buffers We have a use-after-free issue where log completions access buffers via the buffer log item and the buffer has already been freed. Fix this by taking a reference on the buffer when attaching the buffer log item and release the hold when the buffer log item is detached and we no longer need the buffer. Also create a new function xfs_buf_item_free() to combine some common code. SGI-PV: 985757 SGI-Modid: xfs-linux-melb:xfs-kern:32025a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_buf_item.c | 44 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 608c30c3f76..002fc2617c8 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -732,6 +732,7 @@ xfs_buf_item_init( bip->bli_item.li_ops = &xfs_buf_item_ops; bip->bli_item.li_mountp = mp; bip->bli_buf = bp; + xfs_buf_hold(bp); bip->bli_format.blf_type = XFS_LI_BUF; bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); @@ -867,6 +868,21 @@ xfs_buf_item_dirty( return (bip->bli_flags & XFS_BLI_DIRTY); } +STATIC void +xfs_buf_item_free( + xfs_buf_log_item_t *bip) +{ +#ifdef XFS_TRANS_DEBUG + kmem_free(bip->bli_orig); + kmem_free(bip->bli_logged); +#endif /* XFS_TRANS_DEBUG */ + +#ifdef XFS_BLI_TRACE + ktrace_free(bip->bli_trace); +#endif + kmem_zone_free(xfs_buf_item_zone, bip); +} + /* * This is called when the buf log item is no longer needed. It should * free the buf log item associated with the given buffer and clear @@ -887,18 +903,8 @@ xfs_buf_item_relse( (XFS_BUF_IODONE_FUNC(bp) != NULL)) { XFS_BUF_CLR_IODONE_FUNC(bp); } - -#ifdef XFS_TRANS_DEBUG - kmem_free(bip->bli_orig); - bip->bli_orig = NULL; - kmem_free(bip->bli_logged); - bip->bli_logged = NULL; -#endif /* XFS_TRANS_DEBUG */ - -#ifdef XFS_BLI_TRACE - ktrace_free(bip->bli_trace); -#endif - kmem_zone_free(xfs_buf_item_zone, bip); + xfs_buf_rele(bp); + xfs_buf_item_free(bip); } @@ -1120,6 +1126,7 @@ xfs_buf_iodone( ASSERT(bip->bli_buf == bp); + xfs_buf_rele(bp); mp = bip->bli_item.li_mountp; /* @@ -1136,18 +1143,7 @@ xfs_buf_iodone( * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip); - -#ifdef XFS_TRANS_DEBUG - kmem_free(bip->bli_orig); - bip->bli_orig = NULL; - kmem_free(bip->bli_logged); - bip->bli_logged = NULL; -#endif /* XFS_TRANS_DEBUG */ - -#ifdef XFS_BLI_TRACE - ktrace_free(bip->bli_trace); -#endif - kmem_zone_free(xfs_buf_item_zone, bip); + xfs_buf_item_free(bip); } #if defined(XFS_BLI_TRACE) -- GitLab From 2fd6f6ec64ff347447d26646ac6188f3658b383c Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:52:50 +1000 Subject: [PATCH 1952/5416] [XFS] Don't do I/O beyond eof when unreserving space When unreserving space with boundaries that are not block aligned we round up the start and round down the end boundaries and then use this function, xfs_zero_remaining_bytes(), to zero the parts of the blocks that got dropped during the rounding. The problem is we don't consider if these blocks are beyond eof. Worse still is if we encounter delayed allocations beyond eof we will try to use the magic delayed allocation block number as a real block number. If the file size is ever extended to expose these blocks then we'll go through xfs_zero_eof() to zero them anyway. SGI-PV: 983683 SGI-Modid: xfs-linux-melb:xfs-kern:32055a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_vnodeops.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 98a0aecafdd..8b6812f66a1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3160,6 +3160,13 @@ error1: /* Just cancel transaction */ /* * Zero file bytes between startoff and endoff inclusive. * The iolock is held exclusive and no blocks are buffered. + * + * This function is used by xfs_free_file_space() to zero + * partial blocks when the range to free is not block aligned. + * When unreserving space with boundaries that are not block + * aligned we round up the start and round down the end + * boundaries and then use this function to zero the parts of + * the blocks that got dropped during the rounding. */ STATIC int xfs_zero_remaining_bytes( @@ -3176,6 +3183,17 @@ xfs_zero_remaining_bytes( int nimap; int error = 0; + /* + * Avoid doing I/O beyond eof - it's not necessary + * since nothing can read beyond eof. The space will + * be zeroed when the file is extended anyway. + */ + if (startoff >= ip->i_size) + return 0; + + if (endoff > ip->i_size) + endoff = ip->i_size; + bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize, XFS_IS_REALTIME_INODE(ip) ? mp->m_rtdev_targp : mp->m_ddev_targp); -- GitLab From 0855f310dff76ae42c5aac32f600f8f692bbd23f Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Tue, 9 Sep 2008 11:17:29 +0200 Subject: [PATCH 1953/5416] UBIFS: create the name of the background thread in every case If the ubifs partition is mounted RO and then remounted RW we end up with no thread name in ubifs_remount_rw() and the thread appears nameless. Signed-off-by: Sebastian Siewior Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 7562464ac83..3f4902060c7 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1024,14 +1024,13 @@ static int mount_ubifs(struct ubifs_info *c) goto out_dereg; } + sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); if (!mounted_read_only) { err = alloc_wbufs(c); if (err) goto out_cbuf; /* Create background thread */ - sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, - c->vi.vol_id); c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); if (!c->bgt) c->bgt = ERR_PTR(-EINVAL); -- GitLab From ac7643e4d36c63b190709777d9e03392a7d20477 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 15 Sep 2008 04:09:14 -0700 Subject: [PATCH 1954/5416] ARM: DaVinci: Update IO address pointer typechecking Signed-off-by: Kevin Hilman --- arch/arm/mach-davinci/board-evm.c | 2 +- arch/arm/mach-davinci/include/mach/io.h | 43 ++++++++----------------- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index 13435578781..2db7b7850fb 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c @@ -124,7 +124,7 @@ static __init void davinci_evm_irq_init(void) MACHINE_START(DAVINCI_EVM, "DaVinci EVM") /* Maintainer: MontaVista Software */ .phys_io = IO_PHYS, - .io_pg_offst = (io_p2v(IO_PHYS) >> 18) & 0xfffc, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DAVINCI_DDR_BASE + 0x100), .map_io = davinci_evm_map_io, .init_irq = davinci_evm_irq_init, diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index e7accb91086..b78ee914049 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h @@ -22,9 +22,8 @@ #define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */ #define IO_SIZE 0x00400000 #define IO_VIRT (IO_PHYS + IO_OFFSET) -#define io_p2v(pa) ((pa) + IO_OFFSET) #define io_v2p(va) ((va) - IO_OFFSET) -#define IO_ADDRESS(x) io_p2v(x) +#define __IO_ADDRESS(x) ((x) + IO_OFFSET) /* * We don't actually have real ISA nor PCI buses, but there is so many @@ -35,7 +34,12 @@ #define __mem_pci(a) (a) #define __mem_isa(a) (a) -#ifndef __ASSEMBLER__ +#define IO_ADDRESS(pa) IOMEM(__IO_ADDRESS(pa)) + +#ifdef __ASSEMBLER__ +#define IOMEM(x) x +#else +#define IOMEM(x) ((void __force __iomem *)(x)) /* * Functions to access the DaVinci IO region @@ -46,34 +50,13 @@ * - DO NOT use hardcoded virtual addresses to allow changing the * IO address space again if needed */ -#define davinci_readb(a) (*(volatile unsigned char *)IO_ADDRESS(a)) -#define davinci_readw(a) (*(volatile unsigned short *)IO_ADDRESS(a)) -#define davinci_readl(a) (*(volatile unsigned int *)IO_ADDRESS(a)) - -#define davinci_writeb(v,a) (*(volatile unsigned char *)IO_ADDRESS(a) = (v)) -#define davinci_writew(v,a) (*(volatile unsigned short *)IO_ADDRESS(a) = (v)) -#define davinci_writel(v,a) (*(volatile unsigned int *)IO_ADDRESS(a) = (v)) - -/* 16 bit uses LDRH/STRH, base +/- offset_8 */ -typedef struct { volatile u16 offset[256]; } __regbase16; -#define __REGV16(vaddr) ((__regbase16 *)((vaddr)&~0xff)) \ - ->offset[((vaddr)&0xff)>>1] -#define __REG16(paddr) __REGV16(io_p2v(paddr)) - -/* 8/32 bit uses LDR/STR, base +/- offset_12 */ -typedef struct { volatile u8 offset[4096]; } __regbase8; -#define __REGV8(vaddr) ((__regbase8 *)((vaddr)&~4095)) \ - ->offset[((vaddr)&4095)>>0] -#define __REG8(paddr) __REGV8(io_p2v(paddr)) - -typedef struct { volatile u32 offset[4096]; } __regbase32; -#define __REGV32(vaddr) ((__regbase32 *)((vaddr)&~4095)) \ - ->offset[((vaddr)&4095)>>2] - -#define __REG(paddr) __REGV32(io_p2v(paddr)) -#else +#define davinci_readb(a) __raw_readb(IO_ADDRESS(a)) +#define davinci_readw(a) __raw_readw(IO_ADDRESS(a)) +#define davinci_readl(a) __raw_readl(IO_ADDRESS(a)) -#define __REG(x) (*((volatile unsigned long *)io_p2v(x))) +#define davinci_writeb(v, a) __raw_writeb(v, IO_ADDRESS(a)) +#define davinci_writew(v, a) __raw_writew(v, IO_ADDRESS(a)) +#define davinci_writel(v, a) __raw_writel(v, IO_ADDRESS(a)) #endif /* __ASSEMBLER__ */ #endif /* __ASM_ARCH_IO_H */ -- GitLab From dce1115bc32d66237102a4c925e1e0a5e82b9945 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 7 Sep 2008 23:41:04 -0700 Subject: [PATCH 1955/5416] ARM: DaVinci: SOC GPIOs use gpiolib Switch DaVinci SOC gpios over to using the new GPIO library, so it can access GPIO expanders and other non-SOC GPIOs using the same calls. Signed-off-by: David Brownell Signed-off-by: Kevin Hilman --- arch/arm/Kconfig | 1 + arch/arm/mach-davinci/gpio.c | 133 ++++++++++++---------- arch/arm/mach-davinci/include/mach/gpio.h | 73 ++++++------ 3 files changed, 106 insertions(+), 101 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 70dba166890..ea3c858d753 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -515,6 +515,7 @@ config ARCH_DAVINCI select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB select HAVE_CLK help Support for TI's DaVinci platform. diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index c9cb4f09b18..3ebbacdd6db 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -1,7 +1,7 @@ /* * TI DaVinci GPIO Support * - * Copyright (c) 2006 David Brownell + * Copyright (c) 2006-2007 David Brownell * Copyright (c) 2007, MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify @@ -26,47 +26,45 @@ #include -static DEFINE_SPINLOCK(gpio_lock); -static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO); -int gpio_request(unsigned gpio, const char *tag) -{ - if (gpio >= DAVINCI_N_GPIO) - return -EINVAL; +static DEFINE_SPINLOCK(gpio_lock); - if (test_and_set_bit(gpio, gpio_in_use)) - return -EBUSY; +struct davinci_gpio { + struct gpio_chip chip; + struct gpio_controller *__iomem regs; +}; - return 0; -} -EXPORT_SYMBOL(gpio_request); +static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; -void gpio_free(unsigned gpio) -{ - if (gpio >= DAVINCI_N_GPIO) - return; - - clear_bit(gpio, gpio_in_use); -} -EXPORT_SYMBOL(gpio_free); /* create a non-inlined version */ -static struct gpio_controller *__iomem gpio2controller(unsigned gpio) +static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio) { return __gpio_to_controller(gpio); } + +/*--------------------------------------------------------------------------*/ + /* - * Assuming the pin is muxed as a gpio output, set its output value. + * board setup code *MUST* set PINMUX0 and PINMUX1 as + * needed, and enable the GPIO clock. */ -void __gpio_set(unsigned gpio, int value) + +static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; + u32 temp; - __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data); -} -EXPORT_SYMBOL(__gpio_set); + spin_lock(&gpio_lock); + temp = __raw_readl(&g->dir); + temp |= (1 << offset); + __raw_writel(temp, &g->dir); + spin_unlock(&gpio_lock); + return 0; +} /* * Read the pin's value (works even if it's set up as output); @@ -75,61 +73,72 @@ EXPORT_SYMBOL(__gpio_set); * Note that changes are synched to the GPIO clock, so reading values back * right after you've set them may give old values. */ -int __gpio_get(unsigned gpio) +static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; - return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); + return (1 << offset) & __raw_readl(&g->in_data); } -EXPORT_SYMBOL(__gpio_get); - -/*--------------------------------------------------------------------------*/ - -/* - * board setup code *MUST* set PINMUX0 and PINMUX1 as - * needed, and enable the GPIO clock. - */ - -int gpio_direction_input(unsigned gpio) +static int +davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; u32 temp; - u32 mask; - - if (!g) - return -EINVAL; + u32 mask = 1 << offset; spin_lock(&gpio_lock); - mask = __gpio_mask(gpio); temp = __raw_readl(&g->dir); - temp |= mask; + temp &= ~mask; + __raw_writel(mask, value ? &g->set_data : &g->clr_data); __raw_writel(temp, &g->dir); spin_unlock(&gpio_lock); return 0; } -EXPORT_SYMBOL(gpio_direction_input); -int gpio_direction_output(unsigned gpio, int value) +/* + * Assuming the pin is muxed as a gpio output, set its output value. + */ +static void +davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct gpio_controller *__iomem g = gpio2controller(gpio); - u32 temp; - u32 mask; + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; - if (!g) - return -EINVAL; + __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); +} + +static int __init davinci_gpio_setup(void) +{ + int i, base; + + for (i = 0, base = 0; + i < ARRAY_SIZE(chips); + i++, base += 32) { + chips[i].chip.label = "DaVinci"; + + chips[i].chip.direction_input = davinci_direction_in; + chips[i].chip.get = davinci_gpio_get; + chips[i].chip.direction_output = davinci_direction_out; + chips[i].chip.set = davinci_gpio_set; + + chips[i].chip.base = base; + chips[i].chip.ngpio = DAVINCI_N_GPIO - base; + if (chips[i].chip.ngpio > 32) + chips[i].chip.ngpio = 32; + + chips[i].regs = gpio2controller(base); + + gpiochip_add(&chips[i].chip); + } - spin_lock(&gpio_lock); - mask = __gpio_mask(gpio); - temp = __raw_readl(&g->dir); - temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); - __raw_writel(temp, &g->dir); - spin_unlock(&gpio_lock); return 0; } -EXPORT_SYMBOL(gpio_direction_output); +pure_initcall(davinci_gpio_setup); +/*--------------------------------------------------------------------------*/ /* * We expect irqs will normally be set up as input pins, but they can also be * used as output pins ... which is convenient for testing. diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index ec151ccf1e8..b3a2961f0f4 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -14,6 +14,7 @@ #define __DAVINCI_GPIO_H #include +#include #include /* @@ -27,13 +28,16 @@ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are * used as gpios, not with other peripherals. * - * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe - * for later updates, code should write GPIO(N) or: + * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, + * and maybe for later updates, code should write GPIO(N) or: * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53) * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70) * * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc * for now, that's != GPIO(N) + * + * GPIOs can also be on external chips, numbered after the ones built-in + * to the DaVinci chip. For now, they won't be usable as IRQ sources. */ #define GPIO(X) (X) /* 0 <= X <= 70 */ #define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */ @@ -67,11 +71,11 @@ __gpio_to_controller(unsigned gpio) void *__iomem ptr; if (gpio < 32) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); else if (gpio < 64) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); else if (gpio < DAVINCI_N_GPIO) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); else ptr = NULL; return ptr; @@ -83,25 +87,17 @@ static inline u32 __gpio_mask(unsigned gpio) } /* The get/set/clear functions will inline when called with constant - * parameters, for low-overhead bitbanging. Illegal constant parameters - * cause link-time errors. + * parameters referencing built-in GPIOs, for low-overhead bitbanging. * - * Otherwise, calls with variable parameters use outlined functions. + * Otherwise, calls with variable parameters or referencing external + * GPIOs (e.g. on GPIO expander chips) use outlined functions. */ -extern int __error_inval_gpio(void); - -extern void __gpio_set(unsigned gpio, int value); -extern int __gpio_get(unsigned gpio); - static inline void gpio_set_value(unsigned gpio, int value) { - if (__builtin_constant_p(value)) { + if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) { struct gpio_controller *__iomem g; u32 mask; - if (gpio >= DAVINCI_N_GPIO) - __error_inval_gpio(); - g = __gpio_to_controller(gpio); mask = __gpio_mask(gpio); if (value) @@ -111,48 +107,47 @@ static inline void gpio_set_value(unsigned gpio, int value) return; } - __gpio_set(gpio, value); + __gpio_set_value(gpio, value); } /* Returns zero or nonzero; works for gpios configured as inputs OR - * as outputs. + * as outputs, at least for built-in GPIOs. * - * NOTE: changes in reported values are synchronized to the GPIO clock. - * This is most easily seen after calling gpio_set_value() and then immediatly - * gpio_get_value(), where the gpio_get_value() would return the old value - * until the GPIO clock ticks and the new value gets latched. + * NOTE: for built-in GPIOs, changes in reported values are synchronized + * to the GPIO clock. This is easily seen after calling gpio_set_value() + * and then immediately gpio_get_value(), where the gpio_get_value() will + * return the old value until the GPIO clock ticks and the new value gets + * latched. */ - static inline int gpio_get_value(unsigned gpio) { - struct gpio_controller *__iomem g; - - if (!__builtin_constant_p(gpio)) - return __gpio_get(gpio); + struct gpio_controller *__iomem g; - if (gpio >= DAVINCI_N_GPIO) - return __error_inval_gpio(); + if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO) + return __gpio_get_value(gpio); g = __gpio_to_controller(gpio); - return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); + return __gpio_mask(gpio) & __raw_readl(&g->in_data); } -/* powerup default direction is IN */ -extern int gpio_direction_input(unsigned gpio); -extern int gpio_direction_output(unsigned gpio, int value); - -#include /* cansleep wrappers */ - -extern int gpio_request(unsigned gpio, const char *tag); -extern void gpio_free(unsigned gpio); +static inline int gpio_cansleep(unsigned gpio) +{ + if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO) + return 0; + else + return __gpio_cansleep(gpio); +} static inline int gpio_to_irq(unsigned gpio) { + if (gpio >= DAVINCI_N_GPIO) + return -EINVAL; return DAVINCI_N_AINTC_IRQ + gpio; } static inline int irq_to_gpio(unsigned irq) { + /* caller guarantees gpio_to_irq() succeeded */ return irq - DAVINCI_N_AINTC_IRQ; } -- GitLab From d395e6ad98912b52a299999ab667de9a1f393c91 Mon Sep 17 00:00:00 2001 From: Komal Shah Date: Sun, 7 Sep 2008 23:41:28 -0700 Subject: [PATCH 1956/5416] ARM: DaVinci: i2c setup Davinci I2C initialization infrastructure; will be used by EVM init. [ dbrownell@users.sourceforge.net: pass platform data into init code ] Signed-off-by: Komal Shah Signed-off-by: Kevin Hilman Signed-off-by: David Brownell --- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/devices.c | 48 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/i2c.h | 7 +++- 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-davinci/devices.c diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 99ac2e55774..bddfbb71706 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ - gpio.o mux.o + gpio.o mux.o devices.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c new file mode 100644 index 00000000000..3d4b1de8f89 --- /dev/null +++ b/arch/arm/mach-davinci/devices.c @@ -0,0 +1,48 @@ +/* + * mach-davinci/devices.c + * + * DaVinci platform device setup/initialization + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +static struct resource i2c_resources[] = { + { + .start = DAVINCI_I2C_BASE, + .end = DAVINCI_I2C_BASE + 0x40, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device davinci_i2c_device = { + .name = "i2c_davinci", + .id = 1, + .num_resources = ARRAY_SIZE(i2c_resources), + .resource = i2c_resources, +}; + +void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata) +{ + davinci_i2c_device.dev.platform_data = pdata; + (void) platform_device_register(&davinci_i2c_device); +} + diff --git a/arch/arm/mach-davinci/include/mach/i2c.h b/arch/arm/mach-davinci/include/mach/i2c.h index e2f54168abd..c248e9b7e82 100644 --- a/arch/arm/mach-davinci/include/mach/i2c.h +++ b/arch/arm/mach-davinci/include/mach/i2c.h @@ -14,8 +14,11 @@ /* All frequencies are expressed in kHz */ struct davinci_i2c_platform_data { - unsigned int bus_freq; /* standard bus frequency */ - unsigned int bus_delay; /* transaction delay */ + unsigned int bus_freq; /* standard bus frequency (kHz) */ + unsigned int bus_delay; /* post-transaction delay (usec) */ }; +/* for board setup code */ +void davinci_init_i2c(struct davinci_i2c_platform_data *); + #endif /* __ASM_ARCH_I2C_H */ -- GitLab From cece6e5af23815ae4cfa6d3dab1303f80b42feef Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 7 Sep 2008 23:41:57 -0700 Subject: [PATCH 1957/5416] ARM: DaVinci: usb setup Declare the musb_hdrc platform device for DaVinci. Signed-off-by: David Brownell Signed-off-by: Kevin Hilman --- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/include/mach/common.h | 3 + arch/arm/mach-davinci/usb.c | 116 ++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-davinci/usb.c diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index bddfbb71706..4dc458597f4 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ - gpio.o mux.o devices.o + gpio.o mux.o devices.o usb.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index a97dfbb15e5..4b522e5c70e 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -16,4 +16,7 @@ struct sys_timer; extern struct sys_timer davinci_timer; +/* parameters describe VBUS sourcing for host mode */ +extern void setup_usb(unsigned mA, unsigned potpgt_msec); + #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */ diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c new file mode 100644 index 00000000000..fe182a85159 --- /dev/null +++ b/arch/arm/mach-davinci/usb.c @@ -0,0 +1,116 @@ +/* + * USB + */ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) +static struct musb_hdrc_eps_bits musb_eps[] = { + { "ep1_tx", 8, }, + { "ep1_rx", 8, }, + { "ep2_tx", 8, }, + { "ep2_rx", 8, }, + { "ep3_tx", 5, }, + { "ep3_rx", 5, }, + { "ep4_tx", 5, }, + { "ep4_rx", 5, }, +}; + +static struct musb_hdrc_config musb_config = { + .multipoint = true, + .dyn_fifo = true, + .soft_con = true, + .dma = true, + + .num_eps = 5, + .dma_channels = 8, + .ram_bits = 10, + .eps_bits = musb_eps, +}; + +static struct musb_hdrc_platform_data usb_data = { +#if defined(CONFIG_USB_MUSB_OTG) + /* OTG requires a Mini-AB connector */ + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) + .mode = MUSB_PERIPHERAL, +#elif defined(CONFIG_USB_MUSB_HOST) + .mode = MUSB_HOST, +#endif + .config = &musb_config, +}; + +static struct resource usb_resources[] = { + { + /* physical address */ + .start = DAVINCI_USB_OTG_BASE, + .end = DAVINCI_USB_OTG_BASE + 0x5ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_USBINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 usb_dmamask = DMA_32BIT_MASK; + +static struct platform_device usb_dev = { + .name = "musb_hdrc", + .id = -1, + .dev = { + .platform_data = &usb_data, + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .resource = usb_resources, + .num_resources = ARRAY_SIZE(usb_resources), +}; + +#ifdef CONFIG_USB_MUSB_OTG + +static struct otg_transceiver *xceiv; + +struct otg_transceiver *otg_get_transceiver(void) +{ + if (xceiv) + get_device(xceiv->dev); + return xceiv; +} +EXPORT_SYMBOL(otg_get_transceiver); + +int otg_set_transceiver(struct otg_transceiver *x) +{ + if (xceiv && x) + return -EBUSY; + xceiv = x; + return 0; +} +EXPORT_SYMBOL(otg_set_transceiver); + +#endif + +void __init setup_usb(unsigned mA, unsigned potpgt_msec) +{ + usb_data.power = mA / 2; + usb_data.potpgt = potpgt_msec / 2; + platform_device_register(&usb_dev); +} + +#else + +void __init setup_usb(unsigned mA, unsigned potpgt_msec) +{ +} + +#endif /* CONFIG_USB_MUSB_HDRC */ + -- GitLab From 7bff3c4ce44ea48f50dc47a5994454984bd08c59 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 7 Sep 2008 23:43:02 -0700 Subject: [PATCH 1958/5416] ARM: DaVinci: evm sets up many devices Update DaVinci EVM board setup to work with key drivers which are now in mainline kernels: - I2C adapter (driver: i2c_davinci) * three gpio expanders (driver: pcf8574) used for - LEDs - audio codec control - misc device control (including USB VBUS, IDE-vs-CF) * at24 (driver: at24) eeprom - USB controller (driver: musb_hdrc) - IDE controller (driver: palm_bk3710) This board is the first in-tree client for a number of those drivers, and adding this board support means the EVM board can be used for some "real work" ... excepting "DaVinci Technology" video and DSP support (also available in most OMAP3 chips). Also renames the flash as "evm_norflash", since NAND may be jumpered. (Patch contains work by myself, Kevin Hilman, Sergei Shtylyov.) Signed-off-by: David Brownell Signed-off-by: Kevin Hilman Cc: Sergei Shtylyov --- arch/arm/mach-davinci/board-evm.c | 337 ++++++++++++++++++++++++++++-- 1 file changed, 322 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index 2db7b7850fb..9581675f658 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c @@ -13,6 +13,13 @@ #include #include #include +#include +#include + +#include +#include +#include + #include #include #include @@ -20,13 +27,14 @@ #include #include #include -#include #include #include #include +#include #include +#include /* other misc. init functions */ void __init davinci_psc_init(void); @@ -34,10 +42,10 @@ void __init davinci_irq_init(void); void __init davinci_map_common_io(void); void __init davinci_init_common_hw(void); -/* NOR Flash base address set to CS0 by default */ -#define NOR_FLASH_PHYS 0x02000000 +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) -static struct mtd_partition davinci_evm_partitions[] = { +static struct mtd_partition davinci_evm_norflash_partitions[] = { /* bootloader (U-Boot, etc) in first 4 sectors */ { .name = "bootloader", @@ -68,32 +76,323 @@ static struct mtd_partition davinci_evm_partitions[] = { } }; -static struct physmap_flash_data davinci_evm_flash_data = { +static struct physmap_flash_data davinci_evm_norflash_data = { .width = 2, - .parts = davinci_evm_partitions, - .nr_parts = ARRAY_SIZE(davinci_evm_partitions), + .parts = davinci_evm_norflash_partitions, + .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions), }; /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF * limits addresses to 16M, so using addresses past 16M will wrap */ -static struct resource davinci_evm_flash_resource = { - .start = NOR_FLASH_PHYS, - .end = NOR_FLASH_PHYS + SZ_16M - 1, +static struct resource davinci_evm_norflash_resource = { + .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, + .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; -static struct platform_device davinci_evm_flash_device = { +static struct platform_device davinci_evm_norflash_device = { .name = "physmap-flash", .id = 0, .dev = { - .platform_data = &davinci_evm_flash_data, + .platform_data = &davinci_evm_norflash_data, }, .num_resources = 1, - .resource = &davinci_evm_flash_resource, + .resource = &davinci_evm_norflash_resource, +}; + +#endif + +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) + +static struct resource ide_resources[] = { + { + .start = DAVINCI_CFC_ATA_BASE, + .end = DAVINCI_CFC_ATA_BASE + 0x7ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_IDE, + .end = IRQ_IDE, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ide_dma_mask = DMA_32BIT_MASK; + +static struct platform_device ide_dev = { + .name = "palm_bk3710", + .id = -1, + .resource = ide_resources, + .num_resources = ARRAY_SIZE(ide_resources), + .dev = { + .dma_mask = &ide_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, +}; + +#endif + +/*----------------------------------------------------------------------*/ + +/* + * I2C GPIO expanders + */ + +#define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8)) + + +/* U2 -- LEDs */ + +static struct gpio_led evm_leds[] = { + { .name = "DS8", .active_low = 1, + .default_trigger = "heartbeat", }, + { .name = "DS7", .active_low = 1, }, + { .name = "DS6", .active_low = 1, }, + { .name = "DS5", .active_low = 1, }, + { .name = "DS4", .active_low = 1, }, + { .name = "DS3", .active_low = 1, }, + { .name = "DS2", .active_low = 1, + .default_trigger = "mmc0", }, + { .name = "DS1", .active_low = 1, + .default_trigger = "ide-disk", }, +}; + +static const struct gpio_led_platform_data evm_led_data = { + .num_leds = ARRAY_SIZE(evm_leds), + .leds = evm_leds, +}; + +static struct platform_device *evm_led_dev; + +static int +evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + struct gpio_led *leds = evm_leds; + int status; + + while (ngpio--) { + leds->gpio = gpio++; + leds++; + } + + /* what an extremely annoying way to be forced to handle + * device unregistration ... + */ + evm_led_dev = platform_device_alloc("leds-gpio", 0); + platform_device_add_data(evm_led_dev, + &evm_led_data, sizeof evm_led_data); + + evm_led_dev->dev.parent = &client->dev; + status = platform_device_add(evm_led_dev); + if (status < 0) { + platform_device_put(evm_led_dev); + evm_led_dev = NULL; + } + return status; +} + +static int +evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + if (evm_led_dev) { + platform_device_unregister(evm_led_dev); + evm_led_dev = NULL; + } + return 0; +} + +static struct pcf857x_platform_data pcf_data_u2 = { + .gpio_base = PCF_Uxx_BASE(0), + .setup = evm_led_setup, + .teardown = evm_led_teardown, +}; + + +/* U18 - A/V clock generator and user switch */ + +static int sw_gpio; + +static ssize_t +sw_show(struct device *d, struct device_attribute *a, char *buf) +{ + char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n"; + + strcpy(buf, s); + return strlen(s); +} + +static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL); + +static int +evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + int status; + + /* export dip switch option */ + sw_gpio = gpio + 7; + status = gpio_request(sw_gpio, "user_sw"); + if (status == 0) + status = gpio_direction_input(sw_gpio); + if (status == 0) + status = device_create_file(&client->dev, &dev_attr_user_sw); + else + gpio_free(sw_gpio); + if (status != 0) + sw_gpio = -EINVAL; + + /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */ + gpio_request(gpio + 3, "pll_fs2"); + gpio_direction_output(gpio + 3, 0); + + gpio_request(gpio + 2, "pll_fs1"); + gpio_direction_output(gpio + 2, 0); + + gpio_request(gpio + 1, "pll_sr"); + gpio_direction_output(gpio + 1, 0); + + return 0; +} + +static int +evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + gpio_free(gpio + 1); + gpio_free(gpio + 2); + gpio_free(gpio + 3); + + if (sw_gpio > 0) { + device_remove_file(&client->dev, &dev_attr_user_sw); + gpio_free(sw_gpio); + } + return 0; +} + +static struct pcf857x_platform_data pcf_data_u18 = { + .gpio_base = PCF_Uxx_BASE(1), + .n_latch = (1 << 3) | (1 << 2) | (1 << 1), + .setup = evm_u18_setup, + .teardown = evm_u18_teardown, }; + +/* U35 - various I/O signals used to manage USB, CF, ATA, etc */ + +static int +evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + /* p0 = nDRV_VBUS (initial: don't supply it) */ + gpio_request(gpio + 0, "nDRV_VBUS"); + gpio_direction_output(gpio + 0, 1); + + /* p1 = VDDIMX_EN */ + gpio_request(gpio + 1, "VDDIMX_EN"); + gpio_direction_output(gpio + 1, 1); + + /* p2 = VLYNQ_EN */ + gpio_request(gpio + 2, "VLYNQ_EN"); + gpio_direction_output(gpio + 2, 1); + + /* p3 = n3V3_CF_RESET (initial: stay in reset) */ + gpio_request(gpio + 3, "nCF_RESET"); + gpio_direction_output(gpio + 3, 0); + + /* (p4 unused) */ + + /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */ + gpio_request(gpio + 5, "WLAN_RESET"); + gpio_direction_output(gpio + 5, 1); + + /* p6 = nATA_SEL (initial: select) */ + gpio_request(gpio + 6, "nATA_SEL"); + gpio_direction_output(gpio + 6, 0); + + /* p7 = nCF_SEL (initial: deselect) */ + gpio_request(gpio + 7, "nCF_SEL"); + gpio_direction_output(gpio + 7, 1); + + return 0; +} + +static int +evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + gpio_free(gpio + 7); + gpio_free(gpio + 6); + gpio_free(gpio + 5); + gpio_free(gpio + 3); + gpio_free(gpio + 2); + gpio_free(gpio + 1); + gpio_free(gpio + 0); + return 0; +} + +static struct pcf857x_platform_data pcf_data_u35 = { + .gpio_base = PCF_Uxx_BASE(2), + .setup = evm_u35_setup, + .teardown = evm_u35_teardown, +}; + +/*----------------------------------------------------------------------*/ + +/* Most of this EEPROM is unused, but U-Boot uses some data: + * - 0x7f00, 6 bytes Ethernet Address + * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL) + * - ... newer boards may have more + */ +static struct at24_platform_data eeprom_info = { + .byte_len = (256*1024) / 8, + .page_size = 64, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info __initdata i2c_info[] = { + { + I2C_BOARD_INFO("pcf8574", 0x38), + .platform_data = &pcf_data_u2, + }, + { + I2C_BOARD_INFO("pcf8574", 0x39), + .platform_data = &pcf_data_u18, + }, + { + I2C_BOARD_INFO("pcf8574", 0x3a), + .platform_data = &pcf_data_u35, + }, + { + I2C_BOARD_INFO("24c256", 0x50), + .platform_data = &eeprom_info, + }, + /* ALSO: + * - tvl320aic33 audio codec (0x1b) + * - msp430 microcontroller (0x23) + * - tvp5146 video decoder (0x5d) + */ +}; + +/* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz), + * which requires 100 usec of idle bus after i2c writes sent to it. + */ +static struct davinci_i2c_platform_data i2c_pdata = { + .bus_freq = 20 /* kHz */, + .bus_delay = 100 /* usec */, +}; + +static void __init evm_init_i2c(void) +{ + davinci_init_i2c(&i2c_pdata); + i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); +} + static struct platform_device *davinci_evm_devices[] __initdata = { - &davinci_evm_flash_device, +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) + &davinci_evm_norflash_device, +#endif +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) + &ide_dev, +#endif }; static void __init @@ -106,13 +405,21 @@ static __init void davinci_evm_init(void) { davinci_psc_init(); -#if defined(CONFIG_BLK_DEV_DAVINCI) || defined(CONFIG_BLK_DEV_DAVINCI_MODULE) +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, " "but share pins.\n\t Disable IDE for NOR support.\n"); +#endif #endif platform_add_devices(davinci_evm_devices, ARRAY_SIZE(davinci_evm_devices)); + evm_init_i2c(); + + /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ + setup_usb(500, 8); } static __init void davinci_evm_irq_init(void) -- GitLab From 90f7d25c6b672137344f447a30a9159945ffea72 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 16 Sep 2008 11:27:30 -0700 Subject: [PATCH 1959/5416] x86: print DMI information in the oops trace in order to diagnose hard system specific issues, it's useful to have the system name in the oops (as provided by DMI) Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 0c3927accb0..7b9ee9f0963 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -160,6 +161,7 @@ void __show_registers(struct pt_regs *regs, int all) unsigned long d0, d1, d2, d3, d6, d7; unsigned long sp; unsigned short ss, gs; + const char *board; if (user_mode_vm(regs)) { sp = regs->sp; @@ -172,11 +174,15 @@ void __show_registers(struct pt_regs *regs, int all) } printk("\n"); - printk("Pid: %d, comm: %s %s (%s %.*s)\n", + + board = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!board) + board = ""; + printk("Pid: %d, comm: %s %s (%s %.*s) %s\n", task_pid_nr(current), current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); + init_utsname()->version, board); printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", (u16)regs->cs, regs->ip, regs->flags, -- GitLab From 6dcfac4f13d6b32fbaa60b64a23249999e66af8e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 12 Sep 2008 12:27:47 +0300 Subject: [PATCH 1960/5416] UBIFS: TNC / GC race fixes - update GC sequence number if any nodes may have been moved even if GC did not finish the LEB - don't ignore error return when reading Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 14 +++++++++++--- fs/ubifs/tnc.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 13f1019c859..02aba36fe3d 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) err = move_nodes(c, sleb); if (err) - goto out; + goto out_inc_seq; err = gc_sync_wbufs(c); if (err) - goto out; + goto out_inc_seq; err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); if (err) - goto out; + goto out_inc_seq; /* Allow for races with TNC */ c->gced_lnum = lnum; @@ -369,6 +369,14 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) out: ubifs_scan_destroy(sleb); return err; + +out_inc_seq: + /* We may have moved at least some nodes so allow for races with TNC */ + c->gced_lnum = lnum; + smp_wmb(); + c->gc_seq += 1; + smp_wmb(); + goto out; } /** diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 7da209ab937..7634c597088 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1476,7 +1476,7 @@ again: } err = fallible_read_node(c, key, &zbr, node); - if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) { /* * The node may have been GC'ed out from under us so try again * while keeping the TNC mutex locked. -- GitLab From 6e14968c869cd30e236bb626dd0c16421d2a658d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 17 Sep 2008 10:52:07 +0300 Subject: [PATCH 1961/5416] UBIFS: remove incorrect assert The assert was not valid because one of the variables 'taken_empty_lebs' has transient values out of sync with the other variables. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/find.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index e045c8b5542..47814cde240 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -507,7 +507,6 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; - ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); if (rsvd_idx_lebs < lebs) /* * OK to allocate an empty LEB, but we still don't want to go -- GitLab From fbdbf709938d155c719c76b9894d28342632c797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 15 Sep 2008 22:02:43 +0200 Subject: [PATCH 1962/5416] x86, debug: gpio_free might sleep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the documentation gpio_free should only be called from task context only. To make this more explicit add a might sleep to all implementations. This patch changes the gpio_free implementations for the x86 architecture. Signed-off-by: Uwe Kleine-König Signed-off-by: Ingo Molnar --- include/asm-x86/mach-rdc321x/gpio.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h index acce0b7d397..3639ece6485 100644 --- a/include/asm-x86/mach-rdc321x/gpio.h +++ b/include/asm-x86/mach-rdc321x/gpio.h @@ -1,6 +1,8 @@ #ifndef _RDC321X_GPIO_H #define _RDC321X_GPIO_H +#include + extern int rdc_gpio_get_value(unsigned gpio); extern void rdc_gpio_set_value(unsigned gpio, int value); extern int rdc_gpio_direction_input(unsigned gpio); @@ -18,6 +20,7 @@ static inline int gpio_request(unsigned gpio, const char *label) static inline void gpio_free(unsigned gpio) { + might_sleep(); rdc_gpio_free(gpio); } -- GitLab From 32dde0f975e430f00f03f80f7dbab585d8b45eab Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Sep 2008 04:00:28 +0000 Subject: [PATCH 1963/5416] powerpc: Holly board needs dtbImage target One of the changes in the bootwrapper makefile introduced the dtbImage targets for boards that need a simple zImage with a DTB embedded in them (595be948cce574ff2d5dde5d0426a636a4363c70, "[POWERPC] bootwrapper: Build multiple cuImages"). When this was done, it broke booting on the Holly board as the zImage.holly wrapper did not get the DTB embedded properly. This changes the target for the Holly board to a dtbImage so that the wrapper includes the vmlinux, wrapper bits, and DTB. Signed-off-by: Josh Boyer Signed-off-by: Paul Mackerras --- arch/powerpc/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 717a3bc1352..65d1a8454d2 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -195,7 +195,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac -image-$(CONFIG_PPC_HOLLY) += zImage.holly +image-$(CONFIG_PPC_HOLLY) += dtbImage.holly image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage -- GitLab From 2d291e902791e1c8d72bc223b6f063bbb27a1280 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 9 Sep 2008 14:04:18 +0000 Subject: [PATCH 1964/5416] Fix compile failure with non modular builds Commit deac93df26b20cf8438339b5935b5f5643bc30c9 ("lib: Correct printk %pF to work on all architectures") broke the non modular builds by moving an essential function into modules.c. Fix this by moving it out again and into asm/sections.h as an inline. To do this, the definition of struct ppc64_opd_entry has been lifted out of modules.c and put in asm/elf.h where it belongs. Signed-off-by: James Bottomley Signed-off-by: Paul Mackerras --- arch/powerpc/include/asm/elf.h | 7 +++++++ arch/powerpc/include/asm/sections.h | 12 +++++++++++- arch/powerpc/kernel/module_64.c | 19 ------------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 80d1f399ee5..64c6ee22eef 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -409,6 +409,13 @@ do { \ /* Keep this the last entry. */ #define R_PPC64_NUM 107 +/* There's actually a third entry here, but it's unused */ +struct ppc64_opd_entry +{ + unsigned long funcaddr; + unsigned long r2; +}; + #ifdef __KERNEL__ #ifdef CONFIG_SPU_BASE diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 7710e9e6660..07956f3e784 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -2,6 +2,8 @@ #define _ASM_POWERPC_SECTIONS_H #ifdef __KERNEL__ +#include +#include #include #ifdef __powerpc64__ @@ -17,7 +19,15 @@ static inline int in_kernel_text(unsigned long addr) } #undef dereference_function_descriptor -void *dereference_function_descriptor(void *); +static inline void *dereference_function_descriptor(void *ptr) +{ + struct ppc64_opd_entry *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->funcaddr, p)) + ptr = p; + return ptr; +} #endif diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ad79de272ff..1af2377e499 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -21,9 +21,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -43,13 +41,6 @@ #define DEBUGP(fmt , ...) #endif -/* There's actually a third entry here, but it's unused */ -struct ppc64_opd_entry -{ - unsigned long funcaddr; - unsigned long r2; -}; - /* Like PPC32, we need little trampolines to do > 24-bit jumps (into the kernel itself). But on PPC64, these need to be used for every jump, actually, to reset r2 (TOC+0x8000). */ @@ -452,13 +443,3 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; } - -void *dereference_function_descriptor(void *ptr) -{ - struct ppc64_opd_entry *desc = ptr; - void *p; - - if (!probe_kernel_address(&desc->funcaddr, p)) - ptr = p; - return ptr; -} -- GitLab From 6ae19b04ab41a4db0f0c48ec0b78950f6b028823 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 10 Sep 2008 12:06:15 -0400 Subject: [PATCH 1965/5416] Input: ads7846 - introduce .gpio_pendown to get pendown state The GPIO connected to ADS7846 nPENIRQ signal is usually used to get the pendown state as well. Introduce a .gpio_pendown, and use this to decide the pendown state if .get_pendown_state is NULL. Signed-off-by: Eric Miao Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 68 +++++++++++++++++++++++------ include/linux/spi/ads7846.h | 3 ++ 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index ce6f48c695f..8583c766d56 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ struct ads7846 { void *filter_data; void (*filter_cleanup)(void *data); int (*get_pendown_state)(void); + int gpio_pendown; }; /* leave chip selected when we're done, for quicker re-select? */ @@ -491,6 +493,14 @@ static struct attribute_group ads784x_attr_group = { /*--------------------------------------------------------------------------*/ +static int get_pendown_state(struct ads7846 *ts) +{ + if (ts->get_pendown_state) + return ts->get_pendown_state(); + + return !gpio_get_value(ts->gpio_pendown); +} + /* * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, * to retrieve touchscreen status. @@ -550,7 +560,7 @@ static void ads7846_rx(void *ads) */ if (ts->penirq_recheck_delay_usecs) { udelay(ts->penirq_recheck_delay_usecs); - if (!ts->get_pendown_state()) + if (!get_pendown_state(ts)) Rt = 0; } @@ -677,7 +687,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) spin_lock_irq(&ts->lock); - if (unlikely(!ts->get_pendown_state() || + if (unlikely(!get_pendown_state(ts) || device_suspended(&ts->spi->dev))) { if (ts->pendown) { struct input_dev *input = ts->input; @@ -716,7 +726,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle) unsigned long flags; spin_lock_irqsave(&ts->lock, flags); - if (likely(ts->get_pendown_state())) { + if (likely(get_pendown_state(ts))) { if (!ts->irq_disabled) { /* The ARM do_simple_IRQ() dispatcher doesn't act * like the other dispatchers: it will report IRQs @@ -806,6 +816,36 @@ static int ads7846_resume(struct spi_device *spi) return 0; } +static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts) +{ + struct ads7846_platform_data *pdata = spi->dev.platform_data; + int err; + + /* REVISIT when the irq can be triggered active-low, or if for some + * reason the touchscreen isn't hooked up, we don't need to access + * the pendown state. + */ + if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { + dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); + return -EINVAL; + } + + if (pdata->get_pendown_state) { + ts->get_pendown_state = pdata->get_pendown_state; + return 0; + } + + err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); + if (err) { + dev_err(&spi->dev, "failed to request pendown GPIO%d\n", + pdata->gpio_pendown); + return err; + } + + ts->gpio_pendown = pdata->gpio_pendown; + return 0; +} + static int __devinit ads7846_probe(struct spi_device *spi) { struct ads7846 *ts; @@ -833,15 +873,6 @@ static int __devinit ads7846_probe(struct spi_device *spi) return -EINVAL; } - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (pdata->get_pendown_state == NULL) { - dev_dbg(&spi->dev, "no get_pendown_state function?\n"); - return -EINVAL; - } - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except * that even if the hardware can do that, the SPI controller driver * may not. So we stick to very-portable 8 bit words, both RX and TX. @@ -893,7 +924,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->filter_data = ts; } else ts->filter = ads7846_no_filter; - ts->get_pendown_state = pdata->get_pendown_state; + + err = setup_pendown(spi, ts); + if (err) + goto err_cleanup_filter; if (pdata->penirq_recheck_delay_usecs) ts->penirq_recheck_delay_usecs = @@ -1085,7 +1119,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) spi->dev.driver->name, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); err = -EBUSY; - goto err_cleanup_filter; + goto err_free_gpio; } err = ads784x_hwmon_register(spi, ts); @@ -1116,6 +1150,9 @@ static int __devinit ads7846_probe(struct spi_device *spi) ads784x_hwmon_unregister(spi, ts); err_free_irq: free_irq(spi->irq, ts); + err_free_gpio: + if (ts->gpio_pendown != -1) + gpio_free(ts->gpio_pendown); err_cleanup_filter: if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); @@ -1140,6 +1177,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) /* suspend left the IRQ disabled */ enable_irq(ts->spi->irq); + if (ts->gpio_pendown != -1) + gpio_free(ts->gpio_pendown); + if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h index daf744017a3..05eab2f11e6 100644 --- a/include/linux/spi/ads7846.h +++ b/include/linux/spi/ads7846.h @@ -43,6 +43,9 @@ struct ads7846_platform_data { u16 debounce_tol; /* tolerance used for filtering */ u16 debounce_rep; /* additional consecutive good readings * required after the first two */ + int gpio_pendown; /* the GPIO used to decide the pendown + * state if get_pendown_state == NULL + */ int (*get_pendown_state)(void); int (*filter_init) (struct ads7846_platform_data *pdata, void **filter_data); -- GitLab From 1562f98f918f2de7549edbaaabdb8bece52320f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 17 Sep 2008 20:36:49 +0100 Subject: [PATCH 1966/5416] [ARM] Fix IOP13xx build warnings http://armlinux.simtec.co.uk/kautobuild/2.6.27-rc5/iop13xx_defconfig/zimage.log Occurrences Warning text 339 arch/arm/include/asm/dma-mapping.h:40: warning: return makes pointer from integer without a cast 203 arch/arm/include/asm/dma-mapping.h:45: warning: return makes integer from pointer without a cast Acked-by: Dan Williams Signed-off-by: Russell King --- arch/arm/mach-iop13xx/include/mach/memory.h | 58 ++++++++++++++------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index a74b027432d..b82602d529b 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h @@ -26,32 +26,52 @@ /* RAM has 1:1 mapping on the PCIe/x Busses */ #define __virt_to_bus(x) (__virt_to_phys(x)) -#define __bus_to_virt(x) (__phys_to_virt(x)) +#define __bus_to_virt(x) (__phys_to_virt(x)) -#define virt_to_lbus(x) \ -(( ((void*)(x) >= (void*)IOP13XX_PMMR_V_START) && \ -((void*)(x) < (void*)IOP13XX_PMMR_V_END) ) ? \ -((x) - IOP13XX_PMMR_VIRT_MEM_BASE + IOP13XX_PMMR_PHYS_MEM_BASE) : \ -((x) - PAGE_OFFSET + PHYS_OFFSET)) +static inline dma_addr_t __virt_to_lbus(unsigned long x) +{ + return x + IOP13XX_PMMR_PHYS_MEM_BASE - IOP13XX_PMMR_VIRT_MEM_BASE; +} -#define lbus_to_virt(x) \ -(( ((x) >= IOP13XX_PMMR_P_START) && ((x) < IOP13XX_PMMR_P_END) ) ? \ -((x) - IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_VIRT_MEM_BASE ) : \ -((x) - PHYS_OFFSET + PAGE_OFFSET)) +static inline unsigned long __lbus_to_virt(dma_addr_t x) +{ + return x + IOP13XX_PMMR_VIRT_MEM_BASE - IOP13XX_PMMR_PHYS_MEM_BASE; +} + +#define __is_lbus_dma(a) \ + ((a) >= IOP13XX_PMMR_P_START && (a) < IOP13XX_PMMR_P_END) + +#define __is_lbus_virt(a) \ + ((a) >= IOP13XX_PMMR_V_START && (a) < IOP13XX_PMMR_V_END) /* Device is an lbus device if it is on the platform bus of the IOP13XX */ -#define is_lbus_device(dev) (dev &&\ - (strncmp(dev->bus->name, "platform", 8) == 0)) +#define is_lbus_device(dev) \ + (dev && strncmp(dev->bus->name, "platform", 8) == 0) -#define __arch_page_to_dma(dev, page) \ -({is_lbus_device(dev) ? (dma_addr_t)virt_to_lbus(page_address(page)) : \ -(dma_addr_t)__virt_to_bus(page_address(page));}) +#define __arch_dma_to_virt(dev, addr) \ + ({ \ + unsigned long __virt; \ + dma_addr_t __dma = addr; \ + if (is_lbus_device(dev) && __is_lbus_dma(__dma)) \ + __virt = __lbus_to_virt(__dma); \ + else \ + __virt = __bus_to_virt(__dma); \ + (void *)__virt; \ + }) -#define __arch_dma_to_virt(dev, addr) \ -({is_lbus_device(dev) ? lbus_to_virt(addr) : __bus_to_virt(addr);}) +#define __arch_virt_to_dma(dev, addr) \ + ({ \ + unsigned long __virt = (unsigned long)addr; \ + dma_addr_t __dma; \ + if (is_lbus_device(dev) && __is_lbus_virt(__virt)) \ + __dma = __virt_to_lbus(__virt); \ + else \ + __dma = __virt_to_bus(__virt); \ + __dma; \ + }) -#define __arch_virt_to_dma(dev, addr) \ -({is_lbus_device(dev) ? virt_to_lbus(addr) : __virt_to_bus(addr);}) +#define __arch_page_to_dma(dev, page) \ + __arch_virt_to_dma(dev, page_address(page)) #endif /* CONFIG_ARCH_IOP13XX */ #endif /* !ASSEMBLY */ -- GitLab From 380b0fdfd0227d7604cd91ad97fb846ba643e0e7 Mon Sep 17 00:00:00 2001 From: roelkluin Date: Mon, 15 Sep 2008 20:56:44 +0100 Subject: [PATCH 1967/5416] [ARM] 5249/1: davinci: remove redundant check in davinci_psc_config() id is unsigned, check is redundant. Signed-off-by: Roel Kluin Signed-off-by: Russell King --- arch/arm/mach-davinci/psc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 720c48b9ee0..aa2fc375a32 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -70,9 +70,6 @@ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) { u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; - if (id < 0) - return; - mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); if (enable) mdctl |= 0x00000003; /* Enable Module */ -- GitLab From c2fe59444e1827ecd2713a1e6ecfd1ab1fc548ae Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 6 Aug 2008 11:48:25 -0500 Subject: [PATCH 1968/5416] powerpc: add SSI-to-DMA properties to Freescale MPC8610 HPCD device tree Add the fsl,playback-dma and fsl,capture-dma properties to the Freescale MPC8610 HPCD device tree. These properties connect the SSI nodes to the DMA nodes for the DMA channels that the SSI should use. Also update the ssi.txt documentation. These properties will be needed when the ASoC V2 version of the Freescale MPC8610 device drivers are merged into the mainline. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- Documentation/powerpc/dts-bindings/fsl/ssi.txt | 15 +++++++++++++++ arch/powerpc/boot/dts/mpc8610_hpcd.dts | 8 +++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Documentation/powerpc/dts-bindings/fsl/ssi.txt b/Documentation/powerpc/dts-bindings/fsl/ssi.txt index d100555d488..5d9841303ca 100644 --- a/Documentation/powerpc/dts-bindings/fsl/ssi.txt +++ b/Documentation/powerpc/dts-bindings/fsl/ssi.txt @@ -24,6 +24,12 @@ Required properties: "rj-master" - r.j., SSI is clock master "ac97-slave" - AC97 mode, SSI is clock slave "ac97-master" - AC97 mode, SSI is clock master +- fsl,playback-dma: phandle to a DMA node for the DMA channel to use for + playback of audio. This is typically dictated by SOC + design. See the notes below. +- fsl,capture-dma: phandle to a DMA node for the DMA channel to use for + capture (recording) of audio. This is typically dictated + by SOC design. See the notes below. Optional properties: - codec-handle : phandle to a 'codec' node that defines an audio @@ -36,3 +42,12 @@ Child 'codec' node required properties: Child 'codec' node optional properties: - clock-frequency : The frequency of the input clock, which typically comes from an on-board dedicated oscillator. + +Notes on fsl,playback-dma and fsl,capture-dma: + +On SOCs that have an SSI, specific DMA channels are hard-wired for playback +and capture. On the MPC8610, for example, SSI1 must use DMA channel 0 for +playback and DMA channel 1 for capture. SSI2 must use DMA channel 2 for +playback and DMA channel 3 for capture. The developer can choose which +DMA controller to use, but the channels themselves are hard-wired. The +purpose of these two properties is to represent this hardware design. diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 3b3a1062cb2..0f3a36e0ea6 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -207,7 +207,7 @@ reg = <0xe4000 0x100>; }; - i2s@16000 { + ssi@16000 { compatible = "fsl,mpc8610-ssi"; cell-index = <0>; reg = <0x16000 0x100>; @@ -215,6 +215,8 @@ interrupts = <62 2>; fsl,mode = "i2s-slave"; codec-handle = <&cs4270>; + fsl,playback-dma = <&dma00>; + fsl,capture-dma = <&dma01>; }; ssi@16100 { @@ -233,7 +235,7 @@ reg = <0x21300 0x4>; /* DMA general status register */ ranges = <0x0 0x21100 0x200>; - dma-channel@0 { + dma00: dma-channel@0 { compatible = "fsl,mpc8610-dma-channel", "fsl,eloplus-dma-channel"; cell-index = <0>; @@ -241,7 +243,7 @@ interrupt-parent = <&mpic>; interrupts = <20 2>; }; - dma-channel@1 { + dma01: dma-channel@1 { compatible = "fsl,mpc8610-dma-channel", "fsl,eloplus-dma-channel"; cell-index = <1>; -- GitLab From 7e8bc3c6db9b4b74842b1c70bbf5c2a99a112b0d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 17 Sep 2008 20:58:11 +0100 Subject: [PATCH 1969/5416] [ARM] omap: back out 'internal_clock' support The structures weren't ready for this change: arch/arm/plat-omap/devices.c:320: error: 'struct omap_mmc_conf' has no member named 'internal_clock' arch/arm/plat-omap/devices.c:326: error: implicit declaration of function 'omap_ctrl_readl' arch/arm/plat-omap/devices.c:326: error: 'OMAP2_CONTROL_DEVCONF0' undeclared (first use in this function) arch/arm/plat-omap/devices.c:328: error: implicit declaration of function 'omap_ctrl_writel' Signed-off-by: Russell King --- arch/arm/plat-omap/devices.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index bc1cf30c83e..01da719a745 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -316,19 +316,6 @@ static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf) omap_cfg_reg(MMC_DAT3); } } -#if defined(CONFIG_ARCH_OMAP2420) - if (mmc_conf->mmc[0].internal_clock) { - /* - * Use internal loop-back in MMC/SDIO - * Module Input Clock selection - */ - if (cpu_is_omap24xx()) { - u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - v |= (1 << 24); /* not used in 243x */ - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - } - } -#endif } #ifdef CONFIG_ARCH_OMAP16XX -- GitLab From 7424bac82ff3bd956ea04101550e01bdae17284d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 17 Sep 2008 22:09:41 +0400 Subject: [PATCH 1970/5416] UBIFS: fix printk format warnings fs/ubifs/dir.c:428: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type 'long unsigned int' fs/ubifs/debug.c:541: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type 'long unsigned int' Signed-off-by: Alexander Beregalov Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 +- fs/ubifs/dir.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b9cb7747375..d7f7645779f 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); for (i = 0; i < n; i++) printk(KERN_DEBUG "\t ino %llu\n", - le64_to_cpu(orph->inos[i])); + (unsigned long long)le64_to_cpu(orph->inos[i])); break; } default: diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 2b267c9a180..526c01ec800 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", - dent->name, le64_to_cpu(dent->inum), + dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); -- GitLab From ee2fa7435b6dddf1ca119f298ad0100cf50c0397 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 13:47:25 +0200 Subject: [PATCH 1971/5416] AMD IOMMU: set iommu sunc flag after command queuing The iommu->need_sync flag must be set after the command is queued to avoid race conditions. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 69b4d060b21..a96d8c049a8 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -140,6 +140,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid) { struct iommu_cmd cmd; + int ret; BUG_ON(iommu == NULL); @@ -147,9 +148,11 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid) CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY); cmd.data[0] = devid; + ret = iommu_queue_command(iommu, &cmd); + iommu->need_sync = 1; - return iommu_queue_command(iommu, &cmd); + return ret; } /* @@ -159,6 +162,7 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu, u64 address, u16 domid, int pde, int s) { struct iommu_cmd cmd; + int ret; memset(&cmd, 0, sizeof(cmd)); address &= PAGE_MASK; @@ -171,9 +175,11 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu, if (pde) /* PDE bit - we wan't flush everything not only the PTEs */ cmd.data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK; + ret = iommu_queue_command(iommu, &cmd); + iommu->need_sync = 1; - return iommu_queue_command(iommu, &cmd); + return ret; } /* -- GitLab From 7e4f88da7bf1887563f70bd5edbbd0479e31dc12 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 14:19:15 +0200 Subject: [PATCH 1972/5416] AMD IOMMU: protect completion wait loop with iommu lock The unlocked polling of the ComWaitInt bit in the IOMMU completion wait path is racy. Protect it with the iommu lock. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a96d8c049a8..042fdc27bc9 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -101,10 +101,10 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd) */ static int iommu_completion_wait(struct amd_iommu *iommu) { - int ret, ready = 0; + int ret = 0, ready = 0; unsigned status = 0; struct iommu_cmd cmd; - unsigned long i = 0; + unsigned long flags, i = 0; memset(&cmd, 0, sizeof(cmd)); cmd.data[0] = CMD_COMPL_WAIT_INT_MASK; @@ -112,10 +112,12 @@ static int iommu_completion_wait(struct amd_iommu *iommu) iommu->need_sync = 0; - ret = iommu_queue_command(iommu, &cmd); + spin_lock_irqsave(&iommu->lock, flags); + + ret = __iommu_queue_command(iommu, &cmd); if (ret) - return ret; + goto out; while (!ready && (i < EXIT_LOOP_COUNT)) { ++i; @@ -130,6 +132,8 @@ static int iommu_completion_wait(struct amd_iommu *iommu) if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit())) printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n"); +out: + spin_unlock_irqrestore(&iommu->lock, flags); return 0; } -- GitLab From a3028b8ed1e1e9930bfa70ce4555fb7f9fad3dcc Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 02:48:25 -0700 Subject: [PATCH 1973/5416] sctp: set the skb->ip_summed correctly when sending over loopback. Loopback used to clobber the ip_summed filed which sctp then used to figure out if it needed to do checksumming or not. Now that loopback doesn't do that any more, sctp needs to set the ip_summed field correctly. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 0dc4a7dfb23..225c7123c41 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) if (!(dst->dev->features & NETIF_F_NO_CSUM)) { crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); crc32 = sctp_end_cksum(crc32); - } + } else + nskb->ip_summed = CHECKSUM_UNNECESSARY; /* 3) Put the resultant value into the checksum field in the * common header, and leave the rest of the bits unchanged. -- GitLab From 9a22b6e76ba75fa0f3963cdec7829156d00a7173 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 18 Sep 2008 12:50:18 +0200 Subject: [PATCH 1974/5416] dmi scan: warn about too early calls to dmi_check_system() It happened to me recently that i added a dmi_check_system() quirk in a too early codepath, and it was silently ignored because all the DMI tables and strings were still empty. As this situation is clearly a programming error / kernel bug, warn when it happens, instead of silently ignoring quirks. Signed-off-by: Ingo Molnar --- drivers/firmware/dmi_scan.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 455575be356..3e526b6d00c 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -15,6 +15,11 @@ */ static char dmi_empty_string[] = " "; +/* + * Catch too early calls to dmi_check_system(): + */ +static int dmi_initialized; + static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) { const u8 *bp = ((u8 *) dm) + dm->length; @@ -366,7 +371,7 @@ void __init dmi_scan_machine(void) if (efi_enabled) { if (efi.smbios == EFI_INVALID_TABLE_ADDR) - goto out; + goto error; /* This is called as a core_initcall() because it isn't * needed during early boot. This also means we can @@ -374,13 +379,13 @@ void __init dmi_scan_machine(void) */ p = dmi_ioremap(efi.smbios, 32); if (p == NULL) - goto out; + goto error; rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ dmi_iounmap(p, 32); if (!rc) { dmi_available = 1; - return; + goto out; } } else { @@ -391,19 +396,22 @@ void __init dmi_scan_machine(void) */ p = dmi_ioremap(0xF0000, 0x10000); if (p == NULL) - goto out; + goto error; for (q = p; q < p + 0x10000; q += 16) { rc = dmi_present(q); if (!rc) { dmi_available = 1; dmi_iounmap(p, 0x10000); - return; + goto out; } } dmi_iounmap(p, 0x10000); } - out: printk(KERN_INFO "DMI not present or invalid.\n"); + error: + printk(KERN_INFO "DMI not present or invalid.\n"); + out: + dmi_initialized = 1; } /** @@ -424,6 +432,8 @@ int dmi_check_system(const struct dmi_system_id *list) int i, count = 0; const struct dmi_system_id *d = list; + WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n"); + while (d->ident) { for (i = 0; i < ARRAY_SIZE(d->matches); i++) { int s = d->matches[i].slot; -- GitLab From 58005b325394b18b8b6a737e06b4128deb2c4e63 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Thu, 18 Sep 2008 12:19:39 +0100 Subject: [PATCH 1975/5416] [ARM] 5255/1: Update jornada ssp to remove build errors/warnings * Adds ssp functions into header so we don't get "implicit declaration" error at builtime. * Converts jornada_ssp_start/end functions into voids with proper declarations (to avoid "prototype..." warning). * Sorts include files in alphabetical order * Minor comment changes Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King --- arch/arm/mach-sa1100/include/mach/jornada720.h | 11 ++++++++--- arch/arm/mach-sa1100/jornada720_ssp.c | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-sa1100/include/mach/jornada720.h b/arch/arm/mach-sa1100/include/mach/jornada720.h index bc120850d31..cc6b4bfcecf 100644 --- a/arch/arm/mach-sa1100/include/mach/jornada720.h +++ b/arch/arm/mach-sa1100/include/mach/jornada720.h @@ -1,10 +1,10 @@ /* * arch/arm/mach-sa1100/include/mach/jornada720.h * - * This file contains SSP/MCU communication definitions for HP Jornada 710/720/728 + * SSP/MCU communication definitions for HP Jornada 710/720/728 * - * Copyright (C) 2007 Kristoffer Ericson - * Copyright (C) 2000 John Ankcorn + * Copyright 2007,2008 Kristoffer Ericson + * Copyright 2000 John Ankcorn * * 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 @@ -25,3 +25,8 @@ #define PWMOFF 0xDF #define TXDUMMY 0x11 #define ERRORCODE 0x00 + +extern void jornada_ssp_start(void); +extern void jornada_ssp_end(void); +extern int jornada_ssp_inout(u8 byte); +extern int jornada_ssp_byte(u8 byte); diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index 06ea7abd917..28cf3696797 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -21,8 +21,8 @@ #include #include -#include #include +#include static DEFINE_SPINLOCK(jornada_ssp_lock); static unsigned long jornada_ssp_flags; @@ -109,12 +109,12 @@ EXPORT_SYMBOL(jornada_ssp_inout); * jornada_ssp_start - enable mcu * */ -int jornada_ssp_start() +void jornada_ssp_start(void) { spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags); GPCR = GPIO_GPIO25; udelay(50); - return 0; + return; }; EXPORT_SYMBOL(jornada_ssp_start); @@ -122,11 +122,11 @@ EXPORT_SYMBOL(jornada_ssp_start); * jornada_ssp_end - disable mcu and turn off lock * */ -int jornada_ssp_end() +void jornada_ssp_end(void) { GPSR = GPIO_GPIO25; spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags); - return 0; + return; }; EXPORT_SYMBOL(jornada_ssp_end); -- GitLab From 37ec89e83c4ca98323fe74f139301ff3949cfdb6 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 18 Sep 2008 13:49:32 +0100 Subject: [PATCH 1976/5416] GFS2: The war on bloat The following patch shrinks the gfs2_args structure which is embedded in every GFS2 superblock. It cuts down the size of the options to a single unsigned int (the 13 bits of bitfields will be rounded up to that size by the compiler) from the current 11 unsigned ints. So on x86 thats 44 bytes shrinking to 4 bytes, in each and every GFS2 superblock. Signed-off-by: Steven Whitehouse --- fs/gfs2/incore.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index a1777a1927b..b2c5784092c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -386,21 +386,21 @@ struct gfs2_statfs_change_host { #define GFS2_DATA_ORDERED 2 struct gfs2_args { - char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */ - char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ - char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */ - int ar_spectator; /* Don't get a journal because we're always RO */ - int ar_ignore_local_fs; /* Don't optimize even if local_fs is 1 */ - int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */ - int ar_localcaching; /* Local-style caching (dangerous on multihost) */ - int ar_debug; /* Oops on errors instead of trying to be graceful */ - int ar_upgrade; /* Upgrade ondisk/multihost format */ - unsigned int ar_num_glockd; /* Number of glockd threads */ - int ar_posix_acl; /* Enable posix acls */ - int ar_quota; /* off/account/on */ - int ar_suiddir; /* suiddir support */ - int ar_data; /* ordered/writeback */ - int ar_meta; /* mount metafs */ + char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */ + char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ + char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */ + unsigned int ar_spectator:1; /* Don't get a journal */ + unsigned int ar_ignore_local_fs:1; /* Ignore optimisations */ + unsigned int ar_localflocks:1; /* Let the VFS do flock|fcntl */ + unsigned int ar_localcaching:1; /* Local caching */ + unsigned int ar_debug:1; /* Oops on errors */ + unsigned int ar_upgrade:1; /* Upgrade ondisk format */ + unsigned int ar_posix_acl:1; /* Enable posix acls */ + unsigned int ar_quota:2; /* off/account/on */ + unsigned int ar_suiddir:1; /* suiddir support */ + unsigned int ar_data:2; /* ordered/writeback */ + unsigned int ar_meta:1; /* mount metafs */ + unsigned int ar_num_glockd; /* Number of glockd threads */ }; struct gfs2_tune { -- GitLab From 719ee344675c2efed9115934f19aa66a526b6e5b Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 18 Sep 2008 13:53:59 +0100 Subject: [PATCH 1977/5416] GFS2: high time to take some time over atime Until now, we've used the same scheme as GFS1 for atime. This has failed since atime is a per vfsmnt flag, not a per fs flag and as such the "noatime" flag was not getting passed down to the filesystems. This patch removes all the "special casing" around atime updates and we simply use the VFS's atime code. The net result is that GFS2 will now support all the same atime related mount options of any other filesystem on a per-vfsmnt basis. We do lose the "lazy atime" updates, but we gain "relatime". We could add lazy atime to the VFS at a later date, if there is a requirement for that variant still - I suspect relatime will be enough. Also we lose about 100 lines of code after this patch has been applied, and I have a suspicion that it will speed things up a bit, even when atime is "on". So it seems like a nice clean up as well. From a user perspective, everything stays the same except the loss of the per-fs atime quantum tweekable (ought to be per-vfsmnt at the very least, and to be honest I don't think anybody ever used it) and that a number of options which were ignored before now work correctly. Please let me know if you've got any comments. I'm pushing this out early so that you can all see what my plans are. Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 2 - fs/gfs2/glock.h | 1 - fs/gfs2/incore.h | 2 - fs/gfs2/inode.c | 107 ++++-------------------------------------- fs/gfs2/inode.h | 1 - fs/gfs2/ops_address.c | 16 +++---- fs/gfs2/ops_file.c | 16 +++---- fs/gfs2/ops_fstype.c | 23 ++------- fs/gfs2/ops_super.c | 53 ++++++++++++++------- fs/gfs2/sys.c | 11 ----- 10 files changed, 65 insertions(+), 167 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 806e1eb0aa0..c962283d4e7 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1580,8 +1580,6 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags) *p++ = 'a'; if (flags & GL_EXACT) *p++ = 'E'; - if (flags & GL_ATIME) - *p++ = 'a'; if (flags & GL_NOCACHE) *p++ = 'c'; if (test_bit(HIF_HOLDER, &iflags)) diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 971d92af70f..695c6b19361 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -24,7 +24,6 @@ #define GL_ASYNC 0x00000040 #define GL_EXACT 0x00000080 #define GL_SKIP 0x00000100 -#define GL_ATIME 0x00000200 #define GL_NOCACHE 0x00000400 #define GLR_TRYFAILED 13 diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index b2c5784092c..f1ed3a1bf8a 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -420,7 +420,6 @@ struct gfs2_tune { unsigned int gt_quota_scale_den; /* Denominator */ unsigned int gt_quota_cache_secs; unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ - unsigned int gt_atime_quantum; /* Min secs between atime updates */ unsigned int gt_new_files_jdata; unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ unsigned int gt_stall_secs; /* Detects trouble! */ @@ -433,7 +432,6 @@ enum { SDF_JOURNAL_CHECKED = 0, SDF_JOURNAL_LIVE = 1, SDF_SHUTDOWN = 2, - SDF_NOATIME = 3, }; #define GFS2_FSNAME_LEN 256 diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index c8a959c09f1..7cee695fa44 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "gfs2.h" #include "incore.h" @@ -249,6 +250,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) { struct gfs2_dinode_host *di = &ip->i_di; const struct gfs2_dinode *str = buf; + struct timespec atime; u16 height, depth; if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) @@ -275,8 +277,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_size = be64_to_cpu(str->di_size); i_size_write(&ip->i_inode, di->di_size); gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); - ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); - ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); + atime.tv_sec = be64_to_cpu(str->di_atime); + atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); + if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0) + ip->i_inode.i_atime = atime; ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); @@ -1157,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) unsigned int x; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); - error = gfs2_glock_nq_atime(&i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + error = gfs2_glock_nq(&i_gh); if (error) { gfs2_holder_uninit(&i_gh); return error; @@ -1193,101 +1197,6 @@ out: return error; } -/** - * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and - * conditionally update the inode's atime - * @gh: the holder to acquire - * - * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap - * Update if the difference between the current time and the inode's current - * atime is greater than an interval specified at mount. - * - * Returns: errno - */ - -int gfs2_glock_nq_atime(struct gfs2_holder *gh) -{ - struct gfs2_glock *gl = gh->gh_gl; - struct gfs2_sbd *sdp = gl->gl_sbd; - struct gfs2_inode *ip = gl->gl_object; - s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum); - unsigned int state; - int flags; - int error; - struct timespec tv = CURRENT_TIME; - - if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) || - gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || - gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops)) - return -EINVAL; - - state = gh->gh_state; - flags = gh->gh_flags; - - error = gfs2_glock_nq(gh); - if (error) - return error; - - if (test_bit(SDF_NOATIME, &sdp->sd_flags) || - (sdp->sd_vfs->s_flags & MS_RDONLY)) - return 0; - - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { - gfs2_glock_dq(gh); - gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, - gh); - error = gfs2_glock_nq(gh); - if (error) - return error; - - /* Verify that atime hasn't been updated while we were - trying to get exclusive lock. */ - - tv = CURRENT_TIME; - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { - struct buffer_head *dibh; - struct gfs2_dinode *di; - - error = gfs2_trans_begin(sdp, RES_DINODE, 0); - if (error == -EROFS) - return 0; - if (error) - goto fail; - - error = gfs2_meta_inode_buffer(ip, &dibh); - if (error) - goto fail_end_trans; - - ip->i_inode.i_atime = tv; - - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - di = (struct gfs2_dinode *)dibh->b_data; - di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); - di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); - brelse(dibh); - - gfs2_trans_end(sdp); - } - - /* If someone else has asked for the glock, - unlock and let them have it. Then reacquire - in the original state. */ - if (gfs2_glock_is_blocking(gl)) { - gfs2_glock_dq(gh); - gfs2_holder_reinit(state, flags, gh); - return gfs2_glock_nq(gh); - } - } - - return 0; - -fail_end_trans: - gfs2_trans_end(sdp); -fail: - gfs2_glock_dq(gh); - return error; -} - static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index bfd2afc0c90..2d43f69610a 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -92,7 +92,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, const struct gfs2_inode *ip); int gfs2_permission(struct inode *inode, int mask); int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len); -int gfs2_glock_nq_atime(struct gfs2_holder *gh); int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index ae7126aeb44..27563816e1c 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -512,8 +512,8 @@ static int gfs2_readpage(struct file *file, struct page *page) int error; unlock_page(page); - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - error = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + error = gfs2_glock_nq(&gh); if (unlikely(error)) goto out; error = AOP_TRUNCATED_PAGE; @@ -594,8 +594,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, struct gfs2_holder gh; int ret; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - ret = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq(&gh); if (unlikely(ret)) goto out_uninit; if (!gfs2_is_stuffed(ip)) @@ -636,8 +636,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, unsigned to = from + len; struct page *page; - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh); - error = gfs2_glock_nq_atime(&ip->i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); + error = gfs2_glock_nq(&ip->i_gh); if (unlikely(error)) goto out_uninit; @@ -1000,8 +1000,8 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, * unfortunately have the option of only flushing a range like * the VFS does. */ - gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh); - rv = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh); + rv = gfs2_glock_nq(&gh); if (rv) return rv; rv = gfs2_ok_for_dio(ip, rw, offset); diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index e9a366d4411..3a747f8e218 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -89,8 +89,8 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) u64 offset = file->f_pos; int error; - gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); - error = gfs2_glock_nq_atime(&d_gh); + gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + error = gfs2_glock_nq(&d_gh); if (error) { gfs2_holder_uninit(&d_gh); return error; @@ -153,8 +153,8 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) int error; u32 fsflags; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - error = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + error = gfs2_glock_nq(&gh); if (error) return error; @@ -351,8 +351,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) struct gfs2_alloc *al; int ret; - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh); - ret = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + ret = gfs2_glock_nq(&gh); if (ret) goto out; @@ -434,8 +434,8 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); - error = gfs2_glock_nq_atime(&i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + error = gfs2_glock_nq(&i_gh); if (error) { gfs2_holder_uninit(&i_gh); return error; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ae35f097aa6..b117fcf2c4f 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -70,7 +70,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt) gt->gt_quota_scale_den = 1; gt->gt_quota_cache_secs = 300; gt->gt_quota_quantum = 60; - gt->gt_atime_quantum = 3600; gt->gt_new_files_jdata = 0; gt->gt_max_readahead = 1 << 18; gt->gt_stall_secs = 600; @@ -135,22 +134,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) return sdp; } -static void init_vfs(struct super_block *sb, unsigned noatime) -{ - struct gfs2_sbd *sdp = sb->s_fs_info; - - sb->s_magic = GFS2_MAGIC; - sb->s_op = &gfs2_super_ops; - sb->s_export_op = &gfs2_export_ops; - sb->s_time_gran = 1; - sb->s_maxbytes = MAX_LFS_FILESIZE; - - if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME)) - set_bit(noatime, &sdp->sd_flags); - - /* Don't let the VFS update atimes. GFS2 handles this itself. */ - sb->s_flags |= MS_NOATIME | MS_NODIRATIME; -} /** * gfs2_check_sb - Check superblock @@ -1100,7 +1083,11 @@ static int fill_super(struct super_block *sb, void *data, int silent) goto fail; } - init_vfs(sb, SDF_NOATIME); + sb->s_magic = GFS2_MAGIC; + sb->s_op = &gfs2_super_ops; + sb->s_export_op = &gfs2_export_ops; + sb->s_time_gran = 1; + sb->s_maxbytes = MAX_LFS_FILESIZE; /* Set up the buffer cache and fill in some fake block size values to allow us to read-in the on-disk superblock. */ diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 8f332d26b5d..d5355d9b592 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "gfs2.h" #include "incore.h" @@ -38,6 +39,7 @@ #include "dir.h" #include "eattr.h" #include "bmap.h" +#include "meta_io.h" /** * gfs2_write_inode - Make sure the inode is stable on the disk @@ -50,16 +52,41 @@ static int gfs2_write_inode(struct inode *inode, int sync) { struct gfs2_inode *ip = GFS2_I(inode); - - /* Check this is a "normal" inode */ - if (test_bit(GIF_USER, &ip->i_flags)) { - if (current->flags & PF_MEMALLOC) - return 0; - if (sync) - gfs2_log_flush(GFS2_SB(inode), ip->i_gl); + struct gfs2_sbd *sdp = GFS2_SB(inode); + struct gfs2_holder gh; + struct buffer_head *bh; + struct timespec atime; + struct gfs2_dinode *di; + int ret = 0; + + /* Check this is a "normal" inode, etc */ + if (!test_bit(GIF_USER, &ip->i_flags) || + (current->flags & PF_MEMALLOC)) + return 0; + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (ret) + goto do_flush; + ret = gfs2_trans_begin(sdp, RES_DINODE, 0); + if (ret) + goto do_unlock; + ret = gfs2_meta_inode_buffer(ip, &bh); + if (ret == 0) { + di = (struct gfs2_dinode *)bh->b_data; + atime.tv_sec = be64_to_cpu(di->di_atime); + atime.tv_nsec = be32_to_cpu(di->di_atime_nsec); + if (timespec_compare(&inode->i_atime, &atime) > 0) { + gfs2_trans_add_bh(ip->i_gl, bh, 1); + gfs2_dinode_out(ip, bh->b_data); + } + brelse(bh); } - - return 0; + gfs2_trans_end(sdp); +do_unlock: + gfs2_glock_dq_uninit(&gh); +do_flush: + if (sync != 0) + gfs2_log_flush(GFS2_SB(inode), ip->i_gl); + return ret; } /** @@ -297,14 +324,6 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) } } - if (*flags & (MS_NOATIME | MS_NODIRATIME)) - set_bit(SDF_NOATIME, &sdp->sd_flags); - else - clear_bit(SDF_NOATIME, &sdp->sd_flags); - - /* Don't let the VFS update atimes. GFS2 handles this itself. */ - *flags |= MS_NOATIME | MS_NODIRATIME; - return error; } diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 74846559fc3..7e1879f1a02 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -269,14 +269,6 @@ ARGS_ATTR(quota, "%u\n"); ARGS_ATTR(suiddir, "%d\n"); ARGS_ATTR(data, "%d\n"); -/* one oddball doesn't fit the macro mold */ -static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - !!test_bit(SDF_NOATIME, &sdp->sd_flags)); -} -static struct args_attr args_attr_noatime = __ATTR_RO(noatime); - static struct attribute *args_attrs[] = { &args_attr_lockproto.attr, &args_attr_locktable.attr, @@ -292,7 +284,6 @@ static struct attribute *args_attrs[] = { &args_attr_quota.attr, &args_attr_suiddir.attr, &args_attr_data.attr, - &args_attr_noatime.attr, NULL, }; @@ -407,7 +398,6 @@ TUNE_ATTR(incore_log_blocks, 0); TUNE_ATTR(log_flush_secs, 0); TUNE_ATTR(quota_warn_period, 0); TUNE_ATTR(quota_quantum, 0); -TUNE_ATTR(atime_quantum, 0); TUNE_ATTR(max_readahead, 0); TUNE_ATTR(complain_secs, 0); TUNE_ATTR(statfs_slow, 0); @@ -427,7 +417,6 @@ static struct attribute *tune_attrs[] = { &tune_attr_log_flush_secs.attr, &tune_attr_quota_warn_period.attr, &tune_attr_quota_quantum.attr, - &tune_attr_atime_quantum.attr, &tune_attr_max_readahead.attr, &tune_attr_complain_secs.attr, &tune_attr_statfs_slow.attr, -- GitLab From 452c1ce218a68b5dbd626397ecfc65ca89dd3cbb Mon Sep 17 00:00:00 2001 From: Chris Snook Date: Sun, 14 Sep 2008 19:56:10 -0500 Subject: [PATCH 1978/5416] atl2: add atl2 driver Driver for Atheros L2 10/100 network device. Includes necessary changes for Kconfig, Makefile, and pci_ids.h. Signed-off-by: Chris Snook Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 11 + drivers/net/Makefile | 1 + drivers/net/atlx/Makefile | 2 + drivers/net/atlx/atl2.c | 3127 +++++++++++++++++++++++++++++++++++++ drivers/net/atlx/atl2.h | 530 +++++++ include/linux/pci_ids.h | 1 + 6 files changed, 3672 insertions(+) create mode 100644 drivers/net/atlx/atl2.c create mode 100644 drivers/net/atlx/atl2.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4a11296a951..81a3e959c6c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1840,6 +1840,17 @@ config NE_H8300 Say Y here if you want to use the NE2000 compatible controller on the Renesas H8/300 processor. +config ATL2 + tristate "Atheros L2 Fast Ethernet support" + depends on PCI + select CRC32 + select MII + help + This driver supports the Atheros L2 fast ethernet adapter. + + To compile this driver as a module, choose M here. The module + will be called atl2. + source "drivers/net/fs_enet/Kconfig" endif # NET_ETHERNET diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f66b79bd3b8..9221346a515 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_EHEA) += ehea/ obj-$(CONFIG_CAN) += can/ obj-$(CONFIG_BONDING) += bonding/ obj-$(CONFIG_ATL1) += atlx/ +obj-$(CONFIG_ATL2) += atlx/ obj-$(CONFIG_ATL1E) += atl1e/ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o diff --git a/drivers/net/atlx/Makefile b/drivers/net/atlx/Makefile index ca45553a040..e4f6022ca55 100644 --- a/drivers/net/atlx/Makefile +++ b/drivers/net/atlx/Makefile @@ -1 +1,3 @@ obj-$(CONFIG_ATL1) += atl1.o +obj-$(CONFIG_ATL2) += atl2.o + diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c new file mode 100644 index 00000000000..d548a67da1e --- /dev/null +++ b/drivers/net/atlx/atl2.c @@ -0,0 +1,3127 @@ +/* + * Copyright(c) 2006 - 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2007 - 2008 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atl2.h" + +#define ATL2_DRV_VERSION "2.2.3" + +static char atl2_driver_name[] = "atl2"; +static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver"; +static char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation."; +static char atl2_driver_version[] = ATL2_DRV_VERSION; + +MODULE_AUTHOR("Atheros Corporation , Chris Snook "); +MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(ATL2_DRV_VERSION); + +/* + * atl2_pci_tbl - PCI Device ID Table + */ +static struct pci_device_id atl2_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)}, + /* required last entry */ + {0,} +}; +MODULE_DEVICE_TABLE(pci, atl2_pci_tbl); + +static void atl2_set_ethtool_ops(struct net_device *netdev); + +static void atl2_check_options(struct atl2_adapter *adapter); + +/* + * atl2_sw_init - Initialize general software structures (struct atl2_adapter) + * @adapter: board private structure to initialize + * + * atl2_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + */ +static int __devinit atl2_sw_init(struct atl2_adapter *adapter) +{ + struct atl2_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + + /* PCI config space info */ + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_id = pdev->subsystem_device; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + + adapter->wol = 0; + adapter->ict = 50000; /* ~100ms */ + adapter->link_speed = SPEED_0; /* hardware init */ + adapter->link_duplex = FULL_DUPLEX; + + hw->phy_configured = false; + hw->preamble_len = 7; + hw->ipgt = 0x60; + hw->min_ifg = 0x50; + hw->ipgr1 = 0x40; + hw->ipgr2 = 0x60; + hw->retry_buf = 2; + hw->max_retry = 0xf; + hw->lcol = 0x37; + hw->jam_ipg = 7; + hw->fc_rxd_hi = 0; + hw->fc_rxd_lo = 0; + hw->max_frame_size = adapter->netdev->mtu; + + spin_lock_init(&adapter->stats_lock); + spin_lock_init(&adapter->tx_lock); + + set_bit(__ATL2_DOWN, &adapter->flags); + + return 0; +} + +/* + * atl2_set_multi - Multicast and Promiscuous mode set + * @netdev: network interface device structure + * + * The set_multi entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast, + * promiscuous mode, and all-multi behavior. + */ +static void atl2_set_multi(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + struct dev_mc_list *mc_ptr; + u32 rctl; + u32 hash_value; + + /* Check for Promiscuous and All Multicast modes */ + rctl = ATL2_READ_REG(hw, REG_MAC_CTRL); + + if (netdev->flags & IFF_PROMISC) { + rctl |= MAC_CTRL_PROMIS_EN; + } else if (netdev->flags & IFF_ALLMULTI) { + rctl |= MAC_CTRL_MC_ALL_EN; + rctl &= ~MAC_CTRL_PROMIS_EN; + } else + rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, rctl); + + /* clear the old settings from the multicast hash table */ + ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); + + /* comoute mc addresses' hash value ,and put it into hash table */ + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + hash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr); + atl2_hash_set(hw, hash_value); + } +} + +static void init_ring_ptrs(struct atl2_adapter *adapter) +{ + /* Read / Write Ptr Initialize: */ + adapter->txd_write_ptr = 0; + atomic_set(&adapter->txd_read_ptr, 0); + + adapter->rxd_read_ptr = 0; + adapter->rxd_write_ptr = 0; + + atomic_set(&adapter->txs_write_ptr, 0); + adapter->txs_next_clear = 0; +} + +/* + * atl2_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + */ +static int atl2_configure(struct atl2_adapter *adapter) +{ + struct atl2_hw *hw = &adapter->hw; + u32 value; + + /* clear interrupt status */ + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff); + + /* set MAC Address */ + value = (((u32)hw->mac_addr[2]) << 24) | + (((u32)hw->mac_addr[3]) << 16) | + (((u32)hw->mac_addr[4]) << 8) | + (((u32)hw->mac_addr[5])); + ATL2_WRITE_REG(hw, REG_MAC_STA_ADDR, value); + value = (((u32)hw->mac_addr[0]) << 8) | + (((u32)hw->mac_addr[1])); + ATL2_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value); + + /* HI base address */ + ATL2_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, + (u32)((adapter->ring_dma & 0xffffffff00000000ULL) >> 32)); + + /* LO base address */ + ATL2_WRITE_REG(hw, REG_TXD_BASE_ADDR_LO, + (u32)(adapter->txd_dma & 0x00000000ffffffffULL)); + ATL2_WRITE_REG(hw, REG_TXS_BASE_ADDR_LO, + (u32)(adapter->txs_dma & 0x00000000ffffffffULL)); + ATL2_WRITE_REG(hw, REG_RXD_BASE_ADDR_LO, + (u32)(adapter->rxd_dma & 0x00000000ffffffffULL)); + + /* element count */ + ATL2_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4)); + ATL2_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size); + ATL2_WRITE_REGW(hw, REG_RXD_BUF_NUM, (u16)adapter->rxd_ring_size); + + /* config Internal SRAM */ +/* + ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end); + ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end); +*/ + + /* config IPG/IFG */ + value = (((u32)hw->ipgt & MAC_IPG_IFG_IPGT_MASK) << + MAC_IPG_IFG_IPGT_SHIFT) | + (((u32)hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) << + MAC_IPG_IFG_MIFG_SHIFT) | + (((u32)hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) << + MAC_IPG_IFG_IPGR1_SHIFT)| + (((u32)hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) << + MAC_IPG_IFG_IPGR2_SHIFT); + ATL2_WRITE_REG(hw, REG_MAC_IPG_IFG, value); + + /* config Half-Duplex Control */ + value = ((u32)hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | + (((u32)hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) << + MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | + MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | + (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | + (((u32)hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) << + MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); + ATL2_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value); + + /* set Interrupt Moderator Timer */ + ATL2_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt); + ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN); + + /* set Interrupt Clear Timer */ + ATL2_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict); + + /* set MTU */ + ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu + + ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE); + + /* 1590 */ + ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177); + + /* flow control */ + ATL2_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi); + ATL2_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo); + + /* Init mailbox */ + ATL2_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr); + ATL2_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr); + + /* enable DMA read/write */ + ATL2_WRITE_REGB(hw, REG_DMAR, DMAR_EN); + ATL2_WRITE_REGB(hw, REG_DMAW, DMAW_EN); + + value = ATL2_READ_REG(&adapter->hw, REG_ISR); + if ((value & ISR_PHY_LINKDOWN) != 0) + value = 1; /* config failed */ + else + value = 0; + + /* clear all interrupt status */ + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff); + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0); + return value; +} + +/* + * atl2_setup_ring_resources - allocate Tx / RX descriptor resources + * @adapter: board private structure + * + * Return 0 on success, negative on failure + */ +static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + int size; + u8 offset = 0; + + /* real ring DMA buffer */ + adapter->ring_size = size = + adapter->txd_ring_size * 1 + 7 + /* dword align */ + adapter->txs_ring_size * 4 + 7 + /* dword align */ + adapter->rxd_ring_size * 1536 + 127; /* 128bytes align */ + + adapter->ring_vir_addr = pci_alloc_consistent(pdev, size, + &adapter->ring_dma); + if (!adapter->ring_vir_addr) + return -ENOMEM; + memset(adapter->ring_vir_addr, 0, adapter->ring_size); + + /* Init TXD Ring */ + adapter->txd_dma = adapter->ring_dma ; + offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0; + adapter->txd_dma += offset; + adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr + + offset); + + /* Init TXS Ring */ + adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size; + offset = (adapter->txs_dma & 0x7) ? (8 - (adapter->txs_dma & 0x7)) : 0; + adapter->txs_dma += offset; + adapter->txs_ring = (struct tx_pkt_status *) + (((u8 *)adapter->txd_ring) + (adapter->txd_ring_size + offset)); + + /* Init RXD Ring */ + adapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size * 4; + offset = (adapter->rxd_dma & 127) ? + (128 - (adapter->rxd_dma & 127)) : 0; + if (offset > 7) + offset -= 8; + else + offset += (128 - 8); + + adapter->rxd_dma += offset; + adapter->rxd_ring = (struct rx_desc *) (((u8 *)adapter->txs_ring) + + (adapter->txs_ring_size * 4 + offset)); + +/* + * Read / Write Ptr Initialize: + * init_ring_ptrs(adapter); + */ + return 0; +} + +/* + * atl2_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + */ +static inline void atl2_irq_enable(struct atl2_adapter *adapter) +{ + ATL2_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK); + ATL2_WRITE_FLUSH(&adapter->hw); +} + +/* + * atl2_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + */ +static inline void atl2_irq_disable(struct atl2_adapter *adapter) +{ + ATL2_WRITE_REG(&adapter->hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(&adapter->hw); + synchronize_irq(adapter->pdev->irq); +} + +#ifdef NETIF_F_HW_VLAN_TX +static void atl2_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + u32 ctrl; + + atl2_irq_disable(adapter); + adapter->vlgrp = grp; + + if (grp) { + /* enable VLAN tag insert/strip */ + ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); + ctrl |= MAC_CTRL_RMV_VLAN; + ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); + } else { + /* disable VLAN tag insert/strip */ + ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_RMV_VLAN; + ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl); + } + + atl2_irq_enable(adapter); +} + +static void atl2_restore_vlan(struct atl2_adapter *adapter) +{ + atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp); +} +#endif + +static void atl2_intr_rx(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct rx_desc *rxd; + struct sk_buff *skb; + + do { + rxd = adapter->rxd_ring+adapter->rxd_write_ptr; + if (!rxd->status.update) + break; /* end of tx */ + + /* clear this flag at once */ + rxd->status.update = 0; + + if (rxd->status.ok && rxd->status.pkt_size >= 60) { + int rx_size = (int)(rxd->status.pkt_size - 4); + /* alloc new buffer */ + skb = netdev_alloc_skb(netdev, rx_size + NET_IP_ALIGN); + if (NULL == skb) { + printk(KERN_WARNING + "%s: Mem squeeze, deferring packet.\n", + netdev->name); + /* + * Check that some rx space is free. If not, + * free one and mark stats->rx_dropped++. + */ + adapter->net_stats.rx_dropped++; + break; + } + skb_reserve(skb, NET_IP_ALIGN); + skb->dev = netdev; + memcpy(skb->data, rxd->packet, rx_size); + skb_put(skb, rx_size); + skb->protocol = eth_type_trans(skb, netdev); +#ifdef NETIF_F_HW_VLAN_TX + if (adapter->vlgrp && (rxd->status.vlan)) { + u16 vlan_tag = (rxd->status.vtag>>4) | + ((rxd->status.vtag&7) << 13) | + ((rxd->status.vtag&8) << 9); + vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); + } else +#endif + netif_rx(skb); + adapter->net_stats.rx_bytes += rx_size; + adapter->net_stats.rx_packets++; + netdev->last_rx = jiffies; + } else { + adapter->net_stats.rx_errors++; + + if (rxd->status.ok && rxd->status.pkt_size <= 60) + adapter->net_stats.rx_length_errors++; + if (rxd->status.mcast) + adapter->net_stats.multicast++; + if (rxd->status.crc) + adapter->net_stats.rx_crc_errors++; + if (rxd->status.align) + adapter->net_stats.rx_frame_errors++; + } + + /* advance write ptr */ + if (++adapter->rxd_write_ptr == adapter->rxd_ring_size) + adapter->rxd_write_ptr = 0; + } while (1); + + /* update mailbox? */ + adapter->rxd_read_ptr = adapter->rxd_write_ptr; + ATL2_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr); +} + +static void atl2_intr_tx(struct atl2_adapter *adapter) +{ + u32 txd_read_ptr; + u32 txs_write_ptr; + struct tx_pkt_status *txs; + struct tx_pkt_header *txph; + int free_hole = 0; + + do { + txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); + txs = adapter->txs_ring + txs_write_ptr; + if (!txs->update) + break; /* tx stop here */ + + free_hole = 1; + txs->update = 0; + + if (++txs_write_ptr == adapter->txs_ring_size) + txs_write_ptr = 0; + atomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr); + + txd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr); + txph = (struct tx_pkt_header *) + (((u8 *)adapter->txd_ring) + txd_read_ptr); + + if (txph->pkt_size != txs->pkt_size) { + struct tx_pkt_status *old_txs = txs; + printk(KERN_WARNING + "%s: txs packet size not consistent with txd" + " txd_:0x%08x, txs_:0x%08x!\n", + adapter->netdev->name, + *(u32 *)txph, *(u32 *)txs); + printk(KERN_WARNING + "txd read ptr: 0x%x\n", + txd_read_ptr); + txs = adapter->txs_ring + txs_write_ptr; + printk(KERN_WARNING + "txs-behind:0x%08x\n", + *(u32 *)txs); + if (txs_write_ptr < 2) { + txs = adapter->txs_ring + + (adapter->txs_ring_size + + txs_write_ptr - 2); + } else { + txs = adapter->txs_ring + (txs_write_ptr - 2); + } + printk(KERN_WARNING + "txs-before:0x%08x\n", + *(u32 *)txs); + txs = old_txs; + } + + /* 4for TPH */ + txd_read_ptr += (((u32)(txph->pkt_size) + 7) & ~3); + if (txd_read_ptr >= adapter->txd_ring_size) + txd_read_ptr -= adapter->txd_ring_size; + + atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr); + + /* tx statistics: */ + if (txs->ok) + adapter->net_stats.tx_packets++; + else + adapter->net_stats.tx_errors++; + + if (txs->defer) + adapter->net_stats.collisions++; + if (txs->abort_col) + adapter->net_stats.tx_aborted_errors++; + if (txs->late_col) + adapter->net_stats.tx_window_errors++; + if (txs->underun) + adapter->net_stats.tx_fifo_errors++; + } while (1); + + if (free_hole) { + if (netif_queue_stopped(adapter->netdev) && + netif_carrier_ok(adapter->netdev)) + netif_wake_queue(adapter->netdev); + } +} + +static void atl2_check_for_link(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u16 phy_data = 0; + + spin_lock(&adapter->stats_lock); + atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + spin_unlock(&adapter->stats_lock); + + /* notify upper layer link down ASAP */ + if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */ + if (netif_carrier_ok(netdev)) { /* old link state: Up */ + printk(KERN_INFO "%s: %s NIC Link is Down\n", + atl2_driver_name, netdev->name); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } + schedule_work(&adapter->link_chg_task); +} + +static inline void atl2_clear_phy_int(struct atl2_adapter *adapter) +{ + u16 phy_data; + spin_lock(&adapter->stats_lock); + atl2_read_phy_reg(&adapter->hw, 19, &phy_data); + spin_unlock(&adapter->stats_lock); +} + +/* + * atl2_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure + */ +static irqreturn_t atl2_intr(int irq, void *data) +{ + struct atl2_adapter *adapter = netdev_priv(data); + struct atl2_hw *hw = &adapter->hw; + u32 status; + + status = ATL2_READ_REG(hw, REG_ISR); + if (0 == status) + return IRQ_NONE; + + /* link event */ + if (status & ISR_PHY) + atl2_clear_phy_int(adapter); + + /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ + ATL2_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); + + /* check if PCIE PHY Link down */ + if (status & ISR_PHY_LINKDOWN) { + if (netif_running(adapter->netdev)) { /* reset MAC */ + ATL2_WRITE_REG(hw, REG_ISR, 0); + ATL2_WRITE_REG(hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(hw); + schedule_work(&adapter->reset_task); + return IRQ_HANDLED; + } + } + + /* check if DMA read/write error? */ + if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { + ATL2_WRITE_REG(hw, REG_ISR, 0); + ATL2_WRITE_REG(hw, REG_IMR, 0); + ATL2_WRITE_FLUSH(hw); + schedule_work(&adapter->reset_task); + return IRQ_HANDLED; + } + + /* link event */ + if (status & (ISR_PHY | ISR_MANUAL)) { + adapter->net_stats.tx_carrier_errors++; + atl2_check_for_link(adapter); + } + + /* transmit event */ + if (status & ISR_TX_EVENT) + atl2_intr_tx(adapter); + + /* rx exception */ + if (status & ISR_RX_EVENT) + atl2_intr_rx(adapter); + + /* re-enable Interrupt */ + ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0); + return IRQ_HANDLED; +} + +static int atl2_request_irq(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int flags, err = 0; + + flags = IRQF_SHARED; +#ifdef CONFIG_PCI_MSI + adapter->have_msi = true; + err = pci_enable_msi(adapter->pdev); + if (err) + adapter->have_msi = false; + + if (adapter->have_msi) + flags &= ~IRQF_SHARED; +#endif + + return request_irq(adapter->pdev->irq, &atl2_intr, flags, netdev->name, + netdev); +} + +/* + * atl2_free_ring_resources - Free Tx / RX descriptor Resources + * @adapter: board private structure + * + * Free all transmit software resources + */ +static void atl2_free_ring_resources(struct atl2_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + pci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr, + adapter->ring_dma); +} + +/* + * atl2_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + */ +static int atl2_open(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + int err; + u32 val; + + /* disallow open during test */ + if (test_bit(__ATL2_TESTING, &adapter->flags)) + return -EBUSY; + + /* allocate transmit descriptors */ + err = atl2_setup_ring_resources(adapter); + if (err) + return err; + + err = atl2_init_hw(&adapter->hw); + if (err) { + err = -EIO; + goto err_init_hw; + } + + /* hardware has been reset, we need to reload some things */ + atl2_set_multi(netdev); + init_ring_ptrs(adapter); + +#ifdef NETIF_F_HW_VLAN_TX + atl2_restore_vlan(adapter); +#endif + + if (atl2_configure(adapter)) { + err = -EIO; + goto err_config; + } + + err = atl2_request_irq(adapter); + if (err) + goto err_req_irq; + + clear_bit(__ATL2_DOWN, &adapter->flags); + + mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ); + + val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL); + ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, + val | MASTER_CTRL_MANUAL_INT); + + atl2_irq_enable(adapter); + + return 0; + +err_init_hw: +err_req_irq: +err_config: + atl2_free_ring_resources(adapter); + atl2_reset_hw(&adapter->hw); + + return err; +} + +static void atl2_down(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + /* signal that we're down so the interrupt handler does not + * reschedule our watchdog timer */ + set_bit(__ATL2_DOWN, &adapter->flags); + +#ifdef NETIF_F_LLTX + netif_stop_queue(netdev); +#else + netif_tx_disable(netdev); +#endif + + /* reset MAC to disable all RX/TX */ + atl2_reset_hw(&adapter->hw); + msleep(1); + + atl2_irq_disable(adapter); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_config_timer); + clear_bit(0, &adapter->cfg_phy); + + netif_carrier_off(netdev); + adapter->link_speed = SPEED_0; + adapter->link_duplex = -1; +} + +static void atl2_free_irq(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + free_irq(adapter->pdev->irq, netdev); + +#ifdef CONFIG_PCI_MSI + if (adapter->have_msi) + pci_disable_msi(adapter->pdev); +#endif +} + +/* + * atl2_close - Disables a network interface + * @netdev: network interface device structure + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + */ +static int atl2_close(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags)); + + atl2_down(adapter); + atl2_free_irq(adapter); + atl2_free_ring_resources(adapter); + + return 0; +} + +static inline int TxsFreeUnit(struct atl2_adapter *adapter) +{ + u32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr); + + return (adapter->txs_next_clear >= txs_write_ptr) ? + (int) (adapter->txs_ring_size - adapter->txs_next_clear + + txs_write_ptr - 1) : + (int) (txs_write_ptr - adapter->txs_next_clear - 1); +} + +static inline int TxdFreeBytes(struct atl2_adapter *adapter) +{ + u32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr); + + return (adapter->txd_write_ptr >= txd_read_ptr) ? + (int) (adapter->txd_ring_size - adapter->txd_write_ptr + + txd_read_ptr - 1) : + (int) (txd_read_ptr - adapter->txd_write_ptr - 1); +} + +static int atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + struct tx_pkt_header *txph; + u32 offset, copy_len; + int txs_unused; + int txbuf_unused; + + if (test_bit(__ATL2_DOWN, &adapter->flags)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +#ifdef NETIF_F_LLTX + local_irq_save(flags); + if (!spin_trylock(&adapter->tx_lock)) { + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } +#else + spin_lock_irqsave(&adapter->tx_lock, flags); +#endif + txs_unused = TxsFreeUnit(adapter); + txbuf_unused = TxdFreeBytes(adapter); + + if (skb->len + sizeof(struct tx_pkt_header) + 4 > txbuf_unused || + txs_unused < 1) { + /* not enough resources */ + netif_stop_queue(netdev); + spin_unlock_irqrestore(&adapter->tx_lock, flags); + return NETDEV_TX_BUSY; + } + + offset = adapter->txd_write_ptr; + + txph = (struct tx_pkt_header *) (((u8 *)adapter->txd_ring) + offset); + + *(u32 *)txph = 0; + txph->pkt_size = skb->len; + + offset += 4; + if (offset >= adapter->txd_ring_size) + offset -= adapter->txd_ring_size; + copy_len = adapter->txd_ring_size - offset; + if (copy_len >= skb->len) { + memcpy(((u8 *)adapter->txd_ring) + offset, skb->data, skb->len); + offset += ((u32)(skb->len + 3) & ~3); + } else { + memcpy(((u8 *)adapter->txd_ring)+offset, skb->data, copy_len); + memcpy((u8 *)adapter->txd_ring, skb->data+copy_len, + skb->len-copy_len); + offset = ((u32)(skb->len-copy_len + 3) & ~3); + } +#ifdef NETIF_F_HW_VLAN_TX + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + u16 vlan_tag = vlan_tx_tag_get(skb); + vlan_tag = (vlan_tag << 4) | + (vlan_tag >> 13) | + ((vlan_tag >> 9) & 0x8); + txph->ins_vlan = 1; + txph->vlan = vlan_tag; + } +#endif + if (offset >= adapter->txd_ring_size) + offset -= adapter->txd_ring_size; + adapter->txd_write_ptr = offset; + + /* clear txs before send */ + adapter->txs_ring[adapter->txs_next_clear].update = 0; + if (++adapter->txs_next_clear == adapter->txs_ring_size) + adapter->txs_next_clear = 0; + + ATL2_WRITE_REGW(&adapter->hw, REG_MB_TXD_WR_IDX, + (adapter->txd_write_ptr >> 2)); + + spin_unlock_irqrestore(&adapter->tx_lock, flags); + + netdev->trans_start = jiffies; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +/* + * atl2_get_stats - Get System Network Statistics + * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + */ +static struct net_device_stats *atl2_get_stats(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + return &adapter->net_stats; +} + +/* + * atl2_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + */ +static int atl2_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) + return -EINVAL; + + /* set MTU */ + if (hw->max_frame_size != new_mtu) { + netdev->mtu = new_mtu; + ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE + + VLAN_SIZE + ETHERNET_FCS_SIZE); + } + + return 0; +} + +/* + * atl2_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + */ +static int atl2_set_mac(struct net_device *netdev, void *p) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + if (netif_running(netdev)) + return -EBUSY; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + + atl2_set_mac_addr(&adapter->hw); + + return 0; +} + +/* + * atl2_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct mii_ioctl_data *data = if_mii(ifr); + unsigned long flags; + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = 0; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + spin_lock_irqsave(&adapter->stats_lock, flags); + if (atl2_read_phy_reg(&adapter->hw, + data->reg_num & 0x1F, &data->val_out)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); + return -EIO; + } + spin_unlock_irqrestore(&adapter->stats_lock, flags); + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (data->reg_num & ~(0x1F)) + return -EFAULT; + spin_lock_irqsave(&adapter->stats_lock, flags); + if (atl2_write_phy_reg(&adapter->hw, data->reg_num, + data->val_in)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); + return -EIO; + } + spin_unlock_irqrestore(&adapter->stats_lock, flags); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +/* + * atl2_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return atl2_mii_ioctl(netdev, ifr, cmd); +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + return ethtool_ioctl(ifr); +#endif + default: + return -EOPNOTSUPP; + } +} + +/* + * atl2_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + */ +static void atl2_tx_timeout(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + /* Do the reset outside of interrupt context */ + schedule_work(&adapter->reset_task); +} + +/* + * atl2_watchdog - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ +static void atl2_watchdog(unsigned long data) +{ + struct atl2_adapter *adapter = (struct atl2_adapter *) data; + u32 drop_rxd, drop_rxs; + unsigned long flags; + + if (!test_bit(__ATL2_DOWN, &adapter->flags)) { + spin_lock_irqsave(&adapter->stats_lock, flags); + drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV); + drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV); + adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs); + spin_unlock_irqrestore(&adapter->stats_lock, flags); + + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ); + } +} + +/* + * atl2_phy_config - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ +static void atl2_phy_config(unsigned long data) +{ + struct atl2_adapter *adapter = (struct atl2_adapter *) data; + struct atl2_hw *hw = &adapter->hw; + unsigned long flags; + + spin_lock_irqsave(&adapter->stats_lock, flags); + atl2_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); + atl2_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN | + MII_CR_RESTART_AUTO_NEG); + spin_unlock_irqrestore(&adapter->stats_lock, flags); + clear_bit(0, &adapter->cfg_phy); +} + +static int atl2_up(struct atl2_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err = 0; + u32 val; + + /* hardware has been reset, we need to reload some things */ + + err = atl2_init_hw(&adapter->hw); + if (err) { + err = -EIO; + return err; + } + + atl2_set_multi(netdev); + init_ring_ptrs(adapter); + +#ifdef NETIF_F_HW_VLAN_TX + atl2_restore_vlan(adapter); +#endif + + if (atl2_configure(adapter)) { + err = -EIO; + goto err_up; + } + + clear_bit(__ATL2_DOWN, &adapter->flags); + + val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL); + ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val | + MASTER_CTRL_MANUAL_INT); + + atl2_irq_enable(adapter); + +err_up: + return err; +} + +static void atl2_reinit_locked(struct atl2_adapter *adapter) +{ + WARN_ON(in_interrupt()); + while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags)) + msleep(1); + atl2_down(adapter); + atl2_up(adapter); + clear_bit(__ATL2_RESETTING, &adapter->flags); +} + +static void atl2_reset_task(struct work_struct *work) +{ + struct atl2_adapter *adapter; + adapter = container_of(work, struct atl2_adapter, reset_task); + + atl2_reinit_locked(adapter); +} + +static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter) +{ + u32 value; + struct atl2_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + + /* Config MAC CTRL Register */ + value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY; + + /* duplex */ + if (FULL_DUPLEX == adapter->link_duplex) + value |= MAC_CTRL_DUPLX; + + /* flow control */ + value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); + + /* PAD & CRC */ + value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + + /* preamble length */ + value |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) << + MAC_CTRL_PRMLEN_SHIFT); + + /* vlan */ + if (adapter->vlgrp) + value |= MAC_CTRL_RMV_VLAN; + + /* filter mode */ + value |= MAC_CTRL_BC_EN; + if (netdev->flags & IFF_PROMISC) + value |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) + value |= MAC_CTRL_MC_ALL_EN; + + /* half retry buffer */ + value |= (((u32)(adapter->hw.retry_buf & + MAC_CTRL_HALF_LEFT_BUF_MASK)) << MAC_CTRL_HALF_LEFT_BUF_SHIFT); + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); +} + +static int atl2_check_link(struct atl2_adapter *adapter) +{ + struct atl2_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + int ret_val; + u16 speed, duplex, phy_data; + int reconfig = 0; + + /* MII_BMSR must read twise */ + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + if (!(phy_data&BMSR_LSTATUS)) { /* link down */ + if (netif_carrier_ok(netdev)) { /* old link state: Up */ + u32 value; + /* disable rx */ + value = ATL2_READ_REG(hw, REG_MAC_CTRL); + value &= ~MAC_CTRL_RX_EN; + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + return 0; + } + + /* Link Up */ + ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) + return ret_val; + switch (hw->MediaType) { + case MEDIA_TYPE_100M_FULL: + if (speed != SPEED_100 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_HALF: + if (speed != SPEED_100 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_FULL: + if (speed != SPEED_10 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_HALF: + if (speed != SPEED_10 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + } + /* link result is our setting */ + if (reconfig == 0) { + if (adapter->link_speed != speed || + adapter->link_duplex != duplex) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; + atl2_setup_mac_ctrl(adapter); + printk(KERN_INFO "%s: %s NIC Link is Up<%d Mbps %s>\n", + atl2_driver_name, netdev->name, + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "Full Duplex" : "Half Duplex"); + } + + if (!netif_carrier_ok(netdev)) { /* Link down -> Up */ + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + return 0; + } + + /* change original link status */ + if (netif_carrier_ok(netdev)) { + u32 value; + /* disable rx */ + value = ATL2_READ_REG(hw, REG_MAC_CTRL); + value &= ~MAC_CTRL_RX_EN; + ATL2_WRITE_REG(hw, REG_MAC_CTRL, value); + + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + + /* auto-neg, insert timer to re-config phy + * (if interval smaller than 5 seconds, something strange) */ + if (!test_bit(__ATL2_DOWN, &adapter->flags)) { + if (!test_and_set_bit(0, &adapter->cfg_phy)) + mod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ); + } + + return 0; +} + +/* + * atl2_link_chg_task - deal with link change event Out of interrupt context + * @netdev: network interface device structure + */ +static void atl2_link_chg_task(struct work_struct *work) +{ + struct atl2_adapter *adapter; + unsigned long flags; + + adapter = container_of(work, struct atl2_adapter, link_chg_task); + + spin_lock_irqsave(&adapter->stats_lock, flags); + atl2_check_link(adapter); + spin_unlock_irqrestore(&adapter->stats_lock, flags); +} + +static void atl2_setup_pcicmd(struct pci_dev *pdev) +{ + u16 cmd; + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + + if (cmd & PCI_COMMAND_INTX_DISABLE) + cmd &= ~PCI_COMMAND_INTX_DISABLE; + if (cmd & PCI_COMMAND_IO) + cmd &= ~PCI_COMMAND_IO; + if (0 == (cmd & PCI_COMMAND_MEMORY)) + cmd |= PCI_COMMAND_MEMORY; + if (0 == (cmd & PCI_COMMAND_MASTER)) + cmd |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + + /* + * some motherboards BIOS(PXE/EFI) driver may set PME + * while they transfer control to OS (Windows/Linux) + * so we should clear this bit before NIC work normally + */ + pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0); +} + +/* + * atl2_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in atl2_pci_tbl + * + * Returns 0 on success, negative on failure + * + * atl2_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + */ +static int __devinit atl2_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct atl2_adapter *adapter; + static int cards_found; + unsigned long mmio_start; + int mmio_len; + int err; + + cards_found = 0; + + err = pci_enable_device(pdev); + if (err) + return err; + + /* + * atl2 is a shared-high-32-bit device, so we're stuck with 32-bit DMA + * until the kernel has the proper infrastructure to support 64-bit DMA + * on these devices. + */ + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) && + pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n"); + goto err_dma; + } + + /* Mark all PCI regions associated with PCI device + * pdev as being reserved by owner atl2_driver_name */ + err = pci_request_regions(pdev, atl2_driver_name); + if (err) + goto err_pci_reg; + + /* Enables bus-mastering on the device and calls + * pcibios_set_master to do the needed arch specific settings */ + pci_set_master(pdev); + + err = -ENOMEM; + netdev = alloc_etherdev(sizeof(struct atl2_adapter)); + if (!netdev) + goto err_alloc_etherdev; + + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; + adapter->hw.back = adapter; + + mmio_start = pci_resource_start(pdev, 0x0); + mmio_len = pci_resource_len(pdev, 0x0); + + adapter->hw.mem_rang = (u32)mmio_len; + adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); + if (!adapter->hw.hw_addr) { + err = -EIO; + goto err_ioremap; + } + + atl2_setup_pcicmd(pdev); + + netdev->open = &atl2_open; + netdev->stop = &atl2_close; + netdev->hard_start_xmit = &atl2_xmit_frame; + netdev->get_stats = &atl2_get_stats; + netdev->set_multicast_list = &atl2_set_multi; + netdev->set_mac_address = &atl2_set_mac; + netdev->change_mtu = &atl2_change_mtu; + netdev->do_ioctl = &atl2_ioctl; + atl2_set_ethtool_ops(netdev); + +#ifdef HAVE_TX_TIMEOUT + netdev->tx_timeout = &atl2_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; +#endif +#ifdef NETIF_F_HW_VLAN_TX + netdev->vlan_rx_register = atl2_vlan_rx_register; +#endif + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + netdev->mem_start = mmio_start; + netdev->mem_end = mmio_start + mmio_len; + adapter->bd_number = cards_found; + adapter->pci_using_64 = false; + + /* setup the private structure */ + err = atl2_sw_init(adapter); + if (err) + goto err_sw_init; + + err = -EIO; + +#ifdef NETIF_F_HW_VLAN_TX + netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); +#endif + +#ifdef NETIF_F_LLTX + netdev->features |= NETIF_F_LLTX; +#endif + + /* Init PHY as early as possible due to power saving issue */ + atl2_phy_init(&adapter->hw); + + /* reset the controller to + * put the device in a known good starting state */ + + if (atl2_reset_hw(&adapter->hw)) { + err = -EIO; + goto err_reset; + } + + /* copy the MAC address out of the EEPROM */ + atl2_read_mac_addr(&adapter->hw); + memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); +/* FIXME: do we still need this? */ +#ifdef ETHTOOL_GPERMADDR + memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->perm_addr)) { +#else + if (!is_valid_ether_addr(netdev->dev_addr)) { +#endif + err = -EIO; + goto err_eeprom; + } + + atl2_check_options(adapter); + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &atl2_watchdog; + adapter->watchdog_timer.data = (unsigned long) adapter; + + init_timer(&adapter->phy_config_timer); + adapter->phy_config_timer.function = &atl2_phy_config; + adapter->phy_config_timer.data = (unsigned long) adapter; + + INIT_WORK(&adapter->reset_task, atl2_reset_task); + INIT_WORK(&adapter->link_chg_task, atl2_link_chg_task); + + strcpy(netdev->name, "eth%d"); /* ?? */ + err = register_netdev(netdev); + if (err) + goto err_register; + + /* assume we have no link for now */ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + cards_found++; + + return 0; + +err_reset: +err_register: +err_sw_init: +err_eeprom: + iounmap(adapter->hw.hw_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + pci_release_regions(pdev); +err_pci_reg: +err_dma: + pci_disable_device(pdev); + return err; +} + +/* + * atl2_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * atl2_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. The could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + */ +/* FIXME: write the original MAC address back in case it was changed from a + * BIOS-set value, as in atl1 -- CHS */ +static void __devexit atl2_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + + /* flush_scheduled work may reschedule our watchdog task, so + * explicitly disable watchdog tasks from being rescheduled */ + set_bit(__ATL2_DOWN, &adapter->flags); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_config_timer); + + flush_scheduled_work(); + + unregister_netdev(netdev); + + atl2_force_ps(&adapter->hw); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); + + free_netdev(netdev); + + pci_disable_device(pdev); +} + +static int atl2_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u16 speed, duplex; + u32 ctrl = 0; + u32 wufc = adapter->wol; + +#ifdef CONFIG_PM + int retval = 0; +#endif + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags)); + atl2_down(adapter); + } + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) + return retval; +#endif + + atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl); + atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl); + if (ctrl & BMSR_LSTATUS) + wufc &= ~ATLX_WUFC_LNKC; + + if (0 != (ctrl & BMSR_LSTATUS) && 0 != wufc) { + u32 ret_val; + /* get current link speed & duplex */ + ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) { + printk(KERN_DEBUG + "%s: get speed&duplex error while suspend\n", + atl2_driver_name); + goto wol_dis; + } + + ctrl = 0; + + /* turn on magic packet wol */ + if (wufc & ATLX_WUFC_MAG) + ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); + + /* ignore Link Chg event when Link is up */ + ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl); + + /* Config MAC CTRL Register */ + ctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY; + if (FULL_DUPLEX == adapter->link_duplex) + ctrl |= MAC_CTRL_DUPLX; + ctrl |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + ctrl |= (((u32)adapter->hw.preamble_len & + MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + ctrl |= (((u32)(adapter->hw.retry_buf & + MAC_CTRL_HALF_LEFT_BUF_MASK)) << + MAC_CTRL_HALF_LEFT_BUF_SHIFT); + if (wufc & ATLX_WUFC_MAG) { + /* magic packet maybe Broadcast&multicast&Unicast */ + ctrl |= MAC_CTRL_BC_EN; + } + + ATL2_WRITE_REG(hw, REG_MAC_CTRL, ctrl); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + goto suspend_exit; + } + + if (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&ATLX_WUFC_LNKC)) { + /* link is down, so only LINK CHG WOL event enable */ + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl); + ATL2_WRITE_REG(hw, REG_MAC_CTRL, 0); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + hw->phy_configured = false; /* re-init PHY when resume */ + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + + goto suspend_exit; + } + +wol_dis: + /* WOL disabled */ + ATL2_WRITE_REG(hw, REG_WOL_CTRL, 0); + + /* pcie patch */ + ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); + ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1); + ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl); + + atl2_force_ps(hw); + hw->phy_configured = false; /* re-init PHY when resume */ + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + +suspend_exit: + if (netif_running(netdev)) + atl2_free_irq(adapter); + + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +#ifdef CONFIG_PM +static int atl2_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl2_adapter *adapter = netdev_priv(netdev); + u32 err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR + "atl2: Cannot enable PCI device from suspend\n"); + return err; + } + + pci_set_master(pdev); + + ATL2_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */ + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); + + err = atl2_request_irq(adapter); + if (netif_running(netdev) && err) + return err; + + atl2_reset_hw(&adapter->hw); + + if (netif_running(netdev)) + atl2_up(adapter); + + netif_device_attach(netdev); + + return 0; +} +#endif + +static void atl2_shutdown(struct pci_dev *pdev) +{ + atl2_suspend(pdev, PMSG_SUSPEND); +} + +static struct pci_driver atl2_driver = { + .name = atl2_driver_name, + .id_table = atl2_pci_tbl, + .probe = atl2_probe, + .remove = __devexit_p(atl2_remove), + /* Power Managment Hooks */ + .suspend = atl2_suspend, +#ifdef CONFIG_PM + .resume = atl2_resume, +#endif + .shutdown = atl2_shutdown, +}; + +/* + * atl2_init_module - Driver Registration Routine + * + * atl2_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + */ +static int __init atl2_init_module(void) +{ + printk(KERN_INFO "%s - version %s\n", atl2_driver_string, + atl2_driver_version); + printk(KERN_INFO "%s\n", atl2_copyright); + return pci_register_driver(&atl2_driver); +} +module_init(atl2_init_module); + +/* + * atl2_exit_module - Driver Exit Cleanup Routine + * + * atl2_exit_module is called just before the driver is removed + * from memory. + */ +static void __exit atl2_exit_module(void) +{ + pci_unregister_driver(&atl2_driver); +} +module_exit(atl2_exit_module); + +static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) +{ + struct atl2_adapter *adapter = hw->back; + pci_read_config_word(adapter->pdev, reg, value); +} + +static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) +{ + struct atl2_adapter *adapter = hw->back; + pci_write_config_word(adapter->pdev, reg, *value); +} + +static int atl2_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP); + ecmd->advertising = ADVERTISED_TP; + + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->advertising |= hw->autoneg_advertised; + + ecmd->port = PORT_TP; + ecmd->phy_address = 0; + ecmd->transceiver = XCVR_INTERNAL; + + if (adapter->link_speed != SPEED_0) { + ecmd->speed = adapter->link_speed; + if (adapter->link_duplex == FULL_DUPLEX) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; + } + + ecmd->autoneg = AUTONEG_ENABLE; + return 0; +} + +static int atl2_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + + while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags)) + msleep(1); + + if (ecmd->autoneg == AUTONEG_ENABLE) { +#define MY_ADV_MASK (ADVERTISE_10_HALF | \ + ADVERTISE_10_FULL | \ + ADVERTISE_100_HALF| \ + ADVERTISE_100_FULL) + + if ((ecmd->advertising & MY_ADV_MASK) == MY_ADV_MASK) { + hw->MediaType = MEDIA_TYPE_AUTO_SENSOR; + hw->autoneg_advertised = MY_ADV_MASK; + } else if ((ecmd->advertising & MY_ADV_MASK) == + ADVERTISE_100_FULL) { + hw->MediaType = MEDIA_TYPE_100M_FULL; + hw->autoneg_advertised = ADVERTISE_100_FULL; + } else if ((ecmd->advertising & MY_ADV_MASK) == + ADVERTISE_100_HALF) { + hw->MediaType = MEDIA_TYPE_100M_HALF; + hw->autoneg_advertised = ADVERTISE_100_HALF; + } else if ((ecmd->advertising & MY_ADV_MASK) == + ADVERTISE_10_FULL) { + hw->MediaType = MEDIA_TYPE_10M_FULL; + hw->autoneg_advertised = ADVERTISE_10_FULL; + } else if ((ecmd->advertising & MY_ADV_MASK) == + ADVERTISE_10_HALF) { + hw->MediaType = MEDIA_TYPE_10M_HALF; + hw->autoneg_advertised = ADVERTISE_10_HALF; + } else { + clear_bit(__ATL2_RESETTING, &adapter->flags); + return -EINVAL; + } + ecmd->advertising = hw->autoneg_advertised | + ADVERTISED_TP | ADVERTISED_Autoneg; + } else { + clear_bit(__ATL2_RESETTING, &adapter->flags); + return -EINVAL; + } + + /* reset the link */ + if (netif_running(adapter->netdev)) { + atl2_down(adapter); + atl2_up(adapter); + } else + atl2_reset_hw(&adapter->hw); + + clear_bit(__ATL2_RESETTING, &adapter->flags); + return 0; +} + +static u32 atl2_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_HW_CSUM) != 0; +} + +static u32 atl2_get_msglevel(struct net_device *netdev) +{ + return 0; +} + +/* + * It's sane for this to be empty, but we might want to take advantage of this. + */ +static void atl2_set_msglevel(struct net_device *netdev, u32 data) +{ +} + +static int atl2_get_regs_len(struct net_device *netdev) +{ +#define ATL2_REGS_LEN 42 + return sizeof(u32) * ATL2_REGS_LEN; +} + +static void atl2_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u16 phy_data; + + memset(p, 0, sizeof(u32) * ATL2_REGS_LEN); + + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; + + regs_buff[0] = ATL2_READ_REG(hw, REG_VPD_CAP); + regs_buff[1] = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + regs_buff[2] = ATL2_READ_REG(hw, REG_SPI_FLASH_CONFIG); + regs_buff[3] = ATL2_READ_REG(hw, REG_TWSI_CTRL); + regs_buff[4] = ATL2_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); + regs_buff[5] = ATL2_READ_REG(hw, REG_MASTER_CTRL); + regs_buff[6] = ATL2_READ_REG(hw, REG_MANUAL_TIMER_INIT); + regs_buff[7] = ATL2_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); + regs_buff[8] = ATL2_READ_REG(hw, REG_PHY_ENABLE); + regs_buff[9] = ATL2_READ_REG(hw, REG_CMBDISDMA_TIMER); + regs_buff[10] = ATL2_READ_REG(hw, REG_IDLE_STATUS); + regs_buff[11] = ATL2_READ_REG(hw, REG_MDIO_CTRL); + regs_buff[12] = ATL2_READ_REG(hw, REG_SERDES_LOCK); + regs_buff[13] = ATL2_READ_REG(hw, REG_MAC_CTRL); + regs_buff[14] = ATL2_READ_REG(hw, REG_MAC_IPG_IFG); + regs_buff[15] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR); + regs_buff[16] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR+4); + regs_buff[17] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE); + regs_buff[18] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE+4); + regs_buff[19] = ATL2_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); + regs_buff[20] = ATL2_READ_REG(hw, REG_MTU); + regs_buff[21] = ATL2_READ_REG(hw, REG_WOL_CTRL); + regs_buff[22] = ATL2_READ_REG(hw, REG_SRAM_TXRAM_END); + regs_buff[23] = ATL2_READ_REG(hw, REG_DESC_BASE_ADDR_HI); + regs_buff[24] = ATL2_READ_REG(hw, REG_TXD_BASE_ADDR_LO); + regs_buff[25] = ATL2_READ_REG(hw, REG_TXD_MEM_SIZE); + regs_buff[26] = ATL2_READ_REG(hw, REG_TXS_BASE_ADDR_LO); + regs_buff[27] = ATL2_READ_REG(hw, REG_TXS_MEM_SIZE); + regs_buff[28] = ATL2_READ_REG(hw, REG_RXD_BASE_ADDR_LO); + regs_buff[29] = ATL2_READ_REG(hw, REG_RXD_BUF_NUM); + regs_buff[30] = ATL2_READ_REG(hw, REG_DMAR); + regs_buff[31] = ATL2_READ_REG(hw, REG_TX_CUT_THRESH); + regs_buff[32] = ATL2_READ_REG(hw, REG_DMAW); + regs_buff[33] = ATL2_READ_REG(hw, REG_PAUSE_ON_TH); + regs_buff[34] = ATL2_READ_REG(hw, REG_PAUSE_OFF_TH); + regs_buff[35] = ATL2_READ_REG(hw, REG_MB_TXD_WR_IDX); + regs_buff[36] = ATL2_READ_REG(hw, REG_MB_RXD_RD_IDX); + regs_buff[38] = ATL2_READ_REG(hw, REG_ISR); + regs_buff[39] = ATL2_READ_REG(hw, REG_IMR); + + atl2_read_phy_reg(hw, MII_BMCR, &phy_data); + regs_buff[40] = (u32)phy_data; + atl2_read_phy_reg(hw, MII_BMSR, &phy_data); + regs_buff[41] = (u32)phy_data; +} + +static int atl2_get_eeprom_len(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + if (!atl2_check_eeprom_exist(&adapter->hw)) + return 512; + else + return 0; +} + +static int atl2_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *eeprom_buff; + int first_dword, last_dword; + int ret_val = 0; + int i; + + if (eeprom->len == 0) + return -EINVAL; + + if (atl2_check_eeprom_exist(hw)) + return -EINVAL; + + eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + first_dword = eeprom->offset >> 2; + last_dword = (eeprom->offset + eeprom->len - 1) >> 2; + + eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1), + GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + for (i = first_dword; i < last_dword; i++) { + if (!atl2_read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword]))) + return -EIO; + } + + memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), + eeprom->len); + kfree(eeprom_buff); + + return ret_val; +} + +static int atl2_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + struct atl2_hw *hw = &adapter->hw; + u32 *eeprom_buff; + u32 *ptr; + int max_len, first_dword, last_dword, ret_val = 0; + int i; + + if (eeprom->len == 0) + return -EOPNOTSUPP; + + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + + max_len = 512; + + first_dword = eeprom->offset >> 2; + last_dword = (eeprom->offset + eeprom->len - 1) >> 2; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = (u32 *)eeprom_buff; + + if (eeprom->offset & 3) { + /* need read/modify/write of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) + return -EIO; + ptr++; + } + if (((eeprom->offset + eeprom->len) & 3)) { + /* + * need read/modify/write of last changed EEPROM word + * only the first byte of the word is being modified + */ + if (!atl2_read_eeprom(hw, last_dword * 4, + &(eeprom_buff[last_dword - first_dword]))) + return -EIO; + } + + /* Device's eeprom is always little-endian, word addressable */ + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_dword - first_dword + 1; i++) { + if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) + return -EIO; + } + + kfree(eeprom_buff); + return ret_val; +} + +static void atl2_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + strncpy(drvinfo->driver, atl2_driver_name, 32); + strncpy(drvinfo->version, atl2_driver_version, 32); + strncpy(drvinfo->fw_version, "L2", 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + drvinfo->n_stats = 0; + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = atl2_get_regs_len(netdev); + drvinfo->eedump_len = atl2_get_eeprom_len(netdev); +} + +static void atl2_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + + if (adapter->wol & ATLX_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if (adapter->wol & ATLX_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if (adapter->wol & ATLX_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if (adapter->wol & ATLX_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + if (adapter->wol & ATLX_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; +} + +static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) + return -EOPNOTSUPP; + + if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST)) + return -EOPNOTSUPP; + + /* these settings will always override what we currently have */ + adapter->wol = 0; + + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= ATLX_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= ATLX_WUFC_LNKC; + + return 0; +} + +static int atl2_nway_reset(struct net_device *netdev) +{ + struct atl2_adapter *adapter = netdev_priv(netdev); + if (netif_running(netdev)) + atl2_reinit_locked(adapter); + return 0; +} + +static struct ethtool_ops atl2_ethtool_ops = { + .get_settings = atl2_get_settings, + .set_settings = atl2_set_settings, + .get_drvinfo = atl2_get_drvinfo, + .get_regs_len = atl2_get_regs_len, + .get_regs = atl2_get_regs, + .get_wol = atl2_get_wol, + .set_wol = atl2_set_wol, + .get_msglevel = atl2_get_msglevel, + .set_msglevel = atl2_set_msglevel, + .nway_reset = atl2_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = atl2_get_eeprom_len, + .get_eeprom = atl2_get_eeprom, + .set_eeprom = atl2_set_eeprom, + .get_tx_csum = atl2_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, +#endif +}; + +static void atl2_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops); +} + +#define LBYTESWAP(a) ((((a) & 0x00ff00ff) << 8) | \ + (((a) & 0xff00ff00) >> 8)) +#define LONGSWAP(a) ((LBYTESWAP(a) << 16) | (LBYTESWAP(a) >> 16)) +#define SHORTSWAP(a) (((a) << 8) | ((a) >> 8)) + +/* + * Reset the transmit and receive units; mask and clear all interrupts. + * + * hw - Struct containing variables accessed by shared code + * return : 0 or idle status (if error) + */ +static s32 atl2_reset_hw(struct atl2_hw *hw) +{ + u32 icr; + u16 pci_cfg_cmd_word; + int i; + + /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ + atl2_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); + if ((pci_cfg_cmd_word & + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) != + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) { + pci_cfg_cmd_word |= + (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER); + atl2_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word); + } + + /* Clear Interrupt mask to stop board from generating + * interrupts & Clear any pending interrupt events + */ + /* FIXME */ + /* ATL2_WRITE_REG(hw, REG_IMR, 0); */ + /* ATL2_WRITE_REG(hw, REG_ISR, 0xffffffff); */ + + /* Issue Soft Reset to the MAC. This will reset the chip's + * transmit, receive, DMA. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST); + wmb(); + msleep(1); /* delay about 1ms */ + + /* Wait at least 10ms for All module to be Idle */ + for (i = 0; i < 10; i++) { + icr = ATL2_READ_REG(hw, REG_IDLE_STATUS); + if (!icr) + break; + msleep(1); /* delay 1 ms */ + cpu_relax(); + } + + if (icr) + return icr; + + return 0; +} + +#define CUSTOM_SPI_CS_SETUP 2 +#define CUSTOM_SPI_CLK_HI 2 +#define CUSTOM_SPI_CLK_LO 2 +#define CUSTOM_SPI_CS_HOLD 2 +#define CUSTOM_SPI_CS_HI 3 + +static struct atl2_spi_flash_dev flash_table[] = +{ +/* MFR WRSR READ PROGRAM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE */ +{"Atmel", 0x0, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 }, +{"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 }, +{"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7 }, +}; + +static bool atl2_spi_read(struct atl2_hw *hw, u32 addr, u32 *buf) +{ + int i; + u32 value; + + ATL2_WRITE_REG(hw, REG_SPI_DATA, 0); + ATL2_WRITE_REG(hw, REG_SPI_ADDR, addr); + + value = SPI_FLASH_CTRL_WAIT_READY | + (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) << + SPI_FLASH_CTRL_CS_SETUP_SHIFT | + (CUSTOM_SPI_CLK_HI & SPI_FLASH_CTRL_CLK_HI_MASK) << + SPI_FLASH_CTRL_CLK_HI_SHIFT | + (CUSTOM_SPI_CLK_LO & SPI_FLASH_CTRL_CLK_LO_MASK) << + SPI_FLASH_CTRL_CLK_LO_SHIFT | + (CUSTOM_SPI_CS_HOLD & SPI_FLASH_CTRL_CS_HOLD_MASK) << + SPI_FLASH_CTRL_CS_HOLD_SHIFT | + (CUSTOM_SPI_CS_HI & SPI_FLASH_CTRL_CS_HI_MASK) << + SPI_FLASH_CTRL_CS_HI_SHIFT | + (0x1 & SPI_FLASH_CTRL_INS_MASK) << SPI_FLASH_CTRL_INS_SHIFT; + + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + + value |= SPI_FLASH_CTRL_START; + + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + + for (i = 0; i < 10; i++) { + msleep(1); + value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + if (!(value & SPI_FLASH_CTRL_START)) + break; + } + + if (value & SPI_FLASH_CTRL_START) + return false; + + *buf = ATL2_READ_REG(hw, REG_SPI_DATA); + + return true; +} + +/* + * get_permanent_address + * return 0 if get valid mac address, + */ +static int get_permanent_address(struct atl2_hw *hw) +{ + u32 Addr[2]; + u32 i, Control; + u16 Register; + u8 EthAddr[NODE_ADDRESS_SIZE]; + bool KeyValid; + + if (is_valid_ether_addr(hw->perm_mac_addr)) + return 0; + + Addr[0] = 0; + Addr[1] = 0; + + if (!atl2_check_eeprom_exist(hw)) { /* eeprom exists */ + Register = 0; + KeyValid = false; + + /* Read out all EEPROM content */ + i = 0; + while (1) { + if (atl2_read_eeprom(hw, i + 0x100, &Control)) { + if (KeyValid) { + if (Register == REG_MAC_STA_ADDR) + Addr[0] = Control; + else if (Register == + (REG_MAC_STA_ADDR + 4)) + Addr[1] = Control; + KeyValid = false; + } else if ((Control & 0xff) == 0x5A) { + KeyValid = true; + Register = (u16) (Control >> 16); + } else { + /* assume data end while encount an invalid KEYWORD */ + break; + } + } else { + break; /* read error */ + } + i += 4; + } + + *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]); + + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + return 1; + } + + /* see if SPI flash exists? */ + Addr[0] = 0; + Addr[1] = 0; + Register = 0; + KeyValid = false; + i = 0; + while (1) { + if (atl2_spi_read(hw, i + 0x1f000, &Control)) { + if (KeyValid) { + if (Register == REG_MAC_STA_ADDR) + Addr[0] = Control; + else if (Register == (REG_MAC_STA_ADDR + 4)) + Addr[1] = Control; + KeyValid = false; + } else if ((Control & 0xff) == 0x5A) { + KeyValid = true; + Register = (u16) (Control >> 16); + } else { + break; /* data end */ + } + } else { + break; /* read error */ + } + i += 4; + } + + *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *)&Addr[1]); + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + /* maybe MAC-address is from BIOS */ + Addr[0] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR); + Addr[1] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR + 4); + *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]); + *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]); + + if (is_valid_ether_addr(EthAddr)) { + memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE); + return 0; + } + + return 1; +} + +/* + * Reads the adapter's MAC address from the EEPROM + * + * hw - Struct containing variables accessed by shared code + */ +static s32 atl2_read_mac_addr(struct atl2_hw *hw) +{ + u16 i; + + if (get_permanent_address(hw)) { + /* for test */ + /* FIXME: shouldn't we use random_ether_addr() here? */ + hw->perm_mac_addr[0] = 0x00; + hw->perm_mac_addr[1] = 0x13; + hw->perm_mac_addr[2] = 0x74; + hw->perm_mac_addr[3] = 0x00; + hw->perm_mac_addr[4] = 0x5c; + hw->perm_mac_addr[5] = 0x38; + } + + for (i = 0; i < NODE_ADDRESS_SIZE; i++) + hw->mac_addr[i] = hw->perm_mac_addr[i]; + + return 0; +} + +/* + * Hashes an address to determine its location in the multicast table + * + * hw - Struct containing variables accessed by shared code + * mc_addr - the multicast address to hash + * + * atl2_hash_mc_addr + * purpose + * set hash value for a multicast address + * hash calcu processing : + * 1. calcu 32bit CRC for multicast address + * 2. reverse crc with MSB to LSB + */ +static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr) +{ + u32 crc32, value; + int i; + + value = 0; + crc32 = ether_crc_le(6, mc_addr); + + for (i = 0; i < 32; i++) + value |= (((crc32 >> i) & 1) << (31 - i)); + + return value; +} + +/* + * Sets the bit in the multicast table corresponding to the hash value. + * + * hw - Struct containing variables accessed by shared code + * hash_value - Multicast address hash value + */ +static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value) +{ + u32 hash_bit, hash_reg; + u32 mta; + + /* The HASH Table is a register array of 2 32-bit registers. + * It is treated like an array of 64 bits. We want to set + * bit BitArray[hash_value]. So we figure out what register + * the bit is in, read it, OR in the new bit, then write + * back the new value. The register is determined by the + * upper 7 bits of the hash value and the bit within that + * register are determined by the lower 5 bits of the value. + */ + hash_reg = (hash_value >> 31) & 0x1; + hash_bit = (hash_value >> 26) & 0x1F; + + mta = ATL2_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); + + mta |= (1 << hash_bit); + + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); +} + +/* + * atl2_init_pcie - init PCIE module + */ +static void atl2_init_pcie(struct atl2_hw *hw) +{ + u32 value; + value = LTSSM_TEST_MODE_DEF; + ATL2_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value); + + value = PCIE_DLL_TX_CTRL1_DEF; + ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, value); +} + +static void atl2_init_flash_opcode(struct atl2_hw *hw) +{ + if (hw->flash_vendor >= ARRAY_SIZE(flash_table)) + hw->flash_vendor = 0; /* ATMEL */ + + /* Init OP table */ + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM, + flash_table[hw->flash_vendor].cmdPROGRAM); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE, + flash_table[hw->flash_vendor].cmdSECTOR_ERASE); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE, + flash_table[hw->flash_vendor].cmdCHIP_ERASE); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID, + flash_table[hw->flash_vendor].cmdRDID); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN, + flash_table[hw->flash_vendor].cmdWREN); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR, + flash_table[hw->flash_vendor].cmdRDSR); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR, + flash_table[hw->flash_vendor].cmdWRSR); + ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ, + flash_table[hw->flash_vendor].cmdREAD); +} + +/******************************************************************** +* Performs basic configuration of the adapter. +* +* hw - Struct containing variables accessed by shared code +* Assumes that the controller has previously been reset and is in a +* post-reset uninitialized state. Initializes multicast table, +* and Calls routines to setup link +* Leaves the transmit and receive units disabled and uninitialized. +********************************************************************/ +static s32 atl2_init_hw(struct atl2_hw *hw) +{ + u32 ret_val = 0; + + atl2_init_pcie(hw); + + /* Zero out the Multicast HASH table */ + /* clear the old settings from the multicast hash table */ + ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); + ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); + + atl2_init_flash_opcode(hw); + + ret_val = atl2_phy_init(hw); + + return ret_val; +} + +/* + * Detects the current speed and duplex settings of the hardware. + * + * hw - Struct containing variables accessed by shared code + * speed - Speed of the connection + * duplex - Duplex setting of the connection + */ +static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, + u16 *duplex) +{ + s32 ret_val; + u16 phy_data; + + /* Read PHY Specific Status Register (17) */ + ret_val = atl2_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data); + if (ret_val) + return ret_val; + + if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED)) + return ATLX_ERR_PHY_RES; + + switch (phy_data & MII_ATLX_PSSR_SPEED) { + case MII_ATLX_PSSR_100MBS: + *speed = SPEED_100; + break; + case MII_ATLX_PSSR_10MBS: + *speed = SPEED_10; + break; + default: + return ATLX_ERR_PHY_SPEED; + break; + } + + if (phy_data & MII_ATLX_PSSR_DPLX) + *duplex = FULL_DUPLEX; + else + *duplex = HALF_DUPLEX; + + return 0; +} + +/* + * Reads the value from a PHY register + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to read + */ +static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data) +{ + u32 val; + int i; + + val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | + MDIO_START | + MDIO_SUP_PREAMBLE | + MDIO_RW | + MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; + ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val); + + wmb(); + + for (i = 0; i < MDIO_WAIT_TIMES; i++) { + udelay(2); + val = ATL2_READ_REG(hw, REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + wmb(); + } + if (!(val & (MDIO_START | MDIO_BUSY))) { + *phy_data = (u16)val; + return 0; + } + + return ATLX_ERR_PHY; +} + +/* + * Writes a value to a PHY register + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to write + * data - data to write to the PHY + */ +static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data) +{ + int i; + u32 val; + + val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | + (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | + MDIO_SUP_PREAMBLE | + MDIO_START | + MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; + ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val); + + wmb(); + + for (i = 0; i < MDIO_WAIT_TIMES; i++) { + udelay(2); + val = ATL2_READ_REG(hw, REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + + wmb(); + } + + if (!(val & (MDIO_START | MDIO_BUSY))) + return 0; + + return ATLX_ERR_PHY; +} + +/* + * Configures PHY autoneg and flow control advertisement settings + * + * hw - Struct containing variables accessed by shared code + */ +static s32 atl2_phy_setup_autoneg_adv(struct atl2_hw *hw) +{ + s32 ret_val; + s16 mii_autoneg_adv_reg; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ + mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; + + /* Need to parse autoneg_advertised and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + + /* First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). */ + mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK; + + /* Need to parse MediaType and setup the + * appropriate PHY registers. */ + switch (hw->MediaType) { + case MEDIA_TYPE_AUTO_SENSOR: + mii_autoneg_adv_reg |= + (MII_AR_10T_HD_CAPS | + MII_AR_10T_FD_CAPS | + MII_AR_100TX_HD_CAPS| + MII_AR_100TX_FD_CAPS); + hw->autoneg_advertised = + ADVERTISE_10_HALF | + ADVERTISE_10_FULL | + ADVERTISE_100_HALF| + ADVERTISE_100_FULL; + break; + case MEDIA_TYPE_100M_FULL: + mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS; + hw->autoneg_advertised = ADVERTISE_100_FULL; + break; + case MEDIA_TYPE_100M_HALF: + mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS; + hw->autoneg_advertised = ADVERTISE_100_HALF; + break; + case MEDIA_TYPE_10M_FULL: + mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS; + hw->autoneg_advertised = ADVERTISE_10_FULL; + break; + default: + mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS; + hw->autoneg_advertised = ADVERTISE_10_HALF; + break; + } + + /* flow control fixed to enable all */ + mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE); + + hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; + + ret_val = atl2_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); + + if (ret_val) + return ret_val; + + return 0; +} + +/* + * Resets the PHY and make all config validate + * + * hw - Struct containing variables accessed by shared code + * + * Sets bit 15 and 12 of the MII Control regiser (for F001 bug) + */ +static s32 atl2_phy_commit(struct atl2_hw *hw) +{ + s32 ret_val; + u16 phy_data; + + phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG; + ret_val = atl2_write_phy_reg(hw, MII_BMCR, phy_data); + if (ret_val) { + u32 val; + int i; + /* pcie serdes link may be down ! */ + for (i = 0; i < 25; i++) { + msleep(1); + val = ATL2_READ_REG(hw, REG_MDIO_CTRL); + if (!(val & (MDIO_START | MDIO_BUSY))) + break; + } + + if (0 != (val & (MDIO_START | MDIO_BUSY))) { + printk(KERN_ERR "atl2: PCIe link down for at least 25ms !\n"); + return ret_val; + } + } + return 0; +} + +static s32 atl2_phy_init(struct atl2_hw *hw) +{ + s32 ret_val; + u16 phy_val; + + if (hw->phy_configured) + return 0; + + /* Enable PHY */ + ATL2_WRITE_REGW(hw, REG_PHY_ENABLE, 1); + ATL2_WRITE_FLUSH(hw); + msleep(1); + + /* check if the PHY is in powersaving mode */ + atl2_write_phy_reg(hw, MII_DBG_ADDR, 0); + atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val); + + /* 024E / 124E 0r 0274 / 1274 ? */ + if (phy_val & 0x1000) { + phy_val &= ~0x1000; + atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val); + } + + msleep(1); + + /*Enable PHY LinkChange Interrupt */ + ret_val = atl2_write_phy_reg(hw, 18, 0xC00); + if (ret_val) + return ret_val; + + /* setup AutoNeg parameters */ + ret_val = atl2_phy_setup_autoneg_adv(hw); + if (ret_val) + return ret_val; + + /* SW.Reset & En-Auto-Neg to restart Auto-Neg */ + ret_val = atl2_phy_commit(hw); + if (ret_val) + return ret_val; + + hw->phy_configured = true; + + return ret_val; +} + +static void atl2_set_mac_addr(struct atl2_hw *hw) +{ + u32 value; + /* 00-0B-6A-F6-00-DC + * 0: 6AF600DC 1: 000B + * low dword */ + value = (((u32)hw->mac_addr[2]) << 24) | + (((u32)hw->mac_addr[3]) << 16) | + (((u32)hw->mac_addr[4]) << 8) | + (((u32)hw->mac_addr[5])); + ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); + /* hight dword */ + value = (((u32)hw->mac_addr[0]) << 8) | + (((u32)hw->mac_addr[1])); + ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); +} + +/* + * check_eeprom_exist + * return 0 if eeprom exist + */ +static int atl2_check_eeprom_exist(struct atl2_hw *hw) +{ + u32 value; + + value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL); + if (value & SPI_FLASH_CTRL_EN_VPD) { + value &= ~SPI_FLASH_CTRL_EN_VPD; + ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); + } + value = ATL2_READ_REGW(hw, REG_PCIE_CAP_LIST); + return ((value & 0xFF00) == 0x6C00) ? 0 : 1; +} + +/* FIXME: This doesn't look right. -- CHS */ +static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value) +{ + return true; +} + +static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue) +{ + int i; + u32 Control; + + if (Offset & 0x3) + return false; /* address do not align */ + + ATL2_WRITE_REG(hw, REG_VPD_DATA, 0); + Control = (Offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; + ATL2_WRITE_REG(hw, REG_VPD_CAP, Control); + + for (i = 0; i < 10; i++) { + msleep(2); + Control = ATL2_READ_REG(hw, REG_VPD_CAP); + if (Control & VPD_CAP_VPD_FLAG) + break; + } + + if (Control & VPD_CAP_VPD_FLAG) { + *pValue = ATL2_READ_REG(hw, REG_VPD_DATA); + return true; + } + return false; /* timeout */ +} + +static void atl2_force_ps(struct atl2_hw *hw) +{ + u16 phy_val; + + atl2_write_phy_reg(hw, MII_DBG_ADDR, 0); + atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val); + atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val | 0x1000); + + atl2_write_phy_reg(hw, MII_DBG_ADDR, 2); + atl2_write_phy_reg(hw, MII_DBG_DATA, 0x3000); + atl2_write_phy_reg(hw, MII_DBG_ADDR, 3); + atl2_write_phy_reg(hw, MII_DBG_DATA, 0); +} + +/* This is the only thing that needs to be changed to adjust the + * maximum number of ports that the driver can manage. + */ +#define ATL2_MAX_NIC 4 + +#define OPTION_UNSET -1 +#define OPTION_DISABLED 0 +#define OPTION_ENABLED 1 + +/* All parameters are treated the same, as an integer array of values. + * This macro just reduces the need to repeat the same declaration code + * over and over (plus this helps to avoid typo bugs). + */ +#define ATL2_PARAM_INIT {[0 ... ATL2_MAX_NIC] = OPTION_UNSET} +#ifndef module_param_array +/* Module Parameters are always initialized to -1, so that the driver + * can tell the difference between no user specified value or the + * user asking for the default value. + * The true default values are loaded in when atl2_check_options is called. + * + * This is a GCC extension to ANSI C. + * See the item "Labeled Elements in Initializers" in the section + * "Extensions to the C Language Family" of the GCC documentation. + */ + +#define ATL2_PARAM(X, desc) \ + static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ + MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \ + MODULE_PARM_DESC(X, desc); +#else +#define ATL2_PARAM(X, desc) \ + static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \ + static int num_##X = 0; \ + module_param_array_named(X, X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); +#endif + +/* + * Transmit Memory Size + * Valid Range: 64-2048 + * Default Value: 128 + */ +#define ATL2_MIN_TX_MEMSIZE 4 /* 4KB */ +#define ATL2_MAX_TX_MEMSIZE 64 /* 64KB */ +#define ATL2_DEFAULT_TX_MEMSIZE 8 /* 8KB */ +ATL2_PARAM(TxMemSize, "Bytes of Transmit Memory"); + +/* + * Receive Memory Block Count + * Valid Range: 16-512 + * Default Value: 128 + */ +#define ATL2_MIN_RXD_COUNT 16 +#define ATL2_MAX_RXD_COUNT 512 +#define ATL2_DEFAULT_RXD_COUNT 64 +ATL2_PARAM(RxMemBlock, "Number of receive memory block"); + +/* + * User Specified MediaType Override + * + * Valid Range: 0-5 + * - 0 - auto-negotiate at all supported speeds + * - 1 - only link at 1000Mbps Full Duplex + * - 2 - only link at 100Mbps Full Duplex + * - 3 - only link at 100Mbps Half Duplex + * - 4 - only link at 10Mbps Full Duplex + * - 5 - only link at 10Mbps Half Duplex + * Default Value: 0 + */ +ATL2_PARAM(MediaType, "MediaType Select"); + +/* + * Interrupt Moderate Timer in units of 2048 ns (~2 us) + * Valid Range: 10-65535 + * Default Value: 45000(90ms) + */ +#define INT_MOD_DEFAULT_CNT 100 /* 200us */ +#define INT_MOD_MAX_CNT 65000 +#define INT_MOD_MIN_CNT 50 +ATL2_PARAM(IntModTimer, "Interrupt Moderator Timer"); + +/* + * FlashVendor + * Valid Range: 0-2 + * 0 - Atmel + * 1 - SST + * 2 - ST + */ +ATL2_PARAM(FlashVendor, "SPI Flash Vendor"); + +#define AUTONEG_ADV_DEFAULT 0x2F +#define AUTONEG_ADV_MASK 0x2F +#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL + +#define FLASH_VENDOR_DEFAULT 0 +#define FLASH_VENDOR_MIN 0 +#define FLASH_VENDOR_MAX 2 + +struct atl2_option { + enum { enable_option, range_option, list_option } type; + char *name; + char *err; + int def; + union { + struct { /* range_option info */ + int min; + int max; + } r; + struct { /* list_option info */ + int nr; + struct atl2_opt_list { int i; char *str; } *p; + } l; + } arg; +}; + +static int __devinit atl2_validate_option(int *value, struct atl2_option *opt) +{ + int i; + struct atl2_opt_list *ent; + + if (*value == OPTION_UNSET) { + *value = opt->def; + return 0; + } + + switch (opt->type) { + case enable_option: + switch (*value) { + case OPTION_ENABLED: + printk(KERN_INFO "%s Enabled\n", opt->name); + return 0; + break; + case OPTION_DISABLED: + printk(KERN_INFO "%s Disabled\n", opt->name); + return 0; + break; + } + break; + case range_option: + if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { + printk(KERN_INFO "%s set to %i\n", opt->name, *value); + return 0; + } + break; + case list_option: + for (i = 0; i < opt->arg.l.nr; i++) { + ent = &opt->arg.l.p[i]; + if (*value == ent->i) { + if (ent->str[0] != '\0') + printk(KERN_INFO "%s\n", ent->str); + return 0; + } + } + break; + default: + BUG(); + } + + printk(KERN_INFO "Invalid %s specified (%i) %s\n", + opt->name, *value, opt->err); + *value = opt->def; + return -1; +} + +/* + * atl2_check_options - Range Checking for Command Line Parameters + * @adapter: board private structure + * + * This routine checks all command line parameters for valid user + * input. If an invalid value is given, or if no user specified + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + */ +static void __devinit atl2_check_options(struct atl2_adapter *adapter) +{ + int val; + struct atl2_option opt; + int bd = adapter->bd_number; + if (bd >= ATL2_MAX_NIC) { + printk(KERN_NOTICE "Warning: no configuration for board #%i\n", + bd); + printk(KERN_NOTICE "Using defaults for all values\n"); +#ifndef module_param_array + bd = ATL2_MAX_NIC; +#endif + } + + /* Bytes of Transmit Memory */ + opt.type = range_option; + opt.name = "Bytes of Transmit Memory"; + opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_TX_MEMSIZE); + opt.def = ATL2_DEFAULT_TX_MEMSIZE; + opt.arg.r.min = ATL2_MIN_TX_MEMSIZE; + opt.arg.r.max = ATL2_MAX_TX_MEMSIZE; +#ifdef module_param_array + if (num_TxMemSize > bd) { +#endif + val = TxMemSize[bd]; + atl2_validate_option(&val, &opt); + adapter->txd_ring_size = ((u32) val) * 1024; +#ifdef module_param_array + } else + adapter->txd_ring_size = ((u32)opt.def) * 1024; +#endif + /* txs ring size: */ + adapter->txs_ring_size = adapter->txd_ring_size / 128; + if (adapter->txs_ring_size > 160) + adapter->txs_ring_size = 160; + + /* Receive Memory Block Count */ + opt.type = range_option; + opt.name = "Number of receive memory block"; + opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_RXD_COUNT); + opt.def = ATL2_DEFAULT_RXD_COUNT; + opt.arg.r.min = ATL2_MIN_RXD_COUNT; + opt.arg.r.max = ATL2_MAX_RXD_COUNT; +#ifdef module_param_array + if (num_RxMemBlock > bd) { +#endif + val = RxMemBlock[bd]; + atl2_validate_option(&val, &opt); + adapter->rxd_ring_size = (u32)val; + /* FIXME */ + /* ((u16)val)&~1; */ /* even number */ +#ifdef module_param_array + } else + adapter->rxd_ring_size = (u32)opt.def; +#endif + /* init RXD Flow control value */ + adapter->hw.fc_rxd_hi = (adapter->rxd_ring_size / 8) * 7; + adapter->hw.fc_rxd_lo = (ATL2_MIN_RXD_COUNT / 8) > + (adapter->rxd_ring_size / 12) ? (ATL2_MIN_RXD_COUNT / 8) : + (adapter->rxd_ring_size / 12); + + /* Interrupt Moderate Timer */ + opt.type = range_option; + opt.name = "Interrupt Moderate Timer"; + opt.err = "using default of " __MODULE_STRING(INT_MOD_DEFAULT_CNT); + opt.def = INT_MOD_DEFAULT_CNT; + opt.arg.r.min = INT_MOD_MIN_CNT; + opt.arg.r.max = INT_MOD_MAX_CNT; +#ifdef module_param_array + if (num_IntModTimer > bd) { +#endif + val = IntModTimer[bd]; + atl2_validate_option(&val, &opt); + adapter->imt = (u16) val; +#ifdef module_param_array + } else + adapter->imt = (u16)(opt.def); +#endif + /* Flash Vendor */ + opt.type = range_option; + opt.name = "SPI Flash Vendor"; + opt.err = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT); + opt.def = FLASH_VENDOR_DEFAULT; + opt.arg.r.min = FLASH_VENDOR_MIN; + opt.arg.r.max = FLASH_VENDOR_MAX; +#ifdef module_param_array + if (num_FlashVendor > bd) { +#endif + val = FlashVendor[bd]; + atl2_validate_option(&val, &opt); + adapter->hw.flash_vendor = (u8) val; +#ifdef module_param_array + } else + adapter->hw.flash_vendor = (u8)(opt.def); +#endif + /* MediaType */ + opt.type = range_option; + opt.name = "Speed/Duplex Selection"; + opt.err = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR); + opt.def = MEDIA_TYPE_AUTO_SENSOR; + opt.arg.r.min = MEDIA_TYPE_AUTO_SENSOR; + opt.arg.r.max = MEDIA_TYPE_10M_HALF; +#ifdef module_param_array + if (num_MediaType > bd) { +#endif + val = MediaType[bd]; + atl2_validate_option(&val, &opt); + adapter->hw.MediaType = (u16) val; +#ifdef module_param_array + } else + adapter->hw.MediaType = (u16)(opt.def); +#endif +} diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h new file mode 100644 index 00000000000..6e1f28ff227 --- /dev/null +++ b/drivers/net/atlx/atl2.h @@ -0,0 +1,530 @@ +/* atl2.h -- atl2 driver definitions + * + * Copyright(c) 2007 Atheros Corporation. All rights reserved. + * Copyright(c) 2006 xiong huang + * Copyright(c) 2007 Chris Snook + * + * Derived from Intel e1000 driver + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ATL2_H_ +#define _ATL2_H_ + +#include +#include + +#ifndef _ATL2_HW_H_ +#define _ATL2_HW_H_ + +#ifndef _ATL2_OSDEP_H_ +#define _ATL2_OSDEP_H_ + +#include +#include +#include +#include + +#include "atlx.h" + +#ifdef ETHTOOL_OPS_COMPAT +extern int ethtool_ioctl(struct ifreq *ifr); +#endif + +#define PCI_COMMAND_REGISTER PCI_COMMAND +#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE +#define ETH_ADDR_LEN ETH_ALEN + +#define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \ + ((a)->hw_addr + (reg)))) + +#define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr)) + +#define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg))) + +#define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \ + ((a)->hw_addr + (reg)))) + +#define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg))) + +#define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \ + ((a)->hw_addr + (reg)))) + +#define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg))) + +#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \ + (iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2)))) + +#define ATL2_READ_REG_ARRAY(a, reg, offset) \ + (ioread32(((a)->hw_addr + (reg)) + ((offset) << 2))) + +#endif /* _ATL2_OSDEP_H_ */ + +struct atl2_adapter; +struct atl2_hw; + +/* function prototype */ +static s32 atl2_reset_hw(struct atl2_hw *hw); +static s32 atl2_read_mac_addr(struct atl2_hw *hw); +static s32 atl2_init_hw(struct atl2_hw *hw); +static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, + u16 *duplex); +static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr); +static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value); +static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data); +static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data); +static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); +static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); +static void atl2_set_mac_addr(struct atl2_hw *hw); +static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue); +static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value); +static s32 atl2_phy_init(struct atl2_hw *hw); +static int atl2_check_eeprom_exist(struct atl2_hw *hw); +static void atl2_force_ps(struct atl2_hw *hw); + +/* register definition */ + +/* Block IDLE Status Register */ +#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC is non-IDLE */ +#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC is non-IDLE */ +#define IDLE_STATUS_DMAR 8 /* 1: DMAR is non-IDLE */ +#define IDLE_STATUS_DMAW 4 /* 1: DMAW is non-IDLE */ + +/* MDIO Control Register */ +#define MDIO_WAIT_TIMES 10 + +/* MAC Control Register */ +#define MAC_CTRL_DBG_TX_BKPRESURE 0x100000 /* 1: TX max backoff */ +#define MAC_CTRL_MACLP_CLK_PHY 0x8000000 /* 1: 25MHz from phy */ +#define MAC_CTRL_HALF_LEFT_BUF_SHIFT 28 +#define MAC_CTRL_HALF_LEFT_BUF_MASK 0xF /* MAC retry buf x32B */ + +/* Internal SRAM Partition Register */ +#define REG_SRAM_TXRAM_END 0x1500 /* Internal tail address of TXRAM + * default: 2byte*1024 */ +#define REG_SRAM_RXRAM_END 0x1502 /* Internal tail address of RXRAM + * default: 2byte*1024 */ + +/* Descriptor Control register */ +#define REG_TXD_BASE_ADDR_LO 0x1544 /* The base address of the Transmit + * Data Mem low 32-bit(dword align) */ +#define REG_TXD_MEM_SIZE 0x1548 /* Transmit Data Memory size(by + * double word , max 256KB) */ +#define REG_TXS_BASE_ADDR_LO 0x154C /* The base address of the Transmit + * Status Memory low 32-bit(dword word + * align) */ +#define REG_TXS_MEM_SIZE 0x1550 /* double word unit, max 4*2047 + * bytes. */ +#define REG_RXD_BASE_ADDR_LO 0x1554 /* The base address of the Transmit + * Status Memory low 32-bit(unit 8 + * bytes) */ +#define REG_RXD_BUF_NUM 0x1558 /* Receive Data & Status Memory buffer + * number (unit 1536bytes, max + * 1536*2047) */ + +/* DMAR Control Register */ +#define REG_DMAR 0x1580 +#define DMAR_EN 0x1 /* 1: Enable DMAR */ + +/* TX Cur-Through (early tx threshold) Control Register */ +#define REG_TX_CUT_THRESH 0x1590 /* TxMac begin transmit packet + * threshold(unit word) */ + +/* DMAW Control Register */ +#define REG_DMAW 0x15A0 +#define DMAW_EN 0x1 + +/* Flow control register */ +#define REG_PAUSE_ON_TH 0x15A8 /* RXD high watermark of overflow + * threshold configuration register */ +#define REG_PAUSE_OFF_TH 0x15AA /* RXD lower watermark of overflow + * threshold configuration register */ + +/* Mailbox Register */ +#define REG_MB_TXD_WR_IDX 0x15f0 /* double word align */ +#define REG_MB_RXD_RD_IDX 0x15F4 /* RXD Read index (unit: 1536byets) */ + +/* Interrupt Status Register */ +#define ISR_TIMER 1 /* Interrupt when Timer counts down to zero */ +#define ISR_MANUAL 2 /* Software manual interrupt, for debug. Set + * when SW_MAN_INT_EN is set in Table 51 + * Selene Master Control Register + * (Offset 0x1400). */ +#define ISR_RXF_OV 4 /* RXF overflow interrupt */ +#define ISR_TXF_UR 8 /* TXF underrun interrupt */ +#define ISR_TXS_OV 0x10 /* Internal transmit status buffer full + * interrupt */ +#define ISR_RXS_OV 0x20 /* Internal receive status buffer full + * interrupt */ +#define ISR_LINK_CHG 0x40 /* Link Status Change Interrupt */ +#define ISR_HOST_TXD_UR 0x80 +#define ISR_HOST_RXD_OV 0x100 /* Host rx data memory full , one pulse */ +#define ISR_DMAR_TO_RST 0x200 /* DMAR op timeout interrupt. SW should + * do Reset */ +#define ISR_DMAW_TO_RST 0x400 +#define ISR_PHY 0x800 /* phy interrupt */ +#define ISR_TS_UPDATE 0x10000 /* interrupt after new tx pkt status written + * to host */ +#define ISR_RS_UPDATE 0x20000 /* interrupt ater new rx pkt status written + * to host. */ +#define ISR_TX_EARLY 0x40000 /* interrupt when txmac begin transmit one + * packet */ + +#define ISR_TX_EVENT (ISR_TXF_UR | ISR_TXS_OV | ISR_HOST_TXD_UR |\ + ISR_TS_UPDATE | ISR_TX_EARLY) +#define ISR_RX_EVENT (ISR_RXF_OV | ISR_RXS_OV | ISR_HOST_RXD_OV |\ + ISR_RS_UPDATE) + +#define IMR_NORMAL_MASK (\ + /*ISR_LINK_CHG |*/\ + ISR_MANUAL |\ + ISR_DMAR_TO_RST |\ + ISR_DMAW_TO_RST |\ + ISR_PHY |\ + ISR_PHY_LINKDOWN |\ + ISR_TS_UPDATE |\ + ISR_RS_UPDATE) + +/* Receive MAC Statistics Registers */ +#define REG_STS_RX_PAUSE 0x1700 /* Num pause packets received */ +#define REG_STS_RXD_OV 0x1704 /* Num frames dropped due to RX + * FIFO overflow */ +#define REG_STS_RXS_OV 0x1708 /* Num frames dropped due to RX + * Status Buffer Overflow */ +#define REG_STS_RX_FILTER 0x170C /* Num packets dropped due to + * address filtering */ + +/* MII definitions */ + +/* PHY Common Register */ +#define MII_SMARTSPEED 0x14 +#define MII_DBG_ADDR 0x1D +#define MII_DBG_DATA 0x1E + +/* PCI Command Register Bit Definitions */ +#define PCI_REG_COMMAND 0x04 +#define CMD_IO_SPACE 0x0001 +#define CMD_MEMORY_SPACE 0x0002 +#define CMD_BUS_MASTER 0x0004 + +#define MEDIA_TYPE_100M_FULL 1 +#define MEDIA_TYPE_100M_HALF 2 +#define MEDIA_TYPE_10M_FULL 3 +#define MEDIA_TYPE_10M_HALF 4 + +#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */ + +/* The size (in bytes) of a ethernet packet */ +#define ENET_HEADER_SIZE 14 +#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ +#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ +#define ETHERNET_FCS_SIZE 4 +#define MAX_JUMBO_FRAME_SIZE 0x2000 +#define VLAN_SIZE 4 + +struct tx_pkt_header { + unsigned pkt_size:11; + unsigned:4; /* reserved */ + unsigned ins_vlan:1; /* txmac should insert vlan */ + unsigned short vlan; /* vlan tag */ +}; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define TX_PKT_HEADER_SIZE_MASK 0x7FF +#define TX_PKT_HEADER_SIZE_SHIFT 0 +#define TX_PKT_HEADER_INS_VLAN_MASK 0x1 +#define TX_PKT_HEADER_INS_VLAN_SHIFT 15 +#define TX_PKT_HEADER_VLAN_TAG_MASK 0xFFFF +#define TX_PKT_HEADER_VLAN_TAG_SHIFT 16 + +struct tx_pkt_status { + unsigned pkt_size:11; + unsigned:5; /* reserved */ + unsigned ok:1; /* current packet transmitted without error */ + unsigned bcast:1; /* broadcast packet */ + unsigned mcast:1; /* multicast packet */ + unsigned pause:1; /* transmiited a pause frame */ + unsigned ctrl:1; + unsigned defer:1; /* current packet is xmitted with defer */ + unsigned exc_defer:1; + unsigned single_col:1; + unsigned multi_col:1; + unsigned late_col:1; + unsigned abort_col:1; + unsigned underun:1; /* current packet is aborted + * due to txram underrun */ + unsigned:3; /* reserved */ + unsigned update:1; /* always 1'b1 in tx_status_buf */ +}; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define TX_PKT_STATUS_SIZE_MASK 0x7FF +#define TX_PKT_STATUS_SIZE_SHIFT 0 +#define TX_PKT_STATUS_OK_MASK 0x1 +#define TX_PKT_STATUS_OK_SHIFT 16 +#define TX_PKT_STATUS_BCAST_MASK 0x1 +#define TX_PKT_STATUS_BCAST_SHIFT 17 +#define TX_PKT_STATUS_MCAST_MASK 0x1 +#define TX_PKT_STATUS_MCAST_SHIFT 18 +#define TX_PKT_STATUS_PAUSE_MASK 0x1 +#define TX_PKT_STATUS_PAUSE_SHIFT 19 +#define TX_PKT_STATUS_CTRL_MASK 0x1 +#define TX_PKT_STATUS_CTRL_SHIFT 20 +#define TX_PKT_STATUS_DEFER_MASK 0x1 +#define TX_PKT_STATUS_DEFER_SHIFT 21 +#define TX_PKT_STATUS_EXC_DEFER_MASK 0x1 +#define TX_PKT_STATUS_EXC_DEFER_SHIFT 22 +#define TX_PKT_STATUS_SINGLE_COL_MASK 0x1 +#define TX_PKT_STATUS_SINGLE_COL_SHIFT 23 +#define TX_PKT_STATUS_MULTI_COL_MASK 0x1 +#define TX_PKT_STATUS_MULTI_COL_SHIFT 24 +#define TX_PKT_STATUS_LATE_COL_MASK 0x1 +#define TX_PKT_STATUS_LATE_COL_SHIFT 25 +#define TX_PKT_STATUS_ABORT_COL_MASK 0x1 +#define TX_PKT_STATUS_ABORT_COL_SHIFT 26 +#define TX_PKT_STATUS_UNDERRUN_MASK 0x1 +#define TX_PKT_STATUS_UNDERRUN_SHIFT 27 +#define TX_PKT_STATUS_UPDATE_MASK 0x1 +#define TX_PKT_STATUS_UPDATE_SHIFT 31 + +struct rx_pkt_status { + unsigned pkt_size:11; /* packet size, max 2047 bytes */ + unsigned:5; /* reserved */ + unsigned ok:1; /* current packet received ok without error */ + unsigned bcast:1; /* current packet is broadcast */ + unsigned mcast:1; /* current packet is multicast */ + unsigned pause:1; + unsigned ctrl:1; + unsigned crc:1; /* received a packet with crc error */ + unsigned code:1; /* received a packet with code error */ + unsigned runt:1; /* received a packet less than 64 bytes + * with good crc */ + unsigned frag:1; /* received a packet less than 64 bytes + * with bad crc */ + unsigned trunc:1; /* current frame truncated due to rxram full */ + unsigned align:1; /* this packet is alignment error */ + unsigned vlan:1; /* this packet has vlan */ + unsigned:3; /* reserved */ + unsigned update:1; + unsigned short vtag; /* vlan tag */ + unsigned:16; +}; +/* FIXME: replace above bitfields with MASK/SHIFT defines below */ +#define RX_PKT_STATUS_SIZE_MASK 0x7FF +#define RX_PKT_STATUS_SIZE_SHIFT 0 +#define RX_PKT_STATUS_OK_MASK 0x1 +#define RX_PKT_STATUS_OK_SHIFT 16 +#define RX_PKT_STATUS_BCAST_MASK 0x1 +#define RX_PKT_STATUS_BCAST_SHIFT 17 +#define RX_PKT_STATUS_MCAST_MASK 0x1 +#define RX_PKT_STATUS_MCAST_SHIFT 18 +#define RX_PKT_STATUS_PAUSE_MASK 0x1 +#define RX_PKT_STATUS_PAUSE_SHIFT 19 +#define RX_PKT_STATUS_CTRL_MASK 0x1 +#define RX_PKT_STATUS_CTRL_SHIFT 20 +#define RX_PKT_STATUS_CRC_MASK 0x1 +#define RX_PKT_STATUS_CRC_SHIFT 21 +#define RX_PKT_STATUS_CODE_MASK 0x1 +#define RX_PKT_STATUS_CODE_SHIFT 22 +#define RX_PKT_STATUS_RUNT_MASK 0x1 +#define RX_PKT_STATUS_RUNT_SHIFT 23 +#define RX_PKT_STATUS_FRAG_MASK 0x1 +#define RX_PKT_STATUS_FRAG_SHIFT 24 +#define RX_PKT_STATUS_TRUNK_MASK 0x1 +#define RX_PKT_STATUS_TRUNK_SHIFT 25 +#define RX_PKT_STATUS_ALIGN_MASK 0x1 +#define RX_PKT_STATUS_ALIGN_SHIFT 26 +#define RX_PKT_STATUS_VLAN_MASK 0x1 +#define RX_PKT_STATUS_VLAN_SHIFT 27 +#define RX_PKT_STATUS_UPDATE_MASK 0x1 +#define RX_PKT_STATUS_UPDATE_SHIFT 31 +#define RX_PKT_STATUS_VLAN_TAG_MASK 0xFFFF +#define RX_PKT_STATUS_VLAN_TAG_SHIFT 32 + +struct rx_desc { + struct rx_pkt_status status; + unsigned char packet[1536-sizeof(struct rx_pkt_status)]; +}; + +enum atl2_speed_duplex { + atl2_10_half = 0, + atl2_10_full = 1, + atl2_100_half = 2, + atl2_100_full = 3 +}; + +struct atl2_spi_flash_dev { + const char *manu_name; /* manufacturer id */ + /* op-code */ + u8 cmdWRSR; + u8 cmdREAD; + u8 cmdPROGRAM; + u8 cmdWREN; + u8 cmdWRDI; + u8 cmdRDSR; + u8 cmdRDID; + u8 cmdSECTOR_ERASE; + u8 cmdCHIP_ERASE; +}; + +/* Structure containing variables used by the shared code (atl2_hw.c) */ +struct atl2_hw { + u8 __iomem *hw_addr; + void *back; + + u8 preamble_len; + u8 max_retry; /* Retransmission maximum, afterwards the + * packet will be discarded. */ + u8 jam_ipg; /* IPG to start JAM for collision based flow + * control in half-duplex mode. In unit of + * 8-bit time. */ + u8 ipgt; /* Desired back to back inter-packet gap. The + * default is 96-bit time. */ + u8 min_ifg; /* Minimum number of IFG to enforce in between + * RX frames. Frame gap below such IFP is + * dropped. */ + u8 ipgr1; /* 64bit Carrier-Sense window */ + u8 ipgr2; /* 96-bit IPG window */ + u8 retry_buf; /* When half-duplex mode, should hold some + * bytes for mac retry . (8*4bytes unit) */ + + u16 fc_rxd_hi; + u16 fc_rxd_lo; + u16 lcol; /* Collision Window */ + u16 max_frame_size; + + u16 MediaType; + u16 autoneg_advertised; + u16 pci_cmd_word; + + u16 mii_autoneg_adv_reg; + + u32 mem_rang; + u32 txcw; + u32 mc_filter_type; + u32 num_mc_addrs; + u32 collision_delta; + u32 tx_packet_delta; + u16 phy_spd_default; + + u16 device_id; + u16 vendor_id; + u16 subsystem_id; + u16 subsystem_vendor_id; + u8 revision_id; + + /* spi flash */ + u8 flash_vendor; + + u8 dma_fairness; + u8 mac_addr[NODE_ADDRESS_SIZE]; + u8 perm_mac_addr[NODE_ADDRESS_SIZE]; + + /* FIXME */ + /* bool phy_preamble_sup; */ + bool phy_configured; +}; + +#endif /* _ATL2_HW_H_ */ + +struct atl2_ring_header { + /* pointer to the descriptor ring memory */ + void *desc; + /* physical adress of the descriptor ring */ + dma_addr_t dma; + /* length of descriptor ring in bytes */ + unsigned int size; +}; + +/* board specific private data structure */ +struct atl2_adapter { + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; +#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; +#endif + u32 wol; + u16 link_speed; + u16 link_duplex; + + spinlock_t stats_lock; + spinlock_t tx_lock; + + struct work_struct reset_task; + struct work_struct link_chg_task; + struct timer_list watchdog_timer; + struct timer_list phy_config_timer; + + unsigned long cfg_phy; + bool mac_disabled; + + /* All Descriptor memory */ + dma_addr_t ring_dma; + void *ring_vir_addr; + int ring_size; + + struct tx_pkt_header *txd_ring; + dma_addr_t txd_dma; + + struct tx_pkt_status *txs_ring; + dma_addr_t txs_dma; + + struct rx_desc *rxd_ring; + dma_addr_t rxd_dma; + + u32 txd_ring_size; /* bytes per unit */ + u32 txs_ring_size; /* dwords per unit */ + u32 rxd_ring_size; /* 1536 bytes per unit */ + + /* read /write ptr: */ + /* host */ + u32 txd_write_ptr; + u32 txs_next_clear; + u32 rxd_read_ptr; + + /* nic */ + atomic_t txd_read_ptr; + atomic_t txs_write_ptr; + u32 rxd_write_ptr; + + /* Interrupt Moderator timer ( 2us resolution) */ + u16 imt; + /* Interrupt Clear timer (2us resolution) */ + u16 ict; + + unsigned long flags; + /* structs defined in atl2_hw.h */ + u32 bd_number; /* board number */ + bool pci_using_64; + bool have_msi; + struct atl2_hw hw; + + u32 usr_cmd; + /* FIXME */ + /* u32 regs_buff[ATL2_REGS_LEN]; */ + u32 pci_state[16]; + + u32 *config_space; +}; + +enum atl2_state_t { + __ATL2_TESTING, + __ATL2_RESETTING, + __ATL2_DOWN +}; + +#endif /* _ATL2_H_ */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f1624b39675..90a132ab84a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2213,6 +2213,7 @@ #define PCI_VENDOR_ID_ATTANSIC 0x1969 #define PCI_DEVICE_ID_ATTANSIC_L1 0x1048 +#define PCI_DEVICE_ID_ATTANSIC_L2 0x2048 #define PCI_VENDOR_ID_JMICRON 0x197B #define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 -- GitLab From 01f2e4ead2c51226ed1283ef6a8388ca6f4cff8f Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 15 Sep 2008 09:17:11 -0700 Subject: [PATCH 1979/5416] enic: add Cisco 10G Ethernet NIC driver Signed-off-by: Scott Feldman Signed-off-by: Jeff Garzik --- MAINTAINERS | 7 + drivers/net/Kconfig | 7 + drivers/net/Makefile | 1 + drivers/net/enic/Makefile | 5 + drivers/net/enic/cq_desc.h | 79 ++ drivers/net/enic/cq_enet_desc.h | 169 +++ drivers/net/enic/enic.h | 115 ++ drivers/net/enic/enic_main.c | 1949 ++++++++++++++++++++++++++++++ drivers/net/enic/enic_res.c | 370 ++++++ drivers/net/enic/enic_res.h | 151 +++ drivers/net/enic/rq_enet_desc.h | 60 + drivers/net/enic/vnic_cq.c | 89 ++ drivers/net/enic/vnic_cq.h | 113 ++ drivers/net/enic/vnic_dev.c | 674 +++++++++++ drivers/net/enic/vnic_dev.h | 106 ++ drivers/net/enic/vnic_devcmd.h | 282 +++++ drivers/net/enic/vnic_enet.h | 47 + drivers/net/enic/vnic_intr.c | 62 + drivers/net/enic/vnic_intr.h | 92 ++ drivers/net/enic/vnic_nic.h | 65 + drivers/net/enic/vnic_resource.h | 63 + drivers/net/enic/vnic_rq.c | 199 +++ drivers/net/enic/vnic_rq.h | 204 ++++ drivers/net/enic/vnic_rss.h | 32 + drivers/net/enic/vnic_stats.h | 70 ++ drivers/net/enic/vnic_wq.c | 184 +++ drivers/net/enic/vnic_wq.h | 154 +++ drivers/net/enic/wq_enet_desc.h | 98 ++ include/linux/pci_ids.h | 2 + 29 files changed, 5449 insertions(+) create mode 100644 drivers/net/enic/Makefile create mode 100644 drivers/net/enic/cq_desc.h create mode 100644 drivers/net/enic/cq_enet_desc.h create mode 100644 drivers/net/enic/enic.h create mode 100644 drivers/net/enic/enic_main.c create mode 100644 drivers/net/enic/enic_res.c create mode 100644 drivers/net/enic/enic_res.h create mode 100644 drivers/net/enic/rq_enet_desc.h create mode 100644 drivers/net/enic/vnic_cq.c create mode 100644 drivers/net/enic/vnic_cq.h create mode 100644 drivers/net/enic/vnic_dev.c create mode 100644 drivers/net/enic/vnic_dev.h create mode 100644 drivers/net/enic/vnic_devcmd.h create mode 100644 drivers/net/enic/vnic_enet.h create mode 100644 drivers/net/enic/vnic_intr.c create mode 100644 drivers/net/enic/vnic_intr.h create mode 100644 drivers/net/enic/vnic_nic.h create mode 100644 drivers/net/enic/vnic_resource.h create mode 100644 drivers/net/enic/vnic_rq.c create mode 100644 drivers/net/enic/vnic_rq.h create mode 100644 drivers/net/enic/vnic_rss.h create mode 100644 drivers/net/enic/vnic_stats.h create mode 100644 drivers/net/enic/vnic_wq.c create mode 100644 drivers/net/enic/vnic_wq.h create mode 100644 drivers/net/enic/wq_enet_desc.h diff --git a/MAINTAINERS b/MAINTAINERS index b3e92fbe336..467f994b1fa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1046,6 +1046,13 @@ L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ S: Supported +CISCO 10G ETHERNET DRIVER +P: Scott Feldman +M: scofeldm@cisco.com +P: Joe Eykholt +M: jeykholt@cisco.com +S: Supported + CFAG12864B LCD DRIVER P: Miguel Ojeda Sandonis M: miguel.ojeda.sandonis@gmail.com diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 81a3e959c6c..5c012cd8fe3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2388,6 +2388,13 @@ config EHEA To compile the driver as a module, choose M here. The module will be called ehea. +config ENIC + tristate "E, the Cisco 10G Ethernet NIC" + depends on PCI && INET + select INET_LRO + help + This enables the support for the Cisco 10G Ethernet card. + config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI && INET diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9221346a515..d4ec6ba7f07 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_ATL2) += atlx/ obj-$(CONFIG_ATL1E) += atl1e/ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o +obj-$(CONFIG_ENIC) += enic/ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile new file mode 100644 index 00000000000..391c3bce5b7 --- /dev/null +++ b/drivers/net/enic/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_ENIC) := enic.o + +enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ + enic_res.o vnic_dev.o vnic_rq.o + diff --git a/drivers/net/enic/cq_desc.h b/drivers/net/enic/cq_desc.h new file mode 100644 index 00000000000..c036a8bfd04 --- /dev/null +++ b/drivers/net/enic/cq_desc.h @@ -0,0 +1,79 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _CQ_DESC_H_ +#define _CQ_DESC_H_ + +/* + * Completion queue descriptor types + */ +enum cq_desc_types { + CQ_DESC_TYPE_WQ_ENET = 0, + CQ_DESC_TYPE_DESC_COPY = 1, + CQ_DESC_TYPE_WQ_EXCH = 2, + CQ_DESC_TYPE_RQ_ENET = 3, + CQ_DESC_TYPE_RQ_FCP = 4, +}; + +/* Completion queue descriptor: 16B + * + * All completion queues have this basic layout. The + * type_specfic area is unique for each completion + * queue type. + */ +struct cq_desc { + __le16 completed_index; + __le16 q_number; + u8 type_specfic[11]; + u8 type_color; +}; + +#define CQ_DESC_TYPE_BITS 7 +#define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1) +#define CQ_DESC_COLOR_MASK 1 +#define CQ_DESC_Q_NUM_BITS 10 +#define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1) +#define CQ_DESC_COMP_NDX_BITS 12 +#define CQ_DESC_COMP_NDX_MASK ((1 << CQ_DESC_COMP_NDX_BITS) - 1) + +static inline void cq_desc_dec(const struct cq_desc *desc_arg, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index) +{ + const struct cq_desc *desc = desc_arg; + const u8 type_color = desc->type_color; + + *color = (type_color >> CQ_DESC_TYPE_BITS) & CQ_DESC_COLOR_MASK; + + /* + * Make sure color bit is read from desc *before* other fields + * are read from desc. Hardware guarantees color bit is last + * bit (byte) written. Adding the rmb() prevents the compiler + * and/or CPU from reordering the reads which would potentially + * result in reading stale values. + */ + + rmb(); + + *type = type_color & CQ_DESC_TYPE_MASK; + *q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK; + *completed_index = le16_to_cpu(desc->completed_index) & + CQ_DESC_COMP_NDX_MASK; +} + +#endif /* _CQ_DESC_H_ */ diff --git a/drivers/net/enic/cq_enet_desc.h b/drivers/net/enic/cq_enet_desc.h new file mode 100644 index 00000000000..03dce9ed612 --- /dev/null +++ b/drivers/net/enic/cq_enet_desc.h @@ -0,0 +1,169 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _CQ_ENET_DESC_H_ +#define _CQ_ENET_DESC_H_ + +#include "cq_desc.h" + +/* Ethernet completion queue descriptor: 16B */ +struct cq_enet_wq_desc { + __le16 completed_index; + __le16 q_number; + u8 reserved[11]; + u8 type_color; +}; + +static inline void cq_enet_wq_desc_dec(struct cq_enet_wq_desc *desc, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index) +{ + cq_desc_dec((struct cq_desc *)desc, type, + color, q_number, completed_index); +} + +/* Completion queue descriptor: Ethernet receive queue, 16B */ +struct cq_enet_rq_desc { + __le16 completed_index_flags; + __le16 q_number_rss_type_flags; + __le32 rss_hash; + __le16 bytes_written_flags; + __le16 vlan; + __le16 checksum_fcoe; + u8 flags; + u8 type_color; +}; + +#define CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT (0x1 << 12) +#define CQ_ENET_RQ_DESC_FLAGS_FCOE (0x1 << 13) +#define CQ_ENET_RQ_DESC_FLAGS_EOP (0x1 << 14) +#define CQ_ENET_RQ_DESC_FLAGS_SOP (0x1 << 15) + +#define CQ_ENET_RQ_DESC_RSS_TYPE_BITS 4 +#define CQ_ENET_RQ_DESC_RSS_TYPE_MASK \ + ((1 << CQ_ENET_RQ_DESC_RSS_TYPE_BITS) - 1) +#define CQ_ENET_RQ_DESC_RSS_TYPE_NONE 0 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 1 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 2 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 3 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 4 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX 5 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX 6 + +#define CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC (0x1 << 14) + +#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS 14 +#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK \ + ((1 << CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS) - 1) +#define CQ_ENET_RQ_DESC_FLAGS_TRUNCATED (0x1 << 14) +#define CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED (0x1 << 15) + +#define CQ_ENET_RQ_DESC_FCOE_SOF_BITS 4 +#define CQ_ENET_RQ_DESC_FCOE_SOF_MASK \ + ((1 << CQ_ENET_RQ_DESC_FCOE_SOF_BITS) - 1) +#define CQ_ENET_RQ_DESC_FCOE_EOF_BITS 8 +#define CQ_ENET_RQ_DESC_FCOE_EOF_MASK \ + ((1 << CQ_ENET_RQ_DESC_FCOE_EOF_BITS) - 1) +#define CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT 8 + +#define CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK (0x1 << 0) +#define CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK (0x1 << 0) +#define CQ_ENET_RQ_DESC_FLAGS_UDP (0x1 << 1) +#define CQ_ENET_RQ_DESC_FCOE_ENC_ERROR (0x1 << 1) +#define CQ_ENET_RQ_DESC_FLAGS_TCP (0x1 << 2) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK (0x1 << 3) +#define CQ_ENET_RQ_DESC_FLAGS_IPV6 (0x1 << 4) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4 (0x1 << 5) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT (0x1 << 6) +#define CQ_ENET_RQ_DESC_FLAGS_FCS_OK (0x1 << 7) + +static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index, + u8 *ingress_port, u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type, + u8 *csum_not_calc, u32 *rss_hash, u16 *bytes_written, u8 *packet_error, + u8 *vlan_stripped, u16 *vlan, u16 *checksum, u8 *fcoe_sof, + u8 *fcoe_fc_crc_ok, u8 *fcoe_enc_error, u8 *fcoe_eof, + u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok, + u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok) +{ + u16 completed_index_flags = le16_to_cpu(desc->completed_index_flags); + u16 q_number_rss_type_flags = + le16_to_cpu(desc->q_number_rss_type_flags); + u16 bytes_written_flags = le16_to_cpu(desc->bytes_written_flags); + + cq_desc_dec((struct cq_desc *)desc, type, + color, q_number, completed_index); + + *ingress_port = (completed_index_flags & + CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0; + *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ? + 1 : 0; + *eop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_EOP) ? + 1 : 0; + *sop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_SOP) ? + 1 : 0; + + *rss_type = (u8)((q_number_rss_type_flags >> CQ_DESC_Q_NUM_BITS) & + CQ_ENET_RQ_DESC_RSS_TYPE_MASK); + *csum_not_calc = (q_number_rss_type_flags & + CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ? 1 : 0; + + *rss_hash = le32_to_cpu(desc->rss_hash); + + *bytes_written = bytes_written_flags & + CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; + *packet_error = (bytes_written_flags & + CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ? 1 : 0; + *vlan_stripped = (bytes_written_flags & + CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) ? 1 : 0; + + *vlan = le16_to_cpu(desc->vlan); + + if (*fcoe) { + *fcoe_sof = (u8)(le16_to_cpu(desc->checksum_fcoe) & + CQ_ENET_RQ_DESC_FCOE_SOF_MASK); + *fcoe_fc_crc_ok = (desc->flags & + CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK) ? 1 : 0; + *fcoe_enc_error = (desc->flags & + CQ_ENET_RQ_DESC_FCOE_ENC_ERROR) ? 1 : 0; + *fcoe_eof = (u8)((desc->checksum_fcoe >> + CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT) & + CQ_ENET_RQ_DESC_FCOE_EOF_MASK); + *checksum = 0; + } else { + *fcoe_sof = 0; + *fcoe_fc_crc_ok = 0; + *fcoe_enc_error = 0; + *fcoe_eof = 0; + *checksum = le16_to_cpu(desc->checksum_fcoe); + } + + *tcp_udp_csum_ok = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ? 1 : 0; + *udp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_UDP) ? 1 : 0; + *tcp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP) ? 1 : 0; + *ipv4_csum_ok = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ? 1 : 0; + *ipv6 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV6) ? 1 : 0; + *ipv4 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4) ? 1 : 0; + *ipv4_fragment = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT) ? 1 : 0; + *fcs_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ? 1 : 0; +} + +#endif /* _CQ_ENET_DESC_H_ */ diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h new file mode 100644 index 00000000000..fb83c926da5 --- /dev/null +++ b/drivers/net/enic/enic.h @@ -0,0 +1,115 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _ENIC_H_ +#define _ENIC_H_ + +#include + +#include "vnic_enet.h" +#include "vnic_dev.h" +#include "vnic_wq.h" +#include "vnic_rq.h" +#include "vnic_cq.h" +#include "vnic_intr.h" +#include "vnic_stats.h" +#include "vnic_rss.h" + +#define DRV_NAME "enic" +#define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" +#define DRV_VERSION "0.0.1.18163.472" +#define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" +#define PFX DRV_NAME ": " + +#define ENIC_LRO_MAX_DESC 8 +#define ENIC_LRO_MAX_AGGR 64 + +enum enic_cq_index { + ENIC_CQ_RQ, + ENIC_CQ_WQ, + ENIC_CQ_MAX, +}; + +enum enic_intx_intr_index { + ENIC_INTX_WQ_RQ, + ENIC_INTX_ERR, + ENIC_INTX_NOTIFY, + ENIC_INTX_MAX, +}; + +enum enic_msix_intr_index { + ENIC_MSIX_RQ, + ENIC_MSIX_WQ, + ENIC_MSIX_ERR, + ENIC_MSIX_NOTIFY, + ENIC_MSIX_MAX, +}; + +struct enic_msix_entry { + int requested; + char devname[IFNAMSIZ]; + irqreturn_t (*isr)(int, void *); + void *devid; +}; + +/* Per-instance private data structure */ +struct enic { + struct net_device *netdev; + struct pci_dev *pdev; + struct vnic_enet_config config; + struct vnic_dev_bar bar0; + struct vnic_dev *vdev; + struct net_device_stats net_stats; + struct timer_list notify_timer; + struct work_struct reset; + struct msix_entry msix_entry[ENIC_MSIX_MAX]; + struct enic_msix_entry msix[ENIC_MSIX_MAX]; + u32 msg_enable; + spinlock_t devcmd_lock; + u8 mac_addr[ETH_ALEN]; + u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; + unsigned int mc_count; + int csum_rx_enabled; + u32 port_mtu; + + /* work queue cache line section */ + ____cacheline_aligned struct vnic_wq wq[1]; + spinlock_t wq_lock[1]; + unsigned int wq_count; + struct vlan_group *vlan_group; + + /* receive queue cache line section */ + ____cacheline_aligned struct vnic_rq rq[1]; + unsigned int rq_count; + int (*rq_alloc_buf)(struct vnic_rq *rq); + struct napi_struct napi; + struct net_lro_mgr lro_mgr; + struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC]; + + /* interrupt resource cache line section */ + ____cacheline_aligned struct vnic_intr intr[ENIC_MSIX_MAX]; + unsigned int intr_count; + u32 __iomem *legacy_pba; /* memory-mapped */ + + /* completion queue cache line section */ + ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX]; + unsigned int cq_count; +}; + +#endif /* _ENIC_H_ */ diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c new file mode 100644 index 00000000000..4cf5ec76c99 --- /dev/null +++ b/drivers/net/enic/enic_main.c @@ -0,0 +1,1949 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cq_enet_desc.h" +#include "vnic_dev.h" +#include "vnic_intr.h" +#include "vnic_stats.h" +#include "enic_res.h" +#include "enic.h" + +#define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ) +#define ENIC_JUMBO_FIRST_BUF_SIZE 256 + +/* Supported devices */ +static struct pci_device_id enic_id_table[] = { + { PCI_VDEVICE(CISCO, 0x0043) }, + { 0, } /* end of table */ +}; + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR("Scott Feldman "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_DEVICE_TABLE(pci, enic_id_table); + +struct enic_stat { + char name[ETH_GSTRING_LEN]; + unsigned int offset; +}; + +#define ENIC_TX_STAT(stat) \ + { .name = #stat, .offset = offsetof(struct vnic_tx_stats, stat) / 8 } +#define ENIC_RX_STAT(stat) \ + { .name = #stat, .offset = offsetof(struct vnic_rx_stats, stat) / 8 } + +static const struct enic_stat enic_tx_stats[] = { + ENIC_TX_STAT(tx_frames_ok), + ENIC_TX_STAT(tx_unicast_frames_ok), + ENIC_TX_STAT(tx_multicast_frames_ok), + ENIC_TX_STAT(tx_broadcast_frames_ok), + ENIC_TX_STAT(tx_bytes_ok), + ENIC_TX_STAT(tx_unicast_bytes_ok), + ENIC_TX_STAT(tx_multicast_bytes_ok), + ENIC_TX_STAT(tx_broadcast_bytes_ok), + ENIC_TX_STAT(tx_drops), + ENIC_TX_STAT(tx_errors), + ENIC_TX_STAT(tx_tso), +}; + +static const struct enic_stat enic_rx_stats[] = { + ENIC_RX_STAT(rx_frames_ok), + ENIC_RX_STAT(rx_frames_total), + ENIC_RX_STAT(rx_unicast_frames_ok), + ENIC_RX_STAT(rx_multicast_frames_ok), + ENIC_RX_STAT(rx_broadcast_frames_ok), + ENIC_RX_STAT(rx_bytes_ok), + ENIC_RX_STAT(rx_unicast_bytes_ok), + ENIC_RX_STAT(rx_multicast_bytes_ok), + ENIC_RX_STAT(rx_broadcast_bytes_ok), + ENIC_RX_STAT(rx_drop), + ENIC_RX_STAT(rx_no_bufs), + ENIC_RX_STAT(rx_errors), + ENIC_RX_STAT(rx_rss), + ENIC_RX_STAT(rx_crc_errors), + ENIC_RX_STAT(rx_frames_64), + ENIC_RX_STAT(rx_frames_127), + ENIC_RX_STAT(rx_frames_255), + ENIC_RX_STAT(rx_frames_511), + ENIC_RX_STAT(rx_frames_1023), + ENIC_RX_STAT(rx_frames_1518), + ENIC_RX_STAT(rx_frames_to_max), +}; + +static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); +static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); + +static int enic_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct enic *enic = netdev_priv(netdev); + + ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); + ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_EXTERNAL; + + if (netif_carrier_ok(netdev)) { + ecmd->speed = vnic_dev_port_speed(enic->vdev); + ecmd->duplex = DUPLEX_FULL; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; + } + + ecmd->autoneg = AUTONEG_DISABLE; + + return 0; +} + +static void enic_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct enic *enic = netdev_priv(netdev); + struct vnic_devcmd_fw_info *fw_info; + + spin_lock(&enic->devcmd_lock); + vnic_dev_fw_info(enic->vdev, &fw_info); + spin_unlock(&enic->devcmd_lock); + + strncpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); + strncpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); + strncpy(drvinfo->fw_version, fw_info->fw_version, + sizeof(drvinfo->fw_version)); + strncpy(drvinfo->bus_info, pci_name(enic->pdev), + sizeof(drvinfo->bus_info)); +} + +static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data) +{ + unsigned int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < enic_n_tx_stats; i++) { + memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + for (i = 0; i < enic_n_rx_stats; i++) { + memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + break; + } +} + +static int enic_get_stats_count(struct net_device *netdev) +{ + return enic_n_tx_stats + enic_n_rx_stats; +} + +static void enic_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct enic *enic = netdev_priv(netdev); + struct vnic_stats *vstats; + unsigned int i; + + spin_lock(&enic->devcmd_lock); + vnic_dev_stats_dump(enic->vdev, &vstats); + spin_unlock(&enic->devcmd_lock); + + for (i = 0; i < enic_n_tx_stats; i++) + *(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].offset]; + for (i = 0; i < enic_n_rx_stats; i++) + *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset]; +} + +static u32 enic_get_rx_csum(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + return enic->csum_rx_enabled; +} + +static int enic_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct enic *enic = netdev_priv(netdev); + + enic->csum_rx_enabled = + (data && ENIC_SETTING(enic, RXCSUM)) ? 1 : 0; + + return 0; +} + +static int enic_set_tx_csum(struct net_device *netdev, u32 data) +{ + struct enic *enic = netdev_priv(netdev); + + if (data && ENIC_SETTING(enic, TXCSUM)) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + + return 0; +} + +static int enic_set_tso(struct net_device *netdev, u32 data) +{ + struct enic *enic = netdev_priv(netdev); + + if (data && ENIC_SETTING(enic, TSO)) + netdev->features |= + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN; + else + netdev->features &= + ~(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN); + + return 0; +} + +static u32 enic_get_msglevel(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + return enic->msg_enable; +} + +static void enic_set_msglevel(struct net_device *netdev, u32 value) +{ + struct enic *enic = netdev_priv(netdev); + enic->msg_enable = value; +} + +static struct ethtool_ops enic_ethtool_ops = { + .get_settings = enic_get_settings, + .get_drvinfo = enic_get_drvinfo, + .get_msglevel = enic_get_msglevel, + .set_msglevel = enic_set_msglevel, + .get_link = ethtool_op_get_link, + .get_strings = enic_get_strings, + .get_stats_count = enic_get_stats_count, + .get_ethtool_stats = enic_get_ethtool_stats, + .get_rx_csum = enic_get_rx_csum, + .set_rx_csum = enic_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = enic_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = enic_set_tso, +}; + +static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) +{ + struct enic *enic = vnic_dev_priv(wq->vdev); + + if (buf->sop) + pci_unmap_single(enic->pdev, buf->dma_addr, + buf->len, PCI_DMA_TODEVICE); + else + pci_unmap_page(enic->pdev, buf->dma_addr, + buf->len, PCI_DMA_TODEVICE); + + if (buf->os_buf) + dev_kfree_skb_any(buf->os_buf); +} + +static void enic_wq_free_buf(struct vnic_wq *wq, + struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque) +{ + enic_free_wq_buf(wq, buf); +} + +static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, + u8 type, u16 q_number, u16 completed_index, void *opaque) +{ + struct enic *enic = vnic_dev_priv(vdev); + + spin_lock(&enic->wq_lock[q_number]); + + vnic_wq_service(&enic->wq[q_number], cq_desc, + completed_index, enic_wq_free_buf, + opaque); + + if (netif_queue_stopped(enic->netdev) && + vnic_wq_desc_avail(&enic->wq[q_number]) >= MAX_SKB_FRAGS + 1) + netif_wake_queue(enic->netdev); + + spin_unlock(&enic->wq_lock[q_number]); + + return 0; +} + +static void enic_log_q_error(struct enic *enic) +{ + unsigned int i; + u32 error_status; + + for (i = 0; i < enic->wq_count; i++) { + error_status = vnic_wq_error_status(&enic->wq[i]); + if (error_status) + printk(KERN_ERR PFX "%s: WQ[%d] error_status %d\n", + enic->netdev->name, i, error_status); + } + + for (i = 0; i < enic->rq_count; i++) { + error_status = vnic_rq_error_status(&enic->rq[i]); + if (error_status) + printk(KERN_ERR PFX "%s: RQ[%d] error_status %d\n", + enic->netdev->name, i, error_status); + } +} + +static void enic_link_check(struct enic *enic) +{ + int link_status = vnic_dev_link_status(enic->vdev); + int carrier_ok = netif_carrier_ok(enic->netdev); + + if (link_status && !carrier_ok) { + printk(KERN_INFO PFX "%s: Link UP\n", enic->netdev->name); + netif_carrier_on(enic->netdev); + } else if (!link_status && carrier_ok) { + printk(KERN_INFO PFX "%s: Link DOWN\n", enic->netdev->name); + netif_carrier_off(enic->netdev); + } +} + +static void enic_mtu_check(struct enic *enic) +{ + u32 mtu = vnic_dev_mtu(enic->vdev); + + if (mtu != enic->port_mtu) { + if (mtu < enic->netdev->mtu) + printk(KERN_WARNING PFX + "%s: interface MTU (%d) set higher " + "than switch port MTU (%d)\n", + enic->netdev->name, enic->netdev->mtu, mtu); + enic->port_mtu = mtu; + } +} + +static void enic_msglvl_check(struct enic *enic) +{ + u32 msg_enable = vnic_dev_msg_lvl(enic->vdev); + + if (msg_enable != enic->msg_enable) { + printk(KERN_INFO PFX "%s: msg lvl changed from 0x%x to 0x%x\n", + enic->netdev->name, enic->msg_enable, msg_enable); + enic->msg_enable = msg_enable; + } +} + +static void enic_notify_check(struct enic *enic) +{ + enic_msglvl_check(enic); + enic_mtu_check(enic); + enic_link_check(enic); +} + +#define ENIC_TEST_INTR(pba, i) (pba & (1 << i)) + +static irqreturn_t enic_isr_legacy(int irq, void *data) +{ + struct net_device *netdev = data; + struct enic *enic = netdev_priv(netdev); + u32 pba; + + vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]); + + pba = vnic_intr_legacy_pba(enic->legacy_pba); + if (!pba) { + vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); + return IRQ_NONE; /* not our interrupt */ + } + + if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) + enic_notify_check(enic); + + if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) { + enic_log_q_error(enic); + /* schedule recovery from WQ/RQ error */ + schedule_work(&enic->reset); + return IRQ_HANDLED; + } + + if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { + if (netif_rx_schedule_prep(netdev, &enic->napi)) + __netif_rx_schedule(netdev, &enic->napi); + } else { + vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); + } + + return IRQ_HANDLED; +} + +static irqreturn_t enic_isr_msi(int irq, void *data) +{ + struct enic *enic = data; + + /* With MSI, there is no sharing of interrupts, so this is + * our interrupt and there is no need to ack it. The device + * is not providing per-vector masking, so the OS will not + * write to PCI config space to mask/unmask the interrupt. + * We're using mask_on_assertion for MSI, so the device + * automatically masks the interrupt when the interrupt is + * generated. Later, when exiting polling, the interrupt + * will be unmasked (see enic_poll). + * + * Also, the device uses the same PCIe Traffic Class (TC) + * for Memory Write data and MSI, so there are no ordering + * issues; the MSI will always arrive at the Root Complex + * _after_ corresponding Memory Writes (i.e. descriptor + * writes). + */ + + netif_rx_schedule(enic->netdev, &enic->napi); + + return IRQ_HANDLED; +} + +static irqreturn_t enic_isr_msix_rq(int irq, void *data) +{ + struct enic *enic = data; + + /* schedule NAPI polling for RQ cleanup */ + netif_rx_schedule(enic->netdev, &enic->napi); + + return IRQ_HANDLED; +} + +static irqreturn_t enic_isr_msix_wq(int irq, void *data) +{ + struct enic *enic = data; + unsigned int wq_work_to_do = -1; /* no limit */ + unsigned int wq_work_done; + + wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], + wq_work_to_do, enic_wq_service, NULL); + + vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ], + wq_work_done, + 1 /* unmask intr */, + 1 /* reset intr timer */); + + return IRQ_HANDLED; +} + +static irqreturn_t enic_isr_msix_err(int irq, void *data) +{ + struct enic *enic = data; + + enic_log_q_error(enic); + + /* schedule recovery from WQ/RQ error */ + schedule_work(&enic->reset); + + return IRQ_HANDLED; +} + +static irqreturn_t enic_isr_msix_notify(int irq, void *data) +{ + struct enic *enic = data; + + enic_notify_check(enic); + vnic_intr_unmask(&enic->intr[ENIC_MSIX_NOTIFY]); + + return IRQ_HANDLED; +} + +static inline void enic_queue_wq_skb_cont(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb, + unsigned int len_left) +{ + skb_frag_t *frag; + + /* Queue additional data fragments */ + for (frag = skb_shinfo(skb)->frags; len_left; frag++) { + len_left -= frag->size; + enic_queue_wq_desc_cont(wq, skb, + pci_map_page(enic->pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE), + frag->size, + (len_left == 0)); /* EOP? */ + } +} + +static inline void enic_queue_wq_skb_vlan(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb, + int vlan_tag_insert, unsigned int vlan_tag) +{ + unsigned int head_len = skb_headlen(skb); + unsigned int len_left = skb->len - head_len; + int eop = (len_left == 0); + + /* Queue the main skb fragment */ + enic_queue_wq_desc(wq, skb, + pci_map_single(enic->pdev, skb->data, + head_len, PCI_DMA_TODEVICE), + head_len, + vlan_tag_insert, vlan_tag, + eop); + + if (!eop) + enic_queue_wq_skb_cont(enic, wq, skb, len_left); +} + +static inline void enic_queue_wq_skb_csum_l4(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb, + int vlan_tag_insert, unsigned int vlan_tag) +{ + unsigned int head_len = skb_headlen(skb); + unsigned int len_left = skb->len - head_len; + unsigned int hdr_len = skb_transport_offset(skb); + unsigned int csum_offset = hdr_len + skb->csum_offset; + int eop = (len_left == 0); + + /* Queue the main skb fragment */ + enic_queue_wq_desc_csum_l4(wq, skb, + pci_map_single(enic->pdev, skb->data, + head_len, PCI_DMA_TODEVICE), + head_len, + csum_offset, + hdr_len, + vlan_tag_insert, vlan_tag, + eop); + + if (!eop) + enic_queue_wq_skb_cont(enic, wq, skb, len_left); +} + +static inline void enic_queue_wq_skb_tso(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss, + int vlan_tag_insert, unsigned int vlan_tag) +{ + unsigned int head_len = skb_headlen(skb); + unsigned int len_left = skb->len - head_len; + unsigned int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + int eop = (len_left == 0); + + /* Preload TCP csum field with IP pseudo hdr calculated + * with IP length set to zero. HW will later add in length + * to each TCP segment resulting from the TSO. + */ + + if (skb->protocol == __constant_htons(ETH_P_IP)) { + ip_hdr(skb)->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); + } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) { + tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); + } + + /* Queue the main skb fragment */ + enic_queue_wq_desc_tso(wq, skb, + pci_map_single(enic->pdev, skb->data, + head_len, PCI_DMA_TODEVICE), + head_len, + mss, hdr_len, + vlan_tag_insert, vlan_tag, + eop); + + if (!eop) + enic_queue_wq_skb_cont(enic, wq, skb, len_left); +} + +static inline void enic_queue_wq_skb(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb) +{ + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int vlan_tag = 0; + int vlan_tag_insert = 0; + + if (enic->vlan_group && vlan_tx_tag_present(skb)) { + /* VLAN tag from trunking driver */ + vlan_tag_insert = 1; + vlan_tag = vlan_tx_tag_get(skb); + } + + if (mss) + enic_queue_wq_skb_tso(enic, wq, skb, mss, + vlan_tag_insert, vlan_tag); + else if (skb->ip_summed == CHECKSUM_PARTIAL) + enic_queue_wq_skb_csum_l4(enic, wq, skb, + vlan_tag_insert, vlan_tag); + else + enic_queue_wq_skb_vlan(enic, wq, skb, + vlan_tag_insert, vlan_tag); +} + +/* netif_tx_lock held, process context with BHs disabled */ +static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + struct vnic_wq *wq = &enic->wq[0]; + unsigned long flags; + + if (skb->len <= 0) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + /* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs, + * which is very likely. In the off chance it's going to take + * more than * ENIC_NON_TSO_MAX_DESC, linearize the skb. + */ + + if (skb_shinfo(skb)->gso_size == 0 && + skb_shinfo(skb)->nr_frags + 1 > ENIC_NON_TSO_MAX_DESC && + skb_linearize(skb)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + spin_lock_irqsave(&enic->wq_lock[0], flags); + + if (vnic_wq_desc_avail(wq) < skb_shinfo(skb)->nr_frags + 1) { + netif_stop_queue(netdev); + /* This is a hard error, log it */ + printk(KERN_ERR PFX "%s: BUG! Tx ring full when " + "queue awake!\n", netdev->name); + spin_unlock_irqrestore(&enic->wq_lock[0], flags); + return NETDEV_TX_BUSY; + } + + enic_queue_wq_skb(enic, wq, skb); + + if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + 1) + netif_stop_queue(netdev); + + netdev->trans_start = jiffies; + + spin_unlock_irqrestore(&enic->wq_lock[0], flags); + + return NETDEV_TX_OK; +} + +/* dev_base_lock rwlock held, nominally process context */ +static struct net_device_stats *enic_get_stats(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + struct vnic_stats *stats; + + spin_lock(&enic->devcmd_lock); + vnic_dev_stats_dump(enic->vdev, &stats); + spin_unlock(&enic->devcmd_lock); + + enic->net_stats.tx_packets = stats->tx.tx_frames_ok; + enic->net_stats.tx_bytes = stats->tx.tx_bytes_ok; + enic->net_stats.tx_errors = stats->tx.tx_errors; + enic->net_stats.tx_dropped = stats->tx.tx_drops; + + enic->net_stats.rx_packets = stats->rx.rx_frames_ok; + enic->net_stats.rx_bytes = stats->rx.rx_bytes_ok; + enic->net_stats.rx_errors = stats->rx.rx_errors; + enic->net_stats.multicast = stats->rx.rx_multicast_frames_ok; + enic->net_stats.rx_crc_errors = stats->rx.rx_crc_errors; + enic->net_stats.rx_dropped = stats->rx.rx_no_bufs; + + return &enic->net_stats; +} + +static void enic_reset_mcaddrs(struct enic *enic) +{ + enic->mc_count = 0; +} + +static int enic_set_mac_addr(struct net_device *netdev, char *addr) +{ + if (!is_valid_ether_addr(addr)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr, netdev->addr_len); + + return 0; +} + +/* netif_tx_lock held, BHs disabled */ +static void enic_set_multicast_list(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + struct dev_mc_list *list = netdev->mc_list; + int directed = 1; + int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; + int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; + int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; + int allmulti = (netdev->flags & IFF_ALLMULTI) || + (netdev->mc_count > ENIC_MULTICAST_PERFECT_FILTERS); + u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; + unsigned int mc_count = netdev->mc_count; + unsigned int i, j; + + if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) + mc_count = ENIC_MULTICAST_PERFECT_FILTERS; + + spin_lock(&enic->devcmd_lock); + + vnic_dev_packet_filter(enic->vdev, directed, + multicast, broadcast, promisc, allmulti); + + /* Is there an easier way? Trying to minimize to + * calls to add/del multicast addrs. We keep the + * addrs from the last call in enic->mc_addr and + * look for changes to add/del. + */ + + for (i = 0; list && i < mc_count; i++) { + memcpy(mc_addr[i], list->dmi_addr, ETH_ALEN); + list = list->next; + } + + for (i = 0; i < enic->mc_count; i++) { + for (j = 0; j < mc_count; j++) + if (compare_ether_addr(enic->mc_addr[i], + mc_addr[j]) == 0) + break; + if (j == mc_count) + enic_del_multicast_addr(enic, enic->mc_addr[i]); + } + + for (i = 0; i < mc_count; i++) { + for (j = 0; j < enic->mc_count; j++) + if (compare_ether_addr(mc_addr[i], + enic->mc_addr[j]) == 0) + break; + if (j == enic->mc_count) + enic_add_multicast_addr(enic, mc_addr[i]); + } + + /* Save the list to compare against next time + */ + + for (i = 0; i < mc_count; i++) + memcpy(enic->mc_addr[i], mc_addr[i], ETH_ALEN); + + enic->mc_count = mc_count; + + spin_unlock(&enic->devcmd_lock); +} + +/* rtnl lock is held */ +static void enic_vlan_rx_register(struct net_device *netdev, + struct vlan_group *vlan_group) +{ + struct enic *enic = netdev_priv(netdev); + enic->vlan_group = vlan_group; +} + +/* rtnl lock is held */ +static void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +{ + struct enic *enic = netdev_priv(netdev); + + spin_lock(&enic->devcmd_lock); + enic_add_vlan(enic, vid); + spin_unlock(&enic->devcmd_lock); +} + +/* rtnl lock is held */ +static void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct enic *enic = netdev_priv(netdev); + + spin_lock(&enic->devcmd_lock); + enic_del_vlan(enic, vid); + spin_unlock(&enic->devcmd_lock); +} + +/* netif_tx_lock held, BHs disabled */ +static void enic_tx_timeout(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + schedule_work(&enic->reset); +} + +static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf) +{ + struct enic *enic = vnic_dev_priv(rq->vdev); + + if (!buf->os_buf) + return; + + pci_unmap_single(enic->pdev, buf->dma_addr, + buf->len, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(buf->os_buf); +} + +static inline struct sk_buff *enic_rq_alloc_skb(unsigned int size) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb(size + NET_IP_ALIGN); + + if (skb) + skb_reserve(skb, NET_IP_ALIGN); + + return skb; +} + +static int enic_rq_alloc_buf(struct vnic_rq *rq) +{ + struct enic *enic = vnic_dev_priv(rq->vdev); + struct sk_buff *skb; + unsigned int len = enic->netdev->mtu + ETH_HLEN; + unsigned int os_buf_index = 0; + dma_addr_t dma_addr; + + skb = enic_rq_alloc_skb(len); + if (!skb) + return -ENOMEM; + + dma_addr = pci_map_single(enic->pdev, skb->data, + len, PCI_DMA_FROMDEVICE); + + enic_queue_rq_desc(rq, skb, os_buf_index, + dma_addr, len); + + return 0; +} + +static int enic_get_skb_header(struct sk_buff *skb, void **iphdr, + void **tcph, u64 *hdr_flags, void *priv) +{ + struct cq_enet_rq_desc *cq_desc = priv; + unsigned int ip_len; + struct iphdr *iph; + + u8 type, color, eop, sop, ingress_port, vlan_stripped; + u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof; + u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok; + u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc; + u8 packet_error; + u16 q_number, completed_index, bytes_written, vlan, checksum; + u32 rss_hash; + + cq_enet_rq_desc_dec(cq_desc, + &type, &color, &q_number, &completed_index, + &ingress_port, &fcoe, &eop, &sop, &rss_type, + &csum_not_calc, &rss_hash, &bytes_written, + &packet_error, &vlan_stripped, &vlan, &checksum, + &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error, + &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp, + &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment, + &fcs_ok); + + if (!(ipv4 && tcp && !ipv4_fragment)) + return -1; + + skb_reset_network_header(skb); + iph = ip_hdr(skb); + + ip_len = ip_hdrlen(skb); + skb_set_transport_header(skb, ip_len); + + /* check if ip header and tcp header are complete */ + if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb)) + return -1; + + *hdr_flags = LRO_IPV4 | LRO_TCP; + *tcph = tcp_hdr(skb); + *iphdr = iph; + + return 0; +} + +static void enic_rq_indicate_buf(struct vnic_rq *rq, + struct cq_desc *cq_desc, struct vnic_rq_buf *buf, + int skipped, void *opaque) +{ + struct enic *enic = vnic_dev_priv(rq->vdev); + struct sk_buff *skb; + + u8 type, color, eop, sop, ingress_port, vlan_stripped; + u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof; + u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok; + u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc; + u8 packet_error; + u16 q_number, completed_index, bytes_written, vlan, checksum; + u32 rss_hash; + + if (skipped) + return; + + skb = buf->os_buf; + prefetch(skb->data - NET_IP_ALIGN); + pci_unmap_single(enic->pdev, buf->dma_addr, + buf->len, PCI_DMA_FROMDEVICE); + + cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, + &type, &color, &q_number, &completed_index, + &ingress_port, &fcoe, &eop, &sop, &rss_type, + &csum_not_calc, &rss_hash, &bytes_written, + &packet_error, &vlan_stripped, &vlan, &checksum, + &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error, + &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp, + &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment, + &fcs_ok); + + if (packet_error) { + + if (bytes_written > 0 && !fcs_ok) { + if (net_ratelimit()) + printk(KERN_ERR PFX + "%s: packet error: bad FCS\n", + enic->netdev->name); + } + + dev_kfree_skb_any(skb); + + return; + } + + if (eop && bytes_written > 0) { + + /* Good receive + */ + + skb_put(skb, bytes_written); + skb->protocol = eth_type_trans(skb, enic->netdev); + + if (enic->csum_rx_enabled && !csum_not_calc) { + skb->csum = htons(checksum); + skb->ip_summed = CHECKSUM_COMPLETE; + } + + skb->dev = enic->netdev; + enic->netdev->last_rx = jiffies; + + if (enic->vlan_group && vlan_stripped) { + + if (ENIC_SETTING(enic, LRO)) + lro_vlan_hwaccel_receive_skb(&enic->lro_mgr, + skb, enic->vlan_group, + vlan, cq_desc); + else + vlan_hwaccel_receive_skb(skb, + enic->vlan_group, vlan); + + } else { + + if (ENIC_SETTING(enic, LRO)) + lro_receive_skb(&enic->lro_mgr, skb, cq_desc); + else + netif_receive_skb(skb); + + } + + } else { + + /* Buffer overflow + */ + + dev_kfree_skb_any(skb); + } +} + +static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, + u8 type, u16 q_number, u16 completed_index, void *opaque) +{ + struct enic *enic = vnic_dev_priv(vdev); + + vnic_rq_service(&enic->rq[q_number], cq_desc, + completed_index, VNIC_RQ_RETURN_DESC, + enic_rq_indicate_buf, opaque); + + return 0; +} + +static void enic_rq_drop_buf(struct vnic_rq *rq, + struct cq_desc *cq_desc, struct vnic_rq_buf *buf, + int skipped, void *opaque) +{ + struct enic *enic = vnic_dev_priv(rq->vdev); + struct sk_buff *skb = buf->os_buf; + + if (skipped) + return; + + pci_unmap_single(enic->pdev, buf->dma_addr, + buf->len, PCI_DMA_FROMDEVICE); + + dev_kfree_skb_any(skb); +} + +static int enic_rq_service_drop(struct vnic_dev *vdev, struct cq_desc *cq_desc, + u8 type, u16 q_number, u16 completed_index, void *opaque) +{ + struct enic *enic = vnic_dev_priv(vdev); + + vnic_rq_service(&enic->rq[q_number], cq_desc, + completed_index, VNIC_RQ_RETURN_DESC, + enic_rq_drop_buf, opaque); + + return 0; +} + +static int enic_poll(struct napi_struct *napi, int budget) +{ + struct enic *enic = container_of(napi, struct enic, napi); + struct net_device *netdev = enic->netdev; + unsigned int rq_work_to_do = budget; + unsigned int wq_work_to_do = -1; /* no limit */ + unsigned int work_done, rq_work_done, wq_work_done; + + /* Service RQ (first) and WQ + */ + + rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], + rq_work_to_do, enic_rq_service, NULL); + + wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], + wq_work_to_do, enic_wq_service, NULL); + + /* Accumulate intr event credits for this polling + * cycle. An intr event is the completion of a + * a WQ or RQ packet. + */ + + work_done = rq_work_done + wq_work_done; + + if (work_done > 0) + vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ], + work_done, + 0 /* don't unmask intr */, + 0 /* don't reset intr timer */); + + if (rq_work_done > 0) { + + /* Replenish RQ + */ + + vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); + + } else { + + /* If no work done, flush all LROs and exit polling + */ + + if (ENIC_SETTING(enic, LRO)) + lro_flush_all(&enic->lro_mgr); + + netif_rx_complete(netdev, napi); + vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); + } + + return rq_work_done; +} + +static int enic_poll_msix(struct napi_struct *napi, int budget) +{ + struct enic *enic = container_of(napi, struct enic, napi); + struct net_device *netdev = enic->netdev; + unsigned int work_to_do = budget; + unsigned int work_done; + + /* Service RQ + */ + + work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], + work_to_do, enic_rq_service, NULL); + + if (work_done > 0) { + + /* Replenish RQ + */ + + vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); + + /* Accumulate intr event credits for this polling + * cycle. An intr event is the completion of a + * a WQ or RQ packet. + */ + + vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], + work_done, + 0 /* don't unmask intr */, + 0 /* don't reset intr timer */); + } else { + + /* If no work done, flush all LROs and exit polling + */ + + if (ENIC_SETTING(enic, LRO)) + lro_flush_all(&enic->lro_mgr); + + netif_rx_complete(netdev, napi); + vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); + } + + return work_done; +} + +static void enic_notify_timer(unsigned long data) +{ + struct enic *enic = (struct enic *)data; + + enic_notify_check(enic); + + mod_timer(&enic->notify_timer, round_jiffies(ENIC_NOTIFY_TIMER_PERIOD)); +} + +static void enic_free_intr(struct enic *enic) +{ + struct net_device *netdev = enic->netdev; + unsigned int i; + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + case VNIC_DEV_INTR_MODE_MSI: + free_irq(enic->pdev->irq, netdev); + break; + case VNIC_DEV_INTR_MODE_MSIX: + for (i = 0; i < ARRAY_SIZE(enic->msix); i++) + if (enic->msix[i].requested) + free_irq(enic->msix_entry[i].vector, + enic->msix[i].devid); + break; + default: + break; + } +} + +static int enic_request_intr(struct enic *enic) +{ + struct net_device *netdev = enic->netdev; + unsigned int i; + int err = 0; + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + + case VNIC_DEV_INTR_MODE_INTX: + + err = request_irq(enic->pdev->irq, enic_isr_legacy, + IRQF_SHARED, netdev->name, netdev); + break; + + case VNIC_DEV_INTR_MODE_MSI: + + err = request_irq(enic->pdev->irq, enic_isr_msi, + 0, netdev->name, enic); + break; + + case VNIC_DEV_INTR_MODE_MSIX: + + sprintf(enic->msix[ENIC_MSIX_RQ].devname, + "%.11s-rx", netdev->name); + enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq; + enic->msix[ENIC_MSIX_RQ].devid = enic; + + sprintf(enic->msix[ENIC_MSIX_WQ].devname, + "%.11s-tx", netdev->name); + enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq; + enic->msix[ENIC_MSIX_WQ].devid = enic; + + sprintf(enic->msix[ENIC_MSIX_ERR].devname, + "%.11s-err", netdev->name); + enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err; + enic->msix[ENIC_MSIX_ERR].devid = enic; + + sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname, + "%.11s-notify", netdev->name); + enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify; + enic->msix[ENIC_MSIX_NOTIFY].devid = enic; + + for (i = 0; i < ARRAY_SIZE(enic->msix); i++) { + err = request_irq(enic->msix_entry[i].vector, + enic->msix[i].isr, 0, + enic->msix[i].devname, + enic->msix[i].devid); + if (err) { + enic_free_intr(enic); + break; + } + enic->msix[i].requested = 1; + } + + break; + + default: + break; + } + + return err; +} + +static int enic_notify_set(struct enic *enic) +{ + int err; + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY); + break; + case VNIC_DEV_INTR_MODE_MSIX: + err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY); + break; + default: + err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */); + break; + } + + return err; +} + +static void enic_notify_timer_start(struct enic *enic) +{ + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_MSI: + mod_timer(&enic->notify_timer, jiffies); + break; + default: + /* Using intr for notification for INTx/MSI-X */ + break; + }; +} + +/* rtnl lock is held, process context */ +static int enic_open(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + unsigned int i; + int err; + + for (i = 0; i < enic->rq_count; i++) { + err = vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf); + if (err) { + printk(KERN_ERR PFX + "%s: Unable to alloc receive buffers.\n", + netdev->name); + return err; + } + } + + for (i = 0; i < enic->wq_count; i++) + vnic_wq_enable(&enic->wq[i]); + for (i = 0; i < enic->rq_count; i++) + vnic_rq_enable(&enic->rq[i]); + + enic_add_station_addr(enic); + enic_set_multicast_list(netdev); + + netif_wake_queue(netdev); + napi_enable(&enic->napi); + vnic_dev_enable(enic->vdev); + + for (i = 0; i < enic->intr_count; i++) + vnic_intr_unmask(&enic->intr[i]); + + enic_notify_timer_start(enic); + + return 0; +} + +/* rtnl lock is held, process context */ +static int enic_stop(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + unsigned int i; + int err; + + del_timer_sync(&enic->notify_timer); + + vnic_dev_disable(enic->vdev); + napi_disable(&enic->napi); + netif_stop_queue(netdev); + + for (i = 0; i < enic->intr_count; i++) + vnic_intr_mask(&enic->intr[i]); + + for (i = 0; i < enic->wq_count; i++) { + err = vnic_wq_disable(&enic->wq[i]); + if (err) + return err; + } + for (i = 0; i < enic->rq_count; i++) { + err = vnic_rq_disable(&enic->rq[i]); + if (err) + return err; + } + + (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ], + -1, enic_rq_service_drop, NULL); + (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ], + -1, enic_wq_service, NULL); + + for (i = 0; i < enic->wq_count; i++) + vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); + for (i = 0; i < enic->rq_count; i++) + vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); + for (i = 0; i < enic->cq_count; i++) + vnic_cq_clean(&enic->cq[i]); + for (i = 0; i < enic->intr_count; i++) + vnic_intr_clean(&enic->intr[i]); + + return 0; +} + +static int enic_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct enic *enic = netdev_priv(netdev); + int running = netif_running(netdev); + + if (running) + enic_stop(netdev); + + if (new_mtu < ENIC_MIN_MTU) + new_mtu = ENIC_MIN_MTU; + if (new_mtu > ENIC_MAX_MTU) + new_mtu = ENIC_MAX_MTU; + + netdev->mtu = new_mtu; + + if (netdev->mtu > enic->port_mtu) + printk(KERN_WARNING PFX + "%s: interface MTU (%d) set higher " + "than port MTU (%d)\n", + netdev->name, netdev->mtu, enic->port_mtu); + + if (running) + enic_open(netdev); + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void enic_poll_controller(struct net_device *netdev) +{ + struct enic *enic = netdev_priv(netdev); + struct vnic_dev *vdev = enic->vdev; + + switch (vnic_dev_get_intr_mode(vdev)) { + case VNIC_DEV_INTR_MODE_MSIX: + enic_isr_msix_rq(enic->pdev->irq, enic); + enic_isr_msix_wq(enic->pdev->irq, enic); + break; + case VNIC_DEV_INTR_MODE_MSI: + enic_isr_msi(enic->pdev->irq, enic); + break; + case VNIC_DEV_INTR_MODE_INTX: + enic_isr_legacy(enic->pdev->irq, netdev); + break; + default: + break; + } +} +#endif + +static int enic_dev_wait(struct vnic_dev *vdev, + int (*start)(struct vnic_dev *, int), + int (*finished)(struct vnic_dev *, int *), + int arg) +{ + unsigned long time; + int done; + int err; + + BUG_ON(in_interrupt()); + + err = start(vdev, arg); + if (err) + return err; + + /* Wait for func to complete...2 seconds max + */ + + time = jiffies + (HZ * 2); + do { + + err = finished(vdev, &done); + if (err) + return err; + + if (done) + return 0; + + schedule_timeout_uninterruptible(HZ / 10); + + } while (time_after(time, jiffies)); + + return -ETIMEDOUT; +} + +static int enic_dev_open(struct enic *enic) +{ + int err; + + err = enic_dev_wait(enic->vdev, vnic_dev_open, + vnic_dev_open_done, 0); + if (err) + printk(KERN_ERR PFX + "vNIC device open failed, err %d.\n", err); + + return err; +} + +static int enic_dev_soft_reset(struct enic *enic) +{ + int err; + + err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset, + vnic_dev_soft_reset_done, 0); + if (err) + printk(KERN_ERR PFX + "vNIC soft reset failed, err %d.\n", err); + + return err; +} + +static void enic_reset(struct work_struct *work) +{ + struct enic *enic = container_of(work, struct enic, reset); + + if (!netif_running(enic->netdev)) + return; + + rtnl_lock(); + + spin_lock(&enic->devcmd_lock); + vnic_dev_hang_notify(enic->vdev); + spin_unlock(&enic->devcmd_lock); + + enic_stop(enic->netdev); + enic_dev_soft_reset(enic); + enic_reset_mcaddrs(enic); + enic_init_vnic_resources(enic); + enic_open(enic->netdev); + + rtnl_unlock(); +} + +static int enic_set_intr_mode(struct enic *enic) +{ + unsigned int n = ARRAY_SIZE(enic->rq); + unsigned int m = ARRAY_SIZE(enic->wq); + unsigned int i; + + /* Set interrupt mode (INTx, MSI, MSI-X) depending + * system capabilities. + * + * Try MSI-X first + * + * We need n RQs, m WQs, n+m CQs, and n+m+2 INTRs + * (the second to last INTR is used for WQ/RQ errors) + * (the last INTR is used for notifications) + */ + + BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2); + for (i = 0; i < n + m + 2; i++) + enic->msix_entry[i].entry = i; + + if (enic->config.intr_mode < 1 && + enic->rq_count >= n && + enic->wq_count >= m && + enic->cq_count >= n + m && + enic->intr_count >= n + m + 2 && + !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) { + + enic->rq_count = n; + enic->wq_count = m; + enic->cq_count = n + m; + enic->intr_count = n + m + 2; + + vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX); + + return 0; + } + + /* Next try MSI + * + * We need 1 RQ, 1 WQ, 2 CQs, and 1 INTR + */ + + if (enic->config.intr_mode < 2 && + enic->rq_count >= 1 && + enic->wq_count >= 1 && + enic->cq_count >= 2 && + enic->intr_count >= 1 && + !pci_enable_msi(enic->pdev)) { + + enic->rq_count = 1; + enic->wq_count = 1; + enic->cq_count = 2; + enic->intr_count = 1; + + vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSI); + + return 0; + } + + /* Next try INTx + * + * We need 1 RQ, 1 WQ, 2 CQs, and 3 INTRs + * (the first INTR is used for WQ/RQ) + * (the second INTR is used for WQ/RQ errors) + * (the last INTR is used for notifications) + */ + + if (enic->config.intr_mode < 3 && + enic->rq_count >= 1 && + enic->wq_count >= 1 && + enic->cq_count >= 2 && + enic->intr_count >= 3) { + + enic->rq_count = 1; + enic->wq_count = 1; + enic->cq_count = 2; + enic->intr_count = 3; + + vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_INTX); + + return 0; + } + + vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); + + return -EINVAL; +} + +static void enic_clear_intr_mode(struct enic *enic) +{ + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_MSIX: + pci_disable_msix(enic->pdev); + break; + case VNIC_DEV_INTR_MODE_MSI: + pci_disable_msi(enic->pdev); + break; + default: + break; + } + + vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); +} + +static void enic_iounmap(struct enic *enic) +{ + if (enic->bar0.vaddr) + iounmap(enic->bar0.vaddr); +} + +static int __devinit enic_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct enic *enic; + int using_dac = 0; + unsigned int i; + int err; + + const u8 rss_default_cpu = 0; + const u8 rss_hash_type = 0; + const u8 rss_hash_bits = 0; + const u8 rss_base_cpu = 0; + const u8 rss_enable = 0; + const u8 tso_ipid_split_en = 0; + const u8 ig_vlan_strip_en = 1; + + /* Allocate net device structure and initialize. Private + * instance data is initialized to zero. + */ + + netdev = alloc_etherdev(sizeof(struct enic)); + if (!netdev) { + printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + return -ENOMEM; + } + + /* Set the netdev name early so intr vectors are properly + * named and any error msgs can include netdev->name + */ + + rtnl_lock(); + err = dev_alloc_name(netdev, netdev->name); + rtnl_unlock(); + if (err < 0) { + printk(KERN_ERR PFX "Unable to allocate netdev name.\n"); + goto err_out_free_netdev; + } + + pci_set_drvdata(pdev, netdev); + + SET_NETDEV_DEV(netdev, &pdev->dev); + + enic = netdev_priv(netdev); + enic->netdev = netdev; + enic->pdev = pdev; + + /* Setup PCI resources + */ + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR PFX + "%s: Cannot enable PCI device, aborting.\n", + netdev->name); + goto err_out_free_netdev; + } + + err = pci_request_regions(pdev, DRV_NAME); + if (err) { + printk(KERN_ERR PFX + "%s: Cannot request PCI regions, aborting.\n", + netdev->name); + goto err_out_disable_device; + } + + pci_set_master(pdev); + + /* Query PCI controller on system for DMA addressing + * limitation for the device. Try 40-bit first, and + * fail to 32-bit. + */ + + err = pci_set_dma_mask(pdev, DMA_40BIT_MASK); + if (err) { + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + printk(KERN_ERR PFX + "%s: No usable DMA configuration, aborting.\n", + netdev->name); + goto err_out_release_regions; + } + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + printk(KERN_ERR PFX + "%s: Unable to obtain 32-bit DMA " + "for consistent allocations, aborting.\n", + netdev->name); + goto err_out_release_regions; + } + } else { + err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); + if (err) { + printk(KERN_ERR PFX + "%s: Unable to obtain 40-bit DMA " + "for consistent allocations, aborting.\n", + netdev->name); + goto err_out_release_regions; + } + using_dac = 1; + } + + /* Map vNIC resources from BAR0 + */ + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX + "%s: BAR0 not memory-map'able, aborting.\n", + netdev->name); + err = -ENODEV; + goto err_out_release_regions; + } + + enic->bar0.vaddr = pci_iomap(pdev, 0, enic->bar0.len); + enic->bar0.bus_addr = pci_resource_start(pdev, 0); + enic->bar0.len = pci_resource_len(pdev, 0); + + if (!enic->bar0.vaddr) { + printk(KERN_ERR PFX + "%s: Cannot memory-map BAR0 res hdr, aborting.\n", + netdev->name); + err = -ENODEV; + goto err_out_release_regions; + } + + /* Register vNIC device + */ + + enic->vdev = vnic_dev_register(NULL, enic, pdev, &enic->bar0); + if (!enic->vdev) { + printk(KERN_ERR PFX + "%s: vNIC registration failed, aborting.\n", + netdev->name); + err = -ENODEV; + goto err_out_iounmap; + } + + /* Issue device open to get device in known state + */ + + err = enic_dev_open(enic); + if (err) { + printk(KERN_ERR PFX + "%s: vNIC dev open failed, aborting.\n", + netdev->name); + goto err_out_vnic_unregister; + } + + /* Issue device init to initialize the vnic-to-switch link. + * We'll start with carrier off and wait for link UP + * notification later to turn on carrier. We don't need + * to wait here for the vnic-to-switch link initialization + * to complete; link UP notification is the indication that + * the process is complete. + */ + + netif_carrier_off(netdev); + + err = vnic_dev_init(enic->vdev, 0); + if (err) { + printk(KERN_ERR PFX + "%s: vNIC dev init failed, aborting.\n", + netdev->name); + goto err_out_dev_close; + } + + /* Get vNIC configuration + */ + + err = enic_get_vnic_config(enic); + if (err) { + printk(KERN_ERR PFX + "%s: Get vNIC configuration failed, aborting.\n", + netdev->name); + goto err_out_dev_close; + } + + /* Get available resource counts + */ + + enic_get_res_counts(enic); + + /* Set interrupt mode based on resource counts and system + * capabilities + */ + + err = enic_set_intr_mode(enic); + if (err) { + printk(KERN_ERR PFX + "%s: Failed to set intr mode, aborting.\n", + netdev->name); + goto err_out_dev_close; + } + + /* Request interrupt vector(s) + */ + + err = enic_request_intr(enic); + if (err) { + printk(KERN_ERR PFX "%s: Unable to request irq.\n", + netdev->name); + goto err_out_dev_close; + } + + /* Allocate and configure vNIC resources + */ + + err = enic_alloc_vnic_resources(enic); + if (err) { + printk(KERN_ERR PFX + "%s: Failed to alloc vNIC resources, aborting.\n", + netdev->name); + goto err_out_free_vnic_resources; + } + + enic_init_vnic_resources(enic); + + /* Enable VLAN tag stripping. RSS not enabled (yet). + */ + + err = enic_set_nic_cfg(enic, + rss_default_cpu, rss_hash_type, + rss_hash_bits, rss_base_cpu, + rss_enable, tso_ipid_split_en, + ig_vlan_strip_en); + if (err) { + printk(KERN_ERR PFX + "%s: Failed to config nic, aborting.\n", + netdev->name); + goto err_out_free_vnic_resources; + } + + /* Setup notification buffer area + */ + + err = enic_notify_set(enic); + if (err) { + printk(KERN_ERR PFX + "%s: Failed to alloc notify buffer, aborting.\n", + netdev->name); + goto err_out_free_vnic_resources; + } + + /* Setup notification timer, HW reset task, and locks + */ + + init_timer(&enic->notify_timer); + enic->notify_timer.function = enic_notify_timer; + enic->notify_timer.data = (unsigned long)enic; + + INIT_WORK(&enic->reset, enic_reset); + + for (i = 0; i < enic->wq_count; i++) + spin_lock_init(&enic->wq_lock[i]); + + spin_lock_init(&enic->devcmd_lock); + + /* Register net device + */ + + enic->port_mtu = enic->config.mtu; + (void)enic_change_mtu(netdev, enic->port_mtu); + + err = enic_set_mac_addr(netdev, enic->mac_addr); + if (err) { + printk(KERN_ERR PFX + "%s: Invalid MAC address, aborting.\n", + netdev->name); + goto err_out_notify_unset; + } + + netdev->open = enic_open; + netdev->stop = enic_stop; + netdev->hard_start_xmit = enic_hard_start_xmit; + netdev->get_stats = enic_get_stats; + netdev->set_multicast_list = enic_set_multicast_list; + netdev->change_mtu = enic_change_mtu; + netdev->vlan_rx_register = enic_vlan_rx_register; + netdev->vlan_rx_add_vid = enic_vlan_rx_add_vid; + netdev->vlan_rx_kill_vid = enic_vlan_rx_kill_vid; + netdev->tx_timeout = enic_tx_timeout; + netdev->watchdog_timeo = 2 * HZ; + netdev->ethtool_ops = &enic_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = enic_poll_controller; +#endif + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + default: + netif_napi_add(netdev, &enic->napi, enic_poll, 64); + break; + case VNIC_DEV_INTR_MODE_MSIX: + netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64); + break; + } + + netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + if (ENIC_SETTING(enic, TXCSUM)) + netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; + if (ENIC_SETTING(enic, TSO)) + netdev->features |= NETIF_F_TSO | + NETIF_F_TSO6 | NETIF_F_TSO_ECN; + if (using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + + enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); + + if (ENIC_SETTING(enic, LRO)) { + enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR; + enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC; + enic->lro_mgr.lro_arr = enic->lro_desc; + enic->lro_mgr.get_skb_header = enic_get_skb_header; + enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; + enic->lro_mgr.dev = netdev; + enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE; + enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; + } + + err = register_netdev(netdev); + if (err) { + printk(KERN_ERR PFX + "%s: Cannot register net device, aborting.\n", + netdev->name); + goto err_out_notify_unset; + } + + return 0; + +err_out_notify_unset: + vnic_dev_notify_unset(enic->vdev); +err_out_free_vnic_resources: + enic_free_vnic_resources(enic); + enic_free_intr(enic); +err_out_dev_close: + vnic_dev_close(enic->vdev); +err_out_vnic_unregister: + enic_clear_intr_mode(enic); + vnic_dev_unregister(enic->vdev); +err_out_iounmap: + enic_iounmap(enic); +err_out_release_regions: + pci_release_regions(pdev); +err_out_disable_device: + pci_disable_device(pdev); +err_out_free_netdev: + pci_set_drvdata(pdev, NULL); + free_netdev(netdev); + + return err; +} + +static void __devexit enic_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + if (netdev) { + struct enic *enic = netdev_priv(netdev); + + flush_scheduled_work(); + unregister_netdev(netdev); + vnic_dev_notify_unset(enic->vdev); + enic_free_vnic_resources(enic); + enic_free_intr(enic); + vnic_dev_close(enic->vdev); + enic_clear_intr_mode(enic); + vnic_dev_unregister(enic->vdev); + enic_iounmap(enic); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + free_netdev(netdev); + } +} + +static struct pci_driver enic_driver = { + .name = DRV_NAME, + .id_table = enic_id_table, + .probe = enic_probe, + .remove = __devexit_p(enic_remove), +}; + +static int __init enic_init_module(void) +{ + printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION); + + return pci_register_driver(&enic_driver); +} + +static void __exit enic_cleanup_module(void) +{ + pci_unregister_driver(&enic_driver); +} + +module_init(enic_init_module); +module_exit(enic_cleanup_module); diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c new file mode 100644 index 00000000000..95184b9108e --- /dev/null +++ b/drivers/net/enic/enic_res.c @@ -0,0 +1,370 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include + +#include "wq_enet_desc.h" +#include "rq_enet_desc.h" +#include "cq_enet_desc.h" +#include "vnic_resource.h" +#include "vnic_enet.h" +#include "vnic_dev.h" +#include "vnic_wq.h" +#include "vnic_rq.h" +#include "vnic_cq.h" +#include "vnic_intr.h" +#include "vnic_stats.h" +#include "vnic_nic.h" +#include "vnic_rss.h" +#include "enic_res.h" +#include "enic.h" + +int enic_get_vnic_config(struct enic *enic) +{ + struct vnic_enet_config *c = &enic->config; + int err; + + err = vnic_dev_mac_addr(enic->vdev, enic->mac_addr); + if (err) { + printk(KERN_ERR PFX "Error getting MAC addr, %d\n", err); + return err; + } + +#define GET_CONFIG(m) \ + do { \ + err = vnic_dev_spec(enic->vdev, \ + offsetof(struct vnic_enet_config, m), \ + sizeof(c->m), &c->m); \ + if (err) { \ + printk(KERN_ERR PFX \ + "Error getting %s, %d\n", #m, err); \ + return err; \ + } \ + } while (0) + + GET_CONFIG(flags); + GET_CONFIG(wq_desc_count); + GET_CONFIG(rq_desc_count); + GET_CONFIG(mtu); + GET_CONFIG(intr_timer); + GET_CONFIG(intr_timer_type); + GET_CONFIG(intr_mode); + + c->wq_desc_count = + min_t(u32, ENIC_MAX_WQ_DESCS, + max_t(u32, ENIC_MIN_WQ_DESCS, + c->wq_desc_count)); + c->wq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */ + + c->rq_desc_count = + min_t(u32, ENIC_MAX_RQ_DESCS, + max_t(u32, ENIC_MIN_RQ_DESCS, + c->rq_desc_count)); + c->rq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */ + + if (c->mtu == 0) + c->mtu = 1500; + c->mtu = min_t(u16, ENIC_MAX_MTU, + max_t(u16, ENIC_MIN_MTU, + c->mtu)); + + c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer); + + printk(KERN_INFO PFX "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x " + "wq/rq %d/%d\n", + enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2], + enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5], + c->wq_desc_count, c->rq_desc_count); + printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d " + "intr timer %d\n", + c->mtu, ENIC_SETTING(enic, TXCSUM), + ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO), + ENIC_SETTING(enic, LRO), c->intr_timer); + + return 0; +} + +void enic_add_station_addr(struct enic *enic) +{ + vnic_dev_add_addr(enic->vdev, enic->mac_addr); +} + +void enic_add_multicast_addr(struct enic *enic, u8 *addr) +{ + vnic_dev_add_addr(enic->vdev, addr); +} + +void enic_del_multicast_addr(struct enic *enic, u8 *addr) +{ + vnic_dev_del_addr(enic->vdev, addr); +} + +void enic_add_vlan(struct enic *enic, u16 vlanid) +{ + u64 a0 = vlanid, a1 = 0; + int wait = 1000; + int err; + + err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait); + if (err) + printk(KERN_ERR PFX "Can't add vlan id, %d\n", err); +} + +void enic_del_vlan(struct enic *enic, u16 vlanid) +{ + u64 a0 = vlanid, a1 = 0; + int wait = 1000; + int err; + + err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait); + if (err) + printk(KERN_ERR PFX "Can't delete vlan id, %d\n", err); +} + +int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, + u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, + u8 ig_vlan_strip_en) +{ + u64 a0, a1; + u32 nic_cfg; + int wait = 1000; + + vnic_set_nic_cfg(&nic_cfg, rss_default_cpu, + rss_hash_type, rss_hash_bits, rss_base_cpu, + rss_enable, tso_ipid_split_en, ig_vlan_strip_en); + + a0 = nic_cfg; + a1 = 0; + + return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait); +} + +void enic_free_vnic_resources(struct enic *enic) +{ + unsigned int i; + + for (i = 0; i < enic->wq_count; i++) + vnic_wq_free(&enic->wq[i]); + for (i = 0; i < enic->rq_count; i++) + vnic_rq_free(&enic->rq[i]); + for (i = 0; i < enic->cq_count; i++) + vnic_cq_free(&enic->cq[i]); + for (i = 0; i < enic->intr_count; i++) + vnic_intr_free(&enic->intr[i]); +} + +void enic_get_res_counts(struct enic *enic) +{ + enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); + enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); + enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); + enic->intr_count = vnic_dev_get_res_count(enic->vdev, + RES_TYPE_INTR_CTRL); + + printk(KERN_INFO PFX "vNIC resources avail: " + "wq %d rq %d cq %d intr %d\n", + enic->wq_count, enic->rq_count, + enic->cq_count, enic->intr_count); +} + +void enic_init_vnic_resources(struct enic *enic) +{ + enum vnic_dev_intr_mode intr_mode; + unsigned int mask_on_assertion; + unsigned int interrupt_offset; + unsigned int error_interrupt_enable; + unsigned int error_interrupt_offset; + unsigned int cq_index; + unsigned int i; + + intr_mode = vnic_dev_get_intr_mode(enic->vdev); + + /* Init RQ/WQ resources. + * + * RQ[0 - n-1] point to CQ[0 - n-1] + * WQ[0 - m-1] point to CQ[n - n+m-1] + * + * Error interrupt is not enabled for MSI. + */ + + switch (intr_mode) { + case VNIC_DEV_INTR_MODE_INTX: + case VNIC_DEV_INTR_MODE_MSIX: + error_interrupt_enable = 1; + error_interrupt_offset = enic->intr_count - 2; + break; + default: + error_interrupt_enable = 0; + error_interrupt_offset = 0; + break; + } + + for (i = 0; i < enic->rq_count; i++) { + cq_index = i; + vnic_rq_init(&enic->rq[i], + cq_index, + error_interrupt_enable, + error_interrupt_offset); + } + + for (i = 0; i < enic->wq_count; i++) { + cq_index = enic->rq_count + i; + vnic_wq_init(&enic->wq[i], + cq_index, + error_interrupt_enable, + error_interrupt_offset); + } + + /* Init CQ resources + * + * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI + * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X + */ + + for (i = 0; i < enic->cq_count; i++) { + + switch (intr_mode) { + case VNIC_DEV_INTR_MODE_MSIX: + interrupt_offset = i; + break; + default: + interrupt_offset = 0; + break; + } + + vnic_cq_init(&enic->cq[i], + 0 /* flow_control_enable */, + 1 /* color_enable */, + 0 /* cq_head */, + 0 /* cq_tail */, + 1 /* cq_tail_color */, + 1 /* interrupt_enable */, + 1 /* cq_entry_enable */, + 0 /* cq_message_enable */, + interrupt_offset, + 0 /* cq_message_addr */); + } + + /* Init INTR resources + * + * mask_on_assertion is not used for INTx due to the level- + * triggered nature of INTx + */ + + switch (intr_mode) { + case VNIC_DEV_INTR_MODE_MSI: + case VNIC_DEV_INTR_MODE_MSIX: + mask_on_assertion = 1; + break; + default: + mask_on_assertion = 0; + break; + } + + for (i = 0; i < enic->intr_count; i++) { + vnic_intr_init(&enic->intr[i], + enic->config.intr_timer, + enic->config.intr_timer_type, + mask_on_assertion); + } + + /* Clear LIF stats + */ + + vnic_dev_stats_clear(enic->vdev); +} + +int enic_alloc_vnic_resources(struct enic *enic) +{ + enum vnic_dev_intr_mode intr_mode; + unsigned int i; + int err; + + intr_mode = vnic_dev_get_intr_mode(enic->vdev); + + printk(KERN_INFO PFX "vNIC resources used: " + "wq %d rq %d cq %d intr %d intr mode %s\n", + enic->wq_count, enic->rq_count, + enic->cq_count, enic->intr_count, + intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" : + intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" : + intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" : + "unknown" + ); + + /* Allocate queue resources + */ + + for (i = 0; i < enic->wq_count; i++) { + err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i, + enic->config.wq_desc_count, + sizeof(struct wq_enet_desc)); + if (err) + goto err_out_cleanup; + } + + for (i = 0; i < enic->rq_count; i++) { + err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i, + enic->config.rq_desc_count, + sizeof(struct rq_enet_desc)); + if (err) + goto err_out_cleanup; + } + + for (i = 0; i < enic->cq_count; i++) { + if (i < enic->rq_count) + err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i, + enic->config.rq_desc_count, + sizeof(struct cq_enet_rq_desc)); + else + err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i, + enic->config.wq_desc_count, + sizeof(struct cq_enet_wq_desc)); + if (err) + goto err_out_cleanup; + } + + for (i = 0; i < enic->intr_count; i++) { + err = vnic_intr_alloc(enic->vdev, &enic->intr[i], i); + if (err) + goto err_out_cleanup; + } + + /* Hook remaining resource + */ + + enic->legacy_pba = vnic_dev_get_res(enic->vdev, + RES_TYPE_INTR_PBA_LEGACY, 0); + if (!enic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) { + printk(KERN_ERR PFX "Failed to hook legacy pba resource\n"); + err = -ENODEV; + goto err_out_cleanup; + } + + return 0; + +err_out_cleanup: + enic_free_vnic_resources(enic); + + return err; +} diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h new file mode 100644 index 00000000000..68534a29b7a --- /dev/null +++ b/drivers/net/enic/enic_res.h @@ -0,0 +1,151 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _ENIC_RES_H_ +#define _ENIC_RES_H_ + +#include "wq_enet_desc.h" +#include "rq_enet_desc.h" +#include "vnic_wq.h" +#include "vnic_rq.h" + +#define ENIC_MIN_WQ_DESCS 64 +#define ENIC_MAX_WQ_DESCS 4096 +#define ENIC_MIN_RQ_DESCS 64 +#define ENIC_MAX_RQ_DESCS 4096 + +#define ENIC_MIN_MTU 576 /* minimum for IPv4 */ +#define ENIC_MAX_MTU 9000 + +#define ENIC_MULTICAST_PERFECT_FILTERS 32 + +#define ENIC_NON_TSO_MAX_DESC 16 + +#define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) + +static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, unsigned int len, + unsigned int mss_or_csum_offset, unsigned int hdr_len, + int vlan_tag_insert, unsigned int vlan_tag, + int offload_mode, int cq_entry, int sop, int eop) +{ + struct wq_enet_desc *desc = vnic_wq_next_desc(wq); + + wq_enet_desc_enc(desc, + (u64)dma_addr | VNIC_PADDR_TARGET, + (u16)len, + (u16)mss_or_csum_offset, + (u16)hdr_len, (u8)offload_mode, + (u8)eop, (u8)cq_entry, + 0, /* fcoe_encap */ + (u8)vlan_tag_insert, + (u16)vlan_tag, + 0 /* loopback */); + + wmb(); + + vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop); +} + +static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, unsigned int len, int eop) +{ + enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, + 0, 0, 0, 0, 0, + eop, 0 /* !SOP */, eop); +} + +static inline void enic_queue_wq_desc(struct vnic_wq *wq, void *os_buf, + dma_addr_t dma_addr, unsigned int len, int vlan_tag_insert, + unsigned int vlan_tag, int eop) +{ + enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, + 0, 0, vlan_tag_insert, vlan_tag, + WQ_ENET_OFFLOAD_MODE_CSUM, + eop, 1 /* SOP */, eop); +} + +static inline void enic_queue_wq_desc_csum(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, unsigned int len, + int ip_csum, int tcpudp_csum, int vlan_tag_insert, + unsigned int vlan_tag, int eop) +{ + enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, + (ip_csum ? 1 : 0) + (tcpudp_csum ? 2 : 0), + 0, vlan_tag_insert, vlan_tag, + WQ_ENET_OFFLOAD_MODE_CSUM, + eop, 1 /* SOP */, eop); +} + +static inline void enic_queue_wq_desc_csum_l4(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, unsigned int len, + unsigned int csum_offset, unsigned int hdr_len, + int vlan_tag_insert, unsigned int vlan_tag, int eop) +{ + enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, + csum_offset, hdr_len, vlan_tag_insert, vlan_tag, + WQ_ENET_OFFLOAD_MODE_CSUM_L4, + eop, 1 /* SOP */, eop); +} + +static inline void enic_queue_wq_desc_tso(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, unsigned int len, + unsigned int mss, unsigned int hdr_len, int vlan_tag_insert, + unsigned int vlan_tag, int eop) +{ + enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, + mss, hdr_len, vlan_tag_insert, vlan_tag, + WQ_ENET_OFFLOAD_MODE_TSO, + eop, 1 /* SOP */, eop); +} + +static inline void enic_queue_rq_desc(struct vnic_rq *rq, + void *os_buf, unsigned int os_buf_index, + dma_addr_t dma_addr, unsigned int len) +{ + struct rq_enet_desc *desc = vnic_rq_next_desc(rq); + u8 type = os_buf_index ? + RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP; + + rq_enet_desc_enc(desc, + (u64)dma_addr | VNIC_PADDR_TARGET, + type, (u16)len); + + wmb(); + + vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len); +} + +struct enic; + +int enic_get_vnic_config(struct enic *); +void enic_add_station_addr(struct enic *enic); +void enic_add_multicast_addr(struct enic *enic, u8 *addr); +void enic_del_multicast_addr(struct enic *enic, u8 *addr); +void enic_add_vlan(struct enic *enic, u16 vlanid); +void enic_del_vlan(struct enic *enic, u16 vlanid); +int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, + u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, + u8 ig_vlan_strip_en); +void enic_get_res_counts(struct enic *enic); +void enic_init_vnic_resources(struct enic *enic); +int enic_alloc_vnic_resources(struct enic *); +void enic_free_vnic_resources(struct enic *); + +#endif /* _ENIC_RES_H_ */ diff --git a/drivers/net/enic/rq_enet_desc.h b/drivers/net/enic/rq_enet_desc.h new file mode 100644 index 00000000000..a06e649010c --- /dev/null +++ b/drivers/net/enic/rq_enet_desc.h @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _RQ_ENET_DESC_H_ +#define _RQ_ENET_DESC_H_ + +/* Ethernet receive queue descriptor: 16B */ +struct rq_enet_desc { + __le64 address; + __le16 length_type; + u8 reserved[6]; +}; + +enum rq_enet_type_types { + RQ_ENET_TYPE_ONLY_SOP = 0, + RQ_ENET_TYPE_NOT_SOP = 1, + RQ_ENET_TYPE_RESV2 = 2, + RQ_ENET_TYPE_RESV3 = 3, +}; + +#define RQ_ENET_ADDR_BITS 64 +#define RQ_ENET_LEN_BITS 14 +#define RQ_ENET_LEN_MASK ((1 << RQ_ENET_LEN_BITS) - 1) +#define RQ_ENET_TYPE_BITS 2 +#define RQ_ENET_TYPE_MASK ((1 << RQ_ENET_TYPE_BITS) - 1) + +static inline void rq_enet_desc_enc(struct rq_enet_desc *desc, + u64 address, u8 type, u16 length) +{ + desc->address = cpu_to_le64(address); + desc->length_type = cpu_to_le16((length & RQ_ENET_LEN_MASK) | + ((type & RQ_ENET_TYPE_MASK) << RQ_ENET_LEN_BITS)); +} + +static inline void rq_enet_desc_dec(struct rq_enet_desc *desc, + u64 *address, u8 *type, u16 *length) +{ + *address = le64_to_cpu(desc->address); + *length = le16_to_cpu(desc->length_type) & RQ_ENET_LEN_MASK; + *type = (u8)((le16_to_cpu(desc->length_type) >> RQ_ENET_LEN_BITS) & + RQ_ENET_TYPE_MASK); +} + +#endif /* _RQ_ENET_DESC_H_ */ diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/enic/vnic_cq.c new file mode 100644 index 00000000000..020ae6c3f3d --- /dev/null +++ b/drivers/net/enic/vnic_cq.c @@ -0,0 +1,89 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include + +#include "vnic_dev.h" +#include "vnic_cq.h" + +void vnic_cq_free(struct vnic_cq *cq) +{ + vnic_dev_free_desc_ring(cq->vdev, &cq->ring); + + cq->ctrl = NULL; +} + +int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, + unsigned int desc_count, unsigned int desc_size) +{ + int err; + + cq->index = index; + cq->vdev = vdev; + + cq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_CQ, index); + if (!cq->ctrl) { + printk(KERN_ERR "Failed to hook CQ[%d] resource\n", index); + return -EINVAL; + } + + err = vnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size); + if (err) + return err; + + return 0; +} + +void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, + unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, + unsigned int cq_tail_color, unsigned int interrupt_enable, + unsigned int cq_entry_enable, unsigned int cq_message_enable, + unsigned int interrupt_offset, u64 cq_message_addr) +{ + u64 paddr; + + paddr = (u64)cq->ring.base_addr | VNIC_PADDR_TARGET; + writeq(paddr, &cq->ctrl->ring_base); + iowrite32(cq->ring.desc_count, &cq->ctrl->ring_size); + iowrite32(flow_control_enable, &cq->ctrl->flow_control_enable); + iowrite32(color_enable, &cq->ctrl->color_enable); + iowrite32(cq_head, &cq->ctrl->cq_head); + iowrite32(cq_tail, &cq->ctrl->cq_tail); + iowrite32(cq_tail_color, &cq->ctrl->cq_tail_color); + iowrite32(interrupt_enable, &cq->ctrl->interrupt_enable); + iowrite32(cq_entry_enable, &cq->ctrl->cq_entry_enable); + iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable); + iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset); + writeq(cq_message_addr, &cq->ctrl->cq_message_addr); +} + +void vnic_cq_clean(struct vnic_cq *cq) +{ + cq->to_clean = 0; + cq->last_color = 0; + + iowrite32(0, &cq->ctrl->cq_head); + iowrite32(0, &cq->ctrl->cq_tail); + iowrite32(1, &cq->ctrl->cq_tail_color); + + vnic_dev_clear_desc_ring(&cq->ring); +} diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/enic/vnic_cq.h new file mode 100644 index 00000000000..114763cbc2f --- /dev/null +++ b/drivers/net/enic/vnic_cq.h @@ -0,0 +1,113 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_CQ_H_ +#define _VNIC_CQ_H_ + +#include "cq_desc.h" +#include "vnic_dev.h" + +/* Completion queue control */ +struct vnic_cq_ctrl { + u64 ring_base; /* 0x00 */ + u32 ring_size; /* 0x08 */ + u32 pad0; + u32 flow_control_enable; /* 0x10 */ + u32 pad1; + u32 color_enable; /* 0x18 */ + u32 pad2; + u32 cq_head; /* 0x20 */ + u32 pad3; + u32 cq_tail; /* 0x28 */ + u32 pad4; + u32 cq_tail_color; /* 0x30 */ + u32 pad5; + u32 interrupt_enable; /* 0x38 */ + u32 pad6; + u32 cq_entry_enable; /* 0x40 */ + u32 pad7; + u32 cq_message_enable; /* 0x48 */ + u32 pad8; + u32 interrupt_offset; /* 0x50 */ + u32 pad9; + u64 cq_message_addr; /* 0x58 */ + u32 pad10; +}; + +struct vnic_cq { + unsigned int index; + struct vnic_dev *vdev; + struct vnic_cq_ctrl __iomem *ctrl; /* memory-mapped */ + struct vnic_dev_ring ring; + unsigned int to_clean; + unsigned int last_color; +}; + +static inline unsigned int vnic_cq_service(struct vnic_cq *cq, + unsigned int work_to_do, + int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc, + u8 type, u16 q_number, u16 completed_index, void *opaque), + void *opaque) +{ + struct cq_desc *cq_desc; + unsigned int work_done = 0; + u16 q_number, completed_index; + u8 type, color; + + cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + + cq->ring.desc_size * cq->to_clean); + cq_desc_dec(cq_desc, &type, &color, + &q_number, &completed_index); + + while (color != cq->last_color) { + + if ((*q_service)(cq->vdev, cq_desc, type, + q_number, completed_index, opaque)) + break; + + cq->to_clean++; + if (cq->to_clean == cq->ring.desc_count) { + cq->to_clean = 0; + cq->last_color = cq->last_color ? 0 : 1; + } + + cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + + cq->ring.desc_size * cq->to_clean); + cq_desc_dec(cq_desc, &type, &color, + &q_number, &completed_index); + + work_done++; + if (work_done >= work_to_do) + break; + } + + return work_done; +} + +void vnic_cq_free(struct vnic_cq *cq); +int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, + unsigned int desc_count, unsigned int desc_size); +void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, + unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, + unsigned int cq_tail_color, unsigned int interrupt_enable, + unsigned int cq_entry_enable, unsigned int message_enable, + unsigned int interrupt_offset, u64 message_addr); +void vnic_cq_clean(struct vnic_cq *cq); + +#endif /* _VNIC_CQ_H_ */ diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c new file mode 100644 index 00000000000..4d104f5c30f --- /dev/null +++ b/drivers/net/enic/vnic_dev.c @@ -0,0 +1,674 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "vnic_resource.h" +#include "vnic_devcmd.h" +#include "vnic_dev.h" +#include "vnic_stats.h" + +struct vnic_res { + void __iomem *vaddr; + unsigned int count; +}; + +struct vnic_dev { + void *priv; + struct pci_dev *pdev; + struct vnic_res res[RES_TYPE_MAX]; + enum vnic_dev_intr_mode intr_mode; + struct vnic_devcmd __iomem *devcmd; + struct vnic_devcmd_notify *notify; + struct vnic_devcmd_notify notify_copy; + dma_addr_t notify_pa; + u32 *linkstatus; + dma_addr_t linkstatus_pa; + struct vnic_stats *stats; + dma_addr_t stats_pa; + struct vnic_devcmd_fw_info *fw_info; + dma_addr_t fw_info_pa; +}; + +#define VNIC_MAX_RES_HDR_SIZE \ + (sizeof(struct vnic_resource_header) + \ + sizeof(struct vnic_resource) * RES_TYPE_MAX) +#define VNIC_RES_STRIDE 128 + +void *vnic_dev_priv(struct vnic_dev *vdev) +{ + return vdev->priv; +} + +static int vnic_dev_discover_res(struct vnic_dev *vdev, + struct vnic_dev_bar *bar) +{ + struct vnic_resource_header __iomem *rh; + struct vnic_resource __iomem *r; + u8 type; + + if (bar->len < VNIC_MAX_RES_HDR_SIZE) { + printk(KERN_ERR "vNIC BAR0 res hdr length error\n"); + return -EINVAL; + } + + rh = bar->vaddr; + if (!rh) { + printk(KERN_ERR "vNIC BAR0 res hdr not mem-mapped\n"); + return -EINVAL; + } + + if (ioread32(&rh->magic) != VNIC_RES_MAGIC || + ioread32(&rh->version) != VNIC_RES_VERSION) { + printk(KERN_ERR "vNIC BAR0 res magic/version error " + "exp (%lx/%lx) curr (%x/%x)\n", + VNIC_RES_MAGIC, VNIC_RES_VERSION, + ioread32(&rh->magic), ioread32(&rh->version)); + return -EINVAL; + } + + r = (struct vnic_resource __iomem *)(rh + 1); + + while ((type = ioread8(&r->type)) != RES_TYPE_EOL) { + + u8 bar_num = ioread8(&r->bar); + u32 bar_offset = ioread32(&r->bar_offset); + u32 count = ioread32(&r->count); + u32 len; + + r++; + + if (bar_num != 0) /* only mapping in BAR0 resources */ + continue; + + switch (type) { + case RES_TYPE_WQ: + case RES_TYPE_RQ: + case RES_TYPE_CQ: + case RES_TYPE_INTR_CTRL: + /* each count is stride bytes long */ + len = count * VNIC_RES_STRIDE; + if (len + bar_offset > bar->len) { + printk(KERN_ERR "vNIC BAR0 resource %d " + "out-of-bounds, offset 0x%x + " + "size 0x%x > bar len 0x%lx\n", + type, bar_offset, + len, + bar->len); + return -EINVAL; + } + break; + case RES_TYPE_INTR_PBA_LEGACY: + case RES_TYPE_DEVCMD: + len = count; + break; + default: + continue; + } + + vdev->res[type].count = count; + vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset; + } + + return 0; +} + +unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, + enum vnic_res_type type) +{ + return vdev->res[type].count; +} + +void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, + unsigned int index) +{ + if (!vdev->res[type].vaddr) + return NULL; + + switch (type) { + case RES_TYPE_WQ: + case RES_TYPE_RQ: + case RES_TYPE_CQ: + case RES_TYPE_INTR_CTRL: + return (char __iomem *)vdev->res[type].vaddr + + index * VNIC_RES_STRIDE; + default: + return (char __iomem *)vdev->res[type].vaddr; + } +} + +unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, + unsigned int desc_count, unsigned int desc_size) +{ + /* The base address of the desc rings must be 512 byte aligned. + * Descriptor count is aligned to groups of 32 descriptors. A + * count of 0 means the maximum 4096 descriptors. Descriptor + * size is aligned to 16 bytes. + */ + + unsigned int count_align = 32; + unsigned int desc_align = 16; + + ring->base_align = 512; + + if (desc_count == 0) + desc_count = 4096; + + ring->desc_count = ALIGN(desc_count, count_align); + + ring->desc_size = ALIGN(desc_size, desc_align); + + ring->size = ring->desc_count * ring->desc_size; + ring->size_unaligned = ring->size + ring->base_align; + + return ring->size_unaligned; +} + +void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring) +{ + memset(ring->descs, 0, ring->size); +} + +int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, + unsigned int desc_count, unsigned int desc_size) +{ + vnic_dev_desc_ring_size(ring, desc_count, desc_size); + + ring->descs_unaligned = pci_alloc_consistent(vdev->pdev, + ring->size_unaligned, + &ring->base_addr_unaligned); + + if (!ring->descs_unaligned) { + printk(KERN_ERR + "Failed to allocate ring (size=%d), aborting\n", + (int)ring->size); + return -ENOMEM; + } + + ring->base_addr = ALIGN(ring->base_addr_unaligned, + ring->base_align); + ring->descs = (u8 *)ring->descs_unaligned + + (ring->base_addr - ring->base_addr_unaligned); + + vnic_dev_clear_desc_ring(ring); + + ring->desc_avail = ring->desc_count - 1; + + return 0; +} + +void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring) +{ + if (ring->descs) { + pci_free_consistent(vdev->pdev, + ring->size_unaligned, + ring->descs_unaligned, + ring->base_addr_unaligned); + ring->descs = NULL; + } +} + +int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, + u64 *a0, u64 *a1, int wait) +{ + struct vnic_devcmd __iomem *devcmd = vdev->devcmd; + int delay; + u32 status; + int dev_cmd_err[] = { + /* convert from fw's version of error.h to host's version */ + 0, /* ERR_SUCCESS */ + EINVAL, /* ERR_EINVAL */ + EFAULT, /* ERR_EFAULT */ + EPERM, /* ERR_EPERM */ + EBUSY, /* ERR_EBUSY */ + }; + int err; + + status = ioread32(&devcmd->status); + if (status & STAT_BUSY) { + printk(KERN_ERR "Busy devcmd %d\n", _CMD_N(cmd)); + return -EBUSY; + } + + if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) { + writeq(*a0, &devcmd->args[0]); + writeq(*a1, &devcmd->args[1]); + wmb(); + } + + iowrite32(cmd, &devcmd->cmd); + + if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT)) + return 0; + + for (delay = 0; delay < wait; delay++) { + + udelay(100); + + status = ioread32(&devcmd->status); + if (!(status & STAT_BUSY)) { + + if (status & STAT_ERROR) { + err = dev_cmd_err[(int)readq(&devcmd->args[0])]; + printk(KERN_ERR "Error %d devcmd %d\n", + err, _CMD_N(cmd)); + return -err; + } + + if (_CMD_DIR(cmd) & _CMD_DIR_READ) { + rmb(); + *a0 = readq(&devcmd->args[0]); + *a1 = readq(&devcmd->args[1]); + } + + return 0; + } + } + + printk(KERN_ERR "Timedout devcmd %d\n", _CMD_N(cmd)); + return -ETIMEDOUT; +} + +int vnic_dev_fw_info(struct vnic_dev *vdev, + struct vnic_devcmd_fw_info **fw_info) +{ + u64 a0, a1 = 0; + int wait = 1000; + int err = 0; + + if (!vdev->fw_info) { + vdev->fw_info = pci_alloc_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_fw_info), + &vdev->fw_info_pa); + if (!vdev->fw_info) + return -ENOMEM; + + a0 = vdev->fw_info_pa; + + /* only get fw_info once and cache it */ + err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait); + } + + *fw_info = vdev->fw_info; + + return err; +} + +int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size, + void *value) +{ + u64 a0, a1; + int wait = 1000; + int err; + + a0 = offset; + a1 = size; + + err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait); + + switch (size) { + case 1: *(u8 *)value = (u8)a0; break; + case 2: *(u16 *)value = (u16)a0; break; + case 4: *(u32 *)value = (u32)a0; break; + case 8: *(u64 *)value = a0; break; + default: BUG(); break; + } + + return err; +} + +int vnic_dev_stats_clear(struct vnic_dev *vdev) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait); +} + +int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats) +{ + u64 a0, a1; + int wait = 1000; + + if (!vdev->stats) { + vdev->stats = pci_alloc_consistent(vdev->pdev, + sizeof(struct vnic_stats), &vdev->stats_pa); + if (!vdev->stats) + return -ENOMEM; + } + + *stats = vdev->stats; + a0 = vdev->stats_pa; + a1 = sizeof(struct vnic_stats); + + return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait); +} + +int vnic_dev_close(struct vnic_dev *vdev) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait); +} + +int vnic_dev_enable(struct vnic_dev *vdev) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); +} + +int vnic_dev_disable(struct vnic_dev *vdev) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait); +} + +int vnic_dev_open(struct vnic_dev *vdev, int arg) +{ + u64 a0 = (u32)arg, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait); +} + +int vnic_dev_open_done(struct vnic_dev *vdev, int *done) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + int err; + + *done = 0; + + err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait); + if (err) + return err; + + *done = (a0 == 0); + + return 0; +} + +int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) +{ + u64 a0 = (u32)arg, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait); +} + +int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + int err; + + *done = 0; + + err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait); + if (err) + return err; + + *done = (a0 == 0); + + return 0; +} + +int vnic_dev_hang_notify(struct vnic_dev *vdev) +{ + u64 a0, a1; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait); +} + +int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) +{ + u64 a0, a1; + int wait = 1000; + int err, i; + + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = 0; + + err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); + if (err) + return err; + + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = ((u8 *)&a0)[i]; + + return 0; +} + +void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, + int broadcast, int promisc, int allmulti) +{ + u64 a0, a1 = 0; + int wait = 1000; + int err; + + a0 = (directed ? CMD_PFILTER_DIRECTED : 0) | + (multicast ? CMD_PFILTER_MULTICAST : 0) | + (broadcast ? CMD_PFILTER_BROADCAST : 0) | + (promisc ? CMD_PFILTER_PROMISCUOUS : 0) | + (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0); + + err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait); + if (err) + printk(KERN_ERR "Can't set packet filter\n"); +} + +void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + int err; + int i; + + for (i = 0; i < ETH_ALEN; i++) + ((u8 *)&a0)[i] = addr[i]; + + err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); + if (err) + printk(KERN_ERR + "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], + err); +} + +void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) +{ + u64 a0 = 0, a1 = 0; + int wait = 1000; + int err; + int i; + + for (i = 0; i < ETH_ALEN; i++) + ((u8 *)&a0)[i] = addr[i]; + + err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); + if (err) + printk(KERN_ERR + "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], + err); +} + +int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) +{ + u64 a0, a1; + int wait = 1000; + + if (!vdev->notify) { + vdev->notify = pci_alloc_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_notify), + &vdev->notify_pa); + if (!vdev->notify) + return -ENOMEM; + } + + a0 = vdev->notify_pa; + a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; + a1 += sizeof(struct vnic_devcmd_notify); + + return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); +} + +void vnic_dev_notify_unset(struct vnic_dev *vdev) +{ + u64 a0, a1; + int wait = 1000; + + a0 = 0; /* paddr = 0 to unset notify buffer */ + a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */ + a1 += sizeof(struct vnic_devcmd_notify); + + vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); +} + +static int vnic_dev_notify_ready(struct vnic_dev *vdev) +{ + u32 *words; + unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4; + unsigned int i; + u32 csum; + + if (!vdev->notify) + return 0; + + do { + csum = 0; + memcpy(&vdev->notify_copy, vdev->notify, + sizeof(struct vnic_devcmd_notify)); + words = (u32 *)&vdev->notify_copy; + for (i = 1; i < nwords; i++) + csum += words[i]; + } while (csum != words[0]); + + return 1; +} + +int vnic_dev_init(struct vnic_dev *vdev, int arg) +{ + u64 a0 = (u32)arg, a1 = 0; + int wait = 1000; + return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); +} + +int vnic_dev_link_status(struct vnic_dev *vdev) +{ + if (vdev->linkstatus) + return *vdev->linkstatus; + + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.link_state; +} + +u32 vnic_dev_port_speed(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.port_speed; +} + +u32 vnic_dev_msg_lvl(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.msglvl; +} + +u32 vnic_dev_mtu(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.mtu; +} + +void vnic_dev_set_intr_mode(struct vnic_dev *vdev, + enum vnic_dev_intr_mode intr_mode) +{ + vdev->intr_mode = intr_mode; +} + +enum vnic_dev_intr_mode vnic_dev_get_intr_mode( + struct vnic_dev *vdev) +{ + return vdev->intr_mode; +} + +void vnic_dev_unregister(struct vnic_dev *vdev) +{ + if (vdev) { + if (vdev->notify) + pci_free_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_notify), + vdev->notify, + vdev->notify_pa); + if (vdev->linkstatus) + pci_free_consistent(vdev->pdev, + sizeof(u32), + vdev->linkstatus, + vdev->linkstatus_pa); + if (vdev->stats) + pci_free_consistent(vdev->pdev, + sizeof(struct vnic_dev), + vdev->stats, vdev->stats_pa); + if (vdev->fw_info) + pci_free_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_fw_info), + vdev->fw_info, vdev->fw_info_pa); + kfree(vdev); + } +} + +struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, + void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar) +{ + if (!vdev) { + vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC); + if (!vdev) + return NULL; + } + + vdev->priv = priv; + vdev->pdev = pdev; + + if (vnic_dev_discover_res(vdev, bar)) + goto err_out; + + vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0); + if (!vdev->devcmd) + goto err_out; + + return vdev; + +err_out: + vnic_dev_unregister(vdev); + return NULL; +} + diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h new file mode 100644 index 00000000000..2dcffd3a24b --- /dev/null +++ b/drivers/net/enic/vnic_dev.h @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_DEV_H_ +#define _VNIC_DEV_H_ + +#include "vnic_resource.h" +#include "vnic_devcmd.h" + +#ifndef VNIC_PADDR_TARGET +#define VNIC_PADDR_TARGET 0x0000000000000000ULL +#endif + +enum vnic_dev_intr_mode { + VNIC_DEV_INTR_MODE_UNKNOWN, + VNIC_DEV_INTR_MODE_INTX, + VNIC_DEV_INTR_MODE_MSI, + VNIC_DEV_INTR_MODE_MSIX, +}; + +struct vnic_dev_bar { + void __iomem *vaddr; + dma_addr_t bus_addr; + unsigned long len; +}; + +struct vnic_dev_ring { + void *descs; + size_t size; + dma_addr_t base_addr; + size_t base_align; + void *descs_unaligned; + size_t size_unaligned; + dma_addr_t base_addr_unaligned; + unsigned int desc_size; + unsigned int desc_count; + unsigned int desc_avail; +}; + +struct vnic_dev; +struct vnic_stats; + +void *vnic_dev_priv(struct vnic_dev *vdev); +unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, + enum vnic_res_type type); +void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, + unsigned int index); +unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, + unsigned int desc_count, unsigned int desc_size); +void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring); +int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, + unsigned int desc_count, unsigned int desc_size); +void vnic_dev_free_desc_ring(struct vnic_dev *vdev, + struct vnic_dev_ring *ring); +int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, + u64 *a0, u64 *a1, int wait); +int vnic_dev_fw_info(struct vnic_dev *vdev, + struct vnic_devcmd_fw_info **fw_info); +int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size, + void *value); +int vnic_dev_stats_clear(struct vnic_dev *vdev); +int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats); +int vnic_dev_hang_notify(struct vnic_dev *vdev); +void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, + int broadcast, int promisc, int allmulti); +void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); +void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); +int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); +int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr); +void vnic_dev_notify_unset(struct vnic_dev *vdev); +int vnic_dev_link_status(struct vnic_dev *vdev); +u32 vnic_dev_port_speed(struct vnic_dev *vdev); +u32 vnic_dev_msg_lvl(struct vnic_dev *vdev); +u32 vnic_dev_mtu(struct vnic_dev *vdev); +int vnic_dev_close(struct vnic_dev *vdev); +int vnic_dev_enable(struct vnic_dev *vdev); +int vnic_dev_disable(struct vnic_dev *vdev); +int vnic_dev_open(struct vnic_dev *vdev, int arg); +int vnic_dev_open_done(struct vnic_dev *vdev, int *done); +int vnic_dev_init(struct vnic_dev *vdev, int arg); +int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); +int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); +void vnic_dev_set_intr_mode(struct vnic_dev *vdev, + enum vnic_dev_intr_mode intr_mode); +enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); +void vnic_dev_unregister(struct vnic_dev *vdev); +struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, + void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar); + +#endif /* _VNIC_DEV_H_ */ diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h new file mode 100644 index 00000000000..d8617a3373b --- /dev/null +++ b/drivers/net/enic/vnic_devcmd.h @@ -0,0 +1,282 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_DEVCMD_H_ +#define _VNIC_DEVCMD_H_ + +#define _CMD_NBITS 14 +#define _CMD_VTYPEBITS 10 +#define _CMD_FLAGSBITS 6 +#define _CMD_DIRBITS 2 + +#define _CMD_NMASK ((1 << _CMD_NBITS)-1) +#define _CMD_VTYPEMASK ((1 << _CMD_VTYPEBITS)-1) +#define _CMD_FLAGSMASK ((1 << _CMD_FLAGSBITS)-1) +#define _CMD_DIRMASK ((1 << _CMD_DIRBITS)-1) + +#define _CMD_NSHIFT 0 +#define _CMD_VTYPESHIFT (_CMD_NSHIFT+_CMD_NBITS) +#define _CMD_FLAGSSHIFT (_CMD_VTYPESHIFT+_CMD_VTYPEBITS) +#define _CMD_DIRSHIFT (_CMD_FLAGSSHIFT+_CMD_FLAGSBITS) + +/* + * Direction bits (from host perspective). + */ +#define _CMD_DIR_NONE 0U +#define _CMD_DIR_WRITE 1U +#define _CMD_DIR_READ 2U +#define _CMD_DIR_RW (_CMD_DIR_WRITE | _CMD_DIR_READ) + +/* + * Flag bits. + */ +#define _CMD_FLAGS_NONE 0U +#define _CMD_FLAGS_NOWAIT 1U + +/* + * vNIC type bits. + */ +#define _CMD_VTYPE_NONE 0U +#define _CMD_VTYPE_ENET 1U +#define _CMD_VTYPE_FC 2U +#define _CMD_VTYPE_SCSI 4U +#define _CMD_VTYPE_ALL (_CMD_VTYPE_ENET | _CMD_VTYPE_FC | _CMD_VTYPE_SCSI) + +/* + * Used to create cmds.. +*/ +#define _CMDCF(dir, flags, vtype, nr) \ + (((dir) << _CMD_DIRSHIFT) | \ + ((flags) << _CMD_FLAGSSHIFT) | \ + ((vtype) << _CMD_VTYPESHIFT) | \ + ((nr) << _CMD_NSHIFT)) +#define _CMDC(dir, vtype, nr) _CMDCF(dir, 0, vtype, nr) +#define _CMDCNW(dir, vtype, nr) _CMDCF(dir, _CMD_FLAGS_NOWAIT, vtype, nr) + +/* + * Used to decode cmds.. +*/ +#define _CMD_DIR(cmd) (((cmd) >> _CMD_DIRSHIFT) & _CMD_DIRMASK) +#define _CMD_FLAGS(cmd) (((cmd) >> _CMD_FLAGSSHIFT) & _CMD_FLAGSMASK) +#define _CMD_VTYPE(cmd) (((cmd) >> _CMD_VTYPESHIFT) & _CMD_VTYPEMASK) +#define _CMD_N(cmd) (((cmd) >> _CMD_NSHIFT) & _CMD_NMASK) + +enum vnic_devcmd_cmd { + CMD_NONE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0), + + /* mcpu fw info in mem: (u64)a0=paddr to struct vnic_devcmd_fw_info */ + CMD_MCPU_FW_INFO = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1), + + /* dev-specific block member: + * in: (u16)a0=offset,(u8)a1=size + * out: a0=value */ + CMD_DEV_SPEC = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 2), + + /* stats clear */ + CMD_STATS_CLEAR = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 3), + + /* stats dump in mem: (u64)a0=paddr to stats area, + * (u16)a1=sizeof stats area */ + CMD_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 4), + + /* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */ + CMD_PACKET_FILTER = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7), + + /* hang detection notification */ + CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8), + + /* MAC address in (u48)a0 */ + CMD_MAC_ADDR = _CMDC(_CMD_DIR_READ, + _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9), + + /* disable/enable promisc mode: (u8)a0=0/1 */ +/***** XXX DEPRECATED *****/ + CMD_PROMISC_MODE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 10), + + /* disable/enable all-multi mode: (u8)a0=0/1 */ +/***** XXX DEPRECATED *****/ + CMD_ALLMULTI_MODE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 11), + + /* add addr from (u48)a0 */ + CMD_ADDR_ADD = _CMDCNW(_CMD_DIR_WRITE, + _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 12), + + /* del addr from (u48)a0 */ + CMD_ADDR_DEL = _CMDCNW(_CMD_DIR_WRITE, + _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 13), + + /* add VLAN id in (u16)a0 */ + CMD_VLAN_ADD = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 14), + + /* del VLAN id in (u16)a0 */ + CMD_VLAN_DEL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 15), + + /* nic_cfg in (u32)a0 */ + CMD_NIC_CFG = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16), + + /* union vnic_rss_key in mem: (u64)a0=paddr, (u16)a1=len */ + CMD_RSS_KEY = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 17), + + /* union vnic_rss_cpu in mem: (u64)a0=paddr, (u16)a1=len */ + CMD_RSS_CPU = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 18), + + /* initiate softreset */ + CMD_SOFT_RESET = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 19), + + /* softreset status: + * out: a0=0 reset complete, a0=1 reset in progress */ + CMD_SOFT_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 20), + + /* set struct vnic_devcmd_notify buffer in mem: + * in: + * (u64)a0=paddr to notify (set paddr=0 to unset) + * (u32)a1 & 0x00000000ffffffff=sizeof(struct vnic_devcmd_notify) + * (u16)a1 & 0x0000ffff00000000=intr num (-1 for no intr) + * out: + * (u32)a1 = effective size + */ + CMD_NOTIFY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 21), + + /* UNDI API: (u64)a0=paddr to s_PXENV_UNDI_ struct, + * (u8)a1=PXENV_UNDI_xxx */ + CMD_UNDI = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 22), + + /* initiate open sequence (u32)a0=flags (see CMD_OPENF_*) */ + CMD_OPEN = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 23), + + /* open status: + * out: a0=0 open complete, a0=1 open in progress */ + CMD_OPEN_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 24), + + /* close vnic */ + CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25), + + /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ + CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26), + + /* variant of CMD_INIT, with provisioning info + * (u64)a0=paddr of vnic_devcmd_provinfo + * (u32)a1=sizeof provision info */ + CMD_INIT_PROV_INFO = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 27), + + /* enable virtual link */ + CMD_ENABLE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28), + + /* disable virtual link */ + CMD_DISABLE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29), + + /* stats dump all vnics on uplink in mem: (u64)a0=paddr (u32)a1=uif */ + CMD_STATS_DUMP_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 30), + + /* init status: + * out: a0=0 init complete, a0=1 init in progress + * if a0=0, a1=errno */ + CMD_INIT_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31), + + /* INT13 API: (u64)a0=paddr to vnic_int13_params struct + * (u8)a1=INT13_CMD_xxx */ + CMD_INT13 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32), + + /* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */ + CMD_LOGICAL_UPLINK = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 33), + + /* undo initialize of virtual link */ + CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), +}; + +/* flags for CMD_OPEN */ +#define CMD_OPENF_OPROM 0x1 /* open coming from option rom */ + +/* flags for CMD_INIT */ +#define CMD_INITF_DEFAULT_MAC 0x1 /* init with default mac addr */ + +/* flags for CMD_PACKET_FILTER */ +#define CMD_PFILTER_DIRECTED 0x01 +#define CMD_PFILTER_MULTICAST 0x02 +#define CMD_PFILTER_BROADCAST 0x04 +#define CMD_PFILTER_PROMISCUOUS 0x08 +#define CMD_PFILTER_ALL_MULTICAST 0x10 + +enum vnic_devcmd_status { + STAT_NONE = 0, + STAT_BUSY = 1 << 0, /* cmd in progress */ + STAT_ERROR = 1 << 1, /* last cmd caused error (code in a0) */ +}; + +enum vnic_devcmd_error { + ERR_SUCCESS = 0, + ERR_EINVAL = 1, + ERR_EFAULT = 2, + ERR_EPERM = 3, + ERR_EBUSY = 4, + ERR_ECMDUNKNOWN = 5, + ERR_EBADSTATE = 6, + ERR_ENOMEM = 7, + ERR_ETIMEDOUT = 8, + ERR_ELINKDOWN = 9, +}; + +struct vnic_devcmd_fw_info { + char fw_version[32]; + char fw_build[32]; + char hw_version[32]; + char hw_serial_number[32]; +}; + +struct vnic_devcmd_notify { + u32 csum; /* checksum over following words */ + + u32 link_state; /* link up == 1 */ + u32 port_speed; /* effective port speed (rate limit) */ + u32 mtu; /* MTU */ + u32 msglvl; /* requested driver msg lvl */ + u32 uif; /* uplink interface */ + u32 status; /* status bits (see VNIC_STF_*) */ + u32 error; /* error code (see ERR_*) for first ERR */ +}; +#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ + +struct vnic_devcmd_provinfo { + u8 oui[3]; + u8 type; + u8 data[0]; +}; + +/* + * Writing cmd register causes STAT_BUSY to get set in status register. + * When cmd completes, STAT_BUSY will be cleared. + * + * If cmd completed successfully STAT_ERROR will be clear + * and args registers contain cmd-specific results. + * + * If cmd error, STAT_ERROR will be set and args[0] contains error code. + * + * status register is read-only. While STAT_BUSY is set, + * all other register contents are read-only. + */ + +/* Make sizeof(vnic_devcmd) a power-of-2 for I/O BAR. */ +#define VNIC_DEVCMD_NARGS 15 +struct vnic_devcmd { + u32 status; /* RO */ + u32 cmd; /* RW */ + u64 args[VNIC_DEVCMD_NARGS]; /* RW cmd args (little-endian) */ +}; + +#endif /* _VNIC_DEVCMD_H_ */ diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h new file mode 100644 index 00000000000..6332ac9391b --- /dev/null +++ b/drivers/net/enic/vnic_enet.h @@ -0,0 +1,47 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_ENIC_H_ +#define _VNIC_ENIC_H_ + +/* Device-specific region: enet configuration */ +struct vnic_enet_config { + u32 flags; + u32 wq_desc_count; + u32 rq_desc_count; + u16 mtu; + u16 intr_timer; + u8 intr_timer_type; + u8 intr_mode; + char devname[16]; +}; + +#define VENETF_TSO 0x1 /* TSO enabled */ +#define VENETF_LRO 0x2 /* LRO enabled */ +#define VENETF_RXCSUM 0x4 /* RX csum enabled */ +#define VENETF_TXCSUM 0x8 /* TX csum enabled */ +#define VENETF_RSS 0x10 /* RSS enabled */ +#define VENETF_RSSHASH_IPV4 0x20 /* Hash on IPv4 fields */ +#define VENETF_RSSHASH_TCPIPV4 0x40 /* Hash on TCP + IPv4 fields */ +#define VENETF_RSSHASH_IPV6 0x80 /* Hash on IPv6 fields */ +#define VENETF_RSSHASH_TCPIPV6 0x100 /* Hash on TCP + IPv6 fields */ +#define VENETF_RSSHASH_IPV6_EX 0x200 /* Hash on IPv6 extended fields */ +#define VENETF_RSSHASH_TCPIPV6_EX 0x400 /* Hash on TCP + IPv6 ext. fields */ + +#endif /* _VNIC_ENIC_H_ */ diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c new file mode 100644 index 00000000000..ddc38f8f465 --- /dev/null +++ b/drivers/net/enic/vnic_intr.c @@ -0,0 +1,62 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include + +#include "vnic_dev.h" +#include "vnic_intr.h" + +void vnic_intr_free(struct vnic_intr *intr) +{ + intr->ctrl = NULL; +} + +int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, + unsigned int index) +{ + intr->index = index; + intr->vdev = vdev; + + intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index); + if (!intr->ctrl) { + printk(KERN_ERR "Failed to hook INTR[%d].ctrl resource\n", + index); + return -EINVAL; + } + + return 0; +} + +void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, + unsigned int coalescing_type, unsigned int mask_on_assertion) +{ + iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer); + iowrite32(coalescing_type, &intr->ctrl->coalescing_type); + iowrite32(mask_on_assertion, &intr->ctrl->mask_on_assertion); + iowrite32(0, &intr->ctrl->int_credits); +} + +void vnic_intr_clean(struct vnic_intr *intr) +{ + iowrite32(0, &intr->ctrl->int_credits); +} diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h new file mode 100644 index 00000000000..ccc408116af --- /dev/null +++ b/drivers/net/enic/vnic_intr.h @@ -0,0 +1,92 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_INTR_H_ +#define _VNIC_INTR_H_ + +#include + +#include "vnic_dev.h" + +#define VNIC_INTR_TIMER_MAX 0xffff + +#define VNIC_INTR_TIMER_TYPE_ABS 0 +#define VNIC_INTR_TIMER_TYPE_QUIET 1 + +/* Interrupt control */ +struct vnic_intr_ctrl { + u32 coalescing_timer; /* 0x00 */ + u32 pad0; + u32 coalescing_value; /* 0x08 */ + u32 pad1; + u32 coalescing_type; /* 0x10 */ + u32 pad2; + u32 mask_on_assertion; /* 0x18 */ + u32 pad3; + u32 mask; /* 0x20 */ + u32 pad4; + u32 int_credits; /* 0x28 */ + u32 pad5; + u32 int_credit_return; /* 0x30 */ + u32 pad6; +}; + +struct vnic_intr { + unsigned int index; + struct vnic_dev *vdev; + struct vnic_intr_ctrl __iomem *ctrl; /* memory-mapped */ +}; + +static inline void vnic_intr_unmask(struct vnic_intr *intr) +{ + iowrite32(0, &intr->ctrl->mask); +} + +static inline void vnic_intr_mask(struct vnic_intr *intr) +{ + iowrite32(1, &intr->ctrl->mask); +} + +static inline void vnic_intr_return_credits(struct vnic_intr *intr, + unsigned int credits, int unmask, int reset_timer) +{ +#define VNIC_INTR_UNMASK_SHIFT 16 +#define VNIC_INTR_RESET_TIMER_SHIFT 17 + + u32 int_credit_return = (credits & 0xffff) | + (unmask ? (1 << VNIC_INTR_UNMASK_SHIFT) : 0) | + (reset_timer ? (1 << VNIC_INTR_RESET_TIMER_SHIFT) : 0); + + iowrite32(int_credit_return, &intr->ctrl->int_credit_return); +} + +static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) +{ + /* get and ack interrupt in one read (clear-and-ack-on-read) */ + return ioread32(legacy_pba); +} + +void vnic_intr_free(struct vnic_intr *intr); +int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, + unsigned int index); +void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, + unsigned int coalescing_type, unsigned int mask_on_assertion); +void vnic_intr_clean(struct vnic_intr *intr); + +#endif /* _VNIC_INTR_H_ */ diff --git a/drivers/net/enic/vnic_nic.h b/drivers/net/enic/vnic_nic.h new file mode 100644 index 00000000000..dadf26fae69 --- /dev/null +++ b/drivers/net/enic/vnic_nic.h @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_NIC_H_ +#define _VNIC_NIC_H_ + +#define NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD 0xffUL +#define NIC_CFG_RSS_DEFAULT_CPU_SHIFT 0 +#define NIC_CFG_RSS_HASH_TYPE (0xffUL << 8) +#define NIC_CFG_RSS_HASH_TYPE_MASK_FIELD 0xffUL +#define NIC_CFG_RSS_HASH_TYPE_SHIFT 8 +#define NIC_CFG_RSS_HASH_BITS (7UL << 16) +#define NIC_CFG_RSS_HASH_BITS_MASK_FIELD 7UL +#define NIC_CFG_RSS_HASH_BITS_SHIFT 16 +#define NIC_CFG_RSS_BASE_CPU (7UL << 19) +#define NIC_CFG_RSS_BASE_CPU_MASK_FIELD 7UL +#define NIC_CFG_RSS_BASE_CPU_SHIFT 19 +#define NIC_CFG_RSS_ENABLE (1UL << 22) +#define NIC_CFG_RSS_ENABLE_MASK_FIELD 1UL +#define NIC_CFG_RSS_ENABLE_SHIFT 22 +#define NIC_CFG_TSO_IPID_SPLIT_EN (1UL << 23) +#define NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD 1UL +#define NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT 23 +#define NIC_CFG_IG_VLAN_STRIP_EN (1UL << 24) +#define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD 1UL +#define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT 24 + +static inline void vnic_set_nic_cfg(u32 *nic_cfg, + u8 rss_default_cpu, u8 rss_hash_type, + u8 rss_hash_bits, u8 rss_base_cpu, + u8 rss_enable, u8 tso_ipid_split_en, + u8 ig_vlan_strip_en) +{ + *nic_cfg = (rss_default_cpu & NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD) | + ((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_MASK_FIELD) + << NIC_CFG_RSS_HASH_TYPE_SHIFT) | + ((rss_hash_bits & NIC_CFG_RSS_HASH_BITS_MASK_FIELD) + << NIC_CFG_RSS_HASH_BITS_SHIFT) | + ((rss_base_cpu & NIC_CFG_RSS_BASE_CPU_MASK_FIELD) + << NIC_CFG_RSS_BASE_CPU_SHIFT) | + ((rss_enable & NIC_CFG_RSS_ENABLE_MASK_FIELD) + << NIC_CFG_RSS_ENABLE_SHIFT) | + ((tso_ipid_split_en & NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD) + << NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT) | + ((ig_vlan_strip_en & NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD) + << NIC_CFG_IG_VLAN_STRIP_EN_SHIFT); +} + +#endif /* _VNIC_NIC_H_ */ diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h new file mode 100644 index 00000000000..144d2812f08 --- /dev/null +++ b/drivers/net/enic/vnic_resource.h @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_RESOURCE_H_ +#define _VNIC_RESOURCE_H_ + +#define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */ +#define VNIC_RES_VERSION 0x00000000L + +/* vNIC resource types */ +enum vnic_res_type { + RES_TYPE_EOL, /* End-of-list */ + RES_TYPE_WQ, /* Work queues */ + RES_TYPE_RQ, /* Receive queues */ + RES_TYPE_CQ, /* Completion queues */ + RES_TYPE_RSVD1, + RES_TYPE_NIC_CFG, /* Enet NIC config registers */ + RES_TYPE_RSVD2, + RES_TYPE_RSVD3, + RES_TYPE_RSVD4, + RES_TYPE_RSVD5, + RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */ + RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */ + RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */ + RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status, r2c */ + RES_TYPE_RSVD6, + RES_TYPE_RSVD7, + RES_TYPE_DEVCMD, /* Device command region */ + RES_TYPE_PASS_THRU_PAGE, /* Pass-thru page */ + + RES_TYPE_MAX, /* Count of resource types */ +}; + +struct vnic_resource_header { + u32 magic; + u32 version; +}; + +struct vnic_resource { + u8 type; + u8 bar; + u8 pad[2]; + u32 bar_offset; + u32 count; +}; + +#endif /* _VNIC_RESOURCE_H_ */ diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c new file mode 100644 index 00000000000..9365e63e821 --- /dev/null +++ b/drivers/net/enic/vnic_rq.c @@ -0,0 +1,199 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include + +#include "vnic_dev.h" +#include "vnic_rq.h" + +static int vnic_rq_alloc_bufs(struct vnic_rq *rq) +{ + struct vnic_rq_buf *buf; + struct vnic_dev *vdev; + unsigned int i, j, count = rq->ring.desc_count; + unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count); + + vdev = rq->vdev; + + for (i = 0; i < blks; i++) { + rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ, GFP_ATOMIC); + if (!rq->bufs[i]) { + printk(KERN_ERR "Failed to alloc rq_bufs\n"); + return -ENOMEM; + } + } + + for (i = 0; i < blks; i++) { + buf = rq->bufs[i]; + for (j = 0; j < VNIC_RQ_BUF_BLK_ENTRIES; j++) { + buf->index = i * VNIC_RQ_BUF_BLK_ENTRIES + j; + buf->desc = (u8 *)rq->ring.descs + + rq->ring.desc_size * buf->index; + if (buf->index + 1 == count) { + buf->next = rq->bufs[0]; + break; + } else if (j + 1 == VNIC_RQ_BUF_BLK_ENTRIES) { + buf->next = rq->bufs[i + 1]; + } else { + buf->next = buf + 1; + buf++; + } + } + } + + rq->to_use = rq->to_clean = rq->bufs[0]; + rq->buf_index = 0; + + return 0; +} + +void vnic_rq_free(struct vnic_rq *rq) +{ + struct vnic_dev *vdev; + unsigned int i; + + vdev = rq->vdev; + + vnic_dev_free_desc_ring(vdev, &rq->ring); + + for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) { + kfree(rq->bufs[i]); + rq->bufs[i] = NULL; + } + + rq->ctrl = NULL; +} + +int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, + unsigned int desc_count, unsigned int desc_size) +{ + int err; + + rq->index = index; + rq->vdev = vdev; + + rq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_RQ, index); + if (!rq->ctrl) { + printk(KERN_ERR "Failed to hook RQ[%d] resource\n", index); + return -EINVAL; + } + + vnic_rq_disable(rq); + + err = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size); + if (err) + return err; + + err = vnic_rq_alloc_bufs(rq); + if (err) { + vnic_rq_free(rq); + return err; + } + + return 0; +} + +void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, + unsigned int error_interrupt_enable, + unsigned int error_interrupt_offset) +{ + u64 paddr; + u32 fetch_index; + + paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET; + writeq(paddr, &rq->ctrl->ring_base); + iowrite32(rq->ring.desc_count, &rq->ctrl->ring_size); + iowrite32(cq_index, &rq->ctrl->cq_index); + iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable); + iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset); + iowrite32(0, &rq->ctrl->dropped_packet_count); + iowrite32(0, &rq->ctrl->error_status); + + /* Use current fetch_index as the ring starting point */ + fetch_index = ioread32(&rq->ctrl->fetch_index); + rq->to_use = rq->to_clean = + &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES] + [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES]; + iowrite32(fetch_index, &rq->ctrl->posted_index); + + rq->buf_index = 0; +} + +unsigned int vnic_rq_error_status(struct vnic_rq *rq) +{ + return ioread32(&rq->ctrl->error_status); +} + +void vnic_rq_enable(struct vnic_rq *rq) +{ + iowrite32(1, &rq->ctrl->enable); +} + +int vnic_rq_disable(struct vnic_rq *rq) +{ + unsigned int wait; + + iowrite32(0, &rq->ctrl->enable); + + /* Wait for HW to ACK disable request */ + for (wait = 0; wait < 100; wait++) { + if (!(ioread32(&rq->ctrl->running))) + return 0; + udelay(1); + } + + printk(KERN_ERR "Failed to disable RQ[%d]\n", rq->index); + + return -ETIMEDOUT; +} + +void vnic_rq_clean(struct vnic_rq *rq, + void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf)) +{ + struct vnic_rq_buf *buf; + u32 fetch_index; + + BUG_ON(ioread32(&rq->ctrl->enable)); + + buf = rq->to_clean; + + while (vnic_rq_desc_used(rq) > 0) { + + (*buf_clean)(rq, buf); + + buf = rq->to_clean = buf->next; + rq->ring.desc_avail++; + } + + /* Use current fetch_index as the ring starting point */ + fetch_index = ioread32(&rq->ctrl->fetch_index); + rq->to_use = rq->to_clean = + &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES] + [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES]; + iowrite32(fetch_index, &rq->ctrl->posted_index); + + rq->buf_index = 0; + + vnic_dev_clear_desc_ring(&rq->ring); +} + diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h new file mode 100644 index 00000000000..82bfca67cc4 --- /dev/null +++ b/drivers/net/enic/vnic_rq.h @@ -0,0 +1,204 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_RQ_H_ +#define _VNIC_RQ_H_ + +#include + +#include "vnic_dev.h" +#include "vnic_cq.h" + +/* Receive queue control */ +struct vnic_rq_ctrl { + u64 ring_base; /* 0x00 */ + u32 ring_size; /* 0x08 */ + u32 pad0; + u32 posted_index; /* 0x10 */ + u32 pad1; + u32 cq_index; /* 0x18 */ + u32 pad2; + u32 enable; /* 0x20 */ + u32 pad3; + u32 running; /* 0x28 */ + u32 pad4; + u32 fetch_index; /* 0x30 */ + u32 pad5; + u32 error_interrupt_enable; /* 0x38 */ + u32 pad6; + u32 error_interrupt_offset; /* 0x40 */ + u32 pad7; + u32 error_status; /* 0x48 */ + u32 pad8; + u32 dropped_packet_count; /* 0x50 */ + u32 pad9; + u32 dropped_packet_count_rc; /* 0x58 */ + u32 pad10; +}; + +/* Break the vnic_rq_buf allocations into blocks of 64 entries */ +#define VNIC_RQ_BUF_BLK_ENTRIES 64 +#define VNIC_RQ_BUF_BLK_SZ \ + (VNIC_RQ_BUF_BLK_ENTRIES * sizeof(struct vnic_rq_buf)) +#define VNIC_RQ_BUF_BLKS_NEEDED(entries) \ + DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES) +#define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096) + +struct vnic_rq_buf { + struct vnic_rq_buf *next; + dma_addr_t dma_addr; + void *os_buf; + unsigned int os_buf_index; + unsigned int len; + unsigned int index; + void *desc; +}; + +struct vnic_rq { + unsigned int index; + struct vnic_dev *vdev; + struct vnic_rq_ctrl __iomem *ctrl; /* memory-mapped */ + struct vnic_dev_ring ring; + struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX]; + struct vnic_rq_buf *to_use; + struct vnic_rq_buf *to_clean; + void *os_buf_head; + unsigned int buf_index; + unsigned int pkts_outstanding; +}; + +static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq) +{ + /* how many does SW own? */ + return rq->ring.desc_avail; +} + +static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq) +{ + /* how many does HW own? */ + return rq->ring.desc_count - rq->ring.desc_avail - 1; +} + +static inline void *vnic_rq_next_desc(struct vnic_rq *rq) +{ + return rq->to_use->desc; +} + +static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq) +{ + return rq->to_use->index; +} + +static inline unsigned int vnic_rq_next_buf_index(struct vnic_rq *rq) +{ + return rq->buf_index++; +} + +static inline void vnic_rq_post(struct vnic_rq *rq, + void *os_buf, unsigned int os_buf_index, + dma_addr_t dma_addr, unsigned int len) +{ + struct vnic_rq_buf *buf = rq->to_use; + + buf->os_buf = os_buf; + buf->os_buf_index = os_buf_index; + buf->dma_addr = dma_addr; + buf->len = len; + + buf = buf->next; + rq->to_use = buf; + rq->ring.desc_avail--; + + /* Move the posted_index every nth descriptor + */ + +#ifndef VNIC_RQ_RETURN_RATE +#define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */ +#endif + + if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) + iowrite32(buf->index, &rq->ctrl->posted_index); +} + +static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count) +{ + rq->ring.desc_avail += count; +} + +enum desc_return_options { + VNIC_RQ_RETURN_DESC, + VNIC_RQ_DEFER_RETURN_DESC, +}; + +static inline void vnic_rq_service(struct vnic_rq *rq, + struct cq_desc *cq_desc, u16 completed_index, + int desc_return, void (*buf_service)(struct vnic_rq *rq, + struct cq_desc *cq_desc, struct vnic_rq_buf *buf, + int skipped, void *opaque), void *opaque) +{ + struct vnic_rq_buf *buf; + int skipped; + + buf = rq->to_clean; + while (1) { + + skipped = (buf->index != completed_index); + + (*buf_service)(rq, cq_desc, buf, skipped, opaque); + + if (desc_return == VNIC_RQ_RETURN_DESC) + rq->ring.desc_avail++; + + rq->to_clean = buf->next; + + if (!skipped) + break; + + buf = rq->to_clean; + } +} + +static inline int vnic_rq_fill(struct vnic_rq *rq, + int (*buf_fill)(struct vnic_rq *rq)) +{ + int err; + + while (vnic_rq_desc_avail(rq) > 1) { + + err = (*buf_fill)(rq); + if (err) + return err; + } + + return 0; +} + +void vnic_rq_free(struct vnic_rq *rq); +int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, + unsigned int desc_count, unsigned int desc_size); +void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, + unsigned int error_interrupt_enable, + unsigned int error_interrupt_offset); +unsigned int vnic_rq_error_status(struct vnic_rq *rq); +void vnic_rq_enable(struct vnic_rq *rq); +int vnic_rq_disable(struct vnic_rq *rq); +void vnic_rq_clean(struct vnic_rq *rq, + void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf)); + +#endif /* _VNIC_RQ_H_ */ diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h new file mode 100644 index 00000000000..e325d65d7c3 --- /dev/null +++ b/drivers/net/enic/vnic_rss.h @@ -0,0 +1,32 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + */ + +#ifndef _VNIC_RSS_H_ +#define _VNIC_RSS_H_ + +/* RSS key array */ +union vnic_rss_key { + struct { + u8 b[10]; + u8 b_pad[6]; + } key[4]; + u64 raw[8]; +}; + +/* RSS cpu array */ +union vnic_rss_cpu { + struct { + u8 b[4] ; + u8 b_pad[4]; + } cpu[32]; + u64 raw[32]; +}; + +void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key); +void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); +void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key); +void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); + +#endif /* _VNIC_RSS_H_ */ diff --git a/drivers/net/enic/vnic_stats.h b/drivers/net/enic/vnic_stats.h new file mode 100644 index 00000000000..9ff9614d89b --- /dev/null +++ b/drivers/net/enic/vnic_stats.h @@ -0,0 +1,70 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_STATS_H_ +#define _VNIC_STATS_H_ + +/* Tx statistics */ +struct vnic_tx_stats { + u64 tx_frames_ok; + u64 tx_unicast_frames_ok; + u64 tx_multicast_frames_ok; + u64 tx_broadcast_frames_ok; + u64 tx_bytes_ok; + u64 tx_unicast_bytes_ok; + u64 tx_multicast_bytes_ok; + u64 tx_broadcast_bytes_ok; + u64 tx_drops; + u64 tx_errors; + u64 tx_tso; + u64 rsvd[16]; +}; + +/* Rx statistics */ +struct vnic_rx_stats { + u64 rx_frames_ok; + u64 rx_frames_total; + u64 rx_unicast_frames_ok; + u64 rx_multicast_frames_ok; + u64 rx_broadcast_frames_ok; + u64 rx_bytes_ok; + u64 rx_unicast_bytes_ok; + u64 rx_multicast_bytes_ok; + u64 rx_broadcast_bytes_ok; + u64 rx_drop; + u64 rx_no_bufs; + u64 rx_errors; + u64 rx_rss; + u64 rx_crc_errors; + u64 rx_frames_64; + u64 rx_frames_127; + u64 rx_frames_255; + u64 rx_frames_511; + u64 rx_frames_1023; + u64 rx_frames_1518; + u64 rx_frames_to_max; + u64 rsvd[16]; +}; + +struct vnic_stats { + struct vnic_tx_stats tx; + struct vnic_rx_stats rx; +}; + +#endif /* _VNIC_STATS_H_ */ diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c new file mode 100644 index 00000000000..a576d04708e --- /dev/null +++ b/drivers/net/enic/vnic_wq.c @@ -0,0 +1,184 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include + +#include "vnic_dev.h" +#include "vnic_wq.h" + +static int vnic_wq_alloc_bufs(struct vnic_wq *wq) +{ + struct vnic_wq_buf *buf; + struct vnic_dev *vdev; + unsigned int i, j, count = wq->ring.desc_count; + unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count); + + vdev = wq->vdev; + + for (i = 0; i < blks; i++) { + wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ, GFP_ATOMIC); + if (!wq->bufs[i]) { + printk(KERN_ERR "Failed to alloc wq_bufs\n"); + return -ENOMEM; + } + } + + for (i = 0; i < blks; i++) { + buf = wq->bufs[i]; + for (j = 0; j < VNIC_WQ_BUF_BLK_ENTRIES; j++) { + buf->index = i * VNIC_WQ_BUF_BLK_ENTRIES + j; + buf->desc = (u8 *)wq->ring.descs + + wq->ring.desc_size * buf->index; + if (buf->index + 1 == count) { + buf->next = wq->bufs[0]; + break; + } else if (j + 1 == VNIC_WQ_BUF_BLK_ENTRIES) { + buf->next = wq->bufs[i + 1]; + } else { + buf->next = buf + 1; + buf++; + } + } + } + + wq->to_use = wq->to_clean = wq->bufs[0]; + + return 0; +} + +void vnic_wq_free(struct vnic_wq *wq) +{ + struct vnic_dev *vdev; + unsigned int i; + + vdev = wq->vdev; + + vnic_dev_free_desc_ring(vdev, &wq->ring); + + for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) { + kfree(wq->bufs[i]); + wq->bufs[i] = NULL; + } + + wq->ctrl = NULL; +} + +int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, + unsigned int desc_count, unsigned int desc_size) +{ + int err; + + wq->index = index; + wq->vdev = vdev; + + wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index); + if (!wq->ctrl) { + printk(KERN_ERR "Failed to hook WQ[%d] resource\n", index); + return -EINVAL; + } + + vnic_wq_disable(wq); + + err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size); + if (err) + return err; + + err = vnic_wq_alloc_bufs(wq); + if (err) { + vnic_wq_free(wq); + return err; + } + + return 0; +} + +void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, + unsigned int error_interrupt_enable, + unsigned int error_interrupt_offset) +{ + u64 paddr; + + paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET; + writeq(paddr, &wq->ctrl->ring_base); + iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size); + iowrite32(0, &wq->ctrl->fetch_index); + iowrite32(0, &wq->ctrl->posted_index); + iowrite32(cq_index, &wq->ctrl->cq_index); + iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable); + iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset); + iowrite32(0, &wq->ctrl->error_status); +} + +unsigned int vnic_wq_error_status(struct vnic_wq *wq) +{ + return ioread32(&wq->ctrl->error_status); +} + +void vnic_wq_enable(struct vnic_wq *wq) +{ + iowrite32(1, &wq->ctrl->enable); +} + +int vnic_wq_disable(struct vnic_wq *wq) +{ + unsigned int wait; + + iowrite32(0, &wq->ctrl->enable); + + /* Wait for HW to ACK disable request */ + for (wait = 0; wait < 100; wait++) { + if (!(ioread32(&wq->ctrl->running))) + return 0; + udelay(1); + } + + printk(KERN_ERR "Failed to disable WQ[%d]\n", wq->index); + + return -ETIMEDOUT; +} + +void vnic_wq_clean(struct vnic_wq *wq, + void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)) +{ + struct vnic_wq_buf *buf; + + BUG_ON(ioread32(&wq->ctrl->enable)); + + buf = wq->to_clean; + + while (vnic_wq_desc_used(wq) > 0) { + + (*buf_clean)(wq, buf); + + buf = wq->to_clean = buf->next; + wq->ring.desc_avail++; + } + + wq->to_use = wq->to_clean = wq->bufs[0]; + + iowrite32(0, &wq->ctrl->fetch_index); + iowrite32(0, &wq->ctrl->posted_index); + iowrite32(0, &wq->ctrl->error_status); + + vnic_dev_clear_desc_ring(&wq->ring); +} diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h new file mode 100644 index 00000000000..7081828d8a4 --- /dev/null +++ b/drivers/net/enic/vnic_wq.h @@ -0,0 +1,154 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _VNIC_WQ_H_ +#define _VNIC_WQ_H_ + +#include + +#include "vnic_dev.h" +#include "vnic_cq.h" + +/* Work queue control */ +struct vnic_wq_ctrl { + u64 ring_base; /* 0x00 */ + u32 ring_size; /* 0x08 */ + u32 pad0; + u32 posted_index; /* 0x10 */ + u32 pad1; + u32 cq_index; /* 0x18 */ + u32 pad2; + u32 enable; /* 0x20 */ + u32 pad3; + u32 running; /* 0x28 */ + u32 pad4; + u32 fetch_index; /* 0x30 */ + u32 pad5; + u32 dca_value; /* 0x38 */ + u32 pad6; + u32 error_interrupt_enable; /* 0x40 */ + u32 pad7; + u32 error_interrupt_offset; /* 0x48 */ + u32 pad8; + u32 error_status; /* 0x50 */ + u32 pad9; +}; + +struct vnic_wq_buf { + struct vnic_wq_buf *next; + dma_addr_t dma_addr; + void *os_buf; + unsigned int len; + unsigned int index; + int sop; + void *desc; +}; + +/* Break the vnic_wq_buf allocations into blocks of 64 entries */ +#define VNIC_WQ_BUF_BLK_ENTRIES 64 +#define VNIC_WQ_BUF_BLK_SZ \ + (VNIC_WQ_BUF_BLK_ENTRIES * sizeof(struct vnic_wq_buf)) +#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \ + DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES) +#define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096) + +struct vnic_wq { + unsigned int index; + struct vnic_dev *vdev; + struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */ + struct vnic_dev_ring ring; + struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX]; + struct vnic_wq_buf *to_use; + struct vnic_wq_buf *to_clean; + unsigned int pkts_outstanding; +}; + +static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq) +{ + /* how many does SW own? */ + return wq->ring.desc_avail; +} + +static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq) +{ + /* how many does HW own? */ + return wq->ring.desc_count - wq->ring.desc_avail - 1; +} + +static inline void *vnic_wq_next_desc(struct vnic_wq *wq) +{ + return wq->to_use->desc; +} + +static inline void vnic_wq_post(struct vnic_wq *wq, + void *os_buf, dma_addr_t dma_addr, + unsigned int len, int sop, int eop) +{ + struct vnic_wq_buf *buf = wq->to_use; + + buf->sop = sop; + buf->os_buf = eop ? os_buf : NULL; + buf->dma_addr = dma_addr; + buf->len = len; + + buf = buf->next; + if (eop) + iowrite32(buf->index, &wq->ctrl->posted_index); + wq->to_use = buf; + + wq->ring.desc_avail--; +} + +static inline void vnic_wq_service(struct vnic_wq *wq, + struct cq_desc *cq_desc, u16 completed_index, + void (*buf_service)(struct vnic_wq *wq, + struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque), + void *opaque) +{ + struct vnic_wq_buf *buf; + + buf = wq->to_clean; + while (1) { + + (*buf_service)(wq, cq_desc, buf, opaque); + + wq->ring.desc_avail++; + + wq->to_clean = buf->next; + + if (buf->index == completed_index) + break; + + buf = wq->to_clean; + } +} + +void vnic_wq_free(struct vnic_wq *wq); +int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, + unsigned int desc_count, unsigned int desc_size); +void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, + unsigned int error_interrupt_enable, + unsigned int error_interrupt_offset); +unsigned int vnic_wq_error_status(struct vnic_wq *wq); +void vnic_wq_enable(struct vnic_wq *wq); +int vnic_wq_disable(struct vnic_wq *wq); +void vnic_wq_clean(struct vnic_wq *wq, + void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)); + +#endif /* _VNIC_WQ_H_ */ diff --git a/drivers/net/enic/wq_enet_desc.h b/drivers/net/enic/wq_enet_desc.h new file mode 100644 index 00000000000..483596c2d8b --- /dev/null +++ b/drivers/net/enic/wq_enet_desc.h @@ -0,0 +1,98 @@ +/* + * Copyright 2008 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _WQ_ENET_DESC_H_ +#define _WQ_ENET_DESC_H_ + +/* Ethernet work queue descriptor: 16B */ +struct wq_enet_desc { + __le64 address; + __le16 length; + __le16 mss_loopback; + __le16 header_length_flags; + __le16 vlan_tag; +}; + +#define WQ_ENET_ADDR_BITS 64 +#define WQ_ENET_LEN_BITS 14 +#define WQ_ENET_LEN_MASK ((1 << WQ_ENET_LEN_BITS) - 1) +#define WQ_ENET_MSS_BITS 14 +#define WQ_ENET_MSS_MASK ((1 << WQ_ENET_MSS_BITS) - 1) +#define WQ_ENET_MSS_SHIFT 2 +#define WQ_ENET_LOOPBACK_SHIFT 1 +#define WQ_ENET_HDRLEN_BITS 10 +#define WQ_ENET_HDRLEN_MASK ((1 << WQ_ENET_HDRLEN_BITS) - 1) +#define WQ_ENET_FLAGS_OM_BITS 2 +#define WQ_ENET_FLAGS_OM_MASK ((1 << WQ_ENET_FLAGS_OM_BITS) - 1) +#define WQ_ENET_FLAGS_EOP_SHIFT 12 +#define WQ_ENET_FLAGS_CQ_ENTRY_SHIFT 13 +#define WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT 14 +#define WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT 15 + +#define WQ_ENET_OFFLOAD_MODE_CSUM 0 +#define WQ_ENET_OFFLOAD_MODE_RESERVED 1 +#define WQ_ENET_OFFLOAD_MODE_CSUM_L4 2 +#define WQ_ENET_OFFLOAD_MODE_TSO 3 + +static inline void wq_enet_desc_enc(struct wq_enet_desc *desc, + u64 address, u16 length, u16 mss, u16 header_length, + u8 offload_mode, u8 eop, u8 cq_entry, u8 fcoe_encap, + u8 vlan_tag_insert, u16 vlan_tag, u8 loopback) +{ + desc->address = cpu_to_le64(address); + desc->length = cpu_to_le16(length & WQ_ENET_LEN_MASK); + desc->mss_loopback = cpu_to_le16((mss & WQ_ENET_MSS_MASK) << + WQ_ENET_MSS_SHIFT | (loopback & 1) << WQ_ENET_LOOPBACK_SHIFT); + desc->header_length_flags = cpu_to_le16( + (header_length & WQ_ENET_HDRLEN_MASK) | + (offload_mode & WQ_ENET_FLAGS_OM_MASK) << WQ_ENET_HDRLEN_BITS | + (eop & 1) << WQ_ENET_FLAGS_EOP_SHIFT | + (cq_entry & 1) << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT | + (fcoe_encap & 1) << WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT | + (vlan_tag_insert & 1) << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT); + desc->vlan_tag = cpu_to_le16(vlan_tag); +} + +static inline void wq_enet_desc_dec(struct wq_enet_desc *desc, + u64 *address, u16 *length, u16 *mss, u16 *header_length, + u8 *offload_mode, u8 *eop, u8 *cq_entry, u8 *fcoe_encap, + u8 *vlan_tag_insert, u16 *vlan_tag, u8 *loopback) +{ + *address = le64_to_cpu(desc->address); + *length = le16_to_cpu(desc->length) & WQ_ENET_LEN_MASK; + *mss = (le16_to_cpu(desc->mss_loopback) >> WQ_ENET_MSS_SHIFT) & + WQ_ENET_MSS_MASK; + *loopback = (u8)((le16_to_cpu(desc->mss_loopback) >> + WQ_ENET_LOOPBACK_SHIFT) & 1); + *header_length = le16_to_cpu(desc->header_length_flags) & + WQ_ENET_HDRLEN_MASK; + *offload_mode = (u8)((le16_to_cpu(desc->header_length_flags) >> + WQ_ENET_HDRLEN_BITS) & WQ_ENET_FLAGS_OM_MASK); + *eop = (u8)((le16_to_cpu(desc->header_length_flags) >> + WQ_ENET_FLAGS_EOP_SHIFT) & 1); + *cq_entry = (u8)((le16_to_cpu(desc->header_length_flags) >> + WQ_ENET_FLAGS_CQ_ENTRY_SHIFT) & 1); + *fcoe_encap = (u8)((le16_to_cpu(desc->header_length_flags) >> + WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT) & 1); + *vlan_tag_insert = (u8)((le16_to_cpu(desc->header_length_flags) >> + WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT) & 1); + *vlan_tag = le16_to_cpu(desc->vlan_tag); +} + +#endif /* _WQ_ENET_DESC_H_ */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 90a132ab84a..6f4276d461c 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1411,6 +1411,8 @@ #define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 #define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 +#define PCI_VENDOR_ID_CISCO 0x1137 + #define PCI_VENDOR_ID_ZIATECH 0x1138 #define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 -- GitLab From 95252236e73e789dd186ce796a2abc60b3a61ebe Mon Sep 17 00:00:00 2001 From: Guo-Fu Tseng Date: Tue, 16 Sep 2008 01:00:11 +0800 Subject: [PATCH 1980/5416] jme: JMicron Gigabit Ethernet Driver Supporting JMC250, and JMC260. Signed-off-by: Guo-Fu Tseng Acked-and-tested-by: Ethan Hsiao Signed-off-by: Jeff Garzik --- MAINTAINERS | 6 + drivers/net/Kconfig | 12 + drivers/net/Makefile | 1 + drivers/net/jme.c | 3019 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/jme.h | 1199 +++++++++++++++++ 5 files changed, 4237 insertions(+) create mode 100644 drivers/net/jme.c create mode 100644 drivers/net/jme.h diff --git a/MAINTAINERS b/MAINTAINERS index 467f994b1fa..c8203d780f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2326,6 +2326,12 @@ L: video4linux-list@redhat.com W: http://www.ivtvdriver.org S: Maintained +JME NETWORK DRIVER +P: Guo-Fu Tseng +M: cooldavid@cooldavid.org +L: netdev@vger.kernel.org +S: Maintained + JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) P: David Woodhouse M: dwmw2@infradead.org diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c012cd8fe3..069755af761 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2313,6 +2313,18 @@ config ATL1E To compile this driver as a module, choose M here. The module will be called atl1e. +config JME + tristate "JMicron(R) PCI-Express Gigabit Ethernet support" + depends on PCI + select CRC32 + select MII + ---help--- + This driver supports the PCI-Express gigabit ethernet adapters + based on JMicron JMC250 chipset. + + To compile this driver as a module, choose M here. The module + will be called jme. + endif # NETDEV_1000 # diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d4ec6ba7f07..016e23f000e 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_ATL1E) += atl1e/ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_ENIC) += enic/ +obj-$(CONFIG_JME) += jme.o gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ diff --git a/drivers/net/jme.c b/drivers/net/jme.c new file mode 100644 index 00000000000..f292df55754 --- /dev/null +++ b/drivers/net/jme.c @@ -0,0 +1,3019 @@ +/* + * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver + * + * Copyright 2008 JMicron Technology Corporation + * http://www.jmicron.com/ + * + * Author: Guo-Fu Tseng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 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 "jme.h" + +static int force_pseudohp = -1; +static int no_pseudohp = -1; +static int no_extplug = -1; +module_param(force_pseudohp, int, 0); +MODULE_PARM_DESC(force_pseudohp, + "Enable pseudo hot-plug feature manually by driver instead of BIOS."); +module_param(no_pseudohp, int, 0); +MODULE_PARM_DESC(no_pseudohp, "Disable pseudo hot-plug feature."); +module_param(no_extplug, int, 0); +MODULE_PARM_DESC(no_extplug, + "Do not use external plug signal for pseudo hot-plug."); + +static int +jme_mdio_read(struct net_device *netdev, int phy, int reg) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i, val, again = (reg == MII_BMSR) ? 1 : 0; + +read_again: + jwrite32(jme, JME_SMI, SMI_OP_REQ | + smi_phy_addr(phy) | + smi_reg_addr(reg)); + + wmb(); + for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) { + udelay(20); + val = jread32(jme, JME_SMI); + if ((val & SMI_OP_REQ) == 0) + break; + } + + if (i == 0) { + jeprintk(jme->pdev, "phy(%d) read timeout : %d\n", phy, reg); + return 0; + } + + if (again--) + goto read_again; + + return (val & SMI_DATA_MASK) >> SMI_DATA_SHIFT; +} + +static void +jme_mdio_write(struct net_device *netdev, + int phy, int reg, int val) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i; + + jwrite32(jme, JME_SMI, SMI_OP_WRITE | SMI_OP_REQ | + ((val << SMI_DATA_SHIFT) & SMI_DATA_MASK) | + smi_phy_addr(phy) | smi_reg_addr(reg)); + + wmb(); + for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) { + udelay(20); + if ((jread32(jme, JME_SMI) & SMI_OP_REQ) == 0) + break; + } + + if (i == 0) + jeprintk(jme->pdev, "phy(%d) write timeout : %d\n", phy, reg); + + return; +} + +static inline void +jme_reset_phy_processor(struct jme_adapter *jme) +{ + u32 val; + + jme_mdio_write(jme->dev, + jme->mii_if.phy_id, + MII_ADVERTISE, ADVERTISE_ALL | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + + if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) + jme_mdio_write(jme->dev, + jme->mii_if.phy_id, + MII_CTRL1000, + ADVERTISE_1000FULL | ADVERTISE_1000HALF); + + val = jme_mdio_read(jme->dev, + jme->mii_if.phy_id, + MII_BMCR); + + jme_mdio_write(jme->dev, + jme->mii_if.phy_id, + MII_BMCR, val | BMCR_RESET); + + return; +} + +static void +jme_setup_wakeup_frame(struct jme_adapter *jme, + u32 *mask, u32 crc, int fnr) +{ + int i; + + /* + * Setup CRC pattern + */ + jwrite32(jme, JME_WFOI, WFOI_CRC_SEL | (fnr & WFOI_FRAME_SEL)); + wmb(); + jwrite32(jme, JME_WFODP, crc); + wmb(); + + /* + * Setup Mask + */ + for (i = 0 ; i < WAKEUP_FRAME_MASK_DWNR ; ++i) { + jwrite32(jme, JME_WFOI, + ((i << WFOI_MASK_SHIFT) & WFOI_MASK_SEL) | + (fnr & WFOI_FRAME_SEL)); + wmb(); + jwrite32(jme, JME_WFODP, mask[i]); + wmb(); + } +} + +static inline void +jme_reset_mac_processor(struct jme_adapter *jme) +{ + u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0}; + u32 crc = 0xCDCDCDCD; + u32 gpreg0; + int i; + + jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST); + udelay(2); + jwrite32(jme, JME_GHC, jme->reg_ghc); + + jwrite32(jme, JME_RXDBA_LO, 0x00000000); + jwrite32(jme, JME_RXDBA_HI, 0x00000000); + jwrite32(jme, JME_RXQDC, 0x00000000); + jwrite32(jme, JME_RXNDA, 0x00000000); + jwrite32(jme, JME_TXDBA_LO, 0x00000000); + jwrite32(jme, JME_TXDBA_HI, 0x00000000); + jwrite32(jme, JME_TXQDC, 0x00000000); + jwrite32(jme, JME_TXNDA, 0x00000000); + + jwrite32(jme, JME_RXMCHT_LO, 0x00000000); + jwrite32(jme, JME_RXMCHT_HI, 0x00000000); + for (i = 0 ; i < WAKEUP_FRAME_NR ; ++i) + jme_setup_wakeup_frame(jme, mask, crc, i); + if (jme->fpgaver) + gpreg0 = GPREG0_DEFAULT | GPREG0_LNKINTPOLL; + else + gpreg0 = GPREG0_DEFAULT; + jwrite32(jme, JME_GPREG0, gpreg0); + jwrite32(jme, JME_GPREG1, 0); +} + +static inline void +jme_reset_ghc_speed(struct jme_adapter *jme) +{ + jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX); + jwrite32(jme, JME_GHC, jme->reg_ghc); +} + +static inline void +jme_clear_pm(struct jme_adapter *jme) +{ + jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); + pci_set_power_state(jme->pdev, PCI_D0); + pci_enable_wake(jme->pdev, PCI_D0, false); +} + +static int +jme_reload_eeprom(struct jme_adapter *jme) +{ + u32 val; + int i; + + val = jread32(jme, JME_SMBCSR); + + if (val & SMBCSR_EEPROMD) { + val |= SMBCSR_CNACK; + jwrite32(jme, JME_SMBCSR, val); + val |= SMBCSR_RELOAD; + jwrite32(jme, JME_SMBCSR, val); + mdelay(12); + + for (i = JME_EEPROM_RELOAD_TIMEOUT; i > 0; --i) { + mdelay(1); + if ((jread32(jme, JME_SMBCSR) & SMBCSR_RELOAD) == 0) + break; + } + + if (i == 0) { + jeprintk(jme->pdev, "eeprom reload timeout\n"); + return -EIO; + } + } + + return 0; +} + +static void +jme_load_macaddr(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + unsigned char macaddr[6]; + u32 val; + + spin_lock_bh(&jme->macaddr_lock); + val = jread32(jme, JME_RXUMA_LO); + macaddr[0] = (val >> 0) & 0xFF; + macaddr[1] = (val >> 8) & 0xFF; + macaddr[2] = (val >> 16) & 0xFF; + macaddr[3] = (val >> 24) & 0xFF; + val = jread32(jme, JME_RXUMA_HI); + macaddr[4] = (val >> 0) & 0xFF; + macaddr[5] = (val >> 8) & 0xFF; + memcpy(netdev->dev_addr, macaddr, 6); + spin_unlock_bh(&jme->macaddr_lock); +} + +static inline void +jme_set_rx_pcc(struct jme_adapter *jme, int p) +{ + switch (p) { + case PCC_OFF: + jwrite32(jme, JME_PCCRX0, + ((PCC_OFF_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | + ((PCC_OFF_CNT << PCCRX_SHIFT) & PCCRX_MASK)); + break; + case PCC_P1: + jwrite32(jme, JME_PCCRX0, + ((PCC_P1_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | + ((PCC_P1_CNT << PCCRX_SHIFT) & PCCRX_MASK)); + break; + case PCC_P2: + jwrite32(jme, JME_PCCRX0, + ((PCC_P2_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | + ((PCC_P2_CNT << PCCRX_SHIFT) & PCCRX_MASK)); + break; + case PCC_P3: + jwrite32(jme, JME_PCCRX0, + ((PCC_P3_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) | + ((PCC_P3_CNT << PCCRX_SHIFT) & PCCRX_MASK)); + break; + default: + break; + } + wmb(); + + if (!(test_bit(JME_FLAG_POLL, &jme->flags))) + msg_rx_status(jme, "Switched to PCC_P%d\n", p); +} + +static void +jme_start_irq(struct jme_adapter *jme) +{ + register struct dynpcc_info *dpi = &(jme->dpi); + + jme_set_rx_pcc(jme, PCC_P1); + dpi->cur = PCC_P1; + dpi->attempt = PCC_P1; + dpi->cnt = 0; + + jwrite32(jme, JME_PCCTX, + ((PCC_TX_TO << PCCTXTO_SHIFT) & PCCTXTO_MASK) | + ((PCC_TX_CNT << PCCTX_SHIFT) & PCCTX_MASK) | + PCCTXQ0_EN + ); + + /* + * Enable Interrupts + */ + jwrite32(jme, JME_IENS, INTR_ENABLE); +} + +static inline void +jme_stop_irq(struct jme_adapter *jme) +{ + /* + * Disable Interrupts + */ + jwrite32f(jme, JME_IENC, INTR_ENABLE); +} + +static inline void +jme_enable_shadow(struct jme_adapter *jme) +{ + jwrite32(jme, + JME_SHBA_LO, + ((u32)jme->shadow_dma & ~((u32)0x1F)) | SHBA_POSTEN); +} + +static inline void +jme_disable_shadow(struct jme_adapter *jme) +{ + jwrite32(jme, JME_SHBA_LO, 0x0); +} + +static u32 +jme_linkstat_from_phy(struct jme_adapter *jme) +{ + u32 phylink, bmsr; + + phylink = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 17); + bmsr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMSR); + if (bmsr & BMSR_ANCOMP) + phylink |= PHY_LINK_AUTONEG_COMPLETE; + + return phylink; +} + +static inline void +jme_set_phyfifoa(struct jme_adapter *jme) +{ + jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004); +} + +static inline void +jme_set_phyfifob(struct jme_adapter *jme) +{ + jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000); +} + +static int +jme_check_link(struct net_device *netdev, int testonly) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr; + char linkmsg[64]; + int rc = 0; + + linkmsg[0] = '\0'; + + if (jme->fpgaver) + phylink = jme_linkstat_from_phy(jme); + else + phylink = jread32(jme, JME_PHY_LINK); + + if (phylink & PHY_LINK_UP) { + if (!(phylink & PHY_LINK_AUTONEG_COMPLETE)) { + /* + * If we did not enable AN + * Speed/Duplex Info should be obtained from SMI + */ + phylink = PHY_LINK_UP; + + bmcr = jme_mdio_read(jme->dev, + jme->mii_if.phy_id, + MII_BMCR); + + phylink |= ((bmcr & BMCR_SPEED1000) && + (bmcr & BMCR_SPEED100) == 0) ? + PHY_LINK_SPEED_1000M : + (bmcr & BMCR_SPEED100) ? + PHY_LINK_SPEED_100M : + PHY_LINK_SPEED_10M; + + phylink |= (bmcr & BMCR_FULLDPLX) ? + PHY_LINK_DUPLEX : 0; + + strcat(linkmsg, "Forced: "); + } else { + /* + * Keep polling for speed/duplex resolve complete + */ + while (!(phylink & PHY_LINK_SPEEDDPU_RESOLVED) && + --cnt) { + + udelay(1); + + if (jme->fpgaver) + phylink = jme_linkstat_from_phy(jme); + else + phylink = jread32(jme, JME_PHY_LINK); + } + if (!cnt) + jeprintk(jme->pdev, + "Waiting speed resolve timeout.\n"); + + strcat(linkmsg, "ANed: "); + } + + if (jme->phylink == phylink) { + rc = 1; + goto out; + } + if (testonly) + goto out; + + jme->phylink = phylink; + + ghc = jme->reg_ghc & ~(GHC_SPEED_10M | + GHC_SPEED_100M | + GHC_SPEED_1000M | + GHC_DPX); + switch (phylink & PHY_LINK_SPEED_MASK) { + case PHY_LINK_SPEED_10M: + ghc |= GHC_SPEED_10M; + strcat(linkmsg, "10 Mbps, "); + if (is_buggy250(jme->pdev->device, jme->chiprev)) + jme_set_phyfifoa(jme); + break; + case PHY_LINK_SPEED_100M: + ghc |= GHC_SPEED_100M; + strcat(linkmsg, "100 Mbps, "); + if (is_buggy250(jme->pdev->device, jme->chiprev)) + jme_set_phyfifob(jme); + break; + case PHY_LINK_SPEED_1000M: + ghc |= GHC_SPEED_1000M; + strcat(linkmsg, "1000 Mbps, "); + if (is_buggy250(jme->pdev->device, jme->chiprev)) + jme_set_phyfifoa(jme); + break; + default: + break; + } + ghc |= (phylink & PHY_LINK_DUPLEX) ? GHC_DPX : 0; + + strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? + "Full-Duplex, " : + "Half-Duplex, "); + + if (phylink & PHY_LINK_MDI_STAT) + strcat(linkmsg, "MDI-X"); + else + strcat(linkmsg, "MDI"); + + if (phylink & PHY_LINK_DUPLEX) { + jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); + } else { + jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | + TXMCS_BACKOFF | + TXMCS_CARRIERSENSE | + TXMCS_COLLISION); + jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN | + ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) | + TXTRHD_TXREN | + ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL)); + } + + jme->reg_ghc = ghc; + jwrite32(jme, JME_GHC, ghc); + + msg_link(jme, "Link is up at %s.\n", linkmsg); + netif_carrier_on(netdev); + } else { + if (testonly) + goto out; + + msg_link(jme, "Link is down.\n"); + jme->phylink = 0; + netif_carrier_off(netdev); + } + +out: + return rc; +} + +static int +jme_setup_tx_resources(struct jme_adapter *jme) +{ + struct jme_ring *txring = &(jme->txring[0]); + + txring->alloc = dma_alloc_coherent(&(jme->pdev->dev), + TX_RING_ALLOC_SIZE(jme->tx_ring_size), + &(txring->dmaalloc), + GFP_ATOMIC); + + if (!txring->alloc) { + txring->desc = NULL; + txring->dmaalloc = 0; + txring->dma = 0; + return -ENOMEM; + } + + /* + * 16 Bytes align + */ + txring->desc = (void *)ALIGN((unsigned long)(txring->alloc), + RING_DESC_ALIGN); + txring->dma = ALIGN(txring->dmaalloc, RING_DESC_ALIGN); + txring->next_to_use = 0; + atomic_set(&txring->next_to_clean, 0); + atomic_set(&txring->nr_free, jme->tx_ring_size); + + /* + * Initialize Transmit Descriptors + */ + memset(txring->alloc, 0, TX_RING_ALLOC_SIZE(jme->tx_ring_size)); + memset(txring->bufinf, 0, + sizeof(struct jme_buffer_info) * jme->tx_ring_size); + + return 0; +} + +static void +jme_free_tx_resources(struct jme_adapter *jme) +{ + int i; + struct jme_ring *txring = &(jme->txring[0]); + struct jme_buffer_info *txbi = txring->bufinf; + + if (txring->alloc) { + for (i = 0 ; i < jme->tx_ring_size ; ++i) { + txbi = txring->bufinf + i; + if (txbi->skb) { + dev_kfree_skb(txbi->skb); + txbi->skb = NULL; + } + txbi->mapping = 0; + txbi->len = 0; + txbi->nr_desc = 0; + txbi->start_xmit = 0; + } + + dma_free_coherent(&(jme->pdev->dev), + TX_RING_ALLOC_SIZE(jme->tx_ring_size), + txring->alloc, + txring->dmaalloc); + + txring->alloc = NULL; + txring->desc = NULL; + txring->dmaalloc = 0; + txring->dma = 0; + } + txring->next_to_use = 0; + atomic_set(&txring->next_to_clean, 0); + atomic_set(&txring->nr_free, 0); + +} + +static inline void +jme_enable_tx_engine(struct jme_adapter *jme) +{ + /* + * Select Queue 0 + */ + jwrite32(jme, JME_TXCS, TXCS_DEFAULT | TXCS_SELECT_QUEUE0); + wmb(); + + /* + * Setup TX Queue 0 DMA Bass Address + */ + jwrite32(jme, JME_TXDBA_LO, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL); + jwrite32(jme, JME_TXDBA_HI, (__u64)(jme->txring[0].dma) >> 32); + jwrite32(jme, JME_TXNDA, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL); + + /* + * Setup TX Descptor Count + */ + jwrite32(jme, JME_TXQDC, jme->tx_ring_size); + + /* + * Enable TX Engine + */ + wmb(); + jwrite32(jme, JME_TXCS, jme->reg_txcs | + TXCS_SELECT_QUEUE0 | + TXCS_ENABLE); + +} + +static inline void +jme_restart_tx_engine(struct jme_adapter *jme) +{ + /* + * Restart TX Engine + */ + jwrite32(jme, JME_TXCS, jme->reg_txcs | + TXCS_SELECT_QUEUE0 | + TXCS_ENABLE); +} + +static inline void +jme_disable_tx_engine(struct jme_adapter *jme) +{ + int i; + u32 val; + + /* + * Disable TX Engine + */ + jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0); + wmb(); + + val = jread32(jme, JME_TXCS); + for (i = JME_TX_DISABLE_TIMEOUT ; (val & TXCS_ENABLE) && i > 0 ; --i) { + mdelay(1); + val = jread32(jme, JME_TXCS); + rmb(); + } + + if (!i) + jeprintk(jme->pdev, "Disable TX engine timeout.\n"); +} + +static void +jme_set_clean_rxdesc(struct jme_adapter *jme, int i) +{ + struct jme_ring *rxring = jme->rxring; + register struct rxdesc *rxdesc = rxring->desc; + struct jme_buffer_info *rxbi = rxring->bufinf; + rxdesc += i; + rxbi += i; + + rxdesc->dw[0] = 0; + rxdesc->dw[1] = 0; + rxdesc->desc1.bufaddrh = cpu_to_le32((__u64)rxbi->mapping >> 32); + rxdesc->desc1.bufaddrl = cpu_to_le32( + (__u64)rxbi->mapping & 0xFFFFFFFFUL); + rxdesc->desc1.datalen = cpu_to_le16(rxbi->len); + if (jme->dev->features & NETIF_F_HIGHDMA) + rxdesc->desc1.flags = RXFLAG_64BIT; + wmb(); + rxdesc->desc1.flags |= RXFLAG_OWN | RXFLAG_INT; +} + +static int +jme_make_new_rx_buf(struct jme_adapter *jme, int i) +{ + struct jme_ring *rxring = &(jme->rxring[0]); + struct jme_buffer_info *rxbi = rxring->bufinf + i; + struct sk_buff *skb; + + skb = netdev_alloc_skb(jme->dev, + jme->dev->mtu + RX_EXTRA_LEN); + if (unlikely(!skb)) + return -ENOMEM; + + rxbi->skb = skb; + rxbi->len = skb_tailroom(skb); + rxbi->mapping = pci_map_page(jme->pdev, + virt_to_page(skb->data), + offset_in_page(skb->data), + rxbi->len, + PCI_DMA_FROMDEVICE); + + return 0; +} + +static void +jme_free_rx_buf(struct jme_adapter *jme, int i) +{ + struct jme_ring *rxring = &(jme->rxring[0]); + struct jme_buffer_info *rxbi = rxring->bufinf; + rxbi += i; + + if (rxbi->skb) { + pci_unmap_page(jme->pdev, + rxbi->mapping, + rxbi->len, + PCI_DMA_FROMDEVICE); + dev_kfree_skb(rxbi->skb); + rxbi->skb = NULL; + rxbi->mapping = 0; + rxbi->len = 0; + } +} + +static void +jme_free_rx_resources(struct jme_adapter *jme) +{ + int i; + struct jme_ring *rxring = &(jme->rxring[0]); + + if (rxring->alloc) { + for (i = 0 ; i < jme->rx_ring_size ; ++i) + jme_free_rx_buf(jme, i); + + dma_free_coherent(&(jme->pdev->dev), + RX_RING_ALLOC_SIZE(jme->rx_ring_size), + rxring->alloc, + rxring->dmaalloc); + rxring->alloc = NULL; + rxring->desc = NULL; + rxring->dmaalloc = 0; + rxring->dma = 0; + } + rxring->next_to_use = 0; + atomic_set(&rxring->next_to_clean, 0); +} + +static int +jme_setup_rx_resources(struct jme_adapter *jme) +{ + int i; + struct jme_ring *rxring = &(jme->rxring[0]); + + rxring->alloc = dma_alloc_coherent(&(jme->pdev->dev), + RX_RING_ALLOC_SIZE(jme->rx_ring_size), + &(rxring->dmaalloc), + GFP_ATOMIC); + if (!rxring->alloc) { + rxring->desc = NULL; + rxring->dmaalloc = 0; + rxring->dma = 0; + return -ENOMEM; + } + + /* + * 16 Bytes align + */ + rxring->desc = (void *)ALIGN((unsigned long)(rxring->alloc), + RING_DESC_ALIGN); + rxring->dma = ALIGN(rxring->dmaalloc, RING_DESC_ALIGN); + rxring->next_to_use = 0; + atomic_set(&rxring->next_to_clean, 0); + + /* + * Initiallize Receive Descriptors + */ + for (i = 0 ; i < jme->rx_ring_size ; ++i) { + if (unlikely(jme_make_new_rx_buf(jme, i))) { + jme_free_rx_resources(jme); + return -ENOMEM; + } + + jme_set_clean_rxdesc(jme, i); + } + + return 0; +} + +static inline void +jme_enable_rx_engine(struct jme_adapter *jme) +{ + /* + * Select Queue 0 + */ + jwrite32(jme, JME_RXCS, jme->reg_rxcs | + RXCS_QUEUESEL_Q0); + wmb(); + + /* + * Setup RX DMA Bass Address + */ + jwrite32(jme, JME_RXDBA_LO, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL); + jwrite32(jme, JME_RXDBA_HI, (__u64)(jme->rxring[0].dma) >> 32); + jwrite32(jme, JME_RXNDA, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL); + + /* + * Setup RX Descriptor Count + */ + jwrite32(jme, JME_RXQDC, jme->rx_ring_size); + + /* + * Setup Unicast Filter + */ + jme_set_multi(jme->dev); + + /* + * Enable RX Engine + */ + wmb(); + jwrite32(jme, JME_RXCS, jme->reg_rxcs | + RXCS_QUEUESEL_Q0 | + RXCS_ENABLE | + RXCS_QST); +} + +static inline void +jme_restart_rx_engine(struct jme_adapter *jme) +{ + /* + * Start RX Engine + */ + jwrite32(jme, JME_RXCS, jme->reg_rxcs | + RXCS_QUEUESEL_Q0 | + RXCS_ENABLE | + RXCS_QST); +} + +static inline void +jme_disable_rx_engine(struct jme_adapter *jme) +{ + int i; + u32 val; + + /* + * Disable RX Engine + */ + jwrite32(jme, JME_RXCS, jme->reg_rxcs); + wmb(); + + val = jread32(jme, JME_RXCS); + for (i = JME_RX_DISABLE_TIMEOUT ; (val & RXCS_ENABLE) && i > 0 ; --i) { + mdelay(1); + val = jread32(jme, JME_RXCS); + rmb(); + } + + if (!i) + jeprintk(jme->pdev, "Disable RX engine timeout.\n"); + +} + +static int +jme_rxsum_ok(struct jme_adapter *jme, u16 flags) +{ + if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) + return false; + + if (unlikely(!(flags & RXWBFLAG_MF) && + (flags & RXWBFLAG_TCPON) && !(flags & RXWBFLAG_TCPCS))) { + msg_rx_err(jme, "TCP Checksum error.\n"); + goto out_sumerr; + } + + if (unlikely(!(flags & RXWBFLAG_MF) && + (flags & RXWBFLAG_UDPON) && !(flags & RXWBFLAG_UDPCS))) { + msg_rx_err(jme, "UDP Checksum error.\n"); + goto out_sumerr; + } + + if (unlikely((flags & RXWBFLAG_IPV4) && !(flags & RXWBFLAG_IPCS))) { + msg_rx_err(jme, "IPv4 Checksum error.\n"); + goto out_sumerr; + } + + return true; + +out_sumerr: + return false; +} + +static void +jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) +{ + struct jme_ring *rxring = &(jme->rxring[0]); + struct rxdesc *rxdesc = rxring->desc; + struct jme_buffer_info *rxbi = rxring->bufinf; + struct sk_buff *skb; + int framesize; + + rxdesc += idx; + rxbi += idx; + + skb = rxbi->skb; + pci_dma_sync_single_for_cpu(jme->pdev, + rxbi->mapping, + rxbi->len, + PCI_DMA_FROMDEVICE); + + if (unlikely(jme_make_new_rx_buf(jme, idx))) { + pci_dma_sync_single_for_device(jme->pdev, + rxbi->mapping, + rxbi->len, + PCI_DMA_FROMDEVICE); + + ++(NET_STAT(jme).rx_dropped); + } else { + framesize = le16_to_cpu(rxdesc->descwb.framesize) + - RX_PREPAD_SIZE; + + skb_reserve(skb, RX_PREPAD_SIZE); + skb_put(skb, framesize); + skb->protocol = eth_type_trans(skb, jme->dev); + + if (jme_rxsum_ok(jme, rxdesc->descwb.flags)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + if (rxdesc->descwb.flags & RXWBFLAG_TAGON) { + if (jme->vlgrp) { + jme->jme_vlan_rx(skb, jme->vlgrp, + le32_to_cpu(rxdesc->descwb.vlan)); + NET_STAT(jme).rx_bytes += 4; + } + } else { + jme->jme_rx(skb); + } + + if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) == + RXWBFLAG_DEST_MUL) + ++(NET_STAT(jme).multicast); + + jme->dev->last_rx = jiffies; + NET_STAT(jme).rx_bytes += framesize; + ++(NET_STAT(jme).rx_packets); + } + + jme_set_clean_rxdesc(jme, idx); + +} + +static int +jme_process_receive(struct jme_adapter *jme, int limit) +{ + struct jme_ring *rxring = &(jme->rxring[0]); + struct rxdesc *rxdesc = rxring->desc; + int i, j, ccnt, desccnt, mask = jme->rx_ring_mask; + + if (unlikely(!atomic_dec_and_test(&jme->rx_cleaning))) + goto out_inc; + + if (unlikely(atomic_read(&jme->link_changing) != 1)) + goto out_inc; + + if (unlikely(!netif_carrier_ok(jme->dev))) + goto out_inc; + + i = atomic_read(&rxring->next_to_clean); + while (limit-- > 0) { + rxdesc = rxring->desc; + rxdesc += i; + + if ((rxdesc->descwb.flags & RXWBFLAG_OWN) || + !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL)) + goto out; + + desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT; + + if (unlikely(desccnt > 1 || + rxdesc->descwb.errstat & RXWBERR_ALLERR)) { + + if (rxdesc->descwb.errstat & RXWBERR_CRCERR) + ++(NET_STAT(jme).rx_crc_errors); + else if (rxdesc->descwb.errstat & RXWBERR_OVERUN) + ++(NET_STAT(jme).rx_fifo_errors); + else + ++(NET_STAT(jme).rx_errors); + + if (desccnt > 1) + limit -= desccnt - 1; + + for (j = i, ccnt = desccnt ; ccnt-- ; ) { + jme_set_clean_rxdesc(jme, j); + j = (j + 1) & (mask); + } + + } else { + jme_alloc_and_feed_skb(jme, i); + } + + i = (i + desccnt) & (mask); + } + +out: + atomic_set(&rxring->next_to_clean, i); + +out_inc: + atomic_inc(&jme->rx_cleaning); + + return limit > 0 ? limit : 0; + +} + +static void +jme_attempt_pcc(struct dynpcc_info *dpi, int atmp) +{ + if (likely(atmp == dpi->cur)) { + dpi->cnt = 0; + return; + } + + if (dpi->attempt == atmp) { + ++(dpi->cnt); + } else { + dpi->attempt = atmp; + dpi->cnt = 0; + } + +} + +static void +jme_dynamic_pcc(struct jme_adapter *jme) +{ + register struct dynpcc_info *dpi = &(jme->dpi); + + if ((NET_STAT(jme).rx_bytes - dpi->last_bytes) > PCC_P3_THRESHOLD) + jme_attempt_pcc(dpi, PCC_P3); + else if ((NET_STAT(jme).rx_packets - dpi->last_pkts) > PCC_P2_THRESHOLD + || dpi->intr_cnt > PCC_INTR_THRESHOLD) + jme_attempt_pcc(dpi, PCC_P2); + else + jme_attempt_pcc(dpi, PCC_P1); + + if (unlikely(dpi->attempt != dpi->cur && dpi->cnt > 5)) { + if (dpi->attempt < dpi->cur) + tasklet_schedule(&jme->rxclean_task); + jme_set_rx_pcc(jme, dpi->attempt); + dpi->cur = dpi->attempt; + dpi->cnt = 0; + } +} + +static void +jme_start_pcc_timer(struct jme_adapter *jme) +{ + struct dynpcc_info *dpi = &(jme->dpi); + dpi->last_bytes = NET_STAT(jme).rx_bytes; + dpi->last_pkts = NET_STAT(jme).rx_packets; + dpi->intr_cnt = 0; + jwrite32(jme, JME_TMCSR, + TMCSR_EN | ((0xFFFFFF - PCC_INTERVAL_US) & TMCSR_CNT)); +} + +static inline void +jme_stop_pcc_timer(struct jme_adapter *jme) +{ + jwrite32(jme, JME_TMCSR, 0); +} + +static void +jme_shutdown_nic(struct jme_adapter *jme) +{ + u32 phylink; + + phylink = jme_linkstat_from_phy(jme); + + if (!(phylink & PHY_LINK_UP)) { + /* + * Disable all interrupt before issue timer + */ + jme_stop_irq(jme); + jwrite32(jme, JME_TIMER2, TMCSR_EN | 0xFFFFFE); + } +} + +static void +jme_pcc_tasklet(unsigned long arg) +{ + struct jme_adapter *jme = (struct jme_adapter *)arg; + struct net_device *netdev = jme->dev; + + if (unlikely(test_bit(JME_FLAG_SHUTDOWN, &jme->flags))) { + jme_shutdown_nic(jme); + return; + } + + if (unlikely(!netif_carrier_ok(netdev) || + (atomic_read(&jme->link_changing) != 1) + )) { + jme_stop_pcc_timer(jme); + return; + } + + if (!(test_bit(JME_FLAG_POLL, &jme->flags))) + jme_dynamic_pcc(jme); + + jme_start_pcc_timer(jme); +} + +static inline void +jme_polling_mode(struct jme_adapter *jme) +{ + jme_set_rx_pcc(jme, PCC_OFF); +} + +static inline void +jme_interrupt_mode(struct jme_adapter *jme) +{ + jme_set_rx_pcc(jme, PCC_P1); +} + +static inline int +jme_pseudo_hotplug_enabled(struct jme_adapter *jme) +{ + u32 apmc; + apmc = jread32(jme, JME_APMC); + return apmc & JME_APMC_PSEUDO_HP_EN; +} + +static void +jme_start_shutdown_timer(struct jme_adapter *jme) +{ + u32 apmc; + + apmc = jread32(jme, JME_APMC) | JME_APMC_PCIE_SD_EN; + apmc &= ~JME_APMC_EPIEN_CTRL; + if (!no_extplug) { + jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_EN); + wmb(); + } + jwrite32f(jme, JME_APMC, apmc); + + jwrite32f(jme, JME_TIMER2, 0); + set_bit(JME_FLAG_SHUTDOWN, &jme->flags); + jwrite32(jme, JME_TMCSR, + TMCSR_EN | ((0xFFFFFF - APMC_PHP_SHUTDOWN_DELAY) & TMCSR_CNT)); +} + +static void +jme_stop_shutdown_timer(struct jme_adapter *jme) +{ + u32 apmc; + + jwrite32f(jme, JME_TMCSR, 0); + jwrite32f(jme, JME_TIMER2, 0); + clear_bit(JME_FLAG_SHUTDOWN, &jme->flags); + + apmc = jread32(jme, JME_APMC); + apmc &= ~(JME_APMC_PCIE_SD_EN | JME_APMC_EPIEN_CTRL); + jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_DIS); + wmb(); + jwrite32f(jme, JME_APMC, apmc); +} + +static void +jme_link_change_tasklet(unsigned long arg) +{ + struct jme_adapter *jme = (struct jme_adapter *)arg; + struct net_device *netdev = jme->dev; + int rc; + + while (!atomic_dec_and_test(&jme->link_changing)) { + atomic_inc(&jme->link_changing); + msg_intr(jme, "Get link change lock failed.\n"); + while (atomic_read(&jme->link_changing) != 1) + msg_intr(jme, "Waiting link change lock.\n"); + } + + if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) + goto out; + + jme->old_mtu = netdev->mtu; + netif_stop_queue(netdev); + if (jme_pseudo_hotplug_enabled(jme)) + jme_stop_shutdown_timer(jme); + + jme_stop_pcc_timer(jme); + tasklet_disable(&jme->txclean_task); + tasklet_disable(&jme->rxclean_task); + tasklet_disable(&jme->rxempty_task); + + if (netif_carrier_ok(netdev)) { + jme_reset_ghc_speed(jme); + jme_disable_rx_engine(jme); + jme_disable_tx_engine(jme); + jme_reset_mac_processor(jme); + jme_free_rx_resources(jme); + jme_free_tx_resources(jme); + + if (test_bit(JME_FLAG_POLL, &jme->flags)) + jme_polling_mode(jme); + + netif_carrier_off(netdev); + } + + jme_check_link(netdev, 0); + if (netif_carrier_ok(netdev)) { + rc = jme_setup_rx_resources(jme); + if (rc) { + jeprintk(jme->pdev, "Allocating resources for RX error" + ", Device STOPPED!\n"); + goto out_enable_tasklet; + } + + rc = jme_setup_tx_resources(jme); + if (rc) { + jeprintk(jme->pdev, "Allocating resources for TX error" + ", Device STOPPED!\n"); + goto err_out_free_rx_resources; + } + + jme_enable_rx_engine(jme); + jme_enable_tx_engine(jme); + + netif_start_queue(netdev); + + if (test_bit(JME_FLAG_POLL, &jme->flags)) + jme_interrupt_mode(jme); + + jme_start_pcc_timer(jme); + } else if (jme_pseudo_hotplug_enabled(jme)) { + jme_start_shutdown_timer(jme); + } + + goto out_enable_tasklet; + +err_out_free_rx_resources: + jme_free_rx_resources(jme); +out_enable_tasklet: + tasklet_enable(&jme->txclean_task); + tasklet_hi_enable(&jme->rxclean_task); + tasklet_hi_enable(&jme->rxempty_task); +out: + atomic_inc(&jme->link_changing); +} + +static void +jme_rx_clean_tasklet(unsigned long arg) +{ + struct jme_adapter *jme = (struct jme_adapter *)arg; + struct dynpcc_info *dpi = &(jme->dpi); + + jme_process_receive(jme, jme->rx_ring_size); + ++(dpi->intr_cnt); + +} + +static int +jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget)) +{ + struct jme_adapter *jme = jme_napi_priv(holder); + struct net_device *netdev = jme->dev; + int rest; + + rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget)); + + while (atomic_read(&jme->rx_empty) > 0) { + atomic_dec(&jme->rx_empty); + ++(NET_STAT(jme).rx_dropped); + jme_restart_rx_engine(jme); + } + atomic_inc(&jme->rx_empty); + + if (rest) { + JME_RX_COMPLETE(netdev, holder); + jme_interrupt_mode(jme); + } + + JME_NAPI_WEIGHT_SET(budget, rest); + return JME_NAPI_WEIGHT_VAL(budget) - rest; +} + +static void +jme_rx_empty_tasklet(unsigned long arg) +{ + struct jme_adapter *jme = (struct jme_adapter *)arg; + + if (unlikely(atomic_read(&jme->link_changing) != 1)) + return; + + if (unlikely(!netif_carrier_ok(jme->dev))) + return; + + msg_rx_status(jme, "RX Queue Full!\n"); + + jme_rx_clean_tasklet(arg); + + while (atomic_read(&jme->rx_empty) > 0) { + atomic_dec(&jme->rx_empty); + ++(NET_STAT(jme).rx_dropped); + jme_restart_rx_engine(jme); + } + atomic_inc(&jme->rx_empty); +} + +static void +jme_wake_queue_if_stopped(struct jme_adapter *jme) +{ + struct jme_ring *txring = jme->txring; + + smp_wmb(); + if (unlikely(netif_queue_stopped(jme->dev) && + atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) { + msg_tx_done(jme, "TX Queue Waked.\n"); + netif_wake_queue(jme->dev); + } + +} + +static void +jme_tx_clean_tasklet(unsigned long arg) +{ + struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_ring *txring = &(jme->txring[0]); + struct txdesc *txdesc = txring->desc; + struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi; + int i, j, cnt = 0, max, err, mask; + + tx_dbg(jme, "Into txclean.\n"); + + if (unlikely(!atomic_dec_and_test(&jme->tx_cleaning))) + goto out; + + if (unlikely(atomic_read(&jme->link_changing) != 1)) + goto out; + + if (unlikely(!netif_carrier_ok(jme->dev))) + goto out; + + max = jme->tx_ring_size - atomic_read(&txring->nr_free); + mask = jme->tx_ring_mask; + + for (i = atomic_read(&txring->next_to_clean) ; cnt < max ; ) { + + ctxbi = txbi + i; + + if (likely(ctxbi->skb && + !(txdesc[i].descwb.flags & TXWBFLAG_OWN))) { + + tx_dbg(jme, "txclean: %d+%d@%lu\n", + i, ctxbi->nr_desc, jiffies); + + err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR; + + for (j = 1 ; j < ctxbi->nr_desc ; ++j) { + ttxbi = txbi + ((i + j) & (mask)); + txdesc[(i + j) & (mask)].dw[0] = 0; + + pci_unmap_page(jme->pdev, + ttxbi->mapping, + ttxbi->len, + PCI_DMA_TODEVICE); + + ttxbi->mapping = 0; + ttxbi->len = 0; + } + + dev_kfree_skb(ctxbi->skb); + + cnt += ctxbi->nr_desc; + + if (unlikely(err)) { + ++(NET_STAT(jme).tx_carrier_errors); + } else { + ++(NET_STAT(jme).tx_packets); + NET_STAT(jme).tx_bytes += ctxbi->len; + } + + ctxbi->skb = NULL; + ctxbi->len = 0; + ctxbi->start_xmit = 0; + + } else { + break; + } + + i = (i + ctxbi->nr_desc) & mask; + + ctxbi->nr_desc = 0; + } + + tx_dbg(jme, "txclean: done %d@%lu.\n", i, jiffies); + atomic_set(&txring->next_to_clean, i); + atomic_add(cnt, &txring->nr_free); + + jme_wake_queue_if_stopped(jme); + +out: + atomic_inc(&jme->tx_cleaning); +} + +static void +jme_intr_msi(struct jme_adapter *jme, u32 intrstat) +{ + /* + * Disable interrupt + */ + jwrite32f(jme, JME_IENC, INTR_ENABLE); + + if (intrstat & (INTR_LINKCH | INTR_SWINTR)) { + /* + * Link change event is critical + * all other events are ignored + */ + jwrite32(jme, JME_IEVE, intrstat); + tasklet_schedule(&jme->linkch_task); + goto out_reenable; + } + + if (intrstat & INTR_TMINTR) { + jwrite32(jme, JME_IEVE, INTR_TMINTR); + tasklet_schedule(&jme->pcc_task); + } + + if (intrstat & (INTR_PCCTXTO | INTR_PCCTX)) { + jwrite32(jme, JME_IEVE, INTR_PCCTXTO | INTR_PCCTX | INTR_TX0); + tasklet_schedule(&jme->txclean_task); + } + + if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) { + jwrite32(jme, JME_IEVE, (intrstat & (INTR_PCCRX0TO | + INTR_PCCRX0 | + INTR_RX0EMP)) | + INTR_RX0); + } + + if (test_bit(JME_FLAG_POLL, &jme->flags)) { + if (intrstat & INTR_RX0EMP) + atomic_inc(&jme->rx_empty); + + if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) { + if (likely(JME_RX_SCHEDULE_PREP(jme))) { + jme_polling_mode(jme); + JME_RX_SCHEDULE(jme); + } + } + } else { + if (intrstat & INTR_RX0EMP) { + atomic_inc(&jme->rx_empty); + tasklet_hi_schedule(&jme->rxempty_task); + } else if (intrstat & (INTR_PCCRX0TO | INTR_PCCRX0)) { + tasklet_hi_schedule(&jme->rxclean_task); + } + } + +out_reenable: + /* + * Re-enable interrupt + */ + jwrite32f(jme, JME_IENS, INTR_ENABLE); +} + +static irqreturn_t +jme_intr(int irq, void *dev_id) +{ + struct net_device *netdev = dev_id; + struct jme_adapter *jme = netdev_priv(netdev); + u32 intrstat; + + intrstat = jread32(jme, JME_IEVE); + + /* + * Check if it's really an interrupt for us + */ + if (unlikely(intrstat == 0)) + return IRQ_NONE; + + /* + * Check if the device still exist + */ + if (unlikely(intrstat == ~((typeof(intrstat))0))) + return IRQ_NONE; + + jme_intr_msi(jme, intrstat); + + return IRQ_HANDLED; +} + +static irqreturn_t +jme_msi(int irq, void *dev_id) +{ + struct net_device *netdev = dev_id; + struct jme_adapter *jme = netdev_priv(netdev); + u32 intrstat; + + pci_dma_sync_single_for_cpu(jme->pdev, + jme->shadow_dma, + sizeof(u32) * SHADOW_REG_NR, + PCI_DMA_FROMDEVICE); + intrstat = jme->shadow_regs[SHADOW_IEVE]; + jme->shadow_regs[SHADOW_IEVE] = 0; + + jme_intr_msi(jme, intrstat); + + return IRQ_HANDLED; +} + +static void +jme_reset_link(struct jme_adapter *jme) +{ + jwrite32(jme, JME_TMCSR, TMCSR_SWIT); +} + +static void +jme_restart_an(struct jme_adapter *jme) +{ + u32 bmcr; + + spin_lock_bh(&jme->phy_lock); + bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); + bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); + spin_unlock_bh(&jme->phy_lock); +} + +static int +jme_request_irq(struct jme_adapter *jme) +{ + int rc; + struct net_device *netdev = jme->dev; + irq_handler_t handler = jme_intr; + int irq_flags = IRQF_SHARED; + + if (!pci_enable_msi(jme->pdev)) { + set_bit(JME_FLAG_MSI, &jme->flags); + handler = jme_msi; + irq_flags = 0; + } + + rc = request_irq(jme->pdev->irq, handler, irq_flags, netdev->name, + netdev); + if (rc) { + jeprintk(jme->pdev, + "Unable to request %s interrupt (return: %d)\n", + test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx", + rc); + + if (test_bit(JME_FLAG_MSI, &jme->flags)) { + pci_disable_msi(jme->pdev); + clear_bit(JME_FLAG_MSI, &jme->flags); + } + } else { + netdev->irq = jme->pdev->irq; + } + + return rc; +} + +static void +jme_free_irq(struct jme_adapter *jme) +{ + free_irq(jme->pdev->irq, jme->dev); + if (test_bit(JME_FLAG_MSI, &jme->flags)) { + pci_disable_msi(jme->pdev); + clear_bit(JME_FLAG_MSI, &jme->flags); + jme->dev->irq = jme->pdev->irq; + } +} + +static int +jme_open(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int rc; + + jme_clear_pm(jme); + JME_NAPI_ENABLE(jme); + + tasklet_enable(&jme->txclean_task); + tasklet_hi_enable(&jme->rxclean_task); + tasklet_hi_enable(&jme->rxempty_task); + + rc = jme_request_irq(jme); + if (rc) + goto err_out; + + jme_enable_shadow(jme); + jme_start_irq(jme); + + if (test_bit(JME_FLAG_SSET, &jme->flags)) + jme_set_settings(netdev, &jme->old_ecmd); + else + jme_reset_phy_processor(jme); + + jme_reset_link(jme); + + return 0; + +err_out: + netif_stop_queue(netdev); + netif_carrier_off(netdev); + return rc; +} + +static void +jme_set_100m_half(struct jme_adapter *jme) +{ + u32 bmcr, tmp; + + bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); + tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | + BMCR_SPEED1000 | BMCR_FULLDPLX); + tmp |= BMCR_SPEED100; + + if (bmcr != tmp) + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, tmp); + + if (jme->fpgaver) + jwrite32(jme, JME_GHC, GHC_SPEED_100M | GHC_LINK_POLL); + else + jwrite32(jme, JME_GHC, GHC_SPEED_100M); +} + +#define JME_WAIT_LINK_TIME 2000 /* 2000ms */ +static void +jme_wait_link(struct jme_adapter *jme) +{ + u32 phylink, to = JME_WAIT_LINK_TIME; + + mdelay(1000); + phylink = jme_linkstat_from_phy(jme); + while (!(phylink & PHY_LINK_UP) && (to -= 10) > 0) { + mdelay(10); + phylink = jme_linkstat_from_phy(jme); + } +} + +static inline void +jme_phy_off(struct jme_adapter *jme) +{ + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN); +} + +static int +jme_close(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + + jme_stop_irq(jme); + jme_disable_shadow(jme); + jme_free_irq(jme); + + JME_NAPI_DISABLE(jme); + + tasklet_kill(&jme->linkch_task); + tasklet_kill(&jme->txclean_task); + tasklet_kill(&jme->rxclean_task); + tasklet_kill(&jme->rxempty_task); + + jme_reset_ghc_speed(jme); + jme_disable_rx_engine(jme); + jme_disable_tx_engine(jme); + jme_reset_mac_processor(jme); + jme_free_rx_resources(jme); + jme_free_tx_resources(jme); + jme->phylink = 0; + jme_phy_off(jme); + + return 0; +} + +static int +jme_alloc_txdesc(struct jme_adapter *jme, + struct sk_buff *skb) +{ + struct jme_ring *txring = jme->txring; + int idx, nr_alloc, mask = jme->tx_ring_mask; + + idx = txring->next_to_use; + nr_alloc = skb_shinfo(skb)->nr_frags + 2; + + if (unlikely(atomic_read(&txring->nr_free) < nr_alloc)) + return -1; + + atomic_sub(nr_alloc, &txring->nr_free); + + txring->next_to_use = (txring->next_to_use + nr_alloc) & mask; + + return idx; +} + +static void +jme_fill_tx_map(struct pci_dev *pdev, + struct txdesc *txdesc, + struct jme_buffer_info *txbi, + struct page *page, + u32 page_offset, + u32 len, + u8 hidma) +{ + dma_addr_t dmaaddr; + + dmaaddr = pci_map_page(pdev, + page, + page_offset, + len, + PCI_DMA_TODEVICE); + + pci_dma_sync_single_for_device(pdev, + dmaaddr, + len, + PCI_DMA_TODEVICE); + + txdesc->dw[0] = 0; + txdesc->dw[1] = 0; + txdesc->desc2.flags = TXFLAG_OWN; + txdesc->desc2.flags |= (hidma) ? TXFLAG_64BIT : 0; + txdesc->desc2.datalen = cpu_to_le16(len); + txdesc->desc2.bufaddrh = cpu_to_le32((__u64)dmaaddr >> 32); + txdesc->desc2.bufaddrl = cpu_to_le32( + (__u64)dmaaddr & 0xFFFFFFFFUL); + + txbi->mapping = dmaaddr; + txbi->len = len; +} + +static void +jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) +{ + struct jme_ring *txring = jme->txring; + struct txdesc *txdesc = txring->desc, *ctxdesc; + struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; + u8 hidma = jme->dev->features & NETIF_F_HIGHDMA; + int i, nr_frags = skb_shinfo(skb)->nr_frags; + int mask = jme->tx_ring_mask; + struct skb_frag_struct *frag; + u32 len; + + for (i = 0 ; i < nr_frags ; ++i) { + frag = &skb_shinfo(skb)->frags[i]; + ctxdesc = txdesc + ((idx + i + 2) & (mask)); + ctxbi = txbi + ((idx + i + 2) & (mask)); + + jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, frag->page, + frag->page_offset, frag->size, hidma); + } + + len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; + ctxdesc = txdesc + ((idx + 1) & (mask)); + ctxbi = txbi + ((idx + 1) & (mask)); + jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), + offset_in_page(skb->data), len, hidma); + +} + +static int +jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) +{ + if (unlikely(skb_shinfo(skb)->gso_size && + skb_header_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) { + dev_kfree_skb(skb); + return -1; + } + + return 0; +} + +static int +jme_tx_tso(struct sk_buff *skb, + u16 *mss, u8 *flags) +{ + *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT; + if (*mss) { + *flags |= TXFLAG_LSEN; + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, + 0); + } else { + struct ipv6hdr *ip6h = ipv6_hdr(skb); + + tcp_hdr(skb)->check = ~csum_ipv6_magic(&ip6h->saddr, + &ip6h->daddr, 0, + IPPROTO_TCP, + 0); + } + + return 0; + } + + return 1; +} + +static void +jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) +{ + if (skb->ip_summed == CHECKSUM_PARTIAL) { + u8 ip_proto; + + switch (skb->protocol) { + case htons(ETH_P_IP): + ip_proto = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): + ip_proto = ipv6_hdr(skb)->nexthdr; + break; + default: + ip_proto = 0; + break; + } + + switch (ip_proto) { + case IPPROTO_TCP: + *flags |= TXFLAG_TCPCS; + break; + case IPPROTO_UDP: + *flags |= TXFLAG_UDPCS; + break; + default: + msg_tx_err(jme, "Error upper layer protocol.\n"); + break; + } + } +} + +static inline void +jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags) +{ + if (vlan_tx_tag_present(skb)) { + *flags |= TXFLAG_TAGON; + *vlan = vlan_tx_tag_get(skb); + } +} + +static int +jme_fill_first_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx) +{ + struct jme_ring *txring = jme->txring; + struct txdesc *txdesc; + struct jme_buffer_info *txbi; + u8 flags; + + txdesc = (struct txdesc *)txring->desc + idx; + txbi = txring->bufinf + idx; + + txdesc->dw[0] = 0; + txdesc->dw[1] = 0; + txdesc->dw[2] = 0; + txdesc->dw[3] = 0; + txdesc->desc1.pktsize = cpu_to_le16(skb->len); + /* + * Set OWN bit at final. + * When kernel transmit faster than NIC. + * And NIC trying to send this descriptor before we tell + * it to start sending this TX queue. + * Other fields are already filled correctly. + */ + wmb(); + flags = TXFLAG_OWN | TXFLAG_INT; + /* + * Set checksum flags while not tso + */ + if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags)) + jme_tx_csum(jme, skb, &flags); + jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags); + txdesc->desc1.flags = flags; + /* + * Set tx buffer info after telling NIC to send + * For better tx_clean timing + */ + wmb(); + txbi->nr_desc = skb_shinfo(skb)->nr_frags + 2; + txbi->skb = skb; + txbi->len = skb->len; + txbi->start_xmit = jiffies; + if (!txbi->start_xmit) + txbi->start_xmit = (0UL-1); + + return 0; +} + +static void +jme_stop_queue_if_full(struct jme_adapter *jme) +{ + struct jme_ring *txring = jme->txring; + struct jme_buffer_info *txbi = txring->bufinf; + int idx = atomic_read(&txring->next_to_clean); + + txbi += idx; + + smp_wmb(); + if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) { + netif_stop_queue(jme->dev); + msg_tx_queued(jme, "TX Queue Paused.\n"); + smp_wmb(); + if (atomic_read(&txring->nr_free) + >= (jme->tx_wake_threshold)) { + netif_wake_queue(jme->dev); + msg_tx_queued(jme, "TX Queue Fast Waked.\n"); + } + } + + if (unlikely(txbi->start_xmit && + (jiffies - txbi->start_xmit) >= TX_TIMEOUT && + txbi->skb)) { + netif_stop_queue(jme->dev); + msg_tx_queued(jme, "TX Queue Stopped %d@%lu.\n", idx, jiffies); + } +} + +/* + * This function is already protected by netif_tx_lock() + */ + +static int +jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int idx; + + if (unlikely(jme_expand_header(jme, skb))) { + ++(NET_STAT(jme).tx_dropped); + return NETDEV_TX_OK; + } + + idx = jme_alloc_txdesc(jme, skb); + + if (unlikely(idx < 0)) { + netif_stop_queue(netdev); + msg_tx_err(jme, "BUG! Tx ring full when queue awake!\n"); + + return NETDEV_TX_BUSY; + } + + jme_map_tx_skb(jme, skb, idx); + jme_fill_first_tx_desc(jme, skb, idx); + + jwrite32(jme, JME_TXCS, jme->reg_txcs | + TXCS_SELECT_QUEUE0 | + TXCS_QUEUE0S | + TXCS_ENABLE); + netdev->trans_start = jiffies; + + tx_dbg(jme, "xmit: %d+%d@%lu\n", idx, + skb_shinfo(skb)->nr_frags + 2, + jiffies); + jme_stop_queue_if_full(jme); + + return NETDEV_TX_OK; +} + +static int +jme_set_macaddr(struct net_device *netdev, void *p) +{ + struct jme_adapter *jme = netdev_priv(netdev); + struct sockaddr *addr = p; + u32 val; + + if (netif_running(netdev)) + return -EBUSY; + + spin_lock_bh(&jme->macaddr_lock); + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + val = (addr->sa_data[3] & 0xff) << 24 | + (addr->sa_data[2] & 0xff) << 16 | + (addr->sa_data[1] & 0xff) << 8 | + (addr->sa_data[0] & 0xff); + jwrite32(jme, JME_RXUMA_LO, val); + val = (addr->sa_data[5] & 0xff) << 8 | + (addr->sa_data[4] & 0xff); + jwrite32(jme, JME_RXUMA_HI, val); + spin_unlock_bh(&jme->macaddr_lock); + + return 0; +} + +static void +jme_set_multi(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 mc_hash[2] = {}; + int i; + + spin_lock_bh(&jme->rxmcs_lock); + + jme->reg_rxmcs |= RXMCS_BRDFRAME | RXMCS_UNIFRAME; + + if (netdev->flags & IFF_PROMISC) { + jme->reg_rxmcs |= RXMCS_ALLFRAME; + } else if (netdev->flags & IFF_ALLMULTI) { + jme->reg_rxmcs |= RXMCS_ALLMULFRAME; + } else if (netdev->flags & IFF_MULTICAST) { + struct dev_mc_list *mclist; + int bit_nr; + + jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; + for (i = 0, mclist = netdev->mc_list; + mclist && i < netdev->mc_count; + ++i, mclist = mclist->next) { + + bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; + mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); + } + + jwrite32(jme, JME_RXMCHT_LO, mc_hash[0]); + jwrite32(jme, JME_RXMCHT_HI, mc_hash[1]); + } + + wmb(); + jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); + + spin_unlock_bh(&jme->rxmcs_lock); +} + +static int +jme_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + if (new_mtu == jme->old_mtu) + return 0; + + if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || + ((new_mtu) < IPV6_MIN_MTU)) + return -EINVAL; + + if (new_mtu > 4000) { + jme->reg_rxcs &= ~RXCS_FIFOTHNP; + jme->reg_rxcs |= RXCS_FIFOTHNP_64QW; + jme_restart_rx_engine(jme); + } else { + jme->reg_rxcs &= ~RXCS_FIFOTHNP; + jme->reg_rxcs |= RXCS_FIFOTHNP_128QW; + jme_restart_rx_engine(jme); + } + + if (new_mtu > 1900) { + netdev->features &= ~(NETIF_F_HW_CSUM | + NETIF_F_TSO | + NETIF_F_TSO6); + } else { + if (test_bit(JME_FLAG_TXCSUM, &jme->flags)) + netdev->features |= NETIF_F_HW_CSUM; + if (test_bit(JME_FLAG_TSO, &jme->flags)) + netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; + } + + netdev->mtu = new_mtu; + jme_reset_link(jme); + + return 0; +} + +static void +jme_tx_timeout(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + jme->phylink = 0; + jme_reset_phy_processor(jme); + if (test_bit(JME_FLAG_SSET, &jme->flags)) + jme_set_settings(netdev, &jme->old_ecmd); + + /* + * Force to Reset the link again + */ + jme_reset_link(jme); +} + +static void +jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + jme->vlgrp = grp; +} + +static void +jme_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(jme->pdev)); +} + +static int +jme_get_regs_len(struct net_device *netdev) +{ + return JME_REG_LEN; +} + +static void +mmapio_memcpy(struct jme_adapter *jme, u32 *p, u32 reg, int len) +{ + int i; + + for (i = 0 ; i < len ; i += 4) + p[i >> 2] = jread32(jme, reg + i); +} + +static void +mdio_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr) +{ + int i; + u16 *p16 = (u16 *)p; + + for (i = 0 ; i < reg_nr ; ++i) + p16[i] = jme_mdio_read(jme->dev, jme->mii_if.phy_id, i); +} + +static void +jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 *p32 = (u32 *)p; + + memset(p, 0xFF, JME_REG_LEN); + + regs->version = 1; + mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN); + + p32 += 0x100 >> 2; + mmapio_memcpy(jme, p32, JME_PHY, JME_PHY_LEN); + + p32 += 0x100 >> 2; + mmapio_memcpy(jme, p32, JME_MISC, JME_MISC_LEN); + + p32 += 0x100 >> 2; + mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN); + + p32 += 0x100 >> 2; + mdio_memcpy(jme, p32, JME_PHY_REG_NR); +} + +static int +jme_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + ecmd->tx_coalesce_usecs = PCC_TX_TO; + ecmd->tx_max_coalesced_frames = PCC_TX_CNT; + + if (test_bit(JME_FLAG_POLL, &jme->flags)) { + ecmd->use_adaptive_rx_coalesce = false; + ecmd->rx_coalesce_usecs = 0; + ecmd->rx_max_coalesced_frames = 0; + return 0; + } + + ecmd->use_adaptive_rx_coalesce = true; + + switch (jme->dpi.cur) { + case PCC_P1: + ecmd->rx_coalesce_usecs = PCC_P1_TO; + ecmd->rx_max_coalesced_frames = PCC_P1_CNT; + break; + case PCC_P2: + ecmd->rx_coalesce_usecs = PCC_P2_TO; + ecmd->rx_max_coalesced_frames = PCC_P2_CNT; + break; + case PCC_P3: + ecmd->rx_coalesce_usecs = PCC_P3_TO; + ecmd->rx_max_coalesced_frames = PCC_P3_CNT; + break; + default: + break; + } + + return 0; +} + +static int +jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + struct dynpcc_info *dpi = &(jme->dpi); + + if (netif_running(netdev)) + return -EBUSY; + + if (ecmd->use_adaptive_rx_coalesce + && test_bit(JME_FLAG_POLL, &jme->flags)) { + clear_bit(JME_FLAG_POLL, &jme->flags); + jme->jme_rx = netif_rx; + jme->jme_vlan_rx = vlan_hwaccel_rx; + dpi->cur = PCC_P1; + dpi->attempt = PCC_P1; + dpi->cnt = 0; + jme_set_rx_pcc(jme, PCC_P1); + jme_interrupt_mode(jme); + } else if (!(ecmd->use_adaptive_rx_coalesce) + && !(test_bit(JME_FLAG_POLL, &jme->flags))) { + set_bit(JME_FLAG_POLL, &jme->flags); + jme->jme_rx = netif_receive_skb; + jme->jme_vlan_rx = vlan_hwaccel_receive_skb; + jme_interrupt_mode(jme); + } + + return 0; +} + +static void +jme_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 val; + + ecmd->tx_pause = (jme->reg_txpfc & TXPFC_PF_EN) != 0; + ecmd->rx_pause = (jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0; + + spin_lock_bh(&jme->phy_lock); + val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); + spin_unlock_bh(&jme->phy_lock); + + ecmd->autoneg = + (val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0; +} + +static int +jme_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 val; + + if (((jme->reg_txpfc & TXPFC_PF_EN) != 0) ^ + (ecmd->tx_pause != 0)) { + + if (ecmd->tx_pause) + jme->reg_txpfc |= TXPFC_PF_EN; + else + jme->reg_txpfc &= ~TXPFC_PF_EN; + + jwrite32(jme, JME_TXPFC, jme->reg_txpfc); + } + + spin_lock_bh(&jme->rxmcs_lock); + if (((jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0) ^ + (ecmd->rx_pause != 0)) { + + if (ecmd->rx_pause) + jme->reg_rxmcs |= RXMCS_FLOWCTRL; + else + jme->reg_rxmcs &= ~RXMCS_FLOWCTRL; + + jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); + } + spin_unlock_bh(&jme->rxmcs_lock); + + spin_lock_bh(&jme->phy_lock); + val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); + if (((val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0) ^ + (ecmd->autoneg != 0)) { + + if (ecmd->autoneg) + val |= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + else + val &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + + jme_mdio_write(jme->dev, jme->mii_if.phy_id, + MII_ADVERTISE, val); + } + spin_unlock_bh(&jme->phy_lock); + + return 0; +} + +static void +jme_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + wol->supported = WAKE_MAGIC | WAKE_PHY; + + wol->wolopts = 0; + + if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) + wol->wolopts |= WAKE_PHY; + + if (jme->reg_pmcs & PMCS_MFEN) + wol->wolopts |= WAKE_MAGIC; + +} + +static int +jme_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_MAGICSECURE | + WAKE_UCAST | + WAKE_MCAST | + WAKE_BCAST | + WAKE_ARP)) + return -EOPNOTSUPP; + + jme->reg_pmcs = 0; + + if (wol->wolopts & WAKE_PHY) + jme->reg_pmcs |= PMCS_LFEN | PMCS_LREN; + + if (wol->wolopts & WAKE_MAGIC) + jme->reg_pmcs |= PMCS_MFEN; + + jwrite32(jme, JME_PMCS, jme->reg_pmcs); + + return 0; +} + +static int +jme_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int rc; + + spin_lock_bh(&jme->phy_lock); + rc = mii_ethtool_gset(&(jme->mii_if), ecmd); + spin_unlock_bh(&jme->phy_lock); + return rc; +} + +static int +jme_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int rc, fdc = 0; + + if (ecmd->speed == SPEED_1000 && ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + if (jme->mii_if.force_media && + ecmd->autoneg != AUTONEG_ENABLE && + (jme->mii_if.full_duplex != ecmd->duplex)) + fdc = 1; + + spin_lock_bh(&jme->phy_lock); + rc = mii_ethtool_sset(&(jme->mii_if), ecmd); + spin_unlock_bh(&jme->phy_lock); + + if (!rc && fdc) + jme_reset_link(jme); + + if (!rc) { + set_bit(JME_FLAG_SSET, &jme->flags); + jme->old_ecmd = *ecmd; + } + + return rc; +} + +static u32 +jme_get_link(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + return jread32(jme, JME_PHY_LINK) & PHY_LINK_UP; +} + +static u32 +jme_get_msglevel(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + return jme->msg_enable; +} + +static void +jme_set_msglevel(struct net_device *netdev, u32 value) +{ + struct jme_adapter *jme = netdev_priv(netdev); + jme->msg_enable = value; +} + +static u32 +jme_get_rx_csum(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + return jme->reg_rxmcs & RXMCS_CHECKSUM; +} + +static int +jme_set_rx_csum(struct net_device *netdev, u32 on) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + spin_lock_bh(&jme->rxmcs_lock); + if (on) + jme->reg_rxmcs |= RXMCS_CHECKSUM; + else + jme->reg_rxmcs &= ~RXMCS_CHECKSUM; + jwrite32(jme, JME_RXMCS, jme->reg_rxmcs); + spin_unlock_bh(&jme->rxmcs_lock); + + return 0; +} + +static int +jme_set_tx_csum(struct net_device *netdev, u32 on) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + if (on) { + set_bit(JME_FLAG_TXCSUM, &jme->flags); + if (netdev->mtu <= 1900) + netdev->features |= NETIF_F_HW_CSUM; + } else { + clear_bit(JME_FLAG_TXCSUM, &jme->flags); + netdev->features &= ~NETIF_F_HW_CSUM; + } + + return 0; +} + +static int +jme_set_tso(struct net_device *netdev, u32 on) +{ + struct jme_adapter *jme = netdev_priv(netdev); + + if (on) { + set_bit(JME_FLAG_TSO, &jme->flags); + if (netdev->mtu <= 1900) + netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; + } else { + clear_bit(JME_FLAG_TSO, &jme->flags); + netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + } + + return 0; +} + +static int +jme_nway_reset(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + jme_restart_an(jme); + return 0; +} + +static u8 +jme_smb_read(struct jme_adapter *jme, unsigned int addr) +{ + u32 val; + int to; + + val = jread32(jme, JME_SMBCSR); + to = JME_SMB_BUSY_TIMEOUT; + while ((val & SMBCSR_BUSY) && --to) { + msleep(1); + val = jread32(jme, JME_SMBCSR); + } + if (!to) { + msg_hw(jme, "SMB Bus Busy.\n"); + return 0xFF; + } + + jwrite32(jme, JME_SMBINTF, + ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | + SMBINTF_HWRWN_READ | + SMBINTF_HWCMD); + + val = jread32(jme, JME_SMBINTF); + to = JME_SMB_BUSY_TIMEOUT; + while ((val & SMBINTF_HWCMD) && --to) { + msleep(1); + val = jread32(jme, JME_SMBINTF); + } + if (!to) { + msg_hw(jme, "SMB Bus Busy.\n"); + return 0xFF; + } + + return (val & SMBINTF_HWDATR) >> SMBINTF_HWDATR_SHIFT; +} + +static void +jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data) +{ + u32 val; + int to; + + val = jread32(jme, JME_SMBCSR); + to = JME_SMB_BUSY_TIMEOUT; + while ((val & SMBCSR_BUSY) && --to) { + msleep(1); + val = jread32(jme, JME_SMBCSR); + } + if (!to) { + msg_hw(jme, "SMB Bus Busy.\n"); + return; + } + + jwrite32(jme, JME_SMBINTF, + ((data << SMBINTF_HWDATW_SHIFT) & SMBINTF_HWDATW) | + ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | + SMBINTF_HWRWN_WRITE | + SMBINTF_HWCMD); + + val = jread32(jme, JME_SMBINTF); + to = JME_SMB_BUSY_TIMEOUT; + while ((val & SMBINTF_HWCMD) && --to) { + msleep(1); + val = jread32(jme, JME_SMBINTF); + } + if (!to) { + msg_hw(jme, "SMB Bus Busy.\n"); + return; + } + + mdelay(2); +} + +static int +jme_get_eeprom_len(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 val; + val = jread32(jme, JME_SMBCSR); + return (val & SMBCSR_EEPROMD) ? JME_SMB_LEN : 0; +} + +static int +jme_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i, offset = eeprom->offset, len = eeprom->len; + + /* + * ethtool will check the boundary for us + */ + eeprom->magic = JME_EEPROM_MAGIC; + for (i = 0 ; i < len ; ++i) + data[i] = jme_smb_read(jme, i + offset); + + return 0; +} + +static int +jme_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i, offset = eeprom->offset, len = eeprom->len; + + if (eeprom->magic != JME_EEPROM_MAGIC) + return -EINVAL; + + /* + * ethtool will check the boundary for us + */ + for (i = 0 ; i < len ; ++i) + jme_smb_write(jme, i + offset, data[i]); + + return 0; +} + +static const struct ethtool_ops jme_ethtool_ops = { + .get_drvinfo = jme_get_drvinfo, + .get_regs_len = jme_get_regs_len, + .get_regs = jme_get_regs, + .get_coalesce = jme_get_coalesce, + .set_coalesce = jme_set_coalesce, + .get_pauseparam = jme_get_pauseparam, + .set_pauseparam = jme_set_pauseparam, + .get_wol = jme_get_wol, + .set_wol = jme_set_wol, + .get_settings = jme_get_settings, + .set_settings = jme_set_settings, + .get_link = jme_get_link, + .get_msglevel = jme_get_msglevel, + .set_msglevel = jme_set_msglevel, + .get_rx_csum = jme_get_rx_csum, + .set_rx_csum = jme_set_rx_csum, + .set_tx_csum = jme_set_tx_csum, + .set_tso = jme_set_tso, + .set_sg = ethtool_op_set_sg, + .nway_reset = jme_nway_reset, + .get_eeprom_len = jme_get_eeprom_len, + .get_eeprom = jme_get_eeprom, + .set_eeprom = jme_set_eeprom, +}; + +static int +jme_pci_dma64(struct pci_dev *pdev) +{ + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + return 1; + + if (!pci_set_dma_mask(pdev, DMA_40BIT_MASK)) + if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK)) + return 1; + + if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) + return 0; + + return -1; +} + +static inline void +jme_phy_init(struct jme_adapter *jme) +{ + u16 reg26; + + reg26 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 26); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, 26, reg26 | 0x1000); +} + +static inline void +jme_check_hw_ver(struct jme_adapter *jme) +{ + u32 chipmode; + + chipmode = jread32(jme, JME_CHIPMODE); + + jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT; + jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT; +} + +static int __devinit +jme_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rc = 0, using_dac, i; + struct net_device *netdev; + struct jme_adapter *jme; + u16 bmcr, bmsr; + u32 apmc; + + /* + * set up PCI device basics + */ + rc = pci_enable_device(pdev); + if (rc) { + jeprintk(pdev, "Cannot enable PCI device.\n"); + goto err_out; + } + + using_dac = jme_pci_dma64(pdev); + if (using_dac < 0) { + jeprintk(pdev, "Cannot set PCI DMA Mask.\n"); + rc = -EIO; + goto err_out_disable_pdev; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + jeprintk(pdev, "No PCI resource region found.\n"); + rc = -ENOMEM; + goto err_out_disable_pdev; + } + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) { + jeprintk(pdev, "Cannot obtain PCI resource region.\n"); + goto err_out_disable_pdev; + } + + pci_set_master(pdev); + + /* + * alloc and init net device + */ + netdev = alloc_etherdev(sizeof(*jme)); + if (!netdev) { + jeprintk(pdev, "Cannot allocate netdev structure.\n"); + rc = -ENOMEM; + goto err_out_release_regions; + } + netdev->open = jme_open; + netdev->stop = jme_close; + netdev->hard_start_xmit = jme_start_xmit; + netdev->set_mac_address = jme_set_macaddr; + netdev->set_multicast_list = jme_set_multi; + netdev->change_mtu = jme_change_mtu; + netdev->ethtool_ops = &jme_ethtool_ops; + netdev->tx_timeout = jme_tx_timeout; + netdev->watchdog_timeo = TX_TIMEOUT; + netdev->vlan_rx_register = jme_vlan_rx_register; + NETDEV_GET_STATS(netdev, &jme_get_stats); + netdev->features = NETIF_F_HW_CSUM | + NETIF_F_SG | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX; + if (using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + SET_NETDEV_DEV(netdev, &pdev->dev); + pci_set_drvdata(pdev, netdev); + + /* + * init adapter info + */ + jme = netdev_priv(netdev); + jme->pdev = pdev; + jme->dev = netdev; + jme->jme_rx = netif_rx; + jme->jme_vlan_rx = vlan_hwaccel_rx; + jme->old_mtu = netdev->mtu = 1500; + jme->phylink = 0; + jme->tx_ring_size = 1 << 10; + jme->tx_ring_mask = jme->tx_ring_size - 1; + jme->tx_wake_threshold = 1 << 9; + jme->rx_ring_size = 1 << 9; + jme->rx_ring_mask = jme->rx_ring_size - 1; + jme->msg_enable = JME_DEF_MSG_ENABLE; + jme->regs = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!(jme->regs)) { + jeprintk(pdev, "Mapping PCI resource region error.\n"); + rc = -ENOMEM; + goto err_out_free_netdev; + } + jme->shadow_regs = pci_alloc_consistent(pdev, + sizeof(u32) * SHADOW_REG_NR, + &(jme->shadow_dma)); + if (!(jme->shadow_regs)) { + jeprintk(pdev, "Allocating shadow register mapping error.\n"); + rc = -ENOMEM; + goto err_out_unmap; + } + + if (no_pseudohp) { + apmc = jread32(jme, JME_APMC) & ~JME_APMC_PSEUDO_HP_EN; + jwrite32(jme, JME_APMC, apmc); + } else if (force_pseudohp) { + apmc = jread32(jme, JME_APMC) | JME_APMC_PSEUDO_HP_EN; + jwrite32(jme, JME_APMC, apmc); + } + + NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, jme->rx_ring_size >> 2) + + spin_lock_init(&jme->phy_lock); + spin_lock_init(&jme->macaddr_lock); + spin_lock_init(&jme->rxmcs_lock); + + atomic_set(&jme->link_changing, 1); + atomic_set(&jme->rx_cleaning, 1); + atomic_set(&jme->tx_cleaning, 1); + atomic_set(&jme->rx_empty, 1); + + tasklet_init(&jme->pcc_task, + &jme_pcc_tasklet, + (unsigned long) jme); + tasklet_init(&jme->linkch_task, + &jme_link_change_tasklet, + (unsigned long) jme); + tasklet_init(&jme->txclean_task, + &jme_tx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxclean_task, + &jme_rx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxempty_task, + &jme_rx_empty_tasklet, + (unsigned long) jme); + tasklet_disable_nosync(&jme->txclean_task); + tasklet_disable_nosync(&jme->rxclean_task); + tasklet_disable_nosync(&jme->rxempty_task); + jme->dpi.cur = PCC_P1; + + jme->reg_ghc = 0; + jme->reg_rxcs = RXCS_DEFAULT; + jme->reg_rxmcs = RXMCS_DEFAULT; + jme->reg_txpfc = 0; + jme->reg_pmcs = PMCS_MFEN; + set_bit(JME_FLAG_TXCSUM, &jme->flags); + set_bit(JME_FLAG_TSO, &jme->flags); + + /* + * Get Max Read Req Size from PCI Config Space + */ + pci_read_config_byte(pdev, PCI_DCSR_MRRS, &jme->mrrs); + jme->mrrs &= PCI_DCSR_MRRS_MASK; + switch (jme->mrrs) { + case MRRS_128B: + jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_128B; + break; + case MRRS_256B: + jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_256B; + break; + default: + jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_512B; + break; + }; + + /* + * Must check before reset_mac_processor + */ + jme_check_hw_ver(jme); + jme->mii_if.dev = netdev; + if (jme->fpgaver) { + jme->mii_if.phy_id = 0; + for (i = 1 ; i < 32 ; ++i) { + bmcr = jme_mdio_read(netdev, i, MII_BMCR); + bmsr = jme_mdio_read(netdev, i, MII_BMSR); + if (bmcr != 0xFFFFU && (bmcr != 0 || bmsr != 0)) { + jme->mii_if.phy_id = i; + break; + } + } + + if (!jme->mii_if.phy_id) { + rc = -EIO; + jeprintk(pdev, "Can not find phy_id.\n"); + goto err_out_free_shadow; + } + + jme->reg_ghc |= GHC_LINK_POLL; + } else { + jme->mii_if.phy_id = 1; + } + if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) + jme->mii_if.supports_gmii = true; + else + jme->mii_if.supports_gmii = false; + jme->mii_if.mdio_read = jme_mdio_read; + jme->mii_if.mdio_write = jme_mdio_write; + + jme_clear_pm(jme); + jme_set_phyfifoa(jme); + pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->rev); + if (!jme->fpgaver) + jme_phy_init(jme); + jme_phy_off(jme); + + /* + * Reset MAC processor and reload EEPROM for MAC Address + */ + jme_reset_mac_processor(jme); + rc = jme_reload_eeprom(jme); + if (rc) { + jeprintk(pdev, + "Reload eeprom for reading MAC Address error.\n"); + goto err_out_free_shadow; + } + jme_load_macaddr(netdev); + + /* + * Tell stack that we are not ready to work until open() + */ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + /* + * Register netdev + */ + rc = register_netdev(netdev); + if (rc) { + jeprintk(pdev, "Cannot register net device.\n"); + goto err_out_free_shadow; + } + + msg_probe(jme, + "JMC250 gigabit%s ver:%x rev:%x " + "macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", + (jme->fpgaver != 0) ? " (FPGA)" : "", + (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, + jme->rev, + netdev->dev_addr[0], + netdev->dev_addr[1], + netdev->dev_addr[2], + netdev->dev_addr[3], + netdev->dev_addr[4], + netdev->dev_addr[5]); + + return 0; + +err_out_free_shadow: + pci_free_consistent(pdev, + sizeof(u32) * SHADOW_REG_NR, + jme->shadow_regs, + jme->shadow_dma); +err_out_unmap: + iounmap(jme->regs); +err_out_free_netdev: + pci_set_drvdata(pdev, NULL); + free_netdev(netdev); +err_out_release_regions: + pci_release_regions(pdev); +err_out_disable_pdev: + pci_disable_device(pdev); +err_out: + return rc; +} + +static void __devexit +jme_remove_one(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); + + unregister_netdev(netdev); + pci_free_consistent(pdev, + sizeof(u32) * SHADOW_REG_NR, + jme->shadow_regs, + jme->shadow_dma); + iounmap(jme->regs); + pci_set_drvdata(pdev, NULL); + free_netdev(netdev); + pci_release_regions(pdev); + pci_disable_device(pdev); + +} + +static int +jme_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); + + atomic_dec(&jme->link_changing); + + netif_device_detach(netdev); + netif_stop_queue(netdev); + jme_stop_irq(jme); + + tasklet_disable(&jme->txclean_task); + tasklet_disable(&jme->rxclean_task); + tasklet_disable(&jme->rxempty_task); + + jme_disable_shadow(jme); + + if (netif_carrier_ok(netdev)) { + if (test_bit(JME_FLAG_POLL, &jme->flags)) + jme_polling_mode(jme); + + jme_stop_pcc_timer(jme); + jme_reset_ghc_speed(jme); + jme_disable_rx_engine(jme); + jme_disable_tx_engine(jme); + jme_reset_mac_processor(jme); + jme_free_rx_resources(jme); + jme_free_tx_resources(jme); + netif_carrier_off(netdev); + jme->phylink = 0; + } + + tasklet_enable(&jme->txclean_task); + tasklet_hi_enable(&jme->rxclean_task); + tasklet_hi_enable(&jme->rxempty_task); + + pci_save_state(pdev); + if (jme->reg_pmcs) { + jme_set_100m_half(jme); + + if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) + jme_wait_link(jme); + + jwrite32(jme, JME_PMCS, jme->reg_pmcs); + + pci_enable_wake(pdev, PCI_D3cold, true); + } else { + jme_phy_off(jme); + } + pci_set_power_state(pdev, PCI_D3cold); + + return 0; +} + +static int +jme_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); + + jme_clear_pm(jme); + pci_restore_state(pdev); + + if (test_bit(JME_FLAG_SSET, &jme->flags)) + jme_set_settings(netdev, &jme->old_ecmd); + else + jme_reset_phy_processor(jme); + + jme_enable_shadow(jme); + jme_start_irq(jme); + netif_device_attach(netdev); + + atomic_inc(&jme->link_changing); + + jme_reset_link(jme); + + return 0; +} + +static struct pci_device_id jme_pci_tbl[] = { + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, + { } +}; + +static struct pci_driver jme_driver = { + .name = DRV_NAME, + .id_table = jme_pci_tbl, + .probe = jme_init_one, + .remove = __devexit_p(jme_remove_one), +#ifdef CONFIG_PM + .suspend = jme_suspend, + .resume = jme_resume, +#endif /* CONFIG_PM */ +}; + +static int __init +jme_init_module(void) +{ + printk(KERN_INFO PFX "JMicron JMC250 gigabit ethernet " + "driver version %s\n", DRV_VERSION); + return pci_register_driver(&jme_driver); +} + +static void __exit +jme_cleanup_module(void) +{ + pci_unregister_driver(&jme_driver); +} + +module_init(jme_init_module); +module_exit(jme_cleanup_module); + +MODULE_AUTHOR("Guo-Fu Tseng "); +MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_DEVICE_TABLE(pci, jme_pci_tbl); + diff --git a/drivers/net/jme.h b/drivers/net/jme.h new file mode 100644 index 00000000000..b29688431a6 --- /dev/null +++ b/drivers/net/jme.h @@ -0,0 +1,1199 @@ +/* + * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver + * + * Copyright 2008 JMicron Technology Corporation + * http://www.jmicron.com/ + * + * Author: Guo-Fu Tseng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __JME_H_INCLUDED__ +#define __JME_H_INCLUDEE__ + +#define DRV_NAME "jme" +#define DRV_VERSION "1.0.2" +#define PFX DRV_NAME ": " + +#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250 +#define PCI_DEVICE_ID_JMICRON_JMC260 0x0260 + +/* + * Message related definitions + */ +#define JME_DEF_MSG_ENABLE \ + (NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR | \ + NETIF_MSG_HW) + +#define jeprintk(pdev, fmt, args...) \ + printk(KERN_ERR PFX fmt, ## args) + +#ifdef TX_DEBUG +#define tx_dbg(priv, fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ## args) +#else +#define tx_dbg(priv, fmt, args...) +#endif + +#define jme_msg(msglvl, type, priv, fmt, args...) \ + if (netif_msg_##type(priv)) \ + printk(msglvl "%s: " fmt, (priv)->dev->name, ## args) + +#define msg_probe(priv, fmt, args...) \ + jme_msg(KERN_INFO, probe, priv, fmt, ## args) + +#define msg_link(priv, fmt, args...) \ + jme_msg(KERN_INFO, link, priv, fmt, ## args) + +#define msg_intr(priv, fmt, args...) \ + jme_msg(KERN_INFO, intr, priv, fmt, ## args) + +#define msg_rx_err(priv, fmt, args...) \ + jme_msg(KERN_ERR, rx_err, priv, fmt, ## args) + +#define msg_rx_status(priv, fmt, args...) \ + jme_msg(KERN_INFO, rx_status, priv, fmt, ## args) + +#define msg_tx_err(priv, fmt, args...) \ + jme_msg(KERN_ERR, tx_err, priv, fmt, ## args) + +#define msg_tx_done(priv, fmt, args...) \ + jme_msg(KERN_INFO, tx_done, priv, fmt, ## args) + +#define msg_tx_queued(priv, fmt, args...) \ + jme_msg(KERN_INFO, tx_queued, priv, fmt, ## args) + +#define msg_hw(priv, fmt, args...) \ + jme_msg(KERN_ERR, hw, priv, fmt, ## args) + +/* + * Extra PCI Configuration space interface + */ +#define PCI_DCSR_MRRS 0x59 +#define PCI_DCSR_MRRS_MASK 0x70 + +enum pci_dcsr_mrrs_vals { + MRRS_128B = 0x00, + MRRS_256B = 0x10, + MRRS_512B = 0x20, + MRRS_1024B = 0x30, + MRRS_2048B = 0x40, + MRRS_4096B = 0x50, +}; + +#define PCI_SPI 0xB0 + +enum pci_spi_bits { + SPI_EN = 0x10, + SPI_MISO = 0x08, + SPI_MOSI = 0x04, + SPI_SCLK = 0x02, + SPI_CS = 0x01, +}; + +struct jme_spi_op { + void __user *uwbuf; + void __user *urbuf; + __u8 wn; /* Number of write actions */ + __u8 rn; /* Number of read actions */ + __u8 bitn; /* Number of bits per action */ + __u8 spd; /* The maxim acceptable speed of controller, in MHz.*/ + __u8 mode; /* CPOL, CPHA, and Duplex mode of SPI */ + + /* Internal use only */ + u8 *kwbuf; + u8 *krbuf; + u8 sr; + u16 halfclk; /* Half of clock cycle calculated from spd, in ns */ +}; + +enum jme_spi_op_bits { + SPI_MODE_CPHA = 0x01, + SPI_MODE_CPOL = 0x02, + SPI_MODE_DUP = 0x80, +}; + +#define HALF_US 500 /* 500 ns */ +#define JMESPIIOCTL SIOCDEVPRIVATE + +/* + * Dynamic(adaptive)/Static PCC values + */ +enum dynamic_pcc_values { + PCC_OFF = 0, + PCC_P1 = 1, + PCC_P2 = 2, + PCC_P3 = 3, + + PCC_OFF_TO = 0, + PCC_P1_TO = 1, + PCC_P2_TO = 64, + PCC_P3_TO = 128, + + PCC_OFF_CNT = 0, + PCC_P1_CNT = 1, + PCC_P2_CNT = 16, + PCC_P3_CNT = 32, +}; +struct dynpcc_info { + unsigned long last_bytes; + unsigned long last_pkts; + unsigned long intr_cnt; + unsigned char cur; + unsigned char attempt; + unsigned char cnt; +}; +#define PCC_INTERVAL_US 100000 +#define PCC_INTERVAL (HZ / (1000000 / PCC_INTERVAL_US)) +#define PCC_P3_THRESHOLD (2 * 1024 * 1024) +#define PCC_P2_THRESHOLD 800 +#define PCC_INTR_THRESHOLD 800 +#define PCC_TX_TO 1000 +#define PCC_TX_CNT 8 + +/* + * TX/RX Descriptors + * + * TX/RX Ring DESC Count Must be multiple of 16 and <= 1024 + */ +#define RING_DESC_ALIGN 16 /* Descriptor alignment */ +#define TX_DESC_SIZE 16 +#define TX_RING_NR 8 +#define TX_RING_ALLOC_SIZE(s) ((s * TX_DESC_SIZE) + RING_DESC_ALIGN) + +struct txdesc { + union { + __u8 all[16]; + __le32 dw[4]; + struct { + /* DW0 */ + __le16 vlan; + __u8 rsv1; + __u8 flags; + + /* DW1 */ + __le16 datalen; + __le16 mss; + + /* DW2 */ + __le16 pktsize; + __le16 rsv2; + + /* DW3 */ + __le32 bufaddr; + } desc1; + struct { + /* DW0 */ + __le16 rsv1; + __u8 rsv2; + __u8 flags; + + /* DW1 */ + __le16 datalen; + __le16 rsv3; + + /* DW2 */ + __le32 bufaddrh; + + /* DW3 */ + __le32 bufaddrl; + } desc2; + struct { + /* DW0 */ + __u8 ehdrsz; + __u8 rsv1; + __u8 rsv2; + __u8 flags; + + /* DW1 */ + __le16 trycnt; + __le16 segcnt; + + /* DW2 */ + __le16 pktsz; + __le16 rsv3; + + /* DW3 */ + __le32 bufaddrl; + } descwb; + }; +}; + +enum jme_txdesc_flags_bits { + TXFLAG_OWN = 0x80, + TXFLAG_INT = 0x40, + TXFLAG_64BIT = 0x20, + TXFLAG_TCPCS = 0x10, + TXFLAG_UDPCS = 0x08, + TXFLAG_IPCS = 0x04, + TXFLAG_LSEN = 0x02, + TXFLAG_TAGON = 0x01, +}; + +#define TXDESC_MSS_SHIFT 2 +enum jme_rxdescwb_flags_bits { + TXWBFLAG_OWN = 0x80, + TXWBFLAG_INT = 0x40, + TXWBFLAG_TMOUT = 0x20, + TXWBFLAG_TRYOUT = 0x10, + TXWBFLAG_COL = 0x08, + + TXWBFLAG_ALLERR = TXWBFLAG_TMOUT | + TXWBFLAG_TRYOUT | + TXWBFLAG_COL, +}; + +#define RX_DESC_SIZE 16 +#define RX_RING_NR 4 +#define RX_RING_ALLOC_SIZE(s) ((s * RX_DESC_SIZE) + RING_DESC_ALIGN) +#define RX_BUF_DMA_ALIGN 8 +#define RX_PREPAD_SIZE 10 +#define ETH_CRC_LEN 2 +#define RX_VLANHDR_LEN 2 +#define RX_EXTRA_LEN (RX_PREPAD_SIZE + \ + ETH_HLEN + \ + ETH_CRC_LEN + \ + RX_VLANHDR_LEN + \ + RX_BUF_DMA_ALIGN) + +struct rxdesc { + union { + __u8 all[16]; + __le32 dw[4]; + struct { + /* DW0 */ + __le16 rsv2; + __u8 rsv1; + __u8 flags; + + /* DW1 */ + __le16 datalen; + __le16 wbcpl; + + /* DW2 */ + __le32 bufaddrh; + + /* DW3 */ + __le32 bufaddrl; + } desc1; + struct { + /* DW0 */ + __le16 vlan; + __le16 flags; + + /* DW1 */ + __le16 framesize; + __u8 errstat; + __u8 desccnt; + + /* DW2 */ + __le32 rsshash; + + /* DW3 */ + __u8 hashfun; + __u8 hashtype; + __le16 resrv; + } descwb; + }; +}; + +enum jme_rxdesc_flags_bits { + RXFLAG_OWN = 0x80, + RXFLAG_INT = 0x40, + RXFLAG_64BIT = 0x20, +}; + +enum jme_rxwbdesc_flags_bits { + RXWBFLAG_OWN = 0x8000, + RXWBFLAG_INT = 0x4000, + RXWBFLAG_MF = 0x2000, + RXWBFLAG_64BIT = 0x2000, + RXWBFLAG_TCPON = 0x1000, + RXWBFLAG_UDPON = 0x0800, + RXWBFLAG_IPCS = 0x0400, + RXWBFLAG_TCPCS = 0x0200, + RXWBFLAG_UDPCS = 0x0100, + RXWBFLAG_TAGON = 0x0080, + RXWBFLAG_IPV4 = 0x0040, + RXWBFLAG_IPV6 = 0x0020, + RXWBFLAG_PAUSE = 0x0010, + RXWBFLAG_MAGIC = 0x0008, + RXWBFLAG_WAKEUP = 0x0004, + RXWBFLAG_DEST = 0x0003, + RXWBFLAG_DEST_UNI = 0x0001, + RXWBFLAG_DEST_MUL = 0x0002, + RXWBFLAG_DEST_BRO = 0x0003, +}; + +enum jme_rxwbdesc_desccnt_mask { + RXWBDCNT_WBCPL = 0x80, + RXWBDCNT_DCNT = 0x7F, +}; + +enum jme_rxwbdesc_errstat_bits { + RXWBERR_LIMIT = 0x80, + RXWBERR_MIIER = 0x40, + RXWBERR_NIBON = 0x20, + RXWBERR_COLON = 0x10, + RXWBERR_ABORT = 0x08, + RXWBERR_SHORT = 0x04, + RXWBERR_OVERUN = 0x02, + RXWBERR_CRCERR = 0x01, + RXWBERR_ALLERR = 0xFF, +}; + +/* + * Buffer information corresponding to ring descriptors. + */ +struct jme_buffer_info { + struct sk_buff *skb; + dma_addr_t mapping; + int len; + int nr_desc; + unsigned long start_xmit; +}; + +/* + * The structure holding buffer information and ring descriptors all together. + */ +#define MAX_RING_DESC_NR 1024 +struct jme_ring { + void *alloc; /* pointer to allocated memory */ + void *desc; /* pointer to ring memory */ + dma_addr_t dmaalloc; /* phys address of ring alloc */ + dma_addr_t dma; /* phys address for ring dma */ + + /* Buffer information corresponding to each descriptor */ + struct jme_buffer_info bufinf[MAX_RING_DESC_NR]; + + int next_to_use; + atomic_t next_to_clean; + atomic_t nr_free; +}; + +#define NET_STAT(priv) (priv->dev->stats) +#define NETDEV_GET_STATS(netdev, fun_ptr) +#define DECLARE_NET_DEVICE_STATS + +#define DECLARE_NAPI_STRUCT struct napi_struct napi; +#define NETIF_NAPI_SET(dev, napis, pollfn, q) \ + netif_napi_add(dev, napis, pollfn, q); +#define JME_NAPI_HOLDER(holder) struct napi_struct *holder +#define JME_NAPI_WEIGHT(w) int w +#define JME_NAPI_WEIGHT_VAL(w) w +#define JME_NAPI_WEIGHT_SET(w, r) +#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev, napis) +#define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi); +#define JME_NAPI_DISABLE(priv) \ + if (!napi_disable_pending(&priv->napi)) \ + napi_disable(&priv->napi); +#define JME_RX_SCHEDULE_PREP(priv) \ + netif_rx_schedule_prep(priv->dev, &priv->napi) +#define JME_RX_SCHEDULE(priv) \ + __netif_rx_schedule(priv->dev, &priv->napi); + +/* + * Jmac Adapter Private data + */ +#define SHADOW_REG_NR 8 +struct jme_adapter { + struct pci_dev *pdev; + struct net_device *dev; + void __iomem *regs; + dma_addr_t shadow_dma; + u32 *shadow_regs; + struct mii_if_info mii_if; + struct jme_ring rxring[RX_RING_NR]; + struct jme_ring txring[TX_RING_NR]; + spinlock_t phy_lock; + spinlock_t macaddr_lock; + spinlock_t rxmcs_lock; + struct tasklet_struct rxempty_task; + struct tasklet_struct rxclean_task; + struct tasklet_struct txclean_task; + struct tasklet_struct linkch_task; + struct tasklet_struct pcc_task; + unsigned long flags; + u32 reg_txcs; + u32 reg_txpfc; + u32 reg_rxcs; + u32 reg_rxmcs; + u32 reg_ghc; + u32 reg_pmcs; + u32 phylink; + u32 tx_ring_size; + u32 tx_ring_mask; + u32 tx_wake_threshold; + u32 rx_ring_size; + u32 rx_ring_mask; + u8 mrrs; + unsigned int fpgaver; + unsigned int chiprev; + u8 rev; + u32 msg_enable; + struct ethtool_cmd old_ecmd; + unsigned int old_mtu; + struct vlan_group *vlgrp; + struct dynpcc_info dpi; + atomic_t intr_sem; + atomic_t link_changing; + atomic_t tx_cleaning; + atomic_t rx_cleaning; + atomic_t rx_empty; + int (*jme_rx)(struct sk_buff *skb); + int (*jme_vlan_rx)(struct sk_buff *skb, + struct vlan_group *grp, + unsigned short vlan_tag); + DECLARE_NAPI_STRUCT + DECLARE_NET_DEVICE_STATS +}; + +enum shadow_reg_val { + SHADOW_IEVE = 0, +}; + +enum jme_flags_bits { + JME_FLAG_MSI = 1, + JME_FLAG_SSET = 2, + JME_FLAG_TXCSUM = 3, + JME_FLAG_TSO = 4, + JME_FLAG_POLL = 5, + JME_FLAG_SHUTDOWN = 6, +}; + +#define TX_TIMEOUT (5 * HZ) +#define JME_REG_LEN 0x500 +#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9216 + +static inline struct jme_adapter* +jme_napi_priv(struct napi_struct *napi) +{ + struct jme_adapter *jme; + jme = container_of(napi, struct jme_adapter, napi); + return jme; +} + +/* + * MMaped I/O Resters + */ +enum jme_iomap_offsets { + JME_MAC = 0x0000, + JME_PHY = 0x0400, + JME_MISC = 0x0800, + JME_RSS = 0x0C00, +}; + +enum jme_iomap_lens { + JME_MAC_LEN = 0x80, + JME_PHY_LEN = 0x58, + JME_MISC_LEN = 0x98, + JME_RSS_LEN = 0xFF, +}; + +enum jme_iomap_regs { + JME_TXCS = JME_MAC | 0x00, /* Transmit Control and Status */ + JME_TXDBA_LO = JME_MAC | 0x04, /* Transmit Queue Desc Base Addr */ + JME_TXDBA_HI = JME_MAC | 0x08, /* Transmit Queue Desc Base Addr */ + JME_TXQDC = JME_MAC | 0x0C, /* Transmit Queue Desc Count */ + JME_TXNDA = JME_MAC | 0x10, /* Transmit Queue Next Desc Addr */ + JME_TXMCS = JME_MAC | 0x14, /* Transmit MAC Control Status */ + JME_TXPFC = JME_MAC | 0x18, /* Transmit Pause Frame Control */ + JME_TXTRHD = JME_MAC | 0x1C, /* Transmit Timer/Retry@Half-Dup */ + + JME_RXCS = JME_MAC | 0x20, /* Receive Control and Status */ + JME_RXDBA_LO = JME_MAC | 0x24, /* Receive Queue Desc Base Addr */ + JME_RXDBA_HI = JME_MAC | 0x28, /* Receive Queue Desc Base Addr */ + JME_RXQDC = JME_MAC | 0x2C, /* Receive Queue Desc Count */ + JME_RXNDA = JME_MAC | 0x30, /* Receive Queue Next Desc Addr */ + JME_RXMCS = JME_MAC | 0x34, /* Receive MAC Control Status */ + JME_RXUMA_LO = JME_MAC | 0x38, /* Receive Unicast MAC Address */ + JME_RXUMA_HI = JME_MAC | 0x3C, /* Receive Unicast MAC Address */ + JME_RXMCHT_LO = JME_MAC | 0x40, /* Recv Multicast Addr HashTable */ + JME_RXMCHT_HI = JME_MAC | 0x44, /* Recv Multicast Addr HashTable */ + JME_WFODP = JME_MAC | 0x48, /* Wakeup Frame Output Data Port */ + JME_WFOI = JME_MAC | 0x4C, /* Wakeup Frame Output Interface */ + + JME_SMI = JME_MAC | 0x50, /* Station Management Interface */ + JME_GHC = JME_MAC | 0x54, /* Global Host Control */ + JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */ + + + JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */ + JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */ + JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */ + JME_SMBINTF = JME_PHY | 0x44, /* SMB Interface */ + + + JME_TMCSR = JME_MISC | 0x00, /* Timer Control/Status Register */ + JME_GPREG0 = JME_MISC | 0x08, /* General purpose REG-0 */ + JME_GPREG1 = JME_MISC | 0x0C, /* General purpose REG-1 */ + JME_IEVE = JME_MISC | 0x20, /* Interrupt Event Status */ + JME_IREQ = JME_MISC | 0x24, /* Intr Req Status(For Debug) */ + JME_IENS = JME_MISC | 0x28, /* Intr Enable - Setting Port */ + JME_IENC = JME_MISC | 0x2C, /* Interrupt Enable - Clear Port */ + JME_PCCRX0 = JME_MISC | 0x30, /* PCC Control for RX Queue 0 */ + JME_PCCTX = JME_MISC | 0x40, /* PCC Control for TX Queues */ + JME_CHIPMODE = JME_MISC | 0x44, /* Identify FPGA Version */ + JME_SHBA_HI = JME_MISC | 0x48, /* Shadow Register Base HI */ + JME_SHBA_LO = JME_MISC | 0x4C, /* Shadow Register Base LO */ + JME_TIMER1 = JME_MISC | 0x70, /* Timer1 */ + JME_TIMER2 = JME_MISC | 0x74, /* Timer2 */ + JME_APMC = JME_MISC | 0x7C, /* Aggressive Power Mode Control */ + JME_PCCSRX0 = JME_MISC | 0x80, /* PCC Status of RX0 */ +}; + +/* + * TX Control/Status Bits + */ +enum jme_txcs_bits { + TXCS_QUEUE7S = 0x00008000, + TXCS_QUEUE6S = 0x00004000, + TXCS_QUEUE5S = 0x00002000, + TXCS_QUEUE4S = 0x00001000, + TXCS_QUEUE3S = 0x00000800, + TXCS_QUEUE2S = 0x00000400, + TXCS_QUEUE1S = 0x00000200, + TXCS_QUEUE0S = 0x00000100, + TXCS_FIFOTH = 0x000000C0, + TXCS_DMASIZE = 0x00000030, + TXCS_BURST = 0x00000004, + TXCS_ENABLE = 0x00000001, +}; + +enum jme_txcs_value { + TXCS_FIFOTH_16QW = 0x000000C0, + TXCS_FIFOTH_12QW = 0x00000080, + TXCS_FIFOTH_8QW = 0x00000040, + TXCS_FIFOTH_4QW = 0x00000000, + + TXCS_DMASIZE_64B = 0x00000000, + TXCS_DMASIZE_128B = 0x00000010, + TXCS_DMASIZE_256B = 0x00000020, + TXCS_DMASIZE_512B = 0x00000030, + + TXCS_SELECT_QUEUE0 = 0x00000000, + TXCS_SELECT_QUEUE1 = 0x00010000, + TXCS_SELECT_QUEUE2 = 0x00020000, + TXCS_SELECT_QUEUE3 = 0x00030000, + TXCS_SELECT_QUEUE4 = 0x00040000, + TXCS_SELECT_QUEUE5 = 0x00050000, + TXCS_SELECT_QUEUE6 = 0x00060000, + TXCS_SELECT_QUEUE7 = 0x00070000, + + TXCS_DEFAULT = TXCS_FIFOTH_4QW | + TXCS_BURST, +}; + +#define JME_TX_DISABLE_TIMEOUT 10 /* 10 msec */ + +/* + * TX MAC Control/Status Bits + */ +enum jme_txmcs_bit_masks { + TXMCS_IFG2 = 0xC0000000, + TXMCS_IFG1 = 0x30000000, + TXMCS_TTHOLD = 0x00000300, + TXMCS_FBURST = 0x00000080, + TXMCS_CARRIEREXT = 0x00000040, + TXMCS_DEFER = 0x00000020, + TXMCS_BACKOFF = 0x00000010, + TXMCS_CARRIERSENSE = 0x00000008, + TXMCS_COLLISION = 0x00000004, + TXMCS_CRC = 0x00000002, + TXMCS_PADDING = 0x00000001, +}; + +enum jme_txmcs_values { + TXMCS_IFG2_6_4 = 0x00000000, + TXMCS_IFG2_8_5 = 0x40000000, + TXMCS_IFG2_10_6 = 0x80000000, + TXMCS_IFG2_12_7 = 0xC0000000, + + TXMCS_IFG1_8_4 = 0x00000000, + TXMCS_IFG1_12_6 = 0x10000000, + TXMCS_IFG1_16_8 = 0x20000000, + TXMCS_IFG1_20_10 = 0x30000000, + + TXMCS_TTHOLD_1_8 = 0x00000000, + TXMCS_TTHOLD_1_4 = 0x00000100, + TXMCS_TTHOLD_1_2 = 0x00000200, + TXMCS_TTHOLD_FULL = 0x00000300, + + TXMCS_DEFAULT = TXMCS_IFG2_8_5 | + TXMCS_IFG1_16_8 | + TXMCS_TTHOLD_FULL | + TXMCS_DEFER | + TXMCS_CRC | + TXMCS_PADDING, +}; + +enum jme_txpfc_bits_masks { + TXPFC_VLAN_TAG = 0xFFFF0000, + TXPFC_VLAN_EN = 0x00008000, + TXPFC_PF_EN = 0x00000001, +}; + +enum jme_txtrhd_bits_masks { + TXTRHD_TXPEN = 0x80000000, + TXTRHD_TXP = 0x7FFFFF00, + TXTRHD_TXREN = 0x00000080, + TXTRHD_TXRL = 0x0000007F, +}; + +enum jme_txtrhd_shifts { + TXTRHD_TXP_SHIFT = 8, + TXTRHD_TXRL_SHIFT = 0, +}; + +/* + * RX Control/Status Bits + */ +enum jme_rxcs_bit_masks { + /* FIFO full threshold for transmitting Tx Pause Packet */ + RXCS_FIFOTHTP = 0x30000000, + /* FIFO threshold for processing next packet */ + RXCS_FIFOTHNP = 0x0C000000, + RXCS_DMAREQSZ = 0x03000000, /* DMA Request Size */ + RXCS_QUEUESEL = 0x00030000, /* Queue selection */ + RXCS_RETRYGAP = 0x0000F000, /* RX Desc full retry gap */ + RXCS_RETRYCNT = 0x00000F00, /* RX Desc full retry counter */ + RXCS_WAKEUP = 0x00000040, /* Enable receive wakeup packet */ + RXCS_MAGIC = 0x00000020, /* Enable receive magic packet */ + RXCS_SHORT = 0x00000010, /* Enable receive short packet */ + RXCS_ABORT = 0x00000008, /* Enable receive errorr packet */ + RXCS_QST = 0x00000004, /* Receive queue start */ + RXCS_SUSPEND = 0x00000002, + RXCS_ENABLE = 0x00000001, +}; + +enum jme_rxcs_values { + RXCS_FIFOTHTP_16T = 0x00000000, + RXCS_FIFOTHTP_32T = 0x10000000, + RXCS_FIFOTHTP_64T = 0x20000000, + RXCS_FIFOTHTP_128T = 0x30000000, + + RXCS_FIFOTHNP_16QW = 0x00000000, + RXCS_FIFOTHNP_32QW = 0x04000000, + RXCS_FIFOTHNP_64QW = 0x08000000, + RXCS_FIFOTHNP_128QW = 0x0C000000, + + RXCS_DMAREQSZ_16B = 0x00000000, + RXCS_DMAREQSZ_32B = 0x01000000, + RXCS_DMAREQSZ_64B = 0x02000000, + RXCS_DMAREQSZ_128B = 0x03000000, + + RXCS_QUEUESEL_Q0 = 0x00000000, + RXCS_QUEUESEL_Q1 = 0x00010000, + RXCS_QUEUESEL_Q2 = 0x00020000, + RXCS_QUEUESEL_Q3 = 0x00030000, + + RXCS_RETRYGAP_256ns = 0x00000000, + RXCS_RETRYGAP_512ns = 0x00001000, + RXCS_RETRYGAP_1024ns = 0x00002000, + RXCS_RETRYGAP_2048ns = 0x00003000, + RXCS_RETRYGAP_4096ns = 0x00004000, + RXCS_RETRYGAP_8192ns = 0x00005000, + RXCS_RETRYGAP_16384ns = 0x00006000, + RXCS_RETRYGAP_32768ns = 0x00007000, + + RXCS_RETRYCNT_0 = 0x00000000, + RXCS_RETRYCNT_4 = 0x00000100, + RXCS_RETRYCNT_8 = 0x00000200, + RXCS_RETRYCNT_12 = 0x00000300, + RXCS_RETRYCNT_16 = 0x00000400, + RXCS_RETRYCNT_20 = 0x00000500, + RXCS_RETRYCNT_24 = 0x00000600, + RXCS_RETRYCNT_28 = 0x00000700, + RXCS_RETRYCNT_32 = 0x00000800, + RXCS_RETRYCNT_36 = 0x00000900, + RXCS_RETRYCNT_40 = 0x00000A00, + RXCS_RETRYCNT_44 = 0x00000B00, + RXCS_RETRYCNT_48 = 0x00000C00, + RXCS_RETRYCNT_52 = 0x00000D00, + RXCS_RETRYCNT_56 = 0x00000E00, + RXCS_RETRYCNT_60 = 0x00000F00, + + RXCS_DEFAULT = RXCS_FIFOTHTP_128T | + RXCS_FIFOTHNP_128QW | + RXCS_DMAREQSZ_128B | + RXCS_RETRYGAP_256ns | + RXCS_RETRYCNT_32, +}; + +#define JME_RX_DISABLE_TIMEOUT 10 /* 10 msec */ + +/* + * RX MAC Control/Status Bits + */ +enum jme_rxmcs_bits { + RXMCS_ALLFRAME = 0x00000800, + RXMCS_BRDFRAME = 0x00000400, + RXMCS_MULFRAME = 0x00000200, + RXMCS_UNIFRAME = 0x00000100, + RXMCS_ALLMULFRAME = 0x00000080, + RXMCS_MULFILTERED = 0x00000040, + RXMCS_RXCOLLDEC = 0x00000020, + RXMCS_FLOWCTRL = 0x00000008, + RXMCS_VTAGRM = 0x00000004, + RXMCS_PREPAD = 0x00000002, + RXMCS_CHECKSUM = 0x00000001, + + RXMCS_DEFAULT = RXMCS_VTAGRM | + RXMCS_PREPAD | + RXMCS_FLOWCTRL | + RXMCS_CHECKSUM, +}; + +/* + * Wakeup Frame setup interface registers + */ +#define WAKEUP_FRAME_NR 8 +#define WAKEUP_FRAME_MASK_DWNR 4 + +enum jme_wfoi_bit_masks { + WFOI_MASK_SEL = 0x00000070, + WFOI_CRC_SEL = 0x00000008, + WFOI_FRAME_SEL = 0x00000007, +}; + +enum jme_wfoi_shifts { + WFOI_MASK_SHIFT = 4, +}; + +/* + * SMI Related definitions + */ +enum jme_smi_bit_mask { + SMI_DATA_MASK = 0xFFFF0000, + SMI_REG_ADDR_MASK = 0x0000F800, + SMI_PHY_ADDR_MASK = 0x000007C0, + SMI_OP_WRITE = 0x00000020, + /* Set to 1, after req done it'll be cleared to 0 */ + SMI_OP_REQ = 0x00000010, + SMI_OP_MDIO = 0x00000008, /* Software assess In/Out */ + SMI_OP_MDOE = 0x00000004, /* Software Output Enable */ + SMI_OP_MDC = 0x00000002, /* Software CLK Control */ + SMI_OP_MDEN = 0x00000001, /* Software access Enable */ +}; + +enum jme_smi_bit_shift { + SMI_DATA_SHIFT = 16, + SMI_REG_ADDR_SHIFT = 11, + SMI_PHY_ADDR_SHIFT = 6, +}; + +static inline u32 smi_reg_addr(int x) +{ + return (x << SMI_REG_ADDR_SHIFT) & SMI_REG_ADDR_MASK; +} + +static inline u32 smi_phy_addr(int x) +{ + return (x << SMI_PHY_ADDR_SHIFT) & SMI_PHY_ADDR_MASK; +} + +#define JME_PHY_TIMEOUT 100 /* 100 msec */ +#define JME_PHY_REG_NR 32 + +/* + * Global Host Control + */ +enum jme_ghc_bit_mask { + GHC_SWRST = 0x40000000, + GHC_DPX = 0x00000040, + GHC_SPEED = 0x00000030, + GHC_LINK_POLL = 0x00000001, +}; + +enum jme_ghc_speed_val { + GHC_SPEED_10M = 0x00000010, + GHC_SPEED_100M = 0x00000020, + GHC_SPEED_1000M = 0x00000030, +}; + +/* + * Power management control and status register + */ +enum jme_pmcs_bit_masks { + PMCS_WF7DET = 0x80000000, + PMCS_WF6DET = 0x40000000, + PMCS_WF5DET = 0x20000000, + PMCS_WF4DET = 0x10000000, + PMCS_WF3DET = 0x08000000, + PMCS_WF2DET = 0x04000000, + PMCS_WF1DET = 0x02000000, + PMCS_WF0DET = 0x01000000, + PMCS_LFDET = 0x00040000, + PMCS_LRDET = 0x00020000, + PMCS_MFDET = 0x00010000, + PMCS_WF7EN = 0x00008000, + PMCS_WF6EN = 0x00004000, + PMCS_WF5EN = 0x00002000, + PMCS_WF4EN = 0x00001000, + PMCS_WF3EN = 0x00000800, + PMCS_WF2EN = 0x00000400, + PMCS_WF1EN = 0x00000200, + PMCS_WF0EN = 0x00000100, + PMCS_LFEN = 0x00000004, + PMCS_LREN = 0x00000002, + PMCS_MFEN = 0x00000001, +}; + +/* + * Giga PHY Status Registers + */ +enum jme_phy_link_bit_mask { + PHY_LINK_SPEED_MASK = 0x0000C000, + PHY_LINK_DUPLEX = 0x00002000, + PHY_LINK_SPEEDDPU_RESOLVED = 0x00000800, + PHY_LINK_UP = 0x00000400, + PHY_LINK_AUTONEG_COMPLETE = 0x00000200, + PHY_LINK_MDI_STAT = 0x00000040, +}; + +enum jme_phy_link_speed_val { + PHY_LINK_SPEED_10M = 0x00000000, + PHY_LINK_SPEED_100M = 0x00004000, + PHY_LINK_SPEED_1000M = 0x00008000, +}; + +#define JME_SPDRSV_TIMEOUT 500 /* 500 us */ + +/* + * SMB Control and Status + */ +enum jme_smbcsr_bit_mask { + SMBCSR_CNACK = 0x00020000, + SMBCSR_RELOAD = 0x00010000, + SMBCSR_EEPROMD = 0x00000020, + SMBCSR_INITDONE = 0x00000010, + SMBCSR_BUSY = 0x0000000F, +}; + +enum jme_smbintf_bit_mask { + SMBINTF_HWDATR = 0xFF000000, + SMBINTF_HWDATW = 0x00FF0000, + SMBINTF_HWADDR = 0x0000FF00, + SMBINTF_HWRWN = 0x00000020, + SMBINTF_HWCMD = 0x00000010, + SMBINTF_FASTM = 0x00000008, + SMBINTF_GPIOSCL = 0x00000004, + SMBINTF_GPIOSDA = 0x00000002, + SMBINTF_GPIOEN = 0x00000001, +}; + +enum jme_smbintf_vals { + SMBINTF_HWRWN_READ = 0x00000020, + SMBINTF_HWRWN_WRITE = 0x00000000, +}; + +enum jme_smbintf_shifts { + SMBINTF_HWDATR_SHIFT = 24, + SMBINTF_HWDATW_SHIFT = 16, + SMBINTF_HWADDR_SHIFT = 8, +}; + +#define JME_EEPROM_RELOAD_TIMEOUT 2000 /* 2000 msec */ +#define JME_SMB_BUSY_TIMEOUT 20 /* 20 msec */ +#define JME_SMB_LEN 256 +#define JME_EEPROM_MAGIC 0x250 + +/* + * Timer Control/Status Register + */ +enum jme_tmcsr_bit_masks { + TMCSR_SWIT = 0x80000000, + TMCSR_EN = 0x01000000, + TMCSR_CNT = 0x00FFFFFF, +}; + +/* + * General Purpose REG-0 + */ +enum jme_gpreg0_masks { + GPREG0_DISSH = 0xFF000000, + GPREG0_PCIRLMT = 0x00300000, + GPREG0_PCCNOMUTCLR = 0x00040000, + GPREG0_LNKINTPOLL = 0x00001000, + GPREG0_PCCTMR = 0x00000300, + GPREG0_PHYADDR = 0x0000001F, +}; + +enum jme_gpreg0_vals { + GPREG0_DISSH_DW7 = 0x80000000, + GPREG0_DISSH_DW6 = 0x40000000, + GPREG0_DISSH_DW5 = 0x20000000, + GPREG0_DISSH_DW4 = 0x10000000, + GPREG0_DISSH_DW3 = 0x08000000, + GPREG0_DISSH_DW2 = 0x04000000, + GPREG0_DISSH_DW1 = 0x02000000, + GPREG0_DISSH_DW0 = 0x01000000, + GPREG0_DISSH_ALL = 0xFF000000, + + GPREG0_PCIRLMT_8 = 0x00000000, + GPREG0_PCIRLMT_6 = 0x00100000, + GPREG0_PCIRLMT_5 = 0x00200000, + GPREG0_PCIRLMT_4 = 0x00300000, + + GPREG0_PCCTMR_16ns = 0x00000000, + GPREG0_PCCTMR_256ns = 0x00000100, + GPREG0_PCCTMR_1us = 0x00000200, + GPREG0_PCCTMR_1ms = 0x00000300, + + GPREG0_PHYADDR_1 = 0x00000001, + + GPREG0_DEFAULT = GPREG0_PCIRLMT_4 | + GPREG0_PCCTMR_1us | + GPREG0_PHYADDR_1, +}; + +/* + * Interrupt Status Bits + */ +enum jme_interrupt_bits { + INTR_SWINTR = 0x80000000, + INTR_TMINTR = 0x40000000, + INTR_LINKCH = 0x20000000, + INTR_PAUSERCV = 0x10000000, + INTR_MAGICRCV = 0x08000000, + INTR_WAKERCV = 0x04000000, + INTR_PCCRX0TO = 0x02000000, + INTR_PCCRX1TO = 0x01000000, + INTR_PCCRX2TO = 0x00800000, + INTR_PCCRX3TO = 0x00400000, + INTR_PCCTXTO = 0x00200000, + INTR_PCCRX0 = 0x00100000, + INTR_PCCRX1 = 0x00080000, + INTR_PCCRX2 = 0x00040000, + INTR_PCCRX3 = 0x00020000, + INTR_PCCTX = 0x00010000, + INTR_RX3EMP = 0x00008000, + INTR_RX2EMP = 0x00004000, + INTR_RX1EMP = 0x00002000, + INTR_RX0EMP = 0x00001000, + INTR_RX3 = 0x00000800, + INTR_RX2 = 0x00000400, + INTR_RX1 = 0x00000200, + INTR_RX0 = 0x00000100, + INTR_TX7 = 0x00000080, + INTR_TX6 = 0x00000040, + INTR_TX5 = 0x00000020, + INTR_TX4 = 0x00000010, + INTR_TX3 = 0x00000008, + INTR_TX2 = 0x00000004, + INTR_TX1 = 0x00000002, + INTR_TX0 = 0x00000001, +}; + +static const u32 INTR_ENABLE = INTR_SWINTR | + INTR_TMINTR | + INTR_LINKCH | + INTR_PCCRX0TO | + INTR_PCCRX0 | + INTR_PCCTXTO | + INTR_PCCTX | + INTR_RX0EMP; + +/* + * PCC Control Registers + */ +enum jme_pccrx_masks { + PCCRXTO_MASK = 0xFFFF0000, + PCCRX_MASK = 0x0000FF00, +}; + +enum jme_pcctx_masks { + PCCTXTO_MASK = 0xFFFF0000, + PCCTX_MASK = 0x0000FF00, + PCCTX_QS_MASK = 0x000000FF, +}; + +enum jme_pccrx_shifts { + PCCRXTO_SHIFT = 16, + PCCRX_SHIFT = 8, +}; + +enum jme_pcctx_shifts { + PCCTXTO_SHIFT = 16, + PCCTX_SHIFT = 8, +}; + +enum jme_pcctx_bits { + PCCTXQ0_EN = 0x00000001, + PCCTXQ1_EN = 0x00000002, + PCCTXQ2_EN = 0x00000004, + PCCTXQ3_EN = 0x00000008, + PCCTXQ4_EN = 0x00000010, + PCCTXQ5_EN = 0x00000020, + PCCTXQ6_EN = 0x00000040, + PCCTXQ7_EN = 0x00000080, +}; + +/* + * Chip Mode Register + */ +enum jme_chipmode_bit_masks { + CM_FPGAVER_MASK = 0xFFFF0000, + CM_CHIPREV_MASK = 0x0000FF00, + CM_CHIPMODE_MASK = 0x0000000F, +}; + +enum jme_chipmode_shifts { + CM_FPGAVER_SHIFT = 16, + CM_CHIPREV_SHIFT = 8, +}; + +/* + * Shadow base address register bits + */ +enum jme_shadow_base_address_bits { + SHBA_POSTEN = 0x1, +}; + +/* + * Aggressive Power Mode Control + */ +enum jme_apmc_bits { + JME_APMC_PCIE_SD_EN = 0x40000000, + JME_APMC_PSEUDO_HP_EN = 0x20000000, + JME_APMC_EPIEN = 0x04000000, + JME_APMC_EPIEN_CTRL = 0x03000000, +}; + +enum jme_apmc_values { + JME_APMC_EPIEN_CTRL_EN = 0x02000000, + JME_APMC_EPIEN_CTRL_DIS = 0x01000000, +}; + +#define APMC_PHP_SHUTDOWN_DELAY (10 * 1000 * 1000) + +#ifdef REG_DEBUG +static char *MAC_REG_NAME[] = { + "JME_TXCS", "JME_TXDBA_LO", "JME_TXDBA_HI", "JME_TXQDC", + "JME_TXNDA", "JME_TXMCS", "JME_TXPFC", "JME_TXTRHD", + "JME_RXCS", "JME_RXDBA_LO", "JME_RXDBA_HI", "JME_RXQDC", + "JME_RXNDA", "JME_RXMCS", "JME_RXUMA_LO", "JME_RXUMA_HI", + "JME_RXMCHT_LO", "JME_RXMCHT_HI", "JME_WFODP", "JME_WFOI", + "JME_SMI", "JME_GHC", "UNKNOWN", "UNKNOWN", + "JME_PMCS"}; + +static char *PE_REG_NAME[] = { + "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "UNKNOWN", "UNKNOWN", "JME_PHY_CS", "UNKNOWN", + "JME_PHY_LINK", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "JME_SMBCSR", "JME_SMBINTF"}; + +static char *MISC_REG_NAME[] = { + "JME_TMCSR", "JME_GPIO", "JME_GPREG0", "JME_GPREG1", + "JME_IEVE", "JME_IREQ", "JME_IENS", "JME_IENC", + "JME_PCCRX0", "JME_PCCRX1", "JME_PCCRX2", "JME_PCCRX3", + "JME_PCCTX0", "JME_CHIPMODE", "JME_SHBA_HI", "JME_SHBA_LO", + "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", + "JME_TIMER1", "JME_TIMER2", "UNKNOWN", "JME_APMC", + "JME_PCCSRX0"}; + +static inline void reg_dbg(const struct jme_adapter *jme, + const char *msg, u32 val, u32 reg) +{ + const char *regname; + switch (reg & 0xF00) { + case 0x000: + regname = MAC_REG_NAME[(reg & 0xFF) >> 2]; + break; + case 0x400: + regname = PE_REG_NAME[(reg & 0xFF) >> 2]; + break; + case 0x800: + regname = MISC_REG_NAME[(reg & 0xFF) >> 2]; + break; + default: + regname = PE_REG_NAME[0]; + } + printk(KERN_DEBUG "%s: %-20s %08x@%s\n", jme->dev->name, + msg, val, regname); +} +#else +static inline void reg_dbg(const struct jme_adapter *jme, + const char *msg, u32 val, u32 reg) {} +#endif + +/* + * Read/Write MMaped I/O Registers + */ +static inline u32 jread32(struct jme_adapter *jme, u32 reg) +{ + return readl(jme->regs + reg); +} + +static inline void jwrite32(struct jme_adapter *jme, u32 reg, u32 val) +{ + reg_dbg(jme, "REG WRITE", val, reg); + writel(val, jme->regs + reg); + reg_dbg(jme, "VAL AFTER WRITE", readl(jme->regs + reg), reg); +} + +static inline void jwrite32f(struct jme_adapter *jme, u32 reg, u32 val) +{ + /* + * Read after write should cause flush + */ + reg_dbg(jme, "REG WRITE FLUSH", val, reg); + writel(val, jme->regs + reg); + readl(jme->regs + reg); + reg_dbg(jme, "VAL AFTER WRITE", readl(jme->regs + reg), reg); +} + +/* + * PHY Regs + */ +enum jme_phy_reg17_bit_masks { + PREG17_SPEED = 0xC000, + PREG17_DUPLEX = 0x2000, + PREG17_SPDRSV = 0x0800, + PREG17_LNKUP = 0x0400, + PREG17_MDI = 0x0040, +}; + +enum jme_phy_reg17_vals { + PREG17_SPEED_10M = 0x0000, + PREG17_SPEED_100M = 0x4000, + PREG17_SPEED_1000M = 0x8000, +}; + +#define BMSR_ANCOMP 0x0020 + +/* + * Workaround + */ +static inline int is_buggy250(unsigned short device, unsigned int chiprev) +{ + return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11; +} + +/* + * Function prototypes + */ +static int jme_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd); +static void jme_set_multi(struct net_device *netdev); + +#endif -- GitLab From c4e84bde1d595d857d3c74b49b9c45cc770df792 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Thu, 18 Sep 2008 11:56:28 -0400 Subject: [PATCH 1981/5416] qlge: New Qlogic 10Gb Ethernet Driver. Signed-off-by: Ron Mercer Signed-off-by: Jeff Garzik --- Documentation/networking/LICENSE.qlge | 46 + MAINTAINERS | 7 + drivers/net/Kconfig | 9 + drivers/net/Makefile | 1 + drivers/net/qlge/Makefile | 7 + drivers/net/qlge/qlge.h | 1593 ++++++++++ drivers/net/qlge/qlge_dbg.c | 858 ++++++ drivers/net/qlge/qlge_ethtool.c | 415 +++ drivers/net/qlge/qlge_main.c | 3954 +++++++++++++++++++++++++ drivers/net/qlge/qlge_mpi.c | 150 + 10 files changed, 7040 insertions(+) create mode 100644 Documentation/networking/LICENSE.qlge create mode 100644 drivers/net/qlge/Makefile create mode 100644 drivers/net/qlge/qlge.h create mode 100644 drivers/net/qlge/qlge_dbg.c create mode 100644 drivers/net/qlge/qlge_ethtool.c create mode 100644 drivers/net/qlge/qlge_main.c create mode 100644 drivers/net/qlge/qlge_mpi.c diff --git a/Documentation/networking/LICENSE.qlge b/Documentation/networking/LICENSE.qlge new file mode 100644 index 00000000000..123b6edd7f1 --- /dev/null +++ b/Documentation/networking/LICENSE.qlge @@ -0,0 +1,46 @@ +Copyright (c) 2003-2008 QLogic Corporation +QLogic Linux Networking HBA Driver + +This program includes a device driver for Linux 2.6 that may be +distributed with QLogic hardware specific firmware binary file. +You may modify and redistribute the device driver code under the +GNU General Public License as published by the Free Software +Foundation (version 2 or a later version). + +You may redistribute the hardware specific firmware binary file +under the following terms: + + 1. Redistribution of source code (only if applicable), + must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistribution 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 name of QLogic Corporation may not be used to + endorse or promote products derived from this software + without specific prior written permission + +REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE, +THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT +CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR +OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT, +TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN +ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN +COMBINATION WITH THIS PROGRAM. + diff --git a/MAINTAINERS b/MAINTAINERS index c8203d780f0..106684e45e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3396,6 +3396,13 @@ M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported +QLOGIC QLGE 10Gb ETHERNET DRIVER +P: Ron Mercer +M: linux-driver@qlogic.com +M: ron.mercer@qlogic.com +L: netdev@vger.kernel.org +S: Supported + QNX4 FILESYSTEM P: Anders Larsen M: al@alarsen.net diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 069755af761..69c81da48eb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2526,6 +2526,15 @@ config BNX2X To compile this driver as a module, choose M here: the module will be called bnx2x. This is recommended. +config QLGE + tristate "QLogic QLGE 10Gb Ethernet Driver Support" + depends on PCI + help + This driver supports QLogic ISP8XXX 10Gb Ethernet cards. + + To compile this driver as a module, choose M here: the module + will be called qlge. + source "drivers/net/sfc/Kconfig" endif # NETDEV_10000 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 016e23f000e..fa2510b2e60 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o +obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_PPP) += ppp_generic.o obj-$(CONFIG_PPP_ASYNC) += ppp_async.o diff --git a/drivers/net/qlge/Makefile b/drivers/net/qlge/Makefile new file mode 100644 index 00000000000..8a197658d76 --- /dev/null +++ b/drivers/net/qlge/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Qlogic 10GbE PCI Express ethernet driver +# + +obj-$(CONFIG_QLGE) += qlge.o + +qlge-objs := qlge_main.o qlge_dbg.o qlge_mpi.o qlge_ethtool.o diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h new file mode 100644 index 00000000000..c37ea436c91 --- /dev/null +++ b/drivers/net/qlge/qlge.h @@ -0,0 +1,1593 @@ +/* + * QLogic QLA41xx NIC HBA Driver + * Copyright (c) 2003-2006 QLogic Corporation + * + * See LICENSE.qlge for copyright and licensing details. + */ +#ifndef _QLGE_H_ +#define _QLGE_H_ + +#include +#include + +/* + * General definitions... + */ +#define DRV_NAME "qlge" +#define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " +#define DRV_VERSION "v1.00.00-b3" + +#define PFX "qlge: " +#define QPRINTK(qdev, nlevel, klevel, fmt, args...) \ + do { \ + if (!((qdev)->msg_enable & NETIF_MSG_##nlevel)) \ + ; \ + else \ + dev_printk(KERN_##klevel, &((qdev)->pdev->dev), \ + "%s: " fmt, __func__, ##args); \ + } while (0) + +#define QLGE_VENDOR_ID 0x1077 +#define QLGE_DEVICE_ID1 0x8012 +#define QLGE_DEVICE_ID 0x8000 + +#define MAX_RX_RINGS 128 +#define MAX_TX_RINGS 128 + +#define NUM_TX_RING_ENTRIES 256 +#define NUM_RX_RING_ENTRIES 256 + +#define NUM_SMALL_BUFFERS 512 +#define NUM_LARGE_BUFFERS 512 + +#define SMALL_BUFFER_SIZE 256 +#define LARGE_BUFFER_SIZE PAGE_SIZE +#define MAX_SPLIT_SIZE 1023 +#define QLGE_SB_PAD 32 + +#define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */ +#define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */ +#define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2) +#define UDELAY_COUNT 3 +#define UDELAY_DELAY 10 + + +#define TX_DESC_PER_IOCB 8 +/* The maximum number of frags we handle is based + * on PAGE_SIZE... + */ +#if (PAGE_SHIFT == 12) || (PAGE_SHIFT == 13) /* 4k & 8k pages */ +#define TX_DESC_PER_OAL ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2) +#elif (PAGE_SHIFT == 16) /* 64k pages */ +#define TX_DESC_PER_OAL 0 +#endif + +#define DB_PAGE_SIZE 4096 + +/* + * Processor Address Register (PROC_ADDR) bit definitions. + */ +enum { + + /* Misc. stuff */ + MAILBOX_COUNT = 16, + + PROC_ADDR_RDY = (1 << 31), + PROC_ADDR_R = (1 << 30), + PROC_ADDR_ERR = (1 << 29), + PROC_ADDR_DA = (1 << 28), + PROC_ADDR_FUNC0_MBI = 0x00001180, + PROC_ADDR_FUNC0_MBO = (PROC_ADDR_FUNC0_MBI + MAILBOX_COUNT), + PROC_ADDR_FUNC0_CTL = 0x000011a1, + PROC_ADDR_FUNC2_MBI = 0x00001280, + PROC_ADDR_FUNC2_MBO = (PROC_ADDR_FUNC2_MBI + MAILBOX_COUNT), + PROC_ADDR_FUNC2_CTL = 0x000012a1, + PROC_ADDR_MPI_RISC = 0x00000000, + PROC_ADDR_MDE = 0x00010000, + PROC_ADDR_REGBLOCK = 0x00020000, + PROC_ADDR_RISC_REG = 0x00030000, +}; + +/* + * System Register (SYS) bit definitions. + */ +enum { + SYS_EFE = (1 << 0), + SYS_FAE = (1 << 1), + SYS_MDC = (1 << 2), + SYS_DST = (1 << 3), + SYS_DWC = (1 << 4), + SYS_EVW = (1 << 5), + SYS_OMP_DLY_MASK = 0x3f000000, + /* + * There are no values defined as of edit #15. + */ + SYS_ODI = (1 << 14), +}; + +/* + * Reset/Failover Register (RST_FO) bit definitions. + */ +enum { + RST_FO_TFO = (1 << 0), + RST_FO_RR_MASK = 0x00060000, + RST_FO_RR_CQ_CAM = 0x00000000, + RST_FO_RR_DROP = 0x00000001, + RST_FO_RR_DQ = 0x00000002, + RST_FO_RR_RCV_FUNC_CQ = 0x00000003, + RST_FO_FRB = (1 << 12), + RST_FO_MOP = (1 << 13), + RST_FO_REG = (1 << 14), + RST_FO_FR = (1 << 15), +}; + +/* + * Function Specific Control Register (FSC) bit definitions. + */ +enum { + FSC_DBRST_MASK = 0x00070000, + FSC_DBRST_256 = 0x00000000, + FSC_DBRST_512 = 0x00000001, + FSC_DBRST_768 = 0x00000002, + FSC_DBRST_1024 = 0x00000003, + FSC_DBL_MASK = 0x00180000, + FSC_DBL_DBRST = 0x00000000, + FSC_DBL_MAX_PLD = 0x00000008, + FSC_DBL_MAX_BRST = 0x00000010, + FSC_DBL_128_BYTES = 0x00000018, + FSC_EC = (1 << 5), + FSC_EPC_MASK = 0x00c00000, + FSC_EPC_INBOUND = (1 << 6), + FSC_EPC_OUTBOUND = (1 << 7), + FSC_VM_PAGESIZE_MASK = 0x07000000, + FSC_VM_PAGE_2K = 0x00000100, + FSC_VM_PAGE_4K = 0x00000200, + FSC_VM_PAGE_8K = 0x00000300, + FSC_VM_PAGE_64K = 0x00000600, + FSC_SH = (1 << 11), + FSC_DSB = (1 << 12), + FSC_STE = (1 << 13), + FSC_FE = (1 << 15), +}; + +/* + * Host Command Status Register (CSR) bit definitions. + */ +enum { + CSR_ERR_STS_MASK = 0x0000003f, + /* + * There are no valued defined as of edit #15. + */ + CSR_RR = (1 << 8), + CSR_HRI = (1 << 9), + CSR_RP = (1 << 10), + CSR_CMD_PARM_SHIFT = 22, + CSR_CMD_NOP = 0x00000000, + CSR_CMD_SET_RST = 0x1000000, + CSR_CMD_CLR_RST = 0x20000000, + CSR_CMD_SET_PAUSE = 0x30000000, + CSR_CMD_CLR_PAUSE = 0x40000000, + CSR_CMD_SET_H2R_INT = 0x50000000, + CSR_CMD_CLR_H2R_INT = 0x60000000, + CSR_CMD_PAR_EN = 0x70000000, + CSR_CMD_SET_BAD_PAR = 0x80000000, + CSR_CMD_CLR_BAD_PAR = 0x90000000, + CSR_CMD_CLR_R2PCI_INT = 0xa0000000, +}; + +/* + * Configuration Register (CFG) bit definitions. + */ +enum { + CFG_LRQ = (1 << 0), + CFG_DRQ = (1 << 1), + CFG_LR = (1 << 2), + CFG_DR = (1 << 3), + CFG_LE = (1 << 5), + CFG_LCQ = (1 << 6), + CFG_DCQ = (1 << 7), + CFG_Q_SHIFT = 8, + CFG_Q_MASK = 0x7f000000, +}; + +/* + * Status Register (STS) bit definitions. + */ +enum { + STS_FE = (1 << 0), + STS_PI = (1 << 1), + STS_PL0 = (1 << 2), + STS_PL1 = (1 << 3), + STS_PI0 = (1 << 4), + STS_PI1 = (1 << 5), + STS_FUNC_ID_MASK = 0x000000c0, + STS_FUNC_ID_SHIFT = 6, + STS_F0E = (1 << 8), + STS_F1E = (1 << 9), + STS_F2E = (1 << 10), + STS_F3E = (1 << 11), + STS_NFE = (1 << 12), +}; + +/* + * Interrupt Enable Register (INTR_EN) bit definitions. + */ +enum { + INTR_EN_INTR_MASK = 0x007f0000, + INTR_EN_TYPE_MASK = 0x03000000, + INTR_EN_TYPE_ENABLE = 0x00000100, + INTR_EN_TYPE_DISABLE = 0x00000200, + INTR_EN_TYPE_READ = 0x00000300, + INTR_EN_IHD = (1 << 13), + INTR_EN_IHD_MASK = (INTR_EN_IHD << 16), + INTR_EN_EI = (1 << 14), + INTR_EN_EN = (1 << 15), +}; + +/* + * Interrupt Mask Register (INTR_MASK) bit definitions. + */ +enum { + INTR_MASK_PI = (1 << 0), + INTR_MASK_HL0 = (1 << 1), + INTR_MASK_LH0 = (1 << 2), + INTR_MASK_HL1 = (1 << 3), + INTR_MASK_LH1 = (1 << 4), + INTR_MASK_SE = (1 << 5), + INTR_MASK_LSC = (1 << 6), + INTR_MASK_MC = (1 << 7), + INTR_MASK_LINK_IRQS = INTR_MASK_LSC | INTR_MASK_SE | INTR_MASK_MC, +}; + +/* + * Register (REV_ID) bit definitions. + */ +enum { + REV_ID_MASK = 0x0000000f, + REV_ID_NICROLL_SHIFT = 0, + REV_ID_NICREV_SHIFT = 4, + REV_ID_XGROLL_SHIFT = 8, + REV_ID_XGREV_SHIFT = 12, + REV_ID_CHIPREV_SHIFT = 28, +}; + +/* + * Force ECC Error Register (FRC_ECC_ERR) bit definitions. + */ +enum { + FRC_ECC_ERR_VW = (1 << 12), + FRC_ECC_ERR_VB = (1 << 13), + FRC_ECC_ERR_NI = (1 << 14), + FRC_ECC_ERR_NO = (1 << 15), + FRC_ECC_PFE_SHIFT = 16, + FRC_ECC_ERR_DO = (1 << 18), + FRC_ECC_P14 = (1 << 19), +}; + +/* + * Error Status Register (ERR_STS) bit definitions. + */ +enum { + ERR_STS_NOF = (1 << 0), + ERR_STS_NIF = (1 << 1), + ERR_STS_DRP = (1 << 2), + ERR_STS_XGP = (1 << 3), + ERR_STS_FOU = (1 << 4), + ERR_STS_FOC = (1 << 5), + ERR_STS_FOF = (1 << 6), + ERR_STS_FIU = (1 << 7), + ERR_STS_FIC = (1 << 8), + ERR_STS_FIF = (1 << 9), + ERR_STS_MOF = (1 << 10), + ERR_STS_TA = (1 << 11), + ERR_STS_MA = (1 << 12), + ERR_STS_MPE = (1 << 13), + ERR_STS_SCE = (1 << 14), + ERR_STS_STE = (1 << 15), + ERR_STS_FOW = (1 << 16), + ERR_STS_UE = (1 << 17), + ERR_STS_MCH = (1 << 26), + ERR_STS_LOC_SHIFT = 27, +}; + +/* + * RAM Debug Address Register (RAM_DBG_ADDR) bit definitions. + */ +enum { + RAM_DBG_ADDR_FW = (1 << 30), + RAM_DBG_ADDR_FR = (1 << 31), +}; + +/* + * Semaphore Register (SEM) bit definitions. + */ +enum { + /* + * Example: + * reg = SEM_XGMAC0_MASK | (SEM_SET << SEM_XGMAC0_SHIFT) + */ + SEM_CLEAR = 0, + SEM_SET = 1, + SEM_FORCE = 3, + SEM_XGMAC0_SHIFT = 0, + SEM_XGMAC1_SHIFT = 2, + SEM_ICB_SHIFT = 4, + SEM_MAC_ADDR_SHIFT = 6, + SEM_FLASH_SHIFT = 8, + SEM_PROBE_SHIFT = 10, + SEM_RT_IDX_SHIFT = 12, + SEM_PROC_REG_SHIFT = 14, + SEM_XGMAC0_MASK = 0x00030000, + SEM_XGMAC1_MASK = 0x000c0000, + SEM_ICB_MASK = 0x00300000, + SEM_MAC_ADDR_MASK = 0x00c00000, + SEM_FLASH_MASK = 0x03000000, + SEM_PROBE_MASK = 0x0c000000, + SEM_RT_IDX_MASK = 0x30000000, + SEM_PROC_REG_MASK = 0xc0000000, +}; + +/* + * 10G MAC Address Register (XGMAC_ADDR) bit definitions. + */ +enum { + XGMAC_ADDR_RDY = (1 << 31), + XGMAC_ADDR_R = (1 << 30), + XGMAC_ADDR_XME = (1 << 29), + + /* XGMAC control registers */ + PAUSE_SRC_LO = 0x00000100, + PAUSE_SRC_HI = 0x00000104, + GLOBAL_CFG = 0x00000108, + GLOBAL_CFG_RESET = (1 << 0), + GLOBAL_CFG_JUMBO = (1 << 6), + GLOBAL_CFG_TX_STAT_EN = (1 << 10), + GLOBAL_CFG_RX_STAT_EN = (1 << 11), + TX_CFG = 0x0000010c, + TX_CFG_RESET = (1 << 0), + TX_CFG_EN = (1 << 1), + TX_CFG_PREAM = (1 << 2), + RX_CFG = 0x00000110, + RX_CFG_RESET = (1 << 0), + RX_CFG_EN = (1 << 1), + RX_CFG_PREAM = (1 << 2), + FLOW_CTL = 0x0000011c, + PAUSE_OPCODE = 0x00000120, + PAUSE_TIMER = 0x00000124, + PAUSE_FRM_DEST_LO = 0x00000128, + PAUSE_FRM_DEST_HI = 0x0000012c, + MAC_TX_PARAMS = 0x00000134, + MAC_TX_PARAMS_JUMBO = (1 << 31), + MAC_TX_PARAMS_SIZE_SHIFT = 16, + MAC_RX_PARAMS = 0x00000138, + MAC_SYS_INT = 0x00000144, + MAC_SYS_INT_MASK = 0x00000148, + MAC_MGMT_INT = 0x0000014c, + MAC_MGMT_IN_MASK = 0x00000150, + EXT_ARB_MODE = 0x000001fc, + + /* XGMAC TX statistics registers */ + TX_PKTS = 0x00000200, + TX_BYTES = 0x00000208, + TX_MCAST_PKTS = 0x00000210, + TX_BCAST_PKTS = 0x00000218, + TX_UCAST_PKTS = 0x00000220, + TX_CTL_PKTS = 0x00000228, + TX_PAUSE_PKTS = 0x00000230, + TX_64_PKT = 0x00000238, + TX_65_TO_127_PKT = 0x00000240, + TX_128_TO_255_PKT = 0x00000248, + TX_256_511_PKT = 0x00000250, + TX_512_TO_1023_PKT = 0x00000258, + TX_1024_TO_1518_PKT = 0x00000260, + TX_1519_TO_MAX_PKT = 0x00000268, + TX_UNDERSIZE_PKT = 0x00000270, + TX_OVERSIZE_PKT = 0x00000278, + + /* XGMAC statistics control registers */ + RX_HALF_FULL_DET = 0x000002a0, + TX_HALF_FULL_DET = 0x000002a4, + RX_OVERFLOW_DET = 0x000002a8, + TX_OVERFLOW_DET = 0x000002ac, + RX_HALF_FULL_MASK = 0x000002b0, + TX_HALF_FULL_MASK = 0x000002b4, + RX_OVERFLOW_MASK = 0x000002b8, + TX_OVERFLOW_MASK = 0x000002bc, + STAT_CNT_CTL = 0x000002c0, + STAT_CNT_CTL_CLEAR_TX = (1 << 0), + STAT_CNT_CTL_CLEAR_RX = (1 << 1), + AUX_RX_HALF_FULL_DET = 0x000002d0, + AUX_TX_HALF_FULL_DET = 0x000002d4, + AUX_RX_OVERFLOW_DET = 0x000002d8, + AUX_TX_OVERFLOW_DET = 0x000002dc, + AUX_RX_HALF_FULL_MASK = 0x000002f0, + AUX_TX_HALF_FULL_MASK = 0x000002f4, + AUX_RX_OVERFLOW_MASK = 0x000002f8, + AUX_TX_OVERFLOW_MASK = 0x000002fc, + + /* XGMAC RX statistics registers */ + RX_BYTES = 0x00000300, + RX_BYTES_OK = 0x00000308, + RX_PKTS = 0x00000310, + RX_PKTS_OK = 0x00000318, + RX_BCAST_PKTS = 0x00000320, + RX_MCAST_PKTS = 0x00000328, + RX_UCAST_PKTS = 0x00000330, + RX_UNDERSIZE_PKTS = 0x00000338, + RX_OVERSIZE_PKTS = 0x00000340, + RX_JABBER_PKTS = 0x00000348, + RX_UNDERSIZE_FCERR_PKTS = 0x00000350, + RX_DROP_EVENTS = 0x00000358, + RX_FCERR_PKTS = 0x00000360, + RX_ALIGN_ERR = 0x00000368, + RX_SYMBOL_ERR = 0x00000370, + RX_MAC_ERR = 0x00000378, + RX_CTL_PKTS = 0x00000380, + RX_PAUSE_PKTS = 0x00000384, + RX_64_PKTS = 0x00000390, + RX_65_TO_127_PKTS = 0x00000398, + RX_128_255_PKTS = 0x000003a0, + RX_256_511_PKTS = 0x000003a8, + RX_512_TO_1023_PKTS = 0x000003b0, + RX_1024_TO_1518_PKTS = 0x000003b8, + RX_1519_TO_MAX_PKTS = 0x000003c0, + RX_LEN_ERR_PKTS = 0x000003c8, + + /* XGMAC MDIO control registers */ + MDIO_TX_DATA = 0x00000400, + MDIO_RX_DATA = 0x00000410, + MDIO_CMD = 0x00000420, + MDIO_PHY_ADDR = 0x00000430, + MDIO_PORT = 0x00000440, + MDIO_STATUS = 0x00000450, + + /* XGMAC AUX statistics registers */ +}; + +/* + * Enhanced Transmission Schedule Registers (NIC_ETS,CNA_ETS) bit definitions. + */ +enum { + ETS_QUEUE_SHIFT = 29, + ETS_REF = (1 << 26), + ETS_RS = (1 << 27), + ETS_P = (1 << 28), + ETS_FC_COS_SHIFT = 23, +}; + +/* + * Flash Address Register (FLASH_ADDR) bit definitions. + */ +enum { + FLASH_ADDR_RDY = (1 << 31), + FLASH_ADDR_R = (1 << 30), + FLASH_ADDR_ERR = (1 << 29), +}; + +/* + * Stop CQ Processing Register (CQ_STOP) bit definitions. + */ +enum { + CQ_STOP_QUEUE_MASK = (0x007f0000), + CQ_STOP_TYPE_MASK = (0x03000000), + CQ_STOP_TYPE_START = 0x00000100, + CQ_STOP_TYPE_STOP = 0x00000200, + CQ_STOP_TYPE_READ = 0x00000300, + CQ_STOP_EN = (1 << 15), +}; + +/* + * MAC Protocol Address Index Register (MAC_ADDR_IDX) bit definitions. + */ +enum { + MAC_ADDR_IDX_SHIFT = 4, + MAC_ADDR_TYPE_SHIFT = 16, + MAC_ADDR_TYPE_MASK = 0x000f0000, + MAC_ADDR_TYPE_CAM_MAC = 0x00000000, + MAC_ADDR_TYPE_MULTI_MAC = 0x00010000, + MAC_ADDR_TYPE_VLAN = 0x00020000, + MAC_ADDR_TYPE_MULTI_FLTR = 0x00030000, + MAC_ADDR_TYPE_FC_MAC = 0x00040000, + MAC_ADDR_TYPE_MGMT_MAC = 0x00050000, + MAC_ADDR_TYPE_MGMT_VLAN = 0x00060000, + MAC_ADDR_TYPE_MGMT_V4 = 0x00070000, + MAC_ADDR_TYPE_MGMT_V6 = 0x00080000, + MAC_ADDR_TYPE_MGMT_TU_DP = 0x00090000, + MAC_ADDR_ADR = (1 << 25), + MAC_ADDR_RS = (1 << 26), + MAC_ADDR_E = (1 << 27), + MAC_ADDR_MR = (1 << 30), + MAC_ADDR_MW = (1 << 31), + MAX_MULTICAST_ENTRIES = 32, +}; + +/* + * MAC Protocol Address Index Register (SPLT_HDR) bit definitions. + */ +enum { + SPLT_HDR_EP = (1 << 31), +}; + +/* + * FCoE Receive Configuration Register (FC_RCV_CFG) bit definitions. + */ +enum { + FC_RCV_CFG_ECT = (1 << 15), + FC_RCV_CFG_DFH = (1 << 20), + FC_RCV_CFG_DVF = (1 << 21), + FC_RCV_CFG_RCE = (1 << 27), + FC_RCV_CFG_RFE = (1 << 28), + FC_RCV_CFG_TEE = (1 << 29), + FC_RCV_CFG_TCE = (1 << 30), + FC_RCV_CFG_TFE = (1 << 31), +}; + +/* + * NIC Receive Configuration Register (NIC_RCV_CFG) bit definitions. + */ +enum { + NIC_RCV_CFG_PPE = (1 << 0), + NIC_RCV_CFG_VLAN_MASK = 0x00060000, + NIC_RCV_CFG_VLAN_ALL = 0x00000000, + NIC_RCV_CFG_VLAN_MATCH_ONLY = 0x00000002, + NIC_RCV_CFG_VLAN_MATCH_AND_NON = 0x00000004, + NIC_RCV_CFG_VLAN_NONE_AND_NON = 0x00000006, + NIC_RCV_CFG_RV = (1 << 3), + NIC_RCV_CFG_DFQ_MASK = (0x7f000000), + NIC_RCV_CFG_DFQ_SHIFT = 8, + NIC_RCV_CFG_DFQ = 0, /* HARDCODE default queue to 0. */ +}; + +/* + * Mgmt Receive Configuration Register (MGMT_RCV_CFG) bit definitions. + */ +enum { + MGMT_RCV_CFG_ARP = (1 << 0), + MGMT_RCV_CFG_DHC = (1 << 1), + MGMT_RCV_CFG_DHS = (1 << 2), + MGMT_RCV_CFG_NP = (1 << 3), + MGMT_RCV_CFG_I6N = (1 << 4), + MGMT_RCV_CFG_I6R = (1 << 5), + MGMT_RCV_CFG_DH6 = (1 << 6), + MGMT_RCV_CFG_UD1 = (1 << 7), + MGMT_RCV_CFG_UD0 = (1 << 8), + MGMT_RCV_CFG_BCT = (1 << 9), + MGMT_RCV_CFG_MCT = (1 << 10), + MGMT_RCV_CFG_DM = (1 << 11), + MGMT_RCV_CFG_RM = (1 << 12), + MGMT_RCV_CFG_STL = (1 << 13), + MGMT_RCV_CFG_VLAN_MASK = 0xc0000000, + MGMT_RCV_CFG_VLAN_ALL = 0x00000000, + MGMT_RCV_CFG_VLAN_MATCH_ONLY = 0x00004000, + MGMT_RCV_CFG_VLAN_MATCH_AND_NON = 0x00008000, + MGMT_RCV_CFG_VLAN_NONE_AND_NON = 0x0000c000, +}; + +/* + * Routing Index Register (RT_IDX) bit definitions. + */ +enum { + RT_IDX_IDX_SHIFT = 8, + RT_IDX_TYPE_MASK = 0x000f0000, + RT_IDX_TYPE_RT = 0x00000000, + RT_IDX_TYPE_RT_INV = 0x00010000, + RT_IDX_TYPE_NICQ = 0x00020000, + RT_IDX_TYPE_NICQ_INV = 0x00030000, + RT_IDX_DST_MASK = 0x00700000, + RT_IDX_DST_RSS = 0x00000000, + RT_IDX_DST_CAM_Q = 0x00100000, + RT_IDX_DST_COS_Q = 0x00200000, + RT_IDX_DST_DFLT_Q = 0x00300000, + RT_IDX_DST_DEST_Q = 0x00400000, + RT_IDX_RS = (1 << 26), + RT_IDX_E = (1 << 27), + RT_IDX_MR = (1 << 30), + RT_IDX_MW = (1 << 31), + + /* Nic Queue format - type 2 bits */ + RT_IDX_BCAST = (1 << 0), + RT_IDX_MCAST = (1 << 1), + RT_IDX_MCAST_MATCH = (1 << 2), + RT_IDX_MCAST_REG_MATCH = (1 << 3), + RT_IDX_MCAST_HASH_MATCH = (1 << 4), + RT_IDX_FC_MACH = (1 << 5), + RT_IDX_ETH_FCOE = (1 << 6), + RT_IDX_CAM_HIT = (1 << 7), + RT_IDX_CAM_BIT0 = (1 << 8), + RT_IDX_CAM_BIT1 = (1 << 9), + RT_IDX_VLAN_TAG = (1 << 10), + RT_IDX_VLAN_MATCH = (1 << 11), + RT_IDX_VLAN_FILTER = (1 << 12), + RT_IDX_ETH_SKIP1 = (1 << 13), + RT_IDX_ETH_SKIP2 = (1 << 14), + RT_IDX_BCAST_MCAST_MATCH = (1 << 15), + RT_IDX_802_3 = (1 << 16), + RT_IDX_LLDP = (1 << 17), + RT_IDX_UNUSED018 = (1 << 18), + RT_IDX_UNUSED019 = (1 << 19), + RT_IDX_UNUSED20 = (1 << 20), + RT_IDX_UNUSED21 = (1 << 21), + RT_IDX_ERR = (1 << 22), + RT_IDX_VALID = (1 << 23), + RT_IDX_TU_CSUM_ERR = (1 << 24), + RT_IDX_IP_CSUM_ERR = (1 << 25), + RT_IDX_MAC_ERR = (1 << 26), + RT_IDX_RSS_TCP6 = (1 << 27), + RT_IDX_RSS_TCP4 = (1 << 28), + RT_IDX_RSS_IPV6 = (1 << 29), + RT_IDX_RSS_IPV4 = (1 << 30), + RT_IDX_RSS_MATCH = (1 << 31), + + /* Hierarchy for the NIC Queue Mask */ + RT_IDX_ALL_ERR_SLOT = 0, + RT_IDX_MAC_ERR_SLOT = 0, + RT_IDX_IP_CSUM_ERR_SLOT = 1, + RT_IDX_TCP_UDP_CSUM_ERR_SLOT = 2, + RT_IDX_BCAST_SLOT = 3, + RT_IDX_MCAST_MATCH_SLOT = 4, + RT_IDX_ALLMULTI_SLOT = 5, + RT_IDX_UNUSED6_SLOT = 6, + RT_IDX_UNUSED7_SLOT = 7, + RT_IDX_RSS_MATCH_SLOT = 8, + RT_IDX_RSS_IPV4_SLOT = 8, + RT_IDX_RSS_IPV6_SLOT = 9, + RT_IDX_RSS_TCP4_SLOT = 10, + RT_IDX_RSS_TCP6_SLOT = 11, + RT_IDX_CAM_HIT_SLOT = 12, + RT_IDX_UNUSED013 = 13, + RT_IDX_UNUSED014 = 14, + RT_IDX_PROMISCUOUS_SLOT = 15, + RT_IDX_MAX_SLOTS = 16, +}; + +/* + * Control Register Set Map + */ +enum { + PROC_ADDR = 0, /* Use semaphore */ + PROC_DATA = 0x04, /* Use semaphore */ + SYS = 0x08, + RST_FO = 0x0c, + FSC = 0x10, + CSR = 0x14, + LED = 0x18, + ICB_RID = 0x1c, /* Use semaphore */ + ICB_L = 0x20, /* Use semaphore */ + ICB_H = 0x24, /* Use semaphore */ + CFG = 0x28, + BIOS_ADDR = 0x2c, + STS = 0x30, + INTR_EN = 0x34, + INTR_MASK = 0x38, + ISR1 = 0x3c, + ISR2 = 0x40, + ISR3 = 0x44, + ISR4 = 0x48, + REV_ID = 0x4c, + FRC_ECC_ERR = 0x50, + ERR_STS = 0x54, + RAM_DBG_ADDR = 0x58, + RAM_DBG_DATA = 0x5c, + ECC_ERR_CNT = 0x60, + SEM = 0x64, + GPIO_1 = 0x68, /* Use semaphore */ + GPIO_2 = 0x6c, /* Use semaphore */ + GPIO_3 = 0x70, /* Use semaphore */ + RSVD2 = 0x74, + XGMAC_ADDR = 0x78, /* Use semaphore */ + XGMAC_DATA = 0x7c, /* Use semaphore */ + NIC_ETS = 0x80, + CNA_ETS = 0x84, + FLASH_ADDR = 0x88, /* Use semaphore */ + FLASH_DATA = 0x8c, /* Use semaphore */ + CQ_STOP = 0x90, + PAGE_TBL_RID = 0x94, + WQ_PAGE_TBL_LO = 0x98, + WQ_PAGE_TBL_HI = 0x9c, + CQ_PAGE_TBL_LO = 0xa0, + CQ_PAGE_TBL_HI = 0xa4, + MAC_ADDR_IDX = 0xa8, /* Use semaphore */ + MAC_ADDR_DATA = 0xac, /* Use semaphore */ + COS_DFLT_CQ1 = 0xb0, + COS_DFLT_CQ2 = 0xb4, + ETYPE_SKIP1 = 0xb8, + ETYPE_SKIP2 = 0xbc, + SPLT_HDR = 0xc0, + FC_PAUSE_THRES = 0xc4, + NIC_PAUSE_THRES = 0xc8, + FC_ETHERTYPE = 0xcc, + FC_RCV_CFG = 0xd0, + NIC_RCV_CFG = 0xd4, + FC_COS_TAGS = 0xd8, + NIC_COS_TAGS = 0xdc, + MGMT_RCV_CFG = 0xe0, + RT_IDX = 0xe4, + RT_DATA = 0xe8, + RSVD7 = 0xec, + XG_SERDES_ADDR = 0xf0, + XG_SERDES_DATA = 0xf4, + PRB_MX_ADDR = 0xf8, /* Use semaphore */ + PRB_MX_DATA = 0xfc, /* Use semaphore */ +}; + +/* + * CAM output format. + */ +enum { + CAM_OUT_ROUTE_FC = 0, + CAM_OUT_ROUTE_NIC = 1, + CAM_OUT_FUNC_SHIFT = 2, + CAM_OUT_RV = (1 << 4), + CAM_OUT_SH = (1 << 15), + CAM_OUT_CQ_ID_SHIFT = 5, +}; + +/* + * Mailbox definitions + */ +enum { + /* Asynchronous Event Notifications */ + AEN_SYS_ERR = 0x00008002, + AEN_LINK_UP = 0x00008011, + AEN_LINK_DOWN = 0x00008012, + AEN_IDC_CMPLT = 0x00008100, + AEN_IDC_REQ = 0x00008101, + AEN_FW_INIT_DONE = 0x00008400, + AEN_FW_INIT_FAIL = 0x00008401, + + /* Mailbox Command Opcodes. */ + MB_CMD_NOP = 0x00000000, + MB_CMD_EX_FW = 0x00000002, + MB_CMD_MB_TEST = 0x00000006, + MB_CMD_CSUM_TEST = 0x00000007, /* Verify Checksum */ + MB_CMD_ABOUT_FW = 0x00000008, + MB_CMD_LOAD_RISC_RAM = 0x0000000b, + MB_CMD_DUMP_RISC_RAM = 0x0000000c, + MB_CMD_WRITE_RAM = 0x0000000d, + MB_CMD_READ_RAM = 0x0000000f, + MB_CMD_STOP_FW = 0x00000014, + MB_CMD_MAKE_SYS_ERR = 0x0000002a, + MB_CMD_INIT_FW = 0x00000060, + MB_CMD_GET_INIT_CB = 0x00000061, + MB_CMD_GET_FW_STATE = 0x00000069, + MB_CMD_IDC_REQ = 0x00000100, /* Inter-Driver Communication */ + MB_CMD_IDC_ACK = 0x00000101, /* Inter-Driver Communication */ + MB_CMD_SET_WOL_MODE = 0x00000110, /* Wake On Lan */ + MB_WOL_DISABLE = 0x00000000, + MB_WOL_MAGIC_PKT = 0x00000001, + MB_WOL_FLTR = 0x00000002, + MB_WOL_UCAST = 0x00000004, + MB_WOL_MCAST = 0x00000008, + MB_WOL_BCAST = 0x00000010, + MB_WOL_LINK_UP = 0x00000020, + MB_WOL_LINK_DOWN = 0x00000040, + MB_CMD_SET_WOL_FLTR = 0x00000111, /* Wake On Lan Filter */ + MB_CMD_CLEAR_WOL_FLTR = 0x00000112, /* Wake On Lan Filter */ + MB_CMD_SET_WOL_MAGIC = 0x00000113, /* Wake On Lan Magic Packet */ + MB_CMD_CLEAR_WOL_MAGIC = 0x00000114, /* Wake On Lan Magic Packet */ + MB_CMD_PORT_RESET = 0x00000120, + MB_CMD_SET_PORT_CFG = 0x00000122, + MB_CMD_GET_PORT_CFG = 0x00000123, + MB_CMD_SET_ASIC_VOLTS = 0x00000130, + MB_CMD_GET_SNS_DATA = 0x00000131, /* Temp and Volt Sense data. */ + + /* Mailbox Command Status. */ + MB_CMD_STS_GOOD = 0x00004000, /* Success. */ + MB_CMD_STS_INTRMDT = 0x00001000, /* Intermediate Complete. */ + MB_CMD_STS_ERR = 0x00004005, /* Error. */ +}; + +struct mbox_params { + u32 mbox_in[MAILBOX_COUNT]; + u32 mbox_out[MAILBOX_COUNT]; + int in_count; + int out_count; +}; + +struct flash_params { + u8 dev_id_str[4]; + u16 size; + u16 csum; + u16 ver; + u16 sub_dev_id; + u8 mac_addr[6]; + u16 res; +}; + + +/* + * doorbell space for the rx ring context + */ +struct rx_doorbell_context { + u32 cnsmr_idx; /* 0x00 */ + u32 valid; /* 0x04 */ + u32 reserved[4]; /* 0x08-0x14 */ + u32 lbq_prod_idx; /* 0x18 */ + u32 sbq_prod_idx; /* 0x1c */ +}; + +/* + * doorbell space for the tx ring context + */ +struct tx_doorbell_context { + u32 prod_idx; /* 0x00 */ + u32 valid; /* 0x04 */ + u32 reserved[4]; /* 0x08-0x14 */ + u32 lbq_prod_idx; /* 0x18 */ + u32 sbq_prod_idx; /* 0x1c */ +}; + +/* DATA STRUCTURES SHARED WITH HARDWARE. */ + +struct bq_element { + u32 addr_lo; +#define BQ_END 0x00000001 +#define BQ_CONT 0x00000002 +#define BQ_MASK 0x00000003 + u32 addr_hi; +} __attribute((packed)); + +struct tx_buf_desc { + __le64 addr; + __le32 len; +#define TX_DESC_LEN_MASK 0x000fffff +#define TX_DESC_C 0x40000000 +#define TX_DESC_E 0x80000000 +} __attribute((packed)); + +/* + * IOCB Definitions... + */ + +#define OPCODE_OB_MAC_IOCB 0x01 +#define OPCODE_OB_MAC_TSO_IOCB 0x02 +#define OPCODE_IB_MAC_IOCB 0x20 +#define OPCODE_IB_MPI_IOCB 0x21 +#define OPCODE_IB_AE_IOCB 0x3f + +struct ob_mac_iocb_req { + u8 opcode; + u8 flags1; +#define OB_MAC_IOCB_REQ_OI 0x01 +#define OB_MAC_IOCB_REQ_I 0x02 +#define OB_MAC_IOCB_REQ_D 0x08 +#define OB_MAC_IOCB_REQ_F 0x10 + u8 flags2; + u8 flags3; +#define OB_MAC_IOCB_DFP 0x02 +#define OB_MAC_IOCB_V 0x04 + __le32 reserved1[2]; + __le16 frame_len; +#define OB_MAC_IOCB_LEN_MASK 0x3ffff + __le16 reserved2; + __le32 tid; + __le32 txq_idx; + __le32 reserved3; + __le16 vlan_tci; + __le16 reserved4; + struct tx_buf_desc tbd[TX_DESC_PER_IOCB]; +} __attribute((packed)); + +struct ob_mac_iocb_rsp { + u8 opcode; /* */ + u8 flags1; /* */ +#define OB_MAC_IOCB_RSP_OI 0x01 /* */ +#define OB_MAC_IOCB_RSP_I 0x02 /* */ +#define OB_MAC_IOCB_RSP_E 0x08 /* */ +#define OB_MAC_IOCB_RSP_S 0x10 /* too Short */ +#define OB_MAC_IOCB_RSP_L 0x20 /* too Large */ +#define OB_MAC_IOCB_RSP_P 0x40 /* Padded */ + u8 flags2; /* */ + u8 flags3; /* */ +#define OB_MAC_IOCB_RSP_B 0x80 /* */ + __le32 tid; + __le32 txq_idx; + __le32 reserved[13]; +} __attribute((packed)); + +struct ob_mac_tso_iocb_req { + u8 opcode; + u8 flags1; +#define OB_MAC_TSO_IOCB_OI 0x01 +#define OB_MAC_TSO_IOCB_I 0x02 +#define OB_MAC_TSO_IOCB_D 0x08 +#define OB_MAC_TSO_IOCB_IP4 0x40 +#define OB_MAC_TSO_IOCB_IP6 0x80 + u8 flags2; +#define OB_MAC_TSO_IOCB_LSO 0x20 +#define OB_MAC_TSO_IOCB_UC 0x40 +#define OB_MAC_TSO_IOCB_TC 0x80 + u8 flags3; +#define OB_MAC_TSO_IOCB_IC 0x01 +#define OB_MAC_TSO_IOCB_DFP 0x02 +#define OB_MAC_TSO_IOCB_V 0x04 + __le32 reserved1[2]; + __le32 frame_len; + __le32 tid; + __le32 txq_idx; + __le16 total_hdrs_len; + __le16 net_trans_offset; +#define OB_MAC_TRANSPORT_HDR_SHIFT 6 + __le16 vlan_tci; + __le16 mss; + struct tx_buf_desc tbd[TX_DESC_PER_IOCB]; +} __attribute((packed)); + +struct ob_mac_tso_iocb_rsp { + u8 opcode; + u8 flags1; +#define OB_MAC_TSO_IOCB_RSP_OI 0x01 +#define OB_MAC_TSO_IOCB_RSP_I 0x02 +#define OB_MAC_TSO_IOCB_RSP_E 0x08 +#define OB_MAC_TSO_IOCB_RSP_S 0x10 +#define OB_MAC_TSO_IOCB_RSP_L 0x20 +#define OB_MAC_TSO_IOCB_RSP_P 0x40 + u8 flags2; /* */ + u8 flags3; /* */ +#define OB_MAC_TSO_IOCB_RSP_B 0x8000 + __le32 tid; + __le32 txq_idx; + __le32 reserved2[13]; +} __attribute((packed)); + +struct ib_mac_iocb_rsp { + u8 opcode; /* 0x20 */ + u8 flags1; +#define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */ +#define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */ +#define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */ +#define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */ +#define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */ +#define IB_MAC_IOCB_RSP_M_MASK 0x60 /* Multicast info */ +#define IB_MAC_IOCB_RSP_M_NONE 0x00 /* Not mcast frame */ +#define IB_MAC_IOCB_RSP_M_HASH 0x20 /* HASH mcast frame */ +#define IB_MAC_IOCB_RSP_M_REG 0x40 /* Registered mcast frame */ +#define IB_MAC_IOCB_RSP_M_PROM 0x60 /* Promiscuous mcast frame */ +#define IB_MAC_IOCB_RSP_B 0x80 /* Broadcast frame */ + u8 flags2; +#define IB_MAC_IOCB_RSP_P 0x01 /* Promiscuous frame */ +#define IB_MAC_IOCB_RSP_V 0x02 /* Vlan tag present */ +#define IB_MAC_IOCB_RSP_ERR_MASK 0x1c /* */ +#define IB_MAC_IOCB_RSP_ERR_CODE_ERR 0x04 +#define IB_MAC_IOCB_RSP_ERR_OVERSIZE 0x08 +#define IB_MAC_IOCB_RSP_ERR_UNDERSIZE 0x10 +#define IB_MAC_IOCB_RSP_ERR_PREAMBLE 0x14 +#define IB_MAC_IOCB_RSP_ERR_FRAME_LEN 0x18 +#define IB_MAC_IOCB_RSP_ERR_CRC 0x1c +#define IB_MAC_IOCB_RSP_U 0x20 /* UDP packet */ +#define IB_MAC_IOCB_RSP_T 0x40 /* TCP packet */ +#define IB_MAC_IOCB_RSP_FO 0x80 /* Failover port */ + u8 flags3; +#define IB_MAC_IOCB_RSP_RSS_MASK 0x07 /* RSS mask */ +#define IB_MAC_IOCB_RSP_M_NONE 0x00 /* No RSS match */ +#define IB_MAC_IOCB_RSP_M_IPV4 0x04 /* IPv4 RSS match */ +#define IB_MAC_IOCB_RSP_M_IPV6 0x02 /* IPv6 RSS match */ +#define IB_MAC_IOCB_RSP_M_TCP_V4 0x05 /* TCP with IPv4 */ +#define IB_MAC_IOCB_RSP_M_TCP_V6 0x03 /* TCP with IPv6 */ +#define IB_MAC_IOCB_RSP_V4 0x08 /* IPV4 */ +#define IB_MAC_IOCB_RSP_V6 0x10 /* IPV6 */ +#define IB_MAC_IOCB_RSP_IH 0x20 /* Split after IP header */ +#define IB_MAC_IOCB_RSP_DS 0x40 /* data is in small buffer */ +#define IB_MAC_IOCB_RSP_DL 0x80 /* data is in large buffer */ + __le32 data_len; /* */ + __le32 data_addr_lo; /* */ + __le32 data_addr_hi; /* */ + __le32 rss; /* */ + __le16 vlan_id; /* 12 bits */ +#define IB_MAC_IOCB_RSP_C 0x1000 /* VLAN CFI bit */ +#define IB_MAC_IOCB_RSP_COS_SHIFT 12 /* class of service value */ + + __le16 reserved1; + __le32 reserved2[6]; + __le32 flags4; +#define IB_MAC_IOCB_RSP_HV 0x20000000 /* */ +#define IB_MAC_IOCB_RSP_HS 0x40000000 /* */ +#define IB_MAC_IOCB_RSP_HL 0x80000000 /* */ + __le32 hdr_len; /* */ + __le32 hdr_addr_lo; /* */ + __le32 hdr_addr_hi; /* */ +} __attribute((packed)); + +struct ib_ae_iocb_rsp { + u8 opcode; + u8 flags1; +#define IB_AE_IOCB_RSP_OI 0x01 +#define IB_AE_IOCB_RSP_I 0x02 + u8 event; +#define LINK_UP_EVENT 0x00 +#define LINK_DOWN_EVENT 0x01 +#define CAM_LOOKUP_ERR_EVENT 0x06 +#define SOFT_ECC_ERROR_EVENT 0x07 +#define MGMT_ERR_EVENT 0x08 +#define TEN_GIG_MAC_EVENT 0x09 +#define GPI0_H2L_EVENT 0x10 +#define GPI0_L2H_EVENT 0x20 +#define GPI1_H2L_EVENT 0x11 +#define GPI1_L2H_EVENT 0x21 +#define PCI_ERR_ANON_BUF_RD 0x40 + u8 q_id; + __le32 reserved[15]; +} __attribute((packed)); + +/* + * These three structures are for generic + * handling of ib and ob iocbs. + */ +struct ql_net_rsp_iocb { + u8 opcode; + u8 flags0; + __le16 length; + __le32 tid; + __le32 reserved[14]; +} __attribute((packed)); + +struct net_req_iocb { + u8 opcode; + u8 flags0; + __le16 flags1; + __le32 tid; + __le32 reserved1[30]; +} __attribute((packed)); + +/* + * tx ring initialization control block for chip. + * It is defined as: + * "Work Queue Initialization Control Block" + */ +struct wqicb { + __le16 len; +#define Q_LEN_V (1 << 4) +#define Q_LEN_CPP_CONT 0x0000 +#define Q_LEN_CPP_16 0x0001 +#define Q_LEN_CPP_32 0x0002 +#define Q_LEN_CPP_64 0x0003 + __le16 flags; +#define Q_PRI_SHIFT 1 +#define Q_FLAGS_LC 0x1000 +#define Q_FLAGS_LB 0x2000 +#define Q_FLAGS_LI 0x4000 +#define Q_FLAGS_LO 0x8000 + __le16 cq_id_rss; +#define Q_CQ_ID_RSS_RV 0x8000 + __le16 rid; + __le32 addr_lo; + __le32 addr_hi; + __le32 cnsmr_idx_addr_lo; + __le32 cnsmr_idx_addr_hi; +} __attribute((packed)); + +/* + * rx ring initialization control block for chip. + * It is defined as: + * "Completion Queue Initialization Control Block" + */ +struct cqicb { + u8 msix_vect; + u8 reserved1; + u8 reserved2; + u8 flags; +#define FLAGS_LV 0x08 +#define FLAGS_LS 0x10 +#define FLAGS_LL 0x20 +#define FLAGS_LI 0x40 +#define FLAGS_LC 0x80 + __le16 len; +#define LEN_V (1 << 4) +#define LEN_CPP_CONT 0x0000 +#define LEN_CPP_32 0x0001 +#define LEN_CPP_64 0x0002 +#define LEN_CPP_128 0x0003 + __le16 rid; + __le32 addr_lo; + __le32 addr_hi; + __le32 prod_idx_addr_lo; + __le32 prod_idx_addr_hi; + __le16 pkt_delay; + __le16 irq_delay; + __le32 lbq_addr_lo; + __le32 lbq_addr_hi; + __le16 lbq_buf_size; + __le16 lbq_len; /* entry count */ + __le32 sbq_addr_lo; + __le32 sbq_addr_hi; + __le16 sbq_buf_size; + __le16 sbq_len; /* entry count */ +} __attribute((packed)); + +struct ricb { + u8 base_cq; +#define RSS_L4K 0x80 + u8 flags; +#define RSS_L6K 0x01 +#define RSS_LI 0x02 +#define RSS_LB 0x04 +#define RSS_LM 0x08 +#define RSS_RI4 0x10 +#define RSS_RT4 0x20 +#define RSS_RI6 0x40 +#define RSS_RT6 0x80 + __le16 mask; + __le32 hash_cq_id[256]; + __le32 ipv6_hash_key[10]; + __le32 ipv4_hash_key[4]; +} __attribute((packed)); + +/* SOFTWARE/DRIVER DATA STRUCTURES. */ + +struct oal { + struct tx_buf_desc oal[TX_DESC_PER_OAL]; +}; + +struct map_list { + DECLARE_PCI_UNMAP_ADDR(mapaddr); + DECLARE_PCI_UNMAP_LEN(maplen); +}; + +struct tx_ring_desc { + struct sk_buff *skb; + struct ob_mac_iocb_req *queue_entry; + int index; + struct oal oal; + struct map_list map[MAX_SKB_FRAGS + 1]; + int map_cnt; + struct tx_ring_desc *next; +}; + +struct bq_desc { + union { + struct page *lbq_page; + struct sk_buff *skb; + } p; + struct bq_element *bq; + int index; + DECLARE_PCI_UNMAP_ADDR(mapaddr); + DECLARE_PCI_UNMAP_LEN(maplen); +}; + +#define QL_TXQ_IDX(qdev, skb) (smp_processor_id()%(qdev->tx_ring_count)) + +struct tx_ring { + /* + * queue info. + */ + struct wqicb wqicb; /* structure used to inform chip of new queue */ + void *wq_base; /* pci_alloc:virtual addr for tx */ + dma_addr_t wq_base_dma; /* pci_alloc:dma addr for tx */ + u32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */ + dma_addr_t cnsmr_idx_sh_reg_dma; /* dma-shadow copy of consumer */ + u32 wq_size; /* size in bytes of queue area */ + u32 wq_len; /* number of entries in queue */ + void __iomem *prod_idx_db_reg; /* doorbell area index reg at offset 0x00 */ + void __iomem *valid_db_reg; /* doorbell area valid reg at offset 0x04 */ + u16 prod_idx; /* current value for prod idx */ + u16 cq_id; /* completion (rx) queue for tx completions */ + u8 wq_id; /* queue id for this entry */ + u8 reserved1[3]; + struct tx_ring_desc *q; /* descriptor list for the queue */ + spinlock_t lock; + atomic_t tx_count; /* counts down for every outstanding IO */ + atomic_t queue_stopped; /* Turns queue off when full. */ + struct delayed_work tx_work; + struct ql_adapter *qdev; +}; + +/* + * Type of inbound queue. + */ +enum { + DEFAULT_Q = 2, /* Handles slow queue and chip/MPI events. */ + TX_Q = 3, /* Handles outbound completions. */ + RX_Q = 4, /* Handles inbound completions. */ +}; + +struct rx_ring { + struct cqicb cqicb; /* The chip's completion queue init control block. */ + + /* Completion queue elements. */ + void *cq_base; + dma_addr_t cq_base_dma; + u32 cq_size; + u32 cq_len; + u16 cq_id; + u32 *prod_idx_sh_reg; /* Shadowed producer register. */ + dma_addr_t prod_idx_sh_reg_dma; + void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ + u32 cnsmr_idx; /* current sw idx */ + struct ql_net_rsp_iocb *curr_entry; /* next entry on queue */ + void __iomem *valid_db_reg; /* PCI doorbell mem area + 0x04 */ + + /* Large buffer queue elements. */ + u32 lbq_len; /* entry count */ + u32 lbq_size; /* size in bytes of queue */ + u32 lbq_buf_size; + void *lbq_base; + dma_addr_t lbq_base_dma; + void *lbq_base_indirect; + dma_addr_t lbq_base_indirect_dma; + struct bq_desc *lbq; /* array of control blocks */ + void __iomem *lbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x18 */ + u32 lbq_prod_idx; /* current sw prod idx */ + u32 lbq_curr_idx; /* next entry we expect */ + u32 lbq_clean_idx; /* beginning of new descs */ + u32 lbq_free_cnt; /* free buffer desc cnt */ + + /* Small buffer queue elements. */ + u32 sbq_len; /* entry count */ + u32 sbq_size; /* size in bytes of queue */ + u32 sbq_buf_size; + void *sbq_base; + dma_addr_t sbq_base_dma; + void *sbq_base_indirect; + dma_addr_t sbq_base_indirect_dma; + struct bq_desc *sbq; /* array of control blocks */ + void __iomem *sbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x1c */ + u32 sbq_prod_idx; /* current sw prod idx */ + u32 sbq_curr_idx; /* next entry we expect */ + u32 sbq_clean_idx; /* beginning of new descs */ + u32 sbq_free_cnt; /* free buffer desc cnt */ + + /* Misc. handler elements. */ + u32 type; /* Type of queue, tx, rx, or default. */ + u32 irq; /* Which vector this ring is assigned. */ + u32 cpu; /* Which CPU this should run on. */ + char name[IFNAMSIZ + 5]; + struct napi_struct napi; + struct delayed_work rx_work; + u8 reserved; + struct ql_adapter *qdev; +}; + +/* + * RSS Initialization Control Block + */ +struct hash_id { + u8 value[4]; +}; + +struct nic_stats { + /* + * These stats come from offset 200h to 278h + * in the XGMAC register. + */ + u64 tx_pkts; + u64 tx_bytes; + u64 tx_mcast_pkts; + u64 tx_bcast_pkts; + u64 tx_ucast_pkts; + u64 tx_ctl_pkts; + u64 tx_pause_pkts; + u64 tx_64_pkt; + u64 tx_65_to_127_pkt; + u64 tx_128_to_255_pkt; + u64 tx_256_511_pkt; + u64 tx_512_to_1023_pkt; + u64 tx_1024_to_1518_pkt; + u64 tx_1519_to_max_pkt; + u64 tx_undersize_pkt; + u64 tx_oversize_pkt; + + /* + * These stats come from offset 300h to 3C8h + * in the XGMAC register. + */ + u64 rx_bytes; + u64 rx_bytes_ok; + u64 rx_pkts; + u64 rx_pkts_ok; + u64 rx_bcast_pkts; + u64 rx_mcast_pkts; + u64 rx_ucast_pkts; + u64 rx_undersize_pkts; + u64 rx_oversize_pkts; + u64 rx_jabber_pkts; + u64 rx_undersize_fcerr_pkts; + u64 rx_drop_events; + u64 rx_fcerr_pkts; + u64 rx_align_err; + u64 rx_symbol_err; + u64 rx_mac_err; + u64 rx_ctl_pkts; + u64 rx_pause_pkts; + u64 rx_64_pkts; + u64 rx_65_to_127_pkts; + u64 rx_128_255_pkts; + u64 rx_256_511_pkts; + u64 rx_512_to_1023_pkts; + u64 rx_1024_to_1518_pkts; + u64 rx_1519_to_max_pkts; + u64 rx_len_err_pkts; +}; + +/* + * intr_context structure is used during initialization + * to hook the interrupts. It is also used in a single + * irq environment as a context to the ISR. + */ +struct intr_context { + struct ql_adapter *qdev; + u32 intr; + u32 hooked; + u32 intr_en_mask; /* value/mask used to enable this intr */ + u32 intr_dis_mask; /* value/mask used to disable this intr */ + u32 intr_read_mask; /* value/mask used to read this intr */ + char name[IFNAMSIZ * 2]; + atomic_t irq_cnt; /* irq_cnt is used in single vector + * environment. It's incremented for each + * irq handler that is scheduled. When each + * handler finishes it decrements irq_cnt and + * enables interrupts if it's zero. */ + irq_handler_t handler; +}; + +/* adapter flags definitions. */ +enum { + QL_ADAPTER_UP = (1 << 0), /* Adapter has been brought up. */ + QL_LEGACY_ENABLED = (1 << 3), + QL_MSI_ENABLED = (1 << 3), + QL_MSIX_ENABLED = (1 << 4), + QL_DMA64 = (1 << 5), + QL_PROMISCUOUS = (1 << 6), + QL_ALLMULTI = (1 << 7), +}; + +/* link_status bit definitions */ +enum { + LOOPBACK_MASK = 0x00000700, + LOOPBACK_PCS = 0x00000100, + LOOPBACK_HSS = 0x00000200, + LOOPBACK_EXT = 0x00000300, + PAUSE_MASK = 0x000000c0, + PAUSE_STD = 0x00000040, + PAUSE_PRI = 0x00000080, + SPEED_MASK = 0x00000038, + SPEED_100Mb = 0x00000000, + SPEED_1Gb = 0x00000008, + SPEED_10Gb = 0x00000010, + LINK_TYPE_MASK = 0x00000007, + LINK_TYPE_XFI = 0x00000001, + LINK_TYPE_XAUI = 0x00000002, + LINK_TYPE_XFI_BP = 0x00000003, + LINK_TYPE_XAUI_BP = 0x00000004, + LINK_TYPE_10GBASET = 0x00000005, +}; + +/* + * The main Adapter structure definition. + * This structure has all fields relevant to the hardware. + */ +struct ql_adapter { + struct ricb ricb; + unsigned long flags; + u32 wol; + + struct nic_stats nic_stats; + + struct vlan_group *vlgrp; + + /* PCI Configuration information for this device */ + struct pci_dev *pdev; + struct net_device *ndev; /* Parent NET device */ + + /* Hardware information */ + u32 chip_rev_id; + u32 func; /* PCI function for this adapter */ + + spinlock_t adapter_lock; + spinlock_t hw_lock; + spinlock_t stats_lock; + spinlock_t legacy_lock; /* used for maintaining legacy intr sync */ + + /* PCI Bus Relative Register Addresses */ + void __iomem *reg_base; + void __iomem *doorbell_area; + u32 doorbell_area_size; + + u32 msg_enable; + + /* Page for Shadow Registers */ + void *rx_ring_shadow_reg_area; + dma_addr_t rx_ring_shadow_reg_dma; + void *tx_ring_shadow_reg_area; + dma_addr_t tx_ring_shadow_reg_dma; + + u32 mailbox_in; + u32 mailbox_out; + + int tx_ring_size; + int rx_ring_size; + u32 intr_count; + struct msix_entry *msi_x_entry; + struct intr_context intr_context[MAX_RX_RINGS]; + + int (*legacy_check) (struct ql_adapter *); + + int tx_ring_count; /* One per online CPU. */ + u32 rss_ring_first_cq_id;/* index of first inbound (rss) rx_ring */ + u32 rss_ring_count; /* One per online CPU. */ + /* + * rx_ring_count = + * one default queue + + * (CPU count * outbound completion rx_ring) + + * (CPU count * inbound (RSS) completion rx_ring) + */ + int rx_ring_count; + int ring_mem_size; + void *ring_mem; + struct rx_ring *rx_ring; + int rx_csum; + struct tx_ring *tx_ring; + u32 default_rx_queue; + + u16 rx_coalesce_usecs; /* cqicb->int_delay */ + u16 rx_max_coalesced_frames; /* cqicb->pkt_int_delay */ + u16 tx_coalesce_usecs; /* cqicb->int_delay */ + u16 tx_max_coalesced_frames; /* cqicb->pkt_int_delay */ + + u32 xg_sem_mask; + u32 port_link_up; + u32 port_init; + u32 link_status; + + struct flash_params flash; + + struct net_device_stats stats; + struct workqueue_struct *q_workqueue; + struct workqueue_struct *workqueue; + struct delayed_work asic_reset_work; + struct delayed_work mpi_reset_work; + struct delayed_work mpi_work; +}; + +/* + * Typical Register accessor for memory mapped device. + */ +static inline u32 ql_read32(const struct ql_adapter *qdev, int reg) +{ + return readl(qdev->reg_base + reg); +} + +/* + * Typical Register accessor for memory mapped device. + */ +static inline void ql_write32(const struct ql_adapter *qdev, int reg, u32 val) +{ + writel(val, qdev->reg_base + reg); +} + +/* + * Doorbell Registers: + * Doorbell registers are virtual registers in the PCI memory space. + * The space is allocated by the chip during PCI initialization. The + * device driver finds the doorbell address in BAR 3 in PCI config space. + * The registers are used to control outbound and inbound queues. For + * example, the producer index for an outbound queue. Each queue uses + * 1 4k chunk of memory. The lower half of the space is for outbound + * queues. The upper half is for inbound queues. + */ +static inline void ql_write_db_reg(u32 val, void __iomem *addr) +{ + writel(val, addr); + mmiowb(); +} + +/* + * Shadow Registers: + * Outbound queues have a consumer index that is maintained by the chip. + * Inbound queues have a producer index that is maintained by the chip. + * For lower overhead, these registers are "shadowed" to host memory + * which allows the device driver to track the queue progress without + * PCI reads. When an entry is placed on an inbound queue, the chip will + * update the relevant index register and then copy the value to the + * shadow register in host memory. + */ +static inline unsigned int ql_read_sh_reg(const volatile void *addr) +{ + return *(volatile unsigned int __force *)addr; +} + +extern char qlge_driver_name[]; +extern const char qlge_driver_version[]; +extern const struct ethtool_ops qlge_ethtool_ops; + +extern int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask); +extern void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask); +extern int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data); +extern int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, + u32 *value); +extern int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value); +extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, + u16 q_id); +void ql_queue_fw_error(struct ql_adapter *qdev); +void ql_mpi_work(struct work_struct *work); +void ql_mpi_reset_work(struct work_struct *work); +int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit); +void ql_queue_asic_error(struct ql_adapter *qdev); +void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); +void ql_set_ethtool_ops(struct net_device *ndev); +int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); + +#if 1 +#define QL_ALL_DUMP +#define QL_REG_DUMP +#define QL_DEV_DUMP +#define QL_CB_DUMP +/* #define QL_IB_DUMP */ +/* #define QL_OB_DUMP */ +#endif + +#ifdef QL_REG_DUMP +extern void ql_dump_xgmac_control_regs(struct ql_adapter *qdev); +extern void ql_dump_routing_entries(struct ql_adapter *qdev); +extern void ql_dump_regs(struct ql_adapter *qdev); +#define QL_DUMP_REGS(qdev) ql_dump_regs(qdev) +#define QL_DUMP_ROUTE(qdev) ql_dump_routing_entries(qdev) +#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) ql_dump_xgmac_control_regs(qdev) +#else +#define QL_DUMP_REGS(qdev) +#define QL_DUMP_ROUTE(qdev) +#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) +#endif + +#ifdef QL_STAT_DUMP +extern void ql_dump_stat(struct ql_adapter *qdev); +#define QL_DUMP_STAT(qdev) ql_dump_stat(qdev) +#else +#define QL_DUMP_STAT(qdev) +#endif + +#ifdef QL_DEV_DUMP +extern void ql_dump_qdev(struct ql_adapter *qdev); +#define QL_DUMP_QDEV(qdev) ql_dump_qdev(qdev) +#else +#define QL_DUMP_QDEV(qdev) +#endif + +#ifdef QL_CB_DUMP +extern void ql_dump_wqicb(struct wqicb *wqicb); +extern void ql_dump_tx_ring(struct tx_ring *tx_ring); +extern void ql_dump_ricb(struct ricb *ricb); +extern void ql_dump_cqicb(struct cqicb *cqicb); +extern void ql_dump_rx_ring(struct rx_ring *rx_ring); +extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id); +#define QL_DUMP_RICB(ricb) ql_dump_ricb(ricb) +#define QL_DUMP_WQICB(wqicb) ql_dump_wqicb(wqicb) +#define QL_DUMP_TX_RING(tx_ring) ql_dump_tx_ring(tx_ring) +#define QL_DUMP_CQICB(cqicb) ql_dump_cqicb(cqicb) +#define QL_DUMP_RX_RING(rx_ring) ql_dump_rx_ring(rx_ring) +#define QL_DUMP_HW_CB(qdev, size, bit, q_id) \ + ql_dump_hw_cb(qdev, size, bit, q_id) +#else +#define QL_DUMP_RICB(ricb) +#define QL_DUMP_WQICB(wqicb) +#define QL_DUMP_TX_RING(tx_ring) +#define QL_DUMP_CQICB(cqicb) +#define QL_DUMP_RX_RING(rx_ring) +#define QL_DUMP_HW_CB(qdev, size, bit, q_id) +#endif + +#ifdef QL_OB_DUMP +extern void ql_dump_tx_desc(struct tx_buf_desc *tbd); +extern void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb); +extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp); +#define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb) ql_dump_ob_mac_iocb(ob_mac_iocb) +#define QL_DUMP_OB_MAC_RSP(ob_mac_rsp) ql_dump_ob_mac_rsp(ob_mac_rsp) +#else +#define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb) +#define QL_DUMP_OB_MAC_RSP(ob_mac_rsp) +#endif + +#ifdef QL_IB_DUMP +extern void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp); +#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp) ql_dump_ib_mac_rsp(ib_mac_rsp) +#else +#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp) +#endif + +#ifdef QL_ALL_DUMP +extern void ql_dump_all(struct ql_adapter *qdev); +#define QL_DUMP_ALL(qdev) ql_dump_all(qdev) +#else +#define QL_DUMP_ALL(qdev) +#endif + +#endif /* _QLGE_H_ */ diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c new file mode 100644 index 00000000000..f0392b16617 --- /dev/null +++ b/drivers/net/qlge/qlge_dbg.c @@ -0,0 +1,858 @@ +#include "qlge.h" + +#ifdef QL_REG_DUMP +static void ql_dump_intr_states(struct ql_adapter *qdev) +{ + int i; + u32 value; + for (i = 0; i < qdev->intr_count; i++) { + ql_write32(qdev, INTR_EN, qdev->intr_context[i].intr_read_mask); + value = ql_read32(qdev, INTR_EN); + printk(KERN_ERR PFX + "%s: Interrupt %d is %s.\n", + qdev->ndev->name, i, + (value & INTR_EN_EN ? "enabled" : "disabled")); + } +} + +void ql_dump_xgmac_control_regs(struct ql_adapter *qdev) +{ + u32 data; + if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) { + printk(KERN_ERR "%s: Couldn't get xgmac sem.\n", __func__); + return; + } + ql_read_xgmac_reg(qdev, PAUSE_SRC_LO, &data); + printk(KERN_ERR PFX "%s: PAUSE_SRC_LO = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, PAUSE_SRC_HI, &data); + printk(KERN_ERR PFX "%s: PAUSE_SRC_HI = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data); + printk(KERN_ERR PFX "%s: GLOBAL_CFG = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, TX_CFG, &data); + printk(KERN_ERR PFX "%s: TX_CFG = 0x%.08x.\n", qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, RX_CFG, &data); + printk(KERN_ERR PFX "%s: RX_CFG = 0x%.08x.\n", qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, FLOW_CTL, &data); + printk(KERN_ERR PFX "%s: FLOW_CTL = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, PAUSE_OPCODE, &data); + printk(KERN_ERR PFX "%s: PAUSE_OPCODE = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, PAUSE_TIMER, &data); + printk(KERN_ERR PFX "%s: PAUSE_TIMER = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, PAUSE_FRM_DEST_LO, &data); + printk(KERN_ERR PFX "%s: PAUSE_FRM_DEST_LO = 0x%.08x.\n", + qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, PAUSE_FRM_DEST_HI, &data); + printk(KERN_ERR PFX "%s: PAUSE_FRM_DEST_HI = 0x%.08x.\n", + qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, MAC_TX_PARAMS, &data); + printk(KERN_ERR PFX "%s: MAC_TX_PARAMS = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, MAC_RX_PARAMS, &data); + printk(KERN_ERR PFX "%s: MAC_RX_PARAMS = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, MAC_SYS_INT, &data); + printk(KERN_ERR PFX "%s: MAC_SYS_INT = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, MAC_SYS_INT_MASK, &data); + printk(KERN_ERR PFX "%s: MAC_SYS_INT_MASK = 0x%.08x.\n", + qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, MAC_MGMT_INT, &data); + printk(KERN_ERR PFX "%s: MAC_MGMT_INT = 0x%.08x.\n", qdev->ndev->name, + data); + ql_read_xgmac_reg(qdev, MAC_MGMT_IN_MASK, &data); + printk(KERN_ERR PFX "%s: MAC_MGMT_IN_MASK = 0x%.08x.\n", + qdev->ndev->name, data); + ql_read_xgmac_reg(qdev, EXT_ARB_MODE, &data); + printk(KERN_ERR PFX "%s: EXT_ARB_MODE = 0x%.08x.\n", qdev->ndev->name, + data); + ql_sem_unlock(qdev, qdev->xg_sem_mask); + +} + +static void ql_dump_ets_regs(struct ql_adapter *qdev) +{ +} + +static void ql_dump_cam_entries(struct ql_adapter *qdev) +{ + int i; + u32 value[3]; + for (i = 0; i < 4; i++) { + if (ql_get_mac_addr_reg(qdev, MAC_ADDR_TYPE_CAM_MAC, i, value)) { + printk(KERN_ERR PFX + "%s: Failed read of mac index register.\n", + __func__); + return; + } else { + if (value[0]) + printk(KERN_ERR PFX + "%s: CAM index %d CAM Lookup Lower = 0x%.08x:%.08x, Output = 0x%.08x.\n", + qdev->ndev->name, i, value[1], value[0], + value[2]); + } + } + for (i = 0; i < 32; i++) { + if (ql_get_mac_addr_reg + (qdev, MAC_ADDR_TYPE_MULTI_MAC, i, value)) { + printk(KERN_ERR PFX + "%s: Failed read of mac index register.\n", + __func__); + return; + } else { + if (value[0]) + printk(KERN_ERR PFX + "%s: MCAST index %d CAM Lookup Lower = 0x%.08x:%.08x.\n", + qdev->ndev->name, i, value[1], value[0]); + } + } +} + +void ql_dump_routing_entries(struct ql_adapter *qdev) +{ + int i; + u32 value; + for (i = 0; i < 16; i++) { + value = 0; + if (ql_get_routing_reg(qdev, i, &value)) { + printk(KERN_ERR PFX + "%s: Failed read of routing index register.\n", + __func__); + return; + } else { + if (value) + printk(KERN_ERR PFX + "%s: Routing Mask %d = 0x%.08x.\n", + qdev->ndev->name, i, value); + } + } +} + +void ql_dump_regs(struct ql_adapter *qdev) +{ + printk(KERN_ERR PFX "reg dump for function #%d.\n", qdev->func); + printk(KERN_ERR PFX "SYS = 0x%x.\n", + ql_read32(qdev, SYS)); + printk(KERN_ERR PFX "RST_FO = 0x%x.\n", + ql_read32(qdev, RST_FO)); + printk(KERN_ERR PFX "FSC = 0x%x.\n", + ql_read32(qdev, FSC)); + printk(KERN_ERR PFX "CSR = 0x%x.\n", + ql_read32(qdev, CSR)); + printk(KERN_ERR PFX "ICB_RID = 0x%x.\n", + ql_read32(qdev, ICB_RID)); + printk(KERN_ERR PFX "ICB_L = 0x%x.\n", + ql_read32(qdev, ICB_L)); + printk(KERN_ERR PFX "ICB_H = 0x%x.\n", + ql_read32(qdev, ICB_H)); + printk(KERN_ERR PFX "CFG = 0x%x.\n", + ql_read32(qdev, CFG)); + printk(KERN_ERR PFX "BIOS_ADDR = 0x%x.\n", + ql_read32(qdev, BIOS_ADDR)); + printk(KERN_ERR PFX "STS = 0x%x.\n", + ql_read32(qdev, STS)); + printk(KERN_ERR PFX "INTR_EN = 0x%x.\n", + ql_read32(qdev, INTR_EN)); + printk(KERN_ERR PFX "INTR_MASK = 0x%x.\n", + ql_read32(qdev, INTR_MASK)); + printk(KERN_ERR PFX "ISR1 = 0x%x.\n", + ql_read32(qdev, ISR1)); + printk(KERN_ERR PFX "ISR2 = 0x%x.\n", + ql_read32(qdev, ISR2)); + printk(KERN_ERR PFX "ISR3 = 0x%x.\n", + ql_read32(qdev, ISR3)); + printk(KERN_ERR PFX "ISR4 = 0x%x.\n", + ql_read32(qdev, ISR4)); + printk(KERN_ERR PFX "REV_ID = 0x%x.\n", + ql_read32(qdev, REV_ID)); + printk(KERN_ERR PFX "FRC_ECC_ERR = 0x%x.\n", + ql_read32(qdev, FRC_ECC_ERR)); + printk(KERN_ERR PFX "ERR_STS = 0x%x.\n", + ql_read32(qdev, ERR_STS)); + printk(KERN_ERR PFX "RAM_DBG_ADDR = 0x%x.\n", + ql_read32(qdev, RAM_DBG_ADDR)); + printk(KERN_ERR PFX "RAM_DBG_DATA = 0x%x.\n", + ql_read32(qdev, RAM_DBG_DATA)); + printk(KERN_ERR PFX "ECC_ERR_CNT = 0x%x.\n", + ql_read32(qdev, ECC_ERR_CNT)); + printk(KERN_ERR PFX "SEM = 0x%x.\n", + ql_read32(qdev, SEM)); + printk(KERN_ERR PFX "GPIO_1 = 0x%x.\n", + ql_read32(qdev, GPIO_1)); + printk(KERN_ERR PFX "GPIO_2 = 0x%x.\n", + ql_read32(qdev, GPIO_2)); + printk(KERN_ERR PFX "GPIO_3 = 0x%x.\n", + ql_read32(qdev, GPIO_3)); + printk(KERN_ERR PFX "XGMAC_ADDR = 0x%x.\n", + ql_read32(qdev, XGMAC_ADDR)); + printk(KERN_ERR PFX "XGMAC_DATA = 0x%x.\n", + ql_read32(qdev, XGMAC_DATA)); + printk(KERN_ERR PFX "NIC_ETS = 0x%x.\n", + ql_read32(qdev, NIC_ETS)); + printk(KERN_ERR PFX "CNA_ETS = 0x%x.\n", + ql_read32(qdev, CNA_ETS)); + printk(KERN_ERR PFX "FLASH_ADDR = 0x%x.\n", + ql_read32(qdev, FLASH_ADDR)); + printk(KERN_ERR PFX "FLASH_DATA = 0x%x.\n", + ql_read32(qdev, FLASH_DATA)); + printk(KERN_ERR PFX "CQ_STOP = 0x%x.\n", + ql_read32(qdev, CQ_STOP)); + printk(KERN_ERR PFX "PAGE_TBL_RID = 0x%x.\n", + ql_read32(qdev, PAGE_TBL_RID)); + printk(KERN_ERR PFX "WQ_PAGE_TBL_LO = 0x%x.\n", + ql_read32(qdev, WQ_PAGE_TBL_LO)); + printk(KERN_ERR PFX "WQ_PAGE_TBL_HI = 0x%x.\n", + ql_read32(qdev, WQ_PAGE_TBL_HI)); + printk(KERN_ERR PFX "CQ_PAGE_TBL_LO = 0x%x.\n", + ql_read32(qdev, CQ_PAGE_TBL_LO)); + printk(KERN_ERR PFX "CQ_PAGE_TBL_HI = 0x%x.\n", + ql_read32(qdev, CQ_PAGE_TBL_HI)); + printk(KERN_ERR PFX "COS_DFLT_CQ1 = 0x%x.\n", + ql_read32(qdev, COS_DFLT_CQ1)); + printk(KERN_ERR PFX "COS_DFLT_CQ2 = 0x%x.\n", + ql_read32(qdev, COS_DFLT_CQ2)); + printk(KERN_ERR PFX "SPLT_HDR = 0x%x.\n", + ql_read32(qdev, SPLT_HDR)); + printk(KERN_ERR PFX "FC_PAUSE_THRES = 0x%x.\n", + ql_read32(qdev, FC_PAUSE_THRES)); + printk(KERN_ERR PFX "NIC_PAUSE_THRES = 0x%x.\n", + ql_read32(qdev, NIC_PAUSE_THRES)); + printk(KERN_ERR PFX "FC_ETHERTYPE = 0x%x.\n", + ql_read32(qdev, FC_ETHERTYPE)); + printk(KERN_ERR PFX "FC_RCV_CFG = 0x%x.\n", + ql_read32(qdev, FC_RCV_CFG)); + printk(KERN_ERR PFX "NIC_RCV_CFG = 0x%x.\n", + ql_read32(qdev, NIC_RCV_CFG)); + printk(KERN_ERR PFX "FC_COS_TAGS = 0x%x.\n", + ql_read32(qdev, FC_COS_TAGS)); + printk(KERN_ERR PFX "NIC_COS_TAGS = 0x%x.\n", + ql_read32(qdev, NIC_COS_TAGS)); + printk(KERN_ERR PFX "MGMT_RCV_CFG = 0x%x.\n", + ql_read32(qdev, MGMT_RCV_CFG)); + printk(KERN_ERR PFX "XG_SERDES_ADDR = 0x%x.\n", + ql_read32(qdev, XG_SERDES_ADDR)); + printk(KERN_ERR PFX "XG_SERDES_DATA = 0x%x.\n", + ql_read32(qdev, XG_SERDES_DATA)); + printk(KERN_ERR PFX "PRB_MX_ADDR = 0x%x.\n", + ql_read32(qdev, PRB_MX_ADDR)); + printk(KERN_ERR PFX "PRB_MX_DATA = 0x%x.\n", + ql_read32(qdev, PRB_MX_DATA)); + ql_dump_intr_states(qdev); + ql_dump_xgmac_control_regs(qdev); + ql_dump_ets_regs(qdev); + ql_dump_cam_entries(qdev); + ql_dump_routing_entries(qdev); +} +#endif + +#ifdef QL_STAT_DUMP +void ql_dump_stat(struct ql_adapter *qdev) +{ + printk(KERN_ERR "%s: Enter.\n", __func__); + printk(KERN_ERR "tx_pkts = %ld\n", + (unsigned long)qdev->nic_stats.tx_pkts); + printk(KERN_ERR "tx_bytes = %ld\n", + (unsigned long)qdev->nic_stats.tx_bytes); + printk(KERN_ERR "tx_mcast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.tx_mcast_pkts); + printk(KERN_ERR "tx_bcast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.tx_bcast_pkts); + printk(KERN_ERR "tx_ucast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.tx_ucast_pkts); + printk(KERN_ERR "tx_ctl_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.tx_ctl_pkts); + printk(KERN_ERR "tx_pause_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.tx_pause_pkts); + printk(KERN_ERR "tx_64_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_64_pkt); + printk(KERN_ERR "tx_65_to_127_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_65_to_127_pkt); + printk(KERN_ERR "tx_128_to_255_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_128_to_255_pkt); + printk(KERN_ERR "tx_256_511_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_256_511_pkt); + printk(KERN_ERR "tx_512_to_1023_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_512_to_1023_pkt); + printk(KERN_ERR "tx_1024_to_1518_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_1024_to_1518_pkt); + printk(KERN_ERR "tx_1519_to_max_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_1519_to_max_pkt); + printk(KERN_ERR "tx_undersize_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_undersize_pkt); + printk(KERN_ERR "tx_oversize_pkt = %ld.\n", + (unsigned long)qdev->nic_stats.tx_oversize_pkt); + printk(KERN_ERR "rx_bytes = %ld.\n", + (unsigned long)qdev->nic_stats.rx_bytes); + printk(KERN_ERR "rx_bytes_ok = %ld.\n", + (unsigned long)qdev->nic_stats.rx_bytes_ok); + printk(KERN_ERR "rx_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_pkts); + printk(KERN_ERR "rx_pkts_ok = %ld.\n", + (unsigned long)qdev->nic_stats.rx_pkts_ok); + printk(KERN_ERR "rx_bcast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_bcast_pkts); + printk(KERN_ERR "rx_mcast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_mcast_pkts); + printk(KERN_ERR "rx_ucast_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_ucast_pkts); + printk(KERN_ERR "rx_undersize_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_undersize_pkts); + printk(KERN_ERR "rx_oversize_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_oversize_pkts); + printk(KERN_ERR "rx_jabber_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_jabber_pkts); + printk(KERN_ERR "rx_undersize_fcerr_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_undersize_fcerr_pkts); + printk(KERN_ERR "rx_drop_events = %ld.\n", + (unsigned long)qdev->nic_stats.rx_drop_events); + printk(KERN_ERR "rx_fcerr_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_fcerr_pkts); + printk(KERN_ERR "rx_align_err = %ld.\n", + (unsigned long)qdev->nic_stats.rx_align_err); + printk(KERN_ERR "rx_symbol_err = %ld.\n", + (unsigned long)qdev->nic_stats.rx_symbol_err); + printk(KERN_ERR "rx_mac_err = %ld.\n", + (unsigned long)qdev->nic_stats.rx_mac_err); + printk(KERN_ERR "rx_ctl_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_ctl_pkts); + printk(KERN_ERR "rx_pause_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_pause_pkts); + printk(KERN_ERR "rx_64_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_64_pkts); + printk(KERN_ERR "rx_65_to_127_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_65_to_127_pkts); + printk(KERN_ERR "rx_128_255_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_128_255_pkts); + printk(KERN_ERR "rx_256_511_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_256_511_pkts); + printk(KERN_ERR "rx_512_to_1023_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_512_to_1023_pkts); + printk(KERN_ERR "rx_1024_to_1518_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_1024_to_1518_pkts); + printk(KERN_ERR "rx_1519_to_max_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_1519_to_max_pkts); + printk(KERN_ERR "rx_len_err_pkts = %ld.\n", + (unsigned long)qdev->nic_stats.rx_len_err_pkts); +}; +#endif + +#ifdef QL_DEV_DUMP +void ql_dump_qdev(struct ql_adapter *qdev) +{ + int i; + printk(KERN_ERR PFX "qdev->flags = %lx.\n", + qdev->flags); + printk(KERN_ERR PFX "qdev->vlgrp = %p.\n", + qdev->vlgrp); + printk(KERN_ERR PFX "qdev->pdev = %p.\n", + qdev->pdev); + printk(KERN_ERR PFX "qdev->ndev = %p.\n", + qdev->ndev); + printk(KERN_ERR PFX "qdev->chip_rev_id = %d.\n", + qdev->chip_rev_id); + printk(KERN_ERR PFX "qdev->reg_base = %p.\n", + qdev->reg_base); + printk(KERN_ERR PFX "qdev->doorbell_area = %p.\n", + qdev->doorbell_area); + printk(KERN_ERR PFX "qdev->doorbell_area_size = %d.\n", + qdev->doorbell_area_size); + printk(KERN_ERR PFX "msg_enable = %x.\n", + qdev->msg_enable); + printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_area = %p.\n", + qdev->rx_ring_shadow_reg_area); + printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_dma = %p.\n", + (void *)qdev->rx_ring_shadow_reg_dma); + printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_area = %p.\n", + qdev->tx_ring_shadow_reg_area); + printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_dma = %p.\n", + (void *)qdev->tx_ring_shadow_reg_dma); + printk(KERN_ERR PFX "qdev->intr_count = %d.\n", + qdev->intr_count); + if (qdev->msi_x_entry) + for (i = 0; i < qdev->intr_count; i++) { + printk(KERN_ERR PFX + "msi_x_entry.[%d]vector = %d.\n", i, + qdev->msi_x_entry[i].vector); + printk(KERN_ERR PFX + "msi_x_entry.[%d]entry = %d.\n", i, + qdev->msi_x_entry[i].entry); + } + for (i = 0; i < qdev->intr_count; i++) { + printk(KERN_ERR PFX + "intr_context[%d].qdev = %p.\n", i, + qdev->intr_context[i].qdev); + printk(KERN_ERR PFX + "intr_context[%d].intr = %d.\n", i, + qdev->intr_context[i].intr); + printk(KERN_ERR PFX + "intr_context[%d].hooked = %d.\n", i, + qdev->intr_context[i].hooked); + printk(KERN_ERR PFX + "intr_context[%d].intr_en_mask = 0x%08x.\n", i, + qdev->intr_context[i].intr_en_mask); + printk(KERN_ERR PFX + "intr_context[%d].intr_dis_mask = 0x%08x.\n", i, + qdev->intr_context[i].intr_dis_mask); + printk(KERN_ERR PFX + "intr_context[%d].intr_read_mask = 0x%08x.\n", i, + qdev->intr_context[i].intr_read_mask); + } + printk(KERN_ERR PFX "qdev->tx_ring_count = %d.\n", qdev->tx_ring_count); + printk(KERN_ERR PFX "qdev->rx_ring_count = %d.\n", qdev->rx_ring_count); + printk(KERN_ERR PFX "qdev->ring_mem_size = %d.\n", qdev->ring_mem_size); + printk(KERN_ERR PFX "qdev->ring_mem = %p.\n", qdev->ring_mem); + printk(KERN_ERR PFX "qdev->intr_count = %d.\n", qdev->intr_count); + printk(KERN_ERR PFX "qdev->tx_ring = %p.\n", + qdev->tx_ring); + printk(KERN_ERR PFX "qdev->rss_ring_first_cq_id = %d.\n", + qdev->rss_ring_first_cq_id); + printk(KERN_ERR PFX "qdev->rss_ring_count = %d.\n", + qdev->rss_ring_count); + printk(KERN_ERR PFX "qdev->rx_ring = %p.\n", qdev->rx_ring); + printk(KERN_ERR PFX "qdev->default_rx_queue = %d.\n", + qdev->default_rx_queue); + printk(KERN_ERR PFX "qdev->xg_sem_mask = 0x%08x.\n", + qdev->xg_sem_mask); + printk(KERN_ERR PFX "qdev->port_link_up = 0x%08x.\n", + qdev->port_link_up); + printk(KERN_ERR PFX "qdev->port_init = 0x%08x.\n", + qdev->port_init); + +} +#endif + +#ifdef QL_CB_DUMP +void ql_dump_wqicb(struct wqicb *wqicb) +{ + printk(KERN_ERR PFX "Dumping wqicb stuff...\n"); + printk(KERN_ERR PFX "wqicb->len = 0x%x.\n", le16_to_cpu(wqicb->len)); + printk(KERN_ERR PFX "wqicb->flags = %x.\n", le16_to_cpu(wqicb->flags)); + printk(KERN_ERR PFX "wqicb->cq_id_rss = %d.\n", + le16_to_cpu(wqicb->cq_id_rss)); + printk(KERN_ERR PFX "wqicb->rid = 0x%x.\n", le16_to_cpu(wqicb->rid)); + printk(KERN_ERR PFX "wqicb->wq_addr_lo = 0x%.08x.\n", + le32_to_cpu(wqicb->addr_lo)); + printk(KERN_ERR PFX "wqicb->wq_addr_hi = 0x%.08x.\n", + le32_to_cpu(wqicb->addr_hi)); + printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_lo = 0x%.08x.\n", + le32_to_cpu(wqicb->cnsmr_idx_addr_lo)); + printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_hi = 0x%.08x.\n", + le32_to_cpu(wqicb->cnsmr_idx_addr_hi)); +} + +void ql_dump_tx_ring(struct tx_ring *tx_ring) +{ + if (tx_ring == NULL) + return; + printk(KERN_ERR PFX + "===================== Dumping tx_ring %d ===============.\n", + tx_ring->wq_id); + printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base); + printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n", + (u64) tx_ring->wq_base_dma); + printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n", + tx_ring->cnsmr_idx_sh_reg); + printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n", + (u64) tx_ring->cnsmr_idx_sh_reg_dma); + printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size); + printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len); + printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n", + tx_ring->prod_idx_db_reg); + printk(KERN_ERR PFX "tx_ring->valid_db_reg = %p.\n", + tx_ring->valid_db_reg); + printk(KERN_ERR PFX "tx_ring->prod_idx = %d.\n", tx_ring->prod_idx); + printk(KERN_ERR PFX "tx_ring->cq_id = %d.\n", tx_ring->cq_id); + printk(KERN_ERR PFX "tx_ring->wq_id = %d.\n", tx_ring->wq_id); + printk(KERN_ERR PFX "tx_ring->q = %p.\n", tx_ring->q); + printk(KERN_ERR PFX "tx_ring->tx_count = %d.\n", + atomic_read(&tx_ring->tx_count)); +} + +void ql_dump_ricb(struct ricb *ricb) +{ + int i; + printk(KERN_ERR PFX + "===================== Dumping ricb ===============.\n"); + printk(KERN_ERR PFX "Dumping ricb stuff...\n"); + + printk(KERN_ERR PFX "ricb->base_cq = %d.\n", ricb->base_cq & 0x1f); + printk(KERN_ERR PFX "ricb->flags = %s%s%s%s%s%s%s%s%s.\n", + ricb->base_cq & RSS_L4K ? "RSS_L4K " : "", + ricb->flags & RSS_L6K ? "RSS_L6K " : "", + ricb->flags & RSS_LI ? "RSS_LI " : "", + ricb->flags & RSS_LB ? "RSS_LB " : "", + ricb->flags & RSS_LM ? "RSS_LM " : "", + ricb->flags & RSS_RI4 ? "RSS_RI4 " : "", + ricb->flags & RSS_RT4 ? "RSS_RT4 " : "", + ricb->flags & RSS_RI6 ? "RSS_RI6 " : "", + ricb->flags & RSS_RT6 ? "RSS_RT6 " : ""); + printk(KERN_ERR PFX "ricb->mask = 0x%.04x.\n", le16_to_cpu(ricb->mask)); + for (i = 0; i < 16; i++) + printk(KERN_ERR PFX "ricb->hash_cq_id[%d] = 0x%.08x.\n", i, + le32_to_cpu(ricb->hash_cq_id[i])); + for (i = 0; i < 10; i++) + printk(KERN_ERR PFX "ricb->ipv6_hash_key[%d] = 0x%.08x.\n", i, + le32_to_cpu(ricb->ipv6_hash_key[i])); + for (i = 0; i < 4; i++) + printk(KERN_ERR PFX "ricb->ipv4_hash_key[%d] = 0x%.08x.\n", i, + le32_to_cpu(ricb->ipv4_hash_key[i])); +} + +void ql_dump_cqicb(struct cqicb *cqicb) +{ + printk(KERN_ERR PFX "Dumping cqicb stuff...\n"); + + printk(KERN_ERR PFX "cqicb->msix_vect = %d.\n", cqicb->msix_vect); + printk(KERN_ERR PFX "cqicb->flags = %x.\n", cqicb->flags); + printk(KERN_ERR PFX "cqicb->len = %d.\n", le16_to_cpu(cqicb->len)); + printk(KERN_ERR PFX "cqicb->addr_lo = %x.\n", + le32_to_cpu(cqicb->addr_lo)); + printk(KERN_ERR PFX "cqicb->addr_hi = %x.\n", + le32_to_cpu(cqicb->addr_hi)); + printk(KERN_ERR PFX "cqicb->prod_idx_addr_lo = %x.\n", + le32_to_cpu(cqicb->prod_idx_addr_lo)); + printk(KERN_ERR PFX "cqicb->prod_idx_addr_hi = %x.\n", + le32_to_cpu(cqicb->prod_idx_addr_hi)); + printk(KERN_ERR PFX "cqicb->pkt_delay = 0x%.04x.\n", + le16_to_cpu(cqicb->pkt_delay)); + printk(KERN_ERR PFX "cqicb->irq_delay = 0x%.04x.\n", + le16_to_cpu(cqicb->irq_delay)); + printk(KERN_ERR PFX "cqicb->lbq_addr_lo = %x.\n", + le32_to_cpu(cqicb->lbq_addr_lo)); + printk(KERN_ERR PFX "cqicb->lbq_addr_hi = %x.\n", + le32_to_cpu(cqicb->lbq_addr_hi)); + printk(KERN_ERR PFX "cqicb->lbq_buf_size = 0x%.04x.\n", + le16_to_cpu(cqicb->lbq_buf_size)); + printk(KERN_ERR PFX "cqicb->lbq_len = 0x%.04x.\n", + le16_to_cpu(cqicb->lbq_len)); + printk(KERN_ERR PFX "cqicb->sbq_addr_lo = %x.\n", + le32_to_cpu(cqicb->sbq_addr_lo)); + printk(KERN_ERR PFX "cqicb->sbq_addr_hi = %x.\n", + le32_to_cpu(cqicb->sbq_addr_hi)); + printk(KERN_ERR PFX "cqicb->sbq_buf_size = 0x%.04x.\n", + le16_to_cpu(cqicb->sbq_buf_size)); + printk(KERN_ERR PFX "cqicb->sbq_len = 0x%.04x.\n", + le16_to_cpu(cqicb->sbq_len)); +} + +void ql_dump_rx_ring(struct rx_ring *rx_ring) +{ + if (rx_ring == NULL) + return; + printk(KERN_ERR PFX + "===================== Dumping rx_ring %d ===============.\n", + rx_ring->cq_id); + printk(KERN_ERR PFX "Dumping rx_ring %d, type = %s%s%s.\n", + rx_ring->cq_id, rx_ring->type == DEFAULT_Q ? "DEFAULT" : "", + rx_ring->type == TX_Q ? "OUTBOUND COMPLETIONS" : "", + rx_ring->type == RX_Q ? "INBOUND_COMPLETIONS" : ""); + printk(KERN_ERR PFX "rx_ring->cqicb = %p.\n", &rx_ring->cqicb); + printk(KERN_ERR PFX "rx_ring->cq_base = %p.\n", rx_ring->cq_base); + printk(KERN_ERR PFX "rx_ring->cq_base_dma = %llx.\n", + (u64) rx_ring->cq_base_dma); + printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size); + printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len); + printk(KERN_ERR PFX + "rx_ring->prod_idx_sh_reg, addr = %p, value = %d.\n", + rx_ring->prod_idx_sh_reg, + rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0); + printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n", + (u64) rx_ring->prod_idx_sh_reg_dma); + printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n", + rx_ring->cnsmr_idx_db_reg); + printk(KERN_ERR PFX "rx_ring->cnsmr_idx = %d.\n", rx_ring->cnsmr_idx); + printk(KERN_ERR PFX "rx_ring->curr_entry = %p.\n", rx_ring->curr_entry); + printk(KERN_ERR PFX "rx_ring->valid_db_reg = %p.\n", + rx_ring->valid_db_reg); + + printk(KERN_ERR PFX "rx_ring->lbq_base = %p.\n", rx_ring->lbq_base); + printk(KERN_ERR PFX "rx_ring->lbq_base_dma = %llx.\n", + (u64) rx_ring->lbq_base_dma); + printk(KERN_ERR PFX "rx_ring->lbq_base_indirect = %p.\n", + rx_ring->lbq_base_indirect); + printk(KERN_ERR PFX "rx_ring->lbq_base_indirect_dma = %llx.\n", + (u64) rx_ring->lbq_base_indirect_dma); + printk(KERN_ERR PFX "rx_ring->lbq = %p.\n", rx_ring->lbq); + printk(KERN_ERR PFX "rx_ring->lbq_len = %d.\n", rx_ring->lbq_len); + printk(KERN_ERR PFX "rx_ring->lbq_size = %d.\n", rx_ring->lbq_size); + printk(KERN_ERR PFX "rx_ring->lbq_prod_idx_db_reg = %p.\n", + rx_ring->lbq_prod_idx_db_reg); + printk(KERN_ERR PFX "rx_ring->lbq_prod_idx = %d.\n", + rx_ring->lbq_prod_idx); + printk(KERN_ERR PFX "rx_ring->lbq_curr_idx = %d.\n", + rx_ring->lbq_curr_idx); + printk(KERN_ERR PFX "rx_ring->lbq_clean_idx = %d.\n", + rx_ring->lbq_clean_idx); + printk(KERN_ERR PFX "rx_ring->lbq_free_cnt = %d.\n", + rx_ring->lbq_free_cnt); + printk(KERN_ERR PFX "rx_ring->lbq_buf_size = %d.\n", + rx_ring->lbq_buf_size); + + printk(KERN_ERR PFX "rx_ring->sbq_base = %p.\n", rx_ring->sbq_base); + printk(KERN_ERR PFX "rx_ring->sbq_base_dma = %llx.\n", + (u64) rx_ring->sbq_base_dma); + printk(KERN_ERR PFX "rx_ring->sbq_base_indirect = %p.\n", + rx_ring->sbq_base_indirect); + printk(KERN_ERR PFX "rx_ring->sbq_base_indirect_dma = %llx.\n", + (u64) rx_ring->sbq_base_indirect_dma); + printk(KERN_ERR PFX "rx_ring->sbq = %p.\n", rx_ring->sbq); + printk(KERN_ERR PFX "rx_ring->sbq_len = %d.\n", rx_ring->sbq_len); + printk(KERN_ERR PFX "rx_ring->sbq_size = %d.\n", rx_ring->sbq_size); + printk(KERN_ERR PFX "rx_ring->sbq_prod_idx_db_reg addr = %p.\n", + rx_ring->sbq_prod_idx_db_reg); + printk(KERN_ERR PFX "rx_ring->sbq_prod_idx = %d.\n", + rx_ring->sbq_prod_idx); + printk(KERN_ERR PFX "rx_ring->sbq_curr_idx = %d.\n", + rx_ring->sbq_curr_idx); + printk(KERN_ERR PFX "rx_ring->sbq_clean_idx = %d.\n", + rx_ring->sbq_clean_idx); + printk(KERN_ERR PFX "rx_ring->sbq_free_cnt = %d.\n", + rx_ring->sbq_free_cnt); + printk(KERN_ERR PFX "rx_ring->sbq_buf_size = %d.\n", + rx_ring->sbq_buf_size); + printk(KERN_ERR PFX "rx_ring->cq_id = %d.\n", rx_ring->cq_id); + printk(KERN_ERR PFX "rx_ring->irq = %d.\n", rx_ring->irq); + printk(KERN_ERR PFX "rx_ring->cpu = %d.\n", rx_ring->cpu); + printk(KERN_ERR PFX "rx_ring->qdev = %p.\n", rx_ring->qdev); +} + +void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id) +{ + void *ptr; + + printk(KERN_ERR PFX "%s: Enter.\n", __func__); + + ptr = kmalloc(size, GFP_ATOMIC); + if (ptr == NULL) { + printk(KERN_ERR PFX "%s: Couldn't allocate a buffer.\n", + __func__); + return; + } + + if (ql_write_cfg(qdev, ptr, size, bit, q_id)) { + printk(KERN_ERR "%s: Failed to upload control block!\n", + __func__); + goto fail_it; + } + switch (bit) { + case CFG_DRQ: + ql_dump_wqicb((struct wqicb *)ptr); + break; + case CFG_DCQ: + ql_dump_cqicb((struct cqicb *)ptr); + break; + case CFG_DR: + ql_dump_ricb((struct ricb *)ptr); + break; + default: + printk(KERN_ERR PFX "%s: Invalid bit value = %x.\n", + __func__, bit); + break; + } +fail_it: + kfree(ptr); +} +#endif + +#ifdef QL_OB_DUMP +void ql_dump_tx_desc(struct tx_buf_desc *tbd) +{ + printk(KERN_ERR PFX "tbd->addr = 0x%llx\n", + le64_to_cpu((u64) tbd->addr)); + printk(KERN_ERR PFX "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + printk(KERN_ERR PFX "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); + tbd++; + printk(KERN_ERR PFX "tbd->addr = 0x%llx\n", + le64_to_cpu((u64) tbd->addr)); + printk(KERN_ERR PFX "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + printk(KERN_ERR PFX "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); + tbd++; + printk(KERN_ERR PFX "tbd->addr = 0x%llx\n", + le64_to_cpu((u64) tbd->addr)); + printk(KERN_ERR PFX "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + printk(KERN_ERR PFX "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); + +} + +void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb) +{ + struct ob_mac_tso_iocb_req *ob_mac_tso_iocb = + (struct ob_mac_tso_iocb_req *)ob_mac_iocb; + struct tx_buf_desc *tbd; + u16 frame_len; + + printk(KERN_ERR PFX "%s\n", __func__); + printk(KERN_ERR PFX "opcode = %s\n", + (ob_mac_iocb->opcode == OPCODE_OB_MAC_IOCB) ? "MAC" : "TSO"); + printk(KERN_ERR PFX "flags1 = %s %s %s %s %s\n", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_OI ? "OI" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_I ? "I" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_D ? "D" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP4 ? "IP4" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP6 ? "IP6" : ""); + printk(KERN_ERR PFX "flags2 = %s %s %s\n", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_LSO ? "LSO" : "", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_UC ? "UC" : "", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_TC ? "TC" : ""); + printk(KERN_ERR PFX "flags3 = %s %s %s \n", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_IC ? "IC" : "", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_DFP ? "DFP" : "", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_V ? "V" : ""); + printk(KERN_ERR PFX "tid = %x\n", ob_mac_iocb->tid); + printk(KERN_ERR PFX "txq_idx = %d\n", ob_mac_iocb->txq_idx); + printk(KERN_ERR PFX "vlan_tci = %x\n", ob_mac_tso_iocb->vlan_tci); + if (ob_mac_iocb->opcode == OPCODE_OB_MAC_TSO_IOCB) { + printk(KERN_ERR PFX "frame_len = %d\n", + le32_to_cpu(ob_mac_tso_iocb->frame_len)); + printk(KERN_ERR PFX "mss = %d\n", + le16_to_cpu(ob_mac_tso_iocb->mss)); + printk(KERN_ERR PFX "prot_hdr_len = %d\n", + le16_to_cpu(ob_mac_tso_iocb->total_hdrs_len)); + printk(KERN_ERR PFX "hdr_offset = 0x%.04x\n", + le16_to_cpu(ob_mac_tso_iocb->net_trans_offset)); + frame_len = le32_to_cpu(ob_mac_tso_iocb->frame_len); + } else { + printk(KERN_ERR PFX "frame_len = %d\n", + le16_to_cpu(ob_mac_iocb->frame_len)); + frame_len = le16_to_cpu(ob_mac_iocb->frame_len); + } + tbd = &ob_mac_iocb->tbd[0]; + ql_dump_tx_desc(tbd); +} + +void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp) +{ + printk(KERN_ERR PFX "%s\n", __func__); + printk(KERN_ERR PFX "opcode = %d\n", ob_mac_rsp->opcode); + printk(KERN_ERR PFX "flags = %s %s %s %s %s %s %s\n", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_OI ? "OI" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_I ? "I" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_E ? "E" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_S ? "S" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_L ? "L" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_P ? "P" : ".", + ob_mac_rsp->flags2 & OB_MAC_IOCB_RSP_B ? "B" : "."); + printk(KERN_ERR PFX "tid = %x\n", ob_mac_rsp->tid); +} +#endif + +#ifdef QL_IB_DUMP +void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp) +{ + printk(KERN_ERR PFX "%s\n", __func__); + printk(KERN_ERR PFX "opcode = 0x%x\n", ib_mac_rsp->opcode); + printk(KERN_ERR PFX "flags1 = %s%s%s%s%s%s\n", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_OI ? "OI " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_I ? "I " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_TE ? "TE " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU ? "NU " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_IE ? "IE " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_B ? "B " : ""); + + if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) + printk(KERN_ERR PFX "%s%s%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + + printk(KERN_ERR PFX "flags2 = %s%s%s%s%s\n", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) ? "P " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? "V " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) ? "U " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) ? "T " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_FO) ? "FO " : ""); + + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) + printk(KERN_ERR PFX "%s%s%s%s%s error.\n", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_OVERSIZE ? "oversize" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_UNDERSIZE ? "undersize" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_PREAMBLE ? "preamble" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_FRAME_LEN ? "frame length" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_CRC ? "CRC" : ""); + + printk(KERN_ERR PFX "flags3 = %s%s.\n", + ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS ? "DS " : "", + ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL ? "DL " : ""); + + if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) + printk(KERN_ERR PFX "RSS flags = %s%s%s%s.\n", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_IPV4) ? "IPv4 RSS" : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_IPV6) ? "IPv6 RSS " : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_TCP_V4) ? "TCP/IPv4 RSS" : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_TCP_V6) ? "TCP/IPv6 RSS" : ""); + + printk(KERN_ERR PFX "data_len = %d\n", + le32_to_cpu(ib_mac_rsp->data_len)); + printk(KERN_ERR PFX "data_addr_hi = 0x%x\n", + le32_to_cpu(ib_mac_rsp->data_addr_hi)); + printk(KERN_ERR PFX "data_addr_lo = 0x%x\n", + le32_to_cpu(ib_mac_rsp->data_addr_lo)); + if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) + printk(KERN_ERR PFX "rss = %x\n", + le32_to_cpu(ib_mac_rsp->rss)); + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) + printk(KERN_ERR PFX "vlan_id = %x\n", + le16_to_cpu(ib_mac_rsp->vlan_id)); + + printk(KERN_ERR PFX "flags4 = %s%s%s.\n", + le32_to_cpu(ib_mac_rsp-> + flags4) & IB_MAC_IOCB_RSP_HV ? "HV " : "", + le32_to_cpu(ib_mac_rsp-> + flags4) & IB_MAC_IOCB_RSP_HS ? "HS " : "", + le32_to_cpu(ib_mac_rsp-> + flags4) & IB_MAC_IOCB_RSP_HL ? "HL " : ""); + + if (le32_to_cpu(ib_mac_rsp->flags4) & IB_MAC_IOCB_RSP_HV) { + printk(KERN_ERR PFX "hdr length = %d.\n", + le32_to_cpu(ib_mac_rsp->hdr_len)); + printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n", + le32_to_cpu(ib_mac_rsp->hdr_addr_hi)); + printk(KERN_ERR PFX "hdr addr_lo = 0x%x.\n", + le32_to_cpu(ib_mac_rsp->hdr_addr_lo)); + } +} +#endif + +#ifdef QL_ALL_DUMP +void ql_dump_all(struct ql_adapter *qdev) +{ + int i; + + QL_DUMP_REGS(qdev); + QL_DUMP_QDEV(qdev); + for (i = 0; i < qdev->tx_ring_count; i++) { + QL_DUMP_TX_RING(&qdev->tx_ring[i]); + QL_DUMP_WQICB((struct wqicb *)&qdev->tx_ring[i]); + } + for (i = 0; i < qdev->rx_ring_count; i++) { + QL_DUMP_RX_RING(&qdev->rx_ring[i]); + QL_DUMP_CQICB((struct cqicb *)&qdev->rx_ring[i]); + } +} +#endif diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c new file mode 100644 index 00000000000..6457f8c4fda --- /dev/null +++ b/drivers/net/qlge/qlge_ethtool.c @@ -0,0 +1,415 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "qlge.h" + +static int ql_update_ring_coalescing(struct ql_adapter *qdev) +{ + int i, status = 0; + struct rx_ring *rx_ring; + struct cqicb *cqicb; + + if (!netif_running(qdev->ndev)) + return status; + + spin_lock(&qdev->hw_lock); + /* Skip the default queue, and update the outbound handler + * queues if they changed. + */ + cqicb = (struct cqicb *)&qdev->rx_ring[1]; + if (le16_to_cpu(cqicb->irq_delay) != qdev->tx_coalesce_usecs || + le16_to_cpu(cqicb->pkt_delay) != qdev->tx_max_coalesced_frames) { + for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) { + rx_ring = &qdev->rx_ring[i]; + cqicb = (struct cqicb *)rx_ring; + cqicb->irq_delay = le16_to_cpu(qdev->tx_coalesce_usecs); + cqicb->pkt_delay = + le16_to_cpu(qdev->tx_max_coalesced_frames); + cqicb->flags = FLAGS_LI; + status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + CFG_LCQ, rx_ring->cq_id); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to load CQICB.\n"); + goto exit; + } + } + } + + /* Update the inbound (RSS) handler queues if they changed. */ + cqicb = (struct cqicb *)&qdev->rx_ring[qdev->rss_ring_first_cq_id]; + if (le16_to_cpu(cqicb->irq_delay) != qdev->rx_coalesce_usecs || + le16_to_cpu(cqicb->pkt_delay) != qdev->rx_max_coalesced_frames) { + for (i = qdev->rss_ring_first_cq_id; + i <= qdev->rss_ring_first_cq_id + qdev->rss_ring_count; + i++) { + rx_ring = &qdev->rx_ring[i]; + cqicb = (struct cqicb *)rx_ring; + cqicb->irq_delay = le16_to_cpu(qdev->rx_coalesce_usecs); + cqicb->pkt_delay = + le16_to_cpu(qdev->rx_max_coalesced_frames); + cqicb->flags = FLAGS_LI; + status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + CFG_LCQ, rx_ring->cq_id); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to load CQICB.\n"); + goto exit; + } + } + } +exit: + spin_unlock(&qdev->hw_lock); + return status; +} + +void ql_update_stats(struct ql_adapter *qdev) +{ + u32 i; + u64 data; + u64 *iter = &qdev->nic_stats.tx_pkts; + + spin_lock(&qdev->stats_lock); + if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) { + QPRINTK(qdev, DRV, ERR, + "Couldn't get xgmac sem.\n"); + goto quit; + } + /* + * Get TX statistics. + */ + for (i = 0x200; i < 0x280; i += 8) { + if (ql_read_xgmac_reg64(qdev, i, &data)) { + QPRINTK(qdev, DRV, ERR, + "Error reading status register 0x%.04x.\n", i); + goto end; + } else + *iter = data; + iter++; + } + + /* + * Get RX statistics. + */ + for (i = 0x300; i < 0x3d0; i += 8) { + if (ql_read_xgmac_reg64(qdev, i, &data)) { + QPRINTK(qdev, DRV, ERR, + "Error reading status register 0x%.04x.\n", i); + goto end; + } else + *iter = data; + iter++; + } + +end: + ql_sem_unlock(qdev, qdev->xg_sem_mask); +quit: + spin_unlock(&qdev->stats_lock); + + QL_DUMP_STAT(qdev); + + return; +} + +static char ql_stats_str_arr[][ETH_GSTRING_LEN] = { + {"tx_pkts"}, + {"tx_bytes"}, + {"tx_mcast_pkts"}, + {"tx_bcast_pkts"}, + {"tx_ucast_pkts"}, + {"tx_ctl_pkts"}, + {"tx_pause_pkts"}, + {"tx_64_pkts"}, + {"tx_65_to_127_pkts"}, + {"tx_128_to_255_pkts"}, + {"tx_256_511_pkts"}, + {"tx_512_to_1023_pkts"}, + {"tx_1024_to_1518_pkts"}, + {"tx_1519_to_max_pkts"}, + {"tx_undersize_pkts"}, + {"tx_oversize_pkts"}, + {"rx_bytes"}, + {"rx_bytes_ok"}, + {"rx_pkts"}, + {"rx_pkts_ok"}, + {"rx_bcast_pkts"}, + {"rx_mcast_pkts"}, + {"rx_ucast_pkts"}, + {"rx_undersize_pkts"}, + {"rx_oversize_pkts"}, + {"rx_jabber_pkts"}, + {"rx_undersize_fcerr_pkts"}, + {"rx_drop_events"}, + {"rx_fcerr_pkts"}, + {"rx_align_err"}, + {"rx_symbol_err"}, + {"rx_mac_err"}, + {"rx_ctl_pkts"}, + {"rx_pause_pkts"}, + {"rx_64_pkts"}, + {"rx_65_to_127_pkts"}, + {"rx_128_255_pkts"}, + {"rx_256_511_pkts"}, + {"rx_512_to_1023_pkts"}, + {"rx_1024_to_1518_pkts"}, + {"rx_1519_to_max_pkts"}, + {"rx_len_err_pkts"}, +}; + +static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(buf, ql_stats_str_arr, sizeof(ql_stats_str_arr)); + break; + } +} + +static int ql_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(ql_stats_str_arr); + default: + return -EOPNOTSUPP; + } +} + +static void +ql_get_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + struct nic_stats *s = &qdev->nic_stats; + + ql_update_stats(qdev); + + *data++ = s->tx_pkts; + *data++ = s->tx_bytes; + *data++ = s->tx_mcast_pkts; + *data++ = s->tx_bcast_pkts; + *data++ = s->tx_ucast_pkts; + *data++ = s->tx_ctl_pkts; + *data++ = s->tx_pause_pkts; + *data++ = s->tx_64_pkt; + *data++ = s->tx_65_to_127_pkt; + *data++ = s->tx_128_to_255_pkt; + *data++ = s->tx_256_511_pkt; + *data++ = s->tx_512_to_1023_pkt; + *data++ = s->tx_1024_to_1518_pkt; + *data++ = s->tx_1519_to_max_pkt; + *data++ = s->tx_undersize_pkt; + *data++ = s->tx_oversize_pkt; + *data++ = s->rx_bytes; + *data++ = s->rx_bytes_ok; + *data++ = s->rx_pkts; + *data++ = s->rx_pkts_ok; + *data++ = s->rx_bcast_pkts; + *data++ = s->rx_mcast_pkts; + *data++ = s->rx_ucast_pkts; + *data++ = s->rx_undersize_pkts; + *data++ = s->rx_oversize_pkts; + *data++ = s->rx_jabber_pkts; + *data++ = s->rx_undersize_fcerr_pkts; + *data++ = s->rx_drop_events; + *data++ = s->rx_fcerr_pkts; + *data++ = s->rx_align_err; + *data++ = s->rx_symbol_err; + *data++ = s->rx_mac_err; + *data++ = s->rx_ctl_pkts; + *data++ = s->rx_pause_pkts; + *data++ = s->rx_64_pkts; + *data++ = s->rx_65_to_127_pkts; + *data++ = s->rx_128_255_pkts; + *data++ = s->rx_256_511_pkts; + *data++ = s->rx_512_to_1023_pkts; + *data++ = s->rx_1024_to_1518_pkts; + *data++ = s->rx_1519_to_max_pkts; + *data++ = s->rx_len_err_pkts; +} + +static int ql_get_settings(struct net_device *ndev, + struct ethtool_cmd *ecmd) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->advertising = ADVERTISED_10000baseT_Full; + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->transceiver = XCVR_EXTERNAL; + if ((qdev->link_status & LINK_TYPE_MASK) == LINK_TYPE_10GBASET) { + ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); + ecmd->advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg); + ecmd->port = PORT_TP; + } else { + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_FIBRE; + ecmd->port = PORT_FIBRE; + } + + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + + return 0; +} + +static void ql_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *drvinfo) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + strncpy(drvinfo->driver, qlge_driver_name, 32); + strncpy(drvinfo->version, qlge_driver_version, 32); + strncpy(drvinfo->fw_version, "N/A", 32); + strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32); + drvinfo->n_stats = 0; + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +} + +static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) +{ + struct ql_adapter *qdev = netdev_priv(dev); + + c->rx_coalesce_usecs = qdev->rx_coalesce_usecs; + c->tx_coalesce_usecs = qdev->tx_coalesce_usecs; + + /* This chip coalesces as follows: + * If a packet arrives, hold off interrupts until + * cqicb->int_delay expires, but if no other packets arrive don't + * wait longer than cqicb->pkt_int_delay. But ethtool doesn't use a + * timer to coalesce on a frame basis. So, we have to take ethtool's + * max_coalesced_frames value and convert it to a delay in microseconds. + * We do this by using a basic thoughput of 1,000,000 frames per + * second @ (1024 bytes). This means one frame per usec. So it's a + * simple one to one ratio. + */ + c->rx_max_coalesced_frames = qdev->rx_max_coalesced_frames; + c->tx_max_coalesced_frames = qdev->tx_max_coalesced_frames; + + return 0; +} + +static int ql_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *c) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + + /* Validate user parameters. */ + if (c->rx_coalesce_usecs > qdev->rx_ring_size / 2) + return -EINVAL; + /* Don't wait more than 10 usec. */ + if (c->rx_max_coalesced_frames > MAX_INTER_FRAME_WAIT) + return -EINVAL; + if (c->tx_coalesce_usecs > qdev->tx_ring_size / 2) + return -EINVAL; + if (c->tx_max_coalesced_frames > MAX_INTER_FRAME_WAIT) + return -EINVAL; + + /* Verify a change took place before updating the hardware. */ + if (qdev->rx_coalesce_usecs == c->rx_coalesce_usecs && + qdev->tx_coalesce_usecs == c->tx_coalesce_usecs && + qdev->rx_max_coalesced_frames == c->rx_max_coalesced_frames && + qdev->tx_max_coalesced_frames == c->tx_max_coalesced_frames) + return 0; + + qdev->rx_coalesce_usecs = c->rx_coalesce_usecs; + qdev->tx_coalesce_usecs = c->tx_coalesce_usecs; + qdev->rx_max_coalesced_frames = c->rx_max_coalesced_frames; + qdev->tx_max_coalesced_frames = c->tx_max_coalesced_frames; + + return ql_update_ring_coalescing(qdev); +} + +static u32 ql_get_rx_csum(struct net_device *netdev) +{ + struct ql_adapter *qdev = netdev_priv(netdev); + return qdev->rx_csum; +} + +static int ql_set_rx_csum(struct net_device *netdev, uint32_t data) +{ + struct ql_adapter *qdev = netdev_priv(netdev); + qdev->rx_csum = data; + return 0; +} + +static int ql_set_tso(struct net_device *ndev, uint32_t data) +{ + + if (data) { + ndev->features |= NETIF_F_TSO; + ndev->features |= NETIF_F_TSO6; + } else { + ndev->features &= ~NETIF_F_TSO; + ndev->features &= ~NETIF_F_TSO6; + } + return 0; +} + +static u32 ql_get_msglevel(struct net_device *ndev) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + return qdev->msg_enable; +} + +static void ql_set_msglevel(struct net_device *ndev, u32 value) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + qdev->msg_enable = value; +} + +const struct ethtool_ops qlge_ethtool_ops = { + .get_settings = ql_get_settings, + .get_drvinfo = ql_get_drvinfo, + .get_msglevel = ql_get_msglevel, + .set_msglevel = ql_set_msglevel, + .get_link = ethtool_op_get_link, + .get_rx_csum = ql_get_rx_csum, + .set_rx_csum = ql_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ql_set_tso, + .get_coalesce = ql_get_coalesce, + .set_coalesce = ql_set_coalesce, + .get_sset_count = ql_get_sset_count, + .get_strings = ql_get_strings, + .get_ethtool_stats = ql_get_ethtool_stats, +}; + diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c new file mode 100644 index 00000000000..ad878e2b9de --- /dev/null +++ b/drivers/net/qlge/qlge_main.c @@ -0,0 +1,3954 @@ +/* + * QLogic qlge NIC HBA Driver + * Copyright (c) 2003-2008 QLogic Corporation + * See LICENSE.qlge for copyright and licensing details. + * Author: Linux qlge network device driver by + * Ron Mercer + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qlge.h" + +char qlge_driver_name[] = DRV_NAME; +const char qlge_driver_version[] = DRV_VERSION; + +MODULE_AUTHOR("Ron Mercer "); +MODULE_DESCRIPTION(DRV_STRING " "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +static const u32 default_msg = + NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | +/* NETIF_MSG_TIMER | */ + NETIF_MSG_IFDOWN | + NETIF_MSG_IFUP | + NETIF_MSG_RX_ERR | + NETIF_MSG_TX_ERR | + NETIF_MSG_TX_QUEUED | + NETIF_MSG_INTR | NETIF_MSG_TX_DONE | NETIF_MSG_RX_STATUS | +/* NETIF_MSG_PKTDATA | */ + NETIF_MSG_HW | NETIF_MSG_WOL | 0; + +static int debug = 0x00007fff; /* defaults above */ +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +#define MSIX_IRQ 0 +#define MSI_IRQ 1 +#define LEG_IRQ 2 +static int irq_type = MSIX_IRQ; +module_param(irq_type, int, MSIX_IRQ); +MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); + +static struct pci_device_id qlge_pci_tbl[] __devinitdata = { + {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)}, + {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID1)}, + /* required last entry */ + {0,} +}; + +MODULE_DEVICE_TABLE(pci, qlge_pci_tbl); + +/* This hardware semaphore causes exclusive access to + * resources shared between the NIC driver, MPI firmware, + * FCOE firmware and the FC driver. + */ +static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask) +{ + u32 sem_bits = 0; + + switch (sem_mask) { + case SEM_XGMAC0_MASK: + sem_bits = SEM_SET << SEM_XGMAC0_SHIFT; + break; + case SEM_XGMAC1_MASK: + sem_bits = SEM_SET << SEM_XGMAC1_SHIFT; + break; + case SEM_ICB_MASK: + sem_bits = SEM_SET << SEM_ICB_SHIFT; + break; + case SEM_MAC_ADDR_MASK: + sem_bits = SEM_SET << SEM_MAC_ADDR_SHIFT; + break; + case SEM_FLASH_MASK: + sem_bits = SEM_SET << SEM_FLASH_SHIFT; + break; + case SEM_PROBE_MASK: + sem_bits = SEM_SET << SEM_PROBE_SHIFT; + break; + case SEM_RT_IDX_MASK: + sem_bits = SEM_SET << SEM_RT_IDX_SHIFT; + break; + case SEM_PROC_REG_MASK: + sem_bits = SEM_SET << SEM_PROC_REG_SHIFT; + break; + default: + QPRINTK(qdev, PROBE, ALERT, "Bad Semaphore mask!.\n"); + return -EINVAL; + } + + ql_write32(qdev, SEM, sem_bits | sem_mask); + return !(ql_read32(qdev, SEM) & sem_bits); +} + +int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask) +{ + unsigned int seconds = 3; + do { + if (!ql_sem_trylock(qdev, sem_mask)) + return 0; + ssleep(1); + } while (--seconds); + return -ETIMEDOUT; +} + +void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask) +{ + ql_write32(qdev, SEM, sem_mask); + ql_read32(qdev, SEM); /* flush */ +} + +/* This function waits for a specific bit to come ready + * in a given register. It is used mostly by the initialize + * process, but is also used in kernel thread API such as + * netdev->set_multi, netdev->set_mac_address, netdev->vlan_rx_add_vid. + */ +int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit) +{ + u32 temp; + int count = UDELAY_COUNT; + + while (count) { + temp = ql_read32(qdev, reg); + + /* check for errors */ + if (temp & err_bit) { + QPRINTK(qdev, PROBE, ALERT, + "register 0x%.08x access error, value = 0x%.08x!.\n", + reg, temp); + return -EIO; + } else if (temp & bit) + return 0; + udelay(UDELAY_DELAY); + count--; + } + QPRINTK(qdev, PROBE, ALERT, + "Timed out waiting for reg %x to come ready.\n", reg); + return -ETIMEDOUT; +} + +/* The CFG register is used to download TX and RX control blocks + * to the chip. This function waits for an operation to complete. + */ +static int ql_wait_cfg(struct ql_adapter *qdev, u32 bit) +{ + int count = UDELAY_COUNT; + u32 temp; + + while (count) { + temp = ql_read32(qdev, CFG); + if (temp & CFG_LE) + return -EIO; + if (!(temp & bit)) + return 0; + udelay(UDELAY_DELAY); + count--; + } + return -ETIMEDOUT; +} + + +/* Used to issue init control blocks to hw. Maps control block, + * sets address, triggers download, waits for completion. + */ +int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, + u16 q_id) +{ + u64 map; + int status = 0; + int direction; + u32 mask; + u32 value; + + direction = + (bit & (CFG_LRQ | CFG_LR | CFG_LCQ)) ? PCI_DMA_TODEVICE : + PCI_DMA_FROMDEVICE; + + map = pci_map_single(qdev->pdev, ptr, size, direction); + if (pci_dma_mapping_error(qdev->pdev, map)) { + QPRINTK(qdev, IFUP, ERR, "Couldn't map DMA area.\n"); + return -ENOMEM; + } + + status = ql_wait_cfg(qdev, bit); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Timed out waiting for CFG to come ready.\n"); + goto exit; + } + + status = ql_sem_spinlock(qdev, SEM_ICB_MASK); + if (status) + goto exit; + ql_write32(qdev, ICB_L, (u32) map); + ql_write32(qdev, ICB_H, (u32) (map >> 32)); + ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ + + mask = CFG_Q_MASK | (bit << 16); + value = bit | (q_id << CFG_Q_SHIFT); + ql_write32(qdev, CFG, (mask | value)); + + /* + * Wait for the bit to clear after signaling hw. + */ + status = ql_wait_cfg(qdev, bit); +exit: + pci_unmap_single(qdev->pdev, map, size, direction); + return status; +} + +/* Get a specific MAC address from the CAM. Used for debug and reg dump. */ +int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, + u32 *value) +{ + u32 offset = 0; + int status; + + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; + switch (type) { + case MAC_ADDR_TYPE_MULTI_MAC: + case MAC_ADDR_TYPE_CAM_MAC: + { + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E); + if (status) + goto exit; + *value++ = ql_read32(qdev, MAC_ADDR_DATA); + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E); + if (status) + goto exit; + *value++ = ql_read32(qdev, MAC_ADDR_DATA); + if (type == MAC_ADDR_TYPE_CAM_MAC) { + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ + status = + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, + MAC_ADDR_MR, MAC_ADDR_E); + if (status) + goto exit; + *value++ = ql_read32(qdev, MAC_ADDR_DATA); + } + break; + } + case MAC_ADDR_TYPE_VLAN: + case MAC_ADDR_TYPE_MULTI_FLTR: + default: + QPRINTK(qdev, IFUP, CRIT, + "Address type %d not yet supported.\n", type); + status = -EPERM; + } +exit: + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + return status; +} + +/* Set up a MAC, multicast or VLAN address for the + * inbound frame matching. + */ +static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, + u16 index) +{ + u32 offset = 0; + int status = 0; + + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; + switch (type) { + case MAC_ADDR_TYPE_MULTI_MAC: + case MAC_ADDR_TYPE_CAM_MAC: + { + u32 cam_output; + u32 upper = (addr[0] << 8) | addr[1]; + u32 lower = + (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | + (addr[5]); + + QPRINTK(qdev, IFUP, INFO, + "Adding %s address %02x:%02x:%02x:%02x:%02x:%02x" + " at index %d in the CAM.\n", + ((type == + MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" : + "UNICAST"), addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], index); + + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + type); /* type */ + ql_write32(qdev, MAC_ADDR_DATA, lower); + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + type); /* type */ + ql_write32(qdev, MAC_ADDR_DATA, upper); + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + type); /* type */ + /* This field should also include the queue id + and possibly the function id. Right now we hardcode + the route field to NIC core. + */ + if (type == MAC_ADDR_TYPE_CAM_MAC) { + cam_output = (CAM_OUT_ROUTE_NIC | + (qdev-> + func << CAM_OUT_FUNC_SHIFT) | + (qdev-> + rss_ring_first_cq_id << + CAM_OUT_CQ_ID_SHIFT)); + if (qdev->vlgrp) + cam_output |= CAM_OUT_RV; + /* route to NIC core */ + ql_write32(qdev, MAC_ADDR_DATA, cam_output); + } + break; + } + case MAC_ADDR_TYPE_VLAN: + { + u32 enable_bit = *((u32 *) &addr[0]); + /* For VLAN, the addr actually holds a bit that + * either enables or disables the vlan id we are + * addressing. It's either MAC_ADDR_E on or off. + * That's bit-27 we're talking about. + */ + QPRINTK(qdev, IFUP, INFO, "%s VLAN ID %d %s the CAM.\n", + (enable_bit ? "Adding" : "Removing"), + index, (enable_bit ? "to" : "from")); + + status = + ql_wait_reg_rdy(qdev, + MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); + if (status) + goto exit; + ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */ + (index << MAC_ADDR_IDX_SHIFT) | /* index */ + type | /* type */ + enable_bit); /* enable/disable */ + break; + } + case MAC_ADDR_TYPE_MULTI_FLTR: + default: + QPRINTK(qdev, IFUP, CRIT, + "Address type %d not yet supported.\n", type); + status = -EPERM; + } +exit: + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + return status; +} + +/* Get a specific frame routing value from the CAM. + * Used for debug and reg dump. + */ +int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value) +{ + int status = 0; + + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + goto exit; + + status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, RT_IDX_E); + if (status) + goto exit; + + ql_write32(qdev, RT_IDX, + RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT)); + status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, RT_IDX_E); + if (status) + goto exit; + *value = ql_read32(qdev, RT_DATA); +exit: + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); + return status; +} + +/* The NIC function for this chip has 16 routing indexes. Each one can be used + * to route different frame types to various inbound queues. We send broadcast/ + * multicast/error frames to the default queue for slow handling, + * and CAM hit/RSS frames to the fast handling queues. + */ +static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, + int enable) +{ + int status; + u32 value = 0; + + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return status; + + QPRINTK(qdev, IFUP, DEBUG, + "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s mask %s the routing reg.\n", + (enable ? "Adding" : "Removing"), + ((index == RT_IDX_ALL_ERR_SLOT) ? "MAC ERROR/ALL ERROR" : ""), + ((index == RT_IDX_IP_CSUM_ERR_SLOT) ? "IP CSUM ERROR" : ""), + ((index == + RT_IDX_TCP_UDP_CSUM_ERR_SLOT) ? "TCP/UDP CSUM ERROR" : ""), + ((index == RT_IDX_BCAST_SLOT) ? "BROADCAST" : ""), + ((index == RT_IDX_MCAST_MATCH_SLOT) ? "MULTICAST MATCH" : ""), + ((index == RT_IDX_ALLMULTI_SLOT) ? "ALL MULTICAST MATCH" : ""), + ((index == RT_IDX_UNUSED6_SLOT) ? "UNUSED6" : ""), + ((index == RT_IDX_UNUSED7_SLOT) ? "UNUSED7" : ""), + ((index == RT_IDX_RSS_MATCH_SLOT) ? "RSS ALL/IPV4 MATCH" : ""), + ((index == RT_IDX_RSS_IPV6_SLOT) ? "RSS IPV6" : ""), + ((index == RT_IDX_RSS_TCP4_SLOT) ? "RSS TCP4" : ""), + ((index == RT_IDX_RSS_TCP6_SLOT) ? "RSS TCP6" : ""), + ((index == RT_IDX_CAM_HIT_SLOT) ? "CAM HIT" : ""), + ((index == RT_IDX_UNUSED013) ? "UNUSED13" : ""), + ((index == RT_IDX_UNUSED014) ? "UNUSED14" : ""), + ((index == RT_IDX_PROMISCUOUS_SLOT) ? "PROMISCUOUS" : ""), + (enable ? "to" : "from")); + + switch (mask) { + case RT_IDX_CAM_HIT: + { + value = RT_IDX_DST_CAM_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_CAM_HIT_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_VALID: /* Promiscuous Mode frames. */ + { + value = RT_IDX_DST_DFLT_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_PROMISCUOUS_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_ERR: /* Pass up MAC,IP,TCP/UDP error frames. */ + { + value = RT_IDX_DST_DFLT_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_ALL_ERR_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_BCAST: /* Pass up Broadcast frames to default Q. */ + { + value = RT_IDX_DST_DFLT_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_BCAST_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_MCAST: /* Pass up All Multicast frames. */ + { + value = RT_IDX_DST_CAM_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_MCAST_MATCH: /* Pass up matched Multicast frames. */ + { + value = RT_IDX_DST_CAM_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case RT_IDX_RSS_MATCH: /* Pass up matched RSS frames. */ + { + value = RT_IDX_DST_RSS | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (RT_IDX_RSS_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */ + break; + } + case 0: /* Clear the E-bit on an entry. */ + { + value = RT_IDX_DST_DFLT_Q | /* dest */ + RT_IDX_TYPE_NICQ | /* type */ + (index << RT_IDX_IDX_SHIFT);/* index */ + break; + } + default: + QPRINTK(qdev, IFUP, ERR, "Mask type %d not yet supported.\n", + mask); + status = -EPERM; + goto exit; + } + + if (value) { + status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0); + if (status) + goto exit; + value |= (enable ? RT_IDX_E : 0); + ql_write32(qdev, RT_IDX, value); + ql_write32(qdev, RT_DATA, enable ? mask : 0); + } +exit: + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); + return status; +} + +static void ql_enable_interrupts(struct ql_adapter *qdev) +{ + ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16) | INTR_EN_EI); +} + +static void ql_disable_interrupts(struct ql_adapter *qdev) +{ + ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16)); +} + +/* If we're running with multiple MSI-X vectors then we enable on the fly. + * Otherwise, we may have multiple outstanding workers and don't want to + * enable until the last one finishes. In this case, the irq_cnt gets + * incremented everytime we queue a worker and decremented everytime + * a worker finishes. Once it hits zero we enable the interrupt. + */ +void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) +{ + if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) + ql_write32(qdev, INTR_EN, + qdev->intr_context[intr].intr_en_mask); + else { + if (qdev->legacy_check) + spin_lock(&qdev->legacy_lock); + if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) { + QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n", + intr); + ql_write32(qdev, INTR_EN, + qdev->intr_context[intr].intr_en_mask); + } else { + QPRINTK(qdev, INTR, ERR, + "Skip enable, other queue(s) are active.\n"); + } + if (qdev->legacy_check) + spin_unlock(&qdev->legacy_lock); + } +} + +static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) +{ + u32 var = 0; + + if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) + goto exit; + else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) { + ql_write32(qdev, INTR_EN, + qdev->intr_context[intr].intr_dis_mask); + var = ql_read32(qdev, STS); + } + atomic_inc(&qdev->intr_context[intr].irq_cnt); +exit: + return var; +} + +static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev) +{ + int i; + for (i = 0; i < qdev->intr_count; i++) { + /* The enable call does a atomic_dec_and_test + * and enables only if the result is zero. + * So we precharge it here. + */ + atomic_set(&qdev->intr_context[i].irq_cnt, 1); + ql_enable_completion_interrupt(qdev, i); + } + +} + +int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data) +{ + int status = 0; + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, + FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); + if (status) + goto exit; + /* set up for reg read */ + ql_write32(qdev, FLASH_ADDR, FLASH_ADDR_R | offset); + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, + FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); + if (status) + goto exit; + /* get the data */ + *data = ql_read32(qdev, FLASH_DATA); +exit: + return status; +} + +static int ql_get_flash_params(struct ql_adapter *qdev) +{ + int i; + int status; + u32 *p = (u32 *)&qdev->flash; + + if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) + return -ETIMEDOUT; + + for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) { + status = ql_read_flash_word(qdev, i, p); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + goto exit; + } + + } +exit: + ql_sem_unlock(qdev, SEM_FLASH_MASK); + return status; +} + +/* xgmac register are located behind the xgmac_addr and xgmac_data + * register pair. Each read/write requires us to wait for the ready + * bit before reading/writing the data. + */ +static int ql_write_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 data) +{ + int status; + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + if (status) + return status; + /* write the data to the data reg */ + ql_write32(qdev, XGMAC_DATA, data); + /* trigger the write */ + ql_write32(qdev, XGMAC_ADDR, reg); + return status; +} + +/* xgmac register are located behind the xgmac_addr and xgmac_data + * register pair. Each read/write requires us to wait for the ready + * bit before reading/writing the data. + */ +int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data) +{ + int status = 0; + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + if (status) + goto exit; + /* set up for reg read */ + ql_write32(qdev, XGMAC_ADDR, reg | XGMAC_ADDR_R); + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + if (status) + goto exit; + /* get the data */ + *data = ql_read32(qdev, XGMAC_DATA); +exit: + return status; +} + +/* This is used for reading the 64-bit statistics regs. */ +int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data) +{ + int status = 0; + u32 hi = 0; + u32 lo = 0; + + status = ql_read_xgmac_reg(qdev, reg, &lo); + if (status) + goto exit; + + status = ql_read_xgmac_reg(qdev, reg + 4, &hi); + if (status) + goto exit; + + *data = (u64) lo | ((u64) hi << 32); + +exit: + return status; +} + +/* Take the MAC Core out of reset. + * Enable statistics counting. + * Take the transmitter/receiver out of reset. + * This functionality may be done in the MPI firmware at a + * later date. + */ +static int ql_port_initialize(struct ql_adapter *qdev) +{ + int status = 0; + u32 data; + + if (ql_sem_trylock(qdev, qdev->xg_sem_mask)) { + /* Another function has the semaphore, so + * wait for the port init bit to come ready. + */ + QPRINTK(qdev, LINK, INFO, + "Another function has the semaphore, so wait for the port init bit to come ready.\n"); + status = ql_wait_reg_rdy(qdev, STS, qdev->port_init, 0); + if (status) { + QPRINTK(qdev, LINK, CRIT, + "Port initialize timed out.\n"); + } + return status; + } + + QPRINTK(qdev, LINK, INFO, "Got xgmac semaphore!.\n"); + /* Set the core reset. */ + status = ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data); + if (status) + goto end; + data |= GLOBAL_CFG_RESET; + status = ql_write_xgmac_reg(qdev, GLOBAL_CFG, data); + if (status) + goto end; + + /* Clear the core reset and turn on jumbo for receiver. */ + data &= ~GLOBAL_CFG_RESET; /* Clear core reset. */ + data |= GLOBAL_CFG_JUMBO; /* Turn on jumbo. */ + data |= GLOBAL_CFG_TX_STAT_EN; + data |= GLOBAL_CFG_RX_STAT_EN; + status = ql_write_xgmac_reg(qdev, GLOBAL_CFG, data); + if (status) + goto end; + + /* Enable transmitter, and clear it's reset. */ + status = ql_read_xgmac_reg(qdev, TX_CFG, &data); + if (status) + goto end; + data &= ~TX_CFG_RESET; /* Clear the TX MAC reset. */ + data |= TX_CFG_EN; /* Enable the transmitter. */ + status = ql_write_xgmac_reg(qdev, TX_CFG, data); + if (status) + goto end; + + /* Enable receiver and clear it's reset. */ + status = ql_read_xgmac_reg(qdev, RX_CFG, &data); + if (status) + goto end; + data &= ~RX_CFG_RESET; /* Clear the RX MAC reset. */ + data |= RX_CFG_EN; /* Enable the receiver. */ + status = ql_write_xgmac_reg(qdev, RX_CFG, data); + if (status) + goto end; + + /* Turn on jumbo. */ + status = + ql_write_xgmac_reg(qdev, MAC_TX_PARAMS, MAC_TX_PARAMS_JUMBO | (0x2580 << 16)); + if (status) + goto end; + status = + ql_write_xgmac_reg(qdev, MAC_RX_PARAMS, 0x2580); + if (status) + goto end; + + /* Signal to the world that the port is enabled. */ + ql_write32(qdev, STS, ((qdev->port_init << 16) | qdev->port_init)); +end: + ql_sem_unlock(qdev, qdev->xg_sem_mask); + return status; +} + +/* Get the next large buffer. */ +struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring) +{ + struct bq_desc *lbq_desc = &rx_ring->lbq[rx_ring->lbq_curr_idx]; + rx_ring->lbq_curr_idx++; + if (rx_ring->lbq_curr_idx == rx_ring->lbq_len) + rx_ring->lbq_curr_idx = 0; + rx_ring->lbq_free_cnt++; + return lbq_desc; +} + +/* Get the next small buffer. */ +struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring) +{ + struct bq_desc *sbq_desc = &rx_ring->sbq[rx_ring->sbq_curr_idx]; + rx_ring->sbq_curr_idx++; + if (rx_ring->sbq_curr_idx == rx_ring->sbq_len) + rx_ring->sbq_curr_idx = 0; + rx_ring->sbq_free_cnt++; + return sbq_desc; +} + +/* Update an rx ring index. */ +static void ql_update_cq(struct rx_ring *rx_ring) +{ + rx_ring->cnsmr_idx++; + rx_ring->curr_entry++; + if (unlikely(rx_ring->cnsmr_idx == rx_ring->cq_len)) { + rx_ring->cnsmr_idx = 0; + rx_ring->curr_entry = rx_ring->cq_base; + } +} + +static void ql_write_cq_idx(struct rx_ring *rx_ring) +{ + ql_write_db_reg(rx_ring->cnsmr_idx, rx_ring->cnsmr_idx_db_reg); +} + +/* Process (refill) a large buffer queue. */ +static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) +{ + int clean_idx = rx_ring->lbq_clean_idx; + struct bq_desc *lbq_desc; + struct bq_element *bq; + u64 map; + int i; + + while (rx_ring->lbq_free_cnt > 16) { + for (i = 0; i < 16; i++) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "lbq: try cleaning clean_idx = %d.\n", + clean_idx); + lbq_desc = &rx_ring->lbq[clean_idx]; + bq = lbq_desc->bq; + if (lbq_desc->p.lbq_page == NULL) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "lbq: getting new page for index %d.\n", + lbq_desc->index); + lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC); + if (lbq_desc->p.lbq_page == NULL) { + QPRINTK(qdev, RX_STATUS, ERR, + "Couldn't get a page.\n"); + return; + } + map = pci_map_page(qdev->pdev, + lbq_desc->p.lbq_page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(qdev->pdev, map)) { + QPRINTK(qdev, RX_STATUS, ERR, + "PCI mapping failed.\n"); + return; + } + pci_unmap_addr_set(lbq_desc, mapaddr, map); + pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); + bq->addr_lo = /*lbq_desc->addr_lo = */ + cpu_to_le32(map); + bq->addr_hi = /*lbq_desc->addr_hi = */ + cpu_to_le32(map >> 32); + } + clean_idx++; + if (clean_idx == rx_ring->lbq_len) + clean_idx = 0; + } + + rx_ring->lbq_clean_idx = clean_idx; + rx_ring->lbq_prod_idx += 16; + if (rx_ring->lbq_prod_idx == rx_ring->lbq_len) + rx_ring->lbq_prod_idx = 0; + QPRINTK(qdev, RX_STATUS, DEBUG, + "lbq: updating prod idx = %d.\n", + rx_ring->lbq_prod_idx); + ql_write_db_reg(rx_ring->lbq_prod_idx, + rx_ring->lbq_prod_idx_db_reg); + rx_ring->lbq_free_cnt -= 16; + } +} + +/* Process (refill) a small buffer queue. */ +static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) +{ + int clean_idx = rx_ring->sbq_clean_idx; + struct bq_desc *sbq_desc; + struct bq_element *bq; + u64 map; + int i; + + while (rx_ring->sbq_free_cnt > 16) { + for (i = 0; i < 16; i++) { + sbq_desc = &rx_ring->sbq[clean_idx]; + QPRINTK(qdev, RX_STATUS, DEBUG, + "sbq: try cleaning clean_idx = %d.\n", + clean_idx); + bq = sbq_desc->bq; + if (sbq_desc->p.skb == NULL) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "sbq: getting new skb for index %d.\n", + sbq_desc->index); + sbq_desc->p.skb = + netdev_alloc_skb(qdev->ndev, + rx_ring->sbq_buf_size); + if (sbq_desc->p.skb == NULL) { + QPRINTK(qdev, PROBE, ERR, + "Couldn't get an skb.\n"); + rx_ring->sbq_clean_idx = clean_idx; + return; + } + skb_reserve(sbq_desc->p.skb, QLGE_SB_PAD); + map = pci_map_single(qdev->pdev, + sbq_desc->p.skb->data, + rx_ring->sbq_buf_size / + 2, PCI_DMA_FROMDEVICE); + pci_unmap_addr_set(sbq_desc, mapaddr, map); + pci_unmap_len_set(sbq_desc, maplen, + rx_ring->sbq_buf_size / 2); + bq->addr_lo = cpu_to_le32(map); + bq->addr_hi = cpu_to_le32(map >> 32); + } + + clean_idx++; + if (clean_idx == rx_ring->sbq_len) + clean_idx = 0; + } + rx_ring->sbq_clean_idx = clean_idx; + rx_ring->sbq_prod_idx += 16; + if (rx_ring->sbq_prod_idx == rx_ring->sbq_len) + rx_ring->sbq_prod_idx = 0; + QPRINTK(qdev, RX_STATUS, DEBUG, + "sbq: updating prod idx = %d.\n", + rx_ring->sbq_prod_idx); + ql_write_db_reg(rx_ring->sbq_prod_idx, + rx_ring->sbq_prod_idx_db_reg); + + rx_ring->sbq_free_cnt -= 16; + } +} + +static void ql_update_buffer_queues(struct ql_adapter *qdev, + struct rx_ring *rx_ring) +{ + ql_update_sbq(qdev, rx_ring); + ql_update_lbq(qdev, rx_ring); +} + +/* Unmaps tx buffers. Can be called from send() if a pci mapping + * fails at some stage, or from the interrupt when a tx completes. + */ +static void ql_unmap_send(struct ql_adapter *qdev, + struct tx_ring_desc *tx_ring_desc, int mapped) +{ + int i; + for (i = 0; i < mapped; i++) { + if (i == 0 || (i == 7 && mapped > 7)) { + /* + * Unmap the skb->data area, or the + * external sglist (AKA the Outbound + * Address List (OAL)). + * If its the zeroeth element, then it's + * the skb->data area. If it's the 7th + * element and there is more than 6 frags, + * then its an OAL. + */ + if (i == 7) { + QPRINTK(qdev, TX_DONE, DEBUG, + "unmapping OAL area.\n"); + } + pci_unmap_single(qdev->pdev, + pci_unmap_addr(&tx_ring_desc->map[i], + mapaddr), + pci_unmap_len(&tx_ring_desc->map[i], + maplen), + PCI_DMA_TODEVICE); + } else { + QPRINTK(qdev, TX_DONE, DEBUG, "unmapping frag %d.\n", + i); + pci_unmap_page(qdev->pdev, + pci_unmap_addr(&tx_ring_desc->map[i], + mapaddr), + pci_unmap_len(&tx_ring_desc->map[i], + maplen), PCI_DMA_TODEVICE); + } + } + +} + +/* Map the buffers for this transmit. This will return + * NETDEV_TX_BUSY or NETDEV_TX_OK based on success. + */ +static int ql_map_send(struct ql_adapter *qdev, + struct ob_mac_iocb_req *mac_iocb_ptr, + struct sk_buff *skb, struct tx_ring_desc *tx_ring_desc) +{ + int len = skb_headlen(skb); + dma_addr_t map; + int frag_idx, err, map_idx = 0; + struct tx_buf_desc *tbd = mac_iocb_ptr->tbd; + int frag_cnt = skb_shinfo(skb)->nr_frags; + + if (frag_cnt) { + QPRINTK(qdev, TX_QUEUED, DEBUG, "frag_cnt = %d.\n", frag_cnt); + } + /* + * Map the skb buffer first. + */ + map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); + + err = pci_dma_mapping_error(qdev->pdev, map); + if (err) { + QPRINTK(qdev, TX_QUEUED, ERR, + "PCI mapping failed with error: %d\n", err); + + return NETDEV_TX_BUSY; + } + + tbd->len = cpu_to_le32(len); + tbd->addr = cpu_to_le64(map); + pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, map); + pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen, len); + map_idx++; + + /* + * This loop fills the remainder of the 8 address descriptors + * in the IOCB. If there are more than 7 fragments, then the + * eighth address desc will point to an external list (OAL). + * When this happens, the remainder of the frags will be stored + * in this list. + */ + for (frag_idx = 0; frag_idx < frag_cnt; frag_idx++, map_idx++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_idx]; + tbd++; + if (frag_idx == 6 && frag_cnt > 7) { + /* Let's tack on an sglist. + * Our control block will now + * look like this: + * iocb->seg[0] = skb->data + * iocb->seg[1] = frag[0] + * iocb->seg[2] = frag[1] + * iocb->seg[3] = frag[2] + * iocb->seg[4] = frag[3] + * iocb->seg[5] = frag[4] + * iocb->seg[6] = frag[5] + * iocb->seg[7] = ptr to OAL (external sglist) + * oal->seg[0] = frag[6] + * oal->seg[1] = frag[7] + * oal->seg[2] = frag[8] + * oal->seg[3] = frag[9] + * oal->seg[4] = frag[10] + * etc... + */ + /* Tack on the OAL in the eighth segment of IOCB. */ + map = pci_map_single(qdev->pdev, &tx_ring_desc->oal, + sizeof(struct oal), + PCI_DMA_TODEVICE); + err = pci_dma_mapping_error(qdev->pdev, map); + if (err) { + QPRINTK(qdev, TX_QUEUED, ERR, + "PCI mapping outbound address list with error: %d\n", + err); + goto map_error; + } + + tbd->addr = cpu_to_le64(map); + /* + * The length is the number of fragments + * that remain to be mapped times the length + * of our sglist (OAL). + */ + tbd->len = + cpu_to_le32((sizeof(struct tx_buf_desc) * + (frag_cnt - frag_idx)) | TX_DESC_C); + pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, + map); + pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen, + sizeof(struct oal)); + tbd = (struct tx_buf_desc *)&tx_ring_desc->oal; + map_idx++; + } + + map = + pci_map_page(qdev->pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE); + + err = pci_dma_mapping_error(qdev->pdev, map); + if (err) { + QPRINTK(qdev, TX_QUEUED, ERR, + "PCI mapping frags failed with error: %d.\n", + err); + goto map_error; + } + + tbd->addr = cpu_to_le64(map); + tbd->len = cpu_to_le32(frag->size); + pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, map); + pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen, + frag->size); + + } + /* Save the number of segments we've mapped. */ + tx_ring_desc->map_cnt = map_idx; + /* Terminate the last segment. */ + tbd->len = cpu_to_le32(le32_to_cpu(tbd->len) | TX_DESC_E); + return NETDEV_TX_OK; + +map_error: + /* + * If the first frag mapping failed, then i will be zero. + * This causes the unmap of the skb->data area. Otherwise + * we pass in the number of frags that mapped successfully + * so they can be umapped. + */ + ql_unmap_send(qdev, tx_ring_desc, map_idx); + return NETDEV_TX_BUSY; +} + +void ql_realign_skb(struct sk_buff *skb, int len) +{ + void *temp_addr = skb->data; + + /* Undo the skb_reserve(skb,32) we did before + * giving to hardware, and realign data on + * a 2-byte boundary. + */ + skb->data -= QLGE_SB_PAD - NET_IP_ALIGN; + skb->tail -= QLGE_SB_PAD - NET_IP_ALIGN; + skb_copy_to_linear_data(skb, temp_addr, + (unsigned int)len); +} + +/* + * This function builds an skb for the given inbound + * completion. It will be rewritten for readability in the near + * future, but for not it works well. + */ +static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp) +{ + struct bq_desc *lbq_desc; + struct bq_desc *sbq_desc; + struct sk_buff *skb = NULL; + u32 length = le32_to_cpu(ib_mac_rsp->data_len); + u32 hdr_len = le32_to_cpu(ib_mac_rsp->hdr_len); + + /* + * Handle the header buffer if present. + */ + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV && + ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { + QPRINTK(qdev, RX_STATUS, DEBUG, "Header of %d bytes in small buffer.\n", hdr_len); + /* + * Headers fit nicely into a small buffer. + */ + sbq_desc = ql_get_curr_sbuf(rx_ring); + pci_unmap_single(qdev->pdev, + pci_unmap_addr(sbq_desc, mapaddr), + pci_unmap_len(sbq_desc, maplen), + PCI_DMA_FROMDEVICE); + skb = sbq_desc->p.skb; + ql_realign_skb(skb, hdr_len); + skb_put(skb, hdr_len); + sbq_desc->p.skb = NULL; + } + + /* + * Handle the data buffer(s). + */ + if (unlikely(!length)) { /* Is there data too? */ + QPRINTK(qdev, RX_STATUS, DEBUG, + "No Data buffer in this packet.\n"); + return skb; + } + + if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Headers in small, data of %d bytes in small, combine them.\n", length); + /* + * Data is less than small buffer size so it's + * stuffed in a small buffer. + * For this case we append the data + * from the "data" small buffer to the "header" small + * buffer. + */ + sbq_desc = ql_get_curr_sbuf(rx_ring); + pci_dma_sync_single_for_cpu(qdev->pdev, + pci_unmap_addr + (sbq_desc, mapaddr), + pci_unmap_len + (sbq_desc, maplen), + PCI_DMA_FROMDEVICE); + memcpy(skb_put(skb, length), + sbq_desc->p.skb->data, length); + pci_dma_sync_single_for_device(qdev->pdev, + pci_unmap_addr + (sbq_desc, + mapaddr), + pci_unmap_len + (sbq_desc, + maplen), + PCI_DMA_FROMDEVICE); + } else { + QPRINTK(qdev, RX_STATUS, DEBUG, + "%d bytes in a single small buffer.\n", length); + sbq_desc = ql_get_curr_sbuf(rx_ring); + skb = sbq_desc->p.skb; + ql_realign_skb(skb, length); + skb_put(skb, length); + pci_unmap_single(qdev->pdev, + pci_unmap_addr(sbq_desc, + mapaddr), + pci_unmap_len(sbq_desc, + maplen), + PCI_DMA_FROMDEVICE); + sbq_desc->p.skb = NULL; + } + } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Header in small, %d bytes in large. Chain large to small!\n", length); + /* + * The data is in a single large buffer. We + * chain it to the header buffer's skb and let + * it rip. + */ + lbq_desc = ql_get_curr_lbuf(rx_ring); + pci_unmap_page(qdev->pdev, + pci_unmap_addr(lbq_desc, + mapaddr), + pci_unmap_len(lbq_desc, maplen), + PCI_DMA_FROMDEVICE); + QPRINTK(qdev, RX_STATUS, DEBUG, + "Chaining page to skb.\n"); + skb_fill_page_desc(skb, 0, lbq_desc->p.lbq_page, + 0, length); + skb->len += length; + skb->data_len += length; + skb->truesize += length; + lbq_desc->p.lbq_page = NULL; + } else { + /* + * The headers and data are in a single large buffer. We + * copy it to a new skb and let it go. This can happen with + * jumbo mtu on a non-TCP/UDP frame. + */ + lbq_desc = ql_get_curr_lbuf(rx_ring); + skb = netdev_alloc_skb(qdev->ndev, length); + if (skb == NULL) { + QPRINTK(qdev, PROBE, DEBUG, + "No skb available, drop the packet.\n"); + return NULL; + } + skb_reserve(skb, NET_IP_ALIGN); + QPRINTK(qdev, RX_STATUS, DEBUG, + "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); + skb_fill_page_desc(skb, 0, lbq_desc->p.lbq_page, + 0, length); + skb->len += length; + skb->data_len += length; + skb->truesize += length; + length -= length; + lbq_desc->p.lbq_page = NULL; + __pskb_pull_tail(skb, + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? + VLAN_ETH_HLEN : ETH_HLEN); + } + } else { + /* + * The data is in a chain of large buffers + * pointed to by a small buffer. We loop + * thru and chain them to the our small header + * buffer's skb. + * frags: There are 18 max frags and our small + * buffer will hold 32 of them. The thing is, + * we'll use 3 max for our 9000 byte jumbo + * frames. If the MTU goes up we could + * eventually be in trouble. + */ + int size, offset, i = 0; + struct bq_element *bq, bq_array[8]; + sbq_desc = ql_get_curr_sbuf(rx_ring); + pci_unmap_single(qdev->pdev, + pci_unmap_addr(sbq_desc, mapaddr), + pci_unmap_len(sbq_desc, maplen), + PCI_DMA_FROMDEVICE); + if (!(ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS)) { + /* + * This is an non TCP/UDP IP frame, so + * the headers aren't split into a small + * buffer. We have to use the small buffer + * that contains our sg list as our skb to + * send upstairs. Copy the sg list here to + * a local buffer and use it to find the + * pages to chain. + */ + QPRINTK(qdev, RX_STATUS, DEBUG, + "%d bytes of headers & data in chain of large.\n", length); + skb = sbq_desc->p.skb; + bq = &bq_array[0]; + memcpy(bq, skb->data, sizeof(bq_array)); + sbq_desc->p.skb = NULL; + skb_reserve(skb, NET_IP_ALIGN); + } else { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Headers in small, %d bytes of data in chain of large.\n", length); + bq = (struct bq_element *)sbq_desc->p.skb->data; + } + while (length > 0) { + lbq_desc = ql_get_curr_lbuf(rx_ring); + if ((bq->addr_lo & ~BQ_MASK) != lbq_desc->bq->addr_lo) { + QPRINTK(qdev, RX_STATUS, ERR, + "Panic!!! bad large buffer address, expected 0x%.08x, got 0x%.08x.\n", + lbq_desc->bq->addr_lo, bq->addr_lo); + return NULL; + } + pci_unmap_page(qdev->pdev, + pci_unmap_addr(lbq_desc, + mapaddr), + pci_unmap_len(lbq_desc, + maplen), + PCI_DMA_FROMDEVICE); + size = (length < PAGE_SIZE) ? length : PAGE_SIZE; + offset = 0; + + QPRINTK(qdev, RX_STATUS, DEBUG, + "Adding page %d to skb for %d bytes.\n", + i, size); + skb_fill_page_desc(skb, i, lbq_desc->p.lbq_page, + offset, size); + skb->len += size; + skb->data_len += size; + skb->truesize += size; + length -= size; + lbq_desc->p.lbq_page = NULL; + bq++; + i++; + } + __pskb_pull_tail(skb, (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? + VLAN_ETH_HLEN : ETH_HLEN); + } + return skb; +} + +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_intr(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp) +{ + struct net_device *ndev = qdev->ndev; + struct sk_buff *skb = NULL; + + QL_DUMP_IB_MAC_RSP(ib_mac_rsp); + + skb = ql_build_rx_skb(qdev, rx_ring, ib_mac_rsp); + if (unlikely(!skb)) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "No skb available, drop packet.\n"); + return; + } + + prefetch(skb->data); + skb->dev = ndev; + if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { + QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + } + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { + QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); + } + if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { + QPRINTK(qdev, RX_STATUS, ERR, + "Bad checksum for this %s packet.\n", + ((ib_mac_rsp-> + flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); + skb->ip_summed = CHECKSUM_NONE; + } else if (qdev->rx_csum && + ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || + ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { + QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + qdev->stats.rx_packets++; + qdev->stats.rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); + if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Passing a VLAN packet upstream.\n"); + vlan_hwaccel_rx(skb, qdev->vlgrp, + le16_to_cpu(ib_mac_rsp->vlan_id)); + } else { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Passing a normal packet upstream.\n"); + netif_rx(skb); + } + ndev->last_rx = jiffies; +} + +/* Process an outbound completion from an rx ring. */ +static void ql_process_mac_tx_intr(struct ql_adapter *qdev, + struct ob_mac_iocb_rsp *mac_rsp) +{ + struct tx_ring *tx_ring; + struct tx_ring_desc *tx_ring_desc; + + QL_DUMP_OB_MAC_RSP(mac_rsp); + tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; + tx_ring_desc = &tx_ring->q[mac_rsp->tid]; + ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); + qdev->stats.tx_bytes += tx_ring_desc->map_cnt; + qdev->stats.tx_packets++; + dev_kfree_skb(tx_ring_desc->skb); + tx_ring_desc->skb = NULL; + + if (unlikely(mac_rsp->flags1 & (OB_MAC_IOCB_RSP_E | + OB_MAC_IOCB_RSP_S | + OB_MAC_IOCB_RSP_L | + OB_MAC_IOCB_RSP_P | OB_MAC_IOCB_RSP_B))) { + if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_E) { + QPRINTK(qdev, TX_DONE, WARNING, + "Total descriptor length did not match transfer length.\n"); + } + if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_S) { + QPRINTK(qdev, TX_DONE, WARNING, + "Frame too short to be legal, not sent.\n"); + } + if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_L) { + QPRINTK(qdev, TX_DONE, WARNING, + "Frame too long, but sent anyway.\n"); + } + if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_B) { + QPRINTK(qdev, TX_DONE, WARNING, + "PCI backplane error. Frame not sent.\n"); + } + } + atomic_inc(&tx_ring->tx_count); +} + +/* Fire up a handler to reset the MPI processor. */ +void ql_queue_fw_error(struct ql_adapter *qdev) +{ + netif_stop_queue(qdev->ndev); + netif_carrier_off(qdev->ndev); + queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); +} + +void ql_queue_asic_error(struct ql_adapter *qdev) +{ + netif_stop_queue(qdev->ndev); + netif_carrier_off(qdev->ndev); + ql_disable_interrupts(qdev); + queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0); +} + +static void ql_process_chip_ae_intr(struct ql_adapter *qdev, + struct ib_ae_iocb_rsp *ib_ae_rsp) +{ + switch (ib_ae_rsp->event) { + case MGMT_ERR_EVENT: + QPRINTK(qdev, RX_ERR, ERR, + "Management Processor Fatal Error.\n"); + ql_queue_fw_error(qdev); + return; + + case CAM_LOOKUP_ERR_EVENT: + QPRINTK(qdev, LINK, ERR, + "Multiple CAM hits lookup occurred.\n"); + QPRINTK(qdev, DRV, ERR, "This event shouldn't occur.\n"); + ql_queue_asic_error(qdev); + return; + + case SOFT_ECC_ERROR_EVENT: + QPRINTK(qdev, RX_ERR, ERR, "Soft ECC error detected.\n"); + ql_queue_asic_error(qdev); + break; + + case PCI_ERR_ANON_BUF_RD: + QPRINTK(qdev, RX_ERR, ERR, + "PCI error occurred when reading anonymous buffers from rx_ring %d.\n", + ib_ae_rsp->q_id); + ql_queue_asic_error(qdev); + break; + + default: + QPRINTK(qdev, DRV, ERR, "Unexpected event %d.\n", + ib_ae_rsp->event); + ql_queue_asic_error(qdev); + break; + } +} + +static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) +{ + struct ql_adapter *qdev = rx_ring->qdev; + u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); + struct ob_mac_iocb_rsp *net_rsp = NULL; + int count = 0; + + /* While there are entries in the completion queue. */ + while (prod != rx_ring->cnsmr_idx) { + + QPRINTK(qdev, RX_STATUS, DEBUG, + "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id, + prod, rx_ring->cnsmr_idx); + + net_rsp = (struct ob_mac_iocb_rsp *)rx_ring->curr_entry; + rmb(); + switch (net_rsp->opcode) { + + case OPCODE_OB_MAC_TSO_IOCB: + case OPCODE_OB_MAC_IOCB: + ql_process_mac_tx_intr(qdev, net_rsp); + break; + default: + QPRINTK(qdev, RX_STATUS, DEBUG, + "Hit default case, not handled! dropping the packet, opcode = %x.\n", + net_rsp->opcode); + } + count++; + ql_update_cq(rx_ring); + prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); + } + ql_write_cq_idx(rx_ring); + if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { + struct tx_ring *tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; + if (atomic_read(&tx_ring->queue_stopped) && + (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) + /* + * The queue got stopped because the tx_ring was full. + * Wake it up, because it's now at least 25% empty. + */ + netif_wake_queue(qdev->ndev); + } + + return count; +} + +static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) +{ + struct ql_adapter *qdev = rx_ring->qdev; + u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); + struct ql_net_rsp_iocb *net_rsp; + int count = 0; + + /* While there are entries in the completion queue. */ + while (prod != rx_ring->cnsmr_idx) { + + QPRINTK(qdev, RX_STATUS, DEBUG, + "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id, + prod, rx_ring->cnsmr_idx); + + net_rsp = rx_ring->curr_entry; + rmb(); + switch (net_rsp->opcode) { + case OPCODE_IB_MAC_IOCB: + ql_process_mac_rx_intr(qdev, rx_ring, + (struct ib_mac_iocb_rsp *) + net_rsp); + break; + + case OPCODE_IB_AE_IOCB: + ql_process_chip_ae_intr(qdev, (struct ib_ae_iocb_rsp *) + net_rsp); + break; + default: + { + QPRINTK(qdev, RX_STATUS, DEBUG, + "Hit default case, not handled! dropping the packet, opcode = %x.\n", + net_rsp->opcode); + } + } + count++; + ql_update_cq(rx_ring); + prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); + if (count == budget) + break; + } + ql_update_buffer_queues(qdev, rx_ring); + ql_write_cq_idx(rx_ring); + return count; +} + +static int ql_napi_poll_msix(struct napi_struct *napi, int budget) +{ + struct rx_ring *rx_ring = container_of(napi, struct rx_ring, napi); + struct ql_adapter *qdev = rx_ring->qdev; + int work_done = ql_clean_inbound_rx_ring(rx_ring, budget); + + QPRINTK(qdev, RX_STATUS, DEBUG, "Enter, NAPI POLL cq_id = %d.\n", + rx_ring->cq_id); + + if (work_done < budget) { + __netif_rx_complete(qdev->ndev, napi); + ql_enable_completion_interrupt(qdev, rx_ring->irq); + } + return work_done; +} + +static void ql_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + + qdev->vlgrp = grp; + if (grp) { + QPRINTK(qdev, IFUP, DEBUG, "Turning on VLAN in NIC_RCV_CFG.\n"); + ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK | + NIC_RCV_CFG_VLAN_MATCH_AND_NON); + } else { + QPRINTK(qdev, IFUP, DEBUG, + "Turning off VLAN in NIC_RCV_CFG.\n"); + ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK); + } +} + +static void ql_vlan_rx_add_vid(struct net_device *ndev, u16 vid) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + u32 enable_bit = MAC_ADDR_E; + + spin_lock(&qdev->hw_lock); + if (ql_set_mac_addr_reg + (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { + QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n"); + } + spin_unlock(&qdev->hw_lock); +} + +static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + u32 enable_bit = 0; + + spin_lock(&qdev->hw_lock); + if (ql_set_mac_addr_reg + (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { + QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n"); + } + spin_unlock(&qdev->hw_lock); + +} + +/* Worker thread to process a given rx_ring that is dedicated + * to outbound completions. + */ +static void ql_tx_clean(struct work_struct *work) +{ + struct rx_ring *rx_ring = + container_of(work, struct rx_ring, rx_work.work); + ql_clean_outbound_rx_ring(rx_ring); + ql_enable_completion_interrupt(rx_ring->qdev, rx_ring->irq); + +} + +/* Worker thread to process a given rx_ring that is dedicated + * to inbound completions. + */ +static void ql_rx_clean(struct work_struct *work) +{ + struct rx_ring *rx_ring = + container_of(work, struct rx_ring, rx_work.work); + ql_clean_inbound_rx_ring(rx_ring, 64); + ql_enable_completion_interrupt(rx_ring->qdev, rx_ring->irq); +} + +/* MSI-X Multiple Vector Interrupt Handler for outbound completions. */ +static irqreturn_t qlge_msix_tx_isr(int irq, void *dev_id) +{ + struct rx_ring *rx_ring = dev_id; + queue_delayed_work_on(rx_ring->cpu, rx_ring->qdev->q_workqueue, + &rx_ring->rx_work, 0); + return IRQ_HANDLED; +} + +/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */ +static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id) +{ + struct rx_ring *rx_ring = dev_id; + struct ql_adapter *qdev = rx_ring->qdev; + netif_rx_schedule(qdev->ndev, &rx_ring->napi); + return IRQ_HANDLED; +} + +/* We check here to see if we're already handling a legacy + * interrupt. If we are, then it must belong to another + * chip with which we're sharing the interrupt line. + */ +int ql_legacy_check(struct ql_adapter *qdev) +{ + int err; + spin_lock(&qdev->legacy_lock); + err = atomic_read(&qdev->intr_context[0].irq_cnt); + spin_unlock(&qdev->legacy_lock); + return err; +} + +/* This handles a fatal error, MPI activity, and the default + * rx_ring in an MSI-X multiple vector environment. + * In MSI/Legacy environment it also process the rest of + * the rx_rings. + */ +static irqreturn_t qlge_isr(int irq, void *dev_id) +{ + struct rx_ring *rx_ring = dev_id; + struct ql_adapter *qdev = rx_ring->qdev; + struct intr_context *intr_context = &qdev->intr_context[0]; + u32 var; + int i; + int work_done = 0; + + if (qdev->legacy_check && qdev->legacy_check(qdev)) { + QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n"); + return IRQ_NONE; /* Not our interrupt */ + } + + var = ql_read32(qdev, STS); + + /* + * Check for fatal error. + */ + if (var & STS_FE) { + ql_queue_asic_error(qdev); + QPRINTK(qdev, INTR, ERR, "Got fatal error, STS = %x.\n", var); + var = ql_read32(qdev, ERR_STS); + QPRINTK(qdev, INTR, ERR, + "Resetting chip. Error Status Register = 0x%x\n", var); + return IRQ_HANDLED; + } + + /* + * Check MPI processor activity. + */ + if (var & STS_PI) { + /* + * We've got an async event or mailbox completion. + * Handle it and clear the source of the interrupt. + */ + QPRINTK(qdev, INTR, ERR, "Got MPI processor interrupt.\n"); + ql_disable_completion_interrupt(qdev, intr_context->intr); + queue_delayed_work_on(smp_processor_id(), qdev->workqueue, + &qdev->mpi_work, 0); + work_done++; + } + + /* + * Check the default queue and wake handler if active. + */ + rx_ring = &qdev->rx_ring[0]; + if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { + QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); + ql_disable_completion_interrupt(qdev, intr_context->intr); + queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, + &rx_ring->rx_work, 0); + work_done++; + } + + if (!test_bit(QL_MSIX_ENABLED, &qdev->flags)) { + /* + * Start the DPC for each active queue. + */ + for (i = 1; i < qdev->rx_ring_count; i++) { + rx_ring = &qdev->rx_ring[i]; + if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != + rx_ring->cnsmr_idx) { + QPRINTK(qdev, INTR, INFO, + "Waking handler for rx_ring[%d].\n", i); + ql_disable_completion_interrupt(qdev, + intr_context-> + intr); + if (i < qdev->rss_ring_first_cq_id) + queue_delayed_work_on(rx_ring->cpu, + qdev->q_workqueue, + &rx_ring->rx_work, + 0); + else + netif_rx_schedule(qdev->ndev, + &rx_ring->napi); + work_done++; + } + } + } + return work_done ? IRQ_HANDLED : IRQ_NONE; +} + +static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr) +{ + + if (skb_is_gso(skb)) { + int err; + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) + return err; + } + + mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB; + mac_iocb_ptr->flags3 |= OB_MAC_TSO_IOCB_IC; + mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len); + mac_iocb_ptr->total_hdrs_len = + cpu_to_le16(skb_transport_offset(skb) + tcp_hdrlen(skb)); + mac_iocb_ptr->net_trans_offset = + cpu_to_le16(skb_network_offset(skb) | + skb_transport_offset(skb) + << OB_MAC_TRANSPORT_HDR_SHIFT); + mac_iocb_ptr->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_LSO; + if (likely(skb->protocol == htons(ETH_P_IP))) { + struct iphdr *iph = ip_hdr(skb); + iph->check = 0; + mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, + 0); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP6; + tcp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0); + } + return 1; + } + return 0; +} + +static void ql_hw_csum_setup(struct sk_buff *skb, + struct ob_mac_tso_iocb_req *mac_iocb_ptr) +{ + int len; + struct iphdr *iph = ip_hdr(skb); + u16 *check; + mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB; + mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len); + mac_iocb_ptr->net_trans_offset = + cpu_to_le16(skb_network_offset(skb) | + skb_transport_offset(skb) << OB_MAC_TRANSPORT_HDR_SHIFT); + + mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4; + len = (ntohs(iph->tot_len) - (iph->ihl << 2)); + if (likely(iph->protocol == IPPROTO_TCP)) { + check = &(tcp_hdr(skb)->check); + mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_TC; + mac_iocb_ptr->total_hdrs_len = + cpu_to_le16(skb_transport_offset(skb) + + (tcp_hdr(skb)->doff << 2)); + } else { + check = &(udp_hdr(skb)->check); + mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_UC; + mac_iocb_ptr->total_hdrs_len = + cpu_to_le16(skb_transport_offset(skb) + + sizeof(struct udphdr)); + } + *check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, len, iph->protocol, 0); +} + +static int qlge_send(struct sk_buff *skb, struct net_device *ndev) +{ + struct tx_ring_desc *tx_ring_desc; + struct ob_mac_iocb_req *mac_iocb_ptr; + struct ql_adapter *qdev = netdev_priv(ndev); + int tso; + struct tx_ring *tx_ring; + u32 tx_ring_idx = (u32) QL_TXQ_IDX(qdev, skb); + + tx_ring = &qdev->tx_ring[tx_ring_idx]; + + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { + QPRINTK(qdev, TX_QUEUED, INFO, + "%s: shutting down tx queue %d du to lack of resources.\n", + __func__, tx_ring_idx); + netif_stop_queue(ndev); + atomic_inc(&tx_ring->queue_stopped); + return NETDEV_TX_BUSY; + } + tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; + mac_iocb_ptr = tx_ring_desc->queue_entry; + memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr)); + if (ql_map_send(qdev, mac_iocb_ptr, skb, tx_ring_desc) != NETDEV_TX_OK) { + QPRINTK(qdev, TX_QUEUED, ERR, "Could not map the segments.\n"); + return NETDEV_TX_BUSY; + } + + mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; + mac_iocb_ptr->tid = tx_ring_desc->index; + /* We use the upper 32-bits to store the tx queue for this IO. + * When we get the completion we can use it to establish the context. + */ + mac_iocb_ptr->txq_idx = tx_ring_idx; + tx_ring_desc->skb = skb; + + mac_iocb_ptr->frame_len = cpu_to_le16((u16) skb->len); + + if (qdev->vlgrp && vlan_tx_tag_present(skb)) { + QPRINTK(qdev, TX_QUEUED, DEBUG, "Adding a vlan tag %d.\n", + vlan_tx_tag_get(skb)); + mac_iocb_ptr->flags3 |= OB_MAC_IOCB_V; + mac_iocb_ptr->vlan_tci = cpu_to_le16(vlan_tx_tag_get(skb)); + } + tso = ql_tso(skb, (struct ob_mac_tso_iocb_req *)mac_iocb_ptr); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } else if (unlikely(!tso) && (skb->ip_summed == CHECKSUM_PARTIAL)) { + ql_hw_csum_setup(skb, + (struct ob_mac_tso_iocb_req *)mac_iocb_ptr); + } + QL_DUMP_OB_MAC_IOCB(mac_iocb_ptr); + tx_ring->prod_idx++; + if (tx_ring->prod_idx == tx_ring->wq_len) + tx_ring->prod_idx = 0; + wmb(); + + ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg); + ndev->trans_start = jiffies; + QPRINTK(qdev, TX_QUEUED, DEBUG, "tx queued, slot %d, len %d\n", + tx_ring->prod_idx, skb->len); + + atomic_dec(&tx_ring->tx_count); + return NETDEV_TX_OK; +} + +static void ql_free_shadow_space(struct ql_adapter *qdev) +{ + if (qdev->rx_ring_shadow_reg_area) { + pci_free_consistent(qdev->pdev, + PAGE_SIZE, + qdev->rx_ring_shadow_reg_area, + qdev->rx_ring_shadow_reg_dma); + qdev->rx_ring_shadow_reg_area = NULL; + } + if (qdev->tx_ring_shadow_reg_area) { + pci_free_consistent(qdev->pdev, + PAGE_SIZE, + qdev->tx_ring_shadow_reg_area, + qdev->tx_ring_shadow_reg_dma); + qdev->tx_ring_shadow_reg_area = NULL; + } +} + +static int ql_alloc_shadow_space(struct ql_adapter *qdev) +{ + qdev->rx_ring_shadow_reg_area = + pci_alloc_consistent(qdev->pdev, + PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma); + if (qdev->rx_ring_shadow_reg_area == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Allocation of RX shadow space failed.\n"); + return -ENOMEM; + } + qdev->tx_ring_shadow_reg_area = + pci_alloc_consistent(qdev->pdev, PAGE_SIZE, + &qdev->tx_ring_shadow_reg_dma); + if (qdev->tx_ring_shadow_reg_area == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Allocation of TX shadow space failed.\n"); + goto err_wqp_sh_area; + } + return 0; + +err_wqp_sh_area: + pci_free_consistent(qdev->pdev, + PAGE_SIZE, + qdev->rx_ring_shadow_reg_area, + qdev->rx_ring_shadow_reg_dma); + return -ENOMEM; +} + +static void ql_init_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) +{ + struct tx_ring_desc *tx_ring_desc; + int i; + struct ob_mac_iocb_req *mac_iocb_ptr; + + mac_iocb_ptr = tx_ring->wq_base; + tx_ring_desc = tx_ring->q; + for (i = 0; i < tx_ring->wq_len; i++) { + tx_ring_desc->index = i; + tx_ring_desc->skb = NULL; + tx_ring_desc->queue_entry = mac_iocb_ptr; + mac_iocb_ptr++; + tx_ring_desc++; + } + atomic_set(&tx_ring->tx_count, tx_ring->wq_len); + atomic_set(&tx_ring->queue_stopped, 0); +} + +static void ql_free_tx_resources(struct ql_adapter *qdev, + struct tx_ring *tx_ring) +{ + if (tx_ring->wq_base) { + pci_free_consistent(qdev->pdev, tx_ring->wq_size, + tx_ring->wq_base, tx_ring->wq_base_dma); + tx_ring->wq_base = NULL; + } + kfree(tx_ring->q); + tx_ring->q = NULL; +} + +static int ql_alloc_tx_resources(struct ql_adapter *qdev, + struct tx_ring *tx_ring) +{ + tx_ring->wq_base = + pci_alloc_consistent(qdev->pdev, tx_ring->wq_size, + &tx_ring->wq_base_dma); + + if ((tx_ring->wq_base == NULL) + || tx_ring->wq_base_dma & (tx_ring->wq_size - 1)) { + QPRINTK(qdev, IFUP, ERR, "tx_ring alloc failed.\n"); + return -ENOMEM; + } + tx_ring->q = + kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL); + if (tx_ring->q == NULL) + goto err; + + return 0; +err: + pci_free_consistent(qdev->pdev, tx_ring->wq_size, + tx_ring->wq_base, tx_ring->wq_base_dma); + return -ENOMEM; +} + +void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring) +{ + int i; + struct bq_desc *lbq_desc; + + for (i = 0; i < rx_ring->lbq_len; i++) { + lbq_desc = &rx_ring->lbq[i]; + if (lbq_desc->p.lbq_page) { + pci_unmap_page(qdev->pdev, + pci_unmap_addr(lbq_desc, mapaddr), + pci_unmap_len(lbq_desc, maplen), + PCI_DMA_FROMDEVICE); + + put_page(lbq_desc->p.lbq_page); + lbq_desc->p.lbq_page = NULL; + } + lbq_desc->bq->addr_lo = 0; + lbq_desc->bq->addr_hi = 0; + } +} + +/* + * Allocate and map a page for each element of the lbq. + */ +static int ql_alloc_lbq_buffers(struct ql_adapter *qdev, + struct rx_ring *rx_ring) +{ + int i; + struct bq_desc *lbq_desc; + u64 map; + struct bq_element *bq = rx_ring->lbq_base; + + for (i = 0; i < rx_ring->lbq_len; i++) { + lbq_desc = &rx_ring->lbq[i]; + memset(lbq_desc, 0, sizeof(lbq_desc)); + lbq_desc->bq = bq; + lbq_desc->index = i; + lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC); + if (unlikely(!lbq_desc->p.lbq_page)) { + QPRINTK(qdev, IFUP, ERR, "failed alloc_page().\n"); + goto mem_error; + } else { + map = pci_map_page(qdev->pdev, + lbq_desc->p.lbq_page, + 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(qdev->pdev, map)) { + QPRINTK(qdev, IFUP, ERR, + "PCI mapping failed.\n"); + goto mem_error; + } + pci_unmap_addr_set(lbq_desc, mapaddr, map); + pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); + bq->addr_lo = cpu_to_le32(map); + bq->addr_hi = cpu_to_le32(map >> 32); + } + bq++; + } + return 0; +mem_error: + ql_free_lbq_buffers(qdev, rx_ring); + return -ENOMEM; +} + +void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring) +{ + int i; + struct bq_desc *sbq_desc; + + for (i = 0; i < rx_ring->sbq_len; i++) { + sbq_desc = &rx_ring->sbq[i]; + if (sbq_desc == NULL) { + QPRINTK(qdev, IFUP, ERR, "sbq_desc %d is NULL.\n", i); + return; + } + if (sbq_desc->p.skb) { + pci_unmap_single(qdev->pdev, + pci_unmap_addr(sbq_desc, mapaddr), + pci_unmap_len(sbq_desc, maplen), + PCI_DMA_FROMDEVICE); + dev_kfree_skb(sbq_desc->p.skb); + sbq_desc->p.skb = NULL; + } + if (sbq_desc->bq == NULL) { + QPRINTK(qdev, IFUP, ERR, "sbq_desc->bq %d is NULL.\n", + i); + return; + } + sbq_desc->bq->addr_lo = 0; + sbq_desc->bq->addr_hi = 0; + } +} + +/* Allocate and map an skb for each element of the sbq. */ +static int ql_alloc_sbq_buffers(struct ql_adapter *qdev, + struct rx_ring *rx_ring) +{ + int i; + struct bq_desc *sbq_desc; + struct sk_buff *skb; + u64 map; + struct bq_element *bq = rx_ring->sbq_base; + + for (i = 0; i < rx_ring->sbq_len; i++) { + sbq_desc = &rx_ring->sbq[i]; + memset(sbq_desc, 0, sizeof(sbq_desc)); + sbq_desc->index = i; + sbq_desc->bq = bq; + skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size); + if (unlikely(!skb)) { + /* Better luck next round */ + QPRINTK(qdev, IFUP, ERR, + "small buff alloc failed for %d bytes at index %d.\n", + rx_ring->sbq_buf_size, i); + goto mem_err; + } + skb_reserve(skb, QLGE_SB_PAD); + sbq_desc->p.skb = skb; + /* + * Map only half the buffer. Because the + * other half may get some data copied to it + * when the completion arrives. + */ + map = pci_map_single(qdev->pdev, + skb->data, + rx_ring->sbq_buf_size / 2, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(qdev->pdev, map)) { + QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n"); + goto mem_err; + } + pci_unmap_addr_set(sbq_desc, mapaddr, map); + pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2); + bq->addr_lo = /*sbq_desc->addr_lo = */ + cpu_to_le32(map); + bq->addr_hi = /*sbq_desc->addr_hi = */ + cpu_to_le32(map >> 32); + bq++; + } + return 0; +mem_err: + ql_free_sbq_buffers(qdev, rx_ring); + return -ENOMEM; +} + +static void ql_free_rx_resources(struct ql_adapter *qdev, + struct rx_ring *rx_ring) +{ + if (rx_ring->sbq_len) + ql_free_sbq_buffers(qdev, rx_ring); + if (rx_ring->lbq_len) + ql_free_lbq_buffers(qdev, rx_ring); + + /* Free the small buffer queue. */ + if (rx_ring->sbq_base) { + pci_free_consistent(qdev->pdev, + rx_ring->sbq_size, + rx_ring->sbq_base, rx_ring->sbq_base_dma); + rx_ring->sbq_base = NULL; + } + + /* Free the small buffer queue control blocks. */ + kfree(rx_ring->sbq); + rx_ring->sbq = NULL; + + /* Free the large buffer queue. */ + if (rx_ring->lbq_base) { + pci_free_consistent(qdev->pdev, + rx_ring->lbq_size, + rx_ring->lbq_base, rx_ring->lbq_base_dma); + rx_ring->lbq_base = NULL; + } + + /* Free the large buffer queue control blocks. */ + kfree(rx_ring->lbq); + rx_ring->lbq = NULL; + + /* Free the rx queue. */ + if (rx_ring->cq_base) { + pci_free_consistent(qdev->pdev, + rx_ring->cq_size, + rx_ring->cq_base, rx_ring->cq_base_dma); + rx_ring->cq_base = NULL; + } +} + +/* Allocate queues and buffers for this completions queue based + * on the values in the parameter structure. */ +static int ql_alloc_rx_resources(struct ql_adapter *qdev, + struct rx_ring *rx_ring) +{ + + /* + * Allocate the completion queue for this rx_ring. + */ + rx_ring->cq_base = + pci_alloc_consistent(qdev->pdev, rx_ring->cq_size, + &rx_ring->cq_base_dma); + + if (rx_ring->cq_base == NULL) { + QPRINTK(qdev, IFUP, ERR, "rx_ring alloc failed.\n"); + return -ENOMEM; + } + + if (rx_ring->sbq_len) { + /* + * Allocate small buffer queue. + */ + rx_ring->sbq_base = + pci_alloc_consistent(qdev->pdev, rx_ring->sbq_size, + &rx_ring->sbq_base_dma); + + if (rx_ring->sbq_base == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Small buffer queue allocation failed.\n"); + goto err_mem; + } + + /* + * Allocate small buffer queue control blocks. + */ + rx_ring->sbq = + kmalloc(rx_ring->sbq_len * sizeof(struct bq_desc), + GFP_KERNEL); + if (rx_ring->sbq == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Small buffer queue control block allocation failed.\n"); + goto err_mem; + } + + if (ql_alloc_sbq_buffers(qdev, rx_ring)) { + QPRINTK(qdev, IFUP, ERR, + "Small buffer allocation failed.\n"); + goto err_mem; + } + } + + if (rx_ring->lbq_len) { + /* + * Allocate large buffer queue. + */ + rx_ring->lbq_base = + pci_alloc_consistent(qdev->pdev, rx_ring->lbq_size, + &rx_ring->lbq_base_dma); + + if (rx_ring->lbq_base == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Large buffer queue allocation failed.\n"); + goto err_mem; + } + /* + * Allocate large buffer queue control blocks. + */ + rx_ring->lbq = + kmalloc(rx_ring->lbq_len * sizeof(struct bq_desc), + GFP_KERNEL); + if (rx_ring->lbq == NULL) { + QPRINTK(qdev, IFUP, ERR, + "Large buffer queue control block allocation failed.\n"); + goto err_mem; + } + + /* + * Allocate the buffers. + */ + if (ql_alloc_lbq_buffers(qdev, rx_ring)) { + QPRINTK(qdev, IFUP, ERR, + "Large buffer allocation failed.\n"); + goto err_mem; + } + } + + return 0; + +err_mem: + ql_free_rx_resources(qdev, rx_ring); + return -ENOMEM; +} + +static void ql_tx_ring_clean(struct ql_adapter *qdev) +{ + struct tx_ring *tx_ring; + struct tx_ring_desc *tx_ring_desc; + int i, j; + + /* + * Loop through all queues and free + * any resources. + */ + for (j = 0; j < qdev->tx_ring_count; j++) { + tx_ring = &qdev->tx_ring[j]; + for (i = 0; i < tx_ring->wq_len; i++) { + tx_ring_desc = &tx_ring->q[i]; + if (tx_ring_desc && tx_ring_desc->skb) { + QPRINTK(qdev, IFDOWN, ERR, + "Freeing lost SKB %p, from queue %d, index %d.\n", + tx_ring_desc->skb, j, + tx_ring_desc->index); + ql_unmap_send(qdev, tx_ring_desc, + tx_ring_desc->map_cnt); + dev_kfree_skb(tx_ring_desc->skb); + tx_ring_desc->skb = NULL; + } + } + } +} + +static void ql_free_ring_cb(struct ql_adapter *qdev) +{ + kfree(qdev->ring_mem); +} + +static int ql_alloc_ring_cb(struct ql_adapter *qdev) +{ + /* Allocate space for tx/rx ring control blocks. */ + qdev->ring_mem_size = + (qdev->tx_ring_count * sizeof(struct tx_ring)) + + (qdev->rx_ring_count * sizeof(struct rx_ring)); + qdev->ring_mem = kmalloc(qdev->ring_mem_size, GFP_KERNEL); + if (qdev->ring_mem == NULL) { + return -ENOMEM; + } else { + qdev->rx_ring = qdev->ring_mem; + qdev->tx_ring = qdev->ring_mem + + (qdev->rx_ring_count * sizeof(struct rx_ring)); + } + return 0; +} + +static void ql_free_mem_resources(struct ql_adapter *qdev) +{ + int i; + + for (i = 0; i < qdev->tx_ring_count; i++) + ql_free_tx_resources(qdev, &qdev->tx_ring[i]); + for (i = 0; i < qdev->rx_ring_count; i++) + ql_free_rx_resources(qdev, &qdev->rx_ring[i]); + ql_free_shadow_space(qdev); +} + +static int ql_alloc_mem_resources(struct ql_adapter *qdev) +{ + int i; + + /* Allocate space for our shadow registers and such. */ + if (ql_alloc_shadow_space(qdev)) + return -ENOMEM; + + for (i = 0; i < qdev->rx_ring_count; i++) { + if (ql_alloc_rx_resources(qdev, &qdev->rx_ring[i]) != 0) { + QPRINTK(qdev, IFUP, ERR, + "RX resource allocation failed.\n"); + goto err_mem; + } + } + /* Allocate tx queue resources */ + for (i = 0; i < qdev->tx_ring_count; i++) { + if (ql_alloc_tx_resources(qdev, &qdev->tx_ring[i]) != 0) { + QPRINTK(qdev, IFUP, ERR, + "TX resource allocation failed.\n"); + goto err_mem; + } + } + return 0; + +err_mem: + ql_free_mem_resources(qdev); + return -ENOMEM; +} + +/* Set up the rx ring control block and pass it to the chip. + * The control block is defined as + * "Completion Queue Initialization Control Block", or cqicb. + */ +static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) +{ + struct cqicb *cqicb = &rx_ring->cqicb; + void *shadow_reg = qdev->rx_ring_shadow_reg_area + + (rx_ring->cq_id * sizeof(u64) * 4); + u64 shadow_reg_dma = qdev->rx_ring_shadow_reg_dma + + (rx_ring->cq_id * sizeof(u64) * 4); + void __iomem *doorbell_area = + qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id)); + int err = 0; + u16 bq_len; + + /* Set up the shadow registers for this ring. */ + rx_ring->prod_idx_sh_reg = shadow_reg; + rx_ring->prod_idx_sh_reg_dma = shadow_reg_dma; + shadow_reg += sizeof(u64); + shadow_reg_dma += sizeof(u64); + rx_ring->lbq_base_indirect = shadow_reg; + rx_ring->lbq_base_indirect_dma = shadow_reg_dma; + shadow_reg += sizeof(u64); + shadow_reg_dma += sizeof(u64); + rx_ring->sbq_base_indirect = shadow_reg; + rx_ring->sbq_base_indirect_dma = shadow_reg_dma; + + /* PCI doorbell mem area + 0x00 for consumer index register */ + rx_ring->cnsmr_idx_db_reg = (u32 *) doorbell_area; + rx_ring->cnsmr_idx = 0; + rx_ring->curr_entry = rx_ring->cq_base; + + /* PCI doorbell mem area + 0x04 for valid register */ + rx_ring->valid_db_reg = doorbell_area + 0x04; + + /* PCI doorbell mem area + 0x18 for large buffer consumer */ + rx_ring->lbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x18); + + /* PCI doorbell mem area + 0x1c */ + rx_ring->sbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x1c); + + memset((void *)cqicb, 0, sizeof(struct cqicb)); + cqicb->msix_vect = rx_ring->irq; + + cqicb->len = cpu_to_le16(rx_ring->cq_len | LEN_V | LEN_CPP_CONT); + + cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma); + cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32); + + cqicb->prod_idx_addr_lo = cpu_to_le32(rx_ring->prod_idx_sh_reg_dma); + cqicb->prod_idx_addr_hi = + cpu_to_le32((u64) rx_ring->prod_idx_sh_reg_dma >> 32); + + /* + * Set up the control block load flags. + */ + cqicb->flags = FLAGS_LC | /* Load queue base address */ + FLAGS_LV | /* Load MSI-X vector */ + FLAGS_LI; /* Load irq delay values */ + if (rx_ring->lbq_len) { + cqicb->flags |= FLAGS_LL; /* Load lbq values */ + *((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma; + cqicb->lbq_addr_lo = + cpu_to_le32(rx_ring->lbq_base_indirect_dma); + cqicb->lbq_addr_hi = + cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32); + cqicb->lbq_buf_size = cpu_to_le32(rx_ring->lbq_buf_size); + bq_len = (u16) rx_ring->lbq_len; + cqicb->lbq_len = cpu_to_le16(bq_len); + rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16; + rx_ring->lbq_curr_idx = 0; + rx_ring->lbq_clean_idx = rx_ring->lbq_prod_idx; + rx_ring->lbq_free_cnt = 16; + } + if (rx_ring->sbq_len) { + cqicb->flags |= FLAGS_LS; /* Load sbq values */ + *((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma; + cqicb->sbq_addr_lo = + cpu_to_le32(rx_ring->sbq_base_indirect_dma); + cqicb->sbq_addr_hi = + cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32); + cqicb->sbq_buf_size = + cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); + bq_len = (u16) rx_ring->sbq_len; + cqicb->sbq_len = cpu_to_le16(bq_len); + rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16; + rx_ring->sbq_curr_idx = 0; + rx_ring->sbq_clean_idx = rx_ring->sbq_prod_idx; + rx_ring->sbq_free_cnt = 16; + } + switch (rx_ring->type) { + case TX_Q: + /* If there's only one interrupt, then we use + * worker threads to process the outbound + * completion handling rx_rings. We do this so + * they can be run on multiple CPUs. There is + * room to play with this more where we would only + * run in a worker if there are more than x number + * of outbound completions on the queue and more + * than one queue active. Some threshold that + * would indicate a benefit in spite of the cost + * of a context switch. + * If there's more than one interrupt, then the + * outbound completions are processed in the ISR. + */ + if (!test_bit(QL_MSIX_ENABLED, &qdev->flags)) + INIT_DELAYED_WORK(&rx_ring->rx_work, ql_tx_clean); + else { + /* With all debug warnings on we see a WARN_ON message + * when we free the skb in the interrupt context. + */ + INIT_DELAYED_WORK(&rx_ring->rx_work, ql_tx_clean); + } + cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs); + cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames); + break; + case DEFAULT_Q: + INIT_DELAYED_WORK(&rx_ring->rx_work, ql_rx_clean); + cqicb->irq_delay = 0; + cqicb->pkt_delay = 0; + break; + case RX_Q: + /* Inbound completion handling rx_rings run in + * separate NAPI contexts. + */ + netif_napi_add(qdev->ndev, &rx_ring->napi, ql_napi_poll_msix, + 64); + cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs); + cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames); + break; + default: + QPRINTK(qdev, IFUP, DEBUG, "Invalid rx_ring->type = %d.\n", + rx_ring->type); + } + QPRINTK(qdev, IFUP, INFO, "Initializing rx work queue.\n"); + err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb), + CFG_LCQ, rx_ring->cq_id); + if (err) { + QPRINTK(qdev, IFUP, ERR, "Failed to load CQICB.\n"); + return err; + } + QPRINTK(qdev, IFUP, INFO, "Successfully loaded CQICB.\n"); + /* + * Advance the producer index for the buffer queues. + */ + wmb(); + if (rx_ring->lbq_len) + ql_write_db_reg(rx_ring->lbq_prod_idx, + rx_ring->lbq_prod_idx_db_reg); + if (rx_ring->sbq_len) + ql_write_db_reg(rx_ring->sbq_prod_idx, + rx_ring->sbq_prod_idx_db_reg); + return err; +} + +static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) +{ + struct wqicb *wqicb = (struct wqicb *)tx_ring; + void __iomem *doorbell_area = + qdev->doorbell_area + (DB_PAGE_SIZE * tx_ring->wq_id); + void *shadow_reg = qdev->tx_ring_shadow_reg_area + + (tx_ring->wq_id * sizeof(u64)); + u64 shadow_reg_dma = qdev->tx_ring_shadow_reg_dma + + (tx_ring->wq_id * sizeof(u64)); + int err = 0; + + /* + * Assign doorbell registers for this tx_ring. + */ + /* TX PCI doorbell mem area for tx producer index */ + tx_ring->prod_idx_db_reg = (u32 *) doorbell_area; + tx_ring->prod_idx = 0; + /* TX PCI doorbell mem area + 0x04 */ + tx_ring->valid_db_reg = doorbell_area + 0x04; + + /* + * Assign shadow registers for this tx_ring. + */ + tx_ring->cnsmr_idx_sh_reg = shadow_reg; + tx_ring->cnsmr_idx_sh_reg_dma = shadow_reg_dma; + + wqicb->len = cpu_to_le16(tx_ring->wq_len | Q_LEN_V | Q_LEN_CPP_CONT); + wqicb->flags = cpu_to_le16(Q_FLAGS_LC | + Q_FLAGS_LB | Q_FLAGS_LI | Q_FLAGS_LO); + wqicb->cq_id_rss = cpu_to_le16(tx_ring->cq_id); + wqicb->rid = 0; + wqicb->addr_lo = cpu_to_le32(tx_ring->wq_base_dma); + wqicb->addr_hi = cpu_to_le32((u64) tx_ring->wq_base_dma >> 32); + + wqicb->cnsmr_idx_addr_lo = cpu_to_le32(tx_ring->cnsmr_idx_sh_reg_dma); + wqicb->cnsmr_idx_addr_hi = + cpu_to_le32((u64) tx_ring->cnsmr_idx_sh_reg_dma >> 32); + + ql_init_tx_ring(qdev, tx_ring); + + err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ, + (u16) tx_ring->wq_id); + if (err) { + QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); + return err; + } + QPRINTK(qdev, IFUP, INFO, "Successfully loaded WQICB.\n"); + return err; +} + +static void ql_disable_msix(struct ql_adapter *qdev) +{ + if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { + pci_disable_msix(qdev->pdev); + clear_bit(QL_MSIX_ENABLED, &qdev->flags); + kfree(qdev->msi_x_entry); + qdev->msi_x_entry = NULL; + } else if (test_bit(QL_MSI_ENABLED, &qdev->flags)) { + pci_disable_msi(qdev->pdev); + clear_bit(QL_MSI_ENABLED, &qdev->flags); + } +} + +static void ql_enable_msix(struct ql_adapter *qdev) +{ + int i; + + qdev->intr_count = 1; + /* Get the MSIX vectors. */ + if (irq_type == MSIX_IRQ) { + /* Try to alloc space for the msix struct, + * if it fails then go to MSI/legacy. + */ + qdev->msi_x_entry = kcalloc(qdev->rx_ring_count, + sizeof(struct msix_entry), + GFP_KERNEL); + if (!qdev->msi_x_entry) { + irq_type = MSI_IRQ; + goto msi; + } + + for (i = 0; i < qdev->rx_ring_count; i++) + qdev->msi_x_entry[i].entry = i; + + if (!pci_enable_msix + (qdev->pdev, qdev->msi_x_entry, qdev->rx_ring_count)) { + set_bit(QL_MSIX_ENABLED, &qdev->flags); + qdev->intr_count = qdev->rx_ring_count; + QPRINTK(qdev, IFUP, INFO, + "MSI-X Enabled, got %d vectors.\n", + qdev->intr_count); + return; + } else { + kfree(qdev->msi_x_entry); + qdev->msi_x_entry = NULL; + QPRINTK(qdev, IFUP, WARNING, + "MSI-X Enable failed, trying MSI.\n"); + irq_type = MSI_IRQ; + } + } +msi: + if (irq_type == MSI_IRQ) { + if (!pci_enable_msi(qdev->pdev)) { + set_bit(QL_MSI_ENABLED, &qdev->flags); + QPRINTK(qdev, IFUP, INFO, + "Running with MSI interrupts.\n"); + return; + } + } + irq_type = LEG_IRQ; + spin_lock_init(&qdev->legacy_lock); + qdev->legacy_check = ql_legacy_check; + QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n"); +} + +/* + * Here we build the intr_context structures based on + * our rx_ring count and intr vector count. + * The intr_context structure is used to hook each vector + * to possibly different handlers. + */ +static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev) +{ + int i = 0; + struct intr_context *intr_context = &qdev->intr_context[0]; + + ql_enable_msix(qdev); + + if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) { + /* Each rx_ring has it's + * own intr_context since we have separate + * vectors for each queue. + * This only true when MSI-X is enabled. + */ + for (i = 0; i < qdev->intr_count; i++, intr_context++) { + qdev->rx_ring[i].irq = i; + intr_context->intr = i; + intr_context->qdev = qdev; + /* + * We set up each vectors enable/disable/read bits so + * there's no bit/mask calculations in the critical path. + */ + intr_context->intr_en_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | + INTR_EN_TYPE_ENABLE | INTR_EN_IHD_MASK | INTR_EN_IHD + | i; + intr_context->intr_dis_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | + INTR_EN_TYPE_DISABLE | INTR_EN_IHD_MASK | + INTR_EN_IHD | i; + intr_context->intr_read_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | + INTR_EN_TYPE_READ | INTR_EN_IHD_MASK | INTR_EN_IHD | + i; + + if (i == 0) { + /* + * Default queue handles bcast/mcast plus + * async events. Needs buffers. + */ + intr_context->handler = qlge_isr; + sprintf(intr_context->name, "%s-default-queue", + qdev->ndev->name); + } else if (i < qdev->rss_ring_first_cq_id) { + /* + * Outbound queue is for outbound completions only. + */ + intr_context->handler = qlge_msix_tx_isr; + sprintf(intr_context->name, "%s-txq-%d", + qdev->ndev->name, i); + } else { + /* + * Inbound queues handle unicast frames only. + */ + intr_context->handler = qlge_msix_rx_isr; + sprintf(intr_context->name, "%s-rxq-%d", + qdev->ndev->name, i); + } + } + } else { + /* + * All rx_rings use the same intr_context since + * there is only one vector. + */ + intr_context->intr = 0; + intr_context->qdev = qdev; + /* + * We set up each vectors enable/disable/read bits so + * there's no bit/mask calculations in the critical path. + */ + intr_context->intr_en_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_ENABLE; + intr_context->intr_dis_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | + INTR_EN_TYPE_DISABLE; + intr_context->intr_read_mask = + INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_READ; + /* + * Single interrupt means one handler for all rings. + */ + intr_context->handler = qlge_isr; + sprintf(intr_context->name, "%s-single_irq", qdev->ndev->name); + for (i = 0; i < qdev->rx_ring_count; i++) + qdev->rx_ring[i].irq = 0; + } +} + +static void ql_free_irq(struct ql_adapter *qdev) +{ + int i; + struct intr_context *intr_context = &qdev->intr_context[0]; + + for (i = 0; i < qdev->intr_count; i++, intr_context++) { + if (intr_context->hooked) { + if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { + free_irq(qdev->msi_x_entry[i].vector, + &qdev->rx_ring[i]); + QPRINTK(qdev, IFDOWN, ERR, + "freeing msix interrupt %d.\n", i); + } else { + free_irq(qdev->pdev->irq, &qdev->rx_ring[0]); + QPRINTK(qdev, IFDOWN, ERR, + "freeing msi interrupt %d.\n", i); + } + } + } + ql_disable_msix(qdev); +} + +static int ql_request_irq(struct ql_adapter *qdev) +{ + int i; + int status = 0; + struct pci_dev *pdev = qdev->pdev; + struct intr_context *intr_context = &qdev->intr_context[0]; + + ql_resolve_queues_to_irqs(qdev); + + for (i = 0; i < qdev->intr_count; i++, intr_context++) { + atomic_set(&intr_context->irq_cnt, 0); + if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { + status = request_irq(qdev->msi_x_entry[i].vector, + intr_context->handler, + 0, + intr_context->name, + &qdev->rx_ring[i]); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed request for MSIX interrupt %d.\n", + i); + goto err_irq; + } else { + QPRINTK(qdev, IFUP, INFO, + "Hooked intr %d, queue type %s%s%s, with name %s.\n", + i, + qdev->rx_ring[i].type == + DEFAULT_Q ? "DEFAULT_Q" : "", + qdev->rx_ring[i].type == + TX_Q ? "TX_Q" : "", + qdev->rx_ring[i].type == + RX_Q ? "RX_Q" : "", intr_context->name); + } + } else { + QPRINTK(qdev, IFUP, DEBUG, + "trying msi or legacy interrupts.\n"); + QPRINTK(qdev, IFUP, DEBUG, + "%s: irq = %d.\n", __func__, pdev->irq); + QPRINTK(qdev, IFUP, DEBUG, + "%s: context->name = %s.\n", __func__, + intr_context->name); + QPRINTK(qdev, IFUP, DEBUG, + "%s: dev_id = 0x%p.\n", __func__, + &qdev->rx_ring[0]); + status = + request_irq(pdev->irq, qlge_isr, + test_bit(QL_MSI_ENABLED, + &qdev-> + flags) ? 0 : IRQF_SHARED, + intr_context->name, &qdev->rx_ring[0]); + if (status) + goto err_irq; + + QPRINTK(qdev, IFUP, ERR, + "Hooked intr %d, queue type %s%s%s, with name %s.\n", + i, + qdev->rx_ring[0].type == + DEFAULT_Q ? "DEFAULT_Q" : "", + qdev->rx_ring[0].type == TX_Q ? "TX_Q" : "", + qdev->rx_ring[0].type == RX_Q ? "RX_Q" : "", + intr_context->name); + } + intr_context->hooked = 1; + } + return status; +err_irq: + QPRINTK(qdev, IFUP, ERR, "Failed to get the interrupts!!!/n"); + ql_free_irq(qdev); + return status; +} + +static int ql_start_rss(struct ql_adapter *qdev) +{ + struct ricb *ricb = &qdev->ricb; + int status = 0; + int i; + u8 *hash_id = (u8 *) ricb->hash_cq_id; + + memset((void *)ricb, 0, sizeof(ricb)); + + ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; + ricb->flags = + (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RI4 | RSS_RI6 | RSS_RT4 | + RSS_RT6); + ricb->mask = cpu_to_le16(qdev->rss_ring_count - 1); + + /* + * Fill out the Indirection Table. + */ + for (i = 0; i < 32; i++) + hash_id[i] = i & 1; + + /* + * Random values for the IPv6 and IPv4 Hash Keys. + */ + get_random_bytes((void *)&ricb->ipv6_hash_key[0], 40); + get_random_bytes((void *)&ricb->ipv4_hash_key[0], 16); + + QPRINTK(qdev, IFUP, INFO, "Initializing RSS.\n"); + + status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); + return status; + } + QPRINTK(qdev, IFUP, INFO, "Successfully loaded RICB.\n"); + return status; +} + +/* Initialize the frame-to-queue routing. */ +static int ql_route_initialize(struct ql_adapter *qdev) +{ + int status = 0; + int i; + + /* Clear all the entries in the routing table. */ + for (i = 0; i < 16; i++) { + status = ql_set_routing_reg(qdev, i, 0, 0); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to init routing register for CAM packets.\n"); + return status; + } + } + + status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to init routing register for error packets.\n"); + return status; + } + status = ql_set_routing_reg(qdev, RT_IDX_BCAST_SLOT, RT_IDX_BCAST, 1); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to init routing register for broadcast packets.\n"); + return status; + } + /* If we have more than one inbound queue, then turn on RSS in the + * routing block. + */ + if (qdev->rss_ring_count > 1) { + status = ql_set_routing_reg(qdev, RT_IDX_RSS_MATCH_SLOT, + RT_IDX_RSS_MATCH, 1); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to init routing register for MATCH RSS packets.\n"); + return status; + } + } + + status = ql_set_routing_reg(qdev, RT_IDX_CAM_HIT_SLOT, + RT_IDX_CAM_HIT, 1); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to init routing register for CAM packets.\n"); + return status; + } + return status; +} + +static int ql_adapter_initialize(struct ql_adapter *qdev) +{ + u32 value, mask; + int i; + int status = 0; + + /* + * Set up the System register to halt on errors. + */ + value = SYS_EFE | SYS_FAE; + mask = value << 16; + ql_write32(qdev, SYS, mask | value); + + /* Set the default queue. */ + value = NIC_RCV_CFG_DFQ; + mask = NIC_RCV_CFG_DFQ_MASK; + ql_write32(qdev, NIC_RCV_CFG, (mask | value)); + + /* Set the MPI interrupt to enabled. */ + ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); + + /* Enable the function, set pagesize, enable error checking. */ + value = FSC_FE | FSC_EPC_INBOUND | FSC_EPC_OUTBOUND | + FSC_EC | FSC_VM_PAGE_4K | FSC_SH; + + /* Set/clear header splitting. */ + mask = FSC_VM_PAGESIZE_MASK | + FSC_DBL_MASK | FSC_DBRST_MASK | (value << 16); + ql_write32(qdev, FSC, mask | value); + + ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP | + min(SMALL_BUFFER_SIZE, MAX_SPLIT_SIZE)); + + /* Start up the rx queues. */ + for (i = 0; i < qdev->rx_ring_count; i++) { + status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to start rx ring[%d].\n", i); + return status; + } + } + + /* If there is more than one inbound completion queue + * then download a RICB to configure RSS. + */ + if (qdev->rss_ring_count > 1) { + status = ql_start_rss(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to start RSS.\n"); + return status; + } + } + + /* Start up the tx queues. */ + for (i = 0; i < qdev->tx_ring_count; i++) { + status = ql_start_tx_ring(qdev, &qdev->tx_ring[i]); + if (status) { + QPRINTK(qdev, IFUP, ERR, + "Failed to start tx ring[%d].\n", i); + return status; + } + } + + status = ql_port_initialize(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); + return status; + } + + status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); + return status; + } + + status = ql_route_initialize(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to init routing table.\n"); + return status; + } + + /* Start NAPI for the RSS queues. */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) { + QPRINTK(qdev, IFUP, INFO, "Enabling NAPI for rx_ring[%d].\n", + i); + napi_enable(&qdev->rx_ring[i].napi); + } + + return status; +} + +/* Issue soft reset to chip. */ +static int ql_adapter_reset(struct ql_adapter *qdev) +{ + u32 value; + int max_wait_time; + int status = 0; + int resetCnt = 0; + +#define MAX_RESET_CNT 1 +issueReset: + resetCnt++; + QPRINTK(qdev, IFDOWN, DEBUG, "Issue soft reset to chip.\n"); + ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); + /* Wait for reset to complete. */ + max_wait_time = 3; + QPRINTK(qdev, IFDOWN, DEBUG, "Wait %d seconds for reset to complete.\n", + max_wait_time); + do { + value = ql_read32(qdev, RST_FO); + if ((value & RST_FO_FR) == 0) + break; + + ssleep(1); + } while ((--max_wait_time)); + if (value & RST_FO_FR) { + QPRINTK(qdev, IFDOWN, ERR, + "Stuck in SoftReset: FSC_SR:0x%08x\n", value); + if (resetCnt < MAX_RESET_CNT) + goto issueReset; + } + if (max_wait_time == 0) { + status = -ETIMEDOUT; + QPRINTK(qdev, IFDOWN, ERR, + "ETIMEOUT!!! errored out of resetting the chip!\n"); + } + + return status; +} + +static void ql_display_dev_info(struct net_device *ndev) +{ + struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + + QPRINTK(qdev, PROBE, INFO, + "Function #%d, NIC Roll %d, NIC Rev = %d, " + "XG Roll = %d, XG Rev = %d.\n", + qdev->func, + qdev->chip_rev_id & 0x0000000f, + qdev->chip_rev_id >> 4 & 0x0000000f, + qdev->chip_rev_id >> 8 & 0x0000000f, + qdev->chip_rev_id >> 12 & 0x0000000f); + QPRINTK(qdev, PROBE, INFO, + "MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", + ndev->dev_addr[0], ndev->dev_addr[1], + ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4], + ndev->dev_addr[5]); +} + +static int ql_adapter_down(struct ql_adapter *qdev) +{ + struct net_device *ndev = qdev->ndev; + int i, status = 0; + struct rx_ring *rx_ring; + + netif_stop_queue(ndev); + netif_carrier_off(ndev); + + cancel_delayed_work_sync(&qdev->asic_reset_work); + cancel_delayed_work_sync(&qdev->mpi_reset_work); + cancel_delayed_work_sync(&qdev->mpi_work); + + /* The default queue at index 0 is always processed in + * a workqueue. + */ + cancel_delayed_work_sync(&qdev->rx_ring[0].rx_work); + + /* The rest of the rx_rings are processed in + * a workqueue only if it's a single interrupt + * environment (MSI/Legacy). + */ + for (i = 1; i > qdev->rx_ring_count; i++) { + rx_ring = &qdev->rx_ring[i]; + /* Only the RSS rings use NAPI on multi irq + * environment. Outbound completion processing + * is done in interrupt context. + */ + if (i >= qdev->rss_ring_first_cq_id) { + napi_disable(&rx_ring->napi); + } else { + cancel_delayed_work_sync(&rx_ring->rx_work); + } + } + + clear_bit(QL_ADAPTER_UP, &qdev->flags); + + ql_disable_interrupts(qdev); + + ql_tx_ring_clean(qdev); + + spin_lock(&qdev->hw_lock); + status = ql_adapter_reset(qdev); + if (status) + QPRINTK(qdev, IFDOWN, ERR, "reset(func #%d) FAILED!\n", + qdev->func); + spin_unlock(&qdev->hw_lock); + return status; +} + +static int ql_adapter_up(struct ql_adapter *qdev) +{ + int err = 0; + + spin_lock(&qdev->hw_lock); + err = ql_adapter_initialize(qdev); + if (err) { + QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n"); + spin_unlock(&qdev->hw_lock); + goto err_init; + } + spin_unlock(&qdev->hw_lock); + set_bit(QL_ADAPTER_UP, &qdev->flags); + ql_enable_interrupts(qdev); + ql_enable_all_completion_interrupts(qdev); + if ((ql_read32(qdev, STS) & qdev->port_init)) { + netif_carrier_on(qdev->ndev); + netif_start_queue(qdev->ndev); + } + + return 0; +err_init: + ql_adapter_reset(qdev); + return err; +} + +static int ql_cycle_adapter(struct ql_adapter *qdev) +{ + int status; + + status = ql_adapter_down(qdev); + if (status) + goto error; + + status = ql_adapter_up(qdev); + if (status) + goto error; + + return status; +error: + QPRINTK(qdev, IFUP, ALERT, + "Driver up/down cycle failed, closing device\n"); + rtnl_lock(); + dev_close(qdev->ndev); + rtnl_unlock(); + return status; +} + +static void ql_release_adapter_resources(struct ql_adapter *qdev) +{ + ql_free_mem_resources(qdev); + ql_free_irq(qdev); +} + +static int ql_get_adapter_resources(struct ql_adapter *qdev) +{ + int status = 0; + + if (ql_alloc_mem_resources(qdev)) { + QPRINTK(qdev, IFUP, ERR, "Unable to allocate memory.\n"); + return -ENOMEM; + } + status = ql_request_irq(qdev); + if (status) + goto err_irq; + return status; +err_irq: + ql_free_mem_resources(qdev); + return status; +} + +static int qlge_close(struct net_device *ndev) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + + /* + * Wait for device to recover from a reset. + * (Rarely happens, but possible.) + */ + while (!test_bit(QL_ADAPTER_UP, &qdev->flags)) + msleep(1); + ql_adapter_down(qdev); + ql_release_adapter_resources(qdev); + ql_free_ring_cb(qdev); + return 0; +} + +static int ql_configure_rings(struct ql_adapter *qdev) +{ + int i; + struct rx_ring *rx_ring; + struct tx_ring *tx_ring; + int cpu_cnt = num_online_cpus(); + + /* + * For each processor present we allocate one + * rx_ring for outbound completions, and one + * rx_ring for inbound completions. Plus there is + * always the one default queue. For the CPU + * counts we end up with the following rx_rings: + * rx_ring count = + * one default queue + + * (CPU count * outbound completion rx_ring) + + * (CPU count * inbound (RSS) completion rx_ring) + * To keep it simple we limit the total number of + * queues to < 32, so we truncate CPU to 8. + * This limitation can be removed when requested. + */ + + if (cpu_cnt > 8) + cpu_cnt = 8; + + /* + * rx_ring[0] is always the default queue. + */ + /* Allocate outbound completion ring for each CPU. */ + qdev->tx_ring_count = cpu_cnt; + /* Allocate inbound completion (RSS) ring for each CPU. */ + qdev->rss_ring_count = cpu_cnt; + /* cq_id for the first inbound ring handler. */ + qdev->rss_ring_first_cq_id = cpu_cnt + 1; + /* + * qdev->rx_ring_count: + * Total number of rx_rings. This includes the one + * default queue, a number of outbound completion + * handler rx_rings, and the number of inbound + * completion handler rx_rings. + */ + qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1; + + if (ql_alloc_ring_cb(qdev)) + return -ENOMEM; + + for (i = 0; i < qdev->tx_ring_count; i++) { + tx_ring = &qdev->tx_ring[i]; + memset((void *)tx_ring, 0, sizeof(tx_ring)); + tx_ring->qdev = qdev; + tx_ring->wq_id = i; + tx_ring->wq_len = qdev->tx_ring_size; + tx_ring->wq_size = + tx_ring->wq_len * sizeof(struct ob_mac_iocb_req); + + /* + * The completion queue ID for the tx rings start + * immediately after the default Q ID, which is zero. + */ + tx_ring->cq_id = i + 1; + } + + for (i = 0; i < qdev->rx_ring_count; i++) { + rx_ring = &qdev->rx_ring[i]; + memset((void *)rx_ring, 0, sizeof(rx_ring)); + rx_ring->qdev = qdev; + rx_ring->cq_id = i; + rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ + if (i == 0) { /* Default queue at index 0. */ + /* + * Default queue handles bcast/mcast plus + * async events. Needs buffers. + */ + rx_ring->cq_len = qdev->rx_ring_size; + rx_ring->cq_size = + rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); + rx_ring->lbq_len = NUM_LARGE_BUFFERS; + rx_ring->lbq_size = + rx_ring->lbq_len * sizeof(struct bq_element); + rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; + rx_ring->sbq_len = NUM_SMALL_BUFFERS; + rx_ring->sbq_size = + rx_ring->sbq_len * sizeof(struct bq_element); + rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; + rx_ring->type = DEFAULT_Q; + } else if (i < qdev->rss_ring_first_cq_id) { + /* + * Outbound queue handles outbound completions only. + */ + /* outbound cq is same size as tx_ring it services. */ + rx_ring->cq_len = qdev->tx_ring_size; + rx_ring->cq_size = + rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); + rx_ring->lbq_len = 0; + rx_ring->lbq_size = 0; + rx_ring->lbq_buf_size = 0; + rx_ring->sbq_len = 0; + rx_ring->sbq_size = 0; + rx_ring->sbq_buf_size = 0; + rx_ring->type = TX_Q; + } else { /* Inbound completions (RSS) queues */ + /* + * Inbound queues handle unicast frames only. + */ + rx_ring->cq_len = qdev->rx_ring_size; + rx_ring->cq_size = + rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); + rx_ring->lbq_len = NUM_LARGE_BUFFERS; + rx_ring->lbq_size = + rx_ring->lbq_len * sizeof(struct bq_element); + rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; + rx_ring->sbq_len = NUM_SMALL_BUFFERS; + rx_ring->sbq_size = + rx_ring->sbq_len * sizeof(struct bq_element); + rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; + rx_ring->type = RX_Q; + } + } + return 0; +} + +static int qlge_open(struct net_device *ndev) +{ + int err = 0; + struct ql_adapter *qdev = netdev_priv(ndev); + + err = ql_configure_rings(qdev); + if (err) + return err; + + err = ql_get_adapter_resources(qdev); + if (err) + goto error_up; + + err = ql_adapter_up(qdev); + if (err) + goto error_up; + + return err; + +error_up: + ql_release_adapter_resources(qdev); + ql_free_ring_cb(qdev); + return err; +} + +static int qlge_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + + if (ndev->mtu == 1500 && new_mtu == 9000) { + QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n"); + } else if (ndev->mtu == 9000 && new_mtu == 1500) { + QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n"); + } else if ((ndev->mtu == 1500 && new_mtu == 1500) || + (ndev->mtu == 9000 && new_mtu == 9000)) { + return 0; + } else + return -EINVAL; + ndev->mtu = new_mtu; + return 0; +} + +static struct net_device_stats *qlge_get_stats(struct net_device + *ndev) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + return &qdev->stats; +} + +static void qlge_set_multicast_list(struct net_device *ndev) +{ + struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct dev_mc_list *mc_ptr; + int i; + + spin_lock(&qdev->hw_lock); + /* + * Set or clear promiscuous mode if a + * transition is taking place. + */ + if (ndev->flags & IFF_PROMISC) { + if (!test_bit(QL_PROMISCUOUS, &qdev->flags)) { + if (ql_set_routing_reg + (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 1)) { + QPRINTK(qdev, HW, ERR, + "Failed to set promiscous mode.\n"); + } else { + set_bit(QL_PROMISCUOUS, &qdev->flags); + } + } + } else { + if (test_bit(QL_PROMISCUOUS, &qdev->flags)) { + if (ql_set_routing_reg + (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 0)) { + QPRINTK(qdev, HW, ERR, + "Failed to clear promiscous mode.\n"); + } else { + clear_bit(QL_PROMISCUOUS, &qdev->flags); + } + } + } + + /* + * Set or clear all multicast mode if a + * transition is taking place. + */ + if ((ndev->flags & IFF_ALLMULTI) || + (ndev->mc_count > MAX_MULTICAST_ENTRIES)) { + if (!test_bit(QL_ALLMULTI, &qdev->flags)) { + if (ql_set_routing_reg + (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 1)) { + QPRINTK(qdev, HW, ERR, + "Failed to set all-multi mode.\n"); + } else { + set_bit(QL_ALLMULTI, &qdev->flags); + } + } + } else { + if (test_bit(QL_ALLMULTI, &qdev->flags)) { + if (ql_set_routing_reg + (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 0)) { + QPRINTK(qdev, HW, ERR, + "Failed to clear all-multi mode.\n"); + } else { + clear_bit(QL_ALLMULTI, &qdev->flags); + } + } + } + + if (ndev->mc_count) { + for (i = 0, mc_ptr = ndev->mc_list; mc_ptr; + i++, mc_ptr = mc_ptr->next) + if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr, + MAC_ADDR_TYPE_MULTI_MAC, i)) { + QPRINTK(qdev, HW, ERR, + "Failed to loadmulticast address.\n"); + goto exit; + } + if (ql_set_routing_reg + (qdev, RT_IDX_MCAST_MATCH_SLOT, RT_IDX_MCAST_MATCH, 1)) { + QPRINTK(qdev, HW, ERR, + "Failed to set multicast match mode.\n"); + } else { + set_bit(QL_ALLMULTI, &qdev->flags); + } + } +exit: + spin_unlock(&qdev->hw_lock); +} + +static int qlge_set_mac_address(struct net_device *ndev, void *p) +{ + struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + struct sockaddr *addr = p; + + if (netif_running(ndev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); + + spin_lock(&qdev->hw_lock); + if (ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func)) {/* Unicast */ + QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n"); + return -1; + } + spin_unlock(&qdev->hw_lock); + + return 0; +} + +static void qlge_tx_timeout(struct net_device *ndev) +{ + struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); + queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0); +} + +static void ql_asic_reset_work(struct work_struct *work) +{ + struct ql_adapter *qdev = + container_of(work, struct ql_adapter, asic_reset_work.work); + ql_cycle_adapter(qdev); +} + +static void ql_get_board_info(struct ql_adapter *qdev) +{ + qdev->func = + (ql_read32(qdev, STS) & STS_FUNC_ID_MASK) >> STS_FUNC_ID_SHIFT; + if (qdev->func) { + qdev->xg_sem_mask = SEM_XGMAC1_MASK; + qdev->port_link_up = STS_PL1; + qdev->port_init = STS_PI1; + qdev->mailbox_in = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC2_MBI; + qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC2_MBO; + } else { + qdev->xg_sem_mask = SEM_XGMAC0_MASK; + qdev->port_link_up = STS_PL0; + qdev->port_init = STS_PI0; + qdev->mailbox_in = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBI; + qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBO; + } + qdev->chip_rev_id = ql_read32(qdev, REV_ID); +} + +static void ql_release_all(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + + if (qdev->workqueue) { + destroy_workqueue(qdev->workqueue); + qdev->workqueue = NULL; + } + if (qdev->q_workqueue) { + destroy_workqueue(qdev->q_workqueue); + qdev->q_workqueue = NULL; + } + if (qdev->reg_base) + iounmap((void *)qdev->reg_base); + if (qdev->doorbell_area) + iounmap(qdev->doorbell_area); + pci_release_regions(pdev); + pci_set_drvdata(pdev, NULL); +} + +static int __devinit ql_init_device(struct pci_dev *pdev, + struct net_device *ndev, int cards_found) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + int pos, err = 0; + u16 val16; + + memset((void *)qdev, 0, sizeof(qdev)); + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "PCI device enable failed.\n"); + return err; + } + + pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (pos <= 0) { + dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, " + "aborting.\n"); + goto err_out; + } else { + pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16); + val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; + val16 |= (PCI_EXP_DEVCTL_CERE | + PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); + pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16); + } + + err = pci_request_regions(pdev, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "PCI region request failed.\n"); + goto err_out; + } + + pci_set_master(pdev); + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + set_bit(QL_DMA64, &qdev->flags); + err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + } else { + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (!err) + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + } + + if (err) { + dev_err(&pdev->dev, "No usable DMA configuration.\n"); + goto err_out; + } + + pci_set_drvdata(pdev, ndev); + qdev->reg_base = + ioremap_nocache(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + if (!qdev->reg_base) { + dev_err(&pdev->dev, "Register mapping failed.\n"); + err = -ENOMEM; + goto err_out; + } + + qdev->doorbell_area_size = pci_resource_len(pdev, 3); + qdev->doorbell_area = + ioremap_nocache(pci_resource_start(pdev, 3), + pci_resource_len(pdev, 3)); + if (!qdev->doorbell_area) { + dev_err(&pdev->dev, "Doorbell register mapping failed.\n"); + err = -ENOMEM; + goto err_out; + } + + ql_get_board_info(qdev); + qdev->ndev = ndev; + qdev->pdev = pdev; + qdev->msg_enable = netif_msg_init(debug, default_msg); + spin_lock_init(&qdev->hw_lock); + spin_lock_init(&qdev->stats_lock); + + /* make sure the EEPROM is good */ + err = ql_get_flash_params(qdev); + if (err) { + dev_err(&pdev->dev, "Invalid FLASH.\n"); + goto err_out; + } + + if (!is_valid_ether_addr(qdev->flash.mac_addr)) + goto err_out; + + memcpy(ndev->dev_addr, qdev->flash.mac_addr, ndev->addr_len); + memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); + + /* Set up the default ring sizes. */ + qdev->tx_ring_size = NUM_TX_RING_ENTRIES; + qdev->rx_ring_size = NUM_RX_RING_ENTRIES; + + /* Set up the coalescing parameters. */ + qdev->rx_coalesce_usecs = DFLT_COALESCE_WAIT; + qdev->tx_coalesce_usecs = DFLT_COALESCE_WAIT; + qdev->rx_max_coalesced_frames = DFLT_INTER_FRAME_WAIT; + qdev->tx_max_coalesced_frames = DFLT_INTER_FRAME_WAIT; + + /* + * Set up the operating parameters. + */ + qdev->rx_csum = 1; + + qdev->q_workqueue = create_workqueue(ndev->name); + qdev->workqueue = create_singlethread_workqueue(ndev->name); + INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); + INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); + INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); + + if (!cards_found) { + dev_info(&pdev->dev, "%s\n", DRV_STRING); + dev_info(&pdev->dev, "Driver name: %s, Version: %s.\n", + DRV_NAME, DRV_VERSION); + } + return 0; +err_out: + ql_release_all(pdev); + pci_disable_device(pdev); + return err; +} + +static int __devinit qlge_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_entry) +{ + struct net_device *ndev = NULL; + struct ql_adapter *qdev = NULL; + static int cards_found = 0; + int err = 0; + + ndev = alloc_etherdev(sizeof(struct ql_adapter)); + if (!ndev) + return -ENOMEM; + + err = ql_init_device(pdev, ndev, cards_found); + if (err < 0) { + free_netdev(ndev); + return err; + } + + qdev = netdev_priv(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + ndev->features = (0 + | NETIF_F_IP_CSUM + | NETIF_F_SG + | NETIF_F_TSO + | NETIF_F_TSO6 + | NETIF_F_TSO_ECN + | NETIF_F_HW_VLAN_TX + | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); + + if (test_bit(QL_DMA64, &qdev->flags)) + ndev->features |= NETIF_F_HIGHDMA; + + /* + * Set up net_device structure. + */ + ndev->tx_queue_len = qdev->tx_ring_size; + ndev->irq = pdev->irq; + ndev->open = qlge_open; + ndev->stop = qlge_close; + ndev->hard_start_xmit = qlge_send; + SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops); + ndev->change_mtu = qlge_change_mtu; + ndev->get_stats = qlge_get_stats; + ndev->set_multicast_list = qlge_set_multicast_list; + ndev->set_mac_address = qlge_set_mac_address; + ndev->tx_timeout = qlge_tx_timeout; + ndev->watchdog_timeo = 10 * HZ; + ndev->vlan_rx_register = ql_vlan_rx_register; + ndev->vlan_rx_add_vid = ql_vlan_rx_add_vid; + ndev->vlan_rx_kill_vid = ql_vlan_rx_kill_vid; + err = register_netdev(ndev); + if (err) { + dev_err(&pdev->dev, "net device registration failed.\n"); + ql_release_all(pdev); + pci_disable_device(pdev); + return err; + } + netif_carrier_off(ndev); + netif_stop_queue(ndev); + ql_display_dev_info(ndev); + cards_found++; + return 0; +} + +static void __devexit qlge_remove(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + unregister_netdev(ndev); + ql_release_all(pdev); + pci_disable_device(pdev); + free_netdev(ndev); +} + +/* + * This callback is called by the PCI subsystem whenever + * a PCI bus error is detected. + */ +static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, + enum pci_channel_state state) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + + if (netif_running(ndev)) + ql_adapter_down(qdev); + + pci_disable_device(pdev); + + /* Request a slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/* + * This callback is called after the PCI buss has been reset. + * Basically, this tries to restart the card from scratch. + * This is a shortened version of the device probe/discovery code, + * it resembles the first-half of the () routine. + */ +static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + + if (pci_enable_device(pdev)) { + QPRINTK(qdev, IFUP, ERR, + "Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + + netif_carrier_off(ndev); + netif_stop_queue(ndev); + ql_adapter_reset(qdev); + + /* Make sure the EEPROM is good */ + memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); + + if (!is_valid_ether_addr(ndev->perm_addr)) { + QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + return PCI_ERS_RESULT_RECOVERED; +} + +static void qlge_io_resume(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + + pci_set_master(pdev); + + if (netif_running(ndev)) { + if (ql_adapter_up(qdev)) { + QPRINTK(qdev, IFUP, ERR, + "Device initialization failed after reset.\n"); + return; + } + } + + netif_device_attach(ndev); +} + +static struct pci_error_handlers qlge_err_handler = { + .error_detected = qlge_io_error_detected, + .slot_reset = qlge_io_slot_reset, + .resume = qlge_io_resume, +}; + +static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + int err; + + netif_device_detach(ndev); + + if (netif_running(ndev)) { + err = ql_adapter_down(qdev); + if (!err) + return err; + } + + err = pci_save_state(pdev); + if (err) + return err; + + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int qlge_resume(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + int err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) { + QPRINTK(qdev, IFUP, ERR, "Cannot enable PCI device from suspend\n"); + return err; + } + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + if (netif_running(ndev)) { + err = ql_adapter_up(qdev); + if (err) + return err; + } + + netif_device_attach(ndev); + + return 0; +} + +static void qlge_shutdown(struct pci_dev *pdev) +{ + qlge_suspend(pdev, PMSG_SUSPEND); +} + +static struct pci_driver qlge_driver = { + .name = DRV_NAME, + .id_table = qlge_pci_tbl, + .probe = qlge_probe, + .remove = __devexit_p(qlge_remove), +#ifdef CONFIG_PM + .suspend = qlge_suspend, + .resume = qlge_resume, +#endif + .shutdown = qlge_shutdown, + .err_handler = &qlge_err_handler +}; + +static int __init qlge_init_module(void) +{ + return pci_register_driver(&qlge_driver); +} + +static void __exit qlge_exit(void) +{ + pci_unregister_driver(&qlge_driver); +} + +module_init(qlge_init_module); +module_exit(qlge_exit); diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c new file mode 100644 index 00000000000..24fe344bcf1 --- /dev/null +++ b/drivers/net/qlge/qlge_mpi.c @@ -0,0 +1,150 @@ +#include "qlge.h" + +static int ql_read_mbox_reg(struct ql_adapter *qdev, u32 reg, u32 *data) +{ + int status; + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); + if (status) + goto exit; + /* set up for reg read */ + ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R); + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR); + if (status) + goto exit; + /* get the data */ + *data = ql_read32(qdev, PROC_DATA); +exit: + return status; +} + +int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) +{ + int i, status; + + status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); + if (status) + return -EBUSY; + for (i = 0; i < mbcp->out_count; i++) { + status = + ql_read_mbox_reg(qdev, qdev->mailbox_out + i, + &mbcp->mbox_out[i]); + if (status) { + QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n"); + break; + } + } + ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ + return status; +} + +static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) +{ + mbcp->out_count = 2; + + if (ql_get_mb_sts(qdev, mbcp)) + goto exit; + + qdev->link_status = mbcp->mbox_out[1]; + QPRINTK(qdev, DRV, ERR, "Link Up.\n"); + QPRINTK(qdev, DRV, INFO, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]); + if (!netif_carrier_ok(qdev->ndev)) { + QPRINTK(qdev, LINK, INFO, "Link is Up.\n"); + netif_carrier_on(qdev->ndev); + netif_wake_queue(qdev->ndev); + } +exit: + /* Clear the MPI firmware status. */ + ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); +} + +static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) +{ + mbcp->out_count = 3; + + if (ql_get_mb_sts(qdev, mbcp)) { + QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n"); + goto exit; + } + + if (netif_carrier_ok(qdev->ndev)) { + QPRINTK(qdev, LINK, INFO, "Link is Down.\n"); + netif_carrier_off(qdev->ndev); + netif_stop_queue(qdev->ndev); + } + QPRINTK(qdev, DRV, ERR, "Link Down.\n"); + QPRINTK(qdev, DRV, ERR, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]); +exit: + /* Clear the MPI firmware status. */ + ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); +} + +static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) +{ + mbcp->out_count = 2; + + if (ql_get_mb_sts(qdev, mbcp)) { + QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n"); + goto exit; + } + QPRINTK(qdev, DRV, ERR, "Firmware initialized!\n"); + QPRINTK(qdev, DRV, ERR, "Firmware status = 0x%.08x.\n", + mbcp->mbox_out[0]); + QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n", + mbcp->mbox_out[1]); +exit: + /* Clear the MPI firmware status. */ + ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); +} + +void ql_mpi_work(struct work_struct *work) +{ + struct ql_adapter *qdev = + container_of(work, struct ql_adapter, mpi_work.work); + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + mbcp->out_count = 1; + + while (ql_read32(qdev, STS) & STS_PI) { + if (ql_get_mb_sts(qdev, mbcp)) { + QPRINTK(qdev, DRV, ERR, + "Could not read MPI, resetting ASIC!\n"); + ql_queue_asic_error(qdev); + } + + switch (mbcp->mbox_out[0]) { + case AEN_LINK_UP: + ql_link_up(qdev, mbcp); + break; + case AEN_LINK_DOWN: + ql_link_down(qdev, mbcp); + break; + case AEN_FW_INIT_DONE: + ql_init_fw_done(qdev, mbcp); + break; + case MB_CMD_STS_GOOD: + break; + case AEN_FW_INIT_FAIL: + case AEN_SYS_ERR: + case MB_CMD_STS_ERR: + ql_queue_fw_error(qdev); + default: + /* Clear the MPI firmware status. */ + ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); + break; + } + } + ql_enable_completion_interrupt(qdev, 0); +} + +void ql_mpi_reset_work(struct work_struct *work) +{ + struct ql_adapter *qdev = + container_of(work, struct ql_adapter, mpi_reset_work.work); + QPRINTK(qdev, DRV, ERR, + "Enter, qdev = %p..\n", qdev); + ql_write32(qdev, CSR, CSR_CMD_SET_RST); + msleep(50); + ql_write32(qdev, CSR, CSR_CMD_CLR_RST); +} -- GitLab From 9c784f958d01097e3fae24ad75ab3a80ed1e556b Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Sun, 3 Aug 2008 02:29:48 +0100 Subject: [PATCH 1982/5416] [ARM] 5210/2: AFEB9260: board support This patch adds support for AT91SAM9260-based board AFEB9260 which is a product from both Open Source design which runs Open Source software. Some commertial projects are made with this design. A board is basically AT91SAM9260-EK with some modifications and different peripherals and different parts used. Main purpose of this project is to gain experience in hardware design. More info: http://groups.google.com/group/arm9fpga-evolution-board (In Russian only, sorry). Subversion repository: svn://194.85.238.22/home/users/george/svn/arm9eb By this patch only basic functionality is provided. Signed-off-by: Sergey Lapin Acked-by: Andrew Victor Signed-off-by: Russell King --- MAINTAINERS | 6 + arch/arm/configs/afeb9260_defconfig | 1259 ++++++++++++++++++++++++ arch/arm/mach-at91/Kconfig | 9 + arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/board-afeb-9260v1.c | 194 ++++ 5 files changed, 1469 insertions(+) create mode 100644 arch/arm/configs/afeb9260_defconfig create mode 100644 arch/arm/mach-at91/board-afeb-9260v1.c diff --git a/MAINTAINERS b/MAINTAINERS index 186be3ba506..0cc08809e53 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -466,6 +466,12 @@ M: kernel@wantstofly.org L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +ARM/AFEB9260 MACHINE SUPPORT +P: Sergey Lapin +M: slapin@ossfans.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +S: Maintained + ARM/AJECO 1ARM MACHINE SUPPORT P: Lennert Buytenhek M: kernel@wantstofly.org diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig new file mode 100644 index 00000000000..ce84033e619 --- /dev/null +++ b/arch/arm/configs/afeb9260_defconfig @@ -0,0 +1,1259 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc2 +# Tue Aug 12 22:30:16 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_AT91SAM9260=y +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91SAM9260 Variants +# +# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set + +# +# AT91SAM9260 / AT91SAM9XE Board Type +# +# CONFIG_MACH_AT91SAM9260EK is not set +# CONFIG_MACH_CAM60 is not set +# CONFIG_MACH_SAM9_L9260 is not set +CONFIG_MACH_AFEB9260=y +# CONFIG_MACH_USB_A9260 is not set +# CONFIG_MACH_QIL_A9260 is not set + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set +CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ATMEL_PWM is not set +# CONFIG_ATMEL_TCLIB is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_ATMEL_SSC=y +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_MACB is not set +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +CONFIG_AT24=y +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_DEBUG=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ATMEL=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_S3C2410 is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ETH is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_DEBUG=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +CONFIG_RTC_DRV_FM3130=y + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_AT91SAM9 is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index a048b92cb40..68537e37387 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -175,6 +175,15 @@ config MACH_SAM9_L9260 Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260. +config MACH_AFEB9260 + bool "Custom afeb9260 board v1" + depends on ARCH_AT91SAM9260 + help + Select this if you are using custom afeb9260 board based on + open hardware design. Select this for revision 1 of the board. + + + config MACH_USB_A9260 bool "CALAO USB-A9260" depends on ARCH_AT91SAM9260 diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 7d641f97516..a95c49bdf92 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_MACH_CAM60) += board-cam60.o obj-$(CONFIG_MACH_SAM9_L9260) += board-sam9-l9260.o obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o +obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o # AT91SAM9261 board-specific support obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c new file mode 100644 index 00000000000..8778b8e0854 --- /dev/null +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -0,0 +1,194 @@ +/* + * linux/arch/arm/mach-at91/board-afeb-9260v1.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * Copyright (C) 2008 Sergey Lapin + * + * A custom board designed as open hardware; PCBs and various information + * is available at http://groups.google.com/group/arm9fpga-evolution-board/ + * Subversion repository: svn://194.85.238.22/home/users/george/svn/arm9eb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + + +static void __init afeb9260_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91SAM9260_ID_US0, 1, + ATMEL_UART_CTS | ATMEL_UART_RTS + | ATMEL_UART_DTR | ATMEL_UART_DSR + | ATMEL_UART_DCD | ATMEL_UART_RI); + + /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9260_ID_US1, 2, + ATMEL_UART_CTS | ATMEL_UART_RTS); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init afeb9260_init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata afeb9260_usbh_data = { + .ports = 1, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata afeb9260_udc_data = { + .vbus_pin = AT91_PIN_PC5, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + + +/* + * SPI devices. + */ +static struct spi_board_info afeb9260_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 1, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +}; + + + +/* + * NAND flash + */ +static struct mtd_partition __initdata afeb9260_nand_partition[] = { + { + .name = "bootloader", + .offset = 0, + .size = (640 * SZ_1K), + }, + { + .name = "kernel", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_2M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(afeb9260_nand_partition); + return afeb9260_nand_partition; +} + +static struct atmel_nand_data __initdata afeb9260_nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, + .bus_width_16 = 0, +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata afeb9260_mmc_data = { + .slot_b = 1, + .wire4 = 1, +}; + + + +static struct i2c_board_info __initdata afeb9260_i2c_devices[] = { + { + I2C_BOARD_INFO("fm3130", 0x68), + I2C_BOARD_INFO("24c64", 0x50), + }, +}; + +static void __init afeb9260_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&afeb9260_usbh_data); + /* USB Device */ + at91_add_device_udc(&afeb9260_udc_data); + /* SPI */ + at91_add_device_spi(afeb9260_spi_devices, + ARRAY_SIZE(afeb9260_spi_devices)); + /* NAND */ + at91_add_device_nand(&afeb9260_nand_data); + /* MMC */ + at91_add_device_mmc(0, &afeb9260_mmc_data); + /* I2C */ + at91_add_device_i2c(afeb9260_i2c_devices, + ARRAY_SIZE(afeb9260_i2c_devices)); +} + +MACHINE_START(AFEB9260, "Custom afeb9260 board") + /* Maintainer: Sergey Lapin */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = afeb9260_map_io, + .init_irq = afeb9260_init_irq, + .init_machine = afeb9260_board_init, +MACHINE_END + -- GitLab From 53d4351f5868c7d3faa9507608c324ff7d7c186c Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Tue, 12 Aug 2008 13:35:34 +0100 Subject: [PATCH 1983/5416] [ARM] 5219/2: MACB ethernet support for AFEB9260 MACB ethernet support for AFEB9260 Depends on 5210/2 Acked-by: Andrew Victor Signed-off-by: Sergey Lapin Signed-off-by: Russell King --- arch/arm/configs/afeb9260_defconfig | 2 +- arch/arm/mach-at91/board-afeb-9260v1.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig index ce84033e619..ce909586a34 100644 --- a/arch/arm/configs/afeb9260_defconfig +++ b/arch/arm/configs/afeb9260_defconfig @@ -581,7 +581,7 @@ CONFIG_PHYLIB=y # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_MACB is not set +CONFIG_MACB=y # CONFIG_AX88796 is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c index 8778b8e0854..9c040c78889 100644 --- a/arch/arm/mach-at91/board-afeb-9260v1.c +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -106,6 +106,14 @@ static struct spi_board_info afeb9260_spi_devices[] = { }; +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata afeb9260_macb_data = { + .phy_irq_pin = AT91_PIN_PA9, + .is_rmii = 0, +}; + /* * NAND flash @@ -174,6 +182,14 @@ static void __init afeb9260_board_init(void) ARRAY_SIZE(afeb9260_spi_devices)); /* NAND */ at91_add_device_nand(&afeb9260_nand_data); + /* Ethernet */ + at91_add_device_eth(&afeb9260_macb_data); + + /* Standard function's pin assignments are not + * appropriate for us and generic code provide + * no API to configure these pins any other way */ + at91_set_B_periph(AT91_PIN_PA10, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA11, 0); /* ETX3 */ /* MMC */ at91_add_device_mmc(0, &afeb9260_mmc_data); /* I2C */ -- GitLab From fbd03a1cbc04833a952b0d603df96e4800445979 Mon Sep 17 00:00:00 2001 From: Guillaume GARDET Date: Fri, 29 Aug 2008 10:11:24 +0100 Subject: [PATCH 1984/5416] [ARM] 5228/1: Add the RGB555 wiring for the atmel LCD Add the RGB555 wiring for the atmel LCD. Acked-by: Nicolas Ferre Acked-by: Haavard Skinnemoen Signed-off-by: Guillaume GARDET Signed-off-by: Russell King --- drivers/video/atmel_lcdfb.c | 4 ++++ include/video/atmel_lcdc.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5a24c6411d3..cedfd01c983 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -378,6 +378,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, var->red.offset = 11; var->blue.offset = 0; var->green.length = 6; + } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) { + var->red.offset = 10; + var->blue.offset = 0; + var->green.length = 5; } else { /* BGR:555 mode */ var->red.offset = 0; diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h index 920c4e9cb93..6ad87f48599 100644 --- a/include/video/atmel_lcdc.h +++ b/include/video/atmel_lcdc.h @@ -30,6 +30,7 @@ */ #define ATMEL_LCDC_WIRING_BGR 0 #define ATMEL_LCDC_WIRING_RGB 1 +#define ATMEL_LCDC_WIRING_RGB555 2 /* LCD Controller info data structure, stored in device platform_data */ -- GitLab From a745a622434d9c3ff6505125b37fd6828ecadb87 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 5 Sep 2008 00:34:50 +0100 Subject: [PATCH 1985/5416] [ARM] 5240/1: AT91: eeproms on sam9260ek, sam9263ek The at91sam9260 and at91sam9263 EK boards have 64 KiB I2C EEPROMs. This patch declares them in the board init code so the new at24 driver will use them. Signed-off-by: David Brownell Acked-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/board-sam9260ek.c | 20 +++++++++++++++++++- arch/arm/mach-at91/board-sam9263ek.c | 21 ++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index cb20e70b3b0..0a53c038b51 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -222,6 +223,23 @@ static struct gpio_led ek_leds[] = { } }; +/* + * I2C devices + */ +static struct at24_platform_data at24c512 = { + .byte_len = SZ_512K / 8, + .page_size = 128, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info __initdata ek_i2c_devices[] = { + { + I2C_BOARD_INFO("24c512", 0x50), + .platform_data = &at24c512, + }, + /* more devices can be added using expansion connectors */ +}; + static void __init ek_board_init(void) { /* Serial */ @@ -239,7 +257,7 @@ static void __init ek_board_init(void) /* MMC */ at91_add_device_mmc(0, &ek_mmc_data); /* I2C */ - at91_add_device_i2c(NULL, 0); + at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* SSC (to AT73C213) */ at73c213_set_clk(&at73c213_data); at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX); diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index b1d11960a73..c51f2eb3874 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -202,6 +203,24 @@ static struct atmel_nand_data __initdata ek_nand_data = { }; +/* + * I2C devices + */ +static struct at24_platform_data at24c512 = { + .byte_len = SZ_512K / 8, + .page_size = 128, + .flags = AT24_FLAG_ADDR16, +}; + + +static struct i2c_board_info __initdata ek_i2c_devices[] = { + { + I2C_BOARD_INFO("24c512", 0x50), + .platform_data = &at24c512, + }, + /* more devices can be added using expansion connectors */ +}; + /* * LCD Controller */ @@ -360,7 +379,7 @@ static void __init ek_board_init(void) /* NAND */ at91_add_device_nand(&ek_nand_data); /* I2C */ - at91_add_device_i2c(NULL, 0); + at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* LCD Controller */ at91_add_device_lcdc(&ek_lcdc_data); /* Push Buttons */ -- GitLab From 33a7f122740bd820a029faf450a9a0caa9458426 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 18 Sep 2008 17:50:42 -0500 Subject: [PATCH 1986/5416] powerpc: Fix build warnings introduced by PMC support on 32-bit arch/powerpc/kernel/sysfs.c:197:7: warning: "CONFIG_6xx" is not defined arch/powerpc/kernel/sysfs.c:141: warning: 'run_on_cpu' defined but not used Signed-off-by: Kumar Gala --- arch/powerpc/kernel/sysfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index ef2ad92a417..86a2ffccef2 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -134,6 +134,7 @@ void ppc_enable_pmcs(void) } EXPORT_SYMBOL(ppc_enable_pmcs); +#if defined(CONFIG_6xx) || defined(CONFIG_PPC64) /* XXX convert to rusty's on_one_cpu */ static unsigned long run_on_cpu(unsigned long cpu, unsigned long (*func)(unsigned long), @@ -152,6 +153,7 @@ static unsigned long run_on_cpu(unsigned long cpu, return ret; } +#endif #define SYSFS_PMCSETUP(NAME, ADDRESS) \ static unsigned long read_##NAME(unsigned long junk) \ @@ -190,11 +192,11 @@ static ssize_t __used \ * that are implemented on the current processor */ -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) #define HAS_PPC_PMC_CLASSIC 1 #define HAS_PPC_PMC_IBM 1 #define HAS_PPC_PMC_PA6T 1 -#elif CONFIG_6xx +#elif defined(CONFIG_6xx) #define HAS_PPC_PMC_CLASSIC 1 #define HAS_PPC_PMC_IBM 1 #define HAS_PPC_PMC_G4 1 -- GitLab From 0ef46e285c062cbe35d60c0adbff96f530d31c86 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 16:27:38 -0700 Subject: [PATCH 1987/5416] sctp: do not enable peer features if we can't do them. Do not enable peer features like addip and auth, if they are administratively disabled localy. If the peer resports that he supports something that we don't, neither end can use it so enabling it is pointless. This solves a problem when talking to a peer that has auth and addip enabled while we do not. Found by Andrei Pelinescu-Onciul . Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981..fe94f42fa06 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1886,11 +1886,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, /* if the peer reports AUTH, assume that he * supports AUTH. */ - asoc->peer.auth_capable = 1; + if (sctp_auth_enable) + asoc->peer.auth_capable = 1; break; case SCTP_CID_ASCONF: case SCTP_CID_ASCONF_ACK: - asoc->peer.asconf_capable = 1; + if (sctp_addip_enable) + asoc->peer.asconf_capable = 1; break; default: break; @@ -2460,6 +2462,9 @@ do_addr_param: break; case SCTP_PARAM_SET_PRIMARY: + if (!sctp_addip_enable) + goto fall_through; + addr_param = param.v + sizeof(sctp_addip_param_t); af = sctp_get_af_specific(param_type2af(param.p->type)); -- GitLab From add52379dde2e5300e2d574b172e62c6cf43b3d3 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 16:28:27 -0700 Subject: [PATCH 1988/5416] sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH If INIT-ACK is received with SupportedExtensions parameter which indicates that the peer does not support AUTH, the packet will be silently ignore, and sctp_process_init() do cleanup all of the transports in the association. When T1-Init timer is expires, OOPS happen while we try to choose a different init transport. The solution is to only clean up the non-active transports, i.e the ones that the peer added. However, that introduces a problem with sctp_connectx(), because we don't mark the proper state for the transports provided by the user. So, we'll simply mark user-provided transports as ACTIVE. That will allow INIT retransmissions to work properly in the sctp_connectx() context and prevent the crash. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/associola.c | 9 +++++---- net/sctp/sm_make_chunk.c | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c..abd51cef241 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, /* Check to see if this is a duplicate. */ peer = sctp_assoc_lookup_paddr(asoc, addr); if (peer) { + /* An UNKNOWN state is only set on transports added by + * user in sctp_connectx() call. Such transports should be + * considered CONFIRMED per RFC 4960, Section 5.4. + */ if (peer->state == SCTP_UNKNOWN) { - if (peer_state == SCTP_ACTIVE) - peer->state = SCTP_ACTIVE; - if (peer_state == SCTP_UNCONFIRMED) - peer->state = SCTP_UNCONFIRMED; + peer->state = SCTP_ACTIVE; } return peer; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fe94f42fa06..b599cbba4fb 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2321,12 +2321,10 @@ clean_up: /* Release the transport structures. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - list_del_init(pos); - sctp_transport_free(transport); + if (transport->state != SCTP_ACTIVE) + sctp_assoc_rm_peer(asoc, transport); } - asoc->peer.transport_count = 0; - nomem: return 0; } -- GitLab From 344478db5385194ec27f6aaf780ea21c4b4ff02c Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:38:24 -0700 Subject: [PATCH 1989/5416] bnx2: In bnx2_set_mac_link() return void rather then int bnx2_set_mac_link() doesn't need to return any error codes. And all the callers don't check the return code. It is safe to change the return type to a void. Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 2486a656f12..192a24ee3e6 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1127,7 +1127,7 @@ bnx2_init_all_rx_contexts(struct bnx2 *bp) } } -static int +static void bnx2_set_mac_link(struct bnx2 *bp) { u32 val; @@ -1193,8 +1193,6 @@ bnx2_set_mac_link(struct bnx2 *bp) if (CHIP_NUM(bp) == CHIP_NUM_5709) bnx2_init_all_rx_contexts(bp); - - return 0; } static void -- GitLab From 453a9c6e995149c4a43e50b5482a48ed0298b0dc Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:39:16 -0700 Subject: [PATCH 1990/5416] bnx2: Update MODULE_DESCRIPTION to include the 5716 Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 192a24ee3e6..a78b664cd44 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -69,7 +69,7 @@ static char version[] __devinitdata = "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Michael Chan "); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 Driver"); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -- GitLab From fbbf68b7f88953a9c56b7a7b4019fa5212987b34 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:40:03 -0700 Subject: [PATCH 1991/5416] bnx2: Remove name field from bnx2 structure The name of the board is only used during the initialization of the adapter. We can save the space of a pointer by not storing this information. Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 3 +-- drivers/net/bnx2.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a78b664cd44..84177663291 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7718,7 +7718,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(dev->dev_addr, bp->mac_addr, 6); memcpy(dev->perm_addr, bp->mac_addr, 6); - bp->name = board_info[ent->driver_data].name; dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (CHIP_NUM(bp) == CHIP_NUM_5709) @@ -7745,7 +7744,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, " "IRQ %d, node addr %s\n", dev->name, - bp->name, + board_info[ent->driver_data].name, ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', ((CHIP_ID(bp) & 0x0ff0) >> 4), bnx2_bus_string(bp, str), diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index c3c579f98ed..cb47c98ddd7 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6701,8 +6701,6 @@ struct bnx2 { /* End of fields used in the performance code paths. */ - char *name; - int timer_interval; int current_interval; struct timer_list timer; -- GitLab From ac392abce936d78f7b731d90bfbc1001ddb446ea Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:40:49 -0700 Subject: [PATCH 1992/5416] bnx2: Remove timer_interval field from the bnx2 structure The timer_interval field is only assigned once, and never reassigned. We can safely replace all instances of the timer_interval with a constant value. Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 13 ++++++------- drivers/net/bnx2.h | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 84177663291..883e0a72410 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -5598,7 +5598,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) } else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { u32 bmcr; - bp->current_interval = bp->timer_interval; + bp->current_interval = BNX2_TIMER_INTERVAL; bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); @@ -5627,7 +5627,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT; } } else - bp->current_interval = bp->timer_interval; + bp->current_interval = BNX2_TIMER_INTERVAL; if (check_link) { u32 val; @@ -5672,11 +5672,11 @@ bnx2_5708_serdes_timer(struct bnx2 *bp) } else { bnx2_disable_forced_2g5(bp); bp->serdes_an_pending = 2; - bp->current_interval = bp->timer_interval; + bp->current_interval = BNX2_TIMER_INTERVAL; } } else - bp->current_interval = bp->timer_interval; + bp->current_interval = BNX2_TIMER_INTERVAL; spin_unlock(&bp->phy_lock); } @@ -7514,8 +7514,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS; - bp->timer_interval = HZ; - bp->current_interval = HZ; + bp->current_interval = BNX2_TIMER_INTERVAL; bp->phy_addr = 1; @@ -7605,7 +7604,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; init_timer(&bp->timer); - bp->timer.expires = RUN_AT(bp->timer_interval); + bp->timer.expires = RUN_AT(BNX2_TIMER_INTERVAL); bp->timer.data = (unsigned long) bp; bp->timer.function = bnx2_timer; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index cb47c98ddd7..682b8f07752 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6654,6 +6654,8 @@ struct bnx2_napi { struct bnx2_tx_ring_info tx_ring; }; +#define BNX2_TIMER_INTERVAL HZ + struct bnx2 { /* Fields used in the tx and intr/napi performance paths are grouped */ /* together in the beginning of the structure. */ @@ -6701,7 +6703,6 @@ struct bnx2 { /* End of fields used in the performance code paths. */ - int timer_interval; int current_interval; struct timer_list timer; struct work_struct reset_task; -- GitLab From 821c92f258bd9b01eb900992969803645b6ba9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 18 Sep 2008 16:44:31 -0700 Subject: [PATCH 1993/5416] ISDN sockets: add missing lockdep strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/core/sock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/sock.c b/net/core/sock.c index 91f8bbc9352..23b8b9da36b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -154,7 +154,7 @@ static const char *af_family_key_strings[AF_MAX+1] = { "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , - "sk_lock-AF_RXRPC" , "sk_lock-AF_MAX" + "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_MAX" }; static const char *af_family_slock_key_strings[AF_MAX+1] = { "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , @@ -168,7 +168,7 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = { "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , "slock-27" , "slock-28" , "slock-AF_CAN" , "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , - "slock-AF_RXRPC" , "slock-AF_MAX" + "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_MAX" }; static const char *af_family_clock_key_strings[AF_MAX+1] = { "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , @@ -182,7 +182,7 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = { "clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" , "clock-27" , "clock-28" , "clock-AF_CAN" , "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , - "clock-AF_RXRPC" , "clock-AF_MAX" + "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_MAX" }; #endif -- GitLab From 27ed9ddfde8d2967076c51815e4ce297c4a18139 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:46:11 -0700 Subject: [PATCH 1994/5416] bnx2: Promote vector field in bnx2_irq structure from u16 to unsigned int The bnx2 driver stores/uses the irq value from the pci_dev internally. But when it stores the irq value, it has been performing an integer demotion. Because of the recent changes made to arch/x86/kernel/io_apic.c, the new method in creating the irq value (using build_irq_for_pci_dev()) has exposed this bug on x86 systems. Because of this demotion when calling request_irq() from bnx2_request_irq(), the driver would get a return code of -EINVAL. This is because the kernel could not find the requested irq descriptor. By storing the irq value properly, the kernel can find the correct irq descriptor and the bnx2 driver can operate normally. Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index c3c579f98ed..dfacd31f7ed 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6597,7 +6597,7 @@ struct flash_spec { struct bnx2_irq { irq_handler_t handler; - u16 vector; + unsigned int vector; u8 requested; char name[16]; }; -- GitLab From f55c21fd9a92a444e55ad1ca4e4732d56661bf2e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 13 Sep 2008 13:10:31 -0700 Subject: [PATCH 1995/5416] forcedeth: call restore mac addr in nv_shutdown path after | commit f735a2a1a4f2a0f5cd823ce323e82675990469e2 | Author: Tobias Diedrich | Date: Sun May 18 15:02:37 2008 +0200 | | [netdrvr] forcedeth: setup wake-on-lan before shutting down | | When hibernating in 'shutdown' mode, after saving the image the suspend hook | is not called again. | However, if the device is in promiscous mode, wake-on-lan will not work. | This adds a shutdown hook to setup wake-on-lan before the final shutdown. | | Signed-off-by: Tobias Diedrich | Signed-off-by: Jeff Garzik my servers with nvidia ck804 and mcp55 will reverse mac address with kexec. it turns out that we need to restore the mac addr in nv_shutdown(). [akpm@linux-foundation.org: fix typo in printk] Signed-off-by: Yinghai Lu Cc: Tobias Diedrich Cc: Ayaz Abdulla Cc: Jeff Garzik Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0b6ecef9a84..eeb55ed2152 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5643,6 +5643,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); + printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n"); } memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); @@ -5890,14 +5891,12 @@ static void nv_restore_phy(struct net_device *dev) } } -static void __devexit nv_remove(struct pci_dev *pci_dev) +static void nv_restore_mac_addr(struct pci_dev *pci_dev) { struct net_device *dev = pci_get_drvdata(pci_dev); struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - unregister_netdev(dev); - /* special op: write back the misordered MAC address - otherwise * the next nv_probe would see a wrong address. */ @@ -5905,6 +5904,15 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) writel(np->orig_mac[1], base + NvRegMacAddrB); writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); +} + +static void __devexit nv_remove(struct pci_dev *pci_dev) +{ + struct net_device *dev = pci_get_drvdata(pci_dev); + + unregister_netdev(dev); + + nv_restore_mac_addr(pci_dev); /* restore any phy related changes */ nv_restore_phy(dev); @@ -5975,6 +5983,8 @@ static void nv_shutdown(struct pci_dev *pdev) if (netif_running(dev)) nv_close(dev); + nv_restore_mac_addr(pdev); + pci_disable_device(pdev); if (system_state == SYSTEM_POWER_OFF) { if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) -- GitLab From 78566fecbb12a7616ae9a88b2ffbc8062c4a89e3 Mon Sep 17 00:00:00 2001 From: Christopher Li Date: Fri, 5 Sep 2008 14:04:05 -0700 Subject: [PATCH 1996/5416] e1000: prevent corruption of EEPROM/NVM Andrey reports e1000 corruption, and that a patch in vmware's ESX fixed it. The EEPROM corruption is triggered by concurrent access of the EEPROM read/write. Putting a lock around it solve the problem. [akpm@linux-foundation.org: use DEFINE_SPINLOCK to avoid confusing lockdep] Signed-off-by: Christopher Li Reported-by: Andrey Borzenkov Cc: Zach Amsden Cc: Pratap Subrahmanyam Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Bruce Allan Cc: PJ Waskiewicz Cc: John Ronciak Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_hw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 9d6edf3e73f..d04eef53571 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -144,6 +144,8 @@ static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer); static u8 e1000_calculate_mng_checksum(char *buffer, u32 length); static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex); static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw); +static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); /* IGP cable length table */ static const @@ -168,6 +170,8 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] = 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, 124}; +static DEFINE_SPINLOCK(e1000_eeprom_lock); + /****************************************************************************** * Set the phy type member in the hw struct. * @@ -4903,6 +4907,15 @@ static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw) * words - number of words to read *****************************************************************************/ s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + s32 ret; + spin_lock(&e1000_eeprom_lock); + ret = e1000_do_read_eeprom(hw, offset, words, data); + spin_unlock(&e1000_eeprom_lock); + return ret; +} + +static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_eeprom_info *eeprom = &hw->eeprom; u32 i = 0; @@ -5235,6 +5248,16 @@ s32 e1000_update_eeprom_checksum(struct e1000_hw *hw) * EEPROM will most likely contain an invalid checksum. *****************************************************************************/ s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + s32 ret; + spin_lock(&e1000_eeprom_lock); + ret = e1000_do_write_eeprom(hw, offset, words, data); + spin_unlock(&e1000_eeprom_lock); + return ret; +} + + +static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_eeprom_info *eeprom = &hw->eeprom; s32 status = 0; -- GitLab From e7272403d2f9be3dbb7cc185fcc390e781b1af6b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 8 Aug 2008 00:18:04 +0200 Subject: [PATCH 1997/5416] e100: Use pci_pme_active to clear PME_Status and disable PME# Currently e100 uses pci_enable_wake() to clear pending wake-up events and disable PME# during intitialization, but that function is not suitable for this purpose, because it immediately returns error code if device_may_wakeup() returns false for given device. Make e100 use pci_pme_active(), which carries out exactly the required operations, instead. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/net/e100.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 453115acaad..5cf78d612c4 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2738,9 +2738,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->flags |= wol_magic; /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); + pci_pme_active(pdev, false); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) { -- GitLab From 9744197c3d7b329590c2be33ad7b17409bd798fe Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 19 Sep 2008 11:49:54 +1000 Subject: [PATCH 1998/5416] md: Don't wait UNINTERRUPTIBLE for other resync to finish When two md arrays share some block device (e.g each uses different partitions on the one device), a resync of one array will wait for the resync on the other to finish. This can be a long time and as it currently waits TASK_UNINTERRUPTIBLE, the softlockup code notices and complains. So use TASK_INTERRUPTIBLE instead and make sure to flush signals before calling schedule. Signed-off-by: NeilBrown --- drivers/md/md.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4790c83d78d..deeac4b4417 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5761,7 +5761,11 @@ void md_do_sync(mddev_t *mddev) * time 'round when curr_resync == 2 */ continue; - prepare_to_wait(&resync_wait, &wq, TASK_UNINTERRUPTIBLE); + /* We need to wait 'interruptible' so as not to + * contribute to the load average, and not to + * be caught by 'softlockup' + */ + prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); if (!kthread_should_stop() && mddev2->curr_resync >= mddev->curr_resync) { printk(KERN_INFO "md: delaying %s of %s" @@ -5769,6 +5773,8 @@ void md_do_sync(mddev_t *mddev) " share one or more physical units)\n", desc, mdname(mddev), mdname(mddev2)); mddev_put(mddev2); + if (signal_pending(current)) + flush_signals(current); schedule(); finish_wait(&resync_wait, &wq); goto try_again; -- GitLab From 170e7108a368c52df1ec466966fd1db6e45a7ad2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 02:58:50 +0200 Subject: [PATCH 1999/5416] mv643xx_eth: fix receive checksumming We have to explicitly tell the hardware to include the pseudo-header when doing receive checksumming, otherwise hardware checksumming will fail for every received packet and we'll end up setting CHECKSUM_NONE on every received packet. While we're at it, when skb->ip_summed is set to CHECKSUM_UNNECESSARY on received packets, skb->csum is supposed to be undefined, and thus there is no need to set it. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 408827de7d3..94c13be292a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -546,11 +546,8 @@ static int rxq_process(struct rx_queue *rxq, int budget) */ skb_put(skb, byte_cnt - 2 - 4); - if (cmd_sts & LAYER_4_CHECKSUM_OK) { + if (cmd_sts & LAYER_4_CHECKSUM_OK) skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->csum = htons( - (cmd_sts & 0x0007fff8) >> 3); - } skb->protocol = eth_type_trans(skb, mp->dev); netif_receive_skb(skb); } @@ -1994,9 +1991,10 @@ static void port_start(struct mv643xx_eth_private *mp) /* * Receive all unmatched unicast, TCP, UDP, BPDU and broadcast - * frames to RX queue #0. + * frames to RX queue #0, and include the pseudo-header when + * calculating receive checksums. */ - wrl(mp, PORT_CONFIG(mp->port_num), 0x00000000); + wrl(mp, PORT_CONFIG(mp->port_num), 0x02000000); /* * Treat BPDUs as normal multicasts, and disable partition mode. -- GitLab From 4df89bd5a5fc33860f15f5f001a78f2b3f150725 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 04:05:00 +0200 Subject: [PATCH 2000/5416] mv643xx_eth: deal with unexpected ethernet header sizes When the IP header doesn't start 14, 18, 22 or 26 bytes into the packet (which are the only four cases that the hardware can deal with if asked to do IP checksumming on transmit), invoke the software checksum helper instead of letting the packet go out with a corrupt checksum inserted into the packet in the wrong place. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 95 +++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 94c13be292a..9522c449cce 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -699,79 +699,74 @@ static inline __be16 sum16_as_be(__sum16 sum) return (__force __be16)sum; } -static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) +static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) { struct mv643xx_eth_private *mp = txq_to_mp(txq); int nr_frags = skb_shinfo(skb)->nr_frags; int tx_index; struct tx_desc *desc; u32 cmd_sts; + u16 l4i_chk; int length; cmd_sts = TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA; - - tx_index = txq_alloc_desc_index(txq); - desc = &txq->tx_desc_area[tx_index]; - - if (nr_frags) { - txq_submit_frag_skb(txq, skb); - length = skb_headlen(skb); - } else { - cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; - length = skb->len; - } - - desc->byte_cnt = length; - desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + l4i_chk = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) { - int mac_hdr_len; + int tag_bytes; BUG_ON(skb->protocol != htons(ETH_P_IP) && skb->protocol != htons(ETH_P_8021Q)); - cmd_sts |= GEN_TCP_UDP_CHECKSUM | - GEN_IP_V4_CHECKSUM | - ip_hdr(skb)->ihl << TX_IHL_SHIFT; + tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN; + if (unlikely(tag_bytes & ~12)) { + if (skb_checksum_help(skb) == 0) + goto no_csum; + kfree_skb(skb); + return 1; + } - mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; - switch (mac_hdr_len - ETH_HLEN) { - case 0: - break; - case 4: - cmd_sts |= MAC_HDR_EXTRA_4_BYTES; - break; - case 8: - cmd_sts |= MAC_HDR_EXTRA_8_BYTES; - break; - case 12: + if (tag_bytes & 4) cmd_sts |= MAC_HDR_EXTRA_4_BYTES; + if (tag_bytes & 8) cmd_sts |= MAC_HDR_EXTRA_8_BYTES; - break; - default: - if (net_ratelimit()) - dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev, - "mac header length is %d?!\n", mac_hdr_len); - break; - } + + cmd_sts |= GEN_TCP_UDP_CHECKSUM | + GEN_IP_V4_CHECKSUM | + ip_hdr(skb)->ihl << TX_IHL_SHIFT; switch (ip_hdr(skb)->protocol) { case IPPROTO_UDP: cmd_sts |= UDP_FRAME; - desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); + l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); break; case IPPROTO_TCP: - desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); + l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); break; default: BUG(); } } else { +no_csum: /* Errata BTS #50, IHL must be 5 if no HW checksum */ cmd_sts |= 5 << TX_IHL_SHIFT; - desc->l4i_chk = 0; } + tx_index = txq_alloc_desc_index(txq); + desc = &txq->tx_desc_area[tx_index]; + + if (nr_frags) { + txq_submit_frag_skb(txq, skb); + length = skb_headlen(skb); + } else { + cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; + length = skb->len; + } + + desc->l4i_chk = l4i_chk; + desc->byte_cnt = length; + desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + __skb_queue_tail(&txq->tx_skb, skb); /* ensure all other descriptors are written before first cmd_sts */ @@ -786,6 +781,8 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) txq_enable(txq); txq->tx_desc_count += nr_frags + 1; + + return 0; } static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) @@ -794,7 +791,6 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) int queue; struct tx_queue *txq; struct netdev_queue *nq; - int entries_left; queue = skb_get_queue_mapping(skb); txq = mp->txq + queue; @@ -815,14 +811,17 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - txq_submit_skb(txq, skb); - txq->tx_bytes += skb->len; - txq->tx_packets++; - dev->trans_start = jiffies; + if (!txq_submit_skb(txq, skb)) { + int entries_left; + + txq->tx_bytes += skb->len; + txq->tx_packets++; + dev->trans_start = jiffies; - entries_left = txq->tx_ring_size - txq->tx_desc_count; - if (entries_left < MAX_SKB_FRAGS + 1) - netif_tx_stop_queue(nq); + entries_left = txq->tx_ring_size - txq->tx_desc_count; + if (entries_left < MAX_SKB_FRAGS + 1) + netif_tx_stop_queue(nq); + } return NETDEV_TX_OK; } -- GitLab From 4ff3495a51c7226376d8013c5742d1d5e54876a7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 05:04:57 +0200 Subject: [PATCH 2001/5416] mv643xx_eth: enforce frequent hardware statistics polling If we don't poll the hardware statistics counters at least once every ~34 seconds, overflow might occur without us noticing. So, set up a timer to poll the statistics counters at least once every 30 seconds. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9522c449cce..d0ecc440aac 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -356,7 +356,10 @@ struct mv643xx_eth_private { int phy_addr; + struct timer_list mib_counters_timer; + spinlock_t mib_counters_lock; struct mib_counters mib_counters; + struct work_struct tx_timeout_task; struct mii_if_info mii; @@ -1176,6 +1179,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) { struct mib_counters *p = &mp->mib_counters; + spin_lock(&mp->mib_counters_lock); p->good_octets_received += mib_read(mp, 0x00); p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; p->bad_octets_received += mib_read(mp, 0x08); @@ -1208,6 +1212,16 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->bad_crc_event += mib_read(mp, 0x74); p->collision += mib_read(mp, 0x78); p->late_collision += mib_read(mp, 0x7c); + spin_unlock(&mp->mib_counters_lock); + + mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); +} + +static void mib_counters_timer_wrapper(unsigned long _mp) +{ + struct mv643xx_eth_private *mp = (void *)_mp; + + mib_counters_update(mp); } @@ -2148,6 +2162,8 @@ static int mv643xx_eth_stop(struct net_device *dev) wrl(mp, INT_MASK(mp->port_num), 0x00000000); rdl(mp, INT_MASK(mp->port_num)); + del_timer_sync(&mp->mib_counters_timer); + napi_disable(&mp->napi); del_timer_sync(&mp->rx_oom); @@ -2625,6 +2641,19 @@ static int mv643xx_eth_probe(struct platform_device *pdev) } init_pscr(mp, pd->speed, pd->duplex); + + mib_counters_clear(mp); + + init_timer(&mp->mib_counters_timer); + mp->mib_counters_timer.data = (unsigned long)mp; + mp->mib_counters_timer.function = mib_counters_timer_wrapper; + mp->mib_counters_timer.expires = jiffies + 30 * HZ; + add_timer(&mp->mib_counters_timer); + + spin_lock_init(&mp->mib_counters_lock); + + INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); + netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 128); init_timer(&mp->rx_oom); -- GitLab From 4fd5f812c23c7deee6425f4a318e85c317cd1d6c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 13:08:46 +0200 Subject: [PATCH 2002/5416] phylib: allow incremental scanning of an mii bus This patch splits the bus scanning code in mdiobus_register() off into a separate function, and makes this function available for calling from external code. This allows incrementally scanning an mii bus, e.g. as information about which addresses are 'safe' to scan becomes available. Signed-off-by: Lennert Buytenhek Acked-by: Andy Fleming --- drivers/net/phy/mdio_bus.c | 89 ++++++++++++++++++++------------------ include/linux/phy.h | 2 + 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 94e0b7ed76f..e7508c10887 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -60,49 +60,14 @@ int mdiobus_register(struct mii_bus *bus) bus->reset(bus); for (i = 0; i < PHY_MAX_ADDR; i++) { - struct phy_device *phydev; + bus->phy_map[i] = NULL; + if ((bus->phy_mask & (1 << i)) == 0) { + struct phy_device *phydev; - if (bus->phy_mask & (1 << i)) { - bus->phy_map[i] = NULL; - continue; + phydev = mdiobus_scan(bus, i); + if (IS_ERR(phydev)) + err = PTR_ERR(phydev); } - - phydev = get_phy_device(bus, i); - - if (IS_ERR(phydev)) - return PTR_ERR(phydev); - - /* There's a PHY at this address - * We need to set: - * 1) IRQ - * 2) bus_id - * 3) parent - * 4) bus - * 5) mii_bus - * And, we need to register it */ - if (phydev) { - phydev->irq = bus->irq[i]; - - phydev->dev.parent = bus->dev; - phydev->dev.bus = &mdio_bus_type; - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); - - phydev->bus = bus; - - /* Run all of the fixups for this PHY */ - phy_scan_fixups(phydev); - - err = device_register(&phydev->dev); - - if (err) { - printk(KERN_ERR "phy %d failed to register\n", - i); - phy_device_free(phydev); - phydev = NULL; - } - } - - bus->phy_map[i] = phydev; } pr_info("%s: probed\n", bus->name); @@ -122,6 +87,48 @@ void mdiobus_unregister(struct mii_bus *bus) } EXPORT_SYMBOL(mdiobus_unregister); +struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) +{ + struct phy_device *phydev; + int err; + + phydev = get_phy_device(bus, addr); + if (IS_ERR(phydev) || phydev == NULL) + return phydev; + + /* There's a PHY at this address + * We need to set: + * 1) IRQ + * 2) bus_id + * 3) parent + * 4) bus + * 5) mii_bus + * And, we need to register it */ + + phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; + + phydev->dev.parent = bus->dev; + phydev->dev.bus = &mdio_bus_type; + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr); + + phydev->bus = bus; + + /* Run all of the fixups for this PHY */ + phy_scan_fixups(phydev); + + err = device_register(&phydev->dev); + if (err) { + printk(KERN_ERR "phy %d failed to register\n", addr); + phy_device_free(phydev); + phydev = NULL; + } + + bus->phy_map[addr] = phydev; + + return phydev; +} +EXPORT_SYMBOL(mdiobus_scan); + /** * mdio_bus_match - determine if given PHY driver supports the given PHY device * @dev: target PHY device diff --git a/include/linux/phy.h b/include/linux/phy.h index 7224c4099a2..5f170f5b1a3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -410,6 +410,8 @@ int phy_start_aneg(struct phy_device *phydev); int mdiobus_register(struct mii_bus *bus); void mdiobus_unregister(struct mii_bus *bus); +struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); + void phy_sanitize_settings(struct phy_device *phydev); int phy_stop_interrupts(struct phy_device *phydev); int phy_enable_interrupts(struct phy_device *phydev); -- GitLab From 279b0bbba2bb647348ad90e183b3960aa99eccfd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 18 Sep 2008 23:55:27 -0700 Subject: [PATCH 2003/5416] x86: fix arch/x86/kernel/cpu/mtrr/main.c warning fix this warning reported by Andrew Morton: > arch/x86/kernel/cpu/mtrr/main.c: In function 'mtrr_bp_init': > arch/x86/kernel/cpu/mtrr/main.c:1170: warning: 'extra_remove_base' may be used uninitialized in this function the warning is bogus but the logic that prevents uninitialized use is a bit convoluted so simplify it all. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b117d7f8a56..8a7c79234be 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1218,11 +1218,10 @@ static int __init mtrr_cleanup(unsigned address_bits) memset(range, 0, sizeof(range)); extra_remove_size = 0; - if (mtrr_tom2) { - extra_remove_base = 1 << (32 - PAGE_SHIFT); + extra_remove_base = 1 << (32 - PAGE_SHIFT); + if (mtrr_tom2) extra_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; - } nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, extra_remove_size); range_sums = sum_ranges(range, nr_range); -- GitLab From 07a2c01a0c2a0cb4581a67d50d4f17cb4d2457c4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 19 Sep 2008 02:02:05 +0900 Subject: [PATCH 2004/5416] convert swiotlb to use dma_get_mask swiotlb can use dma_get_mask() instead of the homegrown function. Signed-off-by: FUJITA Tomonori Cc: tony.luck@intel.com Signed-off-by: Ingo Molnar --- include/linux/dma-mapping.h | 2 +- lib/swiotlb.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 0dba7433af1..ba9114ec5d3 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -65,7 +65,7 @@ static inline int is_buffer_dma_capable(u64 mask, dma_addr_t addr, size_t size) static inline u64 dma_get_mask(struct device *dev) { - if (dev->dma_mask && *dev->dma_mask) + if (dev && dev->dma_mask && *dev->dma_mask) return *dev->dma_mask; return DMA_32BIT_MASK; } diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 240a67c2c97..f8eebd48914 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -276,11 +276,7 @@ cleanup1: static int address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size) { - dma_addr_t mask = 0xffffffff; - /* If the device has a mask, use it, otherwise default to 32 bits */ - if (hwdev && hwdev->dma_mask) - mask = *hwdev->dma_mask; - return !is_buffer_dma_capable(mask, addr, size); + return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size); } static int is_swiotlb_buffer(char *addr) -- GitLab From 3b7ecb5d2ffde82efd1b1bcc6780dc8a019acf02 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 19 Sep 2008 01:56:23 -0700 Subject: [PATCH 2005/5416] softlockup: Documentation/sysctl/kernel.txt: fix softlockup_thresh description - s/s/seconds/ - s/10 seconds/60 seconds/ - Mention the zero-disables-it feature. Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- Documentation/sysctl/kernel.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 276a7e63782..e1ff0d920a5 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -351,9 +351,10 @@ kernel. This value defaults to SHMMAX. softlockup_thresh: -This value can be used to lower the softlockup tolerance -threshold. The default threshold is 10s. If a cpu is locked up -for 10s, the kernel complains. Valid values are 1-60s. +This value can be used to lower the softlockup tolerance threshold. The +default threshold is 60 seconds. If a cpu is locked up for 60 seconds, +the kernel complains. Valid values are 1-60 seconds. Setting this +tunable to zero will disable the softlockup detection altogether. ============================================================== -- GitLab From dbcc112e3b5367e81a845b082933506b0ff1d1e2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 15:04:26 +0200 Subject: [PATCH 2006/5416] AMD IOMMU: check for invalid device pointers Currently AMD IOMMU code triggers a BUG_ON if NULL is passed as the device. This is inconsistent with other IOMMU implementations. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 43 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 01c68c38840..695e0fc41b1 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -645,6 +645,18 @@ static void set_device_domain(struct amd_iommu *iommu, * *****************************************************************************/ +/* + * This function checks if the driver got a valid device from the caller to + * avoid dereferencing invalid pointers. + */ +static bool check_device(struct device *dev) +{ + if (!dev || !dev->dma_mask) + return false; + + return true; +} + /* * In the dma_ops path we only have the struct device. This function * finds the corresponding IOMMU, the protection domain and the @@ -661,18 +673,19 @@ static int get_device_resources(struct device *dev, struct pci_dev *pcidev; u16 _bdf; - BUG_ON(!dev || dev->bus != &pci_bus_type || !dev->dma_mask); + *iommu = NULL; + *domain = NULL; + *bdf = 0xffff; + + if (dev->bus != &pci_bus_type) + return 0; pcidev = to_pci_dev(dev); _bdf = calc_devid(pcidev->bus->number, pcidev->devfn); /* device not translated by any IOMMU in the system? */ - if (_bdf > amd_iommu_last_bdf) { - *iommu = NULL; - *domain = NULL; - *bdf = 0xffff; + if (_bdf > amd_iommu_last_bdf) return 0; - } *bdf = amd_iommu_alias_table[_bdf]; @@ -826,6 +839,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, u16 devid; dma_addr_t addr; + if (!check_device(dev)) + return bad_dma_address; + get_device_resources(dev, &iommu, &domain, &devid); if (iommu == NULL || domain == NULL) @@ -860,7 +876,8 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, struct protection_domain *domain; u16 devid; - if (!get_device_resources(dev, &iommu, &domain, &devid)) + if (!check_device(dev) || + !get_device_resources(dev, &iommu, &domain, &devid)) /* device not handled by any AMD IOMMU */ return; @@ -910,6 +927,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, phys_addr_t paddr; int mapped_elems = 0; + if (!check_device(dev)) + return 0; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) @@ -967,7 +987,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, u16 devid; int i; - if (!get_device_resources(dev, &iommu, &domain, &devid)) + if (!check_device(dev) || + !get_device_resources(dev, &iommu, &domain, &devid)) return; spin_lock_irqsave(&domain->lock, flags); @@ -999,6 +1020,9 @@ static void *alloc_coherent(struct device *dev, size_t size, u16 devid; phys_addr_t paddr; + if (!check_device(dev)) + return NULL; + virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; @@ -1047,6 +1071,9 @@ static void free_coherent(struct device *dev, size_t size, struct protection_domain *domain; u16 devid; + if (!check_device(dev)) + return; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) -- GitLab From 270cab2426cdc6307725e4f1f46ecf8ab8e69193 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 15:49:46 +0200 Subject: [PATCH 2007/5416] AMD IOMMU: move TLB flushing to the map/unmap helper functions This patch moves the invocation of the flushing functions to the map/unmap helpers because its common code in all dma_ops relevant mapping/unmapping code. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 695e0fc41b1..691e023695a 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -795,6 +795,9 @@ static dma_addr_t __map_single(struct device *dev, } address += offset; + if (unlikely(iommu_has_npcache(iommu))) + iommu_flush_pages(iommu, dma_dom->domain.id, address, size); + out: return address; } @@ -825,6 +828,8 @@ static void __unmap_single(struct amd_iommu *iommu, } dma_ops_free_addresses(dma_dom, dma_addr, pages); + + iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); } /* @@ -853,9 +858,6 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, if (addr == bad_dma_address) goto out; - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -885,8 +887,6 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, __unmap_single(iommu, domain->priv, dma_addr, size, dir); - iommu_flush_pages(iommu, domain->id, dma_addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -948,9 +948,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, mapped_elems++; } else goto unmap; - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, s->dma_address, - s->dma_length); } if (iommu->need_sync) @@ -996,8 +993,6 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, for_each_sg(sglist, s, nelems, i) { __unmap_single(iommu, domain->priv, s->dma_address, s->dma_length, dir); - iommu_flush_pages(iommu, domain->id, s->dma_address, - s->dma_length); s->dma_address = s->dma_length = 0; } @@ -1048,9 +1043,6 @@ static void *alloc_coherent(struct device *dev, size_t size, goto out; } - if (iommu_has_npcache(iommu)) - iommu_flush_pages(iommu, domain->id, *dma_addr, size); - if (iommu->need_sync) iommu_completion_wait(iommu); @@ -1082,7 +1074,6 @@ static void free_coherent(struct device *dev, size_t size, spin_lock_irqsave(&domain->lock, flags); __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); - iommu_flush_pages(iommu, domain->id, dma_addr, size); if (iommu->need_sync) iommu_completion_wait(iommu); -- GitLab From 2842e5bf3115193f05dc9dac20f940e7abf44c1a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 18 Sep 2008 15:23:43 +0200 Subject: [PATCH 2008/5416] x86: move GART TLB flushing options to generic code The GART currently implements the iommu=[no]fullflush command line parameters which influence its IO/TLB flushing strategy. This patch makes these parameters generic so that they can be used by the AMD IOMMU too. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 4 ++++ Documentation/x86/x86_64/boot-options.txt | 2 -- arch/x86/kernel/pci-dma.c | 13 +++++++++++++ arch/x86/kernel/pci-gart_64.c | 13 ------------- include/asm-x86/iommu.h | 1 + 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1150444a21a..40066ceb48f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -893,6 +893,10 @@ and is between 256 and 4096 characters. It is defined in the file nomerge forcesac soft + fullflush + Flush IO/TLB at every deallocation + nofullflush + Flush IO/TLB only when addresses are reused (default) intel_iommu= [DMAR] Intel IOMMU driver (DMAR) option diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt index b0c7b6c4abd..c83c8e4bc8e 100644 --- a/Documentation/x86/x86_64/boot-options.txt +++ b/Documentation/x86/x86_64/boot-options.txt @@ -233,8 +233,6 @@ IOMMU (input/output memory management unit) iommu options only relevant to the AMD GART hardware IOMMU: Set the size of the remapping area in bytes. allowed Overwrite iommu off workarounds for specific chipsets. - fullflush Flush IOMMU on each allocation (default). - nofullflush Don't use IOMMU fullflush. leak Turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on). Default number of leak pages is 20. diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0a1408abcc6..d2f2c0158dc 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -16,6 +16,15 @@ EXPORT_SYMBOL(dma_ops); static int iommu_sac_force __read_mostly; +/* + * If this is disabled the IOMMU will use an optimized flushing strategy + * of only flushing when an mapping is reused. With it true the GART is + * flushed for every mapping. Problem is that doing the lazy flush seems + * to trigger bugs with some popular PCI cards, in particular 3ware (but + * has been also also seen with Qlogic at least). + */ +int iommu_fullflush; + #ifdef CONFIG_IOMMU_DEBUG int panic_on_overflow __read_mostly = 1; int force_iommu __read_mostly = 1; @@ -171,6 +180,10 @@ static __init int iommu_setup(char *p) } if (!strncmp(p, "nomerge", 7)) iommu_merge = 0; + if (!strncmp(p, "fullflush", 8)) + iommu_fullflush = 1; + if (!strncmp(p, "nofullflush", 11)) + iommu_fullflush = 0; if (!strncmp(p, "forcesac", 8)) iommu_sac_force = 1; if (!strncmp(p, "allowdac", 8)) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 9739d568209..508ef470b27 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -45,15 +45,6 @@ static unsigned long iommu_pages; /* .. and in pages */ static u32 *iommu_gatt_base; /* Remapping table */ -/* - * If this is disabled the IOMMU will use an optimized flushing strategy - * of only flushing when an mapping is reused. With it true the GART is - * flushed for every mapping. Problem is that doing the lazy flush seems - * to trigger bugs with some popular PCI cards, in particular 3ware (but - * has been also also seen with Qlogic at least). - */ -int iommu_fullflush = 1; - /* Allocation bitmap for the remapping area: */ static DEFINE_SPINLOCK(iommu_bitmap_lock); /* Guarded by iommu_bitmap_lock: */ @@ -901,10 +892,6 @@ void __init gart_parse_options(char *p) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - if (!strncmp(p, "fullflush", 8)) - iommu_fullflush = 1; - if (!strncmp(p, "nofullflush", 11)) - iommu_fullflush = 0; if (!strncmp(p, "noagp", 5)) no_agp = 1; if (!strncmp(p, "noaperture", 10)) diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h index 621a1af94c4..67b2fd56c6d 100644 --- a/include/asm-x86/iommu.h +++ b/include/asm-x86/iommu.h @@ -7,6 +7,7 @@ extern struct dma_mapping_ops nommu_dma_ops; extern int force_iommu, no_iommu; extern int iommu_detected; extern int dmar_disabled; +extern int iommu_fullflush; extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len); -- GitLab From 1c65577398589bb44ab0980f9b9d30804b48a5db Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 18:40:05 +0200 Subject: [PATCH 2009/5416] AMD IOMMU: implement lazy IO/TLB flushing The IO/TLB flushing on every unmaping operation is the most expensive part in AMD IOMMU code and not strictly necessary. It is sufficient to do the flush before any entries are reused. This is patch implements lazy IO/TLB flushing which does exactly this. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 26 ++++++++++++++++++++++---- arch/x86/kernel/amd_iommu_init.c | 7 ++++++- include/asm-x86/amd_iommu_types.h | 3 +++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 691e023695a..679f2a8e22e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -203,6 +203,14 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid, return 0; } +/* Flush the whole IO/TLB for a given protection domain */ +static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid) +{ + u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; + + iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1); +} + /**************************************************************************** * * The functions below are used the create the page table mappings for @@ -386,14 +394,18 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev, PAGE_SIZE) >> PAGE_SHIFT; limit = limit < size ? limit : size; - if (dom->next_bit >= limit) + if (dom->next_bit >= limit) { dom->next_bit = 0; + dom->need_flush = true; + } address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages, 0 , boundary_size, 0); - if (address == -1) + if (address == -1) { address = iommu_area_alloc(dom->bitmap, limit, 0, pages, 0, boundary_size, 0); + dom->need_flush = true; + } if (likely(address != -1)) { dom->next_bit = address + pages; @@ -553,6 +565,8 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, dma_dom->bitmap[0] = 1; dma_dom->next_bit = 0; + dma_dom->need_flush = false; + /* Intialize the exclusion range if necessary */ if (iommu->exclusion_start && iommu->exclusion_start < dma_dom->aperture_size) { @@ -795,7 +809,10 @@ static dma_addr_t __map_single(struct device *dev, } address += offset; - if (unlikely(iommu_has_npcache(iommu))) + if (unlikely(dma_dom->need_flush && !iommu_fullflush)) { + iommu_flush_tlb(iommu, dma_dom->domain.id); + dma_dom->need_flush = false; + } else if (unlikely(iommu_has_npcache(iommu))) iommu_flush_pages(iommu, dma_dom->domain.id, address, size); out: @@ -829,7 +846,8 @@ static void __unmap_single(struct amd_iommu *iommu, dma_ops_free_addresses(dma_dom, dma_addr, pages); - iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); + if (iommu_fullflush) + iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); } /* diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index a69cc0f5204..f2fa8dc81be 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -995,6 +995,11 @@ int __init amd_iommu_init(void) else printk("disabled\n"); + if (iommu_fullflush) + printk(KERN_INFO "AMD IOMMU: IO/TLB flush on unmap enabled\n"); + else + printk(KERN_INFO "AMD IOMMU: Lazy IO/TLB flushing enabled\n"); + out: return ret; @@ -1057,7 +1062,7 @@ void __init amd_iommu_detect(void) static int __init parse_amd_iommu_options(char *str) { for (; *str; ++str) { - if (strcmp(str, "isolate") == 0) + if (strncmp(str, "isolate", 7) == 0) amd_iommu_isolate = 1; } diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index dcc81206739..dcc472445ff 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -196,6 +196,9 @@ struct dma_ops_domain { * just calculate its address in constant time. */ u64 **pte_pages; + + /* This will be set to true when TLB needs to be flushed */ + bool need_flush; }; /* -- GitLab From 5507eef835c9c941e69d6d96e4b43af23eeb4ac9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 19:01:02 +0200 Subject: [PATCH 2010/5416] AMD IOMMU: add branch hints to completion wait checks This patch adds branch hints to the cecks if a completion_wait is necessary. The completion_waits in the mapping paths are unlikly because they will only happen on software implementations of AMD IOMMU which don't exists today or with lazy IO/TLB flushing when the allocator wraps around the address space. With lazy IO/TLB flushing the completion_wait in the unmapping path is unlikely too. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 679f2a8e22e..d743aa0adcc 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -876,7 +876,7 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, if (addr == bad_dma_address) goto out; - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -905,7 +905,7 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr, __unmap_single(iommu, domain->priv, dma_addr, size, dir); - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); @@ -968,7 +968,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, goto unmap; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -1014,7 +1014,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, s->dma_address = s->dma_length = 0; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); @@ -1061,7 +1061,7 @@ static void *alloc_coherent(struct device *dev, size_t size, goto out; } - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); out: @@ -1093,7 +1093,7 @@ static void free_coherent(struct device *dev, size_t size, __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); - if (iommu->need_sync) + if (unlikely(iommu->need_sync)) iommu_completion_wait(iommu); spin_unlock_irqrestore(&domain->lock, flags); -- GitLab From 6d4f343f84993eb0d5864c0823dc9babd171a33a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 4 Sep 2008 19:18:02 +0200 Subject: [PATCH 2011/5416] AMD IOMMU: align alloc_coherent addresses properly The API definition for dma_alloc_coherent states that the bus address has to be aligned to the next power of 2 boundary greater than the allocation size. This is violated by AMD IOMMU so far and this patch fixes it. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index d743aa0adcc..15792ed082e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -383,7 +383,8 @@ static unsigned long dma_mask_to_pages(unsigned long mask) */ static unsigned long dma_ops_alloc_addresses(struct device *dev, struct dma_ops_domain *dom, - unsigned int pages) + unsigned int pages, + unsigned long align_mask) { unsigned long limit = dma_mask_to_pages(*dev->dma_mask); unsigned long address; @@ -400,10 +401,10 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev, } address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages, - 0 , boundary_size, 0); + 0 , boundary_size, align_mask); if (address == -1) { address = iommu_area_alloc(dom->bitmap, limit, 0, pages, - 0, boundary_size, 0); + 0, boundary_size, align_mask); dom->need_flush = true; } @@ -787,17 +788,22 @@ static dma_addr_t __map_single(struct device *dev, struct dma_ops_domain *dma_dom, phys_addr_t paddr, size_t size, - int dir) + int dir, + bool align) { dma_addr_t offset = paddr & ~PAGE_MASK; dma_addr_t address, start; unsigned int pages; + unsigned long align_mask = 0; int i; pages = iommu_num_pages(paddr, size); paddr &= PAGE_MASK; - address = dma_ops_alloc_addresses(dev, dma_dom, pages); + if (align) + align_mask = (1UL << get_order(size)) - 1; + + address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask); if (unlikely(address == bad_dma_address)) goto out; @@ -872,7 +878,7 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, return (dma_addr_t)paddr; spin_lock_irqsave(&domain->lock, flags); - addr = __map_single(dev, iommu, domain->priv, paddr, size, dir); + addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false); if (addr == bad_dma_address) goto out; @@ -959,7 +965,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, paddr = sg_phys(s); s->dma_address = __map_single(dev, iommu, domain->priv, - paddr, s->length, dir); + paddr, s->length, dir, false); if (s->dma_address) { s->dma_length = s->length; @@ -1053,7 +1059,7 @@ static void *alloc_coherent(struct device *dev, size_t size, spin_lock_irqsave(&domain->lock, flags); *dma_addr = __map_single(dev, iommu, domain->priv, paddr, - size, DMA_BIDIRECTIONAL); + size, DMA_BIDIRECTIONAL, true); if (*dma_addr == bad_dma_address) { free_pages((unsigned long)virt_addr, get_order(size)); -- GitLab From 335503e57b6b8de04cec5d27eb2c3d09ff98905b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 5 Sep 2008 14:29:07 +0200 Subject: [PATCH 2012/5416] AMD IOMMU: add event buffer allocation This patch adds the allocation of a event buffer for each AMD IOMMU in the system. The hardware will log events like device page faults or other errors to this buffer once this is enabled. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 29 +++++++++++++++++++++++++++++ include/asm-x86/amd_iommu_types.h | 9 +++++++++ 2 files changed, 38 insertions(+) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index f2fa8dc81be..41ce8d5d626 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -417,6 +417,30 @@ static void __init free_command_buffer(struct amd_iommu *iommu) free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); } +/* allocates the memory where the IOMMU will log its events to */ +static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) +{ + u64 entry; + iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(EVT_BUFFER_SIZE)); + + if (iommu->evt_buf == NULL) + return NULL; + + entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK; + memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET, + &entry, sizeof(entry)); + + iommu->evt_buf_size = EVT_BUFFER_SIZE; + + return iommu->evt_buf; +} + +static void __init free_event_buffer(struct amd_iommu *iommu) +{ + free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE)); +} + /* sets a specific bit in the device table entry. */ static void set_dev_entry_bit(u16 devid, u8 bit) { @@ -622,6 +646,7 @@ static int __init init_iommu_devices(struct amd_iommu *iommu) static void __init free_iommu_one(struct amd_iommu *iommu) { free_command_buffer(iommu); + free_event_buffer(iommu); iommu_unmap_mmio_space(iommu); } @@ -661,6 +686,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->cmd_buf) return -ENOMEM; + iommu->evt_buf = alloc_event_buffer(iommu); + if (!iommu->evt_buf) + return -ENOMEM; + init_iommu_from_pci(iommu); init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index dcc472445ff..8b8cd0c60b3 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -116,6 +116,10 @@ #define MMIO_CMD_SIZE_SHIFT 56 #define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT) +/* constants for event buffer handling */ +#define EVT_BUFFER_SIZE 8192 /* 512 entries */ +#define EVT_LEN_MASK (0x9ULL << 56) + #define PAGE_MODE_1_LEVEL 0x01 #define PAGE_MODE_2_LEVEL 0x02 #define PAGE_MODE_3_LEVEL 0x03 @@ -243,6 +247,11 @@ struct amd_iommu { /* size of command buffer */ u32 cmd_buf_size; + /* event buffer virtual address */ + u8 *evt_buf; + /* size of event buffer */ + u32 evt_buf_size; + /* if one, we need to send a completion wait command */ int need_sync; -- GitLab From ee893c24edb8ebab9a3fb66566855572579ad616 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 8 Sep 2008 14:48:04 +0200 Subject: [PATCH 2013/5416] AMD IOMMU: save pci segment from ACPI tables This patch adds the pci_seg field to the amd_iommu structure and fills it with the corresponding value from the ACPI table. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 1 + include/asm-x86/amd_iommu_types.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 41ce8d5d626..b50234ef91e 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -676,6 +676,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) */ iommu->devid = h->devid; iommu->cap_ptr = h->cap_ptr; + iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys); if (!iommu->mmio_base) diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index 8b8cd0c60b3..20814b85bbc 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -232,6 +232,9 @@ struct amd_iommu { /* capabilities of that IOMMU read from ACPI */ u32 cap; + /* pci domain of this IOMMU */ + u16 pci_seg; + /* first device this IOMMU handles. read from PCI */ u16 first_device; /* last device this IOMMU handles. read from PCI */ -- GitLab From 3eaf28a1cd2686aaa185b54d5a5e18e91b41f7f2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 8 Sep 2008 15:55:10 +0200 Subject: [PATCH 2014/5416] AMD IOMMU: save pci_dev instead of devid We need the pci_dev later anyways to enable MSI for the IOMMU hardware. So remove the devid pointing to the BDF and replace it with the pci_dev structure where the IOMMU is implemented. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 25 ++++++++++++++++--------- include/asm-x86/amd_iommu_types.h | 5 +++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index b50234ef91e..a7eb89d8923 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -242,9 +242,12 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) /* Function to enable the hardware */ void __init iommu_enable(struct amd_iommu *iommu) { - printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at "); - print_devid(iommu->devid, 0); - printk(" cap 0x%hx\n", iommu->cap_ptr); + printk(KERN_INFO "AMD IOMMU: Enabling IOMMU " + "at %02x:%02x.%x cap 0x%hx\n", + iommu->dev->bus->number, + PCI_SLOT(iommu->dev->devfn), + PCI_FUNC(iommu->dev->devfn), + iommu->cap_ptr); iommu_feature_enable(iommu, CONTROL_IOMMU_EN); } @@ -511,15 +514,14 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) */ static void __init init_iommu_from_pci(struct amd_iommu *iommu) { - int bus = PCI_BUS(iommu->devid); - int dev = PCI_SLOT(iommu->devid); - int fn = PCI_FUNC(iommu->devid); int cap_ptr = iommu->cap_ptr; u32 range; - iommu->cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_CAP_HDR_OFFSET); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, + &iommu->cap); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, + &range); - range = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET); iommu->first_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_FD(range)); iommu->last_device = calc_devid(MMIO_GET_BUS(range), @@ -674,7 +676,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) /* * Copy data from ACPI table entry to the iommu struct */ - iommu->devid = h->devid; + iommu->dev = pci_get_bus_and_slot(PCI_BUS(h->devid), h->devid & 0xff); + if (!iommu->dev) + return 1; + iommu->cap_ptr = h->cap_ptr; iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; @@ -695,6 +700,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); + pci_enable_device(iommu->dev); + return 0; } diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index 20814b85bbc..a5629a21557 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -215,8 +215,9 @@ struct amd_iommu { /* locks the accesses to the hardware */ spinlock_t lock; - /* device id of this IOMMU */ - u16 devid; + /* Pointer to PCI device of this IOMMU */ + struct pci_dev *dev; + /* * Capability pointer. There could be more than one IOMMU per PCI * device function if there are more than one AMD IOMMU capability -- GitLab From a80dc3e0e0dc8393158de317d66ae0f345dc58f9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 16:51:41 +0200 Subject: [PATCH 2015/5416] AMD IOMMU: add MSI interrupt support The AMD IOMMU can generate interrupts for various reasons. This patch adds the basic interrupt enabling infrastructure to the driver. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 + arch/x86/kernel/amd_iommu.c | 11 ++++ arch/x86/kernel/amd_iommu_init.c | 99 ++++++++++++++++++++++++++++++- include/asm-x86/amd_iommu.h | 3 + include/asm-x86/amd_iommu_types.h | 7 +++ 5 files changed, 120 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d132..39fd3f42696 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -553,6 +553,7 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT config AMD_IOMMU bool "AMD IOMMU support" select SWIOTLB + select PCI_MSI depends on X86_64 && PCI && ACPI help With this option you can enable support for AMD IOMMU hardware in diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 15792ed082e..0e494b9d5f2 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -49,6 +49,17 @@ static int iommu_has_npcache(struct amd_iommu *iommu) return iommu->cap & IOMMU_CAP_NPCACHE; } +/**************************************************************************** + * + * Interrupt handling functions + * + ****************************************************************************/ + +irqreturn_t amd_iommu_int_handler(int irq, void *data) +{ + return IRQ_NONE; +} + /**************************************************************************** * * IOMMU command queuing functions diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index a7eb89d8923..14a06464a69 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -515,17 +517,20 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) static void __init init_iommu_from_pci(struct amd_iommu *iommu) { int cap_ptr = iommu->cap_ptr; - u32 range; + u32 range, misc; pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, &iommu->cap); pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, &range); + pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, + &misc); iommu->first_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_FD(range)); iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); + iommu->evt_msi_num = MMIO_MSI_NUM(misc); } /* @@ -696,6 +701,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->evt_buf) return -ENOMEM; + iommu->int_enabled = false; + init_iommu_from_pci(iommu); init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); @@ -741,6 +748,95 @@ static int __init init_iommu_all(struct acpi_table_header *table) return 0; } +/**************************************************************************** + * + * The following functions initialize the MSI interrupts for all IOMMUs + * in the system. Its a bit challenging because there could be multiple + * IOMMUs per PCI BDF but we can call pci_enable_msi(x) only once per + * pci_dev. + * + ****************************************************************************/ + +static int __init iommu_setup_msix(struct amd_iommu *iommu) +{ + struct amd_iommu *curr; + struct msix_entry entries[32]; /* only 32 supported by AMD IOMMU */ + int nvec = 0, i; + + list_for_each_entry(curr, &amd_iommu_list, list) { + if (curr->dev == iommu->dev) { + entries[nvec].entry = curr->evt_msi_num; + entries[nvec].vector = 0; + curr->int_enabled = true; + nvec++; + } + } + + if (pci_enable_msix(iommu->dev, entries, nvec)) { + pci_disable_msix(iommu->dev); + return 1; + } + + for (i = 0; i < nvec; ++i) { + int r = request_irq(entries->vector, amd_iommu_int_handler, + IRQF_SAMPLE_RANDOM, + "AMD IOMMU", + NULL); + if (r) + goto out_free; + } + + return 0; + +out_free: + for (i -= 1; i >= 0; --i) + free_irq(entries->vector, NULL); + + pci_disable_msix(iommu->dev); + + return 1; +} + +static int __init iommu_setup_msi(struct amd_iommu *iommu) +{ + int r; + struct amd_iommu *curr; + + list_for_each_entry(curr, &amd_iommu_list, list) { + if (curr->dev == iommu->dev) + curr->int_enabled = true; + } + + + if (pci_enable_msi(iommu->dev)) + return 1; + + r = request_irq(iommu->dev->irq, amd_iommu_int_handler, + IRQF_SAMPLE_RANDOM, + "AMD IOMMU", + NULL); + + if (r) { + pci_disable_msi(iommu->dev); + return 1; + } + + return 0; +} + +static int __init iommu_init_msi(struct amd_iommu *iommu) +{ + if (iommu->int_enabled) + return 0; + + if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSIX)) + return iommu_setup_msix(iommu); + else if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI)) + return iommu_setup_msi(iommu); + + return 1; +} + /**************************************************************************** * * The next functions belong to the third pass of parsing the ACPI @@ -862,6 +958,7 @@ static void __init enable_iommus(void) list_for_each_entry(iommu, &amd_iommu_list, list) { iommu_set_exclusion_range(iommu); + iommu_init_msi(iommu); iommu_enable(iommu); } } diff --git a/include/asm-x86/amd_iommu.h b/include/asm-x86/amd_iommu.h index 30a12049353..2fd97cb250c 100644 --- a/include/asm-x86/amd_iommu.h +++ b/include/asm-x86/amd_iommu.h @@ -20,10 +20,13 @@ #ifndef _ASM_X86_AMD_IOMMU_H #define _ASM_X86_AMD_IOMMU_H +#include + #ifdef CONFIG_AMD_IOMMU extern int amd_iommu_init(void); extern int amd_iommu_init_dma_ops(void); extern void amd_iommu_detect(void); +extern irqreturn_t amd_iommu_int_handler(int irq, void *data); #else static inline int amd_iommu_init(void) { return -ENODEV; } static inline void amd_iommu_detect(void) { } diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index a5629a21557..8533f09b34b 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -37,6 +37,7 @@ /* Capability offsets used by the driver */ #define MMIO_CAP_HDR_OFFSET 0x00 #define MMIO_RANGE_OFFSET 0x0c +#define MMIO_MISC_OFFSET 0x10 /* Masks, shifts and macros to parse the device range capability */ #define MMIO_RANGE_LD_MASK 0xff000000 @@ -48,6 +49,7 @@ #define MMIO_GET_LD(x) (((x) & MMIO_RANGE_LD_MASK) >> MMIO_RANGE_LD_SHIFT) #define MMIO_GET_FD(x) (((x) & MMIO_RANGE_FD_MASK) >> MMIO_RANGE_FD_SHIFT) #define MMIO_GET_BUS(x) (((x) & MMIO_RANGE_BUS_MASK) >> MMIO_RANGE_BUS_SHIFT) +#define MMIO_MSI_NUM(x) ((x) & 0x1f) /* Flag masks for the AMD IOMMU exclusion range */ #define MMIO_EXCL_ENABLE_MASK 0x01ULL @@ -255,10 +257,15 @@ struct amd_iommu { u8 *evt_buf; /* size of event buffer */ u32 evt_buf_size; + /* MSI number for event interrupt */ + u16 evt_msi_num; /* if one, we need to send a completion wait command */ int need_sync; + /* true if interrupts for this IOMMU are already enabled */ + bool int_enabled; + /* default dma_ops domain for that IOMMU */ struct dma_ops_domain *default_dom; }; -- GitLab From 90008ee4b811c944455752dcb72b291a5ba81b53 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 16:41:05 +0200 Subject: [PATCH 2016/5416] AMD IOMMU: add event handling code This patch adds code for polling and printing out events generated by the AMD IOMMU. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 87 ++++++++++++++++++++++++++++++- arch/x86/kernel/amd_iommu_init.c | 1 - include/asm-x86/amd_iommu_types.h | 22 ++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0e494b9d5f2..0cb8fd2359f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -55,9 +55,94 @@ static int iommu_has_npcache(struct amd_iommu *iommu) * ****************************************************************************/ +static void iommu_print_event(void *__evt) +{ + u32 *event = __evt; + int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; + int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; + int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; + int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; + u64 address = (u64)(((u64)event[3]) << 32) | event[2]; + + printk(KERN_ERR "AMD IOMMU: Event logged ["); + + switch (type) { + case EVENT_TYPE_ILL_DEV: + printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + case EVENT_TYPE_IO_FAULT: + printk("IO_PAGE_FAULT device=%02x:%02x.%x " + "domain=0x%04x address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + domid, address, flags); + break; + case EVENT_TYPE_DEV_TAB_ERR: + printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + case EVENT_TYPE_PAGE_TAB_ERR: + printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " + "domain=0x%04x address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + domid, address, flags); + break; + case EVENT_TYPE_ILL_CMD: + printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); + break; + case EVENT_TYPE_CMD_HARD_ERR: + printk("COMMAND_HARDWARE_ERROR address=0x%016llx " + "flags=0x%04x]\n", address, flags); + break; + case EVENT_TYPE_IOTLB_INV_TO: + printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " + "address=0x%016llx]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address); + break; + case EVENT_TYPE_INV_DEV_REQ: + printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " + "address=0x%016llx flags=0x%04x]\n", + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + address, flags); + break; + default: + printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); + } +} + +static void iommu_poll_events(struct amd_iommu *iommu) +{ + u32 head, tail; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + + head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); + tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); + + while (head != tail) { + iommu_print_event(iommu->evt_buf + head); + head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; + } + + writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); + + spin_unlock_irqrestore(&iommu->lock, flags); +} + irqreturn_t amd_iommu_int_handler(int irq, void *data) { - return IRQ_NONE; + struct amd_iommu *iommu; + + list_for_each_entry(iommu, &amd_iommu_list, list) + iommu_poll_events(iommu); + + return IRQ_HANDLED; } /**************************************************************************** diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 14a06464a69..eed488892c0 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -32,7 +32,6 @@ /* * definitions for the ACPI scanning code */ -#define PCI_BUS(x) (((x) >> 8) & 0xff) #define IVRS_HEADER_LENGTH 48 #define ACPI_IVHD_TYPE 0x10 diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index 8533f09b34b..d8c5a6c6995 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -71,6 +71,25 @@ /* MMIO status bits */ #define MMIO_STATUS_COM_WAIT_INT_MASK 0x04 +/* event logging constants */ +#define EVENT_ENTRY_SIZE 0x10 +#define EVENT_TYPE_SHIFT 28 +#define EVENT_TYPE_MASK 0xf +#define EVENT_TYPE_ILL_DEV 0x1 +#define EVENT_TYPE_IO_FAULT 0x2 +#define EVENT_TYPE_DEV_TAB_ERR 0x3 +#define EVENT_TYPE_PAGE_TAB_ERR 0x4 +#define EVENT_TYPE_ILL_CMD 0x5 +#define EVENT_TYPE_CMD_HARD_ERR 0x6 +#define EVENT_TYPE_IOTLB_INV_TO 0x7 +#define EVENT_TYPE_INV_DEV_REQ 0x8 +#define EVENT_DEVID_MASK 0xffff +#define EVENT_DEVID_SHIFT 0 +#define EVENT_DOMID_MASK 0xffff +#define EVENT_DOMID_SHIFT 0 +#define EVENT_FLAGS_MASK 0xfff +#define EVENT_FLAGS_SHIFT 0x10 + /* feature control bits */ #define CONTROL_IOMMU_EN 0x00ULL #define CONTROL_HT_TUN_EN 0x01ULL @@ -165,6 +184,9 @@ #define MAX_DOMAIN_ID 65536 +/* FIXME: move this macro to */ +#define PCI_BUS(x) (((x) >> 8) & 0xff) + /* * This structure contains generic data for IOMMU protection domains * independent of their use. -- GitLab From 126c52be4b1d2eb667a1d140f0ceaff9d353f700 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 16:47:35 +0200 Subject: [PATCH 2017/5416] AMD IOMMU: enable event logging The code to log IOMMU events is in place now. So enable event logging with this patch. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index eed488892c0..1974b73fece 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -253,6 +253,13 @@ void __init iommu_enable(struct amd_iommu *iommu) iommu_feature_enable(iommu, CONTROL_IOMMU_EN); } +/* Function to enable IOMMU event logging and event interrupts */ +void __init iommu_enable_event_logging(struct amd_iommu *iommu) +{ + iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); + iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); +} + /* * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in * the system has one. @@ -958,6 +965,7 @@ static void __init enable_iommus(void) list_for_each_entry(iommu, &amd_iommu_list, list) { iommu_set_exclusion_range(iommu); iommu_init_msi(iommu); + iommu_enable_event_logging(iommu); iommu_enable(iommu); } } -- GitLab From a22131a223147016041b5e5cd0ae5ab61ef4177e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 17:55:28 +0200 Subject: [PATCH 2018/5416] AMD IOMMU: allow IO page faults from devices There is a bit in the device entry to suppress all IO page faults generated by a device. This bit was set until now because there was no event logging. Now that there is event logging this patch allows IO page faults from devices to see them in the kernel log. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 1974b73fece..8c137598555 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -950,7 +950,6 @@ static void init_device_table(void) for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { set_dev_entry_bit(devid, DEV_ENTRY_VALID); set_dev_entry_bit(devid, DEV_ENTRY_TRANSLATION); - set_dev_entry_bit(devid, DEV_ENTRY_NO_PAGE_FAULT); } } -- GitLab From b39ba6ad004a31bf2a08ba2b08c1e0f9b3530bb7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 18:40:46 +0200 Subject: [PATCH 2019/5416] AMD IOMMU: add dma_supported callback This function determines if the AMD IOMMU implementation is responsible for a given device. So the DMA layer can get this information from the driver. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0cb8fd2359f..a6a6f8ed1cf 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1204,6 +1204,30 @@ free_mem: free_pages((unsigned long)virt_addr, get_order(size)); } +/* + * This function is called by the DMA layer to find out if we can handle a + * particular device. It is part of the dma_ops. + */ +static int amd_iommu_dma_supported(struct device *dev, u64 mask) +{ + u16 bdf; + struct pci_dev *pcidev; + + /* No device or no PCI device */ + if (!dev || dev->bus != &pci_bus_type) + return 0; + + pcidev = to_pci_dev(dev); + + bdf = calc_devid(pcidev->bus->number, pcidev->devfn); + + /* Out of our scope? */ + if (bdf > amd_iommu_last_bdf) + return 0; + + return 1; +} + /* * The function for pre-allocating protection domains. * @@ -1247,6 +1271,7 @@ static struct dma_mapping_ops amd_iommu_dma_ops = { .unmap_single = unmap_single, .map_sg = map_sg, .unmap_sg = unmap_sg, + .dma_supported = amd_iommu_dma_supported, }; /* -- GitLab From bd60b735c658e6e8c656e89771d281bcfcf51279 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:24:48 +0200 Subject: [PATCH 2020/5416] AMD IOMMU: don't assign preallocated protection domains to devices In isolation mode the protection domains for the devices are preallocated and preassigned. This is bad if a device should be passed to a virtualization guest because the IOMMU code does not know if it is in use by a driver. This patch changes the code to assign the device to the preallocated domain only if there are dma mapping requests for it. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 43 +++++++++++++++++++++++++++---- include/asm-x86/amd_iommu_types.h | 6 +++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a6a6f8ed1cf..7c179144745 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -33,6 +33,10 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock); +/* A list of preallocated protection domains */ +static LIST_HEAD(iommu_pd_list); +static DEFINE_SPINLOCK(iommu_pd_list_lock); + /* * general struct to manage commands send to an IOMMU */ @@ -663,6 +667,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, dma_dom->next_bit = 0; dma_dom->need_flush = false; + dma_dom->target_dev = 0xffff; /* Intialize the exclusion range if necessary */ if (iommu->exclusion_start && @@ -768,6 +773,33 @@ static bool check_device(struct device *dev) return true; } +/* + * In this function the list of preallocated protection domains is traversed to + * find the domain for a specific device + */ +static struct dma_ops_domain *find_protection_domain(u16 devid) +{ + struct dma_ops_domain *entry, *ret = NULL; + unsigned long flags; + + if (list_empty(&iommu_pd_list)) + return NULL; + + spin_lock_irqsave(&iommu_pd_list_lock, flags); + + list_for_each_entry(entry, &iommu_pd_list, list) { + if (entry->target_dev == devid) { + ret = entry; + list_del(&ret->list); + break; + } + } + + spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + + return ret; +} + /* * In the dma_ops path we only have the struct device. This function * finds the corresponding IOMMU, the protection domain and the @@ -803,9 +835,11 @@ static int get_device_resources(struct device *dev, *iommu = amd_iommu_rlookup_table[*bdf]; if (*iommu == NULL) return 0; - dma_dom = (*iommu)->default_dom; *domain = domain_for_device(*bdf); if (*domain == NULL) { + dma_dom = find_protection_domain(*bdf); + if (!dma_dom) + dma_dom = (*iommu)->default_dom; *domain = &dma_dom->domain; set_device_domain(*iommu, *domain, *bdf); printk(KERN_INFO "AMD IOMMU: Using protection domain %d for " @@ -1257,10 +1291,9 @@ void prealloc_protection_domains(void) if (!dma_dom) continue; init_unity_mappings_for_device(dma_dom, devid); - set_device_domain(iommu, &dma_dom->domain, devid); - printk(KERN_INFO "AMD IOMMU: Allocated domain %d for device ", - dma_dom->domain.id); - print_devid(devid, 1); + dma_dom->target_dev = devid; + + list_add_tail(&dma_dom->list, &iommu_pd_list); } } diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index d8c5a6c6995..9aa22ead22f 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -227,6 +227,12 @@ struct dma_ops_domain { /* This will be set to true when TLB needs to be flushed */ bool need_flush; + + /* + * if this is a preallocated domain, keep the device for which it was + * preallocated in this variable + */ + u16 target_dev; }; /* -- GitLab From 38ddf41b198e21d3ecbe5752e875857b7ce7589e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:38:32 +0200 Subject: [PATCH 2021/5416] AMD IOMMU: some set_device_domain cleanups Remove some magic numbers and split the pte_root using standard functions. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 9 +++++---- include/asm-x86/amd_iommu_types.h | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 7c179144745..a34d8e915e3 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -739,12 +739,13 @@ static void set_device_domain(struct amd_iommu *iommu, u64 pte_root = virt_to_phys(domain->pt_root); - pte_root |= (domain->mode & 0x07) << 9; - pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | 2; + pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) + << DEV_ENTRY_MODE_SHIFT; + pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; write_lock_irqsave(&amd_iommu_devtable_lock, flags); - amd_iommu_dev_table[devid].data[0] = pte_root; - amd_iommu_dev_table[devid].data[1] = pte_root >> 32; + amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); + amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); amd_iommu_dev_table[devid].data[2] = domain->id; amd_iommu_pd_table[devid] = domain; diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index 9aa22ead22f..f953309a636 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -130,6 +130,8 @@ #define DEV_ENTRY_NMI_PASS 0xba #define DEV_ENTRY_LINT0_PASS 0xbe #define DEV_ENTRY_LINT1_PASS 0xbf +#define DEV_ENTRY_MODE_MASK 0x07 +#define DEV_ENTRY_MODE_SHIFT 0x09 /* constants to configure the command buffer */ #define CMD_BUFFER_SIZE 8192 @@ -159,6 +161,7 @@ #define IOMMU_MAP_SIZE_L3 (1ULL << 39) #define IOMMU_PTE_P (1ULL << 0) +#define IOMMU_PTE_TV (1ULL << 1) #define IOMMU_PTE_U (1ULL << 59) #define IOMMU_PTE_FC (1ULL << 60) #define IOMMU_PTE_IR (1ULL << 61) -- GitLab From 13d9fead3daa0efa1b8bb6ae59650e4453b39128 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 10 Sep 2008 20:19:40 +0900 Subject: [PATCH 2022/5416] AMD IOMMU: avoid unnecessary low zone allocation in alloc_coherent x86's common alloc_coherent (dma_alloc_coherent in dma-mapping.h) sets up the gfp flag according to the device dma_mask but AMD IOMMU doesn't need it for devices that the IOMMU can do virtual mappings for. This patch avoids unnecessary low zone allocation. Signed-off-by: FUJITA Tomonori Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a34d8e915e3..e4866660463 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1173,6 +1173,9 @@ static void *alloc_coherent(struct device *dev, size_t size, if (!check_device(dev)) return NULL; + if (!get_device_resources(dev, &iommu, &domain, &devid)) + flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; @@ -1180,8 +1183,6 @@ static void *alloc_coherent(struct device *dev, size_t size, memset(virt_addr, 0, size); paddr = virt_to_phys(virt_addr); - get_device_resources(dev, &iommu, &domain, &devid); - if (!iommu || !domain) { *dma_addr = (dma_addr_t)paddr; return virt_addr; -- GitLab From c97ac5359e6897abe22770740294dda185bac30d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 11 Sep 2008 10:59:15 +0200 Subject: [PATCH 2023/5416] AMD IOMMU: replace memset with __GFP_ZERO in alloc_coherent Remove the memset and use __GFP_ZERO at allocation time instead. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index e4866660463..f405a61f61f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1176,11 +1176,11 @@ static void *alloc_coherent(struct device *dev, size_t size, if (!get_device_resources(dev, &iommu, &domain, &devid)) flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); + flag |= __GFP_ZERO; virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) return 0; - memset(virt_addr, 0, size); paddr = virt_to_phys(virt_addr); if (!iommu || !domain) { -- GitLab From 6754086ce67c0a1f5d7eac612102368781e14588 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 12:17:00 +0200 Subject: [PATCH 2024/5416] AMD IOMMU: simplify dma_mask_to_pages The current calculation is very complicated. This patch replaces it with a much simpler version. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index f405a61f61f..db64482b179 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -472,8 +472,7 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, ****************************************************************************/ static unsigned long dma_mask_to_pages(unsigned long mask) { - return (mask >> PAGE_SHIFT) + - (PAGE_ALIGN(mask & ~PAGE_MASK) >> PAGE_SHIFT); + return PAGE_ALIGN(mask) >> PAGE_SHIFT; } /* -- GitLab From d58befd3a0110c93d70756537b4d01d05a9e6e12 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 12:19:58 +0200 Subject: [PATCH 2025/5416] AMD IOMMU: free domain bitmap with its allocation order The amd_iommu_pd_alloc_bitmap is allocated with a calculated order and freed with order 1. This is not a bug since the calculated order always evaluates to 1, but its unclean code. So replace the 1 with the calculation in the release path. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 8c137598555..e60f4cd29eb 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1144,7 +1144,8 @@ out: return ret; free: - free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, 1); + free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, + get_order(MAX_DOMAIN_ID/8)); free_pages((unsigned long)amd_iommu_pd_table, get_order(rlookup_table_size)); -- GitLab From 199d0d501202f077fe647a5c14fe046b17abc46b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 16:45:59 +0200 Subject: [PATCH 2026/5416] AMD IOMMU: remove unnecessary cast to u64 in the init code The ctrl variable is only u32 and readl also returns a 32 bit value. So the cast to u64 is pointless. Remove it with this patch. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index e60f4cd29eb..505fc04e896 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -235,7 +235,7 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) { u32 ctrl; - ctrl = (u64)readl(iommu->mmio_base + MMIO_CONTROL_OFFSET); + ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET); ctrl &= ~(1 << bit); writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET); } -- GitLab From b514e55569855bbaab782a8ec073630ed4e99c68 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 17:14:27 +0200 Subject: [PATCH 2027/5416] AMD IOMMU: calculate IVHD size with a function The current calculation of the IVHD entry size is hard to read. So move this code to a seperate function to make it more clear what this calculation does. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 505fc04e896..80250e63bd0 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -296,6 +296,14 @@ static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) * ****************************************************************************/ +/* + * This function calculates the length of a given IVHD entry + */ +static inline int ivhd_entry_length(u8 *ivhd) +{ + return 0x04 << (*ivhd >> 6); +} + /* * This function reads the last device id the IOMMU has to handle from the PCI * capability header for this IOMMU @@ -340,7 +348,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) default: break; } - p += 0x04 << (*p >> 6); + p += ivhd_entry_length(p); } WARN_ON(p != end); @@ -641,7 +649,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, break; } - p += 0x04 << (e->type >> 6); + p += ivhd_entry_length(p); } } -- GitLab From 23c1713fe9e6ac886a4d44415298d0cbb2e83df2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 17:18:17 +0200 Subject: [PATCH 2028/5416] AMD IOMMU: use cmd_buf_size when freeing the command buffer The command buffer release function uses the CMD_BUF_SIZE macro for get_order. Replace this with iommu->cmd_buf_size which is more reliable about the actual size of the buffer. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 80250e63bd0..db0c83af44d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -433,7 +433,8 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu) static void __init free_command_buffer(struct amd_iommu *iommu) { - free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); + free_pages((unsigned long)iommu->cmd_buf, + get_order(iommu->cmd_buf_size)); } /* allocates the memory where the IOMMU will log its events to */ -- GitLab From bbd001c73cb92aa8f779ae44bb89d8a5dee74ad5 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 17:22:45 +0200 Subject: [PATCH 2029/5416] add AMD IOMMU tree to MAINTAINERS file Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0a613cb926c..9ac82eab82e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -387,6 +387,7 @@ AMD IOMMU (AMD-VI) P: Joerg Roedel M: joerg.roedel@amd.com L: iommu@lists.linux-foundation.org +T: git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git S: Supported AMS (Apple Motion Sensor) DRIVER -- GitLab From 832a90c30485117d65180cc9a8d9869c1b158570 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 18 Sep 2008 15:54:23 +0200 Subject: [PATCH 2030/5416] AMD IOMMU: use coherent_dma_mask in alloc_coherent The alloc_coherent implementation for AMD IOMMU currently uses *dev->dma_mask per default. This patch changes it to prefer dev->coherent_dma_mask if it is set. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index db64482b179..6f7b9744573 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -483,9 +483,10 @@ static unsigned long dma_mask_to_pages(unsigned long mask) static unsigned long dma_ops_alloc_addresses(struct device *dev, struct dma_ops_domain *dom, unsigned int pages, - unsigned long align_mask) + unsigned long align_mask, + u64 dma_mask) { - unsigned long limit = dma_mask_to_pages(*dev->dma_mask); + unsigned long limit = dma_mask_to_pages(dma_mask); unsigned long address; unsigned long size = dom->aperture_size >> PAGE_SHIFT; unsigned long boundary_size; @@ -919,7 +920,8 @@ static dma_addr_t __map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir, - bool align) + bool align, + u64 dma_mask) { dma_addr_t offset = paddr & ~PAGE_MASK; dma_addr_t address, start; @@ -933,7 +935,8 @@ static dma_addr_t __map_single(struct device *dev, if (align) align_mask = (1UL << get_order(size)) - 1; - address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask); + address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, + dma_mask); if (unlikely(address == bad_dma_address)) goto out; @@ -997,10 +1000,13 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, struct protection_domain *domain; u16 devid; dma_addr_t addr; + u64 dma_mask; if (!check_device(dev)) return bad_dma_address; + dma_mask = *dev->dma_mask; + get_device_resources(dev, &iommu, &domain, &devid); if (iommu == NULL || domain == NULL) @@ -1008,7 +1014,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr, return (dma_addr_t)paddr; spin_lock_irqsave(&domain->lock, flags); - addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false); + addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false, + dma_mask); if (addr == bad_dma_address) goto out; @@ -1080,10 +1087,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, struct scatterlist *s; phys_addr_t paddr; int mapped_elems = 0; + u64 dma_mask; if (!check_device(dev)) return 0; + dma_mask = *dev->dma_mask; + get_device_resources(dev, &iommu, &domain, &devid); if (!iommu || !domain) @@ -1095,7 +1105,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, paddr = sg_phys(s); s->dma_address = __map_single(dev, iommu, domain->priv, - paddr, s->length, dir, false); + paddr, s->length, dir, false, + dma_mask); if (s->dma_address) { s->dma_length = s->length; @@ -1168,6 +1179,7 @@ static void *alloc_coherent(struct device *dev, size_t size, struct protection_domain *domain; u16 devid; phys_addr_t paddr; + u64 dma_mask = dev->coherent_dma_mask; if (!check_device(dev)) return NULL; @@ -1187,10 +1199,13 @@ static void *alloc_coherent(struct device *dev, size_t size, return virt_addr; } + if (!dma_mask) + dma_mask = *dev->dma_mask; + spin_lock_irqsave(&domain->lock, flags); *dma_addr = __map_single(dev, iommu, domain->priv, paddr, - size, DMA_BIDIRECTIONAL, true); + size, DMA_BIDIRECTIONAL, true, dma_mask); if (*dma_addr == bad_dma_address) { free_pages((unsigned long)virt_addr, get_order(size)); -- GitLab From 7fb61a7b6f9111245867fa2bce47949f4298d430 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 17:56:54 +0200 Subject: [PATCH 2031/5416] atstk1000: fix build breakage with BOARD_ATSTK100X_SW2_CUSTOM=y The #ifdef surrounding the code adding the mmc controller had a typo, causing it to be compiled even when mmc was supposed to be disabled. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index ee4c292683e..dfc3443e23a 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -325,7 +325,7 @@ static int __init atstk1002_init(void) #ifdef CONFIG_BOARD_ATSTK100X_SPI1 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif -#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM at32_add_device_mci(0, MCI_PDATA); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM -- GitLab From 1b771c12b56fdea6c0596a69c63b097b62ce9f41 Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Mon, 8 Sep 2008 00:22:45 +0200 Subject: [PATCH 2032/5416] avr32: add .gitignore files Ignore Kernel binaries, kernel/vmlinux.lds and a log file. Signed-off-by: Markus Heidelberg Signed-off-by: Haavard Skinnemoen --- arch/avr32/boot/images/.gitignore | 4 ++++ arch/avr32/kernel/.gitignore | 1 + 2 files changed, 5 insertions(+) create mode 100644 arch/avr32/boot/images/.gitignore create mode 100644 arch/avr32/kernel/.gitignore diff --git a/arch/avr32/boot/images/.gitignore b/arch/avr32/boot/images/.gitignore new file mode 100644 index 00000000000..64ea9d0141d --- /dev/null +++ b/arch/avr32/boot/images/.gitignore @@ -0,0 +1,4 @@ +uImage +uImage.srec +vmlinux.cso +sfdwarf.log diff --git a/arch/avr32/kernel/.gitignore b/arch/avr32/kernel/.gitignore new file mode 100644 index 00000000000..c5f676c3c22 --- /dev/null +++ b/arch/avr32/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds -- GitLab From e37925ebdb9738fc7968119198c6997e79093c02 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 10 Sep 2008 15:52:04 +0200 Subject: [PATCH 2033/5416] avr32: add generic_find_next_le_bit bit function This patch implements the generic_find_next_le_bit bit function for AVR32 architecture. This is used by EXT4 file system. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/avr32_ksyms.c | 1 + arch/avr32/lib/findbit.S | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 84a7d44edc6..11e310c567a 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -58,6 +58,7 @@ EXPORT_SYMBOL(find_first_zero_bit); EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); +EXPORT_SYMBOL(generic_find_next_le_bit); EXPORT_SYMBOL(generic_find_next_zero_le_bit); /* I/O primitives (lib/io-*.S) */ diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S index c6b91dee857..997b33b2288 100644 --- a/arch/avr32/lib/findbit.S +++ b/arch/avr32/lib/findbit.S @@ -123,6 +123,36 @@ ENTRY(find_next_bit) brgt 1b retal r11 +ENTRY(generic_find_next_le_bit) + lsr r8, r10, 5 + sub r9, r11, r10 + retle r11 + + lsl r8, 2 + add r12, r8 + andl r10, 31, COH + breq 1f + + /* offset is not word-aligned. Handle the first (32 - r10) bits */ + ldswp.w r8, r12[0] + sub r12, -4 + lsr r8, r8, r10 + brne .L_found + + /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ + add r9, r10 + sub r9, 32 + retle r11 + + /* Main loop. offset must be word-aligned */ +1: ldswp.w r8, r12[0] + cp.w r8, 0 + brne .L_found + sub r12, -4 + sub r9, 32 + brgt 1b + retal r11 + ENTRY(generic_find_next_zero_le_bit) lsr r8, r10, 5 sub r9, r11, r10 -- GitLab From 73d4393d1df4ff3892b040396f101ede94e9e846 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 17 Sep 2008 13:39:45 +0200 Subject: [PATCH 2034/5416] avr32: fix sys_sync_file_range() call convention On AVR32, all parameters beyond the 5th are passed on the stack. System calls don't use the stack -- they borrow a callee-saved register instead. This means that syscalls that take 6 parameters must be called through a stub that pushes the last parameter on the stack. This patch adds a stub for sync_file_range syscall on AVR32 architecture. Tested with uClibc snapshot. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/syscall-stubs.S | 9 +++++++++ arch/avr32/kernel/syscall_table.S | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 890286a1e62..673178e235f 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -109,3 +109,12 @@ __sys_epoll_pwait: rcall sys_epoll_pwait sub sp, -4 popm pc + + .global __sys_sync_file_range + .type __sys_sync_file_range,@function +__sys_sync_file_range: + pushm lr + st.w --sp, ARG6 + rcall sys_sync_file_range + sub sp, -4 + popm pc diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 478bda4c4a0..7ee0057613b 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -275,7 +275,7 @@ sys_call_table: .long sys_set_robust_list .long sys_get_robust_list /* 260 */ .long __sys_splice - .long sys_sync_file_range + .long __sys_sync_file_range .long sys_tee .long sys_vmsplice .long __sys_epoll_pwait /* 265 */ -- GitLab From ed94493fb38a665cebcf750dfabe8a6dd13e136f Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 13:34:19 +0200 Subject: [PATCH 2035/5416] mv643xx_eth: convert to phylib Switch mv643xx_eth from using drivers/net/mii.c to using phylib. Since the mv643xx_eth hardware does all the link state handling and PHY polling, the driver will use phylib in the "Doing it all yourself" mode described in the phylib documentation. Signed-off-by: Lennert Buytenhek Acked-by: Andy Fleming --- drivers/net/Kconfig | 2 +- drivers/net/mv643xx_eth.c | 248 ++++++++++++++++---------------------- 2 files changed, 105 insertions(+), 145 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4a11296a951..d85d76019af 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2262,7 +2262,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION - select MII + select PHYLIB help This driver supports the gigabit ethernet MACs in the Marvell Discovery PPC/MIPS chipset family (MV643XX) and diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index d0ecc440aac..1f944a23f53 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -248,9 +248,9 @@ struct mv643xx_eth_shared_private { struct mv643xx_eth_shared_private *smi; /* - * Protects access to SMI_REG, which is shared between ports. + * Provides access to local SMI interface. */ - struct mutex phy_lock; + struct mii_bus smi_bus; /* * If we have access to the error interrupt pin (which is @@ -354,14 +354,13 @@ struct mv643xx_eth_private { struct net_device *dev; - int phy_addr; + struct phy_device *phy; struct timer_list mib_counters_timer; spinlock_t mib_counters_lock; struct mib_counters mib_counters; struct work_struct tx_timeout_task; - struct mii_if_info mii; struct napi_struct napi; u8 work_link; @@ -1076,62 +1075,50 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) return 0; } -static int smi_reg_read(struct mv643xx_eth_private *mp, - unsigned int addr, unsigned int reg) +static int smi_bus_read(struct mii_bus *bus, int addr, int reg) { - struct mv643xx_eth_shared_private *msp = mp->shared->smi; + struct mv643xx_eth_shared_private *msp = bus->priv; void __iomem *smi_reg = msp->base + SMI_REG; int ret; - mutex_lock(&msp->phy_lock); - if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - ret = -ETIMEDOUT; - goto out; + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; } writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - ret = -ETIMEDOUT; - goto out; + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; } ret = readl(smi_reg); if (!(ret & SMI_READ_VALID)) { - printk("%s: SMI bus read not valid\n", mp->dev->name); - ret = -ENODEV; - goto out; + printk("mv643xx_eth: SMI bus read not valid\n"); + return -ENODEV; } - ret &= 0xffff; - -out: - mutex_unlock(&msp->phy_lock); - - return ret; + return ret & 0xffff; } -static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, - unsigned int reg, unsigned int value) +static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val) { - struct mv643xx_eth_shared_private *msp = mp->shared->smi; + struct mv643xx_eth_shared_private *msp = bus->priv; void __iomem *smi_reg = msp->base + SMI_REG; - mutex_lock(&msp->phy_lock); - if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - mutex_unlock(&msp->phy_lock); + printk("mv643xx_eth: SMI bus busy timeout\n"); return -ETIMEDOUT; } writel(SMI_OPCODE_WRITE | (reg << 21) | - (addr << 16) | (value & 0xffff), smi_reg); + (addr << 16) | (val & 0xffff), smi_reg); - mutex_unlock(&msp->phy_lock); + if (smi_wait_ready(msp)) { + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } return 0; } @@ -1287,7 +1274,9 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd * struct mv643xx_eth_private *mp = netdev_priv(dev); int err; - err = mii_ethtool_gset(&mp->mii, cmd); + err = phy_read_status(mp->phy); + if (err == 0) + err = phy_ethtool_gset(mp->phy, cmd); /* * The MAC does not support 1000baseT_Half. @@ -1341,7 +1330,7 @@ static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd * */ cmd->advertising &= ~ADVERTISED_1000baseT_Half; - return mii_ethtool_sset(&mp->mii, cmd); + return phy_ethtool_sset(mp->phy, cmd); } static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) @@ -1363,7 +1352,7 @@ static int mv643xx_eth_nway_reset(struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); - return mii_nway_restart(&mp->mii); + return genphy_restart_aneg(mp->phy); } static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) @@ -1373,14 +1362,7 @@ static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) static u32 mv643xx_eth_get_link(struct net_device *dev) { - struct mv643xx_eth_private *mp = netdev_priv(dev); - - return mii_link_ok(&mp->mii); -} - -static u32 mv643xx_eth_get_link_phyless(struct net_device *dev) -{ - return 1; + return !!netif_carrier_ok(dev); } static void mv643xx_eth_get_strings(struct net_device *dev, @@ -1448,7 +1430,7 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = { .set_settings = mv643xx_eth_set_settings_phyless, .get_drvinfo = mv643xx_eth_get_drvinfo, .nway_reset = mv643xx_eth_nway_reset_phyless, - .get_link = mv643xx_eth_get_link_phyless, + .get_link = mv643xx_eth_get_link, .set_sg = ethtool_op_set_sg, .get_strings = mv643xx_eth_get_strings, .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, @@ -1941,16 +1923,16 @@ static void phy_reset(struct mv643xx_eth_private *mp) { int data; - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + data = phy_read(mp->phy, MII_BMCR); if (data < 0) return; data |= BMCR_RESET; - if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data) < 0) + if (phy_write(mp->phy, MII_BMCR, data) < 0) return; do { - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + data = phy_read(mp->phy, MII_BMCR); } while (data >= 0 && data & BMCR_RESET); } @@ -1962,7 +1944,7 @@ static void port_start(struct mv643xx_eth_private *mp) /* * Perform PHY reset, if there is a PHY. */ - if (mp->phy_addr != -1) { + if (mp->phy != NULL) { struct ethtool_cmd cmd; mv643xx_eth_get_settings(mp->dev, &cmd); @@ -1979,7 +1961,7 @@ static void port_start(struct mv643xx_eth_private *mp) wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); pscr |= DO_NOT_FORCE_LINK_FAIL; - if (mp->phy_addr == -1) + if (mp->phy == NULL) pscr |= FORCE_LINK_PASS; wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); @@ -2188,8 +2170,8 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mv643xx_eth_private *mp = netdev_priv(dev); - if (mp->phy_addr != -1) - return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); + if (mp->phy != NULL) + return phy_mii_ioctl(mp->phy, if_mii(ifr), cmd); return -EOPNOTSUPP; } @@ -2259,18 +2241,6 @@ static void mv643xx_eth_netpoll(struct net_device *dev) } #endif -static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg) -{ - struct mv643xx_eth_private *mp = netdev_priv(dev); - return smi_reg_read(mp, addr, reg); -} - -static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val) -{ - struct mv643xx_eth_private *mp = netdev_priv(dev); - smi_reg_write(mp, addr, reg, val); -} - /* platform glue ************************************************************/ static void @@ -2365,11 +2335,23 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (msp->base == NULL) goto out_free; - msp->smi = msp; - if (pd != NULL && pd->shared_smi != NULL) + /* + * Set up and register SMI bus. + */ + if (pd == NULL || pd->shared_smi == NULL) { + msp->smi_bus.priv = msp; + msp->smi_bus.name = "mv643xx_eth smi"; + msp->smi_bus.read = smi_bus_read; + msp->smi_bus.write = smi_bus_write, + snprintf(msp->smi_bus.id, MII_BUS_ID_SIZE, "%d", pdev->id); + msp->smi_bus.dev = &pdev->dev; + msp->smi_bus.phy_mask = 0xffffffff; + if (mdiobus_register(&msp->smi_bus) < 0) + goto out_unmap; + msp->smi = msp; + } else { msp->smi = platform_get_drvdata(pd->shared_smi); - - mutex_init(&msp->phy_lock); + } msp->err_interrupt = NO_IRQ; init_waitqueue_head(&msp->smi_busy_wait); @@ -2405,6 +2387,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) return 0; +out_unmap: + iounmap(msp->base); out_free: kfree(msp); out: @@ -2414,7 +2398,10 @@ out: static int mv643xx_eth_shared_remove(struct platform_device *pdev) { struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); + struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; + if (pd == NULL || pd->shared_smi == NULL) + mdiobus_unregister(&msp->smi_bus); if (msp->err_interrupt != NO_IRQ) free_irq(msp->err_interrupt, msp); iounmap(msp->base); @@ -2462,17 +2449,6 @@ static void set_params(struct mv643xx_eth_private *mp, else uc_addr_get(mp, dev->dev_addr); - if (pd->phy_addr == MV643XX_ETH_PHY_NONE) { - mp->phy_addr = -1; - } else { - if (pd->phy_addr != MV643XX_ETH_PHY_ADDR_DEFAULT) { - mp->phy_addr = pd->phy_addr & 0x3f; - phy_addr_set(mp, mp->phy_addr); - } else { - mp->phy_addr = phy_addr_get(mp); - } - } - mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE; if (pd->rx_queue_size) mp->default_rx_ring_size = pd->rx_queue_size; @@ -2490,76 +2466,60 @@ static void set_params(struct mv643xx_eth_private *mp, mp->txq_count = pd->tx_queue_count ? : 1; } -static int phy_detect(struct mv643xx_eth_private *mp) +static struct phy_device *phy_scan(struct mv643xx_eth_private *mp, + int phy_addr) { - int data; - int data2; + struct mii_bus *bus = &mp->shared->smi->smi_bus; + struct phy_device *phydev; + int start; + int num; + int i; - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); - if (data < 0) - return -ENODEV; + if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) { + start = phy_addr_get(mp) & 0x1f; + num = 32; + } else { + start = phy_addr & 0x1f; + num = 1; + } - if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE) < 0) - return -ENODEV; + phydev = NULL; + for (i = 0; i < num; i++) { + int addr = (start + i) & 0x1f; - data2 = smi_reg_read(mp, mp->phy_addr, MII_BMCR); - if (data2 < 0) - return -ENODEV; + if (bus->phy_map[addr] == NULL) + mdiobus_scan(bus, addr); - if (((data ^ data2) & BMCR_ANENABLE) == 0) - return -ENODEV; - - smi_reg_write(mp, mp->phy_addr, MII_BMCR, data); + if (phydev == NULL) { + phydev = bus->phy_map[addr]; + if (phydev != NULL) + phy_addr_set(mp, addr); + } + } - return 0; + return phydev; } -static int phy_init(struct mv643xx_eth_private *mp, - struct mv643xx_eth_platform_data *pd) +static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) { - struct ethtool_cmd cmd; - int err; + struct phy_device *phy = mp->phy; - err = phy_detect(mp); - if (err) { - dev_printk(KERN_INFO, &mp->dev->dev, - "no PHY detected at addr %d\n", mp->phy_addr); - return err; - } phy_reset(mp); - mp->mii.phy_id = mp->phy_addr; - mp->mii.phy_id_mask = 0x3f; - mp->mii.reg_num_mask = 0x1f; - mp->mii.dev = mp->dev; - mp->mii.mdio_read = mv643xx_eth_mdio_read; - mp->mii.mdio_write = mv643xx_eth_mdio_write; - - mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); - - memset(&cmd, 0, sizeof(cmd)); - - cmd.port = PORT_MII; - cmd.transceiver = XCVR_INTERNAL; - cmd.phy_address = mp->phy_addr; - if (pd->speed == 0) { - cmd.autoneg = AUTONEG_ENABLE; - cmd.speed = SPEED_100; - cmd.advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full; - if (mp->mii.supports_gmii) - cmd.advertising |= ADVERTISED_1000baseT_Full; + phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); + + if (speed == 0) { + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->advertising = phy->supported | ADVERTISED_Autoneg; } else { - cmd.autoneg = AUTONEG_DISABLE; - cmd.speed = pd->speed; - cmd.duplex = pd->duplex; + phy->autoneg = AUTONEG_DISABLE; + phy->advertising = 0; + phy->speed = speed; + phy->duplex = duplex; } - - mv643xx_eth_set_settings(mp->dev, &cmd); - - return 0; + phy_start_aneg(phy); } static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) @@ -2573,7 +2533,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) } pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED; - if (mp->phy_addr == -1) { + if (mp->phy == NULL) { pscr |= DISABLE_AUTO_NEG_SPEED_GMII; if (speed == SPEED_1000) pscr |= SET_GMII_SPEED_TO_1000; @@ -2627,18 +2587,16 @@ static int mv643xx_eth_probe(struct platform_device *pdev) set_params(mp, pd); dev->real_num_tx_queues = mp->txq_count; - mib_counters_clear(mp); - INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); - - if (mp->phy_addr != -1) { - err = phy_init(mp, pd); - if (err) - goto out; + if (pd->phy_addr != MV643XX_ETH_PHY_NONE) + mp->phy = phy_scan(mp, pd->phy_addr); + if (mp->phy != NULL) { + phy_init(mp, pd->speed, pd->duplex); SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); } else { SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); } + init_pscr(mp, pd->speed, pd->duplex); @@ -2711,6 +2669,8 @@ static int mv643xx_eth_remove(struct platform_device *pdev) struct mv643xx_eth_private *mp = platform_get_drvdata(pdev); unregister_netdev(mp->dev); + if (mp->phy != NULL) + phy_detach(mp->phy); flush_scheduled_work(); free_netdev(mp->dev); -- GitLab From 042af53c7839282de15cc7fd7ad8ab938d74ab7c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 09:01:57 +0200 Subject: [PATCH 2036/5416] mv643xx_eth: bump version to 1.4 Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 1f944a23f53..55aa8ba7e0f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -55,7 +55,7 @@ #include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; -static char mv643xx_eth_driver_version[] = "1.3"; +static char mv643xx_eth_driver_version[] = "1.4"; /* -- GitLab From 3d431a742728e6b619ce57a030a92d228c13d1d2 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Wed, 20 Aug 2008 15:39:59 +0200 Subject: [PATCH 2037/5416] avr32: nmi_enter() without nmi_exit() While updating the rcu code, I noticed that do_nmi() for AVR32 is odd: There is an nmi_enter() call without an nmi_exit(). This can't be correct, it breaks rcu (at least the preempt version) and lockdep. [haavard.skinnemoen@atmel.com: fixed another case that returned directly] Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/traps.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index b835c4c0136..0d987373bc0 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -116,15 +116,15 @@ asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) switch (ret) { case NOTIFY_OK: case NOTIFY_STOP: - return; + break; case NOTIFY_BAD: die("Fatal Non-Maskable Interrupt", regs, SIGINT); default: + printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n"); + nmi_disable(); break; } - - printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n"); - nmi_disable(); + nmi_exit(); } asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs) -- GitLab From b38fd42ff46a4a31dced8533e8a6e549693500b6 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 16 Jul 2008 16:17:08 -0500 Subject: [PATCH 2038/5416] powerpc/fsl-booke: Fixup 64-bit PTE reading for SMP support We need to create a false data dependency to ensure the loads of the pte are done in the right order. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/head_fsl_booke.S | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 3cb52fa0eda..377e0c155c9 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -579,13 +579,19 @@ interrupt_base: FIND_PTE andc. r13,r13,r11 /* Check permission */ - bne 2f /* Bail if permission mismach */ #ifdef CONFIG_PTE_64BIT - lwz r13, 0(r12) +#ifdef CONFIG_SMP + subf r10,r11,r12 /* create false data dep */ + lwzx r13,r11,r10 /* Get upper pte bits */ +#else + lwz r13,0(r12) /* Get upper pte bits */ +#endif #endif - /* Jump to common tlb load */ + bne 2f /* Bail if permission/valid mismach */ + + /* Jump to common tlb load */ b finish_tlb_load 2: /* The bailout. Restore registers to pre-exception conditions @@ -640,10 +646,20 @@ interrupt_base: FIND_PTE andc. r13,r13,r11 /* Check permission */ + +#ifdef CONFIG_PTE_64BIT +#ifdef CONFIG_SMP + subf r10,r11,r12 /* create false data dep */ + lwzx r13,r11,r10 /* Get upper pte bits */ +#else + lwz r13,0(r12) /* Get upper pte bits */ +#endif +#endif + bne 2f /* Bail if permission mismach */ #ifdef CONFIG_PTE_64BIT - lwz r13, 0(r12) + lwz r13,0(r12) #endif /* Jump to common TLB load point */ @@ -702,7 +718,7 @@ interrupt_base: /* * Both the instruction and data TLB miss get to this * point to load the TLB. - * r10 - EA of fault + * r10 - available to use * r11 - TLB (info from Linux PTE) * r12 - available to use * r13 - upper bits of PTE (if PTE_64BIT) or available to use -- GitLab From 8b05cefca73bfbd98c89f16327f5d7da52ab7c3c Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Fri, 12 Sep 2008 10:42:56 -0500 Subject: [PATCH 2039/5416] cpm_uart: Pass actual dev ptr to dma_* in ucc and cpm_uart serial We're currently passing NULL, and really shouldn't be. Signed-off-by: Becky Bruce Acked-By: Timur Tabi Signed-off-by: Kumar Gala --- drivers/serial/cpm_uart/cpm_uart_core.c | 3 +++ drivers/serial/cpm_uart/cpm_uart_cpm1.c | 6 +++--- drivers/serial/cpm_uart/cpm_uart_cpm2.c | 6 +++--- drivers/serial/ucc_uart.c | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 25efca5a7a1..a6c4d744495 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -1333,6 +1333,9 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev, if (ret) return ret; + /* initialize the device pointer for the port */ + pinfo->port.dev = &ofdev->dev; + return uart_add_one_port(&cpm_reg, &pinfo->port); } diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 0f0aff06c59..1b94c56ec23 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -100,7 +100,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); dma_addr = (u32)cpm_dpram_phys(mem_addr); } else - mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, + mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr, GFP_KERNEL); if (mem_addr == NULL) { @@ -127,8 +127,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) void cpm_uart_freebuf(struct uart_cpm_port *pinfo) { - dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos * - pinfo->rx_fifosize) + + dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos * + pinfo->rx_fifosize) + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize), pinfo->mem_addr, pinfo->dma_addr); diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index b8db4d3eed3..141c0a3333a 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -136,7 +136,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) dma_addr = virt_to_bus(mem_addr); } else - mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, + mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr, GFP_KERNEL); if (mem_addr == NULL) { @@ -163,8 +163,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) void cpm_uart_freebuf(struct uart_cpm_port *pinfo) { - dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos * - pinfo->rx_fifosize) + + dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos * + pinfo->rx_fifosize) + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize), (void __force *)pinfo->mem_addr, pinfo->dma_addr); diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 5c5d18dcb6a..539c933b335 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -1009,7 +1009,7 @@ static int qe_uart_request_port(struct uart_port *port) rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize); tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize); - bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr, + bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr, GFP_KERNEL); if (!bd_virt) { dev_err(port->dev, "could not allocate buffer descriptors\n"); @@ -1051,7 +1051,7 @@ static void qe_uart_release_port(struct uart_port *port) container_of(port, struct uart_qe_port, port); struct ucc_slow_private *uccs = qe_port->us_private; - dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt, + dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt, qe_port->bd_dma_addr); ucc_slow_free(uccs); -- GitLab From 02a1416478b70cd49bd74827438c8ba797784728 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 12:44:54 -0700 Subject: [PATCH 2040/5416] net: Fix build with ARCH=um If UM is going to claim that it supports DMA by setting HAS_DMA, it should provide a dma_mapping_error() implementation. Based upon a report by Julius Volz. Signed-off-by: David S. Miller --- include/asm-um/dma-mapping.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h index f0ee4fb5591..90fc708b320 100644 --- a/include/asm-um/dma-mapping.h +++ b/include/asm-um/dma-mapping.h @@ -118,4 +118,11 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size, BUG(); } +static inline int +dma_mapping_error(struct device *dev, dma_addr_t dma_handle) +{ + BUG(); + return 0; +} + #endif -- GitLab From 53159d06cb07517422f977591264ca9bf806febb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 16:13:05 -0700 Subject: [PATCH 2041/5416] qlge: Fix warnings in debugging code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/qlge/qlge_dbg.c: In function ‘ql_dump_qdev’: drivers/net/qlge/qlge_dbg.c:369: warning: cast to pointer from integer of different size drivers/net/qlge/qlge_dbg.c:373: warning: cast to pointer from integer of different size drivers/net/qlge/qlge_dbg.c: In function ‘ql_dump_tx_ring’: drivers/net/qlge/qlge_dbg.c:457: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:461: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c: In function ‘ql_dump_rx_ring’: drivers/net/qlge/qlge_dbg.c:557: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:565: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:575: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:579: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:598: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ drivers/net/qlge/qlge_dbg.c:602: warning: format ‘%llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘long unsigned int’ Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_dbg.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index f0392b16617..47df304a02c 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -365,12 +365,12 @@ void ql_dump_qdev(struct ql_adapter *qdev) qdev->msg_enable); printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_area = %p.\n", qdev->rx_ring_shadow_reg_area); - printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_dma = %p.\n", - (void *)qdev->rx_ring_shadow_reg_dma); + printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_dma = %llx.\n", + (unsigned long long) qdev->rx_ring_shadow_reg_dma); printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_area = %p.\n", qdev->tx_ring_shadow_reg_area); - printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_dma = %p.\n", - (void *)qdev->tx_ring_shadow_reg_dma); + printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_dma = %llx.\n", + (unsigned long long) qdev->tx_ring_shadow_reg_dma); printk(KERN_ERR PFX "qdev->intr_count = %d.\n", qdev->intr_count); if (qdev->msi_x_entry) @@ -454,11 +454,11 @@ void ql_dump_tx_ring(struct tx_ring *tx_ring) tx_ring->wq_id); printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base); printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n", - (u64) tx_ring->wq_base_dma); + (unsigned long long) tx_ring->wq_base_dma); printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n", tx_ring->cnsmr_idx_sh_reg); printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n", - (u64) tx_ring->cnsmr_idx_sh_reg_dma); + (unsigned long long) tx_ring->cnsmr_idx_sh_reg_dma); printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size); printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len); printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n", @@ -554,7 +554,7 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) printk(KERN_ERR PFX "rx_ring->cqicb = %p.\n", &rx_ring->cqicb); printk(KERN_ERR PFX "rx_ring->cq_base = %p.\n", rx_ring->cq_base); printk(KERN_ERR PFX "rx_ring->cq_base_dma = %llx.\n", - (u64) rx_ring->cq_base_dma); + (unsigned long long) rx_ring->cq_base_dma); printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size); printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len); printk(KERN_ERR PFX @@ -562,7 +562,7 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) rx_ring->prod_idx_sh_reg, rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0); printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n", - (u64) rx_ring->prod_idx_sh_reg_dma); + (unsigned long long) rx_ring->prod_idx_sh_reg_dma); printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n", rx_ring->cnsmr_idx_db_reg); printk(KERN_ERR PFX "rx_ring->cnsmr_idx = %d.\n", rx_ring->cnsmr_idx); @@ -572,11 +572,11 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) printk(KERN_ERR PFX "rx_ring->lbq_base = %p.\n", rx_ring->lbq_base); printk(KERN_ERR PFX "rx_ring->lbq_base_dma = %llx.\n", - (u64) rx_ring->lbq_base_dma); + (unsigned long long) rx_ring->lbq_base_dma); printk(KERN_ERR PFX "rx_ring->lbq_base_indirect = %p.\n", rx_ring->lbq_base_indirect); printk(KERN_ERR PFX "rx_ring->lbq_base_indirect_dma = %llx.\n", - (u64) rx_ring->lbq_base_indirect_dma); + (unsigned long long) rx_ring->lbq_base_indirect_dma); printk(KERN_ERR PFX "rx_ring->lbq = %p.\n", rx_ring->lbq); printk(KERN_ERR PFX "rx_ring->lbq_len = %d.\n", rx_ring->lbq_len); printk(KERN_ERR PFX "rx_ring->lbq_size = %d.\n", rx_ring->lbq_size); @@ -595,11 +595,11 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) printk(KERN_ERR PFX "rx_ring->sbq_base = %p.\n", rx_ring->sbq_base); printk(KERN_ERR PFX "rx_ring->sbq_base_dma = %llx.\n", - (u64) rx_ring->sbq_base_dma); + (unsigned long long) rx_ring->sbq_base_dma); printk(KERN_ERR PFX "rx_ring->sbq_base_indirect = %p.\n", rx_ring->sbq_base_indirect); printk(KERN_ERR PFX "rx_ring->sbq_base_indirect_dma = %llx.\n", - (u64) rx_ring->sbq_base_indirect_dma); + (unsigned long long) rx_ring->sbq_base_indirect_dma); printk(KERN_ERR PFX "rx_ring->sbq = %p.\n", rx_ring->sbq); printk(KERN_ERR PFX "rx_ring->sbq_len = %d.\n", rx_ring->sbq_len); printk(KERN_ERR PFX "rx_ring->sbq_size = %d.\n", rx_ring->sbq_size); -- GitLab From 04da2cf9bb133355b7073be25ef3ce88c8edc135 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 16:14:24 -0700 Subject: [PATCH 2042/5416] qlge: Protect qlge_resume() with CONFIG_PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following build warning: drivers/net/qlge/qlge_main.c:3897: warning: ‘qlge_resume’ defined but not used Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ad878e2b9de..3af822b6226 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3893,6 +3893,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +#ifdef CONFIG_PM static int qlge_resume(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); @@ -3921,6 +3922,7 @@ static int qlge_resume(struct pci_dev *pdev) return 0; } +#endif /* CONFIG_PM */ static void qlge_shutdown(struct pci_dev *pdev) { -- GitLab From 9f7263236aa4401f8e52cae084f652175b7a7b5f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 12 Sep 2008 14:12:08 +0200 Subject: [PATCH 2043/5416] KVM: ia64: 'struct fdesc' build fix Commit 4611a77 ("[IA64] fix compile failure with non modular builds") introduced struct fdesc into asm/elf.h, which duplicates KVM's definition. Remove the latter to avoid the build error. Signed-off-by: Jes Sorensen Acked-by: Tony Luck Signed-off-by: Avi Kivity --- arch/ia64/kvm/kvm-ia64.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 7a37d06376b..cd0d1a7284b 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "misc.h" #include "vti.h" @@ -61,12 +62,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { NULL } }; - -struct fdesc{ - unsigned long ip; - unsigned long gp; -}; - static void kvm_flush_icache(unsigned long start, unsigned long len) { int l; -- GitLab From 69c010b24560be5ca7667e94a352183e60ed205e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 21:17:43 -0700 Subject: [PATCH 2044/5416] sparc32: Use PROM device probing for sun4m irq registers. Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 40 ++++----- arch/sparc/kernel/sun4m_irq.c | 163 +++++++++++----------------------- 2 files changed, 74 insertions(+), 129 deletions(-) diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 68689facaaa..faf9ccd9ef5 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -272,17 +272,18 @@ smp4m_ticker: */ maybe_smp4m_msg: GET_PROCESSOR4M_ID(o3) - set sun4m_interrupts, %l5 - ld [%l5], %o5 + sethi %hi(sun4m_irq_percpu), %l5 + sll %o3, 2, %o3 + or %l5, %lo(sun4m_irq_percpu), %o5 sethi %hi(0x40000000), %o2 - sll %o3, 12, %o3 ld [%o5 + %o3], %o1 - andcc %o1, %o2, %g0 + ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending + andcc %o3, %o2, %g0 be,a smp4m_ticker cmp %l7, 14 - st %o2, [%o5 + 0x4] + st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -300,16 +301,16 @@ linux_trap_ipi15_sun4m: SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR4M_ID(o0) - set sun4m_interrupts, %l5 - ld [%l5], %o5 - sll %o0, 12, %o0 - add %o5, %o0, %o5 - ld [%o5], %o3 + sethi %hi(sun4m_irq_percpu), %l5 + or %l5, %lo(sun4m_irq_percpu), %o5 + sll %o0, 2, %o0 + ld [%o5 + %o0], %o5 + ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be 1f ! Must be an NMI async memory error - st %o2, [%o5 + 4] + st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -323,12 +324,11 @@ linux_trap_ipi15_sun4m: 1: /* NMI async memory error handling. */ sethi %hi(0x80000000), %l4 - sethi %hi(0x4000), %o3 - sub %o5, %o0, %o5 - add %o5, %o3, %l5 - st %l4, [%l5 + 0xc] + sethi %hi(sun4m_irq_global), %o5 + ld [%o5 + %lo(sun4m_irq_global)], %l5 + st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -337,9 +337,9 @@ linux_trap_ipi15_sun4m: WRITE_PAUSE call sun4m_nmi nop - st %l4, [%l5 + 0x8] + st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE RESTORE_ALL diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 5b17146f0c1..39d40e96d39 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -41,53 +41,25 @@ #include "irq.h" -/* On the sun4m, just like the timers, we have both per-cpu and master - * interrupt registers. - */ - -/* These registers are used for sending/receiving irqs from/to - * different cpu's. - */ -struct sun4m_intreg_percpu { - unsigned int tbt; /* Interrupts still pending for this cpu. */ - - /* These next two registers are WRITE-ONLY and are only - * "on bit" sensitive, "off bits" written have NO affect. - */ - unsigned int clear; /* Clear this cpus irqs here. */ - unsigned int set; /* Set this cpus irqs here. */ - unsigned char space[PAGE_SIZE - 12]; +struct sun4m_irq_percpu { + u32 pending; + u32 clear; + u32 set; }; -/* - * djhr - * Actually the clear and set fields in this struct are misleading.. - * according to the SLAVIO manual (and the same applies for the SEC) - * the clear field clears bits in the mask which will ENABLE that IRQ - * the set field sets bits in the mask to DISABLE the IRQ. - * - * Also the undirected_xx address in the SLAVIO is defined as - * RESERVED and write only.. - * - * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor - * sun4m machines, for MP the layout makes more sense. - */ -struct sun4m_intregs { - struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; - unsigned int tbt; /* IRQ's that are still pending. */ - unsigned int irqs; /* Master IRQ bits. */ - - /* Again, like the above, two these registers are WRITE-ONLY. */ - unsigned int clear; /* Clear master IRQ's by setting bits here. */ - unsigned int set; /* Set master IRQ's by setting bits here. */ - - /* This register is both READ and WRITE. */ - unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +struct sun4m_irq_global { + u32 pending; + u32 mask; + u32 mask_clear; + u32 mask_set; + u32 interrupt_target; }; -static unsigned long dummy; +/* Code in entry.S needs to get at these register mappings. */ +struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; +struct sun4m_irq_global __iomem *sun4m_irq_global; -struct sun4m_intregs *sun4m_interrupts; +static unsigned long dummy; unsigned long *irq_rcvreg = &dummy; /* Dave Redman (djhr@tadpole.co.uk) @@ -182,9 +154,9 @@ static void sun4m_disable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->set = mask; + sbus_writel(mask, &sun4m_irq_global->mask_set); else - sun4m_interrupts->cpu_intregs[cpu].set = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); local_irq_restore(flags); } @@ -201,13 +173,13 @@ static void sun4m_enable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->clear = mask; + sbus_writel(mask, &sun4m_irq_global->mask_clear); else - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); local_irq_restore(flags); } else { local_irq_save(flags); - sun4m_interrupts->clear = SUN4M_INT_FLOPPY; + sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); local_irq_restore(flags); } } @@ -236,34 +208,30 @@ static unsigned long cpu_pil_to_imask[16] = { */ static void sun4m_disable_pil_irq(unsigned int pil) { - sun4m_interrupts->set = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); } static void sun4m_enable_pil_irq(unsigned int pil) { - sun4m_interrupts->clear = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); } #ifdef CONFIG_SMP static void sun4m_send_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].set = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); } static void sun4m_clear_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); } static void sun4m_set_udt(int cpu) { - sun4m_interrupts->undirected_target = cpu; + sbus_writel(cpu, &sun4m_irq_global->interrupt_target); } #endif @@ -347,7 +315,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) for (i = 0; i < num_cpu_timers; i++) sbus_writel(0, &timers_percpu[i]->l14_limit); if (num_cpu_timers == 4) - sbus_writel(SUN4M_INT_E14, &sun4m_interrupts->set); + sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set); #ifdef CONFIG_SMP { @@ -372,62 +340,38 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) void __init sun4m_init_IRQ(void) { - int ie_node,i; - struct linux_prom_registers int_regs[PROMREG_MAX]; - int num_regs; - struct resource r; - int mid; - - local_irq_disable(); - if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || - (ie_node = prom_getchild (ie_node)) == 0 || - (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { - prom_printf("Cannot find /obio/interrupt node\n"); - prom_halt(); + struct device_node *dp = of_find_node_by_name(NULL, "interrupt"); + int len, i, mid, num_cpu_iregs; + const u32 *addr; + + if (!dp) { + printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n"); + return; } - num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)); - num_regs = (num_regs/sizeof(struct linux_prom_registers)); - - /* Apply the obio ranges to these registers. */ - prom_apply_obio_ranges(int_regs, num_regs); - - int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr; - int_regs[4].reg_size = int_regs[num_regs-1].reg_size; - int_regs[4].which_io = int_regs[num_regs-1].which_io; - for(ie_node = 1; ie_node < 4; ie_node++) { - int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE; - int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size; - int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; + + addr = of_get_property(dp, "address", &len); + if (!addr) { + printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); + return; } - memset((char *)&r, 0, sizeof(struct resource)); - /* Map the interrupt registers for all possible cpus. */ - r.flags = int_regs[0].which_io; - r.start = int_regs[0].phys_addr; - sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0, - PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); + num_cpu_iregs = (len / sizeof(u32)) - 1; + for (i = 0; i < num_cpu_iregs; i++) { + sun4m_irq_percpu[i] = (void __iomem *) + (unsigned long) addr[i]; + } + sun4m_irq_global = (void __iomem *) + (unsigned long) addr[num_cpu_iregs]; - /* Map the system interrupt control registers. */ - r.flags = int_regs[4].which_io; - r.start = int_regs[4].phys_addr; - of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + local_irq_disable(); - sun4m_interrupts->set = ~SUN4M_INT_MASKALL; + sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff; - - if (!cpu_find_by_instance(1, NULL, NULL)) { - /* system wide interrupts go to cpu 0, this should always - * be safe because it is guaranteed to be fitted or OBP doesn't - * come up - * - * Not sure, but writing here on SLAVIO systems may puke - * so I don't do it unless there is more than 1 cpu. - */ - irq_rcvreg = (unsigned long *) - &sun4m_interrupts->undirected_target; - sun4m_interrupts->undirected_target = 0; + sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); + + if (num_cpu_iregs == 4) { + irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target; + sbus_writel(0, &sun4m_irq_global->interrupt_target); } BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); @@ -442,5 +386,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); #endif + /* Cannot enable interrupts until OBP ticker is disabled. */ } -- GitLab From f5f1085720c4799dd1437f78e28e40c8dd557bba Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:04:55 -0700 Subject: [PATCH 2045/5416] sparc32: Use PROM infrastructure for probing and mapping sun4d timers. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 13 --- arch/sparc/kernel/sun4d_irq.c | 139 ++++++++++++++++++------------ 2 files changed, 83 insertions(+), 69 deletions(-) diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 8906e987ef8..860a05ef456 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -35,19 +35,6 @@ struct sun4c_timer_info { #define SUN_TIMER_PHYSADDR 0xf3000000 -#define SUN4D_PRM_CNT_L 0x80000000 -#define SUN4D_PRM_CNT_LVALUE 0x7FFFFC00 - -struct sun4d_timer_regs { - volatile unsigned int l10_timer_limit; - volatile unsigned int l10_cur_countx; - volatile unsigned int l10_limit_noclear; - volatile unsigned int ctrl; - volatile unsigned int l10_cur_count; -}; - -extern struct sun4d_timer_regs *sun4d_timers; - extern __volatile__ unsigned int *master_l10_counter; extern __volatile__ unsigned int *master_l10_limit; diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 12541f51fcf..4156bf6657f 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -45,7 +45,16 @@ /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ /* #define DISTRIBUTE_IRQS */ -struct sun4d_timer_regs *sun4d_timers; +struct sun4d_timer_regs { + u32 l10_timer_limit; + u32 l10_cur_countx; + u32 l10_limit_noclear; + u32 ctrl; + u32 l10_cur_count; +}; + +static struct sun4d_timer_regs __iomem *sun4d_timers; + #define TIMER_IRQ 10 #define MAX_STATIC_ALLOC 4 @@ -446,8 +455,7 @@ void __init sun4d_distribute_irqs(void) static void sun4d_clear_clock_irq(void) { - volatile unsigned int clear_intr; - clear_intr = sun4d_timers->l10_timer_limit; + sbus_readl(&sun4d_timers->l10_timer_limit); } static void sun4d_clear_profile_irq(int cpu) @@ -460,71 +468,90 @@ static void sun4d_load_profile_irq(int cpu, unsigned int limit) bw_set_prof_limit(cpu, limit); } -static void __init sun4d_init_timers(irq_handler_t counter_fn) +static void __init sun4d_load_profile_irqs(void) { - int irq; - int cpu; - struct resource r; - int mid; + int cpu = 0, mid; - /* Map the User Timer registers. */ - memset(&r, 0, sizeof(r)); + while (!cpu_find_by_instance(cpu, NULL, &mid)) { + sun4d_load_profile_irq(mid >> 3, 0); + cpu++; + } +} + +static void __init sun4d_fixup_trap_table(void) +{ #ifdef CONFIG_SMP - r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT; -#else - r.start = CSR_BASE(0)+BW_TIMER_LIMIT; + unsigned long flags; + extern unsigned long lvl14_save[4]; + struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; + extern unsigned int real_irq_entry[], smp4d_ticker[]; + extern unsigned int patchme_maybe_smp_msg[]; + + /* Adjust so that we jump directly to smp4d_ticker */ + lvl14_save[2] += smp4d_ticker - real_irq_entry; + + /* For SMP we use the level 14 ticker, however the bootup code + * has copied the firmware's level 14 vector into the boot cpu's + * trap table, we must fix this now or we get squashed. + */ + local_irq_save(flags); + patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ + trap_table->inst_one = lvl14_save[0]; + trap_table->inst_two = lvl14_save[1]; + trap_table->inst_three = lvl14_save[2]; + trap_table->inst_four = lvl14_save[3]; + local_flush_cache_all(); + local_irq_restore(flags); #endif - r.flags = 0xf; - sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0, - PAGE_SIZE, "user timer"); +} + +static void __init sun4d_init_timers(irq_handler_t counter_fn) +{ + struct device_node *dp; + struct resource res; + const u32 *reg; + int err; + + dp = of_find_node_by_name(NULL, "cpu-unit"); + if (!dp) { + prom_printf("sun4d_init_timers: Unable to find cpu-unit\n"); + prom_halt(); + } + + /* Which cpu-unit we use is arbitrary, we can view the bootbus timer + * registers via any cpu's mapping. The first 'reg' property is the + * bootbus. + */ + reg = of_get_property(dp, "reg", NULL); + if (!reg) { + prom_printf("sun4d_init_timers: No reg property\n"); + prom_halt(); + } + + res.start = reg[1]; + res.end = reg[2] - 1; + res.flags = reg[0] & 0xff; + sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT, + sizeof(struct sun4d_timer_regs), "user timer"); + if (!sun4d_timers) { + prom_printf("sun4d_init_timers: Can't map timer regs\n"); + prom_halt(); + } + + sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); - sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4d_timers->l10_cur_count; master_l10_limit = &sun4d_timers->l10_timer_limit; - irq = request_irq(TIMER_IRQ, - counter_fn, + err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); - if (irq) { - prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); + if (err) { + prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); prom_halt(); } - - /* Enable user timer free run for CPU 0 in BW */ - /* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */ - - cpu = 0; - while (!cpu_find_by_instance(cpu, NULL, &mid)) { - sun4d_load_profile_irq(mid >> 3, 0); - cpu++; - } - -#ifdef CONFIG_SMP - { - unsigned long flags; - extern unsigned long lvl14_save[4]; - struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; - extern unsigned int real_irq_entry[], smp4d_ticker[]; - extern unsigned int patchme_maybe_smp_msg[]; - - /* Adjust so that we jump directly to smp4d_ticker */ - lvl14_save[2] += smp4d_ticker - real_irq_entry; - - /* For SMP we use the level 14 ticker, however the bootup code - * has copied the firmware's level 14 vector into the boot cpu's - * trap table, we must fix this now or we get squashed. - */ - local_irq_save(flags); - patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ - trap_table->inst_one = lvl14_save[0]; - trap_table->inst_two = lvl14_save[1]; - trap_table->inst_three = lvl14_save[2]; - trap_table->inst_four = lvl14_save[3]; - local_flush_cache_all(); - local_irq_restore(flags); - } -#endif + sun4d_load_profile_irqs(); + sun4d_fixup_trap_table(); } void __init sun4d_init_sbi_irq(void) -- GitLab From f8376e933c4e80663f6f66a5b5dd90390a0feba2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:05:25 -0700 Subject: [PATCH 2046/5416] sparc32: Remove some SMP ifdefs in sun4d_irq.c Always do the sbus_tid[] handling. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 42 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 4156bf6657f..6e3bf6eee54 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -60,9 +60,7 @@ static struct sun4d_timer_regs __iomem *sun4d_timers; #define MAX_STATIC_ALLOC 4 extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; extern int static_irq_count; -#ifdef CONFIG_SMP static unsigned char sbus_tid[32]; -#endif static struct irqaction *irq_action[NR_IRQS]; extern spinlock_t irq_action_lock; @@ -81,9 +79,9 @@ static int sbus_to_pil[] = { }; static int nsbi; -#ifdef CONFIG_SMP + +/* Exported for sun4d_smp.c */ DEFINE_SPINLOCK(sun4d_imsk_lock); -#endif int show_sun4d_interrupts(struct seq_file *p, void *v) { @@ -349,36 +347,28 @@ out: static void sun4d_disable_irq(unsigned int irq) { -#ifdef CONFIG_SMP int tid = sbus_tid[(irq >> 5) - 1]; unsigned long flags; -#endif - if (irq < NR_IRQS) return; -#ifdef CONFIG_SMP + if (irq < NR_IRQS) + return; + spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); spin_unlock_irqrestore(&sun4d_imsk_lock, flags); -#else - cc_set_imsk(cc_get_imsk() | (1 << sbus_to_pil[(irq >> 2) & 7])); -#endif } static void sun4d_enable_irq(unsigned int irq) { -#ifdef CONFIG_SMP int tid = sbus_tid[(irq >> 5) - 1]; unsigned long flags; -#endif - if (irq < NR_IRQS) return; -#ifdef CONFIG_SMP + if (irq < NR_IRQS) + return; + spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); spin_unlock_irqrestore(&sun4d_imsk_lock, flags); -#else - cc_set_imsk(cc_get_imsk() & ~(1 << sbus_to_pil[(irq >> 2) & 7])); -#endif } #ifdef CONFIG_SMP @@ -557,6 +547,11 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) void __init sun4d_init_sbi_irq(void) { struct device_node *dp; + int target_cpu = 0; + +#ifdef CONFIG_SMP + target_cpu = boot_cpu_id; +#endif nsbi = 0; for_each_node_by_name(dp, "sbi") @@ -571,14 +566,9 @@ void __init sun4d_init_sbi_irq(void) int board = of_getintprop_default(dp, "board#", 0); unsigned int mask; -#ifdef CONFIG_SMP - { - extern unsigned char boot_cpu_id; - - set_sbi_tid(devid, boot_cpu_id << 3); - sbus_tid[board] = boot_cpu_id; - } -#endif + set_sbi_tid(devid, target_cpu << 3); + sbus_tid[board] = target_cpu; + /* Get rid of pending irqs from PROM */ mask = acquire_sbi(devid, 0xffffffff); if (mask) { -- GitLab From a73554aedb8f69bd2024cbbf74980582bb91afb4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:40 -0700 Subject: [PATCH 2047/5416] sparc32: Remove #if 0'd code from sun4c_irq.c Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 722d2516f28..5602972f357 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -36,11 +36,6 @@ #include #include -#if 0 -static struct resource sun4c_timer_eb = { "sun4c_timer" }; -static struct resource sun4c_intr_eb = { "sun4c_intr" }; -#endif - /* * Bit field defines for the interrupt registers on various * Sparc machines. @@ -173,10 +168,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) prom_halt(); } -#if 0 - /* This does not work on 4/330 */ - sun4c_enable_irq(10); -#endif claim_ticker14(NULL, PROFILE_IRQ, 0); } -- GitLab From 1de937a536ea1a132d22dc198a9e07d208d40a29 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:56 -0700 Subject: [PATCH 2048/5416] sparc32: Call sun4m_clear_profile_irq() directly from sun4m_smp.c This is the only use of the clear_profile_irq() btfixup entry, which just eats up lots of dead space on other platform types. A subsequent commit will delete the other implementations and the btfixup entry as well. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 3 ++- arch/sparc/kernel/sun4m_smp.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 39d40e96d39..8e1ecc6def2 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -264,7 +264,8 @@ static void sun4m_clear_clock_irq(void) sbus_readl(&timers_global->l10_limit); } -static void sun4m_clear_profile_irq(int cpu) +/* Exported for sun4m_smp.c */ +void sun4m_clear_profile_irq(int cpu) { sbus_readl(&timers_percpu[cpu]->l14_limit); } diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a14a76ac7f3..e3c0be17729 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -313,6 +313,8 @@ void smp4m_cross_call_irq(void) ccall_info.processors_out[i] = 1; } +extern void sun4m_clear_profile_irq(int cpu); + void smp4m_percpu_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs; @@ -320,7 +322,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) old_regs = set_irq_regs(regs); - clear_profile_irq(cpu); + sun4m_clear_profile_irq(cpu); profile_tick(CPU_PROFILING); -- GitLab From 76954261ba907950cb5216e5c3075b5ba03c1a6b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:07:06 -0700 Subject: [PATCH 2049/5416] sparc32: Kill clear_profile_irq btfixup entry. Unused. Signed-off-by: David S. Miller --- arch/sparc/kernel/irq.h | 6 ------ arch/sparc/kernel/pcic.c | 6 ------ arch/sparc/kernel/sun4c_irq.c | 6 ------ arch/sparc/kernel/sun4d_irq.c | 6 ------ arch/sparc/kernel/sun4m_irq.c | 1 - 5 files changed, 25 deletions(-) diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 32ef3ebd0a8..db751388153 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -13,7 +13,6 @@ BTFIXUPDEF_CALL(void, enable_irq, unsigned int) BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) BTFIXUPDEF_CALL(void, clear_clock_irq, void) -BTFIXUPDEF_CALL(void, clear_profile_irq, int) BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) static inline void __disable_irq(unsigned int irq) @@ -41,11 +40,6 @@ static inline void clear_clock_irq(void) BTFIXUP_CALL(clear_clock_irq)(); } -static inline void clear_profile_irq(int irq) -{ - BTFIXUP_CALL(clear_profile_irq)(irq); -} - static inline void load_profile_irq(int cpu, int limit) { BTFIXUP_CALL(load_profile_irq)(cpu, limit); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index e5950b03df1..462584e55fb 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -897,11 +897,6 @@ static void pcic_enable_irq(unsigned int irq_nr) local_irq_restore(flags); } -static void pcic_clear_profile_irq(int cpu) -{ - printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); -} - static void pcic_load_profile_irq(int cpu, unsigned int limit) { printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); @@ -927,7 +922,6 @@ void __init sun4m_pci_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); } diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 5602972f357..6f28a13829c 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -131,11 +131,6 @@ static void sun4c_clear_clock_irq(void) clear_intr = sun4c_timers->timer_limit10; } -static void sun4c_clear_profile_irq(int cpu) -{ - /* Errm.. not sure how to do this.. */ -} - static void sun4c_load_profile_irq(int cpu, unsigned int limit) { /* Errm.. not sure how to do this.. */ @@ -204,7 +199,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); sparc_init_timers = sun4c_init_timers; #ifdef CONFIG_SMP diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 6e3bf6eee54..d376d380ac0 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -448,11 +448,6 @@ static void sun4d_clear_clock_irq(void) sbus_readl(&sun4d_timers->l10_timer_limit); } -static void sun4d_clear_profile_irq(int cpu) -{ - bw_get_prof_limit(cpu); -} - static void sun4d_load_profile_irq(int cpu, unsigned int limit) { bw_set_prof_limit(cpu, limit); @@ -585,7 +580,6 @@ void __init sun4d_init_IRQ(void) BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4d_init_timers; #ifdef CONFIG_SMP diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 8e1ecc6def2..ab309eca09c 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -379,7 +379,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP -- GitLab From b218fa0e9c2ad94b4e9ab5517a9210f9fa3745e2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:08:26 -0700 Subject: [PATCH 2050/5416] sparc32: Stop calling claim_ticker14() from sun4c_irq.c Since the first argument is always NULL, the only side effect is to disable the PROFILE_IRQ, so just do that directly. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 6f28a13829c..ae3149ecaec 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -163,7 +163,7 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) prom_halt(); } - claim_ticker14(NULL, PROFILE_IRQ, 0); + sun4c_disable_irq(PROFILE_IRQ); } #ifdef CONFIG_SMP -- GitLab From 5ff0d55f93f8119b71b33d4c444cf5105d4c1d12 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Sep 2008 00:04:35 -0700 Subject: [PATCH 2051/5416] sparc32: Delete claim_ticker14(). No more users. Signed-off-by: David S. Miller --- arch/sparc/kernel/tick14.c | 46 -------------------------------------- 1 file changed, 46 deletions(-) diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 77a4f3aeec6..138bbf5f872 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -1,30 +1,12 @@ /* tick14.c - * linux/arch/sparc/kernel/tick14.c * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) * * This file handles the Sparc specific level14 ticker * This is really useful for profiling OBP uses it for keyboard * aborts and other stuff. - * - * */ -#include -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "irq.h" extern unsigned long lvl14_save[5]; static unsigned long *linux_lvl14 = NULL; @@ -55,31 +37,3 @@ void install_obp_ticker(void) linux_lvl14[2] = obp_lvl14[2]; linux_lvl14[3] = obp_lvl14[3]; } - -void claim_ticker14(irq_handler_t handler, - int irq_nr, unsigned int timeout ) -{ - int cpu = smp_processor_id(); - - /* first we copy the obp handler instructions - */ - __disable_irq(irq_nr); - if (!handler) - return; - - linux_lvl14 = (unsigned long *)lvl14_save[4]; - obp_lvl14[0] = linux_lvl14[0]; - obp_lvl14[1] = linux_lvl14[1]; - obp_lvl14[2] = linux_lvl14[2]; - obp_lvl14[3] = linux_lvl14[3]; - - if (!request_irq(irq_nr, - handler, - (IRQF_DISABLED | SA_STATIC_ALLOC), - "counter14", - NULL)) { - install_linux_ticker(); - load_profile_irq(cpu, timeout); - __enable_irq(irq_nr); - } -} -- GitLab From 45bb5a7cbfa28dedc07730d6ecedbd574faf5459 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:43:48 -0700 Subject: [PATCH 2052/5416] sparc32: Use PROM device probing for sun4c interrupt register. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4c_irq.c | 47 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index ae3149ecaec..8033132eda8 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -59,7 +59,7 @@ * * so don't go making it static, like I tried. sigh. */ -unsigned char *interrupt_enable = NULL; +unsigned char __iomem *interrupt_enable = NULL; static void sun4c_disable_irq(unsigned int irq_nr) { @@ -68,7 +68,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) local_irq_save(flags); irq_nr &= (NR_IRQS - 1); - current_mask = *interrupt_enable; + current_mask = sbus_readb(interrupt_enable); switch(irq_nr) { case 1: new_mask = ((current_mask) & (~(SUN4C_INT_E1))); @@ -86,7 +86,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) local_irq_restore(flags); return; } - *interrupt_enable = new_mask; + sbus_writeb(new_mask, interrupt_enable); local_irq_restore(flags); } @@ -97,7 +97,7 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_save(flags); irq_nr &= (NR_IRQS - 1); - current_mask = *interrupt_enable; + current_mask = sbus_readb(interrupt_enable); switch(irq_nr) { case 1: new_mask = ((current_mask) | SUN4C_INT_E1); @@ -115,7 +115,7 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_restore(flags); return; } - *interrupt_enable = new_mask; + sbus_writeb(new_mask, interrupt_enable); local_irq_restore(flags); } @@ -172,27 +172,22 @@ static void sun4c_nop(void) {} void __init sun4c_init_IRQ(void) { - struct linux_prom_registers int_regs[2]; - int ie_node; - struct resource phyres; - - ie_node = prom_searchsiblings (prom_getchild(prom_root_node), - "interrupt-enable"); - if(ie_node == 0) - panic("Cannot find /interrupt-enable node"); - - /* Depending on the "address" property is bad news... */ - interrupt_enable = NULL; - if (prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)) != -1) { - memset(&phyres, 0, sizeof(struct resource)); - phyres.flags = int_regs[0].which_io; - phyres.start = int_regs[0].phys_addr; - interrupt_enable = (char *) of_ioremap(&phyres, 0, - int_regs[0].reg_size, "sun4c_intr"); + struct device_node *dp; + const u32 *addr; + + dp = of_find_node_by_name(NULL, "interrupt-enable"); + if (!dp) { + prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n"); + prom_halt(); + } + + addr = of_get_property(dp, "address", NULL); + if (!addr) { + prom_printf("sun4c_init_IRQ: No address property\n"); + prom_halt(); } - if (!interrupt_enable) - panic("Cannot map interrupt_enable"); + + interrupt_enable = (void __iomem *) (unsigned long) addr[0]; BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); @@ -206,6 +201,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP); #endif - *interrupt_enable = (SUN4C_INT_ENABLE); + sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable); /* Cannot enable interrupts until OBP ticker is disabled. */ } -- GitLab From 8bd8deead7f00006781c366887da8cf6a02c69ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:47:43 -0700 Subject: [PATCH 2053/5416] sparc32: Use PROM device probing for sun4c timers. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 24 ------------- arch/sparc/kernel/sun4c_irq.c | 59 ++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 860a05ef456..351f257eec0 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -11,30 +11,6 @@ #include /* For SUN4M_NCPUS */ #include -/* Timer structures. The interrupt timer has two properties which - * are the counter (which is handled in do_timer in sched.c) and the limit. - * This limit is where the timer's counter 'wraps' around. Oddly enough, - * the sun4c timer when it hits the limit wraps back to 1 and not zero - * thus when calculating the value at which it will fire a microsecond you - * must adjust by one. Thanks SUN for designing such great hardware ;( - */ - -/* Note that I am only going to use the timer that interrupts at - * Sparc IRQ 10. There is another one available that can fire at - * IRQ 14. Currently it is left untouched, we keep the PROM's limit - * register value and let the prom take these interrupts. This allows - * L1-A to work. - */ - -struct sun4c_timer_info { - __volatile__ unsigned int cur_count10; - __volatile__ unsigned int timer_limit10; - __volatile__ unsigned int cur_count14; - __volatile__ unsigned int timer_limit14; -}; - -#define SUN_TIMER_PHYSADDR 0xf3000000 - extern __volatile__ unsigned int *master_l10_counter; extern __volatile__ unsigned int *master_l10_limit; diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 8033132eda8..92096ba31d5 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -119,16 +119,18 @@ static void sun4c_enable_irq(unsigned int irq_nr) local_irq_restore(flags); } -#define TIMER_IRQ 10 /* Also at level 14, but we ignore that one. */ -#define PROFILE_IRQ 14 /* Level14 ticker.. used by OBP for polling */ +struct sun4c_timer_info { + u32 l10_count; + u32 l10_limit; + u32 l14_count; + u32 l14_limit; +}; -volatile struct sun4c_timer_info *sun4c_timers; +static struct sun4c_timer_info __iomem *sun4c_timers; static void sun4c_clear_clock_irq(void) { - volatile unsigned int clear_intr; - - clear_intr = sun4c_timers->timer_limit10; + sbus_readl(&sun4c_timers->l10_limit); } static void sun4c_load_profile_irq(int cpu, unsigned int limit) @@ -138,32 +140,49 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) static void __init sun4c_init_timers(irq_handler_t counter_fn) { - int irq; + const struct linux_prom_irqs *irq; + struct device_node *dp; + const u32 *addr; + int err; - /* Map the Timer chip, this is implemented in hardware inside - * the cache chip on the sun4c. - */ - sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, - sizeof(struct sun4c_timer_info)); + dp = of_find_node_by_name(NULL, "counter-timer"); + if (!dp) { + prom_printf("sun4c_init_timers: Unable to find counter-timer\n"); + prom_halt(); + } + + addr = of_get_property(dp, "address", NULL); + if (!addr) { + prom_printf("sun4c_init_timers: No address property\n"); + prom_halt(); + } + + sun4c_timers = (void __iomem *) (unsigned long) addr[0]; + + irq = of_get_property(dp, "intr", NULL); + if (!irq) { + prom_printf("sun4c_init_timers: No intr property\n"); + prom_halt(); + } /* Have the level 10 timer tick at 100HZ. We don't touch the * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. */ - sun4c_timers->timer_limit10 = (((1000000/HZ) + 1) << 10); - master_l10_counter = &sun4c_timers->cur_count10; - master_l10_limit = &sun4c_timers->timer_limit10; + sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); + + master_l10_counter = &sun4c_timers->l10_count; + master_l10_limit = &sun4c_timers->l10_limit; - irq = request_irq(TIMER_IRQ, - counter_fn, + err = request_irq(irq[0].pri, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); - if (irq) { - prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); + if (err) { + prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_halt(); } - sun4c_disable_irq(PROFILE_IRQ); + sun4c_disable_irq(irq[1].pri); } #ifdef CONFIG_SMP -- GitLab From c7e606a8f863b2119176674610618dad3d80a16d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:48:04 -0700 Subject: [PATCH 2054/5416] sparc32: Delete master_l10_limit. It is only set, never used. Signed-off-by: David S. Miller --- arch/sparc/include/asm/timer_32.h | 1 - arch/sparc/kernel/sun4c_irq.c | 1 - arch/sparc/kernel/sun4d_irq.c | 1 - arch/sparc/kernel/sun4m_irq.c | 1 - arch/sparc/kernel/time.c | 1 - 5 files changed, 5 deletions(-) diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 351f257eec0..2ec030ef381 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -12,7 +12,6 @@ #include extern __volatile__ unsigned int *master_l10_counter; -extern __volatile__ unsigned int *master_l10_limit; /* FIXME: Make do_[gs]ettimeofday btfixup calls */ BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 92096ba31d5..5dc8a576948 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -172,7 +172,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); master_l10_counter = &sun4c_timers->l10_count; - master_l10_limit = &sun4c_timers->l10_limit; err = request_irq(irq[0].pri, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index d376d380ac0..d3cb76ce418 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -526,7 +526,6 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); master_l10_counter = &sun4d_timers->l10_cur_count; - master_l10_limit = &sun4d_timers->l10_timer_limit; err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index ab309eca09c..c09ec39d68a 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -303,7 +303,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); master_l10_counter = &timers_global->l10_count; - master_l10_limit = &timers_global->l10_limit; err = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index fa54d585f55..62c1d94cb43 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -73,7 +73,6 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); __volatile__ unsigned int *master_l10_counter; -__volatile__ unsigned int *master_l10_limit; /* * timer_interrupt() needs to keep up the real-time clock, -- GitLab From e7913de9285a4e40733cdabbe62b6f1fa3bbdf01 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 13 Sep 2008 22:48:41 -0700 Subject: [PATCH 2055/5416] sparc32: Kill irq_rcvreg from sun4m_irq.c Unused. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index c09ec39d68a..c6096fc70c6 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -59,9 +59,6 @@ struct sun4m_irq_global { struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; struct sun4m_irq_global __iomem *sun4m_irq_global; -static unsigned long dummy; -unsigned long *irq_rcvreg = &dummy; - /* Dave Redman (djhr@tadpole.co.uk) * The sun4m interrupt registers. */ @@ -369,10 +366,9 @@ void __init sun4m_init_IRQ(void) for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); - if (num_cpu_iregs == 4) { - irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target; + if (num_cpu_iregs == 4) sbus_writel(0, &sun4m_irq_global->interrupt_target); - } + BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); -- GitLab From 778b1c65bfa2bfe4018394480f97d387e8f00a91 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 15:33:21 -0700 Subject: [PATCH 2056/5416] sparc32: Add more extensive documentation of sun4m interrupts. Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4m_irq.c | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index c6096fc70c6..ec66d4aab09 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -87,6 +87,59 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) +/* Interrupt level assignment on sun4m: + * + * level source + * ------------------------------------------------------------ + * 1 softint-1 + * 2 softint-2, VME/SBUS level 1 + * 3 softint-3, VME/SBUS level 2 + * 4 softint-4, onboard SCSI + * 5 softint-5, VME/SBUS level 3 + * 6 softint-6, onboard ETHERNET + * 7 softint-7, VME/SBUS level 4 + * 8 softint-8, onboard VIDEO + * 9 softint-9, VME/SBUS level 5, Module Interrupt + * 10 softint-10, system counter/timer + * 11 softint-11, VME/SBUS level 6, Floppy + * 12 softint-12, Keyboard/Mouse, Serial + * 13 softint-13, VME/SBUS level 7, ISDN Audio + * 14 softint-14, per-processor counter/timer + * 15 softint-15, Asynchronous Errors (broadcast) + * + * Each interrupt source is masked distinctly in the sun4m interrupt + * registers. The PIL level alone is therefore ambiguous, since multiple + * interrupt sources map to a single PIL. + * + * This ambiguity is resolved in the 'intr' property for device nodes + * in the OF device tree. Each 'intr' property entry is composed of + * two 32-bit words. The first word is the IRQ priority value, which + * is what we're intersted in. The second word is the IRQ vector, which + * is unused. + * + * The low 4 bits of the IRQ priority indicate the PIL, and the upper + * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20 + * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled. + * + * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI + * whereas a value of 0x33 is SBUS level 2. Here are some sample + * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and + * Tadpole S3 GX systems. + * + * esp: 0x24 onboard ESP SCSI + * le: 0x26 onboard Lance ETHERNET + * p9100: 0x32 SBUS level 1 P9100 video + * bpp: 0x33 SBUS level 2 BPP parallel port device + * DBRI: 0x39 SBUS level 5 DBRI ISDN audio + * SUNW,leo: 0x39 SBUS level 5 LEO video + * pcmcia: 0x3b SBUS level 6 PCMCIA controller + * uctrl: 0x3b SBUS level 6 UCTRL device + * modem: 0x3d SBUS level 7 MODEM + * zs: 0x2c onboard keyboard/mouse/serial + * floppy: 0x2b onboard Floppy + * power: 0x22 onboard power device (XXX unknown mask bit XXX) + */ + /* These tables only apply for interrupts greater than 15.. * * any intr value below 0x10 is considered to be a soft-int -- GitLab From 13b3c3fa27f8f4ed306ce624f446fab000dd8ee4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 10:25:19 +0200 Subject: [PATCH 2057/5416] hwmon: (atxp1) Fix device detection logic The atxp1 device detection code has a major logic flaw, fix it. Not sure how we managed to miss this when the driver was merged... Signed-off-by: Jean Delvare Acked-by: Sebastian Witt --- drivers/hwmon/atxp1.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index d191118ba0c..d6b490d3e36 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -31,7 +31,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); -MODULE_VERSION("0.6.2"); +MODULE_VERSION("0.6.3"); MODULE_AUTHOR("Sebastian Witt "); #define ATXP1_VID 0x00 @@ -289,16 +289,16 @@ static int atxp1_detect(struct i2c_client *new_client, int kind, if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && - (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) { + (i2c_smbus_read_byte_data(new_client, 0xff) == 0))) + return -ENODEV; - /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) - * showing the same as register 0x00 */ - temp = i2c_smbus_read_byte_data(new_client, 0x00); + /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) + * showing the same as register 0x00 */ + temp = i2c_smbus_read_byte_data(new_client, 0x00); - if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && - (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) - return -ENODEV; - } + if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && + (i2c_smbus_read_byte_data(new_client, 0x11) == temp))) + return -ENODEV; /* Get VRM */ temp = vid_which_vrm(); -- GitLab From 859b9ef30cc1bdba4b55327b95b22489bd5591c2 Mon Sep 17 00:00:00 2001 From: Andrew Paprocki Date: Sat, 20 Sep 2008 10:25:19 +0200 Subject: [PATCH 2058/5416] hwmon: (it87) Fix fan tachometer reading in IT8712F rev 0x7 (I) The IT8712F v0.9.1 datasheet applies to revisions >= 0x8 (J). The driver was incorrectly attempting to enable 16-bit fan readings on rev 0x7 (I) which led to incorrect RPM values. Signed-off-by: Andrew Paprocki Tested-by: John Gumb Signed-off-by: Jean Delvare --- drivers/hwmon/it87.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 30cdb095677..f1133081cc4 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -273,10 +273,10 @@ struct it87_data { static inline int has_16bit_fans(const struct it87_data *data) { /* IT8705F Datasheet 0.4.1, 3h == Version G. - IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I. + IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. These are the first revisions with 16bit tachometer support. */ return (data->type == it87 && data->revision >= 0x03) - || (data->type == it8712 && data->revision >= 0x07) + || (data->type == it8712 && data->revision >= 0x08) || data->type == it8716 || data->type == it8718; } -- GitLab From d130d97154f5342973a0fffc0b5a144359273c79 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 20 Sep 2008 10:25:20 +0200 Subject: [PATCH 2059/5416] hwmon: (ad7414) Make ad7414_update_device() static This patch makes the needlessly global ad7414_update_device() static. Signed-off-by: Adrian Bunk Acked-by: Sean MacLennan Signed-off-by: Jean Delvare --- drivers/hwmon/ad7414.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index ce8d94fbfd7..bfda8c80ef2 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -69,7 +69,7 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) return i2c_smbus_write_byte_data(client, reg, value); } -struct ad7414_data *ad7414_update_device(struct device *dev) +static struct ad7414_data *ad7414_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct ad7414_data *data = i2c_get_clientdata(client); -- GitLab From fe246eb0b7f2e995c4f172f360bc4e86baccaafe Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 3 Sep 2008 19:33:30 +0400 Subject: [PATCH 2060/5416] tmio_mmc: fix compilation with debug enabled Signed-off-by: Dmitry Baryshkov Acked-by: Ian Molton Signed-off-by: Pierre Ossman --- drivers/mmc/host/tmio_mmc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9e647a06054..ba2b4240a86 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -159,10 +159,10 @@ static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host, #define STATUS_TO_TEXT(a) \ do { \ if (status & TMIO_STAT_##a) \ - printf(#a); \ + printk(#a); \ } while (0) -void debug_status(u32 status) +void pr_debug_status(u32 status) { printk(KERN_DEBUG "status: %08x = ", status); STATUS_TO_TEXT(CARD_REMOVE); -- GitLab From 87e60f2b80202575a23fa1bf56c6eb3b419c480a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:27 +0200 Subject: [PATCH 2061/5416] atmel-mci: debugfs: enable clock before dumping regs Make sure that the peripheral clock is enabled before reading the MMIO registers for the debugfs "regs" dump. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 0bd06f5bd62..6de773d3a0c 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -195,7 +195,9 @@ static int atmci_regs_show(struct seq_file *s, void *v) /* Grab a more or less consistent snapshot */ spin_lock_irq(&host->mmc->lock); + clk_enable(host->mck); memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); + clk_disable(host->mck); spin_unlock_irq(&host->mmc->lock); seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", -- GitLab From b17339a12c279d73869c74a37642035cd2f896f8 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:28 +0200 Subject: [PATCH 2062/5416] atmel-mci: Fix memory leak in atmci_regs_show The debugfs hook atmci_regs_show allocates a temporary buffer for storing a register snapshot, but it doesn't free it before returning. Plug this leak. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 6de773d3a0c..becca914507 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -218,6 +218,8 @@ static int atmci_regs_show(struct seq_file *s, void *v) atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + kfree(buf); + return 0; } -- GitLab From 75d33cc751214f8388d58fca3ef6d1df786b5861 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:29 +0200 Subject: [PATCH 2063/5416] atmel-mci: Fix bogus debugfs file size We used to store a binary register snapshot in the "regs" file, so we set the file size to be the size of this snapshot. This is no longer valid since we switched to using seq_file. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index becca914507..39096083bb6 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -241,7 +241,6 @@ static void atmci_init_debugfs(struct atmel_mci *host) struct mmc_host *mmc; struct dentry *root; struct dentry *node; - struct resource *res; mmc = host->mmc; root = mmc->debugfs_root; @@ -255,9 +254,6 @@ static void atmci_init_debugfs(struct atmel_mci *host) if (!node) goto err; - res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); - node->d_inode->i_size = res->end - res->start + 1; - node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops); if (!node) goto err; -- GitLab From da45b66ec89bbf3a1c172688c35d4d3a6e8e757f Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:30 +0200 Subject: [PATCH 2064/5416] atmel-mci: Set MMC_CAP_NEEDS_POLL if no detect_pin This allows the mmc core to detect card insertion/removal for slots that don't have any CD pin wired up. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 39096083bb6..917035e16da 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1059,6 +1059,10 @@ static int __init atmci_probe(struct platform_device *pdev) host->present = !gpio_get_value(host->detect_pin); } } + + if (!gpio_is_valid(host->detect_pin)) + mmc->caps |= MMC_CAP_NEEDS_POLL; + if (gpio_is_valid(host->wp_pin)) { if (gpio_request(host->wp_pin, "mmc_wp")) { dev_dbg(&mmc->class_dev, "no WP pin available\n"); -- GitLab From 9d4e98e9609bc19d4a8ac4a5c3218358d1820114 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 13 Sep 2008 19:02:07 +0900 Subject: [PATCH 2065/5416] mmc_block: handle error from mmc_register_driver() Check error from mmc_register_driver() and properly unwind block device registration. Signed-off-by: Akinobu Mita Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 86dbb366415..43d9a5b53e8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -613,14 +613,19 @@ static struct mmc_driver mmc_driver = { static int __init mmc_blk_init(void) { - int res = -ENOMEM; + int res; res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); if (res) goto out; - return mmc_register_driver(&mmc_driver); + res = mmc_register_driver(&mmc_driver); + if (res) + goto out2; + return 0; + out2: + unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); out: return res; } -- GitLab From a650031a6bd16cb6789da9b3c27fc97341239f12 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 13 Sep 2008 19:03:32 +0900 Subject: [PATCH 2066/5416] mmc_test: initialize mmc_test_lock statically The mutex mmc_test_lock is initialized at every time mmc_test device is probed. Probing another mmc_test device may break the mutex, if the probe function is called while the mutex is locked. This patch fixes it by statically initializing mmc_test_lock. Signed-off-by: Akinobu Mita Signed-off-by: Pierre Ossman --- drivers/mmc/card/mmc_test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index f26b01d811a..b92b172074e 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -1040,7 +1040,7 @@ static const struct mmc_test_case mmc_test_cases[] = { }; -static struct mutex mmc_test_lock; +static DEFINE_MUTEX(mmc_test_lock); static void mmc_test_run(struct mmc_test_card *test, int testcase) { @@ -1171,8 +1171,6 @@ static int mmc_test_probe(struct mmc_card *card) if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD)) return -ENODEV; - mutex_init(&mmc_test_lock); - ret = device_create_file(&card->dev, &dev_attr_test); if (ret) return ret; -- GitLab From b9012e0a4255c93e1d81f1ccee591de6414b5955 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Sat, 20 Sep 2008 20:05:21 -0700 Subject: [PATCH 2067/5416] IB/ehca: Generate flush status CQ entries When a QP goes into error state, it is required that CQ entries with a flush error status are delivered to the application for any outstanding work requests. eHCA does not do this in hardware, so this patch adds software flush CQE generation to the ehca driver. Whenever a QP gets into error state, it is added to the QP error list of its respective CQ. If the error QP list of a CQ is not empty, poll_cq() generates flush CQEs before polling the actual CQ. Signed-off-by: Alexander Schmidt Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_classes.h | 14 +- drivers/infiniband/hw/ehca/ehca_cq.c | 3 + drivers/infiniband/hw/ehca/ehca_iverbs.h | 2 + drivers/infiniband/hw/ehca/ehca_qp.c | 225 ++++++++++++++++++++-- drivers/infiniband/hw/ehca/ehca_reqs.c | 211 +++++++++++++++++--- 5 files changed, 412 insertions(+), 43 deletions(-) diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 1ab919f836a..5d7b7855afb 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -164,6 +164,13 @@ struct ehca_qmap_entry { u16 reported; }; +struct ehca_queue_map { + struct ehca_qmap_entry *map; + unsigned int entries; + unsigned int tail; + unsigned int left_to_poll; +}; + struct ehca_qp { union { struct ib_qp ib_qp; @@ -173,8 +180,9 @@ struct ehca_qp { enum ehca_ext_qp_type ext_type; enum ib_qp_state state; struct ipz_queue ipz_squeue; - struct ehca_qmap_entry *sq_map; + struct ehca_queue_map sq_map; struct ipz_queue ipz_rqueue; + struct ehca_queue_map rq_map; struct h_galpas galpas; u32 qkey; u32 real_qp_num; @@ -204,6 +212,8 @@ struct ehca_qp { atomic_t nr_events; /* events seen */ wait_queue_head_t wait_completion; int mig_armed; + struct list_head sq_err_node; + struct list_head rq_err_node; }; #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ) @@ -233,6 +243,8 @@ struct ehca_cq { /* mmap counter for resources mapped into user space */ u32 mm_count_queue; u32 mm_count_galpa; + struct list_head sqp_err_list; + struct list_head rqp_err_list; }; enum ehca_mr_flag { diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 5540b276a33..33647a95eb9 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c @@ -276,6 +276,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, for (i = 0; i < QP_HASHTAB_LEN; i++) INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]); + INIT_LIST_HEAD(&my_cq->sqp_err_list); + INIT_LIST_HEAD(&my_cq->rqp_err_list); + if (context) { struct ipz_queue *ipz_queue = &my_cq->ipz_queue; struct ehca_create_cq_resp resp; diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index a8a2ea585d2..8f7f282ead6 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -197,6 +197,8 @@ void ehca_poll_eqs(unsigned long data); int ehca_calc_ipd(struct ehca_shca *shca, int port, enum ib_rate path_rate, u32 *ipd); +void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq); + #ifdef CONFIG_PPC_64K_PAGES void *ehca_alloc_fw_ctrlblock(gfp_t flags); void ehca_free_fw_ctrlblock(void *ptr); diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index b6bcee03673..4dbe2870e01 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -396,6 +396,50 @@ static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue, queue->is_small = (queue->page_size != 0); } +/* needs to be called with cq->spinlock held */ +void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq) +{ + struct list_head *list, *node; + + /* TODO: support low latency QPs */ + if (qp->ext_type == EQPT_LLQP) + return; + + if (on_sq) { + list = &qp->send_cq->sqp_err_list; + node = &qp->sq_err_node; + } else { + list = &qp->recv_cq->rqp_err_list; + node = &qp->rq_err_node; + } + + if (list_empty(node)) + list_add_tail(node, list); + + return; +} + +static void del_from_err_list(struct ehca_cq *cq, struct list_head *node) +{ + unsigned long flags; + + spin_lock_irqsave(&cq->spinlock, flags); + + if (!list_empty(node)) + list_del_init(node); + + spin_unlock_irqrestore(&cq->spinlock, flags); +} + +static void reset_queue_map(struct ehca_queue_map *qmap) +{ + int i; + + qmap->tail = 0; + for (i = 0; i < qmap->entries; i++) + qmap->map[i].reported = 1; +} + /* * Create an ib_qp struct that is either a QP or an SRQ, depending on * the value of the is_srq parameter. If init_attr and srq_init_attr share @@ -407,12 +451,11 @@ static struct ehca_qp *internal_create_qp( struct ib_srq_init_attr *srq_init_attr, struct ib_udata *udata, int is_srq) { - struct ehca_qp *my_qp; + struct ehca_qp *my_qp, *my_srq = NULL; struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, ib_device); struct ib_ucontext *context = NULL; - u32 nr_qes; u64 h_ret; int is_llqp = 0, has_srq = 0; int qp_type, max_send_sge, max_recv_sge, ret; @@ -457,8 +500,7 @@ static struct ehca_qp *internal_create_qp( /* handle SRQ base QPs */ if (init_attr->srq) { - struct ehca_qp *my_srq = - container_of(init_attr->srq, struct ehca_qp, ib_srq); + my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq); has_srq = 1; parms.ext_type = EQPT_SRQBASE; @@ -716,15 +758,19 @@ static struct ehca_qp *internal_create_qp( "and pages ret=%i", ret); goto create_qp_exit2; } - nr_qes = my_qp->ipz_squeue.queue_length / + + my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length / my_qp->ipz_squeue.qe_size; - my_qp->sq_map = vmalloc(nr_qes * + my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries * sizeof(struct ehca_qmap_entry)); - if (!my_qp->sq_map) { + if (!my_qp->sq_map.map) { ehca_err(pd->device, "Couldn't allocate squeue " "map ret=%i", ret); goto create_qp_exit3; } + INIT_LIST_HEAD(&my_qp->sq_err_node); + /* to avoid the generation of bogus flush CQEs */ + reset_queue_map(&my_qp->sq_map); } if (HAS_RQ(my_qp)) { @@ -736,6 +782,25 @@ static struct ehca_qp *internal_create_qp( "and pages ret=%i", ret); goto create_qp_exit4; } + + my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length / + my_qp->ipz_rqueue.qe_size; + my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries * + sizeof(struct ehca_qmap_entry)); + if (!my_qp->rq_map.map) { + ehca_err(pd->device, "Couldn't allocate squeue " + "map ret=%i", ret); + goto create_qp_exit5; + } + INIT_LIST_HEAD(&my_qp->rq_err_node); + /* to avoid the generation of bogus flush CQEs */ + reset_queue_map(&my_qp->rq_map); + } else if (init_attr->srq) { + /* this is a base QP, use the queue map of the SRQ */ + my_qp->rq_map = my_srq->rq_map; + INIT_LIST_HEAD(&my_qp->rq_err_node); + + my_qp->ipz_rqueue = my_srq->ipz_rqueue; } if (is_srq) { @@ -799,7 +864,7 @@ static struct ehca_qp *internal_create_qp( if (ret) { ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%i", ret); - goto create_qp_exit6; + goto create_qp_exit7; } } @@ -825,25 +890,29 @@ static struct ehca_qp *internal_create_qp( if (ib_copy_to_udata(udata, &resp, sizeof resp)) { ehca_err(pd->device, "Copy to udata failed"); ret = -EINVAL; - goto create_qp_exit7; + goto create_qp_exit8; } } return my_qp; -create_qp_exit7: +create_qp_exit8: ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num); -create_qp_exit6: +create_qp_exit7: kfree(my_qp->mod_qp_parm); +create_qp_exit6: + if (HAS_RQ(my_qp)) + vfree(my_qp->rq_map.map); + create_qp_exit5: if (HAS_RQ(my_qp)) ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); create_qp_exit4: if (HAS_SQ(my_qp)) - vfree(my_qp->sq_map); + vfree(my_qp->sq_map.map); create_qp_exit3: if (HAS_SQ(my_qp)) @@ -1035,6 +1104,101 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, return 0; } +static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, + struct ehca_queue_map *qmap) +{ + void *wqe_v; + u64 q_ofs; + u32 wqe_idx; + + /* convert real to abs address */ + wqe_p = wqe_p & (~(1UL << 63)); + + wqe_v = abs_to_virt(wqe_p); + + if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) { + ehca_gen_err("Invalid offset for calculating left cqes " + "wqe_p=%#lx wqe_v=%p\n", wqe_p, wqe_v); + return -EFAULT; + } + + wqe_idx = q_ofs / ipz_queue->qe_size; + if (wqe_idx < qmap->tail) + qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx; + else + qmap->left_to_poll = wqe_idx - qmap->tail; + + return 0; +} + +static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) +{ + u64 h_ret; + void *send_wqe_p, *recv_wqe_p; + int ret; + unsigned long flags; + int qp_num = my_qp->ib_qp.qp_num; + + /* this hcall is not supported on base QPs */ + if (my_qp->ext_type != EQPT_SRQBASE) { + /* get send and receive wqe pointer */ + h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, + my_qp->ipz_qp_handle, &my_qp->pf, + &send_wqe_p, &recv_wqe_p, 4); + if (h_ret != H_SUCCESS) { + ehca_err(&shca->ib_device, "disable_and_get_wqe() " + "failed ehca_qp=%p qp_num=%x h_ret=%li", + my_qp, qp_num, h_ret); + return ehca2ib_return_code(h_ret); + } + + /* + * acquire lock to ensure that nobody is polling the cq which + * could mean that the qmap->tail pointer is in an + * inconsistent state. + */ + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue, + &my_qp->sq_map); + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + if (ret) + return ret; + + + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue, + &my_qp->rq_map); + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); + if (ret) + return ret; + } else { + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + my_qp->sq_map.left_to_poll = 0; + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + my_qp->rq_map.left_to_poll = 0; + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); + } + + /* this assures flush cqes being generated only for pending wqes */ + if ((my_qp->sq_map.left_to_poll == 0) && + (my_qp->rq_map.left_to_poll == 0)) { + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + ehca_add_to_err_list(my_qp, 1); + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + + if (HAS_RQ(my_qp)) { + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + ehca_add_to_err_list(my_qp, 0); + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, + flags); + } + } + + return 0; +} + /* * internal_modify_qp with circumvention to handle aqp0 properly * smi_reset2init indicates if this is an internal reset-to-init-call for @@ -1539,10 +1703,27 @@ static int internal_modify_qp(struct ib_qp *ibqp, goto modify_qp_exit2; } } + if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) { + ret = check_for_left_cqes(my_qp, shca); + if (ret) + goto modify_qp_exit2; + } if (statetrans == IB_QPST_ANY2RESET) { ipz_qeit_reset(&my_qp->ipz_rqueue); ipz_qeit_reset(&my_qp->ipz_squeue); + + if (qp_cur_state == IB_QPS_ERR) { + del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); + + if (HAS_RQ(my_qp)) + del_from_err_list(my_qp->recv_cq, + &my_qp->rq_err_node); + } + reset_queue_map(&my_qp->sq_map); + + if (HAS_RQ(my_qp)) + reset_queue_map(&my_qp->rq_map); } if (attr_mask & IB_QP_QKEY) @@ -1958,6 +2139,16 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, idr_remove(&ehca_qp_idr, my_qp->token); write_unlock_irqrestore(&ehca_qp_idr_lock, flags); + /* + * SRQs will never get into an error list and do not have a recv_cq, + * so we need to skip them here. + */ + if (HAS_RQ(my_qp) && !IS_SRQ(my_qp)) + del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node); + + if (HAS_SQ(my_qp)) + del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); + /* now wait until all pending events have completed */ wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events)); @@ -1983,7 +2174,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, if (qp_type == IB_QPT_GSI) { struct ib_event event; ehca_info(dev, "device %s: port %x is inactive.", - shca->ib_device.name, port_num); + shca->ib_device.name, port_num); event.device = &shca->ib_device; event.event = IB_EVENT_PORT_ERR; event.element.port_num = port_num; @@ -1991,11 +2182,15 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, ib_dispatch_event(&event); } - if (HAS_RQ(my_qp)) + if (HAS_RQ(my_qp)) { ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); + + vfree(my_qp->rq_map.map); + } if (HAS_SQ(my_qp)) { ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); - vfree(my_qp->sq_map); + + vfree(my_qp->sq_map.map); } kmem_cache_free(qp_cache, my_qp); atomic_dec(&shca->num_qps); diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 4426d82fe79..64928079eaf 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -53,9 +53,25 @@ /* in RC traffic, insert an empty RDMA READ every this many packets */ #define ACK_CIRC_THRESHOLD 2000000 +static u64 replace_wr_id(u64 wr_id, u16 idx) +{ + u64 ret; + + ret = wr_id & ~QMAP_IDX_MASK; + ret |= idx & QMAP_IDX_MASK; + + return ret; +} + +static u16 get_app_wr_id(u64 wr_id) +{ + return wr_id & QMAP_IDX_MASK; +} + static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, struct ehca_wqe *wqe_p, - struct ib_recv_wr *recv_wr) + struct ib_recv_wr *recv_wr, + u32 rq_map_idx) { u8 cnt_ds; if (unlikely((recv_wr->num_sge < 0) || @@ -69,7 +85,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, /* clear wqe header until sglist */ memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - wqe_p->work_request_id = recv_wr->wr_id; + wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx); wqe_p->nr_of_data_seg = recv_wr->num_sge; for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) { @@ -146,6 +162,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, u64 dma_length; struct ehca_av *my_av; u32 remote_qkey = send_wr->wr.ud.remote_qkey; + struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx]; if (unlikely((send_wr->num_sge < 0) || (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) { @@ -158,11 +175,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, /* clear wqe header until sglist */ memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK; - wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK; + wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx); - qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK; - qp->sq_map[sq_map_idx].reported = 0; + qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); + qmap_entry->reported = 0; switch (send_wr->opcode) { case IB_WR_SEND: @@ -496,7 +512,9 @@ static int internal_post_recv(struct ehca_qp *my_qp, struct ehca_wqe *wqe_p; int wqe_cnt = 0; int ret = 0; + u32 rq_map_idx; unsigned long flags; + struct ehca_qmap_entry *qmap_entry; if (unlikely(!HAS_RQ(my_qp))) { ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d", @@ -524,8 +542,15 @@ static int internal_post_recv(struct ehca_qp *my_qp, } goto post_recv_exit0; } + /* + * Get the index of the WQE in the recv queue. The same index + * is used for writing into the rq_map. + */ + rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size; + /* write a RECV WQE into the QUEUE */ - ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr); + ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr, + rq_map_idx); /* * if something failed, * reset the free entry pointer to the start value @@ -540,6 +565,11 @@ static int internal_post_recv(struct ehca_qp *my_qp, } goto post_recv_exit0; } + + qmap_entry = &my_qp->rq_map.map[rq_map_idx]; + qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); + qmap_entry->reported = 0; + wqe_cnt++; } /* eof for cur_recv_wr */ @@ -596,10 +626,12 @@ static const u8 ib_wc_opcode[255] = { /* internal function to poll one entry of cq */ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) { - int ret = 0; + int ret = 0, qmap_tail_idx; struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); struct ehca_cqe *cqe; struct ehca_qp *my_qp; + struct ehca_qmap_entry *qmap_entry; + struct ehca_queue_map *qmap; int cqe_count = 0, is_error; repoll: @@ -674,27 +706,52 @@ repoll: goto repoll; wc->qp = &my_qp->ib_qp; - if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) { - struct ehca_qmap_entry *qmap_entry; + if (is_error) { /* - * We got a send completion and need to restore the original - * wr_id. + * set left_to_poll to 0 because in error state, we will not + * get any additional CQEs */ - qmap_entry = &my_qp->sq_map[cqe->work_request_id & - QMAP_IDX_MASK]; + ehca_add_to_err_list(my_qp, 1); + my_qp->sq_map.left_to_poll = 0; - if (qmap_entry->reported) { - ehca_warn(cq->device, "Double cqe on qp_num=%#x", - my_qp->real_qp_num); - /* found a double cqe, discard it and read next one */ - goto repoll; - } - wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK; - wc->wr_id |= qmap_entry->app_wr_id; - qmap_entry->reported = 1; - } else + if (HAS_RQ(my_qp)) + ehca_add_to_err_list(my_qp, 0); + my_qp->rq_map.left_to_poll = 0; + } + + qmap_tail_idx = get_app_wr_id(cqe->work_request_id); + if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) + /* We got a send completion. */ + qmap = &my_qp->sq_map; + else /* We got a receive completion. */ - wc->wr_id = cqe->work_request_id; + qmap = &my_qp->rq_map; + + qmap_entry = &qmap->map[qmap_tail_idx]; + if (qmap_entry->reported) { + ehca_warn(cq->device, "Double cqe on qp_num=%#x", + my_qp->real_qp_num); + /* found a double cqe, discard it and read next one */ + goto repoll; + } + + wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); + qmap_entry->reported = 1; + + /* this is a proper completion, we need to advance the tail pointer */ + if (++qmap->tail == qmap->entries) + qmap->tail = 0; + + /* if left_to_poll is decremented to 0, add the QP to the error list */ + if (qmap->left_to_poll > 0) { + qmap->left_to_poll--; + if ((my_qp->sq_map.left_to_poll == 0) && + (my_qp->rq_map.left_to_poll == 0)) { + ehca_add_to_err_list(my_qp, 1); + if (HAS_RQ(my_qp)) + ehca_add_to_err_list(my_qp, 0); + } + } /* eval ib_wc_opcode */ wc->opcode = ib_wc_opcode[cqe->optype]-1; @@ -733,13 +790,88 @@ poll_cq_one_exit0: return ret; } +static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, + struct ib_wc *wc, int num_entries, + struct ipz_queue *ipz_queue, int on_sq) +{ + int nr = 0; + struct ehca_wqe *wqe; + u64 offset; + struct ehca_queue_map *qmap; + struct ehca_qmap_entry *qmap_entry; + + if (on_sq) + qmap = &my_qp->sq_map; + else + qmap = &my_qp->rq_map; + + qmap_entry = &qmap->map[qmap->tail]; + + while ((nr < num_entries) && (qmap_entry->reported == 0)) { + /* generate flush CQE */ + memset(wc, 0, sizeof(*wc)); + + offset = qmap->tail * ipz_queue->qe_size; + wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); + if (!wqe) { + ehca_err(cq->device, "Invalid wqe offset=%#lx on " + "qp_num=%#x", offset, my_qp->real_qp_num); + return nr; + } + + wc->wr_id = replace_wr_id(wqe->work_request_id, + qmap_entry->app_wr_id); + + if (on_sq) { + switch (wqe->optype) { + case WQE_OPTYPE_SEND: + wc->opcode = IB_WC_SEND; + break; + case WQE_OPTYPE_RDMAWRITE: + wc->opcode = IB_WC_RDMA_WRITE; + break; + case WQE_OPTYPE_RDMAREAD: + wc->opcode = IB_WC_RDMA_READ; + break; + default: + ehca_err(cq->device, "Invalid optype=%x", + wqe->optype); + return nr; + } + } else + wc->opcode = IB_WC_RECV; + + if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) { + wc->ex.imm_data = wqe->immediate_data; + wc->wc_flags |= IB_WC_WITH_IMM; + } + + wc->status = IB_WC_WR_FLUSH_ERR; + + wc->qp = &my_qp->ib_qp; + + /* mark as reported and advance tail pointer */ + qmap_entry->reported = 1; + if (++qmap->tail == qmap->entries) + qmap->tail = 0; + qmap_entry = &qmap->map[qmap->tail]; + + wc++; nr++; + } + + return nr; + +} + int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) { struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); int nr; + struct ehca_qp *err_qp; struct ib_wc *current_wc = wc; int ret = 0; unsigned long flags; + int entries_left = num_entries; if (num_entries < 1) { ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p " @@ -749,15 +881,40 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) } spin_lock_irqsave(&my_cq->spinlock, flags); - for (nr = 0; nr < num_entries; nr++) { + + /* generate flush cqes for send queues */ + list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) { + nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, + &err_qp->ipz_squeue, 1); + entries_left -= nr; + current_wc += nr; + + if (entries_left == 0) + break; + } + + /* generate flush cqes for receive queues */ + list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) { + nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, + &err_qp->ipz_rqueue, 0); + entries_left -= nr; + current_wc += nr; + + if (entries_left == 0) + break; + } + + for (nr = 0; nr < entries_left; nr++) { ret = ehca_poll_cq_one(cq, current_wc); if (ret) break; current_wc++; } /* eof for nr */ + entries_left -= nr; + spin_unlock_irqrestore(&my_cq->spinlock, flags); if (ret == -EAGAIN || !ret) - ret = nr; + ret = num_entries - entries_left; poll_cq_exit0: return ret; -- GitLab From 940358967599ba9057b3c51ba906e1cd5b984729 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Sat, 20 Sep 2008 20:05:51 -0700 Subject: [PATCH 2068/5416] IB/ipath: Fix SLID generation for RC/UC QPs when LMC > 0 The code to set the source LID in the sent LRH was not setting the low bits if LMC != 0 for RC/UC QPs. Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_rc.c | 3 ++- drivers/infiniband/hw/ipath/ipath_ruc.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 97710522624..7b93cda1a4b 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -675,7 +675,8 @@ static void send_rc_ack(struct ipath_qp *qp) hdr.lrh[0] = cpu_to_be16(lrh0); hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); - hdr.lrh[3] = cpu_to_be16(dd->ipath_lid); + hdr.lrh[3] = cpu_to_be16(dd->ipath_lid | + qp->remote_ah_attr.src_path_bits); ohdr->bth[0] = cpu_to_be32(bth0); ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK); diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index af051f75766..fc0f6d9e603 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -618,7 +618,8 @@ void ipath_make_ruc_header(struct ipath_ibdev *dev, struct ipath_qp *qp, qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC); - qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid); + qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid | + qp->remote_ah_attr.src_path_bits); bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index); bth0 |= extra_bytes << 20; ohdr->bth[0] = cpu_to_be32(bth0 | (1 << 22)); -- GitLab From 7097228c54e7348d8c8c6dccc96e50191e39c2f8 Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Sat, 20 Sep 2008 20:06:16 -0700 Subject: [PATCH 2069/5416] IB/mad: Don't discard BMA responses in kernel This fixes the problem of incoming BMA responses being dropped due to a bad "is response" check. Fix the test to use the ib_response_mad() predicate, which correctly handles BMA MADs. This fixes . Signed-off-by: Michael Brooks Acked-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 1adf2efd3cb..49c45feccd5 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1697,9 +1697,8 @@ static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv, u8 port_num = mad_agent_priv->agent.port_num; u8 lmc; - send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> - mad_hdr.method & IB_MGMT_METHOD_RESP; - rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; + send_resp = ib_response_mad((struct ib_mad *)wr->send_buf.mad); + rcv_resp = ib_response_mad(rwc->recv_buf.mad); if (send_resp == rcv_resp) /* both requests, or both responses. GIDs different */ -- GitLab From cd86f420614c1a2dea9c21d7f4f1acb5ec2465b2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 20 Sep 2008 20:06:32 -0700 Subject: [PATCH 2070/5416] IB: Drop code after return statement A break after a return serves no purpose, remove it. Signed-off-by: Julia Lawall Reviewed-by: Richard Genoud Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_provider.c | 1 - drivers/infiniband/hw/nes/nes_verbs.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index 2acf9b62cf9..69580e282af 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c @@ -272,7 +272,6 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd, pr_debug("%s: Invalid QP type: %d\n", __func__, init_attr->qp_type); return ERR_PTR(-EINVAL); - break; } if (err) { diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index d79942e8497..932e56fcf77 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1467,7 +1467,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, default: nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type); return ERR_PTR(-EINVAL); - break; } /* update the QP table */ @@ -2498,7 +2497,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr); return ibmr; - break; case IWNES_MEMREG_TYPE_QP: case IWNES_MEMREG_TYPE_CQ: nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); @@ -2572,7 +2570,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, nesmr->ibmr.lkey = -1; nesmr->mode = req.reg_type; return &nesmr->ibmr; - break; } return ERR_PTR(-ENOSYS); -- GitLab From 64edc2736e23994e0334b70c5ff08dc33e2ebbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:18:32 -0700 Subject: [PATCH 2071/5416] tcp: Partial hint clearing has again become meaningless MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ie., the difference between partial and all clearing doesn't exists anymore since the SACK optimizations got dropped by an sacktag rewrite. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/net/tcp.h | 7 +------ net/ipv4/tcp_input.c | 5 ++--- net/ipv4/tcp_output.c | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 8983386356a..b7167632695 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1035,7 +1035,7 @@ static inline void tcp_mib_init(struct net *net) } /* from STCP */ -static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp) +static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) { tp->lost_skb_hint = NULL; tp->scoreboard_skb_hint = NULL; @@ -1043,11 +1043,6 @@ static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp) tp->forward_skb_hint = NULL; } -static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) -{ - tcp_clear_retrans_hints_partial(tp); -} - /* MD5 Signature */ struct crypto_hash; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f79a5160729..7306bfb16cd 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1883,7 +1883,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) tp->high_seq = tp->snd_nxt; TCP_ECN_queue_cwr(tp); - tcp_clear_retrans_hints_partial(tp); + tcp_clear_all_retrans_hints(tp); } static void tcp_clear_retrans_partial(struct tcp_sock *tp) @@ -1934,12 +1934,11 @@ void tcp_enter_loss(struct sock *sk, int how) /* Push undo marker, if it was plain RTO and nothing * was retransmitted. */ tp->undo_marker = tp->snd_una; - tcp_clear_retrans_hints_partial(tp); } else { tp->sacked_out = 0; tp->fackets_out = 0; - tcp_clear_all_retrans_hints(tp); } + tcp_clear_all_retrans_hints(tp); tcp_for_write_queue(skb, sk) { if (skb == tcp_send_head(sk)) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8165f5aa8c7..11490958a09 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -750,7 +750,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, BUG_ON(len > skb->len); - tcp_clear_retrans_hints_partial(tp); + tcp_clear_all_retrans_hints(tp); nsize = skb_headlen(skb) - len; if (nsize < 0) nsize = 0; @@ -1823,7 +1823,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, tp->packets_out -= tcp_skb_pcount(next_skb); /* changed transmit queue under us so clear hints */ - tcp_clear_retrans_hints_partial(tp); + tcp_clear_all_retrans_hints(tp); sk_wmem_free_skb(sk, next_skb); } -- GitLab From c8c213f20ce97c66fe2ff86f33814d1ca0f9d7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:18:55 -0700 Subject: [PATCH 2072/5416] tcp: move tcp_verify_retransmit_hint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7306bfb16cd..9e95ad637db 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -979,6 +979,19 @@ static void tcp_update_reordering(struct sock *sk, const int metric, } } +/* RFC: This is from the original, I doubt that this is necessary at all: + * clear xmit_retrans hint if seq of this skb is beyond hint. How could we + * retransmitted past LOST markings in the first place? I'm not fully sure + * about undo and end of connection cases, which can cause R without L? + */ +static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) +{ + if ((tp->retransmit_skb_hint != NULL) && + before(TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) + tp->retransmit_skb_hint = NULL; +} + /* This procedure tags the retransmission queue when SACKs arrive. * * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). @@ -2156,19 +2169,6 @@ static int tcp_time_to_recover(struct sock *sk) return 0; } -/* RFC: This is from the original, I doubt that this is necessary at all: - * clear xmit_retrans hint if seq of this skb is beyond hint. How could we - * retransmitted past LOST markings in the first place? I'm not fully sure - * about undo and end of connection cases, which can cause R without L? - */ -static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) -{ - if ((tp->retransmit_skb_hint != NULL) && - before(TCP_SKB_CB(skb)->seq, - TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) - tp->retransmit_skb_hint = NULL; -} - /* Mark head of queue up as lost. With RFC3517 SACK, the packets is * is against sacked "cnt", otherwise it's against facked "cnt" */ -- GitLab From 41ea36e35a0daa75377b3e70680e5c3a3f83fe27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:19:22 -0700 Subject: [PATCH 2073/5416] tcp: add helper for lost bit toggling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This useful because we'd need to verifying soon in many places which makes things slightly more complex than it used to be. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9e95ad637db..12512336dbd 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -992,6 +992,16 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) tp->retransmit_skb_hint = NULL; } +static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) +{ + if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { + tcp_verify_retransmit_hint(tp, skb); + + tp->lost_out += tcp_skb_pcount(skb); + TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; + } +} + /* This procedure tags the retransmission queue when SACKs arrive. * * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). @@ -2216,11 +2226,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) cnt = packets; } - if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { - TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; - tp->lost_out += tcp_skb_pcount(skb); - tcp_verify_retransmit_hint(tp, skb); - } + tcp_skb_mark_lost(tp, skb); } tcp_verify_left_out(tp); } @@ -2262,11 +2268,7 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) if (!tcp_skb_timedout(sk, skb)) break; - if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { - TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; - tp->lost_out += tcp_skb_pcount(skb); - tcp_verify_retransmit_hint(tp, skb); - } + tcp_skb_mark_lost(tp, skb); } tp->scoreboard_skb_hint = skb; -- GitLab From 006f582c73f4eda35e06fd323193c3df43fb3459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:20:20 -0700 Subject: [PATCH 2074/5416] tcp: convert retransmit_cnt_hint to seqno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Main benefit in this is that we can then freely point the retransmit_skb_hint to anywhere we want to because there's no longer need to know what would be the count changes involve, and since this is really used only as a terminator, unnecessary work is one time walk at most, and if some retransmissions are necessary after that point later on, the walk is not full waste of time anyway. Since retransmit_high must be kept valid, all lost markers must ensure that. Now I also have learned how those "holes" in the rexmittable skbs can appear, mtu probe does them. So I removed the misleading comment as well. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/linux/tcp.h | 2 +- include/net/tcp.h | 2 ++ net/ipv4/tcp_input.c | 34 ++++++++++++++++++++-------------- net/ipv4/tcp_output.c | 25 +++++++------------------ 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 2e2557388e3..d7637c4b284 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -358,7 +358,7 @@ struct tcp_sock { */ int lost_cnt_hint; - int retransmit_cnt_hint; + u32 retransmit_high; /* L-bits may be on up to this seqno */ u32 lost_retrans_low; /* Sent seq after any rxmit (lowest) */ diff --git a/include/net/tcp.h b/include/net/tcp.h index b7167632695..d0e90c50722 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -472,6 +472,8 @@ extern void tcp_send_delayed_ack(struct sock *sk); /* tcp_input.c */ extern void tcp_cwnd_application_limited(struct sock *sk); +extern void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, + struct sk_buff *skb); /* tcp_timer.c */ extern void tcp_init_xmit_timers(struct sock *); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 12512336dbd..d271cc82500 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -979,17 +979,17 @@ static void tcp_update_reordering(struct sock *sk, const int metric, } } -/* RFC: This is from the original, I doubt that this is necessary at all: - * clear xmit_retrans hint if seq of this skb is beyond hint. How could we - * retransmitted past LOST markings in the first place? I'm not fully sure - * about undo and end of connection cases, which can cause R without L? - */ +/* This must be called before lost_out is incremented */ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) { - if ((tp->retransmit_skb_hint != NULL) && + if ((tp->retransmit_skb_hint == NULL) || before(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) - tp->retransmit_skb_hint = NULL; + tp->retransmit_skb_hint = skb; + + if (!tp->lost_out || + after(TCP_SKB_CB(skb)->end_seq, tp->retransmit_high)) + tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; } static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) @@ -1002,6 +1002,16 @@ static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) } } +void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb) +{ + tcp_verify_retransmit_hint(tp, skb); + + if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { + tp->lost_out += tcp_skb_pcount(skb); + TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; + } +} + /* This procedure tags the retransmission queue when SACKs arrive. * * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). @@ -1178,13 +1188,7 @@ static void tcp_mark_lost_retrans(struct sock *sk) TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; tp->retrans_out -= tcp_skb_pcount(skb); - /* clear lost hint */ - tp->retransmit_skb_hint = NULL; - - if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { - tp->lost_out += tcp_skb_pcount(skb); - TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; - } + tcp_skb_mark_lost_uncond_verify(tp, skb); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT); } else { if (before(ack_seq, new_low_seq)) @@ -1890,6 +1894,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tp->lost_out += tcp_skb_pcount(skb); + tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; } } tcp_verify_left_out(tp); @@ -1974,6 +1979,7 @@ void tcp_enter_loss(struct sock *sk, int how) TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tp->lost_out += tcp_skb_pcount(skb); + tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; } } tcp_verify_left_out(tp); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 11490958a09..cfae61b40c4 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1838,7 +1838,7 @@ void tcp_simple_retransmit(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; unsigned int mss = tcp_current_mss(sk, 0); - int lost = 0; + u32 prior_lost = tp->lost_out; tcp_for_write_queue(skb, sk) { if (skb == tcp_send_head(sk)) @@ -1849,17 +1849,13 @@ void tcp_simple_retransmit(struct sock *sk) TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; tp->retrans_out -= tcp_skb_pcount(skb); } - if (!(TCP_SKB_CB(skb)->sacked & TCPCB_LOST)) { - TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; - tp->lost_out += tcp_skb_pcount(skb); - lost = 1; - } + tcp_skb_mark_lost_uncond_verify(tp, skb); } } tcp_clear_all_retrans_hints(tp); - if (!lost) + if (prior_lost == tp->lost_out) return; if (tcp_is_reno(tp)) @@ -2009,15 +2005,11 @@ void tcp_xmit_retransmit_queue(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; - int packet_cnt; - if (tp->retransmit_skb_hint) { + if (tp->retransmit_skb_hint) skb = tp->retransmit_skb_hint; - packet_cnt = tp->retransmit_cnt_hint; - } else { + else skb = tcp_write_queue_head(sk); - packet_cnt = 0; - } /* First pass: retransmit lost packets. */ if (tp->lost_out) { @@ -2028,7 +2020,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk) break; /* we could do better than to assign each time */ tp->retransmit_skb_hint = skb; - tp->retransmit_cnt_hint = packet_cnt; /* Assume this retransmit will generate * only one packet for congestion window @@ -2039,6 +2030,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) */ if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) return; + if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) + break; if (sacked & TCPCB_LOST) { if (!(sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { @@ -2059,10 +2052,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk) inet_csk(sk)->icsk_rto, TCP_RTO_MAX); } - - packet_cnt += tcp_skb_pcount(skb); - if (packet_cnt >= tp->lost_out) - break; } } } -- GitLab From f09142eddb75005e41b0af3e5214979d8b534b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:20:50 -0700 Subject: [PATCH 2075/5416] tcp: Kill precaution that's very likely obsolete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I suspect it might have been related to the changed amount of lost skbs, which was counted by retransmit_cnt_hint that got changed. The place for this clearing was very illogical anyway, it should have been after the LOST-bit clearing loop to make any sense. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d271cc82500..28e93f1e421 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2385,10 +2385,6 @@ static void tcp_undo_cwr(struct sock *sk, const int undo) } tcp_moderate_cwnd(tp); tp->snd_cwnd_stamp = tcp_time_stamp; - - /* There is something screwy going on with the retrans hints after - an undo */ - tcp_clear_all_retrans_hints(tp); } static inline int tcp_may_undo(struct tcp_sock *tp) -- GitLab From 184d68b2b0b836587f92887b14baea41033ffeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:21:16 -0700 Subject: [PATCH 2076/5416] tcp: No need to clear retransmit_skb_hint when SACKing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because lost counter no longer requires tuning, this is trivial to remove (the tuning wouldn't have been too hard either) because no "new" retransmittable skb appeared below retransmit_skb_hint when SACKing for sure. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 28e93f1e421..d017aed6edd 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1298,9 +1298,6 @@ static int tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); tp->lost_out -= tcp_skb_pcount(skb); tp->retrans_out -= tcp_skb_pcount(skb); - - /* clear lost hint */ - tp->retransmit_skb_hint = NULL; } } else { if (!(sacked & TCPCB_RETRANS)) { @@ -1319,9 +1316,6 @@ static int tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, if (sacked & TCPCB_LOST) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; tp->lost_out -= tcp_skb_pcount(skb); - - /* clear lost hint */ - tp->retransmit_skb_hint = NULL; } } @@ -1351,7 +1345,6 @@ static int tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, if (dup_sack && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; tp->retrans_out -= tcp_skb_pcount(skb); - tp->retransmit_skb_hint = NULL; } return flag; -- GitLab From b5afe7bc71a1689376c9b547376d17568469f3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:21:54 -0700 Subject: [PATCH 2077/5416] tcp: add tcp_can_forward_retransmit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 46 ++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index cfae61b40c4..957c4e3d217 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1992,6 +1992,33 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) return err; } +static int tcp_can_forward_retransmit(struct sock *sk) +{ + const struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); + + /* Forward retransmissions are possible only during Recovery. */ + if (icsk->icsk_ca_state != TCP_CA_Recovery) + return 0; + + /* No forward retransmissions in Reno are possible. */ + if (tcp_is_reno(tp)) + return 0; + + /* Yeah, we have to make difficult choice between forward transmission + * and retransmission... Both ways have their merits... + * + * For now we do not retransmit anything, while we have some new + * segments to send. In the other cases, follow rule 3 for + * NextSeg() specified in RFC3517. + */ + + if (tcp_may_send_now(sk)) + return 0; + + return 1; +} + /* This gets called after a retransmit timeout, and the initially * retransmitted data is acknowledged. It tries to continue * resending the rest of the retransmit queue, until either @@ -2057,24 +2084,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) } /* OK, demanded retransmission is finished. */ - - /* Forward retransmissions are possible only during Recovery. */ - if (icsk->icsk_ca_state != TCP_CA_Recovery) - return; - - /* No forward retransmissions in Reno are possible. */ - if (tcp_is_reno(tp)) - return; - - /* Yeah, we have to make difficult choice between forward transmission - * and retransmission... Both ways have their merits... - * - * For now we do not retransmit anything, while we have some new - * segments to send. In the other cases, follow rule 3 for - * NextSeg() specified in RFC3517. - */ - - if (tcp_may_send_now(sk)) + if (!tcp_can_forward_retransmit(sk)) return; /* If nothing is SACKed, highest_sack in the loop won't be valid */ -- GitLab From 34638570b58290e8cb875fb24dcbe836ffeb6cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:22:17 -0700 Subject: [PATCH 2078/5416] tcp: remove obsolete validity concern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 957c4e3d217..6f2a3f4a1af 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2087,10 +2087,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (!tcp_can_forward_retransmit(sk)) return; - /* If nothing is SACKed, highest_sack in the loop won't be valid */ - if (!tp->sacked_out) - return; - if (tp->forward_skb_hint) skb = tp->forward_skb_hint; else -- GitLab From 61eb55f4db7eaf5fb2d5ec12981a8cda755bb0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:22:59 -0700 Subject: [PATCH 2079/5416] tcp: Reorganize skb tagbit checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6f2a3f4a1af..2f24ecc3706 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2032,6 +2032,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; + int mib_idx; if (tp->retransmit_skb_hint) skb = tp->retransmit_skb_hint; @@ -2059,27 +2060,26 @@ void tcp_xmit_retransmit_queue(struct sock *sk) return; if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) break; + if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) + continue; - if (sacked & TCPCB_LOST) { - if (!(sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { - int mib_idx; - - if (tcp_retransmit_skb(sk, skb)) { - tp->retransmit_skb_hint = NULL; - return; - } - if (icsk->icsk_ca_state != TCP_CA_Loss) - mib_idx = LINUX_MIB_TCPFASTRETRANS; - else - mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; - NET_INC_STATS_BH(sock_net(sk), mib_idx); - - if (skb == tcp_write_queue_head(sk)) - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, - inet_csk(sk)->icsk_rto, - TCP_RTO_MAX); - } + if (!(sacked & TCPCB_LOST)) + continue; + + if (tcp_retransmit_skb(sk, skb)) { + tp->retransmit_skb_hint = NULL; + return; } + if (icsk->icsk_ca_state != TCP_CA_Loss) + mib_idx = LINUX_MIB_TCPFASTRETRANS; + else + mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; + NET_INC_STATS_BH(sock_net(sk), mib_idx); + + if (skb == tcp_write_queue_head(sk)) + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + inet_csk(sk)->icsk_rto, + TCP_RTO_MAX); } } -- GitLab From 08ebd1721ab8fd362e90ae17b461c07b23fa2824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:23:49 -0700 Subject: [PATCH 2080/5416] tcp: remove tp->lost_out guard to make joining diff nicer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The validity of the retransmit_high must then be ensured if no L'ed skb exits! This makes a minor change to behavior, we now have to iterate the head to find out that the loop terminates. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 75 ++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 2f24ecc3706..9f44be633ef 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2034,53 +2034,54 @@ void tcp_xmit_retransmit_queue(struct sock *sk) struct sk_buff *skb; int mib_idx; + if (!tp->lost_out) + tp->retransmit_high = tp->snd_una; + if (tp->retransmit_skb_hint) skb = tp->retransmit_skb_hint; else skb = tcp_write_queue_head(sk); /* First pass: retransmit lost packets. */ - if (tp->lost_out) { - tcp_for_write_queue_from(skb, sk) { - __u8 sacked = TCP_SKB_CB(skb)->sacked; + tcp_for_write_queue_from(skb, sk) { + __u8 sacked = TCP_SKB_CB(skb)->sacked; - if (skb == tcp_send_head(sk)) - break; - /* we could do better than to assign each time */ - tp->retransmit_skb_hint = skb; - - /* Assume this retransmit will generate - * only one packet for congestion window - * calculation purposes. This works because - * tcp_retransmit_skb() will chop up the - * packet to be MSS sized and all the - * packet counting works out. - */ - if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) - return; - if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) - break; - if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) - continue; + if (skb == tcp_send_head(sk)) + break; + /* we could do better than to assign each time */ + tp->retransmit_skb_hint = skb; + + /* Assume this retransmit will generate + * only one packet for congestion window + * calculation purposes. This works because + * tcp_retransmit_skb() will chop up the + * packet to be MSS sized and all the + * packet counting works out. + */ + if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) + return; + if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) + break; + if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) + continue; - if (!(sacked & TCPCB_LOST)) - continue; + if (!(sacked & TCPCB_LOST)) + continue; - if (tcp_retransmit_skb(sk, skb)) { - tp->retransmit_skb_hint = NULL; - return; - } - if (icsk->icsk_ca_state != TCP_CA_Loss) - mib_idx = LINUX_MIB_TCPFASTRETRANS; - else - mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; - NET_INC_STATS_BH(sock_net(sk), mib_idx); - - if (skb == tcp_write_queue_head(sk)) - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, - inet_csk(sk)->icsk_rto, - TCP_RTO_MAX); + if (tcp_retransmit_skb(sk, skb)) { + tp->retransmit_skb_hint = NULL; + return; } + if (icsk->icsk_ca_state != TCP_CA_Loss) + mib_idx = LINUX_MIB_TCPFASTRETRANS; + else + mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; + NET_INC_STATS_BH(sock_net(sk), mib_idx); + + if (skb == tcp_write_queue_head(sk)) + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + inet_csk(sk)->icsk_rto, + TCP_RTO_MAX); } /* OK, demanded retransmission is finished. */ -- GitLab From 0e1c54c2a405494281e0639aacc90db03b50ae77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:24:21 -0700 Subject: [PATCH 2081/5416] tcp: reorganize retransmit code loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both loops are quite similar, so they can be combined with little effort. As a result, forward_skb_hint becomes obsolete as well. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 - include/net/tcp.h | 1 - net/ipv4/tcp_output.c | 79 ++++++++++++++++++------------------------- 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d7637c4b284..76729062829 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -342,7 +342,6 @@ struct tcp_sock { struct sk_buff* lost_skb_hint; struct sk_buff *scoreboard_skb_hint; struct sk_buff *retransmit_skb_hint; - struct sk_buff *forward_skb_hint; struct sk_buff_head out_of_order_queue; /* Out of order segments go here */ diff --git a/include/net/tcp.h b/include/net/tcp.h index d0e90c50722..220f54cf42e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1042,7 +1042,6 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) tp->lost_skb_hint = NULL; tp->scoreboard_skb_hint = NULL; tp->retransmit_skb_hint = NULL; - tp->forward_skb_hint = NULL; } /* MD5 Signature */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9f44be633ef..b5b4ddcdda4 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2032,7 +2032,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; + struct sk_buff *hole = NULL; int mib_idx; + int fwd_rexmitting = 0; if (!tp->lost_out) tp->retransmit_high = tp->snd_una; @@ -2049,7 +2051,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (skb == tcp_send_head(sk)) break; /* we could do better than to assign each time */ - tp->retransmit_skb_hint = skb; + if (hole == NULL) + tp->retransmit_skb_hint = skb; /* Assume this retransmit will generate * only one packet for congestion window @@ -2060,65 +2063,49 @@ void tcp_xmit_retransmit_queue(struct sock *sk) */ if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) return; - if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) - break; - if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) - continue; - - if (!(sacked & TCPCB_LOST)) - continue; - - if (tcp_retransmit_skb(sk, skb)) { - tp->retransmit_skb_hint = NULL; - return; - } - if (icsk->icsk_ca_state != TCP_CA_Loss) - mib_idx = LINUX_MIB_TCPFASTRETRANS; - else - mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; - NET_INC_STATS_BH(sock_net(sk), mib_idx); - - if (skb == tcp_write_queue_head(sk)) - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, - inet_csk(sk)->icsk_rto, - TCP_RTO_MAX); - } - - /* OK, demanded retransmission is finished. */ - if (!tcp_can_forward_retransmit(sk)) - return; - if (tp->forward_skb_hint) - skb = tp->forward_skb_hint; - else - skb = tcp_write_queue_head(sk); + if (fwd_rexmitting) { +begin_fwd: + if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) + break; + mib_idx = LINUX_MIB_TCPFORWARDRETRANS; - tcp_for_write_queue_from(skb, sk) { - if (skb == tcp_send_head(sk)) - break; - tp->forward_skb_hint = skb; + } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) { + if (!tcp_can_forward_retransmit(sk)) + break; + /* Backtrack if necessary to non-L'ed skb */ + if (hole != NULL) { + skb = hole; + hole = NULL; + } + fwd_rexmitting = 1; + goto begin_fwd; - if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) - break; + } else if (!(sacked & TCPCB_LOST)) { + if (hole == NULL && !(sacked & TCPCB_SACKED_RETRANS)) + hole = skb; + continue; - if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) - break; + } else { + if (icsk->icsk_ca_state != TCP_CA_Loss) + mib_idx = LINUX_MIB_TCPFASTRETRANS; + else + mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; + } - if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS) + if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) continue; - /* Ok, retransmit it. */ if (tcp_retransmit_skb(sk, skb)) { - tp->forward_skb_hint = NULL; - break; + tp->retransmit_skb_hint = NULL; + return; } + NET_INC_STATS_BH(sock_net(sk), mib_idx); if (skb == tcp_write_queue_head(sk)) inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, inet_csk(sk)->icsk_rto, TCP_RTO_MAX); - - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFORWARDRETRANS); } } -- GitLab From f0ceb0ed86b4792a4ed9d3438f5f7572e48f9803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:24:49 -0700 Subject: [PATCH 2082/5416] tcp: remove retransmit_skb_hint clearing from failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn't much sense here afaict, probably never has. Since fragmenting and collapsing deal the hints by themselves, there should be very little reason for the rexmit loop to do that. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b5b4ddcdda4..f900fae8b87 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2096,10 +2096,8 @@ begin_fwd: if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) continue; - if (tcp_retransmit_skb(sk, skb)) { - tp->retransmit_skb_hint = NULL; + if (tcp_retransmit_skb(sk, skb)) return; - } NET_INC_STATS_BH(sock_net(sk), mib_idx); if (skb == tcp_write_queue_head(sk)) -- GitLab From ef9da47c7cc64d69526331f315e76b5680d4048f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:25:15 -0700 Subject: [PATCH 2083/5416] tcp: don't clear retransmit_skb_hint when not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most importantly avoid doing it with cumulative ACK. Not clearing means that we no longer need n^2 processing in resolution of each fast recovery. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/net/tcp.h | 7 ++++++- net/ipv4/tcp_input.c | 4 +++- net/ipv4/tcp_output.c | 8 +++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 220f54cf42e..ea815723d41 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1037,10 +1037,15 @@ static inline void tcp_mib_init(struct net *net) } /* from STCP */ -static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) +static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp) { tp->lost_skb_hint = NULL; tp->scoreboard_skb_hint = NULL; +} + +static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) +{ + tcp_clear_retrans_hints_partial(tp); tp->retransmit_skb_hint = NULL; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d017aed6edd..44a4fffc2cc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2925,7 +2925,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets) tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); - tcp_clear_all_retrans_hints(tp); + tcp_clear_retrans_hints_partial(tp); + if (skb == tp->retransmit_skb_hint) + tp->retransmit_skb_hint = NULL; } if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f900fae8b87..239cea7b6c0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -750,7 +750,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, BUG_ON(len > skb->len); - tcp_clear_all_retrans_hints(tp); + tcp_clear_retrans_hints_partial(tp); nsize = skb_headlen(skb) - len; if (nsize < 0) nsize = 0; @@ -1823,7 +1823,9 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, tp->packets_out -= tcp_skb_pcount(next_skb); /* changed transmit queue under us so clear hints */ - tcp_clear_all_retrans_hints(tp); + tcp_clear_retrans_hints_partial(tp); + if (next_skb == tp->retransmit_skb_hint) + tp->retransmit_skb_hint = skb; sk_wmem_free_skb(sk, next_skb); } @@ -1853,7 +1855,7 @@ void tcp_simple_retransmit(struct sock *sk) } } - tcp_clear_all_retrans_hints(tp); + tcp_clear_retrans_hints_partial(tp); if (prior_lost == tp->lost_out) return; -- GitLab From 90638a04ad8484b6b6c567656fb3f6d0689e23da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:25:52 -0700 Subject: [PATCH 2084/5416] tcp: don't clear lost_skb_hint when not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most importantly avoid doing it with cumulative ACK. However, since we have lost_cnt_hint in the picture as well needing adjustments, it's not as trivial as dealing with retransmit_skb_hint (and cannot be done in the all place we could trivially leave retransmit_skb_hint untouched). With the previous patch, this should mostly remove O(n^2) behavior while cumulative ACKs start flowing once rexmit after a lossy round-trip made it through. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 44a4fffc2cc..85627f83665 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2844,6 +2844,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets) int flag = 0; u32 pkts_acked = 0; u32 reord = tp->packets_out; + u32 prior_sacked = tp->sacked_out; s32 seq_rtt = -1; s32 ca_seq_rtt = -1; ktime_t last_ackt = net_invalid_timestamp(); @@ -2925,9 +2926,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets) tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); - tcp_clear_retrans_hints_partial(tp); + tp->scoreboard_skb_hint = NULL; if (skb == tp->retransmit_skb_hint) tp->retransmit_skb_hint = NULL; + if (skb == tp->lost_skb_hint) + tp->lost_skb_hint = NULL; } if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) @@ -2946,6 +2949,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets) /* Non-retransmitted hole got filled? That's reordering */ if (reord < prior_fackets) tcp_update_reordering(sk, tp->fackets_out - reord, 0); + + /* No need to care for underflows here because + * the lost_skb_hint gets NULLed if we're past it + * (or something non-trivial happened) + */ + if (tcp_is_fack(tp)) + tp->lost_cnt_hint -= pkts_acked; + else + tp->lost_cnt_hint -= prior_sacked - tp->sacked_out; } tp->fackets_out -= min(pkts_acked, tp->fackets_out); -- GitLab From 618d9f25548ba6fc3a9cd2ce5cd56f4f015b0635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 20 Sep 2008 21:26:22 -0700 Subject: [PATCH 2085/5416] tcp: back retransmit_high when it over-estimated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If lost skb is sacked, we might have nothing to retransmit as high as the retransmit_high is pointing to, so place it lower to avoid unnecessary walking. This is mainly for the case where high L'ed skbs gets sacked. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 239cea7b6c0..8f9793a37b6 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2035,16 +2035,22 @@ void tcp_xmit_retransmit_queue(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; struct sk_buff *hole = NULL; + u32 last_lost; int mib_idx; int fwd_rexmitting = 0; if (!tp->lost_out) tp->retransmit_high = tp->snd_una; - if (tp->retransmit_skb_hint) + if (tp->retransmit_skb_hint) { skb = tp->retransmit_skb_hint; - else + last_lost = TCP_SKB_CB(skb)->end_seq; + if (after(last_lost, tp->retransmit_high)) + last_lost = tp->retransmit_high; + } else { skb = tcp_write_queue_head(sk); + last_lost = tp->snd_una; + } /* First pass: retransmit lost packets. */ tcp_for_write_queue_from(skb, sk) { @@ -2073,6 +2079,7 @@ begin_fwd: mib_idx = LINUX_MIB_TCPFORWARDRETRANS; } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) { + tp->retransmit_high = last_lost; if (!tcp_can_forward_retransmit(sk)) break; /* Backtrack if necessary to non-L'ed skb */ @@ -2089,6 +2096,7 @@ begin_fwd: continue; } else { + last_lost = TCP_SKB_CB(skb)->end_seq; if (icsk->icsk_ca_state != TCP_CA_Loss) mib_idx = LINUX_MIB_TCPFASTRETRANS; else -- GitLab From 7ee766d8fba9dfd93bf3eca7a8d84a25404a68dc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 20 Sep 2008 22:00:40 -0700 Subject: [PATCH 2086/5416] sparc64: Fix disappearing PCI devices on e3500. Based upon a bug report by Meelis Roos. The OF device layer builds properties by matching bus types and applying 'range' properties as appropriate, up to the root. The match for "PCI" busses is looking at the 'device_type' property, and this does work %99 of the time. But on an E3500 system with a PCI QFE card, the DEC 21153 bridge sitting above the QFE network interface devices has a 'name' of "pci", but it completely lacks a 'device_type' property. So we don't match it as a PCI bus, and subsequently we end up with no resource values at all for the devices sitting under that DEC bridge. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f845f150f56..100ebd52749 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -169,7 +169,7 @@ static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long fla static int of_bus_pci_match(struct device_node *np) { - if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + if (!strcmp(np->name, "pci")) { const char *model = of_get_property(np, "model", NULL); if (model && !strcmp(model, "SUNW,simba")) @@ -200,7 +200,7 @@ static int of_bus_simba_match(struct device_node *np) /* Treat PCI busses lacking ranges property just like * simba. */ - if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + if (!strcmp(np->name, "pci")) { if (!of_find_property(np, "ranges", NULL)) return 1; } @@ -429,7 +429,7 @@ static int __init use_1to1_mapping(struct device_node *pp) * it lacks a ranges property, and this will include * cases like Simba. */ - if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex")) + if (!strcmp(pp->name, "pci")) return 0; return 1; @@ -714,8 +714,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, break; } } else { - if (!strcmp(pp->type, "pci") || - !strcmp(pp->type, "pciex")) { + if (!strcmp(pp->name, "pci")) { unsigned int this_orig_irq = irq; irq = pci_irq_swizzle(dp, pp, irq); -- GitLab From ad55dcaff0e34269f86975ce2ea0da22e9eb74a1 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 20 Sep 2008 22:05:50 -0700 Subject: [PATCH 2087/5416] netdev: simple_tx_hash shouldn't hash inside fragments Currently simple_tx_hash is hashing inside of udp fragments. As a result packets are getting getting sent to all queues when they shouldn't be. This causes a serious performance regression which can be seen by sending UDP frames larger than mtu on multiqueue devices. This change will make it so that fragments are hashed only as IP datagrams w/o any protocol information. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index e719ed29310..e8eb2b47834 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include @@ -1667,7 +1668,7 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) { u32 addr1, addr2, ports; u32 hash, ihl; - u8 ip_proto; + u8 ip_proto = 0; if (unlikely(!simple_tx_hashrnd_initialized)) { get_random_bytes(&simple_tx_hashrnd, 4); @@ -1676,7 +1677,8 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) switch (skb->protocol) { case __constant_htons(ETH_P_IP): - ip_proto = ip_hdr(skb)->protocol; + if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) + ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl; -- GitLab From a574420ff46cff0245e6b0fce2e961aa2717743d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 20 Sep 2008 22:07:34 -0700 Subject: [PATCH 2088/5416] multiq: requeue should rewind the current_band Currently dequeueing a packet and requeueing the same packet will cause a different packet to be pulled on the next dequeue. This change forces requeue to rewind the current_band. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/sched/sch_multiq.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 5d9cd68e91d..915f3149dde 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -97,6 +97,7 @@ static int multiq_requeue(struct sk_buff *skb, struct Qdisc *sch) { struct Qdisc *qdisc; + struct multiq_sched_data *q = qdisc_priv(sch); int ret; qdisc = multiq_classify(skb, sch, &ret); @@ -113,6 +114,10 @@ multiq_requeue(struct sk_buff *skb, struct Qdisc *sch) if (ret == NET_XMIT_SUCCESS) { sch->q.qlen++; sch->qstats.requeues++; + if (q->curband) + q->curband--; + else + q->curband = q->bands - 1; return NET_XMIT_SUCCESS; } if (net_xmit_drop_count(ret)) -- GitLab From 6067804047b64dde89f4f133fc7eba48ee44107d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 20 Sep 2008 22:20:49 -0700 Subject: [PATCH 2089/5416] net: Use hton[sl]() instead of __constant_hton[sl]() where applicable Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 2 +- net/atm/br2684.c | 8 ++++---- net/core/dev.c | 4 ++-- net/ethernet/eth.c | 2 +- net/ipv4/ipvs/ip_vs_core.c | 4 ++-- net/ipv6/ip6_tunnel.c | 4 ++-- net/mac80211/wme.c | 2 +- net/sched/cls_flow.c | 28 ++++++++++++++-------------- net/sched/sch_dsmark.c | 8 ++++---- net/sched/sch_sfq.c | 4 ++-- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 97688cdb550..8883e9c8a22 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -48,7 +48,7 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) switch (veth->h_vlan_encapsulated_proto) { #ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): /* TODO: Confirm this will work with VLAN headers... */ return arp_find(veth->h_dest, skb); diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 8d9a6f15888..280de481edc 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -375,11 +375,11 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) if (memcmp (skb->data + 6, ethertype_ipv6, sizeof(ethertype_ipv6)) == 0) - skb->protocol = __constant_htons(ETH_P_IPV6); + skb->protocol = htons(ETH_P_IPV6); else if (memcmp (skb->data + 6, ethertype_ipv4, sizeof(ethertype_ipv4)) == 0) - skb->protocol = __constant_htons(ETH_P_IP); + skb->protocol = htons(ETH_P_IP); else goto error; skb_pull(skb, sizeof(llc_oui_ipv4)); @@ -404,9 +404,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) skb_reset_network_header(skb); iph = ip_hdr(skb); if (iph->version == 4) - skb->protocol = __constant_htons(ETH_P_IP); + skb->protocol = htons(ETH_P_IP); else if (iph->version == 6) - skb->protocol = __constant_htons(ETH_P_IPV6); + skb->protocol = htons(ETH_P_IPV6); else goto error; skb->pkt_type = PACKET_HOST; diff --git a/net/core/dev.c b/net/core/dev.c index f48d1b24f9c..fdfc4b6a644 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1675,13 +1675,13 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) } switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl; break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ip_proto = ipv6_hdr(skb)->nexthdr; addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a80839b02e3..647a9edee37 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -129,7 +129,7 @@ int eth_rebuild_header(struct sk_buff *skb) switch (eth->h_proto) { #ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif default: diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index ece748dbd0c..958abf3e5f8 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -938,7 +938,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, EnterFunction(11); - af = (skb->protocol == __constant_htons(ETH_P_IP)) ? AF_INET : AF_INET6; + af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; if (skb->ipvs_property) return NF_ACCEPT; @@ -1258,7 +1258,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, struct ip_vs_conn *cp; int ret, restart, af; - af = (skb->protocol == __constant_htons(ETH_P_IP)) ? AF_INET : AF_INET6; + af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 17c7b098cdb..64ce3d33d9c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1050,10 +1050,10 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) } switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ret = ip4ip6_tnl_xmit(skb, dev); break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ret = ip6ip6_tnl_xmit(skb, dev); break; default: diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 6748dedcab5..c703f8b44e9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -39,7 +39,7 @@ static unsigned int classify_1d(struct sk_buff *skb) return skb->priority - 256; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): dscp = ip_hdr(skb)->tos & 0xfc; break; diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 8f63a1a9401..0ebaff637e3 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -67,9 +67,9 @@ static inline u32 addr_fold(void *addr) static u32 flow_get_src(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(ip_hdr(skb)->saddr); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); default: return addr_fold(skb->sk); @@ -79,9 +79,9 @@ static u32 flow_get_src(const struct sk_buff *skb) static u32 flow_get_dst(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(ip_hdr(skb)->daddr); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); default: return addr_fold(skb->dst) ^ (__force u16)skb->protocol; @@ -91,9 +91,9 @@ static u32 flow_get_dst(const struct sk_buff *skb) static u32 flow_get_proto(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ip_hdr(skb)->protocol; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ipv6_hdr(skb)->nexthdr; default: return 0; @@ -120,7 +120,7 @@ static u32 flow_get_proto_src(const struct sk_buff *skb) u32 res = 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): { + case htons(ETH_P_IP): { struct iphdr *iph = ip_hdr(skb); if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && @@ -128,7 +128,7 @@ static u32 flow_get_proto_src(const struct sk_buff *skb) res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); break; } - case __constant_htons(ETH_P_IPV6): { + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); if (has_ports(iph->nexthdr)) @@ -147,7 +147,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb) u32 res = 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): { + case htons(ETH_P_IP): { struct iphdr *iph = ip_hdr(skb); if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && @@ -155,7 +155,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb) res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); break; } - case __constant_htons(ETH_P_IPV6): { + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); if (has_ports(iph->nexthdr)) @@ -213,9 +213,9 @@ static u32 flow_get_nfct(const struct sk_buff *skb) static u32 flow_get_nfct_src(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(CTTUPLE(skb, src.u3.ip)); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(CTTUPLE(skb, src.u3.ip6[3])); } fallback: @@ -225,9 +225,9 @@ fallback: static u32 flow_get_nfct_dst(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(CTTUPLE(skb, dst.u3.ip)); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(CTTUPLE(skb, dst.u3.ip6[3])); } fallback: diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index edd1298f85f..ba43aab3a85 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -202,7 +202,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (p->set_tc_index) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): if (skb_cow_head(skb, sizeof(struct iphdr))) goto drop; @@ -210,7 +210,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) & ~INET_ECN_MASK; break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): if (skb_cow_head(skb, sizeof(struct ipv6hdr))) goto drop; @@ -289,11 +289,11 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) pr_debug("index %d->%d\n", skb->tc_index, index); switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ipv4_change_dsfield(ip_hdr(skb), p->mask[index], p->value[index]); break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index], p->value[index]); break; diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 6e041d10dbd..fe1508ef0d3 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -119,7 +119,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) u32 h, h2; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): { const struct iphdr *iph = ip_hdr(skb); h = iph->daddr; @@ -134,7 +134,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) h2 ^= *(((u32*)iph) + iph->ihl); break; } - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); h = iph->daddr.s6_addr32[3]; diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index e55427f73df..5c1954d28d0 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -769,7 +769,7 @@ repost: /* check for expected message types */ /* The order of some of these tests is important. */ switch (headerp->rm_type) { - case __constant_htonl(RDMA_MSG): + case htonl(RDMA_MSG): /* never expect read chunks */ /* never expect reply chunks (two ways to check) */ /* never expect write chunks without having offered RDMA */ @@ -802,7 +802,7 @@ repost: rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); break; - case __constant_htonl(RDMA_NOMSG): + case htonl(RDMA_NOMSG): /* never expect read or write chunks, always reply chunks */ if (headerp->rm_body.rm_chunks[0] != xdr_zero || headerp->rm_body.rm_chunks[1] != xdr_zero || -- GitLab From f5fff5dc8a7a3f395b0525c02ba92c95d42b7390 Mon Sep 17 00:00:00 2001 From: Tom Quetchenbach Date: Sun, 21 Sep 2008 00:21:51 -0700 Subject: [PATCH 2090/5416] tcp: advertise MSS requested by user I'm trying to use the TCP_MAXSEG option to setsockopt() to set the MSS for both sides of a bidirectional connection. man tcp says: "If this option is set before connection establishment, it also changes the MSS value announced to the other end in the initial packet." However, the kernel only uses the MTU/route cache to set the advertised MSS. That means if I set the MSS to, say, 500 before calling connect(), I will send at most 500-byte packets, but I will still receive 1500-byte packets in reply. This is a bug, either in the kernel or the documentation. This patch (applies to latest net-2.6) reduces the advertised value to that requested by the user as long as setsockopt() is called before connect() or accept(). This seems like the behavior that one would expect as well as that which is documented. I've tried to make sure that things that depend on the advertised MSS are set correctly. Signed-off-by: Tom Quetchenbach Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++++ net/ipv4/tcp_output.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3dfbc21e555..44aef1c1f37 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1364,6 +1364,10 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, tcp_mtup_init(newsk); tcp_sync_mss(newsk, dst_mtu(dst)); newtp->advmss = dst_metric(dst, RTAX_ADVMSS); + if (tcp_sk(sk)->rx_opt.user_mss && + tcp_sk(sk)->rx_opt.user_mss < newtp->advmss) + newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; + tcp_initialize_rcv_mss(newsk); #ifdef CONFIG_TCP_MD5SIG diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8f9793a37b6..c3d58ee3e16 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2232,6 +2232,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct sk_buff *skb; struct tcp_md5sig_key *md5; __u8 *md5_hash_location; + int mss; skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); if (skb == NULL) @@ -2242,13 +2243,17 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, skb->dst = dst_clone(dst); + mss = dst_metric(dst, RTAX_ADVMSS); + if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) + mss = tp->rx_opt.user_mss; + if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ __u8 rcv_wscale; /* Set this up on the first call only */ req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW); /* tcp_full_space because it is guaranteed to be the first packet */ tcp_select_initial_window(tcp_full_space(sk), - dst_metric(dst, RTAX_ADVMSS) - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0), + mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0), &req->rcv_wnd, &req->window_clamp, ireq->wscale_ok, @@ -2258,8 +2263,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, memset(&opts, 0, sizeof(opts)); TCP_SKB_CB(skb)->when = tcp_time_stamp; - tcp_header_size = tcp_synack_options(sk, req, - dst_metric(dst, RTAX_ADVMSS), + tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5) + sizeof(struct tcphdr); @@ -2333,6 +2337,9 @@ static void tcp_connect_init(struct sock *sk) if (!tp->window_clamp) tp->window_clamp = dst_metric(dst, RTAX_WINDOW); tp->advmss = dst_metric(dst, RTAX_ADVMSS); + if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < tp->advmss) + tp->advmss = tp->rx_opt.user_mss; + tcp_initialize_rcv_mss(sk); tcp_select_initial_window(tcp_full_space(sk), -- GitLab From a1cd0464c6f5857d87466130753d81b783bd3c52 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 21 Sep 2008 00:28:26 -0700 Subject: [PATCH 2091/5416] sparc: arch/sparc/kernel/pmc.c -- extra #include? I have no SPARC compiler handy to verify, but it looks like this is another file that doesn't need ... Signed-off-by: David S. Miller --- arch/sparc/kernel/pmc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 814eb3ce039..2afcfab4f11 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,6 @@ * #define PMC_NO_IDLE */ -#define PMC_MINOR MISC_DYNAMIC_MINOR #define PMC_OBPNAME "SUNW,pmc" #define PMC_DEVNAME "pmc" -- GitLab From b80a1b80818cd83c6c2109081b43551e7af72c84 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 20 Sep 2008 17:20:04 +0200 Subject: [PATCH 2092/5416] [MIPS] Fix 64-bit IP checksum code Use unsigned loads to avoid possible misscalculation of IP checksums. This bug was instruced in f761106cd728bcf65b7fe161b10221ee00cf7132 (lmo) / ed99e2bc1dc5dc54eb5a019f4975562dbef20103 (kernel.org). [Original fix by Atsushi. Improved instruction scheduling and fix for unaligned unsigned load by me -- Ralf] Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 8d7784122c1..edac9892c51 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -39,12 +39,14 @@ #ifdef USE_DOUBLE #define LOAD ld +#define LOAD32 lwu #define ADD daddu #define NBYTES 8 #else #define LOAD lw +#define LOAD32 lw #define ADD addu #define NBYTES 4 @@ -60,6 +62,14 @@ ADD sum, v1; \ .set pop +#define ADDC32(sum,reg) \ + .set push; \ + .set noat; \ + addu sum, reg; \ + sltu v1, sum, reg; \ + addu sum, v1; \ + .set pop + #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ LOAD _t1, (offset + UNIT(1))(src); \ @@ -132,7 +142,7 @@ LEAF(csum_partial) beqz t8, .Lqword_align andi t8, src, 0x8 - lw t0, 0x00(src) + LOAD32 t0, 0x00(src) LONG_SUBU a1, a1, 0x4 ADDC(sum, t0) PTR_ADDU src, src, 0x4 @@ -211,7 +221,7 @@ LEAF(csum_partial) LONG_SRL t8, t8, 0x2 .Lend_words: - lw t0, (src) + LOAD32 t0, (src) LONG_SUBU t8, t8, 0x1 ADDC(sum, t0) .set reorder /* DADDI_WAR */ @@ -230,6 +240,9 @@ LEAF(csum_partial) /* Still a full word to go */ ulw t1, (src) PTR_ADDIU src, 4 +#ifdef USE_DOUBLE + dsll t1, t1, 32 /* clear lower 32bit */ +#endif ADDC(sum, t1) 1: move t1, zero @@ -280,7 +293,7 @@ LEAF(csum_partial) 1: .set reorder /* Add the passed partial csum. */ - ADDC(sum, a2) + ADDC32(sum, a2) jr ra .set noreorder END(csum_partial) @@ -681,7 +694,7 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) .set pop 1: .set reorder - ADDC(sum, psum) + ADDC32(sum, psum) jr ra .set noreorder -- GitLab From 6657fe0a0281e06ff46eb42bc18ecb68d8b14b27 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 9 Sep 2008 15:19:10 +0200 Subject: [PATCH 2093/5416] [MIPS] SMTC: Clear TIF_FPUBOUND on clone / fork. Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b16facd9ea8..ce7684335a4 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -148,6 +148,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, clear_tsk_thread_flag(p, TIF_USEDFPU); #ifdef CONFIG_MIPS_MT_FPAFF + clear_tsk_thread_flag(p, TIF_FPUBOUND); + /* * FPU affinity support is cleaner if we track the * user-visible CPU affinity from the very beginning. -- GitLab From c65a5480ff29198c241f11d39d9e34ab22c72c69 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 12 Nov 2007 02:05:18 +0900 Subject: [PATCH 2094/5416] [MIPS] Fix potential latency problem due to non-atomic cpu_wait. If an interrupt happened between checking of NEED_RESCHED and WAIT instruction, adjust EPC to restart from checking of NEED_RESCHED. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 16 ++-------------- arch/mips/kernel/genex.S | 37 ++++++++++++++++++++++++++++++++++++ arch/mips/kernel/traps.c | 22 +++++++++++++++------ 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 335a6ae3d59..11c92dc5379 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -45,18 +45,7 @@ static void r39xx_wait(void) local_irq_enable(); } -/* - * There is a race when WAIT instruction executed with interrupt - * enabled. - * But it is implementation-dependent wheter the pipelie restarts when - * a non-enabled interrupt is requested. - */ -static void r4k_wait(void) -{ - __asm__(" .set mips3 \n" - " wait \n" - " .set mips0 \n"); -} +extern void r4k_wait(void); /* * This variant is preferable as it allows testing need_resched and going to @@ -128,7 +117,7 @@ static int __init wait_disable(char *s) __setup("nowait", wait_disable); -static inline void check_wait(void) +void __init check_wait(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -242,7 +231,6 @@ static inline void check_errata(void) void __init check_bugs32(void) { - check_wait(); check_errata(); } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index c6ada98ee04..f886dd7f708 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -20,6 +20,7 @@ #include #include #include +#include #define PANIC_PIC(msg) \ .set push; \ @@ -126,7 +127,42 @@ handle_vcei: __FINIT + .align 5 /* 32 byte rollback region */ +LEAF(r4k_wait) + .set push + .set noreorder + /* start of rollback region */ + LONG_L t0, TI_FLAGS($28) + nop + andi t0, _TIF_NEED_RESCHED + bnez t0, 1f + nop + nop + nop + .set mips3 + wait + /* end of rollback region (the region size must be power of two) */ + .set pop +1: + jr ra + END(r4k_wait) + + .macro BUILD_ROLLBACK_PROLOGUE handler + FEXPORT(rollback_\handler) + .set push + .set noat + MFC0 k0, CP0_EPC + PTR_LA k1, r4k_wait + ori k0, 0x1f /* 32 byte rollback region */ + xori k0, 0x1f + bne k0, k1, 9f + MTC0 k0, CP0_EPC +9: + .set pop + .endm + .align 5 +BUILD_ROLLBACK_PROLOGUE handle_int NESTED(handle_int, PT_SIZE, sp) #ifdef CONFIG_TRACE_IRQFLAGS /* @@ -201,6 +237,7 @@ NESTED(except_vec_ejtag_debug, 0, sp) * This prototype is copied to ebase + n*IntCtl.VS and patched * to invoke the handler */ +BUILD_ROLLBACK_PROLOGUE except_vec_vi NESTED(except_vec_vi, 0, sp) SAVE_SOME SAVE_AT diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6bee29097a5..5fd0cd020af 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -46,6 +46,9 @@ #include #include +extern void check_wait(void); +extern asmlinkage void r4k_wait(void); +extern asmlinkage void rollback_handle_int(void); extern asmlinkage void handle_int(void); extern asmlinkage void handle_tlbm(void); extern asmlinkage void handle_tlbl(void); @@ -1251,6 +1254,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) extern char except_vec_vi, except_vec_vi_lui; extern char except_vec_vi_ori, except_vec_vi_end; + extern char rollback_except_vec_vi; + char *vec_start = (cpu_wait == r4k_wait) ? + &rollback_except_vec_vi : &except_vec_vi; #ifdef CONFIG_MIPS_MT_SMTC /* * We need to provide the SMTC vectored interrupt handler @@ -1258,11 +1264,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) * Status.IM bit to be masked before going there. */ extern char except_vec_vi_mori; - const int mori_offset = &except_vec_vi_mori - &except_vec_vi; + const int mori_offset = &except_vec_vi_mori - vec_start; #endif /* CONFIG_MIPS_MT_SMTC */ - const int handler_len = &except_vec_vi_end - &except_vec_vi; - const int lui_offset = &except_vec_vi_lui - &except_vec_vi; - const int ori_offset = &except_vec_vi_ori - &except_vec_vi; + const int handler_len = &except_vec_vi_end - vec_start; + const int lui_offset = &except_vec_vi_lui - vec_start; + const int ori_offset = &except_vec_vi_ori - vec_start; if (handler_len > VECTORSPACING) { /* @@ -1272,7 +1278,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) panic("VECTORSPACING too small"); } - memcpy(b, &except_vec_vi, handler_len); + memcpy(b, vec_start, handler_len); #ifdef CONFIG_MIPS_MT_SMTC BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ @@ -1554,6 +1560,10 @@ void __init trap_init(void) extern char except_vec3_generic, except_vec3_r4000; extern char except_vec4; unsigned long i; + int rollback; + + check_wait(); + rollback = (cpu_wait == r4k_wait); #if defined(CONFIG_KGDB) if (kgdb_early_setup) @@ -1618,7 +1628,7 @@ void __init trap_init(void) if (board_be_init) board_be_init(); - set_except_vector(0, handle_int); + set_except_vector(0, rollback ? rollback_handle_int : handle_int); set_except_vector(1, handle_tlbm); set_except_vector(2, handle_tlbl); set_except_vector(3, handle_tlbs); -- GitLab From 6b3766a263a62fc82ca0457faa73dc34b98ceb87 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 5 Aug 2008 23:45:14 +0900 Subject: [PATCH 2095/5416] [MIPS] vmlinux.lds.S: handle .text.* The -ffunction-sections puts each text in .text.function_name section. Without this patch, most functions are placed outside _text..._etext area and it breaks show_stacktrace(), etc. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index b5470ceb418..afb119f3568 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -36,6 +36,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT KPROBES_TEXT + *(.text.*) *(.fixup) *(.gnu.warning) } :text = 0 -- GitLab From 795fb7e74dff04f661b61eccd3c48554b7d1f747 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 12:33:08 +0200 Subject: [PATCH 2096/5416] MAINTAINERS: Trivial whitespace cleanups * Drop trailing whitespace. * Replace spaces and combinations of spaces and tabs by single tabs. Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds --- MAINTAINERS | 162 ++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0a613cb926c..85cfd4d2ff4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -271,20 +271,20 @@ W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI WMI DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk -L: linux-acpi@vger.kernel.org -W: http://www.lesswatts.org/projects/acpi/ -S: Maintained +P: Carlos Corbacho +M: carlos@strangeworlds.co.uk +L: linux-acpi@vger.kernel.org +W: http://www.lesswatts.org/projects/acpi/ +S: Maintained AD1889 ALSA SOUND DRIVER -P: Kyle McMartin -M: kyle@mcmartin.ca -P: Thibaut Varene -M: T-Bone@parisc-linux.org -W: http://wiki.parisc-linux.org/AD1889 -L: linux-parisc@vger.kernel.org -S: Maintained +P: Kyle McMartin +M: kyle@mcmartin.ca +P: Thibaut Varene +M: T-Bone@parisc-linux.org +W: http://wiki.parisc-linux.org/AD1889 +L: linux-parisc@vger.kernel.org +S: Maintained ADM1025 HARDWARE MONITOR DRIVER P: Jean Delvare @@ -473,11 +473,11 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/ATMEL AT91RM9200 ARM ARCHITECTURE -P: Andrew Victor -M: linux@maxim.org.za -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -W: http://maxim.org.za/at91_26.html -S: Maintained +P: Andrew Victor +M: linux@maxim.org.za +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://maxim.org.za/at91_26.html +S: Maintained ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE P: Lennert Buytenhek @@ -532,10 +532,10 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/HP JORNADA 7XX MACHINE SUPPORT -P: Kristoffer Ericson -M: kristoffer.ericson@gmail.com -W: www.jlime.com -S: Maintained +P: Kristoffer Ericson +M: kristoffer.ericson@gmail.com +W: www.jlime.com +S: Maintained ARM/INTEL IOP32X ARM ARCHITECTURE P: Lennert Buytenhek @@ -1017,7 +1017,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER -P: Jonathan Corbet +P: Jonathan Corbet M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained @@ -1423,12 +1423,12 @@ L: linux-acpi@vger.kernel.org S: Supported DOCUMENTATION (/Documentation directory) -P: Michael Kerrisk -M: mtk.manpages@gmail.com -P: Randy Dunlap -M: rdunlap@xenotime.net -L: linux-doc@vger.kernel.org -S: Maintained +P: Michael Kerrisk +M: mtk.manpages@gmail.com +P: Randy Dunlap +M: rdunlap@xenotime.net +L: linux-doc@vger.kernel.org +S: Maintained DOUBLETALK DRIVER P: James R. Van Zandt @@ -1459,7 +1459,7 @@ S: Maintained DVB SUBSYSTEM AND DRIVERS P: LinuxTV.org Project M: v4l-dvb-maintainer@linuxtv.org -L: linux-dvb@linuxtv.org (subscription required) +L: linux-dvb@linuxtv.org (subscription required) W: http://linuxtv.org/ T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained @@ -2108,7 +2108,7 @@ M: rolandd@cisco.com P: Sean Hefty M: sean.hefty@intel.com P: Hal Rosenstock -M: hal.rosenstock@gmail.com +M: hal.rosenstock@gmail.com L: general@lists.openfabrics.org W: http://www.openib.org/ T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git @@ -2696,17 +2696,17 @@ S: Maintained MARVELL YUKON / SYSKONNECT DRIVER P: Mirko Lindner -M: mlindner@syskonnect.de +M: mlindner@syskonnect.de P: Ralph Roesler -M: rroesler@syskonnect.de -W: http://www.syskonnect.com -S: Supported +M: rroesler@syskonnect.de +W: http://www.syskonnect.com +S: Supported MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 P: Michael Kerrisk M: mtk.manpages@gmail.com -W: http://www.kernel.org/doc/man-pages -S: Supported +W: http://www.kernel.org/doc/man-pages +S: Supported MARVELL LIBERTAS WIRELESS DRIVER P: Dan Williams @@ -2867,10 +2867,10 @@ L: linux-kernel@vger.kernel.org S: Maintained MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER -P: Felipe Balbi -M: felipe.balbi@nokia.com -L: linux-usb@vger.kernel.org -S: Maintained +P: Felipe Balbi +M: felipe.balbi@nokia.com +L: linux-usb@vger.kernel.org +S: Maintained MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) P: Andrew Gallatin @@ -2882,7 +2882,7 @@ W: http://www.myri.com/scs/download-Myri10GE.html S: Supported NATSEMI ETHERNET DRIVER (DP8381x) -P: Tim Hockin +P: Tim Hockin M: thockin@hockin.org S: Maintained @@ -3101,7 +3101,7 @@ M: laforge@gnumonks.org S: Maintained OMNIVISION OV7670 SENSOR DRIVER -P: Jonathan Corbet +P: Jonathan Corbet M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained @@ -3211,7 +3211,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git S: Supported PCI HOTPLUG CORE -P: Kristen Carlson Accardi +P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com S: Supported @@ -3650,7 +3650,7 @@ M: jmorris@namei.org P: Eric Paris M: eparis@parisplace.org L: linux-kernel@vger.kernel.org (kernel issues) -L: selinux@tycho.nsa.gov (subscribers-only, general discussion) +L: selinux@tycho.nsa.gov (subscribers-only, general discussion) W: http://www.nsa.gov/selinux S: Supported @@ -3768,10 +3768,10 @@ M: bn@niasdigital.com S: Maintained SOC-CAMERA V4L2 SUBSYSTEM -P: Guennadi Liakhovetski -M: g.liakhovetski@gmx.de -L: video4linux-list@redhat.com -S: Maintained +P: Guennadi Liakhovetski +M: g.liakhovetski@gmx.de +L: video4linux-list@redhat.com +S: Maintained SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar @@ -4006,9 +4006,9 @@ T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git S: Maintained TI FLASH MEDIA INTERFACE DRIVER -P: Alex Dubov -M: oakad@yahoo.com -S: Maintained +P: Alex Dubov +M: oakad@yahoo.com +S: Maintained TI OMAP MMC INTERFACE DRIVER P: Carlos Aguiar, Anderson Briglia and Syed Khasim @@ -4154,13 +4154,13 @@ USB BLOCK DRIVER (UB ub) P: Pete Zaitcev M: zaitcev@redhat.com L: linux-kernel@vger.kernel.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB CDC ETHERNET DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ @@ -4187,13 +4187,13 @@ S: Maintained USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Odd Fixes USB ET61X[12]51 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4201,33 +4201,33 @@ S: Maintained USB GADGET/PERIPHERAL SUBSYSTEM P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) P: Jiri Kosina M: jkosina@suse.cz -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ @@ -4235,26 +4235,26 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ USB OHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Odd Fixes USB OPTION-CARD DRIVER P: Matthias Urlichs M: smurf@smurf.noris.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB OV511 DRIVER P: Mark McClelland M: mmcclell@bigfoot.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained USB PEGASUS DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -4262,13 +4262,13 @@ S: Maintained USB PRINTER DRIVER (usblp) P: Pete Zaitcev M: zaitcev@redhat.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB RTL8150 DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -4276,20 +4276,20 @@ S: Maintained USB SE401 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse M: wgreathouse@smva.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL CYPRESS M8 DRIVER P: Lonnie Mendez M: dignome@gmail.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i W: http://firstlight.net/cvs @@ -4304,39 +4304,39 @@ USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers M: pberger@brimson.com M: alborchers@steinerpoint.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL DRIVER P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL KEYSPAN DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained USB SERIAL WHITEHEAT DRIVER P: Support Department M: support@connecttech.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4344,7 +4344,7 @@ S: Maintained USB SUBSYSTEM P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported @@ -4352,7 +4352,7 @@ S: Supported USB UHCI DRIVER P: Alan Stern M: stern@rowland.harvard.edu -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB "USBNET" DRIVER FRAMEWORK @@ -4373,7 +4373,7 @@ S: Maintained USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4387,7 +4387,7 @@ S: Maintained USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4395,14 +4395,14 @@ S: Maintained USB ZD1201 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained USB ZR364XX DRIVER P: Antoine Jacquet M: royale@zerezo.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://royale.zerezo.com/zr364xx/ S: Maintained -- GitLab From baaea1dc0befb7b64e6dbf2d1469d0a296a79e54 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 12:34:33 +0200 Subject: [PATCH 2097/5416] MAINTAINERS: Various fixes * Normalize some S: entries to match the enumeration at the beginning of the file. * Change one mailing list entry from S: to L:. Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds --- MAINTAINERS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 85cfd4d2ff4..cad81a24e83 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1359,7 +1359,7 @@ P: Digi International, Inc M: Eng.Linux@digi.com L: Eng.Linux@digi.com W: http://www.digi.com -S: Orphaned +S: Orphan DIRECTORY NOTIFICATION P: Stephen Rothwell @@ -1797,7 +1797,7 @@ FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) P: Rik Faith M: faith@cs.unc.edu L: linux-scsi@vger.kernel.org -S: Odd fixes (e.g., new signatures) +S: Odd Fixes (e.g., new signatures) GDT SCSI DISK ARRAY CONTROLLER DRIVER P: Achim Leubner @@ -1838,10 +1838,10 @@ S: Maintained HARDWARE MONITORING L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ -S: Orphaned +S: Orphan HARDWARE RANDOM NUMBER GENERATOR CORE -S: Orphaned +S: Orphan HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER P: Robert Love @@ -2735,7 +2735,7 @@ S: Maintained MEGARAID SCSI DRIVERS P: Neela Syam Kolli M: megaraidlinux@lsi.com -S: linux-scsi@vger.kernel.org +L: linux-scsi@vger.kernel.org W: http://megaraid.lsilogic.com S: Maintained @@ -2853,7 +2853,7 @@ MULTIMEDIA CARD (MMC) ETC. OVER SPI P: David Brownell M: dbrownell@users.sourceforge.net L: linux-kernel@vger.kernel.org -S: Odd fixes +S: Odd Fixes MULTISOUND SOUND DRIVER P: Andrew Veliath @@ -3925,7 +3925,7 @@ S: Maintained STARMODE RADIO IP (STRIP) PROTOCOL DRIVER W: http://mosquitonet.Stanford.EDU/strip.html -S: Unsupported ? +S: Orphan STRADIS MPEG-2 DECODER DRIVER P: Nathan Laredo -- GitLab From e505240b6a6fd47b84cfeb1272ffeacd3e0874b3 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Sun, 21 Sep 2008 21:30:02 +0100 Subject: [PATCH 2098/5416] [ARM] 5257/2: [AT91] Use SZ_ definitions and MTDPART_OFS_NXTBLK instead of hex-values In the various AT91 board files, replace hard-coded size values (eg, 0x800000) with the SZ_ size definitions (eg, SZ_8M) from sizes.h Also replace MTD partition offsets with MTDPART_OFS_NXTBLK. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/board-cap9adk.c | 2 +- arch/arm/mach-at91/board-csb337.c | 4 +-- arch/arm/mach-at91/board-csb637.c | 4 +-- arch/arm/mach-at91/board-dk.c | 4 +-- arch/arm/mach-at91/board-ecbat91.c | 2 +- arch/arm/mach-at91/board-ek.c | 4 +-- arch/arm/mach-at91/board-picotux200.c | 2 +- arch/arm/mach-at91/board-qil-a9260.c | 14 ++++---- arch/arm/mach-at91/board-sam9-l9260.c | 4 +-- arch/arm/mach-at91/board-sam9260ek.c | 6 ++-- arch/arm/mach-at91/board-sam9261ek.c | 6 ++-- arch/arm/mach-at91/board-sam9263ek.c | 12 +++---- arch/arm/mach-at91/board-sam9g20ek.c | 8 ++--- arch/arm/mach-at91/board-sam9rlek.c | 6 ++-- arch/arm/mach-at91/board-usb-a9260.c | 14 ++++---- arch/arm/mach-at91/board-usb-a9263.c | 14 ++++---- arch/arm/mach-at91/board-yl-9200.c | 50 +++++++++++++-------------- 17 files changed, 78 insertions(+), 78 deletions(-) diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index 196199552eb..201b89392dc 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -214,7 +214,7 @@ static struct physmap_flash_data cap9adk_nor_data = { }; #define NOR_BASE AT91_CHIPSELECT_0 -#define NOR_SIZE 0x800000 +#define NOR_SIZE SZ_8M static struct resource nor_flash_resources[] = { { diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index cb7c9a8fa48..4bdf69d552e 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include +#include #include #include @@ -114,7 +114,7 @@ static struct spi_board_info csb337_spi_devices[] = { }; #define CSB_FLASH_BASE AT91_CHIPSELECT_0 -#define CSB_FLASH_SIZE 0x800000 +#define CSB_FLASH_SIZE SZ_8M static struct mtd_partition csb_flash_partitions[] = { { diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c index 8db8bd8babd..cfa3f04b220 100644 --- a/arch/arm/mach-at91/board-csb637.c +++ b/arch/arm/mach-at91/board-csb637.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include +#include #include #include @@ -72,7 +72,7 @@ static struct at91_udc_data __initdata csb637_udc_data = { }; #define CSB_FLASH_BASE AT91_CHIPSELECT_0 -#define CSB_FLASH_SIZE 0x1000000 +#define CSB_FLASH_SIZE SZ_16M static struct mtd_partition csb_flash_partitions[] = { { diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c index 43e1aa7ecef..0fd0f5bc77e 100644 --- a/arch/arm/mach-at91/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include #include +#include #include #include #include @@ -157,7 +157,7 @@ static struct atmel_nand_data __initdata dk_nand_data = { }; #define DK_FLASH_BASE AT91_CHIPSELECT_0 -#define DK_FLASH_SIZE 0x200000 +#define DK_FLASH_SIZE SZ_2M static struct physmap_flash_data dk_flash_data = { .width = 2, diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c index bfeee8a2af2..1d69908617f 100644 --- a/arch/arm/mach-at91/board-ecbat91.c +++ b/arch/arm/mach-at91/board-ecbat91.c @@ -86,7 +86,7 @@ static struct mtd_partition __initdata my_flash0_partitions[] = { /* 0x8400 */ .name = "Darrell-loader", .offset = 0, - .size = 12* 1056, + .size = 12 * 1056, }, { .name = "U-boot", diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c index 60626e7a349..4cdfaac8e59 100644 --- a/arch/arm/mach-at91/board-ek.c +++ b/arch/arm/mach-at91/board-ek.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include #include +#include #include #include #include @@ -116,7 +116,7 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = { }; #define EK_FLASH_BASE AT91_CHIPSELECT_0 -#define EK_FLASH_SIZE 0x200000 +#define EK_FLASH_SIZE SZ_2M static struct physmap_flash_data ek_flash_data = { .width = 2, diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c index dbc912d633c..859727e7ea3 100644 --- a/arch/arm/mach-at91/board-picotux200.c +++ b/arch/arm/mach-at91/board-picotux200.c @@ -105,7 +105,7 @@ static struct at91_mmc_data __initdata picotux200_mmc_data = { // }; #define PICOTUX200_FLASH_BASE AT91_CHIPSELECT_0 -#define PICOTUX200_FLASH_SIZE 0x400000 +#define PICOTUX200_FLASH_SIZE SZ_4M static struct physmap_flash_data picotux200_flash_data = { .width = 2, diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index 4c28413426c..cfb4571a2e2 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -39,6 +38,7 @@ #include #include +#include #include #include #include @@ -119,18 +119,18 @@ static struct at91_eth_data __initdata ek_macb_data = { static struct mtd_partition __initdata ek_nand_partition[] = { { .name = "Uboot & Kernel", - .offset = 0x00000000, - .size = 16 * 1024 * 1024, + .offset = 0, + .size = SZ_16M, }, { .name = "Root FS", - .offset = 0x01000000, - .size = 120 * 1024 * 1024, + .offset = MTDPART_OFS_NXTBLK, + .size = 120 * SZ_1M, }, { .name = "FS", - .offset = 0x08800000, - .size = 120 * 1024 * 1024, + .offset = MTDPART_OFS_NXTBLK, + .size = 120 * SZ_1M, }, }; diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index e4910cb26c1..99bb4cc23a0 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -126,11 +126,11 @@ static struct mtd_partition __initdata ek_nand_partition[] = { { .name = "Bootloader Area", .offset = 0, - .size = 10 * 1024 * 1024, + .size = 10 * SZ_1M, }, { .name = "User Area", - .offset = 10 * 1024 * 1024, + .offset = MTDPART_OFS_NXTBLK, .size = MTDPART_SIZ_FULL, }, }; diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 0a53c038b51..e22433d5dfb 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include #include +#include #include #include @@ -164,11 +164,11 @@ static struct mtd_partition __initdata ek_nand_partition[] = { { .name = "Partition 1", .offset = 0, - .size = 256 * 1024, + .size = SZ_256K, }, { .name = "Partition 2", - .offset = 256 * 1024, + .offset = MTDPART_OFS_NXTBLK, .size = MTDPART_SIZ_FULL, }, }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 1a9963b811c..03d3382cfef 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -35,7 +35,6 @@ #include diff --git a/block/blk-core.c b/block/blk-core.c index 2616cdd049a..86d22e7d65c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -531,7 +531,7 @@ EXPORT_SYMBOL(blk_alloc_queue_node); * request queue; this lock will be taken also from interrupt context, so irq * disabling is needed for it. * - * Function returns a pointer to the initialized request queue, or NULL if + * Function returns a pointer to the initialized request queue, or %NULL if * it didn't succeed. * * Note: @@ -913,7 +913,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) EXPORT_SYMBOL(blk_requeue_request); /** - * blk_insert_request - insert a special request in to a request queue + * blk_insert_request - insert a special request into a request queue * @q: request queue where request should be inserted * @rq: request to be inserted * @at_head: insert request at head or tail of queue @@ -923,8 +923,8 @@ EXPORT_SYMBOL(blk_requeue_request); * Many block devices need to execute commands asynchronously, so they don't * block the whole kernel from preemption during request execution. This is * accomplished normally by inserting aritficial requests tagged as - * REQ_SPECIAL in to the corresponding request queue, and letting them be - * scheduled for actual execution by the request queue. + * REQ_TYPE_SPECIAL in to the corresponding request queue, and letting them + * be scheduled for actual execution by the request queue. * * We have the option of inserting the head or the tail of the queue. * Typically we use the tail for new ioctls and so forth. We use the head @@ -1322,7 +1322,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) } /** - * generic_make_request: hand a buffer to its device driver for I/O + * generic_make_request - hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. * * generic_make_request() is used to make I/O requests of block @@ -1480,13 +1480,13 @@ void generic_make_request(struct bio *bio) EXPORT_SYMBOL(generic_make_request); /** - * submit_bio: submit a bio to the block device layer for I/O + * submit_bio - submit a bio to the block device layer for I/O * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) * @bio: The &struct bio which describes the I/O * * submit_bio() is very similar in purpose to generic_make_request(), and * uses that function to do most of the work. Both are fairly rough - * interfaces, @bio must be presetup and ready for I/O. + * interfaces; @bio must be presetup and ready for I/O. * */ void submit_bio(int rw, struct bio *bio) @@ -1524,7 +1524,7 @@ EXPORT_SYMBOL(submit_bio); /** * __end_that_request_first - end I/O on a request * @req: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: @@ -1532,8 +1532,8 @@ EXPORT_SYMBOL(submit_bio); * for the next range of segments (if any) in the cluster. * * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request + * %0 - we are done with this request, call end_that_request_last() + * %1 - still buffers pending for this request **/ static int __end_that_request_first(struct request *req, int error, int nr_bytes) @@ -1544,7 +1544,7 @@ static int __end_that_request_first(struct request *req, int error, blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); /* - * for a REQ_BLOCK_PC request, we want to carry any eventual + * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual * sense key with us all the way through */ if (!blk_pc_request(req)) @@ -1810,11 +1810,11 @@ EXPORT_SYMBOL_GPL(blk_rq_cur_bytes); /** * end_queued_request - end all I/O on a queued request * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag + * @uptodate: error value or %0/%1 uptodate flag * * Description: * Ends all I/O on a request, and removes it from the block layer queues. - * Not suitable for normal IO completion, unless the driver still has + * Not suitable for normal I/O completion, unless the driver still has * the request attached to the block layer. * **/ @@ -1827,7 +1827,7 @@ EXPORT_SYMBOL(end_queued_request); /** * end_dequeued_request - end all I/O on a dequeued request * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag + * @uptodate: error value or %0/%1 uptodate flag * * Description: * Ends all I/O on a request. The request must already have been @@ -1845,14 +1845,14 @@ EXPORT_SYMBOL(end_dequeued_request); /** * end_request - end I/O on the current segment of the request * @req: the request being processed - * @uptodate: error value or 0/1 uptodate flag + * @uptodate: error value or %0/%1 uptodate flag * * Description: * Ends I/O on the current segment of a request. If that is the only * remaining segment, the request is also completed and freed. * - * This is a remnant of how older block drivers handled IO completions. - * Modern drivers typically end IO on the full request in one go, unless + * This is a remnant of how older block drivers handled I/O completions. + * Modern drivers typically end I/O on the full request in one go, unless * they have a residual value to account for. For that case this function * isn't really useful, unless the residual just happens to be the * full current segment. In other words, don't use this function in new @@ -1870,12 +1870,12 @@ EXPORT_SYMBOL(end_request); /** * blk_end_io - Generic end_io function to complete a request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete @rq * @bidi_bytes: number of bytes to complete @rq->next_rq * @drv_callback: function called between completion of bios in the request * and completion of the request. - * If the callback returns non 0, this helper returns without + * If the callback returns non %0, this helper returns without * completion of the request. * * Description: @@ -1883,8 +1883,8 @@ EXPORT_SYMBOL(end_request); * If @rq has leftover, sets it up for the next range of segments. * * Return: - * 0 - we are done with this request - * 1 - this request is not freed yet, it still has pending buffers. + * %0 - we are done with this request + * %1 - this request is not freed yet, it still has pending buffers. **/ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes, @@ -1919,7 +1919,7 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, /** * blk_end_request - Helper function for drivers to complete the request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: @@ -1927,8 +1927,8 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, * If @rq has leftover, sets it up for the next range of segments. * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int blk_end_request(struct request *rq, int error, unsigned int nr_bytes) { @@ -1939,15 +1939,15 @@ EXPORT_SYMBOL_GPL(blk_end_request); /** * __blk_end_request - Helper function for drivers to complete the request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: * Must be called with queue lock held unlike blk_end_request(). * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int __blk_end_request(struct request *rq, int error, unsigned int nr_bytes) { @@ -1966,7 +1966,7 @@ EXPORT_SYMBOL_GPL(__blk_end_request); /** * blk_end_bidi_request - Helper function for drivers to complete bidi request. * @rq: the bidi request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete @rq * @bidi_bytes: number of bytes to complete @rq->next_rq * @@ -1974,8 +1974,8 @@ EXPORT_SYMBOL_GPL(__blk_end_request); * Ends I/O on a number of bytes attached to @rq and @rq->next_rq. * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes) @@ -1987,11 +1987,11 @@ EXPORT_SYMBOL_GPL(blk_end_bidi_request); /** * blk_end_request_callback - Special helper function for tricky drivers * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * @drv_callback: function called between completion of bios in the request * and completion of the request. - * If the callback returns non 0, this helper returns without + * If the callback returns non %0, this helper returns without * completion of the request. * * Description: @@ -2004,10 +2004,10 @@ EXPORT_SYMBOL_GPL(blk_end_bidi_request); * Don't use this interface in other places anymore. * * Return: - * 0 - we are done with this request - * 1 - this request is not freed yet. - * this request still has pending buffers or - * the driver doesn't want to finish this request yet. + * %0 - we are done with this request + * %1 - this request is not freed yet. + * this request still has pending buffers or + * the driver doesn't want to finish this request yet. **/ int blk_end_request_callback(struct request *rq, int error, unsigned int nr_bytes, diff --git a/block/blk-exec.c b/block/blk-exec.c index 9bceff7674f..6af716d1e54 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -16,7 +16,7 @@ /** * blk_end_sync_rq - executes a completion event on a request * @rq: request to complete - * @error: end io status of the request + * @error: end I/O status of the request */ static void blk_end_sync_rq(struct request *rq, int error) { @@ -41,7 +41,7 @@ static void blk_end_sync_rq(struct request *rq, int error) * @done: I/O completion handler * * Description: - * Insert a fully prepared request at the back of the io scheduler queue + * Insert a fully prepared request at the back of the I/O scheduler queue * for execution. Don't wait for completion. */ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, @@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); * @at_head: insert request at head or tail of queue * * Description: - * Insert a fully prepared request at the back of the io scheduler queue + * Insert a fully prepared request at the back of the I/O scheduler queue * for execution and wait for completion. */ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 3f1a8478cc3..d87606eaca1 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -109,8 +109,8 @@ EXPORT_SYMBOL(blk_rq_map_integrity_sg); /** * blk_integrity_compare - Compare integrity profile of two block devices - * @b1: Device to compare - * @b2: Device to compare + * @bd1: Device to compare + * @bd2: Device to compare * * Description: Meta-devices like DM and MD need to verify that all * sub-devices use the same integrity format before advertising to diff --git a/block/blk-map.c b/block/blk-map.c index af37e4ae62f..ea1bf53929e 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -85,17 +85,17 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, } /** - * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_user - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request structure to fill * @ubuf: the user buffer * @len: length of user data * * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise + * Data will be mapped directly for zero copy I/O, if possible. Otherwise * a kernel bounce buffer is used. * - * A matching blk_rq_unmap_user() must be issued at the end of io, while + * A matching blk_rq_unmap_user() must be issued at the end of I/O, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() @@ -154,7 +154,7 @@ unmap_rq: EXPORT_SYMBOL(blk_rq_map_user); /** - * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to map data to * @iov: pointer to the iovec @@ -162,10 +162,10 @@ EXPORT_SYMBOL(blk_rq_map_user); * @len: I/O byte count * * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise + * Data will be mapped directly for zero copy I/O, if possible. Otherwise * a kernel bounce buffer is used. * - * A matching blk_rq_unmap_user() must be issued at the end of io, while + * A matching blk_rq_unmap_user() must be issued at the end of I/O, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() @@ -224,7 +224,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, * Description: * Unmap a rq previously mapped by blk_rq_map_user(). The caller must * supply the original rq->bio from the blk_rq_map_user() return, since - * the io completion may have changed rq->bio. + * the I/O completion may have changed rq->bio. */ int blk_rq_unmap_user(struct bio *bio) { @@ -250,7 +250,7 @@ int blk_rq_unmap_user(struct bio *bio) EXPORT_SYMBOL(blk_rq_unmap_user); /** - * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to fill * @kbuf: the kernel buffer diff --git a/block/blk-settings.c b/block/blk-settings.c index 539d873c820..d70692badcd 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -144,7 +144,7 @@ EXPORT_SYMBOL(blk_queue_make_request); * Different hardware can have different requirements as to what pages * it can do I/O directly to. A low level driver can call * blk_queue_bounce_limit to have lower memory pages allocated as bounce - * buffers for doing I/O to pages residing above @page. + * buffers for doing I/O to pages residing above @dma_addr. **/ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr) { @@ -229,7 +229,7 @@ EXPORT_SYMBOL(blk_queue_max_phys_segments); * Description: * Enables a low level driver to set an upper limit on the number of * hw data segments in a request. This would be the largest number of - * address/length pairs the host adapter can actually give as once + * address/length pairs the host adapter can actually give at once * to the device. **/ void blk_queue_max_hw_segments(struct request_queue *q, @@ -410,7 +410,7 @@ EXPORT_SYMBOL(blk_queue_segment_boundary); * @mask: alignment mask * * description: - * set required memory and length aligment for direct dma transactions. + * set required memory and length alignment for direct dma transactions. * this is used when buiding direct io requests for the queue. * **/ @@ -426,7 +426,7 @@ EXPORT_SYMBOL(blk_queue_dma_alignment); * @mask: alignment mask * * description: - * update required memory and length aligment for direct dma transactions. + * update required memory and length alignment for direct dma transactions. * If the requested alignment is larger than the current alignment, then * the current queue alignment is updated to the new value, otherwise it * is left alone. The design of this is to allow multiple objects diff --git a/block/blk-tag.c b/block/blk-tag.c index ed5166fbc59..8a99688eb1b 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -29,7 +29,7 @@ EXPORT_SYMBOL(blk_queue_find_tag); * __blk_free_tags - release a given set of tag maintenance info * @bqt: the tag map to free * - * Tries to free the specified @bqt@. Returns true if it was + * Tries to free the specified @bqt. Returns true if it was * actually freed and false if there are still references using it */ static int __blk_free_tags(struct blk_queue_tag *bqt) @@ -78,7 +78,7 @@ void __blk_queue_free_tags(struct request_queue *q) * blk_free_tags - release a given set of tag maintenance info * @bqt: the tag map to free * - * For externally managed @bqt@ frees the map. Callers of this + * For externally managed @bqt frees the map. Callers of this * function must guarantee to have released all the queues that * might have been using this tag map. */ @@ -94,7 +94,7 @@ EXPORT_SYMBOL(blk_free_tags); * @q: the request queue for the device * * Notes: - * This is used to disabled tagged queuing to a device, yet leave + * This is used to disable tagged queuing to a device, yet leave * queue in function. **/ void blk_queue_free_tags(struct request_queue *q) @@ -271,7 +271,7 @@ EXPORT_SYMBOL(blk_queue_resize_tags); * @rq: the request that has completed * * Description: - * Typically called when end_that_request_first() returns 0, meaning + * Typically called when end_that_request_first() returns %0, meaning * all transfers have been done for a request. It's important to call * this function before end_that_request_last(), as that will put the * request back on the free list thus corrupting the internal tag list. diff --git a/block/genhd.c b/block/genhd.c index e0ce23ac2ec..c114a43052d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -211,10 +211,11 @@ void unlink_gendisk(struct gendisk *disk) /** * get_gendisk - get partitioning information for a given device - * @dev: device to get partitioning information for + * @devt: device to get partitioning information for + * @part: returned partition index * * This function gets the structure containing partitioning - * information for the given device @dev. + * information for the given device @devt. */ struct gendisk *get_gendisk(dev_t devt, int *part) { -- GitLab From a1ed5b0cffe4b16a93a6a3390e8cee0fbef94f86 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:50:16 +0200 Subject: [PATCH 3405/5416] klist: don't iterate over deleted entries A klist entry is kept on the list till all its current iterations are finished; however, a new iteration after deletion also iterates over deleted entries as long as their reference count stays above zero. This causes problems for cases where there are users which iterate over the list while synchronized against list manipulations and natuarally expect already deleted entries to not show up during iteration. This patch implements dead flag which gets set on deletion so that iteration can skip already deleted entries. The dead flag piggy backs on the lowest bit of knode->n_klist and only visible to klist implementation proper. While at it, drop klist_iter->i_head as it's redundant and doesn't offer anything in semantics or performance wise as klist_iter->i_klist is dereferenced on every iteration anyway. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman Cc: Alan Stern Cc: Jens Axboe Signed-off-by: Jens Axboe --- include/linux/klist.h | 3 +- lib/klist.c | 96 +++++++++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/include/linux/klist.h b/include/linux/klist.h index 06c338ef7f1..8ea98db223e 100644 --- a/include/linux/klist.h +++ b/include/linux/klist.h @@ -38,7 +38,7 @@ extern void klist_init(struct klist *k, void (*get)(struct klist_node *), void (*put)(struct klist_node *)); struct klist_node { - struct klist *n_klist; + void *n_klist; /* never access directly */ struct list_head n_node; struct kref n_ref; struct completion n_removed; @@ -57,7 +57,6 @@ extern int klist_node_attached(struct klist_node *n); struct klist_iter { struct klist *i_klist; - struct list_head *i_head; struct klist_node *i_cur; }; diff --git a/lib/klist.c b/lib/klist.c index cca37f96faa..bbdd3015c2c 100644 --- a/lib/klist.c +++ b/lib/klist.c @@ -37,6 +37,37 @@ #include #include +/* + * Use the lowest bit of n_klist to mark deleted nodes and exclude + * dead ones from iteration. + */ +#define KNODE_DEAD 1LU +#define KNODE_KLIST_MASK ~KNODE_DEAD + +static struct klist *knode_klist(struct klist_node *knode) +{ + return (struct klist *) + ((unsigned long)knode->n_klist & KNODE_KLIST_MASK); +} + +static bool knode_dead(struct klist_node *knode) +{ + return (unsigned long)knode->n_klist & KNODE_DEAD; +} + +static void knode_set_klist(struct klist_node *knode, struct klist *klist) +{ + knode->n_klist = klist; + /* no knode deserves to start its life dead */ + WARN_ON(knode_dead(knode)); +} + +static void knode_kill(struct klist_node *knode) +{ + /* and no knode should die twice ever either, see we're very humane */ + WARN_ON(knode_dead(knode)); + *(unsigned long *)&knode->n_klist |= KNODE_DEAD; +} /** * klist_init - Initialize a klist structure. @@ -79,7 +110,7 @@ static void klist_node_init(struct klist *k, struct klist_node *n) INIT_LIST_HEAD(&n->n_node); init_completion(&n->n_removed); kref_init(&n->n_ref); - n->n_klist = k; + knode_set_klist(n, k); if (k->get) k->get(n); } @@ -115,7 +146,7 @@ EXPORT_SYMBOL_GPL(klist_add_tail); */ void klist_add_after(struct klist_node *n, struct klist_node *pos) { - struct klist *k = pos->n_klist; + struct klist *k = knode_klist(pos); klist_node_init(k, n); spin_lock(&k->k_lock); @@ -131,7 +162,7 @@ EXPORT_SYMBOL_GPL(klist_add_after); */ void klist_add_before(struct klist_node *n, struct klist_node *pos) { - struct klist *k = pos->n_klist; + struct klist *k = knode_klist(pos); klist_node_init(k, n); spin_lock(&k->k_lock); @@ -144,9 +175,10 @@ static void klist_release(struct kref *kref) { struct klist_node *n = container_of(kref, struct klist_node, n_ref); + WARN_ON(!knode_dead(n)); list_del(&n->n_node); complete(&n->n_removed); - n->n_klist = NULL; + knode_set_klist(n, NULL); } static int klist_dec_and_del(struct klist_node *n) @@ -154,22 +186,29 @@ static int klist_dec_and_del(struct klist_node *n) return kref_put(&n->n_ref, klist_release); } -/** - * klist_del - Decrement the reference count of node and try to remove. - * @n: node we're deleting. - */ -void klist_del(struct klist_node *n) +static void klist_put(struct klist_node *n, bool kill) { - struct klist *k = n->n_klist; + struct klist *k = knode_klist(n); void (*put)(struct klist_node *) = k->put; spin_lock(&k->k_lock); + if (kill) + knode_kill(n); if (!klist_dec_and_del(n)) put = NULL; spin_unlock(&k->k_lock); if (put) put(n); } + +/** + * klist_del - Decrement the reference count of node and try to remove. + * @n: node we're deleting. + */ +void klist_del(struct klist_node *n) +{ + klist_put(n, true); +} EXPORT_SYMBOL_GPL(klist_del); /** @@ -206,7 +245,6 @@ void klist_iter_init_node(struct klist *k, struct klist_iter *i, struct klist_node *n) { i->i_klist = k; - i->i_head = &k->k_list; i->i_cur = n; if (n) kref_get(&n->n_ref); @@ -237,7 +275,7 @@ EXPORT_SYMBOL_GPL(klist_iter_init); void klist_iter_exit(struct klist_iter *i) { if (i->i_cur) { - klist_del(i->i_cur); + klist_put(i->i_cur, false); i->i_cur = NULL; } } @@ -258,27 +296,33 @@ static struct klist_node *to_klist_node(struct list_head *n) */ struct klist_node *klist_next(struct klist_iter *i) { - struct list_head *next; - struct klist_node *lnode = i->i_cur; - struct klist_node *knode = NULL; void (*put)(struct klist_node *) = i->i_klist->put; + struct klist_node *last = i->i_cur; + struct klist_node *next; spin_lock(&i->i_klist->k_lock); - if (lnode) { - next = lnode->n_node.next; - if (!klist_dec_and_del(lnode)) + + if (last) { + next = to_klist_node(last->n_node.next); + if (!klist_dec_and_del(last)) put = NULL; } else - next = i->i_head->next; + next = to_klist_node(i->i_klist->k_list.next); - if (next != i->i_head) { - knode = to_klist_node(next); - kref_get(&knode->n_ref); + i->i_cur = NULL; + while (next != to_klist_node(&i->i_klist->k_list)) { + if (likely(!knode_dead(next))) { + kref_get(&next->n_ref); + i->i_cur = next; + break; + } + next = to_klist_node(next->n_node.next); } - i->i_cur = knode; + spin_unlock(&i->i_klist->k_lock); - if (put && lnode) - put(lnode); - return knode; + + if (put && last) + put(last); + return i->i_cur; } EXPORT_SYMBOL_GPL(klist_next); -- GitLab From 5a3ceb861663040f9ef0176df4aaa494bba5e352 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:50:19 +0200 Subject: [PATCH 3406/5416] driver-core: use klist for class device list and implement iterator Iterating over entries using callback usually isn't too fun especially when the entry being iterated over can't be manipulated freely. This patch converts class->p->class_devices to klist and implements class device iterator so that the users can freely build their own control structure. The users are also free to call back into class code without worrying about locking. class_for_each_device() and class_find_device() are converted to use the new iterators, so their users don't have to worry about locking anymore either. Note: This depends on klist-dont-iterate-over-deleted-entries patch because class_intf->add/remove_dev() depends on proper synchronization with device removal. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman Cc: Jens Axboe Signed-off-by: Jens Axboe --- drivers/base/base.h | 2 +- drivers/base/class.c | 136 +++++++++++++++++++++++++++++++---------- drivers/base/core.c | 6 +- include/linux/device.h | 14 ++++- 4 files changed, 120 insertions(+), 38 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 31dc0cd84af..0a5f055dffb 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -54,7 +54,7 @@ struct driver_private { */ struct class_private { struct kset class_subsys; - struct list_head class_devices; + struct klist class_devices; struct list_head class_interfaces; struct kset class_dirs; struct mutex class_mutex; diff --git a/drivers/base/class.c b/drivers/base/class.c index cc5e28c8885..eb85e431230 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,6 +135,20 @@ static void remove_class_attrs(struct class *cls) } } +static void klist_class_dev_get(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + get_device(dev); +} + +static void klist_class_dev_put(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + put_device(dev); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -145,7 +159,7 @@ int __class_register(struct class *cls, struct lock_class_key *key) cp = kzalloc(sizeof(*cp), GFP_KERNEL); if (!cp) return -ENOMEM; - INIT_LIST_HEAD(&cp->class_devices); + klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put); INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); __mutex_init(&cp->class_mutex, "struct class mutex", key); @@ -268,6 +282,71 @@ char *make_class_name(const char *name, struct kobject *kobj) } #endif +/** + * class_dev_iter_init - initialize class device iterator + * @iter: class iterator to initialize + * @class: the class we wanna iterate over + * @start: the device to start iterating from, if any + * @type: device_type of the devices to iterate over, NULL for all + * + * Initialize class iterator @iter such that it iterates over devices + * of @class. If @start is set, the list iteration will start there, + * otherwise if it is NULL, the iteration starts at the beginning of + * the list. + */ +void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, + struct device *start, const struct device_type *type) +{ + struct klist_node *start_knode = NULL; + + if (start) + start_knode = &start->knode_class; + klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode); + iter->type = type; +} +EXPORT_SYMBOL_GPL(class_dev_iter_init); + +/** + * class_dev_iter_next - iterate to the next device + * @iter: class iterator to proceed + * + * Proceed @iter to the next device and return it. Returns NULL if + * iteration is complete. + * + * The returned device is referenced and won't be released till + * iterator is proceed to the next device or exited. The caller is + * free to do whatever it wants to do with the device including + * calling back into class code. + */ +struct device *class_dev_iter_next(struct class_dev_iter *iter) +{ + struct klist_node *knode; + struct device *dev; + + while (1) { + knode = klist_next(&iter->ki); + if (!knode) + return NULL; + dev = container_of(knode, struct device, knode_class); + if (!iter->type || iter->type == dev->type) + return dev; + } +} +EXPORT_SYMBOL_GPL(class_dev_iter_next); + +/** + * class_dev_iter_exit - finish iteration + * @iter: class iterator to finish + * + * Finish an iteration. Always call this function after iteration is + * complete whether the iteration ran till the end or not. + */ +void class_dev_iter_exit(struct class_dev_iter *iter) +{ + klist_iter_exit(&iter->ki); +} +EXPORT_SYMBOL_GPL(class_dev_iter_exit); + /** * class_for_each_device - device iterator * @class: the class we're iterating @@ -283,13 +362,13 @@ char *make_class_name(const char *name, struct kobject *kobj) * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * - * Note, we hold class->class_mutex in this function, so it can not be - * re-acquired in @fn, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; int error = 0; @@ -301,20 +380,13 @@ int class_for_each_device(struct class *class, struct device *start, return -EINVAL; } - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { error = fn(dev, data); - put_device(dev); if (error) break; } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); return error; } @@ -337,16 +409,15 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * We hold class->class_mutex in this function, so it can not be - * re-acquired in @match, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ struct device *class_find_device(struct class *class, struct device *start, void *data, int (*match)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; - int found = 0; if (!class) return NULL; @@ -356,29 +427,23 @@ struct device *class_find_device(struct class *class, struct device *start, return NULL; } - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { if (match(dev, data)) { - found = 1; + get_device(dev); break; - } else - put_device(dev); + } } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); - return found ? dev : NULL; + return dev; } EXPORT_SYMBOL_GPL(class_find_device); int class_interface_register(struct class_interface *class_intf) { struct class *parent; + struct class_dev_iter iter; struct device *dev; if (!class_intf || !class_intf->class) @@ -391,8 +456,10 @@ int class_interface_register(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->add_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); @@ -402,6 +469,7 @@ int class_interface_register(struct class_interface *class_intf) void class_interface_unregister(struct class_interface *class_intf) { struct class *parent = class_intf->class; + struct class_dev_iter iter; struct device *dev; if (!parent) @@ -410,8 +478,10 @@ void class_interface_unregister(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_del_init(&class_intf->node); if (class_intf->remove_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->remove_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); diff --git a/drivers/base/core.c b/drivers/base/core.c index d021c98605b..b98cb1416a2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -536,7 +536,6 @@ void device_initialize(struct device *dev) klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); - INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); @@ -916,7 +915,8 @@ int device_add(struct device *dev) if (dev->class) { mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ - list_add_tail(&dev->node, &dev->class->p->class_devices); + klist_add_tail(&dev->knode_class, + &dev->class->p->class_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, @@ -1032,7 +1032,7 @@ void device_del(struct device *dev) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ - list_del_init(&dev->node); + klist_del(&dev->knode_class); mutex_unlock(&dev->class->p->class_mutex); } device_remove_file(dev, &uevent_attr); diff --git a/include/linux/device.h b/include/linux/device.h index 4d8372d135d..246937c9cbc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -199,6 +199,11 @@ struct class { struct class_private *p; }; +struct class_dev_iter { + struct klist_iter ki; + const struct device_type *type; +}; + extern struct kobject *sysfs_dev_block_kobj; extern struct kobject *sysfs_dev_char_kobj; extern int __must_check __class_register(struct class *class, @@ -213,6 +218,13 @@ extern void class_unregister(struct class *class); __class_register(class, &__key); \ }) +extern void class_dev_iter_init(struct class_dev_iter *iter, + struct class *class, + struct device *start, + const struct device_type *type); +extern struct device *class_dev_iter_next(struct class_dev_iter *iter); +extern void class_dev_iter_exit(struct class_dev_iter *iter); + extern int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -396,7 +408,7 @@ struct device { spinlock_t devres_lock; struct list_head devres_head; - struct list_head node; + struct klist_node knode_class; struct class *class; dev_t devt; /* dev_t, creates the sysfs "dev" */ struct attribute_group **groups; /* optional groups */ -- GitLab From ac65ece4eee10b03ac29ee925cadc179dc810bab Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:30:12 +0900 Subject: [PATCH 3407/5416] block: fix partition info printouts Recent block_class iteration updates 5c6f35c5..27f3025 broke partition info printouts. * printk_all_partitions(): Partition print out stops when it meets a partition hole. Partition printing inner loop should continue instead of exiting on empty partition slot. * /proc/partitions and /proc/diskstats: If all information can't be read in single read(), the information is truncated. This is because find_start() doesn't actually update the counter containing the initial seek. It runs to the end and ends up always reporting EOF on the second read. This patch fixes both problems. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman Signed-off-by: Jens Axboe --- block/genhd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index c114a43052d..0be95135c40 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -236,7 +236,7 @@ static int printk_partition(struct device *dev, void *data) int n; if (dev->type != &disk_type) - goto exit; + return 0; sgp = dev_to_disk(dev); /* @@ -244,7 +244,7 @@ static int printk_partition(struct device *dev, void *data) */ if (get_capacity(sgp) == 0 || (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - goto exit; + return 0; /* * Note, unlike /proc/partitions, I am showing the numbers in @@ -264,15 +264,15 @@ static int printk_partition(struct device *dev, void *data) /* now show the partitions */ for (n = 0; n < sgp->minors - 1; ++n) { if (sgp->part[n] == NULL) - goto exit; + continue; if (sgp->part[n]->nr_sects == 0) - goto exit; + continue; printk(" %02x%02x %10llu %s\n", sgp->major, n + 1 + sgp->first_minor, (unsigned long long)sgp->part[n]->nr_sects >> 1, disk_name(sgp, n + 1, buf)); } -exit: + return 0; } -- GitLab From 2ac3cee5298a247b2774f3319b28a05f588c3f0e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 08:53:37 +0200 Subject: [PATCH 3408/5416] block: don't grab block_class_lock unnecessarily block_class_lock protects major_names array and bdev_map and doesn't have anything to do with block class devices. Don't grab them while iterating over block class devices. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 0be95135c40..9eb8b3e212c 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -283,9 +283,7 @@ static int printk_partition(struct device *dev, void *data) */ void __init printk_all_partitions(void) { - mutex_lock(&block_class_lock); class_for_each_device(&block_class, NULL, NULL, printk_partition); - mutex_unlock(&block_class_lock); } #ifdef CONFIG_PROC_FS @@ -305,17 +303,15 @@ static int find_start(struct device *dev, void *data) static void *part_start(struct seq_file *part, loff_t *pos) { struct device *dev; - loff_t k = *pos; + loff_t n = *pos; - if (!k) + if (!n) part->private = (void *)1LU; /* tell show to print header */ - mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, &k, find_start); - if (dev) { - put_device(dev); + dev = class_find_device(&block_class, NULL, &n, find_start); + if (dev) return dev_to_disk(dev); - } + return NULL; } @@ -341,7 +337,6 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos) static void part_stop(struct seq_file *part, void *v) { - mutex_unlock(&block_class_lock); } static int show_partition(struct seq_file *part, void *v) @@ -583,14 +578,12 @@ static struct device_type disk_type = { static void *diskstats_start(struct seq_file *part, loff_t *pos) { struct device *dev; - loff_t k = *pos; + loff_t n = *pos; - mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, &k, find_start); - if (dev) { - put_device(dev); + dev = class_find_device(&block_class, NULL, &n, find_start); + if (dev) return dev_to_disk(dev); - } + return NULL; } @@ -610,7 +603,6 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) static void diskstats_stop(struct seq_file *part, void *v) { - mutex_unlock(&block_class_lock); } static int diskstats_show(struct seq_file *s, void *v) @@ -729,7 +721,6 @@ dev_t blk_lookup_devt(const char *name, int part) dev_t devt = MKDEV(0, 0); struct find_block find; - mutex_lock(&block_class_lock); find.name = name; find.part = part; dev = class_find_device(&block_class, NULL, &find, match_id); @@ -738,7 +729,6 @@ dev_t blk_lookup_devt(const char *name, int part) devt = MKDEV(MAJOR(dev->devt), MINOR(dev->devt) + part); } - mutex_unlock(&block_class_lock); return devt; } -- GitLab From def4e38ddda9bef20b69bfa939195c2f79da7979 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 08:57:12 +0200 Subject: [PATCH 3409/5416] block: use class_dev_iterator instead of class_for_each_device() Recent block_class iteration updates 5c6f35c5..27f3025 converted all class device iteration to class_for_each_device() and class_find_device(), which are correct but pain in the ass to use. This pach converts them to newly introduced class_dev_iterator so that they can use more natural control structures instead of separate callbacks and struct to pass parameters to them. This results in smaller and easier code. This patch also restores the original behavior of not printing header in /proc/partitions if there's no partition to print. This is trivial but still user-visible behavior. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman Signed-off-by: Jens Axboe --- block/genhd.c | 252 +++++++++++++++++++------------------------------- 1 file changed, 97 insertions(+), 155 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 9eb8b3e212c..8b9a9ff1a84 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -225,57 +225,6 @@ struct gendisk *get_gendisk(dev_t devt, int *part) return kobj ? dev_to_disk(dev) : NULL; } -/* - * print a partitions - intended for places where the root filesystem can't be - * mounted and thus to give the victim some idea of what went wrong - */ -static int printk_partition(struct device *dev, void *data) -{ - struct gendisk *sgp; - char buf[BDEVNAME_SIZE]; - int n; - - if (dev->type != &disk_type) - return 0; - - sgp = dev_to_disk(dev); - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - return 0; - - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } - - return 0; -} - /* * print a full list of all partitions - intended for places where the root * filesystem can't be mounted and thus to give the victim some idea of what @@ -283,60 +232,108 @@ static int printk_partition(struct device *dev, void *data) */ void __init printk_all_partitions(void) { - class_for_each_device(&block_class, NULL, NULL, printk_partition); + struct class_dev_iter iter; + struct device *dev; + + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { + struct gendisk *disk = dev_to_disk(dev); + char buf[BDEVNAME_SIZE]; + int n; + + /* + * Don't show empty devices or things that have been + * surpressed + */ + if (get_capacity(disk) == 0 || + (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) + continue; + + /* + * Note, unlike /proc/partitions, I am showing the + * numbers in hex - the same format as the root= + * option takes. + */ + printk("%02x%02x %10llu %s", + disk->major, disk->first_minor, + (unsigned long long)get_capacity(disk) >> 1, + disk_name(disk, 0, buf)); + if (disk->driverfs_dev != NULL && + disk->driverfs_dev->driver != NULL) + printk(" driver: %s\n", + disk->driverfs_dev->driver->name); + else + printk(" (driver?)\n"); + + /* now show the partitions */ + for (n = 0; n < disk->minors - 1; ++n) { + if (disk->part[n] == NULL) + continue; + if (disk->part[n]->nr_sects == 0) + continue; + printk(" %02x%02x %10llu %s\n", + disk->major, n + 1 + disk->first_minor, + (unsigned long long)disk->part[n]->nr_sects >> 1, + disk_name(disk, n + 1, buf)); + } + } + class_dev_iter_exit(&iter); } #ifdef CONFIG_PROC_FS /* iterator */ -static int find_start(struct device *dev, void *data) +static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos) { - loff_t *k = data; + loff_t skip = *pos; + struct class_dev_iter *iter; + struct device *dev; - if (dev->type != &disk_type) - return 0; - if (!*k) - return 1; - (*k)--; - return 0; + iter = kmalloc(GFP_KERNEL, sizeof(*iter)); + if (!iter) + return ERR_PTR(-ENOMEM); + + seqf->private = iter; + class_dev_iter_init(iter, &block_class, NULL, &disk_type); + do { + dev = class_dev_iter_next(iter); + if (!dev) + return NULL; + } while (skip--); + + return dev_to_disk(dev); } -static void *part_start(struct seq_file *part, loff_t *pos) +static void *disk_seqf_next(struct seq_file *seqf, void *v, loff_t *pos) { struct device *dev; - loff_t n = *pos; - - if (!n) - part->private = (void *)1LU; /* tell show to print header */ - dev = class_find_device(&block_class, NULL, &n, find_start); + (*pos)++; + dev = class_dev_iter_next(seqf->private); if (dev) return dev_to_disk(dev); return NULL; } -static int find_next(struct device *dev, void *data) +static void disk_seqf_stop(struct seq_file *seqf, void *v) { - if (dev->type == &disk_type) - return 1; - return 0; -} + struct class_dev_iter *iter = seqf->private; -static void *part_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct gendisk *gp = v; - struct device *dev; - ++*pos; - dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) { - put_device(dev); - return dev_to_disk(dev); + /* stop is called even after start failed :-( */ + if (iter) { + class_dev_iter_exit(iter); + kfree(iter); } - return NULL; } -static void part_stop(struct seq_file *part, void *v) +static void *show_partition_start(struct seq_file *seqf, loff_t *pos) { + static void *p; + + p = disk_seqf_start(seqf, pos); + if (!IS_ERR(p) && p) + seq_puts(seqf, "major minor #blocks name\n\n"); + return p; } static int show_partition(struct seq_file *part, void *v) @@ -383,9 +380,9 @@ static int show_partition(struct seq_file *part, void *v) } const struct seq_operations partitions_op = { - .start = part_start, - .next = part_next, - .stop = part_stop, + .start = show_partition_start, + .next = disk_seqf_next, + .stop = disk_seqf_stop, .show = show_partition }; #endif @@ -567,44 +564,6 @@ static struct device_type disk_type = { }; #ifdef CONFIG_PROC_FS -/* - * aggregate disk stat collector. Uses the same stats that the sysfs - * entries do, above, but makes them available through one seq_file. - * - * The output looks suspiciously like /proc/partitions with a bunch of - * extra fields. - */ - -static void *diskstats_start(struct seq_file *part, loff_t *pos) -{ - struct device *dev; - loff_t n = *pos; - - dev = class_find_device(&block_class, NULL, &n, find_start); - if (dev) - return dev_to_disk(dev); - - return NULL; -} - -static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct gendisk *gp = v; - struct device *dev; - - ++*pos; - dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) { - put_device(dev); - return dev_to_disk(dev); - } - return NULL; -} - -static void diskstats_stop(struct seq_file *part, void *v) -{ -} - static int diskstats_show(struct seq_file *s, void *v) { struct gendisk *gp = v; @@ -666,9 +625,9 @@ static int diskstats_show(struct seq_file *s, void *v) } const struct seq_operations diskstats_op = { - .start = diskstats_start, - .next = diskstats_next, - .stop = diskstats_stop, + .start = disk_seqf_start, + .next = disk_seqf_next, + .stop = disk_seqf_stop, .show = diskstats_show }; #endif /* CONFIG_PROC_FS */ @@ -696,40 +655,23 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ -struct find_block { - const char *name; - int part; -}; - -static int match_id(struct device *dev, void *data) +dev_t blk_lookup_devt(const char *name, int part) { - struct find_block *find = data; + dev_t devt = MKDEV(0, 0); + struct class_dev_iter iter; + struct device *dev; - if (dev->type != &disk_type) - return 0; - if (strcmp(dev->bus_id, find->name) == 0) { + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); - if (find->part < disk->minors) - return 1; - } - return 0; -} -dev_t blk_lookup_devt(const char *name, int part) -{ - struct device *dev; - dev_t devt = MKDEV(0, 0); - struct find_block find; - - find.name = name; - find.part = part; - dev = class_find_device(&block_class, NULL, &find, match_id); - if (dev) { - put_device(dev); - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + part); + if (!strcmp(dev->bus_id, name) && part < disk->minors) { + devt = MKDEV(MAJOR(dev->devt), + MINOR(dev->devt) + part); + break; + } } - + class_dev_iter_exit(&iter); return devt; } EXPORT_SYMBOL(blk_lookup_devt); -- GitLab From ec2cdedf798385a9397ac50dd0405dd658f8529c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:30:15 +0900 Subject: [PATCH 3410/5416] block: allow deleting zero length partition delete_partition() was noop for zero length partition. As the addition code allows creating zero lenght partition and deletion is assumed to always succeed, this causes memory leak for zero length partitions. Allow zero length partitions to end their meaningless lives. While at it, allow deleting zero lenght partition via BLKPG_DEL_PARTITION ioctl too. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/ioctl.c | 2 -- fs/partitions/check.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index 375c57922b0..c722de0ef2e 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -68,8 +68,6 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user case BLKPG_DEL_PARTITION: if (!disk->part[part-1]) return -ENXIO; - if (disk->part[part - 1]->nr_sects == 0) - return -ENXIO; bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ecc3330972e..68f3e41ae66 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -325,8 +325,6 @@ void delete_partition(struct gendisk *disk, int part) if (!p) return; - if (!p->nr_sects) - return; disk->part[part-1] = NULL; p->start_sect = 0; p->nr_sects = 0; -- GitLab From 88e341261ca4d39eec21b212961c77eff51105f7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:30:16 +0900 Subject: [PATCH 3411/5416] block: update add_partition() error handling d805dda4 tried to fix error case handling in add_partition() but had a few problems. * disk->part[] entry is set early and left dangling if operation fails. * Once device initialized, the last put_device() is responsible for freeing all the resources. The failure path freed part_stats and p regardless of put_device() causing double free. * holders subdir holds reference to the disk device, so failure path should remove it to release resources properly which was missing. This patch fixes the above problems and while at it move partition slot busy check into add_partition() for completeness and inlines holders subdirectory creation. Using separate function for it just obfuscates the code. Signed-off-by: Tejun Heo Cc: Abdel Benamrouche Signed-off-by: Jens Axboe --- block/ioctl.c | 7 ++----- fs/partitions/check.c | 40 +++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index c722de0ef2e..eb046aeede8 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -43,12 +43,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user || pstart < 0 || plength < 0) return -EINVAL; } - /* partition number in use? */ + mutex_lock(&bdev->bd_mutex); - if (disk->part[part - 1]) { - mutex_unlock(&bdev->bd_mutex); - return -EBUSY; - } + /* overlap? */ for (i = 0; i < disk->minors - 1; i++) { struct hd_struct *s = disk->part[i]; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 68f3e41ae66..16f98d82460 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -300,15 +300,6 @@ struct device_type part_type = { .release = part_release, }; -static inline void partition_sysfs_add_subdir(struct hd_struct *p) -{ - struct kobject *k; - - k = kobject_get(&p->dev.kobj); - p->holder_dir = kobject_create_and_add("holders", k); - kobject_put(k); -} - static inline void disk_sysfs_add_subdirs(struct gendisk *disk) { struct kobject *k; @@ -347,13 +338,16 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, struct hd_struct *p; int err; + if (disk->part[part - 1]) + return -EBUSY; + p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; if (!init_part_stats(p)) { err = -ENOMEM; - goto out0; + goto out_free; } p->start_sect = start; p->nr_sects = len; @@ -372,34 +366,42 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, p->dev.class = &block_class; p->dev.type = &part_type; p->dev.parent = &disk->dev; - disk->part[part-1] = p; /* delay uevent until 'holders' subdir is created */ p->dev.uevent_suppress = 1; err = device_add(&p->dev); if (err) - goto out1; - partition_sysfs_add_subdir(p); + goto out_put; + + err = -ENOMEM; + p->holder_dir = kobject_create_and_add("holders", &p->dev.kobj); + if (!p->holder_dir) + goto out_del; + p->dev.uevent_suppress = 0; if (flags & ADDPART_FLAG_WHOLEDISK) { err = device_create_file(&p->dev, &dev_attr_whole_disk); if (err) - goto out2; + goto out_del; } + /* everything is up and running, commence */ + disk->part[part - 1] = p; + /* suppress uevent if the disk supresses it */ if (!disk->dev.uevent_suppress) kobject_uevent(&p->dev.kobj, KOBJ_ADD); return 0; -out2: +out_free: + kfree(p); + return err; +out_del: + kobject_put(p->holder_dir); device_del(&p->dev); -out1: +out_put: put_device(&p->dev); - free_part_stats(p); -out0: - kfree(p); return err; } -- GitLab From 310a2c1012934f590192377f65940cad4aa72b15 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:17 +0900 Subject: [PATCH 3412/5416] block: misc updates This patch makes the following misc updates in preparation for disk->part dereference fix and extended block devt support. * implment part_to_disk() * fix comment about gendisk->part indexing * rename get_part() to disk_map_sector() * don't use n which is always zero while printing disk information in diskstats_show() Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 7 ++++--- block/blk-merge.c | 4 ++-- block/genhd.c | 4 ++-- drivers/block/aoe/aoecmd.c | 2 +- include/linux/genhd.h | 13 ++++++++++--- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 86d22e7d65c..a0dc2e72fcb 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -60,7 +60,7 @@ static void drive_stat_acct(struct request *rq, int new_io) if (!blk_fs_request(rq) || !rq->rq_disk) return; - part = get_part(rq->rq_disk, rq->sector); + part = disk_map_sector(rq->rq_disk, rq->sector); if (!new_io) __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector); else { @@ -1557,7 +1557,8 @@ static int __end_that_request_first(struct request *req, int error, } if (blk_fs_request(req) && req->rq_disk) { - struct hd_struct *part = get_part(req->rq_disk, req->sector); + struct hd_struct *part = + disk_map_sector(req->rq_disk, req->sector); const int rw = rq_data_dir(req); all_stat_add(req->rq_disk, part, sectors[rw], @@ -1745,7 +1746,7 @@ static void end_that_request_last(struct request *req, int error) if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); - struct hd_struct *part = get_part(disk, req->sector); + struct hd_struct *part = disk_map_sector(disk, req->sector); __all_stat_inc(disk, part, ios[rw], req->sector); __all_stat_add(disk, part, ticks[rw], duration, req->sector); diff --git a/block/blk-merge.c b/block/blk-merge.c index d81d91419ff..9b17da698d7 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -387,8 +387,8 @@ static int attempt_merge(struct request_queue *q, struct request *req, elv_merge_requests(q, req, next); if (req->rq_disk) { - struct hd_struct *part - = get_part(req->rq_disk, req->sector); + struct hd_struct *part = + disk_map_sector(req->rq_disk, req->sector); disk_round_stats(req->rq_disk); req->rq_disk->in_flight--; if (part) { diff --git a/block/genhd.c b/block/genhd.c index 8b9a9ff1a84..11038fbc75e 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -568,7 +568,7 @@ static int diskstats_show(struct seq_file *s, void *v) { struct gendisk *gp = v; char buf[BDEVNAME_SIZE]; - int n = 0; + int n; /* if (&gp->dev.kobj.entry == block_class.devices.next) @@ -582,7 +582,7 @@ static int diskstats_show(struct seq_file *s, void *v) disk_round_stats(gp); preempt_enable(); seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", - gp->major, n + gp->first_minor, disk_name(gp, n, buf), + gp->major, gp->first_minor, disk_name(gp, 0, buf), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), (unsigned long long)disk_stat_read(gp, sectors[0]), jiffies_to_msecs(disk_stat_read(gp, ticks[0])), diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 2f1746295d0..885d1409521 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -757,7 +757,7 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector const int rw = bio_data_dir(bio); struct hd_struct *part; - part = get_part(disk, sector); + part = disk_map_sector(disk, sector); all_stat_inc(disk, part, ios[rw], sector); all_stat_add(disk, part, ticks[rw], duration, sector); all_stat_add(disk, part, sectors[rw], n_sect, sector); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index be4f5e5bfe0..c64e659c984 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -116,7 +116,7 @@ struct gendisk { int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ char disk_name[32]; /* name of major driver */ - struct hd_struct **part; /* [indexed by minor] */ + struct hd_struct **part; /* [indexed by minor - 1] */ struct block_device_operations *fops; struct request_queue *queue; void *private_data; @@ -145,14 +145,21 @@ struct gendisk { #endif }; +static inline struct gendisk *part_to_disk(struct hd_struct *part) +{ + if (likely(part)) + return dev_to_disk((part)->dev.parent); + return NULL; +} + /* * Macros to operate on percpu disk statistics: * * The __ variants should only be called in critical sections. The full * variants disable/enable preemption. */ -static inline struct hd_struct *get_part(struct gendisk *gendiskp, - sector_t sector) +static inline struct hd_struct *disk_map_sector(struct gendisk *gendiskp, + sector_t sector) { struct hd_struct *part; int i; -- GitLab From cf771cb5a7b716f3f9e532fd42a1e3a0a75adec5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 09:01:09 +0200 Subject: [PATCH 3413/5416] block: make variable and argument names more consistent In hd_struct, @partno is used to denote partition number and a number of other places use @part to denote hd_struct. Functions use @part and @index instead. This causes confusion and makes it difficult to use consistent variable names for hd_struct. Always use @partno if a variable represents partition number. Also, print out functions use @f or @part for seq_file argument. Use @seqf uniformly instead. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 54 ++++++++++++++++++++----------------------- block/ioctl.c | 15 ++++++------ fs/block_dev.c | 8 +++---- fs/partitions/check.c | 33 +++++++++++++------------- include/linux/genhd.h | 12 +++++----- 5 files changed, 60 insertions(+), 62 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 11038fbc75e..dc9ad4c171e 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -43,14 +43,14 @@ static inline int major_to_index(int major) } #ifdef CONFIG_PROC_FS -void blkdev_show(struct seq_file *f, off_t offset) +void blkdev_show(struct seq_file *seqf, off_t offset) { struct blk_major_name *dp; if (offset < BLKDEV_MAJOR_HASH_SIZE) { mutex_lock(&block_class_lock); for (dp = major_names[offset]; dp; dp = dp->next) - seq_printf(f, "%3d %s\n", dp->major, dp->name); + seq_printf(seqf, "%3d %s\n", dp->major, dp->name); mutex_unlock(&block_class_lock); } } @@ -157,7 +157,7 @@ void blk_unregister_region(dev_t devt, unsigned long range) EXPORT_SYMBOL(blk_unregister_region); -static struct kobject *exact_match(dev_t devt, int *part, void *data) +static struct kobject *exact_match(dev_t devt, int *partno, void *data) { struct gendisk *p = data; @@ -217,9 +217,9 @@ void unlink_gendisk(struct gendisk *disk) * This function gets the structure containing partitioning * information for the given device @devt. */ -struct gendisk *get_gendisk(dev_t devt, int *part) +struct gendisk *get_gendisk(dev_t devt, int *partno) { - struct kobject *kobj = kobj_lookup(bdev_map, devt, part); + struct kobject *kobj = kobj_lookup(bdev_map, devt, partno); struct device *dev = kobj_to_dev(kobj); return kobj ? dev_to_disk(dev) : NULL; @@ -336,23 +336,12 @@ static void *show_partition_start(struct seq_file *seqf, loff_t *pos) return p; } -static int show_partition(struct seq_file *part, void *v) +static int show_partition(struct seq_file *seqf, void *v) { struct gendisk *sgp = v; int n; char buf[BDEVNAME_SIZE]; - /* - * Print header if start told us to do. This is to preserve - * the original behavior of not printing header if no - * partition exists. This hackery will be removed later with - * class iteration clean up. - */ - if (part->private) { - seq_puts(part, "major minor #blocks name\n\n"); - part->private = NULL; - } - /* Don't show non-partitionable removeable devices or empty devices */ if (!get_capacity(sgp) || (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) @@ -361,7 +350,7 @@ static int show_partition(struct seq_file *part, void *v) return 0; /* show the full disk and all non-0 size partitions of it */ - seq_printf(part, "%4d %4d %10llu %s\n", + seq_printf(seqf, "%4d %4d %10llu %s\n", sgp->major, sgp->first_minor, (unsigned long long)get_capacity(sgp) >> 1, disk_name(sgp, 0, buf)); @@ -370,7 +359,7 @@ static int show_partition(struct seq_file *part, void *v) continue; if (sgp->part[n]->nr_sects == 0) continue; - seq_printf(part, "%4d %4d %10llu %s\n", + seq_printf(seqf, "%4d %4d %10llu %s\n", sgp->major, n + 1 + sgp->first_minor, (unsigned long long)sgp->part[n]->nr_sects >> 1 , disk_name(sgp, n + 1, buf)); @@ -388,7 +377,7 @@ const struct seq_operations partitions_op = { #endif -static struct kobject *base_probe(dev_t devt, int *part, void *data) +static struct kobject *base_probe(dev_t devt, int *partno, void *data) { if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) /* Make old-style 2.4 aliases work */ @@ -564,7 +553,14 @@ static struct device_type disk_type = { }; #ifdef CONFIG_PROC_FS -static int diskstats_show(struct seq_file *s, void *v) +/* + * aggregate disk stat collector. Uses the same stats that the sysfs + * entries do, above, but makes them available through one seq_file. + * + * The output looks suspiciously like /proc/partitions with a bunch of + * extra fields. + */ +static int diskstats_show(struct seq_file *seqf, void *v) { struct gendisk *gp = v; char buf[BDEVNAME_SIZE]; @@ -572,7 +568,7 @@ static int diskstats_show(struct seq_file *s, void *v) /* if (&gp->dev.kobj.entry == block_class.devices.next) - seq_puts(s, "major minor name" + seq_puts(seqf, "major minor name" " rio rmerge rsect ruse wio wmerge " "wsect wuse running use aveq" "\n\n"); @@ -581,7 +577,7 @@ static int diskstats_show(struct seq_file *s, void *v) preempt_disable(); disk_round_stats(gp); preempt_enable(); - seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", + seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", gp->major, gp->first_minor, disk_name(gp, 0, buf), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), (unsigned long long)disk_stat_read(gp, sectors[0]), @@ -603,7 +599,7 @@ static int diskstats_show(struct seq_file *s, void *v) preempt_disable(); part_round_stats(hd); preempt_enable(); - seq_printf(s, "%4d %4d %s %lu %lu %llu " + seq_printf(seqf, "%4d %4d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", gp->major, n + gp->first_minor + 1, disk_name(gp, n + 1, buf), @@ -655,7 +651,7 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ -dev_t blk_lookup_devt(const char *name, int part) +dev_t blk_lookup_devt(const char *name, int partno) { dev_t devt = MKDEV(0, 0); struct class_dev_iter iter; @@ -665,9 +661,9 @@ dev_t blk_lookup_devt(const char *name, int part) while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); - if (!strcmp(dev->bus_id, name) && part < disk->minors) { + if (!strcmp(dev->bus_id, name) && partno < disk->minors) { devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + part); + MINOR(dev->devt) + partno); break; } } @@ -777,10 +773,10 @@ int bdev_read_only(struct block_device *bdev) EXPORT_SYMBOL(bdev_read_only); -int invalidate_partition(struct gendisk *disk, int index) +int invalidate_partition(struct gendisk *disk, int partno) { int res = 0; - struct block_device *bdev = bdget_disk(disk, index); + struct block_device *bdev = bdget_disk(disk, partno); if (bdev) { fsync_bdev(bdev); res = __invalidate_device(bdev); diff --git a/block/ioctl.c b/block/ioctl.c index eb046aeede8..d77f5e280a6 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -15,7 +15,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user struct blkpg_ioctl_arg a; struct blkpg_partition p; long long start, length; - int part; + int partno; int i; int err; @@ -28,8 +28,8 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user disk = bdev->bd_disk; if (bdev != bdev->bd_contains) return -EINVAL; - part = p.pno; - if (part <= 0 || part >= disk->minors) + partno = p.pno; + if (partno <= 0 || partno >= disk->minors) return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: @@ -59,13 +59,14 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user } } /* all seems OK */ - err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE); + err = add_partition(disk, partno, start, length, + ADDPART_FLAG_NONE); mutex_unlock(&bdev->bd_mutex); return err; case BLKPG_DEL_PARTITION: - if (!disk->part[part-1]) + if (!disk->part[partno - 1]) return -ENXIO; - bdevp = bdget_disk(disk, part); + bdevp = bdget_disk(disk, partno); if (!bdevp) return -ENOMEM; mutex_lock(&bdevp->bd_mutex); @@ -79,7 +80,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user invalidate_bdev(bdevp); mutex_lock_nested(&bdev->bd_mutex, 1); - delete_partition(disk, part); + delete_partition(disk, partno); mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); diff --git a/fs/block_dev.c b/fs/block_dev.c index aff54219e04..de0776cd721 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -930,7 +930,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) struct module *owner = NULL; struct gendisk *disk; int ret; - int part; + int partno; int perm = 0; if (file->f_mode & FMODE_READ) @@ -949,7 +949,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) ret = -ENXIO; file->f_mapping = bdev->bd_inode->i_mapping; lock_kernel(); - disk = get_gendisk(bdev->bd_dev, &part); + disk = get_gendisk(bdev->bd_dev, &partno); if (!disk) { unlock_kernel(); bdput(bdev); @@ -961,7 +961,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) if (!bdev->bd_openers) { bdev->bd_disk = disk; bdev->bd_contains = bdev; - if (!part) { + if (!partno) { struct backing_dev_info *bdi; if (disk->fops->open) { ret = disk->fops->open(bdev->bd_inode, file); @@ -989,7 +989,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) if (ret) goto out_first; bdev->bd_contains = whole; - p = disk->part[part - 1]; + p = disk->part[partno - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 16f98d82460..b86aab1b0df 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -120,22 +120,22 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = * a pointer to that same buffer (for convenience). */ -char *disk_name(struct gendisk *hd, int part, char *buf) +char *disk_name(struct gendisk *hd, int partno, char *buf) { - if (!part) + if (!partno) snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name); else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) - snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, part); + snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno); else - snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, part); + snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno); return buf; } const char *bdevname(struct block_device *bdev, char *buf) { - int part = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor; - return disk_name(bdev->bd_disk, part, buf); + int partno = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor; + return disk_name(bdev->bd_disk, partno, buf); } EXPORT_SYMBOL(bdevname); @@ -310,13 +310,13 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk) kobject_put(k); } -void delete_partition(struct gendisk *disk, int part) +void delete_partition(struct gendisk *disk, int partno) { - struct hd_struct *p = disk->part[part-1]; + struct hd_struct *p = disk->part[partno - 1]; if (!p) return; - disk->part[part-1] = NULL; + disk->part[partno - 1] = NULL; p->start_sect = 0; p->nr_sects = 0; part_stat_set_all(p, 0); @@ -333,12 +333,13 @@ static ssize_t whole_disk_show(struct device *dev, static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, whole_disk_show, NULL); -int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) +int add_partition(struct gendisk *disk, int partno, + sector_t start, sector_t len, int flags) { struct hd_struct *p; int err; - if (disk->part[part - 1]) + if (disk->part[partno - 1]) return -EBUSY; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -351,18 +352,18 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, } p->start_sect = start; p->nr_sects = len; - p->partno = part; + p->partno = partno; p->policy = disk->policy; if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1])) snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%sp%d", disk->dev.bus_id, part); + "%sp%d", disk->dev.bus_id, partno); else snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%s%d", disk->dev.bus_id, part); + "%s%d", disk->dev.bus_id, partno); device_initialize(&p->dev); - p->dev.devt = MKDEV(disk->major, disk->first_minor + part); + p->dev.devt = MKDEV(disk->major, disk->first_minor + partno); p->dev.class = &block_class; p->dev.type = &part_type; p->dev.parent = &disk->dev; @@ -386,7 +387,7 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, } /* everything is up and running, commence */ - disk->part[part - 1] = p; + disk->part[partno - 1] = p; /* suppress uevent if the disk supresses it */ if (!disk->dev.uevent_suppress) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c64e659c984..d1723c0a860 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -365,7 +365,7 @@ extern int get_blkdev_list(char *, int); extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp); -extern struct gendisk *get_gendisk(dev_t dev, int *part); +extern struct gendisk *get_gendisk(dev_t dev, int *partno); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); @@ -534,8 +534,8 @@ struct unixware_disklabel { #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 -extern dev_t blk_lookup_devt(const char *name, int part); -extern char *disk_name (struct gendisk *hd, int part, char *buf); +extern dev_t blk_lookup_devt(const char *name, int partno); +extern char *disk_name (struct gendisk *hd, int partno, char *buf); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int); @@ -553,16 +553,16 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data); extern void blk_unregister_region(dev_t devt, unsigned long range); -static inline struct block_device *bdget_disk(struct gendisk *disk, int index) +static inline struct block_device *bdget_disk(struct gendisk *disk, int partno) { - return bdget(MKDEV(disk->major, disk->first_minor) + index); + return bdget(MKDEV(disk->major, disk->first_minor) + partno); } #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } -static inline dev_t blk_lookup_devt(const char *name, int part) +static inline dev_t blk_lookup_devt(const char *name, int partno) { dev_t devt = MKDEV(0, 0); return devt; -- GitLab From f331c0296f2a9fee0d396a70598b954062603015 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 09:01:48 +0200 Subject: [PATCH 3414/5416] block: don't depend on consecutive minor space * Implement disk_devt() and part_devt() and use them to directly access devt instead of computing it from ->major and ->first_minor. Note that all references to ->major and ->first_minor outside of block layer is used to determine devt of the disk (the part0) and as ->major and ->first_minor will continue to represent devt for the disk, converting these users aren't strictly necessary. However, convert them for consistency. * Implement disk_max_parts() to avoid directly deferencing genhd->minors. * Update bdget_disk() such that it doesn't assume consecutive minor space. * Move devt computation from register_disk() to add_disk() and make it the only one (all other usages use the initially determined value). These changes clean up the code and will help disk->part dereference fix and extended block device numbers. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 107 ++++++++++++++++++++-------- block/ioctl.c | 6 +- drivers/block/pktcdvd.c | 2 +- drivers/block/ps3disk.c | 2 +- drivers/char/random.c | 6 +- drivers/md/dm-ioctl.c | 4 +- drivers/md/dm-stripe.c | 4 +- drivers/md/dm.c | 7 +- drivers/memstick/core/mspro_block.c | 2 +- drivers/mmc/card/block.c | 2 +- drivers/s390/block/dasd_proc.c | 3 +- drivers/s390/block/dcssblk.c | 4 +- drivers/scsi/sr.c | 2 +- fs/block_dev.c | 2 +- fs/partitions/check.c | 19 ++--- include/linux/genhd.h | 27 +++++-- 16 files changed, 132 insertions(+), 67 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index dc9ad4c171e..fa32d09fda2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -186,13 +186,14 @@ void add_disk(struct gendisk *disk) int retval; disk->flags |= GENHD_FL_UP; - blk_register_region(MKDEV(disk->major, disk->first_minor), - disk->minors, NULL, exact_match, exact_lock, disk); + disk->dev.devt = MKDEV(disk->major, disk->first_minor); + blk_register_region(disk_devt(disk), disk->minors, NULL, + exact_match, exact_lock, disk); register_disk(disk); blk_register_queue(disk); bdi = &disk->queue->backing_dev_info; - bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); + bdi_register_dev(bdi, disk_devt(disk)); retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); WARN_ON(retval); } @@ -205,8 +206,7 @@ void unlink_gendisk(struct gendisk *disk) sysfs_remove_link(&disk->dev.kobj, "bdi"); bdi_unregister(&disk->queue->backing_dev_info); blk_unregister_queue(disk); - blk_unregister_region(MKDEV(disk->major, disk->first_minor), - disk->minors); + blk_unregister_region(disk_devt(disk), disk->minors); } /** @@ -225,6 +225,38 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) return kobj ? dev_to_disk(dev) : NULL; } +/** + * bdget_disk - do bdget() by gendisk and partition number + * @disk: gendisk of interest + * @partno: partition number + * + * Find partition @partno from @disk, do bdget() on it. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * Resulting block_device on success, NULL on failure. + */ +extern struct block_device *bdget_disk(struct gendisk *disk, int partno) +{ + dev_t devt = MKDEV(0, 0); + + if (partno == 0) + devt = disk_devt(disk); + else { + struct hd_struct *part = disk->part[partno - 1]; + + if (part && part->nr_sects) + devt = part_devt(part); + } + + if (likely(devt != MKDEV(0, 0))) + return bdget(devt); + return NULL; +} +EXPORT_SYMBOL(bdget_disk); + /* * print a full list of all partitions - intended for places where the root * filesystem can't be mounted and thus to give the victim some idea of what @@ -255,7 +287,7 @@ void __init printk_all_partitions(void) * option takes. */ printk("%02x%02x %10llu %s", - disk->major, disk->first_minor, + MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)), (unsigned long long)get_capacity(disk) >> 1, disk_name(disk, 0, buf)); if (disk->driverfs_dev != NULL && @@ -266,15 +298,15 @@ void __init printk_all_partitions(void) printk(" (driver?)\n"); /* now show the partitions */ - for (n = 0; n < disk->minors - 1; ++n) { - if (disk->part[n] == NULL) - continue; - if (disk->part[n]->nr_sects == 0) + for (n = 0; n < disk_max_parts(disk); ++n) { + struct hd_struct *part = disk->part[n]; + + if (!part || !part->nr_sects) continue; printk(" %02x%02x %10llu %s\n", - disk->major, n + 1 + disk->first_minor, - (unsigned long long)disk->part[n]->nr_sects >> 1, - disk_name(disk, n + 1, buf)); + MAJOR(part_devt(part)), MINOR(part_devt(part)), + (unsigned long long)part->nr_sects >> 1, + disk_name(disk, part->partno, buf)); } } class_dev_iter_exit(&iter); @@ -343,26 +375,27 @@ static int show_partition(struct seq_file *seqf, void *v) char buf[BDEVNAME_SIZE]; /* Don't show non-partitionable removeable devices or empty devices */ - if (!get_capacity(sgp) || - (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) + if (!get_capacity(sgp) || (!disk_max_parts(sgp) && + (sgp->flags & GENHD_FL_REMOVABLE))) return 0; if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) return 0; /* show the full disk and all non-0 size partitions of it */ seq_printf(seqf, "%4d %4d %10llu %s\n", - sgp->major, sgp->first_minor, + MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)), (unsigned long long)get_capacity(sgp) >> 1, disk_name(sgp, 0, buf)); - for (n = 0; n < sgp->minors - 1; n++) { - if (!sgp->part[n]) + for (n = 0; n < disk_max_parts(sgp); n++) { + struct hd_struct *part = sgp->part[n]; + if (!part) continue; - if (sgp->part[n]->nr_sects == 0) + if (part->nr_sects == 0) continue; seq_printf(seqf, "%4d %4d %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1 , - disk_name(sgp, n + 1, buf)); + MAJOR(part_devt(part)), MINOR(part_devt(part)), + (unsigned long long)part->nr_sects >> 1, + disk_name(sgp, part->partno, buf)); } return 0; @@ -578,7 +611,8 @@ static int diskstats_show(struct seq_file *seqf, void *v) disk_round_stats(gp); preempt_enable(); seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", - gp->major, gp->first_minor, disk_name(gp, 0, buf), + MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), + disk_name(gp, 0, buf), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), (unsigned long long)disk_stat_read(gp, sectors[0]), jiffies_to_msecs(disk_stat_read(gp, ticks[0])), @@ -590,7 +624,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); /* now show all non-0 size partitions of it */ - for (n = 0; n < gp->minors - 1; n++) { + for (n = 0; n < disk_max_parts(gp); n++) { struct hd_struct *hd = gp->part[n]; if (!hd || !hd->nr_sects) @@ -601,8 +635,8 @@ static int diskstats_show(struct seq_file *seqf, void *v) preempt_enable(); seq_printf(seqf, "%4d %4d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", - gp->major, n + gp->first_minor + 1, - disk_name(gp, n + 1, buf), + MAJOR(part_devt(hd)), MINOR(part_devt(hd)), + disk_name(gp, hd->partno, buf), part_stat_read(hd, ios[0]), part_stat_read(hd, merges[0]), (unsigned long long)part_stat_read(hd, sectors[0]), @@ -661,11 +695,22 @@ dev_t blk_lookup_devt(const char *name, int partno) while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); - if (!strcmp(dev->bus_id, name) && partno < disk->minors) { - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + partno); - break; + if (strcmp(dev->bus_id, name)) + continue; + if (partno < 0 || partno > disk_max_parts(disk)) + continue; + + if (partno == 0) + devt = disk_devt(disk); + else { + struct hd_struct *part = disk->part[partno - 1]; + + if (!part || !part->nr_sects) + continue; + + devt = part_devt(part); } + break; } class_dev_iter_exit(&iter); return devt; @@ -755,7 +800,7 @@ void set_disk_ro(struct gendisk *disk, int flag) { int i; disk->policy = flag; - for (i = 0; i < disk->minors - 1; i++) + for (i = 0; i < disk_max_parts(disk); i++) if (disk->part[i]) disk->part[i]->policy = flag; } diff --git a/block/ioctl.c b/block/ioctl.c index d77f5e280a6..403f7d7e0c2 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -29,7 +29,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user if (bdev != bdev->bd_contains) return -EINVAL; partno = p.pno; - if (partno <= 0 || partno >= disk->minors) + if (partno <= 0 || partno > disk_max_parts(disk)) return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: @@ -47,7 +47,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user mutex_lock(&bdev->bd_mutex); /* overlap? */ - for (i = 0; i < disk->minors - 1; i++) { + for (i = 0; i < disk_max_parts(disk); i++) { struct hd_struct *s = disk->part[i]; if (!s) @@ -96,7 +96,7 @@ static int blkdev_reread_part(struct block_device *bdev) struct gendisk *disk = bdev->bd_disk; int res; - if (disk->minors == 1 || bdev != bdev->bd_contains) + if (!disk_max_parts(disk) || bdev != bdev->bd_contains) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 29b7a648cc6..e1a90bbb474 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2911,7 +2911,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) if (!disk->queue) goto out_mem2; - pd->pkt_dev = MKDEV(disk->major, disk->first_minor); + pd->pkt_dev = MKDEV(pktdev_major, idx); ret = pkt_new_dev(pd, dev); if (ret) goto out_new_dev; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 4b0d6c7f4c6..936466f62af 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -541,7 +541,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev) struct ps3disk_private *priv = dev->sbd.core.driver_data; mutex_lock(&ps3disk_mask_mutex); - __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS, + __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS, &ps3disk_mask); mutex_unlock(&ps3disk_mask_mutex); del_gendisk(priv->gendisk); diff --git a/drivers/char/random.c b/drivers/char/random.c index 7ce1ac4baa6..6af435b8986 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -661,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk) if (!disk || !disk->random) return; /* first major is 1, so we get >= 0x200 here */ - DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor); + DEBUG_ENT("disk event %d:%d\n", + MAJOR(disk_devt(disk)), MINOR(disk_devt(disk))); - add_timer_randomness(disk->random, - 0x100 + MKDEV(disk->major, disk->first_minor)); + add_timer_randomness(disk->random, 0x100 + disk_devt(disk)); } #endif diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index b262c0042de..c3de311117a 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -426,7 +426,7 @@ static int list_devices(struct dm_ioctl *param, size_t param_size) old_nl->next = (uint32_t) ((void *) nl - (void *) old_nl); disk = dm_disk(hc->md); - nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + nl->dev = huge_encode_dev(disk_devt(disk)); nl->next = 0; strcpy(nl->name, hc->name); @@ -539,7 +539,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) if (dm_suspended(md)) param->flags |= DM_SUSPEND_FLAG; - param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + param->dev = huge_encode_dev(disk_devt(disk)); /* * Yes, this will be out of date by the time it gets back diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 4de90ab3968..b745d8ac625 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -284,8 +284,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, memset(major_minor, 0, sizeof(major_minor)); sprintf(major_minor, "%d:%d", - bio->bi_bdev->bd_disk->major, - bio->bi_bdev->bd_disk->first_minor); + MAJOR(disk_devt(bio->bi_bdev->bd_disk)), + MINOR(disk_devt(bio->bi_bdev->bd_disk))); /* * Test to see which stripe drive triggered the event diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ace998ce59f..a78caad2999 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1146,7 +1146,7 @@ static void unlock_fs(struct mapped_device *md); static void free_dev(struct mapped_device *md) { - int minor = md->disk->first_minor; + int minor = MINOR(disk_devt(md->disk)); if (md->suspended_bdev) { unlock_fs(md); @@ -1267,7 +1267,7 @@ static struct mapped_device *dm_find_md(dev_t dev) md = idr_find(&_minor_idr, minor); if (md && (md == MINOR_ALLOCED || - (dm_disk(md)->first_minor != minor) || + (MINOR(disk_devt(dm_disk(md))) != minor) || test_bit(DMF_FREEING, &md->flags))) { md = NULL; goto out; @@ -1318,7 +1318,8 @@ void dm_put(struct mapped_device *md) if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { map = dm_get_table(md); - idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor); + idr_replace(&_minor_idr, MINOR_ALLOCED, + MINOR(disk_devt(dm_disk(md)))); set_bit(DMF_FREEING, &md->flags); spin_unlock(&_minor_lock); if (!dm_suspended(md)) { diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index d2d2318dafa..82bf649ef13 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -197,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) static int mspro_block_disk_release(struct gendisk *disk) { struct mspro_block_data *msb = disk->private_data; - int disk_id = disk->first_minor >> MSPRO_BLOCK_PART_SHIFT; + int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT; mutex_lock(&mspro_block_disk_lock); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ebc8b9d7761..97156b689e8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -83,7 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { - int devidx = md->disk->first_minor >> MMC_SHIFT; + int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; __clear_bit(devidx, dev_use); put_disk(md->disk); diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 03c0e40a92f..e3b5c4d3036 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -76,7 +76,8 @@ dasd_devices_show(struct seq_file *m, void *v) /* Print kdev. */ if (block->gdp) seq_printf(m, " at (%3d:%6d)", - block->gdp->major, block->gdp->first_minor); + MAJOR(disk_devt(block->gdp)), + MINOR(disk_devt(block->gdp))); else seq_printf(m, " at (???:??????)"); /* Print device name. */ diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 711b3004b3e..9481e4a3f76 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -114,7 +114,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) found = 0; // test if minor available list_for_each_entry(entry, &dcssblk_devices, lh) - if (minor == entry->gd->first_minor) + if (minor == MINOR(disk_devt(entry->gd))) found++; if (!found) break; // got unused minor } @@ -397,7 +397,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char goto unload_seg; } sprintf(dev_info->gd->disk_name, "dcssblk%d", - dev_info->gd->first_minor); + MINOR(disk_devt(dev_info->gd))); list_add_tail(&dev_info->lh, &dcssblk_devices); if (!try_module_get(THIS_MODULE)) { diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 27f5bfd1def..8dbe3798d5f 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -878,7 +878,7 @@ static void sr_kref_release(struct kref *kref) struct gendisk *disk = cd->disk; spin_lock(&sr_index_lock); - clear_bit(disk->first_minor, sr_index_bits); + clear_bit(MINOR(disk_devt(disk)), sr_index_bits); spin_unlock(&sr_index_lock); unregister_cdrom(&cd->cdi); diff --git a/fs/block_dev.c b/fs/block_dev.c index de0776cd721..72e0a2887cb 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev) if (bdops->revalidate_disk) bdops->revalidate_disk(bdev->bd_disk); - if (bdev->bd_disk->minors > 1) + if (disk_max_parts(bdev->bd_disk)) bdev->bd_invalidated = 1; return 1; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index b86aab1b0df..e77fa144a07 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -134,7 +134,11 @@ char *disk_name(struct gendisk *hd, int partno, char *buf) const char *bdevname(struct block_device *bdev, char *buf) { - int partno = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor; + int partno = 0; + + if (bdev->bd_part) + partno = bdev->bd_part->partno; + return disk_name(bdev->bd_disk, partno, buf); } @@ -169,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); - state->limit = hd->minors; + state->limit = disk_max_parts(hd) + 1; i = res = err = 0; while (!res && check_part[i]) { memset(&state->parts, 0, sizeof(state->parts)); @@ -416,7 +420,6 @@ void register_disk(struct gendisk *disk) int err; disk->dev.parent = disk->driverfs_dev; - disk->dev.devt = MKDEV(disk->major, disk->first_minor); strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); /* ewww... some of these buggers have / in the name... */ @@ -440,7 +443,7 @@ void register_disk(struct gendisk *disk) disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ - if (disk->minors == 1) + if (!disk_max_parts(disk)) goto exit; /* No such device (e.g., media were just removed) */ @@ -463,8 +466,8 @@ exit: kobject_uevent(&disk->dev.kobj, KOBJ_ADD); /* announce possible partitions */ - for (i = 1; i < disk->minors; i++) { - p = disk->part[i-1]; + for (i = 0; i < disk_max_parts(disk); i++) { + p = disk->part[i]; if (!p || !p->nr_sects) continue; kobject_uevent(&p->dev.kobj, KOBJ_ADD); @@ -482,7 +485,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (res) return res; bdev->bd_invalidated = 0; - for (p = 1; p < disk->minors; p++) + for (p = 1; p <= disk_max_parts(disk); p++) delete_partition(disk, p); if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); @@ -545,7 +548,7 @@ void del_gendisk(struct gendisk *disk) int p; /* invalidate stuff */ - for (p = disk->minors - 1; p > 0; p--) { + for (p = disk_max_parts(disk); p > 0; p--) { invalidate_partition(disk, p); delete_partition(disk, p); } diff --git a/include/linux/genhd.h b/include/linux/genhd.h index d1723c0a860..0ff75329199 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -111,10 +111,14 @@ struct hd_struct { #define GENHD_FL_FAIL 64 struct gendisk { + /* major, first_minor and minors are input parameters only, + * don't use directly. Use disk_devt() and disk_max_parts(). + */ int major; /* major number of driver */ int first_minor; int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ + char disk_name[32]; /* name of major driver */ struct hd_struct **part; /* [indexed by minor - 1] */ struct block_device_operations *fops; @@ -152,6 +156,21 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) return NULL; } +static inline int disk_max_parts(struct gendisk *disk) +{ + return disk->minors - 1; +} + +static inline dev_t disk_devt(struct gendisk *disk) +{ + return disk->dev.devt; +} + +static inline dev_t part_devt(struct hd_struct *part) +{ + return part->dev.devt; +} + /* * Macros to operate on percpu disk statistics: * @@ -163,7 +182,7 @@ static inline struct hd_struct *disk_map_sector(struct gendisk *gendiskp, { struct hd_struct *part; int i; - for (i = 0; i < gendiskp->minors - 1; i++) { + for (i = 0; i < disk_max_parts(gendiskp); i++) { part = gendiskp->part[i]; if (part && part->start_sect <= sector && sector < part->start_sect + part->nr_sects) @@ -366,6 +385,7 @@ extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(dev_t dev, int *partno); +extern struct block_device *bdget_disk(struct gendisk *disk, int partno); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); @@ -553,11 +573,6 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data); extern void blk_unregister_region(dev_t devt, unsigned long range); -static inline struct block_device *bdget_disk(struct gendisk *disk, int partno) -{ - return bdget(MKDEV(disk->major, disk->first_minor) + partno); -} - #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } -- GitLab From e71bf0d0ee89e51b92776391c5634938236977d5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 09:03:02 +0200 Subject: [PATCH 3415/5416] block: fix disk->part[] dereferencing race disk->part[] is protected by its matching bdev's lock. However, non-critical accesses like collecting stats and printing out sysfs and proc information used to be performed without any locking. As partitions can come and go dynamically, partitions can go away underneath those non-critical accesses. As some of those accesses are writes, this theoretically can lead to silent corruption. This patch fixes the race by using RCU for the partition array and dev reference counter to hold partitions. * Rename disk->part[] to disk->__part[] to make sure no one outside genhd layer proper accesses it directly. * Use RCU for disk->__part[] dereferencing. * Implement disk_{get|put}_part() which can be used to get and put partitions from gendisk respectively. * Iterators are implemented to help iterate through all partitions safely. * Functions which require RCU readlock are marked with _rcu suffix. * Use disk_put_part() in __blkdev_put() instead of directly putting the contained kobject. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 20 +++- block/blk-merge.c | 9 +- block/genhd.c | 218 +++++++++++++++++++++++++++++++------ block/ioctl.c | 26 +++-- drivers/block/aoe/aoecmd.c | 6 +- fs/block_dev.c | 15 +-- fs/partitions/check.c | 70 +++++++----- include/linux/genhd.h | 53 ++++++--- 8 files changed, 323 insertions(+), 94 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index a0dc2e72fcb..d6128d9ad60 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -60,7 +60,9 @@ static void drive_stat_acct(struct request *rq, int new_io) if (!blk_fs_request(rq) || !rq->rq_disk) return; - part = disk_map_sector(rq->rq_disk, rq->sector); + rcu_read_lock(); + + part = disk_map_sector_rcu(rq->rq_disk, rq->sector); if (!new_io) __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector); else { @@ -71,6 +73,8 @@ static void drive_stat_acct(struct request *rq, int new_io) part->in_flight++; } } + + rcu_read_unlock(); } void blk_queue_congestion_threshold(struct request_queue *q) @@ -1557,12 +1561,14 @@ static int __end_that_request_first(struct request *req, int error, } if (blk_fs_request(req) && req->rq_disk) { - struct hd_struct *part = - disk_map_sector(req->rq_disk, req->sector); const int rw = rq_data_dir(req); + struct hd_struct *part; + rcu_read_lock(); + part = disk_map_sector_rcu(req->rq_disk, req->sector); all_stat_add(req->rq_disk, part, sectors[rw], nr_bytes >> 9, req->sector); + rcu_read_unlock(); } total_bytes = bio_nbytes = 0; @@ -1746,7 +1752,11 @@ static void end_that_request_last(struct request *req, int error) if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); - struct hd_struct *part = disk_map_sector(disk, req->sector); + struct hd_struct *part; + + rcu_read_lock(); + + part = disk_map_sector_rcu(disk, req->sector); __all_stat_inc(disk, part, ios[rw], req->sector); __all_stat_add(disk, part, ticks[rw], duration, req->sector); @@ -1756,6 +1766,8 @@ static void end_that_request_last(struct request *req, int error) part_round_stats(part); part->in_flight--; } + + rcu_read_unlock(); } if (req->end_io) diff --git a/block/blk-merge.c b/block/blk-merge.c index 9b17da698d7..eb2a3ca5830 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -387,14 +387,19 @@ static int attempt_merge(struct request_queue *q, struct request *req, elv_merge_requests(q, req, next); if (req->rq_disk) { - struct hd_struct *part = - disk_map_sector(req->rq_disk, req->sector); + struct hd_struct *part; + + rcu_read_lock(); + + part = disk_map_sector_rcu(req->rq_disk, req->sector); disk_round_stats(req->rq_disk); req->rq_disk->in_flight--; if (part) { part_round_stats(part); part->in_flight--; } + + rcu_read_unlock(); } req->ioprio = ioprio_best(req->ioprio, next->ioprio); diff --git a/block/genhd.c b/block/genhd.c index fa32d09fda2..b431d654394 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -26,6 +26,158 @@ struct kobject *block_depr; static struct device_type disk_type; +/** + * disk_get_part - get partition + * @disk: disk to look partition from + * @partno: partition number + * + * Look for partition @partno from @disk. If found, increment + * reference count and return it. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * Pointer to the found partition on success, NULL if not found. + */ +struct hd_struct *disk_get_part(struct gendisk *disk, int partno) +{ + struct hd_struct *part; + + if (unlikely(partno < 1 || partno > disk_max_parts(disk))) + return NULL; + rcu_read_lock(); + part = rcu_dereference(disk->__part[partno - 1]); + if (part) + get_device(&part->dev); + rcu_read_unlock(); + + return part; +} +EXPORT_SYMBOL_GPL(disk_get_part); + +/** + * disk_part_iter_init - initialize partition iterator + * @piter: iterator to initialize + * @disk: disk to iterate over + * @flags: DISK_PITER_* flags + * + * Initialize @piter so that it iterates over partitions of @disk. + * + * CONTEXT: + * Don't care. + */ +void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, + unsigned int flags) +{ + piter->disk = disk; + piter->part = NULL; + + if (flags & DISK_PITER_REVERSE) + piter->idx = disk_max_parts(piter->disk) - 1; + else + piter->idx = 0; + + piter->flags = flags; +} +EXPORT_SYMBOL_GPL(disk_part_iter_init); + +/** + * disk_part_iter_next - proceed iterator to the next partition and return it + * @piter: iterator of interest + * + * Proceed @piter to the next partition and return it. + * + * CONTEXT: + * Don't care. + */ +struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) +{ + int inc, end; + + /* put the last partition */ + disk_put_part(piter->part); + piter->part = NULL; + + rcu_read_lock(); + + /* determine iteration parameters */ + if (piter->flags & DISK_PITER_REVERSE) { + inc = -1; + end = -1; + } else { + inc = 1; + end = disk_max_parts(piter->disk); + } + + /* iterate to the next partition */ + for (; piter->idx != end; piter->idx += inc) { + struct hd_struct *part; + + part = rcu_dereference(piter->disk->__part[piter->idx]); + if (!part) + continue; + if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) + continue; + + get_device(&part->dev); + piter->part = part; + piter->idx += inc; + break; + } + + rcu_read_unlock(); + + return piter->part; +} +EXPORT_SYMBOL_GPL(disk_part_iter_next); + +/** + * disk_part_iter_exit - finish up partition iteration + * @piter: iter of interest + * + * Called when iteration is over. Cleans up @piter. + * + * CONTEXT: + * Don't care. + */ +void disk_part_iter_exit(struct disk_part_iter *piter) +{ + disk_put_part(piter->part); + piter->part = NULL; +} +EXPORT_SYMBOL_GPL(disk_part_iter_exit); + +/** + * disk_map_sector_rcu - map sector to partition + * @disk: gendisk of interest + * @sector: sector to map + * + * Find out which partition @sector maps to on @disk. This is + * primarily used for stats accounting. + * + * CONTEXT: + * RCU read locked. The returned partition pointer is valid only + * while preemption is disabled. + * + * RETURNS: + * Found partition on success, NULL if there's no matching partition. + */ +struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) +{ + int i; + + for (i = 0; i < disk_max_parts(disk); i++) { + struct hd_struct *part = rcu_dereference(disk->__part[i]); + + if (part && part->start_sect <= sector && + sector < part->start_sect + part->nr_sects) + return part; + } + return NULL; +} +EXPORT_SYMBOL_GPL(disk_map_sector_rcu); + /* * Can be deleted altogether. Later. * @@ -245,10 +397,12 @@ extern struct block_device *bdget_disk(struct gendisk *disk, int partno) if (partno == 0) devt = disk_devt(disk); else { - struct hd_struct *part = disk->part[partno - 1]; + struct hd_struct *part; + part = disk_get_part(disk, partno); if (part && part->nr_sects) devt = part_devt(part); + disk_put_part(part); } if (likely(devt != MKDEV(0, 0))) @@ -270,8 +424,9 @@ void __init printk_all_partitions(void) class_dev_iter_init(&iter, &block_class, NULL, &disk_type); while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); + struct disk_part_iter piter; + struct hd_struct *part; char buf[BDEVNAME_SIZE]; - int n; /* * Don't show empty devices or things that have been @@ -298,16 +453,13 @@ void __init printk_all_partitions(void) printk(" (driver?)\n"); /* now show the partitions */ - for (n = 0; n < disk_max_parts(disk); ++n) { - struct hd_struct *part = disk->part[n]; - - if (!part || !part->nr_sects) - continue; + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) printk(" %02x%02x %10llu %s\n", MAJOR(part_devt(part)), MINOR(part_devt(part)), (unsigned long long)part->nr_sects >> 1, disk_name(disk, part->partno, buf)); - } + disk_part_iter_exit(&piter); } class_dev_iter_exit(&iter); } @@ -371,7 +523,8 @@ static void *show_partition_start(struct seq_file *seqf, loff_t *pos) static int show_partition(struct seq_file *seqf, void *v) { struct gendisk *sgp = v; - int n; + struct disk_part_iter piter; + struct hd_struct *part; char buf[BDEVNAME_SIZE]; /* Don't show non-partitionable removeable devices or empty devices */ @@ -386,17 +539,14 @@ static int show_partition(struct seq_file *seqf, void *v) MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)), (unsigned long long)get_capacity(sgp) >> 1, disk_name(sgp, 0, buf)); - for (n = 0; n < disk_max_parts(sgp); n++) { - struct hd_struct *part = sgp->part[n]; - if (!part) - continue; - if (part->nr_sects == 0) - continue; + + disk_part_iter_init(&piter, sgp, 0); + while ((part = disk_part_iter_next(&piter))) seq_printf(seqf, "%4d %4d %10llu %s\n", MAJOR(part_devt(part)), MINOR(part_devt(part)), (unsigned long long)part->nr_sects >> 1, disk_name(sgp, part->partno, buf)); - } + disk_part_iter_exit(&piter); return 0; } @@ -571,7 +721,7 @@ static void disk_release(struct device *dev) struct gendisk *disk = dev_to_disk(dev); kfree(disk->random); - kfree(disk->part); + kfree(disk->__part); free_disk_stats(disk); kfree(disk); } @@ -596,8 +746,9 @@ static struct device_type disk_type = { static int diskstats_show(struct seq_file *seqf, void *v) { struct gendisk *gp = v; + struct disk_part_iter piter; + struct hd_struct *hd; char buf[BDEVNAME_SIZE]; - int n; /* if (&gp->dev.kobj.entry == block_class.devices.next) @@ -624,12 +775,8 @@ static int diskstats_show(struct seq_file *seqf, void *v) jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); /* now show all non-0 size partitions of it */ - for (n = 0; n < disk_max_parts(gp); n++) { - struct hd_struct *hd = gp->part[n]; - - if (!hd || !hd->nr_sects) - continue; - + disk_part_iter_init(&piter, gp, 0); + while ((hd = disk_part_iter_next(&piter))) { preempt_disable(); part_round_stats(hd); preempt_enable(); @@ -650,6 +797,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) jiffies_to_msecs(part_stat_read(hd, time_in_queue)) ); } + disk_part_iter_exit(&piter); return 0; } @@ -703,12 +851,16 @@ dev_t blk_lookup_devt(const char *name, int partno) if (partno == 0) devt = disk_devt(disk); else { - struct hd_struct *part = disk->part[partno - 1]; + struct hd_struct *part; - if (!part || !part->nr_sects) + part = disk_get_part(disk, partno); + if (!part || !part->nr_sects) { + disk_put_part(part); continue; + } devt = part_devt(part); + disk_put_part(part); } break; } @@ -735,9 +887,9 @@ struct gendisk *alloc_disk_node(int minors, int node_id) } if (minors > 1) { int size = (minors - 1) * sizeof(struct hd_struct *); - disk->part = kmalloc_node(size, + disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, node_id); - if (!disk->part) { + if (!disk->__part) { free_disk_stats(disk); kfree(disk); return NULL; @@ -798,10 +950,14 @@ EXPORT_SYMBOL(set_device_ro); void set_disk_ro(struct gendisk *disk, int flag) { - int i; + struct disk_part_iter piter; + struct hd_struct *part; + disk->policy = flag; - for (i = 0; i < disk_max_parts(disk); i++) - if (disk->part[i]) disk->part[i]->policy = flag; + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) + part->policy = flag; + disk_part_iter_exit(&piter); } EXPORT_SYMBOL(set_disk_ro); diff --git a/block/ioctl.c b/block/ioctl.c index 403f7d7e0c2..a5f672ad55f 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -12,11 +12,12 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user { struct block_device *bdevp; struct gendisk *disk; + struct hd_struct *part; struct blkpg_ioctl_arg a; struct blkpg_partition p; + struct disk_part_iter piter; long long start, length; int partno; - int i; int err; if (!capable(CAP_SYS_ADMIN)) @@ -47,28 +48,33 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user mutex_lock(&bdev->bd_mutex); /* overlap? */ - for (i = 0; i < disk_max_parts(disk); i++) { - struct hd_struct *s = disk->part[i]; - - if (!s) - continue; - if (!(start+length <= s->start_sect || - start >= s->start_sect + s->nr_sects)) { + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) { + if (!(start + length <= part->start_sect || + start >= part->start_sect + part->nr_sects)) { + disk_part_iter_exit(&piter); mutex_unlock(&bdev->bd_mutex); return -EBUSY; } } + disk_part_iter_exit(&piter); + /* all seems OK */ err = add_partition(disk, partno, start, length, ADDPART_FLAG_NONE); mutex_unlock(&bdev->bd_mutex); return err; case BLKPG_DEL_PARTITION: - if (!disk->part[partno - 1]) + part = disk_get_part(disk, partno); + if (!part) return -ENXIO; - bdevp = bdget_disk(disk, partno); + + bdevp = bdget(part_devt(part)); + disk_put_part(part); if (!bdevp) return -ENOMEM; + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { mutex_unlock(&bdevp->bd_mutex); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 885d1409521..84c03d65dcc 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -757,11 +757,15 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector const int rw = bio_data_dir(bio); struct hd_struct *part; - part = disk_map_sector(disk, sector); + rcu_read_lock(); + + part = disk_map_sector_rcu(disk, sector); all_stat_inc(disk, part, ios[rw], sector); all_stat_add(disk, part, ticks[rw], duration, sector); all_stat_add(disk, part, sectors[rw], n_sect, sector); all_stat_add(disk, part, io_ticks, duration, sector); + + rcu_read_unlock(); } void diff --git a/fs/block_dev.c b/fs/block_dev.c index 72e0a2887cb..2f2873b9a04 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -929,6 +929,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) { struct module *owner = NULL; struct gendisk *disk; + struct hd_struct *part = NULL; int ret; int partno; int perm = 0; @@ -978,7 +979,6 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) if (bdev->bd_invalidated) rescan_partitions(disk, bdev); } else { - struct hd_struct *p; struct block_device *whole; whole = bdget_disk(disk, 0); ret = -ENOMEM; @@ -989,16 +989,16 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) if (ret) goto out_first; bdev->bd_contains = whole; - p = disk->part[partno - 1]; + part = disk_get_part(disk, partno); bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; - if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { + if (!(disk->flags & GENHD_FL_UP) || + !part || !part->nr_sects) { ret = -ENXIO; goto out_first; } - kobject_get(&p->dev.kobj); - bdev->bd_part = p; - bd_set_size(bdev, (loff_t) p->nr_sects << 9); + bdev->bd_part = part; + bd_set_size(bdev, (loff_t)part->nr_sects << 9); } } else { put_disk(disk); @@ -1027,6 +1027,7 @@ out_first: __blkdev_put(bdev->bd_contains, 1); bdev->bd_contains = NULL; put_disk(disk); + disk_put_part(part); module_put(owner); out: mutex_unlock(&bdev->bd_mutex); @@ -1119,7 +1120,7 @@ static int __blkdev_put(struct block_device *bdev, int for_part) module_put(owner); if (bdev->bd_contains != bdev) { - kobject_put(&bdev->bd_part->dev.kobj); + disk_put_part(bdev->bd_part); bdev->bd_part = NULL; } bdev->bd_disk = NULL; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index e77fa144a07..96c8bf41e45 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -314,19 +314,29 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk) kobject_put(k); } +static void delete_partition_rcu_cb(struct rcu_head *head) +{ + struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); + + part->start_sect = 0; + part->nr_sects = 0; + part_stat_set_all(part, 0); + put_device(&part->dev); +} + void delete_partition(struct gendisk *disk, int partno) { - struct hd_struct *p = disk->part[partno - 1]; + struct hd_struct *part; - if (!p) + part = disk->__part[partno-1]; + if (!part) return; - disk->part[partno - 1] = NULL; - p->start_sect = 0; - p->nr_sects = 0; - part_stat_set_all(p, 0); - kobject_put(p->holder_dir); - device_del(&p->dev); - put_device(&p->dev); + + rcu_assign_pointer(disk->__part[partno-1], NULL); + kobject_put(part->holder_dir); + device_del(&part->dev); + + call_rcu(&part->rcu_head, delete_partition_rcu_cb); } static ssize_t whole_disk_show(struct device *dev, @@ -343,7 +353,7 @@ int add_partition(struct gendisk *disk, int partno, struct hd_struct *p; int err; - if (disk->part[partno - 1]) + if (disk->__part[partno - 1]) return -EBUSY; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -391,7 +401,8 @@ int add_partition(struct gendisk *disk, int partno, } /* everything is up and running, commence */ - disk->part[partno - 1] = p; + INIT_RCU_HEAD(&p->rcu_head); + rcu_assign_pointer(disk->__part[partno - 1], p); /* suppress uevent if the disk supresses it */ if (!disk->dev.uevent_suppress) @@ -414,9 +425,9 @@ out_put: void register_disk(struct gendisk *disk) { struct block_device *bdev; + struct disk_part_iter piter; + struct hd_struct *part; char *s; - int i; - struct hd_struct *p; int err; disk->dev.parent = disk->driverfs_dev; @@ -466,16 +477,16 @@ exit: kobject_uevent(&disk->dev.kobj, KOBJ_ADD); /* announce possible partitions */ - for (i = 0; i < disk_max_parts(disk); i++) { - p = disk->part[i]; - if (!p || !p->nr_sects) - continue; - kobject_uevent(&p->dev.kobj, KOBJ_ADD); - } + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) + kobject_uevent(&part->dev.kobj, KOBJ_ADD); + disk_part_iter_exit(&piter); } int rescan_partitions(struct gendisk *disk, struct block_device *bdev) { + struct disk_part_iter piter; + struct hd_struct *part; struct parsed_partitions *state; int p, res; @@ -485,8 +496,12 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (res) return res; bdev->bd_invalidated = 0; - for (p = 1; p <= disk_max_parts(disk); p++) - delete_partition(disk, p); + + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) + delete_partition(disk, part->partno); + disk_part_iter_exit(&piter); + if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) @@ -545,13 +560,18 @@ EXPORT_SYMBOL(read_dev_sector); void del_gendisk(struct gendisk *disk) { - int p; + struct disk_part_iter piter; + struct hd_struct *part; /* invalidate stuff */ - for (p = disk_max_parts(disk); p > 0; p--) { - invalidate_partition(disk, p); - delete_partition(disk, p); + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE); + while ((part = disk_part_iter_next(&piter))) { + invalidate_partition(disk, part->partno); + delete_partition(disk, part->partno); } + disk_part_iter_exit(&piter); + invalidate_partition(disk, 0); disk->capacity = 0; disk->flags &= ~GENHD_FL_UP; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 0ff75329199..7fbba19e076 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -11,6 +11,7 @@ #include #include +#include #ifdef CONFIG_BLOCK @@ -100,6 +101,7 @@ struct hd_struct { #else struct disk_stats dkstats; #endif + struct rcu_head rcu_head; }; #define GENHD_FL_REMOVABLE 1 @@ -120,7 +122,14 @@ struct gendisk { * disks that can't be partitioned. */ char disk_name[32]; /* name of major driver */ - struct hd_struct **part; /* [indexed by minor - 1] */ + + /* Array of pointers to partitions indexed by partno - 1. + * Protected with matching bdev lock but stat and other + * non-critical accesses use RCU. Always access through + * helpers. + */ + struct hd_struct **__part; + struct block_device_operations *fops; struct request_queue *queue; void *private_data; @@ -171,25 +180,41 @@ static inline dev_t part_devt(struct hd_struct *part) return part->dev.devt; } +extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno); + +static inline void disk_put_part(struct hd_struct *part) +{ + if (likely(part)) + put_device(&part->dev); +} + +/* + * Smarter partition iterator without context limits. + */ +#define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ +#define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ + +struct disk_part_iter { + struct gendisk *disk; + struct hd_struct *part; + int idx; + unsigned int flags; +}; + +extern void disk_part_iter_init(struct disk_part_iter *piter, + struct gendisk *disk, unsigned int flags); +extern struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter); +extern void disk_part_iter_exit(struct disk_part_iter *piter); + +extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, + sector_t sector); + /* * Macros to operate on percpu disk statistics: * * The __ variants should only be called in critical sections. The full * variants disable/enable preemption. */ -static inline struct hd_struct *disk_map_sector(struct gendisk *gendiskp, - sector_t sector) -{ - struct hd_struct *part; - int i; - for (i = 0; i < disk_max_parts(gendiskp); i++) { - part = gendiskp->part[i]; - if (part && part->start_sect <= sector - && sector < part->start_sect + part->nr_sects) - return part; - } - return NULL; -} #ifdef CONFIG_SMP #define __disk_stat_add(gendiskp, field, addnd) \ -- GitLab From c9959059161ddd7bf4670cf47367033d6b2f79c4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:21 +0900 Subject: [PATCH 3416/5416] block: fix diskstats access There are two variants of stat functions - ones prefixed with double underbars which don't care about preemption and ones without which disable preemption before manipulating per-cpu counters. It's unclear whether the underbarred ones assume that preemtion is disabled on entry as some callers don't do that. This patch unifies diskstats access by implementing disk_stat_lock() and disk_stat_unlock() which take care of both RCU (for partition access) and preemption (for per-cpu counter access). diskstats access should always be enclosed between the two functions. As such, there's no need for the versions which disables preemption. They're removed and double underbars ones are renamed to drop the underbars. As an extra argument is added, there's no danger of using the old version unconverted. disk_stat_lock() uses get_cpu() and returns the cpu index and all diskstat functions which access per-cpu counters now has @cpu argument to help RT. This change adds RCU or preemption operations at some places but also collapses several preemption ops into one at others. Overall, the performance difference should be negligible as all involved ops are very lightweight per-cpu ones. Signed-off-by: Tejun Heo Cc: Peter Zijlstra Signed-off-by: Jens Axboe --- block/blk-core.c | 52 +++++++------- block/blk-merge.c | 11 +-- block/genhd.c | 20 +++--- drivers/block/aoe/aoecmd.c | 15 ++-- drivers/md/dm.c | 26 ++++--- drivers/md/linear.c | 7 +- drivers/md/multipath.c | 7 +- drivers/md/raid0.c | 7 +- drivers/md/raid1.c | 8 ++- drivers/md/raid10.c | 7 +- drivers/md/raid5.c | 8 ++- fs/partitions/check.c | 7 +- include/linux/genhd.h | 139 +++++++++++++++---------------------- 13 files changed, 158 insertions(+), 156 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index d6128d9ad60..e0a5ee36849 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -56,25 +56,26 @@ static void drive_stat_acct(struct request *rq, int new_io) { struct hd_struct *part; int rw = rq_data_dir(rq); + int cpu; if (!blk_fs_request(rq) || !rq->rq_disk) return; - rcu_read_lock(); - + cpu = disk_stat_lock(); part = disk_map_sector_rcu(rq->rq_disk, rq->sector); + if (!new_io) - __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector); + all_stat_inc(cpu, rq->rq_disk, part, merges[rw], rq->sector); else { - disk_round_stats(rq->rq_disk); + disk_round_stats(cpu, rq->rq_disk); rq->rq_disk->in_flight++; if (part) { - part_round_stats(part); + part_round_stats(cpu, part); part->in_flight++; } } - rcu_read_unlock(); + disk_stat_unlock(); } void blk_queue_congestion_threshold(struct request_queue *q) @@ -997,7 +998,7 @@ static inline void add_request(struct request_queue *q, struct request *req) * /proc/diskstats. This accounts immediately for all queue usage up to * the current jiffies and restarts the counters again. */ -void disk_round_stats(struct gendisk *disk) +void disk_round_stats(int cpu, struct gendisk *disk) { unsigned long now = jiffies; @@ -1005,15 +1006,15 @@ void disk_round_stats(struct gendisk *disk) return; if (disk->in_flight) { - __disk_stat_add(disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); - __disk_stat_add(disk, io_ticks, (now - disk->stamp)); + disk_stat_add(cpu, disk, time_in_queue, + disk->in_flight * (now - disk->stamp)); + disk_stat_add(cpu, disk, io_ticks, (now - disk->stamp)); } disk->stamp = now; } EXPORT_SYMBOL_GPL(disk_round_stats); -void part_round_stats(struct hd_struct *part) +void part_round_stats(int cpu, struct hd_struct *part) { unsigned long now = jiffies; @@ -1021,9 +1022,9 @@ void part_round_stats(struct hd_struct *part) return; if (part->in_flight) { - __part_stat_add(part, time_in_queue, - part->in_flight * (now - part->stamp)); - __part_stat_add(part, io_ticks, (now - part->stamp)); + part_stat_add(cpu, part, time_in_queue, + part->in_flight * (now - part->stamp)); + part_stat_add(cpu, part, io_ticks, (now - part->stamp)); } part->stamp = now; } @@ -1563,12 +1564,13 @@ static int __end_that_request_first(struct request *req, int error, if (blk_fs_request(req) && req->rq_disk) { const int rw = rq_data_dir(req); struct hd_struct *part; + int cpu; - rcu_read_lock(); + cpu = disk_stat_lock(); part = disk_map_sector_rcu(req->rq_disk, req->sector); - all_stat_add(req->rq_disk, part, sectors[rw], - nr_bytes >> 9, req->sector); - rcu_read_unlock(); + all_stat_add(cpu, req->rq_disk, part, sectors[rw], + nr_bytes >> 9, req->sector); + disk_stat_unlock(); } total_bytes = bio_nbytes = 0; @@ -1753,21 +1755,21 @@ static void end_that_request_last(struct request *req, int error) unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); struct hd_struct *part; + int cpu; - rcu_read_lock(); - + cpu = disk_stat_lock(); part = disk_map_sector_rcu(disk, req->sector); - __all_stat_inc(disk, part, ios[rw], req->sector); - __all_stat_add(disk, part, ticks[rw], duration, req->sector); - disk_round_stats(disk); + all_stat_inc(cpu, disk, part, ios[rw], req->sector); + all_stat_add(cpu, disk, part, ticks[rw], duration, req->sector); + disk_round_stats(cpu, disk); disk->in_flight--; if (part) { - part_round_stats(part); + part_round_stats(cpu, part); part->in_flight--; } - rcu_read_unlock(); + disk_stat_unlock(); } if (req->end_io) diff --git a/block/blk-merge.c b/block/blk-merge.c index eb2a3ca5830..d926a24bf1f 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -388,18 +388,19 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (req->rq_disk) { struct hd_struct *part; + int cpu; - rcu_read_lock(); - + cpu = disk_stat_lock(); part = disk_map_sector_rcu(req->rq_disk, req->sector); - disk_round_stats(req->rq_disk); + + disk_round_stats(cpu, req->rq_disk); req->rq_disk->in_flight--; if (part) { - part_round_stats(part); + part_round_stats(cpu, part); part->in_flight--; } - rcu_read_unlock(); + disk_stat_unlock(); } req->ioprio = ioprio_best(req->ioprio, next->ioprio); diff --git a/block/genhd.c b/block/genhd.c index b431d654394..430626e440f 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -633,10 +633,11 @@ static ssize_t disk_stat_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gendisk *disk = dev_to_disk(dev); + int cpu; - preempt_disable(); - disk_round_stats(disk); - preempt_enable(); + cpu = disk_stat_lock(); + disk_round_stats(cpu, disk); + disk_stat_unlock(); return sprintf(buf, "%8lu %8lu %8llu %8u " "%8lu %8lu %8llu %8u " @@ -749,6 +750,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) struct disk_part_iter piter; struct hd_struct *hd; char buf[BDEVNAME_SIZE]; + int cpu; /* if (&gp->dev.kobj.entry == block_class.devices.next) @@ -758,9 +760,9 @@ static int diskstats_show(struct seq_file *seqf, void *v) "\n\n"); */ - preempt_disable(); - disk_round_stats(gp); - preempt_enable(); + cpu = disk_stat_lock(); + disk_round_stats(cpu, gp); + disk_stat_unlock(); seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), disk_name(gp, 0, buf), @@ -777,9 +779,9 @@ static int diskstats_show(struct seq_file *seqf, void *v) /* now show all non-0 size partitions of it */ disk_part_iter_init(&piter, gp, 0); while ((hd = disk_part_iter_next(&piter))) { - preempt_disable(); - part_round_stats(hd); - preempt_enable(); + cpu = disk_stat_lock(); + part_round_stats(cpu, hd); + disk_stat_unlock(); seq_printf(seqf, "%4d %4d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", MAJOR(part_devt(hd)), MINOR(part_devt(hd)), diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 84c03d65dcc..17eed8c025d 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -756,16 +756,17 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector unsigned long n_sect = bio->bi_size >> 9; const int rw = bio_data_dir(bio); struct hd_struct *part; + int cpu; - rcu_read_lock(); - + cpu = disk_stat_lock(); part = disk_map_sector_rcu(disk, sector); - all_stat_inc(disk, part, ios[rw], sector); - all_stat_add(disk, part, ticks[rw], duration, sector); - all_stat_add(disk, part, sectors[rw], n_sect, sector); - all_stat_add(disk, part, io_ticks, duration, sector); - rcu_read_unlock(); + all_stat_inc(cpu, disk, part, ios[rw], sector); + all_stat_add(cpu, disk, part, ticks[rw], duration, sector); + all_stat_add(cpu, disk, part, sectors[rw], n_sect, sector); + all_stat_add(cpu, disk, part, io_ticks, duration, sector); + + disk_stat_unlock(); } void diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a78caad2999..653624792ea 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -377,12 +377,13 @@ static void free_tio(struct mapped_device *md, struct dm_target_io *tio) static void start_io_acct(struct dm_io *io) { struct mapped_device *md = io->md; + int cpu; io->start_time = jiffies; - preempt_disable(); - disk_round_stats(dm_disk(md)); - preempt_enable(); + cpu = disk_stat_lock(); + disk_round_stats(cpu, dm_disk(md)); + disk_stat_unlock(); dm_disk(md)->in_flight = atomic_inc_return(&md->pending); } @@ -391,15 +392,15 @@ static int end_io_acct(struct dm_io *io) struct mapped_device *md = io->md; struct bio *bio = io->bio; unsigned long duration = jiffies - io->start_time; - int pending; + int pending, cpu; int rw = bio_data_dir(bio); - preempt_disable(); - disk_round_stats(dm_disk(md)); - preempt_enable(); - dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + cpu = disk_stat_lock(); + disk_round_stats(cpu, dm_disk(md)); + disk_stat_add(cpu, dm_disk(md), ticks[rw], duration); + disk_stat_unlock(); - disk_stat_add(dm_disk(md), ticks[rw], duration); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); return !pending; } @@ -885,6 +886,7 @@ static int dm_request(struct request_queue *q, struct bio *bio) int r = -EIO; int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; + int cpu; /* * There is no use in forwarding any barrier request since we can't @@ -897,8 +899,10 @@ static int dm_request(struct request_queue *q, struct bio *bio) down_read(&md->io_lock); - disk_stat_inc(dm_disk(md), ios[rw]); - disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, dm_disk(md), ios[rw]); + disk_stat_add(cpu, dm_disk(md), sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); /* * If we're suspended we have to queue diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b1eebf88c20..00cbc8e4729 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -318,14 +318,17 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) mddev_t *mddev = q->queuedata; dev_info_t *tmp_dev; sector_t block; + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); return 0; } - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); tmp_dev = which_dev(mddev, bio->bi_sector); block = bio->bi_sector >> 1; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index c4779ccba1c..182f5a94cdc 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -147,6 +147,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) struct multipath_bh * mp_bh; struct multipath_info *multipath; const int rw = bio_data_dir(bio); + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); @@ -158,8 +159,10 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->master_bio = bio; mp_bh->mddev = mddev; - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 18361063566..e26030fa59a 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -399,14 +399,17 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) sector_t chunk; sector_t block, rsect; const int rw = bio_data_dir(bio); + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); return 0; } - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); chunk_size = mddev->chunk_size >> 10; chunk_sects = mddev->chunk_size >> 9; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 0b82030c265..babb13036f9 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -779,7 +779,7 @@ static int make_request(struct request_queue *q, struct bio * bio) struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); const int do_sync = bio_sync(bio); - int do_barriers; + int cpu, do_barriers; mdk_rdev_t *blocked_rdev; /* @@ -804,8 +804,10 @@ static int make_request(struct request_queue *q, struct bio * bio) bitmap = mddev->bitmap; - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); /* * make_request() can abort the operation when READA is being diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d3b9aa09628..5ec80da0a9d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -789,6 +789,7 @@ static int make_request(struct request_queue *q, struct bio * bio) mirror_info_t *mirror; r10bio_t *r10_bio; struct bio *read_bio; + int cpu; int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); @@ -843,8 +844,10 @@ static int make_request(struct request_queue *q, struct bio * bio) */ wait_barrier(conf); - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); + disk_stat_unlock(); r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 37e546528f9..5899f211515 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3387,7 +3387,7 @@ static int make_request(struct request_queue *q, struct bio * bi) sector_t logical_sector, last_sector; struct stripe_head *sh; const int rw = bio_data_dir(bi); - int remaining; + int cpu, remaining; if (unlikely(bio_barrier(bi))) { bio_endio(bi, -EOPNOTSUPP); @@ -3396,8 +3396,10 @@ static int make_request(struct request_queue *q, struct bio * bi) md_write_start(mddev, bi); - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); + cpu = disk_stat_lock(); + disk_stat_inc(cpu, mddev->gendisk, ios[rw]); + disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bi)); + disk_stat_unlock(); if (rw == READ && mddev->reshape_position == MaxSector && diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 96c8bf41e45..c442f0aadac 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -219,10 +219,11 @@ static ssize_t part_stat_show(struct device *dev, struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); + int cpu; - preempt_disable(); - part_round_stats(p); - preempt_enable(); + cpu = disk_stat_lock(); + part_round_stats(cpu, p); + disk_stat_unlock(); return sprintf(buf, "%8lu %8lu %8llu %8u " "%8lu %8lu %8llu %8u " diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 7fbba19e076..ac8a901f200 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -209,16 +209,24 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter); extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector); -/* +/* * Macros to operate on percpu disk statistics: * - * The __ variants should only be called in critical sections. The full - * variants disable/enable preemption. + * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters + * and should be called between disk_stat_lock() and + * disk_stat_unlock(). + * + * part_stat_read() can be called at any time. + * + * part_stat_{add|set_all}() and {init|free}_part_stats are for + * internal use only. */ - #ifdef CONFIG_SMP -#define __disk_stat_add(gendiskp, field, addnd) \ - (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) +#define disk_stat_lock() ({ rcu_read_lock(); get_cpu(); }) +#define disk_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0) + +#define disk_stat_add(cpu, gendiskp, field, addnd) \ + (per_cpu_ptr(gendiskp->dkstats, cpu)->field += addnd) #define disk_stat_read(gendiskp, field) \ ({ \ @@ -229,7 +237,8 @@ extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, res; \ }) -static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { +static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) +{ int i; for_each_possible_cpu(i) @@ -237,14 +246,14 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { sizeof(struct disk_stats)); } -#define __part_stat_add(part, field, addnd) \ - (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd) +#define part_stat_add(cpu, part, field, addnd) \ + (per_cpu_ptr(part->dkstats, cpu)->field += addnd) -#define __all_stat_add(gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - __part_stat_add(part, field, addnd); \ - __disk_stat_add(gendiskp, field, addnd); \ +#define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ +({ \ + if (part) \ + part_stat_add(cpu, part, field, addnd); \ + disk_stat_add(cpu, gendiskp, field, addnd); \ }) #define part_stat_read(part, field) \ @@ -264,10 +273,13 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) memset(per_cpu_ptr(part->dkstats, i), value, sizeof(struct disk_stats)); } - + #else /* !CONFIG_SMP */ -#define __disk_stat_add(gendiskp, field, addnd) \ - (gendiskp->dkstats.field += addnd) +#define disk_stat_lock() ({ rcu_read_lock(); 0; }) +#define disk_stat_unlock() rcu_read_unlock() + +#define disk_stat_add(cpu, gendiskp, field, addnd) \ + (gendiskp->dkstats.field += addnd) #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) @@ -275,14 +287,14 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); } -#define __part_stat_add(part, field, addnd) \ +#define part_stat_add(cpu, part, field, addnd) \ (part->dkstats.field += addnd) -#define __all_stat_add(gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - part->dkstats.field += addnd; \ - __disk_stat_add(gendiskp, field, addnd); \ +#define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ +({ \ + if (part) \ + part_stat_add(cpu, part, field, addnd); \ + disk_stat_add(cpu, gendiskp, field, addnd); \ }) #define part_stat_read(part, field) (part->dkstats.field) @@ -294,63 +306,26 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) #endif /* CONFIG_SMP */ -#define disk_stat_add(gendiskp, field, addnd) \ - do { \ - preempt_disable(); \ - __disk_stat_add(gendiskp, field, addnd); \ - preempt_enable(); \ - } while (0) - -#define __disk_stat_dec(gendiskp, field) __disk_stat_add(gendiskp, field, -1) -#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1) - -#define __disk_stat_inc(gendiskp, field) __disk_stat_add(gendiskp, field, 1) -#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1) - -#define __disk_stat_sub(gendiskp, field, subnd) \ - __disk_stat_add(gendiskp, field, -subnd) -#define disk_stat_sub(gendiskp, field, subnd) \ - disk_stat_add(gendiskp, field, -subnd) - -#define part_stat_add(gendiskp, field, addnd) \ - do { \ - preempt_disable(); \ - __part_stat_add(gendiskp, field, addnd);\ - preempt_enable(); \ - } while (0) - -#define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1) -#define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1) - -#define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1) -#define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1) - -#define __part_stat_sub(gendiskp, field, subnd) \ - __part_stat_add(gendiskp, field, -subnd) -#define part_stat_sub(gendiskp, field, subnd) \ - part_stat_add(gendiskp, field, -subnd) - -#define all_stat_add(gendiskp, part, field, addnd, sector) \ - do { \ - preempt_disable(); \ - __all_stat_add(gendiskp, part, field, addnd, sector); \ - preempt_enable(); \ - } while (0) - -#define __all_stat_dec(gendiskp, field, sector) \ - __all_stat_add(gendiskp, field, -1, sector) -#define all_stat_dec(gendiskp, field, sector) \ - all_stat_add(gendiskp, field, -1, sector) - -#define __all_stat_inc(gendiskp, part, field, sector) \ - __all_stat_add(gendiskp, part, field, 1, sector) -#define all_stat_inc(gendiskp, part, field, sector) \ - all_stat_add(gendiskp, part, field, 1, sector) - -#define __all_stat_sub(gendiskp, part, field, subnd, sector) \ - __all_stat_add(gendiskp, part, field, -subnd, sector) -#define all_stat_sub(gendiskp, part, field, subnd, sector) \ - all_stat_add(gendiskp, part, field, -subnd, sector) +#define disk_stat_dec(cpu, gendiskp, field) \ + disk_stat_add(cpu, gendiskp, field, -1) +#define disk_stat_inc(cpu, gendiskp, field) \ + disk_stat_add(cpu, gendiskp, field, 1) +#define disk_stat_sub(cpu, gendiskp, field, subnd) \ + disk_stat_add(cpu, gendiskp, field, -subnd) + +#define part_stat_dec(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, -1) +#define part_stat_inc(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, 1) +#define part_stat_sub(cpu, gendiskp, field, subnd) \ + part_stat_add(cpu, gendiskp, field, -subnd) + +#define all_stat_dec(cpu, gendiskp, field, sector) \ + all_stat_add(cpu, gendiskp, field, -1, sector) +#define all_stat_inc(cpu, gendiskp, part, field, sector) \ + all_stat_add(cpu, gendiskp, part, field, 1, sector) +#define all_stat_sub(cpu, gendiskp, part, field, subnd, sector) \ + all_stat_add(cpu, gendiskp, part, field, -subnd, sector) /* Inlines to alloc and free disk stats in struct gendisk */ #ifdef CONFIG_SMP @@ -401,8 +376,8 @@ static inline void free_part_stats(struct hd_struct *part) #endif /* CONFIG_SMP */ /* drivers/block/ll_rw_blk.c */ -extern void disk_round_stats(struct gendisk *disk); -extern void part_round_stats(struct hd_struct *part); +extern void disk_round_stats(int cpu, struct gendisk *disk); +extern void part_round_stats(int cpu, struct hd_struct *part); /* drivers/block/genhd.c */ extern int get_blkdev_list(char *, int); -- GitLab From bcce3de1be61e424deef35d1e86e86a35c4b6e65 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:22 +0900 Subject: [PATCH 3417/5416] block: implement extended dev numbers Implement extended device numbers. A block driver can tell block layer that it wants to use extended device numbers. After the usual minor space is used up, block layer automatically allocates devt's from EXT_BLOCK_MAJOR. Currently only one major number is allocated for this but as the allocation is strictly on-demand, ~1mil minor space under it should suffice unless the system actually has more than ~1mil partitions and if that ever happens adding more majors to the extended devt area is easy. Due to internal implementation issues, the first partition can't be allocated on the extended area. In other words, genhd->minors should at least be 1. This limitation will be lifted by later changes. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 120 ++++++++++++++++++++++++++++++++++++++++-- fs/partitions/check.c | 9 +++- include/linux/genhd.h | 13 +++-- include/linux/major.h | 2 + 4 files changed, 135 insertions(+), 9 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 430626e440f..7bbfed05cec 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "blk.h" @@ -24,6 +25,15 @@ static DEFINE_MUTEX(block_class_lock); struct kobject *block_depr; #endif +/* for extended dynamic devt allocation, currently only one major is used */ +#define MAX_EXT_DEVT (1 << MINORBITS) + +/* For extended devt allocation. ext_devt_mutex prevents look up + * results from going away underneath its user. + */ +static DEFINE_MUTEX(ext_devt_mutex); +static DEFINE_IDR(ext_devt_idr); + static struct device_type disk_type; /** @@ -288,6 +298,74 @@ EXPORT_SYMBOL(unregister_blkdev); static struct kobj_map *bdev_map; +/** + * blk_alloc_devt - allocate a dev_t for a partition + * @part: partition to allocate dev_t for + * @gfp_mask: memory allocation flag + * @devt: out parameter for resulting dev_t + * + * Allocate a dev_t for block device. + * + * RETURNS: + * 0 on success, allocated dev_t is returned in *@devt. -errno on + * failure. + * + * CONTEXT: + * Might sleep. + */ +int blk_alloc_devt(struct hd_struct *part, dev_t *devt) +{ + struct gendisk *disk = part_to_disk(part); + int idx, rc; + + /* in consecutive minor range? */ + if (part->partno < disk->minors) { + *devt = MKDEV(disk->major, disk->first_minor + part->partno); + return 0; + } + + /* allocate ext devt */ + do { + if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL)) + return -ENOMEM; + rc = idr_get_new(&ext_devt_idr, part, &idx); + } while (rc == -EAGAIN); + + if (rc) + return rc; + + if (idx > MAX_EXT_DEVT) { + idr_remove(&ext_devt_idr, idx); + return -EBUSY; + } + + *devt = MKDEV(BLOCK_EXT_MAJOR, idx); + return 0; +} + +/** + * blk_free_devt - free a dev_t + * @devt: dev_t to free + * + * Free @devt which was allocated using blk_alloc_devt(). + * + * CONTEXT: + * Might sleep. + */ +void blk_free_devt(dev_t devt) +{ + might_sleep(); + + if (devt == MKDEV(0, 0)) + return; + + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { + mutex_lock(&ext_devt_mutex); + idr_remove(&ext_devt_idr, MINOR(devt)); + mutex_unlock(&ext_devt_mutex); + } +} + /* * Register device numbers dev..(dev+range-1) * range must be nonzero @@ -371,10 +449,27 @@ void unlink_gendisk(struct gendisk *disk) */ struct gendisk *get_gendisk(dev_t devt, int *partno) { - struct kobject *kobj = kobj_lookup(bdev_map, devt, partno); - struct device *dev = kobj_to_dev(kobj); + struct gendisk *disk = NULL; + + if (MAJOR(devt) != BLOCK_EXT_MAJOR) { + struct kobject *kobj; + + kobj = kobj_lookup(bdev_map, devt, partno); + if (kobj) + disk = dev_to_disk(kobj_to_dev(kobj)); + } else { + struct hd_struct *part; + + mutex_lock(&ext_devt_mutex); + part = idr_find(&ext_devt_idr, MINOR(devt)); + if (part && get_disk(part_to_disk(part))) { + *partno = part->partno; + disk = part_to_disk(part); + } + mutex_unlock(&ext_devt_mutex); + } - return kobj ? dev_to_disk(dev) : NULL; + return disk; } /** @@ -877,18 +972,30 @@ struct gendisk *alloc_disk(int minors) } struct gendisk *alloc_disk_node(int minors, int node_id) +{ + return alloc_disk_ext_node(minors, 0, node_id); +} + +struct gendisk *alloc_disk_ext(int minors, int ext_minors) +{ + return alloc_disk_ext_node(minors, ext_minors, -1); +} + +struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) { struct gendisk *disk; disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL | __GFP_ZERO, node_id); if (disk) { + int tot_minors = minors + ext_minors; + if (!init_disk_stats(disk)) { kfree(disk); return NULL; } - if (minors > 1) { - int size = (minors - 1) * sizeof(struct hd_struct *); + if (tot_minors > 1) { + int size = (tot_minors - 1) * sizeof(struct hd_struct *); disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, node_id); if (!disk->__part) { @@ -898,6 +1005,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id) } } disk->minors = minors; + disk->ext_minors = ext_minors; rand_initialize_disk(disk); disk->dev.class = &block_class; disk->dev.type = &disk_type; @@ -910,6 +1018,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id) EXPORT_SYMBOL(alloc_disk); EXPORT_SYMBOL(alloc_disk_node); +EXPORT_SYMBOL(alloc_disk_ext); +EXPORT_SYMBOL(alloc_disk_ext_node); struct kobject *get_disk(struct gendisk *disk) { diff --git a/fs/partitions/check.c b/fs/partitions/check.c index c442f0aadac..0d4b7f28f13 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -333,6 +333,7 @@ void delete_partition(struct gendisk *disk, int partno) if (!part) return; + blk_free_devt(part_devt(part)); rcu_assign_pointer(disk->__part[partno-1], NULL); kobject_put(part->holder_dir); device_del(&part->dev); @@ -352,6 +353,7 @@ int add_partition(struct gendisk *disk, int partno, sector_t start, sector_t len, int flags) { struct hd_struct *p; + dev_t devt = MKDEV(0, 0); int err; if (disk->__part[partno - 1]) @@ -378,11 +380,15 @@ int add_partition(struct gendisk *disk, int partno, "%s%d", disk->dev.bus_id, partno); device_initialize(&p->dev); - p->dev.devt = MKDEV(disk->major, disk->first_minor + partno); p->dev.class = &block_class; p->dev.type = &part_type; p->dev.parent = &disk->dev; + err = blk_alloc_devt(p, &devt); + if (err) + goto out_put; + p->dev.devt = devt; + /* delay uevent until 'holders' subdir is created */ p->dev.uevent_suppress = 1; err = device_add(&p->dev); @@ -419,6 +425,7 @@ out_del: device_del(&p->dev); out_put: put_device(&p->dev); + blk_free_devt(devt); return err; } diff --git a/include/linux/genhd.h b/include/linux/genhd.h index ac8a901f200..6fc53242406 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -113,13 +113,15 @@ struct hd_struct { #define GENHD_FL_FAIL 64 struct gendisk { - /* major, first_minor and minors are input parameters only, - * don't use directly. Use disk_devt() and disk_max_parts(). + /* major, first_minor, minors and ext_minors are input + * parameters only, don't use directly. Use disk_devt() and + * disk_max_parts(). */ int major; /* major number of driver */ int first_minor; int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ + int ext_minors; /* number of extended dynamic minors */ char disk_name[32]; /* name of major driver */ @@ -167,7 +169,7 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) static inline int disk_max_parts(struct gendisk *disk) { - return disk->minors - 1; + return disk->minors + disk->ext_minors - 1; } static inline dev_t disk_devt(struct gendisk *disk) @@ -554,6 +556,8 @@ struct unixware_disklabel { #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 +extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt); +extern void blk_free_devt(dev_t devt); extern dev_t blk_lookup_devt(const char *name, int partno); extern char *disk_name (struct gendisk *hd, int partno, char *buf); @@ -564,6 +568,9 @@ extern void printk_all_partitions(void); extern struct gendisk *alloc_disk_node(int minors, int node_id); extern struct gendisk *alloc_disk(int minors); +extern struct gendisk *alloc_disk_ext_node(int minors, int ext_minrs, + int node_id); +extern struct gendisk *alloc_disk_ext(int minors, int ext_minors); extern struct kobject *get_disk(struct gendisk *disk); extern void put_disk(struct gendisk *disk); extern void blk_register_region(dev_t devt, unsigned long range, diff --git a/include/linux/major.h b/include/linux/major.h index 53d5fafd85c..88249452b93 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -170,4 +170,6 @@ #define VIOTAPE_MAJOR 230 +#define BLOCK_EXT_MAJOR 259 + #endif -- GitLab From 1f0142905d4812966831613847db38a66da29eb8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:23 +0900 Subject: [PATCH 3418/5416] block: adjust formatting for large minors and add ext_range sysfs attr With extended minors and the soon-to-follow debug feature, large minor numbers for block devices will be common. This patch does the followings to make printouts pretty. * Adapt print formats such that large minors don't break the formatting. * For extended MAJ:MIN, %02x%02x for MAJ:MIN used in printk_all_partitions() doesn't cut it anymore. Update it such that %03x:%05x is used if either MAJ or MIN doesn't fit in %02x. * Implement ext_range sysfs attribute which shows total minors the device can use including both conventional minor space and the extended one. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 45 ++++++++++++++++++++++++++++++++++----------- include/linux/fs.h | 1 + 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 7bbfed05cec..ee4b13520e5 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -366,6 +366,18 @@ void blk_free_devt(dev_t devt) } } +static char *bdevt_str(dev_t devt, char *buf) +{ + if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) { + char tbuf[BDEVT_SIZE]; + snprintf(tbuf, BDEVT_SIZE, "%02x%02x", MAJOR(devt), MINOR(devt)); + snprintf(buf, BDEVT_SIZE, "%-9s", tbuf); + } else + snprintf(buf, BDEVT_SIZE, "%03x:%05x", MAJOR(devt), MINOR(devt)); + + return buf; +} + /* * Register device numbers dev..(dev+range-1) * range must be nonzero @@ -521,7 +533,8 @@ void __init printk_all_partitions(void) struct gendisk *disk = dev_to_disk(dev); struct disk_part_iter piter; struct hd_struct *part; - char buf[BDEVNAME_SIZE]; + char name_buf[BDEVNAME_SIZE]; + char devt_buf[BDEVT_SIZE]; /* * Don't show empty devices or things that have been @@ -536,10 +549,10 @@ void __init printk_all_partitions(void) * numbers in hex - the same format as the root= * option takes. */ - printk("%02x%02x %10llu %s", - MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)), + printk("%s %10llu %s", + bdevt_str(disk_devt(disk), devt_buf), (unsigned long long)get_capacity(disk) >> 1, - disk_name(disk, 0, buf)); + disk_name(disk, 0, name_buf)); if (disk->driverfs_dev != NULL && disk->driverfs_dev->driver != NULL) printk(" driver: %s\n", @@ -550,10 +563,10 @@ void __init printk_all_partitions(void) /* now show the partitions */ disk_part_iter_init(&piter, disk, 0); while ((part = disk_part_iter_next(&piter))) - printk(" %02x%02x %10llu %s\n", - MAJOR(part_devt(part)), MINOR(part_devt(part)), + printk(" %s %10llu %s\n", + bdevt_str(part_devt(part), devt_buf), (unsigned long long)part->nr_sects >> 1, - disk_name(disk, part->partno, buf)); + disk_name(disk, part->partno, name_buf)); disk_part_iter_exit(&piter); } class_dev_iter_exit(&iter); @@ -630,14 +643,14 @@ static int show_partition(struct seq_file *seqf, void *v) return 0; /* show the full disk and all non-0 size partitions of it */ - seq_printf(seqf, "%4d %4d %10llu %s\n", + seq_printf(seqf, "%4d %7d %10llu %s\n", MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)), (unsigned long long)get_capacity(sgp) >> 1, disk_name(sgp, 0, buf)); disk_part_iter_init(&piter, sgp, 0); while ((part = disk_part_iter_next(&piter))) - seq_printf(seqf, "%4d %4d %10llu %s\n", + seq_printf(seqf, "%4d %7d %10llu %s\n", MAJOR(part_devt(part)), MINOR(part_devt(part)), (unsigned long long)part->nr_sects >> 1, disk_name(sgp, part->partno, buf)); @@ -691,6 +704,14 @@ static ssize_t disk_range_show(struct device *dev, return sprintf(buf, "%d\n", disk->minors); } +static ssize_t disk_ext_range_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gendisk *disk = dev_to_disk(dev); + + return sprintf(buf, "%d\n", disk_max_parts(disk) + 1); +} + static ssize_t disk_removable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -780,6 +801,7 @@ static ssize_t disk_fail_store(struct device *dev, #endif static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); +static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); @@ -792,6 +814,7 @@ static struct device_attribute dev_attr_fail = static struct attribute *disk_attrs[] = { &dev_attr_range.attr, + &dev_attr_ext_range.attr, &dev_attr_removable.attr, &dev_attr_ro.attr, &dev_attr_size.attr, @@ -858,7 +881,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) cpu = disk_stat_lock(); disk_round_stats(cpu, gp); disk_stat_unlock(); - seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", + seq_printf(seqf, "%4d %7d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), disk_name(gp, 0, buf), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), @@ -877,7 +900,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) cpu = disk_stat_lock(); part_round_stats(cpu, hd); disk_stat_unlock(); - seq_printf(seqf, "%4d %4d %s %lu %lu %llu " + seq_printf(seqf, "%4d %7d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", MAJOR(part_devt(hd)), MINOR(part_devt(hd)), disk_name(gp, hd->partno, buf), diff --git a/include/linux/fs.h b/include/linux/fs.h index 860689f541b..02a9fb5a830 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1685,6 +1685,7 @@ extern void chrdev_show(struct seq_file *,off_t); /* fs/block_dev.c */ #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ +#define BDEVT_SIZE 10 /* Largest string for MAJ:MIN for blkdev */ #ifdef CONFIG_BLOCK #define BLKDEV_MAJOR_HASH_SIZE 255 -- GitLab From f615b48cc7df7cac3865ec76ac1a5bb04d3e07f4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:24 +0900 Subject: [PATCH 3419/5416] sd/ide-disk: apply extended minors to sd and ide Update sd and ide-disk such that they can take advantage of extended minors. ide-disk already has 64 minors per device and currently doesn't use extended minors although after this patch it can be turned on by simply tweaking constants. sd only had 16 minors per device causing problems on certain peculiar configurations. This patch lifts the restriction and enables it to use upto 64 minors. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- drivers/ide/ide-disk.c | 11 ++++++++--- drivers/scsi/sd.c | 9 +++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 07ef88bd109..7a88de9ada2 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -41,6 +41,10 @@ #include #include +#define IDE_DISK_PARTS (1 << PARTN_BITS) +#define IDE_DISK_MINORS IDE_DISK_PARTS +#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) + struct ide_disk_obj { ide_drive_t *drive; ide_driver_t *driver; @@ -1151,8 +1155,8 @@ static int ide_disk_probe(ide_drive_t *drive) if (!idkp) goto failed; - g = alloc_disk_node(1 << PARTN_BITS, - hwif_to_node(drive->hwif)); + g = alloc_disk_ext_node(IDE_DISK_MINORS, IDE_DISK_EXT_MINORS, + hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; @@ -1178,7 +1182,8 @@ static int ide_disk_probe(ide_drive_t *drive) } else drive->attach = 1; - g->minors = 1 << PARTN_BITS; + g->minors = IDE_DISK_MINORS; + g->ext_minors = IDE_DISK_EXT_MINORS; g->driverfs_dev = &drive->gendev; g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; set_capacity(g, idedisk_capacity(drive)); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e5e7d785645..d1bb0e1d2d2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -86,6 +86,10 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +#define SD_PARTS 64 +#define SD_MINORS 16 +#define SD_EXT_MINORS (SD_PARTS - SD_MINORS) + static int sd_revalidate_disk(struct gendisk *); static int sd_probe(struct device *); static int sd_remove(struct device *); @@ -1801,7 +1805,7 @@ static int sd_probe(struct device *dev) if (!sdkp) goto out; - gd = alloc_disk(16); + gd = alloc_disk_ext(SD_MINORS, SD_EXT_MINORS); if (!gd) goto out_free; @@ -1845,7 +1849,8 @@ static int sd_probe(struct device *dev) gd->major = sd_major((index & 0xf0) >> 4); gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); - gd->minors = 16; + gd->minors = SD_MINORS; + gd->ext_minors = SD_EXT_MINORS; gd->fops = &sd_fops; if (index < 26) { -- GitLab From 870d6656126add8e383645732b03df2b7ccd4f94 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:47:25 +0900 Subject: [PATCH 3420/5416] block: implement CONFIG_DEBUG_BLOCK_EXT_DEVT Extended devt introduces non-contiguos device numbers. This patch implements a debug option which forces most devt allocations to be from the extended area and spreads them out. This is enabled by default if DEBUG_KERNEL is set and achieves... 1. Detects code paths in kernel or userland which expect predetermined consecutive device numbers. 2. When something goes wrong, avoid corruption as adding to the minor of earlier partition won't lead to the wrong but valid device. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 38 +++++++++++++++++++++++++++++++++++--- drivers/ide/ide-disk.c | 6 ++++++ drivers/scsi/sd.c | 6 ++++++ lib/Kconfig.debug | 16 ++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index ee4b13520e5..67e5a59ced2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -298,6 +298,38 @@ EXPORT_SYMBOL(unregister_blkdev); static struct kobj_map *bdev_map; +/** + * blk_mangle_minor - scatter minor numbers apart + * @minor: minor number to mangle + * + * Scatter consecutively allocated @minor number apart if MANGLE_DEVT + * is enabled. Mangling twice gives the original value. + * + * RETURNS: + * Mangled value. + * + * CONTEXT: + * Don't care. + */ +static int blk_mangle_minor(int minor) +{ +#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT + int i; + + for (i = 0; i < MINORBITS / 2; i++) { + int low = minor & (1 << i); + int high = minor & (1 << (MINORBITS - 1 - i)); + int distance = MINORBITS - 1 - 2 * i; + + minor ^= low | high; /* clear both bits */ + low <<= distance; /* swap the positions */ + high >>= distance; + minor |= low | high; /* and set */ + } +#endif + return minor; +} + /** * blk_alloc_devt - allocate a dev_t for a partition * @part: partition to allocate dev_t for @@ -339,7 +371,7 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) return -EBUSY; } - *devt = MKDEV(BLOCK_EXT_MAJOR, idx); + *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); return 0; } @@ -361,7 +393,7 @@ void blk_free_devt(dev_t devt) if (MAJOR(devt) == BLOCK_EXT_MAJOR) { mutex_lock(&ext_devt_mutex); - idr_remove(&ext_devt_idr, MINOR(devt)); + idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); mutex_unlock(&ext_devt_mutex); } } @@ -473,7 +505,7 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) struct hd_struct *part; mutex_lock(&ext_devt_mutex); - part = idr_find(&ext_devt_idr, MINOR(devt)); + part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); if (part && get_disk(part_to_disk(part))) { *partno = part->partno; disk = part_to_disk(part); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7a88de9ada2..a072df5053a 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -42,7 +42,13 @@ #include #define IDE_DISK_PARTS (1 << PARTN_BITS) + +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define IDE_DISK_MINORS IDE_DISK_PARTS +#else +#define IDE_DISK_MINORS 1 +#endif + #define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) struct ide_disk_obj { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d1bb0e1d2d2..280d231a86e 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -87,7 +87,13 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #define SD_PARTS 64 + +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define SD_MINORS 16 +#else +#define SD_MINORS 1 +#endif + #define SD_EXT_MINORS (SD_PARTS - SD_MINORS) static int sd_revalidate_disk(struct gendisk *); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0b504814e37..5a536f703a8 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -624,6 +624,22 @@ config BACKTRACE_SELF_TEST Say N if you are unsure. +config DEBUG_BLOCK_EXT_DEVT + bool "Force extended block device numbers and spread them" + depends on DEBUG_KERNEL + depends on BLOCK + default y + help + Conventionally, block device numbers are allocated from + predetermined contiguous area. However, extended block area + may introduce non-contiguous block device numbers. This + option forces most block device numbers to be allocated from + the extended space and spreads them to discover kernel or + userland code paths which assume predetermined contiguous + device number allocation. + + Say N if you are unsure. + config LKDTM tristate "Linux Kernel Dump Test Tool Module" depends on DEBUG_KERNEL -- GitLab From ed9e1982347b36573cd622ee5f4e2a7ccd79b3fd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:05 +0900 Subject: [PATCH 3421/5416] block: implement and use {disk|part}_to_dev() Implement {disk|part}_to_dev() and use them to access generic device instead of directly dereferencing {disk|part}->dev. To make sure no user is left behind, rename generic devices fields to __dev. This is in preparation of unifying partition 0 handling with other partitions. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-integrity.c | 5 ++- block/blk-sysfs.c | 4 +- block/genhd.c | 27 ++++++------- drivers/block/aoe/aoeblk.c | 4 +- drivers/block/nbd.c | 4 +- drivers/ide/ide-probe.c | 2 +- drivers/md/dm.c | 4 +- drivers/md/md.c | 10 ++--- fs/block_dev.c | 4 +- fs/partitions/check.c | 79 ++++++++++++++++++++------------------ include/linux/genhd.h | 20 +++++----- 11 files changed, 86 insertions(+), 77 deletions(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index d87606eaca1..69023da6315 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -331,7 +331,8 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) return -1; if (kobject_init_and_add(&bi->kobj, &integrity_ktype, - &disk->dev.kobj, "%s", "integrity")) { + &disk_to_dev(disk)->kobj, + "%s", "integrity")) { kmem_cache_free(integrity_cachep, bi); return -1; } @@ -375,7 +376,7 @@ void blk_integrity_unregister(struct gendisk *disk) kobject_uevent(&bi->kobj, KOBJ_REMOVE); kobject_del(&bi->kobj); - kobject_put(&disk->dev.kobj); + kobject_put(&disk_to_dev(disk)->kobj); kmem_cache_free(integrity_cachep, bi); } EXPORT_SYMBOL(blk_integrity_unregister); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 304ec73ab82..b9a6ed16664 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -310,7 +310,7 @@ int blk_register_queue(struct gendisk *disk) if (!q->request_fn) return 0; - ret = kobject_add(&q->kobj, kobject_get(&disk->dev.kobj), + ret = kobject_add(&q->kobj, kobject_get(&disk_to_dev(disk)->kobj), "%s", "queue"); if (ret < 0) return ret; @@ -339,6 +339,6 @@ void blk_unregister_queue(struct gendisk *disk) kobject_uevent(&q->kobj, KOBJ_REMOVE); kobject_del(&q->kobj); - kobject_put(&disk->dev.kobj); + kobject_put(&disk_to_dev(disk)->kobj); } } diff --git a/block/genhd.c b/block/genhd.c index 67e5a59ced2..0a2f16bd54b 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -59,7 +59,7 @@ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) rcu_read_lock(); part = rcu_dereference(disk->__part[partno - 1]); if (part) - get_device(&part->dev); + get_device(part_to_dev(part)); rcu_read_unlock(); return part; @@ -130,7 +130,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) continue; - get_device(&part->dev); + get_device(part_to_dev(part)); piter->part = part; piter->idx += inc; break; @@ -435,7 +435,7 @@ static struct kobject *exact_match(dev_t devt, int *partno, void *data) { struct gendisk *p = data; - return &p->dev.kobj; + return &disk_to_dev(p)->kobj; } static int exact_lock(dev_t devt, void *data) @@ -460,7 +460,7 @@ void add_disk(struct gendisk *disk) int retval; disk->flags |= GENHD_FL_UP; - disk->dev.devt = MKDEV(disk->major, disk->first_minor); + disk_to_dev(disk)->devt = MKDEV(disk->major, disk->first_minor); blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); register_disk(disk); @@ -468,7 +468,8 @@ void add_disk(struct gendisk *disk) bdi = &disk->queue->backing_dev_info; bdi_register_dev(bdi, disk_devt(disk)); - retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj, + "bdi"); WARN_ON(retval); } @@ -477,7 +478,7 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ void unlink_gendisk(struct gendisk *disk) { - sysfs_remove_link(&disk->dev.kobj, "bdi"); + sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); bdi_unregister(&disk->queue->backing_dev_info); blk_unregister_queue(disk); blk_unregister_region(disk_devt(disk), disk->minors); @@ -903,7 +904,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) int cpu; /* - if (&gp->dev.kobj.entry == block_class.devices.next) + if (&disk_to_dev(gp)->kobj.entry == block_class.devices.next) seq_puts(seqf, "major minor name" " rio rmerge rsect ruse wio wmerge " "wsect wuse running use aveq" @@ -972,7 +973,7 @@ static void media_change_notify_thread(struct work_struct *work) * set enviroment vars to indicate which event this is for * so that user space will know to go check the media status. */ - kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp); + kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp); put_device(gd->driverfs_dev); } @@ -1062,9 +1063,9 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->minors = minors; disk->ext_minors = ext_minors; rand_initialize_disk(disk); - disk->dev.class = &block_class; - disk->dev.type = &disk_type; - device_initialize(&disk->dev); + disk_to_dev(disk)->class = &block_class; + disk_to_dev(disk)->type = &disk_type; + device_initialize(disk_to_dev(disk)); INIT_WORK(&disk->async_notify, media_change_notify_thread); } @@ -1086,7 +1087,7 @@ struct kobject *get_disk(struct gendisk *disk) owner = disk->fops->owner; if (owner && !try_module_get(owner)) return NULL; - kobj = kobject_get(&disk->dev.kobj); + kobj = kobject_get(&disk_to_dev(disk)->kobj); if (kobj == NULL) { module_put(owner); return NULL; @@ -1100,7 +1101,7 @@ EXPORT_SYMBOL(get_disk); void put_disk(struct gendisk *disk) { if (disk) - kobject_put(&disk->dev.kobj); + kobject_put(&disk_to_dev(disk)->kobj); } EXPORT_SYMBOL(put_disk); diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 0c39782b266..3edb6cb7d68 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -109,12 +109,12 @@ static const struct attribute_group attr_group = { static int aoedisk_add_sysfs(struct aoedev *d) { - return sysfs_create_group(&d->gd->dev.kobj, &attr_group); + return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group); } void aoedisk_rm_sysfs(struct aoedev *d) { - sysfs_remove_group(&d->gd->dev.kobj, &attr_group); + sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group); } static int diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 1778e4a2c67..7b3351260d5 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -403,7 +403,7 @@ static int nbd_do_it(struct nbd_device *lo) BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr); + ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); if (ret) { printk(KERN_ERR "nbd: sysfs_create_file failed!"); return ret; @@ -412,7 +412,7 @@ static int nbd_do_it(struct nbd_device *lo) while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); - sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr); + sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); return 0; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a51a30e9eab..70aa86c8807 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1188,7 +1188,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data) { struct gendisk *p = data; *part &= (1 << PARTN_BITS) - 1; - return &p->dev.kobj; + return &disk_to_dev(p)->kobj; } static int exact_lock(dev_t dev, void *data) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 653624792ea..637806695bb 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1186,7 +1186,7 @@ static void event_callback(void *context) list_splice_init(&md->uevent_list, &uevents); spin_unlock_irqrestore(&md->uevent_lock, flags); - dm_send_uevents(&uevents, &md->disk->dev.kobj); + dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj); atomic_inc(&md->event_nr); wake_up(&md->eventq); @@ -1643,7 +1643,7 @@ out: *---------------------------------------------------------------*/ void dm_kobject_uevent(struct mapped_device *md) { - kobject_uevent(&md->disk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE); } uint32_t dm_next_uevent_seq(struct mapped_device *md) diff --git a/drivers/md/md.c b/drivers/md/md.c index deeac4b4417..96e9fccd2ea 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1465,9 +1465,9 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) goto fail; if (rdev->bdev->bd_part) - ko = &rdev->bdev->bd_part->dev.kobj; + ko = &part_to_dev(rdev->bdev->bd_part)->kobj; else - ko = &rdev->bdev->bd_disk->dev.kobj; + ko = &disk_to_dev(rdev->bdev->bd_disk)->kobj; if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) { kobject_del(&rdev->kobj); goto fail; @@ -3470,8 +3470,8 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) disk->queue = mddev->queue; add_disk(disk); mddev->gendisk = disk; - error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj, - "%s", "md"); + error = kobject_init_and_add(&mddev->kobj, &md_ktype, + &disk_to_dev(disk)->kobj, "%s", "md"); mutex_unlock(&disks_mutex); if (error) printk(KERN_WARNING "md: cannot register %s/md - name in use\n", @@ -3761,7 +3761,7 @@ static int do_md_run(mddev_t * mddev) sysfs_notify(&mddev->kobj, NULL, "array_state"); sysfs_notify(&mddev->kobj, NULL, "sync_action"); sysfs_notify(&mddev->kobj, NULL, "degraded"); - kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); return 0; } diff --git a/fs/block_dev.c b/fs/block_dev.c index 2f2873b9a04..a02df22f37c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -543,9 +543,9 @@ EXPORT_SYMBOL(bd_release); static struct kobject *bdev_get_kobj(struct block_device *bdev) { if (bdev->bd_contains != bdev) - return kobject_get(&bdev->bd_part->dev.kobj); + return kobject_get(&part_to_dev(bdev->bd_part)->kobj); else - return kobject_get(&bdev->bd_disk->dev.kobj); + return kobject_get(&disk_to_dev(bdev->bd_disk)->kobj); } static struct kobject *bdev_get_holder(struct block_device *bdev) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 0d4b7f28f13..ac0df3acdcd 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -309,7 +309,7 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk) { struct kobject *k; - k = kobject_get(&disk->dev.kobj); + k = kobject_get(&disk_to_dev(disk)->kobj); disk->holder_dir = kobject_create_and_add("holders", k); disk->slave_dir = kobject_create_and_add("slaves", k); kobject_put(k); @@ -322,7 +322,7 @@ static void delete_partition_rcu_cb(struct rcu_head *head) part->start_sect = 0; part->nr_sects = 0; part_stat_set_all(part, 0); - put_device(&part->dev); + put_device(part_to_dev(part)); } void delete_partition(struct gendisk *disk, int partno) @@ -336,7 +336,7 @@ void delete_partition(struct gendisk *disk, int partno) blk_free_devt(part_devt(part)); rcu_assign_pointer(disk->__part[partno-1], NULL); kobject_put(part->holder_dir); - device_del(&part->dev); + device_del(part_to_dev(part)); call_rcu(&part->rcu_head, delete_partition_rcu_cb); } @@ -354,6 +354,9 @@ int add_partition(struct gendisk *disk, int partno, { struct hd_struct *p; dev_t devt = MKDEV(0, 0); + struct device *ddev = disk_to_dev(disk); + struct device *pdev; + const char *dname; int err; if (disk->__part[partno - 1]) @@ -367,42 +370,43 @@ int add_partition(struct gendisk *disk, int partno, err = -ENOMEM; goto out_free; } + pdev = part_to_dev(p); + p->start_sect = start; p->nr_sects = len; p->partno = partno; p->policy = disk->policy; - if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1])) - snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%sp%d", disk->dev.bus_id, partno); + dname = dev_name(ddev); + if (isdigit(dname[strlen(dname) - 1])) + snprintf(pdev->bus_id, BUS_ID_SIZE, "%sp%d", dname, partno); else - snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%s%d", disk->dev.bus_id, partno); + snprintf(pdev->bus_id, BUS_ID_SIZE, "%s%d", dname, partno); - device_initialize(&p->dev); - p->dev.class = &block_class; - p->dev.type = &part_type; - p->dev.parent = &disk->dev; + device_initialize(pdev); + pdev->class = &block_class; + pdev->type = &part_type; + pdev->parent = ddev; err = blk_alloc_devt(p, &devt); if (err) - goto out_put; - p->dev.devt = devt; + goto out_free; + pdev->devt = devt; /* delay uevent until 'holders' subdir is created */ - p->dev.uevent_suppress = 1; - err = device_add(&p->dev); + pdev->uevent_suppress = 1; + err = device_add(pdev); if (err) goto out_put; err = -ENOMEM; - p->holder_dir = kobject_create_and_add("holders", &p->dev.kobj); + p->holder_dir = kobject_create_and_add("holders", &pdev->kobj); if (!p->holder_dir) goto out_del; - p->dev.uevent_suppress = 0; + pdev->uevent_suppress = 0; if (flags & ADDPART_FLAG_WHOLEDISK) { - err = device_create_file(&p->dev, &dev_attr_whole_disk); + err = device_create_file(pdev, &dev_attr_whole_disk); if (err) goto out_del; } @@ -412,8 +416,8 @@ int add_partition(struct gendisk *disk, int partno, rcu_assign_pointer(disk->__part[partno - 1], p); /* suppress uevent if the disk supresses it */ - if (!disk->dev.uevent_suppress) - kobject_uevent(&p->dev.kobj, KOBJ_ADD); + if (!ddev->uevent_suppress) + kobject_uevent(&pdev->kobj, KOBJ_ADD); return 0; @@ -422,9 +426,9 @@ out_free: return err; out_del: kobject_put(p->holder_dir); - device_del(&p->dev); + device_del(pdev); out_put: - put_device(&p->dev); + put_device(pdev); blk_free_devt(devt); return err; } @@ -432,30 +436,31 @@ out_put: /* Not exported, helper to add_disk(). */ void register_disk(struct gendisk *disk) { + struct device *ddev = disk_to_dev(disk); struct block_device *bdev; struct disk_part_iter piter; struct hd_struct *part; char *s; int err; - disk->dev.parent = disk->driverfs_dev; + ddev->parent = disk->driverfs_dev; - strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); + strlcpy(ddev->bus_id, disk->disk_name, BUS_ID_SIZE); /* ewww... some of these buggers have / in the name... */ - s = strchr(disk->dev.bus_id, '/'); + s = strchr(ddev->bus_id, '/'); if (s) *s = '!'; /* delay uevents, until we scanned partition table */ - disk->dev.uevent_suppress = 1; + ddev->uevent_suppress = 1; - if (device_add(&disk->dev)) + if (device_add(ddev)) return; #ifndef CONFIG_SYSFS_DEPRECATED - err = sysfs_create_link(block_depr, &disk->dev.kobj, - kobject_name(&disk->dev.kobj)); + err = sysfs_create_link(block_depr, &ddev->kobj, + kobject_name(&ddev->kobj)); if (err) { - device_del(&disk->dev); + device_del(ddev); return; } #endif @@ -481,13 +486,13 @@ void register_disk(struct gendisk *disk) exit: /* announce disk after possible partitions are created */ - disk->dev.uevent_suppress = 0; - kobject_uevent(&disk->dev.kobj, KOBJ_ADD); + ddev->uevent_suppress = 0; + kobject_uevent(&ddev->kobj, KOBJ_ADD); /* announce possible partitions */ disk_part_iter_init(&piter, disk, 0); while ((part = disk_part_iter_next(&piter))) - kobject_uevent(&part->dev.kobj, KOBJ_ADD); + kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); disk_part_iter_exit(&piter); } @@ -518,7 +523,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) return -EIO; /* tell userspace that the media / partition table may have changed */ - kobject_uevent(&disk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); for (p = 1; p < state->limit; p++) { sector_t size = state->parts[p].size; @@ -591,7 +596,7 @@ void del_gendisk(struct gendisk *disk) kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; #ifndef CONFIG_SYSFS_DEPRECATED - sysfs_remove_link(block_depr, disk->dev.bus_id); + sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); #endif - device_del(&disk->dev); + device_del(disk_to_dev(disk)); } diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 6fc53242406..e4e18c509ac 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -15,9 +15,11 @@ #ifdef CONFIG_BLOCK -#define kobj_to_dev(k) container_of(k, struct device, kobj) -#define dev_to_disk(device) container_of(device, struct gendisk, dev) -#define dev_to_part(device) container_of(device, struct hd_struct, dev) +#define kobj_to_dev(k) container_of((k), struct device, kobj) +#define dev_to_disk(device) container_of((device), struct gendisk, __dev) +#define dev_to_part(device) container_of((device), struct hd_struct, __dev) +#define disk_to_dev(disk) (&((disk)->__dev)) +#define part_to_dev(part) (&((part)->__dev)) extern struct device_type part_type; extern struct kobject *block_depr; @@ -88,7 +90,7 @@ struct disk_stats { struct hd_struct { sector_t start_sect; sector_t nr_sects; - struct device dev; + struct device __dev; struct kobject *holder_dir; int policy, partno; #ifdef CONFIG_FAIL_MAKE_REQUEST @@ -139,7 +141,7 @@ struct gendisk { int flags; struct device *driverfs_dev; // FIXME: remove - struct device dev; + struct device __dev; struct kobject *holder_dir; struct kobject *slave_dir; @@ -163,7 +165,7 @@ struct gendisk { static inline struct gendisk *part_to_disk(struct hd_struct *part) { if (likely(part)) - return dev_to_disk((part)->dev.parent); + return dev_to_disk(part_to_dev(part)->parent); return NULL; } @@ -174,12 +176,12 @@ static inline int disk_max_parts(struct gendisk *disk) static inline dev_t disk_devt(struct gendisk *disk) { - return disk->dev.devt; + return disk_to_dev(disk)->devt; } static inline dev_t part_devt(struct hd_struct *part) { - return part->dev.devt; + return part_to_dev(part)->devt; } extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno); @@ -187,7 +189,7 @@ extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno); static inline void disk_put_part(struct hd_struct *part) { if (likely(part)) - put_device(&part->dev); + put_device(part_to_dev(part)); } /* -- GitLab From b5d0b9df0ba5d9a044f3a21e7544f53d90bd1465 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 09:06:42 +0200 Subject: [PATCH 3422/5416] block: introduce partition 0 genhd and partition code handled disk and partitions separately. All information about the whole disk was in struct genhd and partitions in struct hd_struct. However, the whole disk (part0) and other partitions have a lot in common and the data structures end up having good number of common fields and thus separate code paths doing the same thing. Also, the partition array was indexed by partno - 1 which gets pretty confusing at times. This patch introduces partition 0 and makes the partition array indexed by partno. Following patches will unify the handling of disk and parts piece-by-piece. This patch also implements disk_partitionable() which tests whether a disk is partitionable. With coming dynamic partition array change, the most common usage of disk_max_parts() will be testing whether a disk is partitionable and the number of max partitions will become much less important. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 40 +++++++++++++++++++++++----------------- block/ioctl.c | 4 ++-- fs/block_dev.c | 2 +- fs/partitions/check.c | 12 ++++++------ include/linux/genhd.h | 11 +++++++++-- 5 files changed, 41 insertions(+), 28 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 0a2f16bd54b..65b7386c26d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -54,10 +54,10 @@ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) { struct hd_struct *part; - if (unlikely(partno < 1 || partno > disk_max_parts(disk))) + if (unlikely(partno < 0 || partno >= disk_max_parts(disk))) return NULL; rcu_read_lock(); - part = rcu_dereference(disk->__part[partno - 1]); + part = rcu_dereference(disk->__part[partno]); if (part) get_device(part_to_dev(part)); rcu_read_unlock(); @@ -85,8 +85,10 @@ void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, if (flags & DISK_PITER_REVERSE) piter->idx = disk_max_parts(piter->disk) - 1; - else + else if (flags & DISK_PITER_INCL_PART0) piter->idx = 0; + else + piter->idx = 1; piter->flags = flags; } @@ -114,7 +116,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) /* determine iteration parameters */ if (piter->flags & DISK_PITER_REVERSE) { inc = -1; - end = -1; + if (piter->flags & DISK_PITER_INCL_PART0) + end = -1; + else + end = 0; } else { inc = 1; end = disk_max_parts(piter->disk); @@ -177,7 +182,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) { int i; - for (i = 0; i < disk_max_parts(disk); i++) { + for (i = 1; i < disk_max_parts(disk); i++) { struct hd_struct *part = rcu_dereference(disk->__part[i]); if (part && part->start_sect <= sector && @@ -669,7 +674,7 @@ static int show_partition(struct seq_file *seqf, void *v) char buf[BDEVNAME_SIZE]; /* Don't show non-partitionable removeable devices or empty devices */ - if (!get_capacity(sgp) || (!disk_max_parts(sgp) && + if (!get_capacity(sgp) || (!disk_partitionable(sgp) && (sgp->flags & GENHD_FL_REMOVABLE))) return 0; if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) @@ -742,7 +747,7 @@ static ssize_t disk_ext_range_show(struct device *dev, { struct gendisk *disk = dev_to_disk(dev); - return sprintf(buf, "%d\n", disk_max_parts(disk) + 1); + return sprintf(buf, "%d\n", disk_max_parts(disk)); } static ssize_t disk_removable_show(struct device *dev, @@ -998,7 +1003,7 @@ dev_t blk_lookup_devt(const char *name, int partno) if (strcmp(dev->bus_id, name)) continue; - if (partno < 0 || partno > disk_max_parts(disk)) + if (partno < 0 || partno >= disk_max_parts(disk)) continue; if (partno == 0) @@ -1045,21 +1050,22 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) GFP_KERNEL | __GFP_ZERO, node_id); if (disk) { int tot_minors = minors + ext_minors; + int size = tot_minors * sizeof(struct hd_struct *); if (!init_disk_stats(disk)) { kfree(disk); return NULL; } - if (tot_minors > 1) { - int size = (tot_minors - 1) * sizeof(struct hd_struct *); - disk->__part = kmalloc_node(size, - GFP_KERNEL | __GFP_ZERO, node_id); - if (!disk->__part) { - free_disk_stats(disk); - kfree(disk); - return NULL; - } + + disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, + node_id); + if (!disk->__part) { + free_disk_stats(disk); + kfree(disk); + return NULL; } + disk->__part[0] = &disk->part0; + disk->minors = minors; disk->ext_minors = ext_minors; rand_initialize_disk(disk); diff --git a/block/ioctl.c b/block/ioctl.c index a5f672ad55f..64e7c67a64b 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user if (bdev != bdev->bd_contains) return -EINVAL; partno = p.pno; - if (partno <= 0 || partno > disk_max_parts(disk)) + if (partno <= 0 || partno >= disk_max_parts(disk)) return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: @@ -102,7 +102,7 @@ static int blkdev_reread_part(struct block_device *bdev) struct gendisk *disk = bdev->bd_disk; int res; - if (!disk_max_parts(disk) || bdev != bdev->bd_contains) + if (!disk_partitionable(disk) || bdev != bdev->bd_contains) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff --git a/fs/block_dev.c b/fs/block_dev.c index a02df22f37c..c982a910797 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev) if (bdops->revalidate_disk) bdops->revalidate_disk(bdev->bd_disk); - if (disk_max_parts(bdev->bd_disk)) + if (disk_partitionable(bdev->bd_disk)) bdev->bd_invalidated = 1; return 1; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ac0df3acdcd..b60699c271a 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -173,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); - state->limit = disk_max_parts(hd) + 1; + state->limit = disk_max_parts(hd); i = res = err = 0; while (!res && check_part[i]) { memset(&state->parts, 0, sizeof(state->parts)); @@ -329,12 +329,12 @@ void delete_partition(struct gendisk *disk, int partno) { struct hd_struct *part; - part = disk->__part[partno-1]; + part = disk->__part[partno]; if (!part) return; blk_free_devt(part_devt(part)); - rcu_assign_pointer(disk->__part[partno-1], NULL); + rcu_assign_pointer(disk->__part[partno], NULL); kobject_put(part->holder_dir); device_del(part_to_dev(part)); @@ -359,7 +359,7 @@ int add_partition(struct gendisk *disk, int partno, const char *dname; int err; - if (disk->__part[partno - 1]) + if (disk->__part[partno]) return -EBUSY; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -413,7 +413,7 @@ int add_partition(struct gendisk *disk, int partno, /* everything is up and running, commence */ INIT_RCU_HEAD(&p->rcu_head); - rcu_assign_pointer(disk->__part[partno - 1], p); + rcu_assign_pointer(disk->__part[partno], p); /* suppress uevent if the disk supresses it */ if (!ddev->uevent_suppress) @@ -467,7 +467,7 @@ void register_disk(struct gendisk *disk) disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ - if (!disk_max_parts(disk)) + if (!disk_partitionable(disk)) goto exit; /* No such device (e.g., media were just removed) */ diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e4e18c509ac..9e866a2aee5 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -127,12 +127,13 @@ struct gendisk { char disk_name[32]; /* name of major driver */ - /* Array of pointers to partitions indexed by partno - 1. + /* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other * non-critical accesses use RCU. Always access through * helpers. */ struct hd_struct **__part; + struct hd_struct part0; struct block_device_operations *fops; struct request_queue *queue; @@ -171,7 +172,12 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) static inline int disk_max_parts(struct gendisk *disk) { - return disk->minors + disk->ext_minors - 1; + return disk->minors + disk->ext_minors; +} + +static inline bool disk_partitionable(struct gendisk *disk) +{ + return disk_max_parts(disk) > 1; } static inline dev_t disk_devt(struct gendisk *disk) @@ -197,6 +203,7 @@ static inline void disk_put_part(struct hd_struct *part) */ #define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ #define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ +#define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */ struct disk_part_iter { struct gendisk *disk; -- GitLab From 80795aefb76d10c5d698e60c7e7750b5330787da Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:07 +0900 Subject: [PATCH 3423/5416] block: move capacity from disk to part0 Move disk->capacity to part0->nr_sects and convert all users who directly accessed the field to use {get|set}_capacity(). This is done early to allow the __dev field to be moved. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoecmd.c | 4 ++-- drivers/block/aoe/aoedev.c | 2 +- fs/partitions/check.c | 2 +- include/linux/genhd.h | 5 ++--- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 3edb6cb7d68..aa69556c348 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -276,7 +276,7 @@ aoeblk_gdalloc(void *vp) gd->first_minor = d->sysminor * AOE_PARTITIONS; gd->fops = &aoe_bdops; gd->private_data = d; - gd->capacity = d->ssize; + set_capacity(gd, d->ssize); snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", d->aoemajor, d->aoeminor); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 17eed8c025d..934800f979c 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -645,7 +645,7 @@ aoecmd_sleepwork(struct work_struct *work) unsigned long flags; u64 ssize; - ssize = d->gd->capacity; + ssize = get_capacity(d->gd); bd = bdget_disk(d->gd, 0); if (bd) { @@ -707,7 +707,7 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) return; if (d->gd != NULL) { - d->gd->capacity = ssize; + set_capacity(d->gd, ssize); d->flags |= DEVFL_NEWSIZE; } else d->flags |= DEVFL_GDALLOC; diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index a1d813ab0d6..6a8038d115b 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -91,7 +91,7 @@ aoedev_downdev(struct aoedev *d) } if (d->gd) - d->gd->capacity = 0; + set_capacity(d->gd, 0); d->flags &= ~DEVFL_UP; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index b60699c271a..902b95f1f9d 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -586,7 +586,7 @@ void del_gendisk(struct gendisk *disk) disk_part_iter_exit(&piter); invalidate_partition(disk, 0); - disk->capacity = 0; + set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; unlink_gendisk(disk); disk_stat_set_all(disk, 0); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 9e866a2aee5..1cf828148ec 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -138,7 +138,6 @@ struct gendisk { struct block_device_operations *fops; struct request_queue *queue; void *private_data; - sector_t capacity; int flags; struct device *driverfs_dev; // FIXME: remove @@ -411,11 +410,11 @@ static inline sector_t get_start_sect(struct block_device *bdev) } static inline sector_t get_capacity(struct gendisk *disk) { - return disk->capacity; + return disk->part0.nr_sects; } static inline void set_capacity(struct gendisk *disk, sector_t size) { - disk->capacity = size; + disk->part0.nr_sects = size; } #ifdef CONFIG_SOLARIS_X86_PARTITION -- GitLab From 548b10eb2959c96cef6fc29fc96e0931eeb53bc5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Aug 2008 09:01:47 +0200 Subject: [PATCH 3424/5416] block: move __dev from disk to part0 Move disk->__dev to part0->__dev. This simplifies bdget_disk() and lookup_devt() and allows common sysfs attributes to be unified. part_to_disk() is updated to handle part0 -> disk. Updated to include a fix from Bartlomiej Zolnierkiewicz , he writes: "part0 is a "special" partition and doesn't need to have capacity set - this fixes regression caused by "block: move __dev from disk to part0" commit." Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 40 ++++++++++++---------------------------- include/linux/genhd.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 65b7386c26d..36b9f1bdd91 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -537,22 +537,15 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) */ extern struct block_device *bdget_disk(struct gendisk *disk, int partno) { - dev_t devt = MKDEV(0, 0); + struct hd_struct *part; + struct block_device *bdev = NULL; - if (partno == 0) - devt = disk_devt(disk); - else { - struct hd_struct *part; + part = disk_get_part(disk, partno); + if (part && (part->nr_sects || partno == 0)) + bdev = bdget(part_devt(part)); + disk_put_part(part); - part = disk_get_part(disk, partno); - if (part && part->nr_sects) - devt = part_devt(part); - disk_put_part(part); - } - - if (likely(devt != MKDEV(0, 0))) - return bdget(devt); - return NULL; + return bdev; } EXPORT_SYMBOL(bdget_disk); @@ -1000,27 +993,18 @@ dev_t blk_lookup_devt(const char *name, int partno) class_dev_iter_init(&iter, &block_class, NULL, &disk_type); while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); + struct hd_struct *part; if (strcmp(dev->bus_id, name)) continue; - if (partno < 0 || partno >= disk_max_parts(disk)) - continue; - - if (partno == 0) - devt = disk_devt(disk); - else { - struct hd_struct *part; - - part = disk_get_part(disk, partno); - if (!part || !part->nr_sects) { - disk_put_part(part); - continue; - } + part = disk_get_part(disk, partno); + if (part && (part->nr_sects || partno == 0)) { devt = part_devt(part); disk_put_part(part); + break; } - break; + disk_put_part(part); } class_dev_iter_exit(&iter); return devt; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 1cf828148ec..ff293ec8b3f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -16,9 +16,9 @@ #ifdef CONFIG_BLOCK #define kobj_to_dev(k) container_of((k), struct device, kobj) -#define dev_to_disk(device) container_of((device), struct gendisk, __dev) +#define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev) #define dev_to_part(device) container_of((device), struct hd_struct, __dev) -#define disk_to_dev(disk) (&((disk)->__dev)) +#define disk_to_dev(disk) (&(disk)->part0.__dev) #define part_to_dev(part) (&((part)->__dev)) extern struct device_type part_type; @@ -141,7 +141,6 @@ struct gendisk { int flags; struct device *driverfs_dev; // FIXME: remove - struct device __dev; struct kobject *holder_dir; struct kobject *slave_dir; @@ -164,8 +163,12 @@ struct gendisk { static inline struct gendisk *part_to_disk(struct hd_struct *part) { - if (likely(part)) - return dev_to_disk(part_to_dev(part)->parent); + if (likely(part)) { + if (part->partno) + return dev_to_disk(part_to_dev(part)->parent); + else + return dev_to_disk(part_to_dev(part)); + } return NULL; } -- GitLab From e56105214943ce5f0901d20e972a7cfd0d1d0656 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:09 +0900 Subject: [PATCH 3425/5416] block: unify sysfs size node handling Now that capacity and __dev are moved to part0, part0 and others can share the same method. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 10 +--------- fs/partitions/check.c | 4 ++-- include/linux/genhd.h | 3 +++ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 36b9f1bdd91..c70db35076a 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -760,14 +760,6 @@ static ssize_t disk_ro_show(struct device *dev, return sprintf(buf, "%d\n", disk->policy ? 1 : 0); } -static ssize_t disk_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - - return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk)); -} - static ssize_t disk_capability_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -835,7 +827,7 @@ static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); -static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); #ifdef CONFIG_FAIL_MAKE_REQUEST diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 902b95f1f9d..24d2c56d7d2 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -208,8 +208,8 @@ static ssize_t part_start_show(struct device *dev, return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect); } -static ssize_t part_size_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index ff293ec8b3f..9cb8380cf0e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -591,6 +591,9 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data); extern void blk_unregister_region(dev_t devt, unsigned long range); +extern ssize_t part_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } -- GitLab From b7db9956e57c8151b930d5e5fe5c766e6aad3ff7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:10 +0900 Subject: [PATCH 3426/5416] block: move policy from disk to part0 Move disk->policy to part0->policy. Implement and use get_disk_ro(). Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 16 +++++----------- drivers/ide/ide-cd.c | 2 +- drivers/md/dm-ioctl.c | 2 +- fs/partitions/check.c | 2 +- include/linux/genhd.h | 6 +++++- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index c70db35076a..70358f3c742 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -757,7 +757,7 @@ static ssize_t disk_ro_show(struct device *dev, { struct gendisk *disk = dev_to_disk(dev); - return sprintf(buf, "%d\n", disk->policy ? 1 : 0); + return sprintf(buf, "%d\n", get_disk_ro(disk) ? 1 : 0); } static ssize_t disk_capability_show(struct device *dev, @@ -1090,10 +1090,7 @@ EXPORT_SYMBOL(put_disk); void set_device_ro(struct block_device *bdev, int flag) { - if (bdev->bd_contains != bdev) - bdev->bd_part->policy = flag; - else - bdev->bd_disk->policy = flag; + bdev->bd_part->policy = flag; } EXPORT_SYMBOL(set_device_ro); @@ -1103,8 +1100,8 @@ void set_disk_ro(struct gendisk *disk, int flag) struct disk_part_iter piter; struct hd_struct *part; - disk->policy = flag; - disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY | DISK_PITER_INCL_PART0); while ((part = disk_part_iter_next(&piter))) part->policy = flag; disk_part_iter_exit(&piter); @@ -1116,10 +1113,7 @@ int bdev_read_only(struct block_device *bdev) { if (!bdev) return 0; - else if (bdev->bd_contains != bdev) - return bdev->bd_part->policy; - else - return bdev->bd_disk->policy; + return bdev->bd_part->policy; } EXPORT_SYMBOL(bdev_read_only); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f16bb466723..03c2cb6a58b 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1113,7 +1113,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) if (write) { /* disk has become write protected */ - if (cd->disk->policy) { + if (get_disk_ro(cd->disk)) { cdrom_end_request(drive, 0); return ide_stopped; } diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index c3de311117a..5b919159f08 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -548,7 +548,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) */ param->open_count = dm_open_count(md); - if (disk->policy) + if (get_disk_ro(disk)) param->flags |= DM_READONLY_FLAG; param->event_nr = dm_get_event_nr(md); diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 24d2c56d7d2..ace6d03602c 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -375,7 +375,7 @@ int add_partition(struct gendisk *disk, int partno, p->start_sect = start; p->nr_sects = len; p->partno = partno; - p->policy = disk->policy; + p->policy = get_disk_ro(disk); dname = dev_name(ddev); if (isdigit(dname[strlen(dname) - 1])) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 9cb8380cf0e..4411bdd671d 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -145,7 +145,6 @@ struct gendisk { struct kobject *slave_dir; struct timer_rand_state *random; - int policy; atomic_t sync_io; /* RAID */ unsigned long stamp; @@ -403,6 +402,11 @@ extern struct block_device *bdget_disk(struct gendisk *disk, int partno); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); +static inline int get_disk_ro(struct gendisk *disk) +{ + return disk->part0.policy; +} + /* drivers/char/random.c */ extern void add_disk_randomness(struct gendisk *disk); extern void rand_initialize_disk(struct gendisk *disk); -- GitLab From 4c46501d1659475dc6c89554af6ce7fe6ecf615c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:11 +0900 Subject: [PATCH 3427/5416] block: move holder_dir from disk to part0 Move disk->holder_dir to part0->holder_dir. Kill now mostly superflous bdev_get_holder(). While at it, kill superflous kobject_get/put() around holder_dir, slave_dir and cmd_filter creation and collapse disk_sysfs_add_subdirs() into register_disk(). These serve no purpose but obfuscating the code. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/cmd-filter.c | 9 ++------- fs/block_dev.c | 10 +--------- fs/partitions/check.c | 15 +++------------ include/linux/genhd.h | 1 - 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/block/cmd-filter.c b/block/cmd-filter.c index 79c14996ac1..e669aed4c6b 100644 --- a/block/cmd-filter.c +++ b/block/cmd-filter.c @@ -211,14 +211,10 @@ int blk_register_filter(struct gendisk *disk) { int ret; struct blk_cmd_filter *filter = &disk->queue->cmd_filter; - struct kobject *parent = kobject_get(disk->holder_dir->parent); - if (!parent) - return -ENODEV; - - ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent, + ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, + &disk_to_dev(disk)->kobj, "%s", "cmd_filter"); - if (ret < 0) return ret; @@ -231,7 +227,6 @@ void blk_unregister_filter(struct gendisk *disk) struct blk_cmd_filter *filter = &disk->queue->cmd_filter; kobject_put(&filter->kobj); - kobject_put(disk->holder_dir->parent); } EXPORT_SYMBOL(blk_unregister_filter); #endif diff --git a/fs/block_dev.c b/fs/block_dev.c index c982a910797..57d57264285 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -548,14 +548,6 @@ static struct kobject *bdev_get_kobj(struct block_device *bdev) return kobject_get(&disk_to_dev(bdev->bd_disk)->kobj); } -static struct kobject *bdev_get_holder(struct block_device *bdev) -{ - if (bdev->bd_contains != bdev) - return kobject_get(bdev->bd_part->holder_dir); - else - return kobject_get(bdev->bd_disk->holder_dir); -} - static int add_symlink(struct kobject *from, struct kobject *to) { if (!from || !to) @@ -608,7 +600,7 @@ static int bd_holder_grab_dirs(struct block_device *bdev, if (!bo->sdev) goto fail_put_hdev; - bo->hdir = bdev_get_holder(bdev); + bo->hdir = kobject_get(bdev->bd_part->holder_dir); if (!bo->hdir) goto fail_put_sdev; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ace6d03602c..f0f604950ff 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -305,16 +305,6 @@ struct device_type part_type = { .release = part_release, }; -static inline void disk_sysfs_add_subdirs(struct gendisk *disk) -{ - struct kobject *k; - - k = kobject_get(&disk_to_dev(disk)->kobj); - disk->holder_dir = kobject_create_and_add("holders", k); - disk->slave_dir = kobject_create_and_add("slaves", k); - kobject_put(k); -} - static void delete_partition_rcu_cb(struct rcu_head *head) { struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); @@ -464,7 +454,8 @@ void register_disk(struct gendisk *disk) return; } #endif - disk_sysfs_add_subdirs(disk); + disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); + disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); /* No minors to use for partitions */ if (!disk_partitionable(disk)) @@ -592,7 +583,7 @@ void del_gendisk(struct gendisk *disk) disk_stat_set_all(disk, 0); disk->stamp = 0; - kobject_put(disk->holder_dir); + kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; #ifndef CONFIG_SYSFS_DEPRECATED diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 4411bdd671d..2c0e1b597ab 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -141,7 +141,6 @@ struct gendisk { int flags; struct device *driverfs_dev; // FIXME: remove - struct kobject *holder_dir; struct kobject *slave_dir; struct timer_rand_state *random; -- GitLab From 0762b8bde9729f10f8e6249809660ff2ec3ad735 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:12 +0900 Subject: [PATCH 3428/5416] block: always set bdev->bd_part Till now, bdev->bd_part is set only if the bdev was for parts other than part0. This patch makes bdev->bd_part always set so that code paths don't have to differenciate common handling. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 2 +- drivers/md/md.c | 5 +--- fs/block_dev.c | 67 ++++++++++++++++++++----------------------- fs/partitions/check.c | 7 +---- include/linux/genhd.h | 2 +- 5 files changed, 35 insertions(+), 48 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index e0a5ee36849..a4a7c08d2f2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1274,7 +1274,7 @@ __setup("fail_make_request=", setup_fail_make_request); static int should_fail_request(struct bio *bio) { if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) || - (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail)) + bio->bi_bdev->bd_part->make_it_fail) return should_fail(&fail_make_request, bio->bi_size); return 0; diff --git a/drivers/md/md.c b/drivers/md/md.c index 96e9fccd2ea..2bd9cf41612 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1464,10 +1464,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) goto fail; - if (rdev->bdev->bd_part) - ko = &part_to_dev(rdev->bdev->bd_part)->kobj; - else - ko = &disk_to_dev(rdev->bdev->bd_disk)->kobj; + ko = &part_to_dev(rdev->bdev->bd_part)->kobj; if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) { kobject_del(&rdev->kobj); goto fail; diff --git a/fs/block_dev.c b/fs/block_dev.c index 57d57264285..c3fa19bd64d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -540,14 +540,6 @@ EXPORT_SYMBOL(bd_release); * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 */ -static struct kobject *bdev_get_kobj(struct block_device *bdev) -{ - if (bdev->bd_contains != bdev) - return kobject_get(&part_to_dev(bdev->bd_part)->kobj); - else - return kobject_get(&disk_to_dev(bdev->bd_disk)->kobj); -} - static int add_symlink(struct kobject *from, struct kobject *to) { if (!from || !to) @@ -596,7 +588,7 @@ static int bd_holder_grab_dirs(struct block_device *bdev, if (!bo->hdev) goto fail_put_sdir; - bo->sdev = bdev_get_kobj(bdev); + bo->sdev = kobject_get(&part_to_dev(bdev->bd_part)->kobj); if (!bo->sdev) goto fail_put_hdev; @@ -919,7 +911,6 @@ static int __blkdev_put(struct block_device *bdev, int for_part); static int do_open(struct block_device *bdev, struct file *file, int for_part) { - struct module *owner = NULL; struct gendisk *disk; struct hd_struct *part = NULL; int ret; @@ -941,25 +932,27 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) ret = -ENXIO; file->f_mapping = bdev->bd_inode->i_mapping; + lock_kernel(); + disk = get_gendisk(bdev->bd_dev, &partno); - if (!disk) { - unlock_kernel(); - bdput(bdev); - return ret; - } - owner = disk->fops->owner; + if (!disk) + goto out_unlock_kernel; + part = disk_get_part(disk, partno); + if (!part) + goto out_unlock_kernel; mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { bdev->bd_disk = disk; + bdev->bd_part = part; bdev->bd_contains = bdev; if (!partno) { struct backing_dev_info *bdi; if (disk->fops->open) { ret = disk->fops->open(bdev->bd_inode, file); if (ret) - goto out_first; + goto out_clear; } if (!bdev->bd_openers) { bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); @@ -975,31 +968,32 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) whole = bdget_disk(disk, 0); ret = -ENOMEM; if (!whole) - goto out_first; + goto out_clear; BUG_ON(for_part); ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); if (ret) - goto out_first; + goto out_clear; bdev->bd_contains = whole; - part = disk_get_part(disk, partno); bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; if (!(disk->flags & GENHD_FL_UP) || !part || !part->nr_sects) { ret = -ENXIO; - goto out_first; + goto out_clear; } - bdev->bd_part = part; bd_set_size(bdev, (loff_t)part->nr_sects << 9); } } else { + disk_put_part(part); put_disk(disk); - module_put(owner); + module_put(disk->fops->owner); + part = NULL; + disk = NULL; if (bdev->bd_contains == bdev) { if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev->bd_inode, file); if (ret) - goto out; + goto out_unlock_bdev; } if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); @@ -1012,20 +1006,24 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) unlock_kernel(); return 0; -out_first: + out_clear: bdev->bd_disk = NULL; + bdev->bd_part = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) __blkdev_put(bdev->bd_contains, 1); bdev->bd_contains = NULL; - put_disk(disk); - disk_put_part(part); - module_put(owner); -out: + out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); + out_unlock_kernel: unlock_kernel(); - if (ret) - bdput(bdev); + + disk_put_part(part); + if (disk) + module_put(disk->fops->owner); + put_disk(disk); + bdput(bdev); + return ret; } @@ -1110,11 +1108,8 @@ static int __blkdev_put(struct block_device *bdev, int for_part) put_disk(disk); module_put(owner); - - if (bdev->bd_contains != bdev) { - disk_put_part(bdev->bd_part); - bdev->bd_part = NULL; - } + disk_put_part(bdev->bd_part); + bdev->bd_part = NULL; bdev->bd_disk = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f0f604950ff..87298c0fc8c 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -134,12 +134,7 @@ char *disk_name(struct gendisk *hd, int partno, char *buf) const char *bdevname(struct block_device *bdev, char *buf) { - int partno = 0; - - if (bdev->bd_part) - partno = bdev->bd_part->partno; - - return disk_name(bdev->bd_disk, partno, buf); + return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf); } EXPORT_SYMBOL(bdevname); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 2c0e1b597ab..45a3682b5d8 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -412,7 +412,7 @@ extern void rand_initialize_disk(struct gendisk *disk); static inline sector_t get_start_sect(struct block_device *bdev) { - return bdev->bd_contains == bdev ? 0 : bdev->bd_part->start_sect; + return bdev->bd_part->start_sect; } static inline sector_t get_capacity(struct gendisk *disk) { -- GitLab From eddb2e26b5ee3c5da68ba4bf1921ba20e2097bff Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:13 +0900 Subject: [PATCH 3429/5416] block: kill GENHD_FL_FAIL and use part0->make_it_fail GENHD_FL_FAIL for disk is what make_it_fail is for parts. Kill it and use part0->make_it_fail. Sysfs node handling is unified too. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 5 +++-- block/genhd.c | 30 +----------------------------- fs/partitions/check.c | 10 +++++----- include/linux/genhd.h | 8 +++++++- 4 files changed, 16 insertions(+), 37 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index a4a7c08d2f2..505ec61067d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1273,8 +1273,9 @@ __setup("fail_make_request=", setup_fail_make_request); static int should_fail_request(struct bio *bio) { - if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) || - bio->bi_bdev->bd_part->make_it_fail) + struct hd_struct *part = bio->bi_bdev->bd_part; + + if (part_to_disk(part)->part0.make_it_fail || part->make_it_fail) return should_fail(&fail_make_request, bio->bi_size); return 0; diff --git a/block/genhd.c b/block/genhd.c index 70358f3c742..06a252f2b96 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -795,34 +795,6 @@ static ssize_t disk_stat_show(struct device *dev, jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); } -#ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t disk_fail_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - - return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); -} - -static ssize_t disk_fail_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gendisk *disk = dev_to_disk(dev); - int i; - - if (count > 0 && sscanf(buf, "%d", &i) > 0) { - if (i == 0) - disk->flags &= ~GENHD_FL_FAIL; - else - disk->flags |= GENHD_FL_FAIL; - } - - return count; -} - -#endif - static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); @@ -832,7 +804,7 @@ static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); #ifdef CONFIG_FAIL_MAKE_REQUEST static struct device_attribute dev_attr_fail = - __ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store); + __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); #endif static struct attribute *disk_attrs[] = { diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 87298c0fc8c..60592d9f43b 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -238,17 +238,17 @@ static ssize_t part_stat_show(struct device *dev, } #ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t part_fail_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_fail_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); return sprintf(buf, "%d\n", p->make_it_fail); } -static ssize_t part_fail_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +ssize_t part_fail_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct hd_struct *p = dev_to_part(dev); int i; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 45a3682b5d8..3d15b42dc35 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -112,7 +112,6 @@ struct hd_struct { #define GENHD_FL_CD 8 #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 -#define GENHD_FL_FAIL 64 struct gendisk { /* major, first_minor, minors and ext_minors are input @@ -596,6 +595,13 @@ extern void blk_unregister_region(dev_t devt, unsigned long range); extern ssize_t part_size_show(struct device *dev, struct device_attribute *attr, char *buf); +#ifdef CONFIG_FAIL_MAKE_REQUEST +extern ssize_t part_fail_show(struct device *dev, + struct device_attribute *attr, char *buf); +extern ssize_t part_fail_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +#endif /* CONFIG_FAIL_MAKE_REQUEST */ #else /* CONFIG_BLOCK */ -- GitLab From 074a7aca7afa6f230104e8e65eba3420263714a5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:14 +0900 Subject: [PATCH 3430/5416] block: move stats from disk to part0 Move stats related fields - stamp, in_flight, dkstats - from disk to part0 and unify stat handling such that... * part_stat_*() now updates part0 together if the specified partition is not part0. ie. part_stat_*() are now essentially all_stat_*(). * {disk|all}_stat_*() are gone. * part_round_stats() is updated similary. It handles part0 stats automatically and disk_round_stats() is killed. * part_{inc|dec}_in_fligh() is implemented which automatically updates part0 stats for parts other than part0. * disk_map_sector_rcu() is updated to return part0 if no part matches. Combined with the above changes, this makes NULL special case handling in callers unnecessary. * Separate stats show code paths for disk are collapsed into part stats show code paths. * Rename disk_stat_lock/unlock() to part_stat_lock/unlock() While at it, reposition stat handling macros a bit and add missing parentheses around macro parameters. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 84 ++++++++------------ block/blk-merge.c | 12 +-- block/genhd.c | 97 ++++++---------------- drivers/block/aoe/aoecmd.c | 12 +-- drivers/md/dm.c | 27 ++++--- drivers/md/linear.c | 9 ++- drivers/md/md.c | 4 +- drivers/md/multipath.c | 9 ++- drivers/md/raid0.c | 9 ++- drivers/md/raid1.c | 9 ++- drivers/md/raid10.c | 9 ++- drivers/md/raid5.c | 9 ++- fs/partitions/check.c | 12 +-- include/linux/genhd.h | 159 +++++++++++-------------------------- 14 files changed, 165 insertions(+), 296 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 505ec61067d..98138f00252 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -61,21 +61,17 @@ static void drive_stat_acct(struct request *rq, int new_io) if (!blk_fs_request(rq) || !rq->rq_disk) return; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part = disk_map_sector_rcu(rq->rq_disk, rq->sector); if (!new_io) - all_stat_inc(cpu, rq->rq_disk, part, merges[rw], rq->sector); + part_stat_inc(cpu, part, merges[rw]); else { - disk_round_stats(cpu, rq->rq_disk); - rq->rq_disk->in_flight++; - if (part) { - part_round_stats(cpu, part); - part->in_flight++; - } + part_round_stats(cpu, part); + part_inc_in_flight(part); } - disk_stat_unlock(); + part_stat_unlock(); } void blk_queue_congestion_threshold(struct request_queue *q) @@ -983,8 +979,22 @@ static inline void add_request(struct request_queue *q, struct request *req) __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } -/* - * disk_round_stats() - Round off the performance stats on a struct +static void part_round_stats_single(int cpu, struct hd_struct *part, + unsigned long now) +{ + if (now == part->stamp) + return; + + if (part->in_flight) { + __part_stat_add(cpu, part, time_in_queue, + part->in_flight * (now - part->stamp)); + __part_stat_add(cpu, part, io_ticks, (now - part->stamp)); + } + part->stamp = now; +} + +/** + * part_round_stats() - Round off the performance stats on a struct * disk_stats. * * The average IO queue length and utilisation statistics are maintained @@ -998,36 +1008,15 @@ static inline void add_request(struct request_queue *q, struct request *req) * /proc/diskstats. This accounts immediately for all queue usage up to * the current jiffies and restarts the counters again. */ -void disk_round_stats(int cpu, struct gendisk *disk) -{ - unsigned long now = jiffies; - - if (now == disk->stamp) - return; - - if (disk->in_flight) { - disk_stat_add(cpu, disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); - disk_stat_add(cpu, disk, io_ticks, (now - disk->stamp)); - } - disk->stamp = now; -} -EXPORT_SYMBOL_GPL(disk_round_stats); - void part_round_stats(int cpu, struct hd_struct *part) { unsigned long now = jiffies; - if (now == part->stamp) - return; - - if (part->in_flight) { - part_stat_add(cpu, part, time_in_queue, - part->in_flight * (now - part->stamp)); - part_stat_add(cpu, part, io_ticks, (now - part->stamp)); - } - part->stamp = now; + if (part->partno) + part_round_stats_single(cpu, &part_to_disk(part)->part0, now); + part_round_stats_single(cpu, part, now); } +EXPORT_SYMBOL_GPL(part_round_stats); /* * queue lock must be held @@ -1567,11 +1556,10 @@ static int __end_that_request_first(struct request *req, int error, struct hd_struct *part; int cpu; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part = disk_map_sector_rcu(req->rq_disk, req->sector); - all_stat_add(cpu, req->rq_disk, part, sectors[rw], - nr_bytes >> 9, req->sector); - disk_stat_unlock(); + part_stat_add(cpu, part, sectors[rw], nr_bytes >> 9); + part_stat_unlock(); } total_bytes = bio_nbytes = 0; @@ -1758,19 +1746,15 @@ static void end_that_request_last(struct request *req, int error) struct hd_struct *part; int cpu; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part = disk_map_sector_rcu(disk, req->sector); - all_stat_inc(cpu, disk, part, ios[rw], req->sector); - all_stat_add(cpu, disk, part, ticks[rw], duration, req->sector); - disk_round_stats(cpu, disk); - disk->in_flight--; - if (part) { - part_round_stats(cpu, part); - part->in_flight--; - } + part_stat_inc(cpu, part, ios[rw]); + part_stat_add(cpu, part, ticks[rw], duration); + part_round_stats(cpu, part); + part_dec_in_flight(part); - disk_stat_unlock(); + part_stat_unlock(); } if (req->end_io) diff --git a/block/blk-merge.c b/block/blk-merge.c index d926a24bf1f..c77196d5589 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -390,17 +390,13 @@ static int attempt_merge(struct request_queue *q, struct request *req, struct hd_struct *part; int cpu; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part = disk_map_sector_rcu(req->rq_disk, req->sector); - disk_round_stats(cpu, req->rq_disk); - req->rq_disk->in_flight--; - if (part) { - part_round_stats(cpu, part); - part->in_flight--; - } + part_round_stats(cpu, part); + part_dec_in_flight(part); - disk_stat_unlock(); + part_stat_unlock(); } req->ioprio = ioprio_best(req->ioprio, next->ioprio); diff --git a/block/genhd.c b/block/genhd.c index 06a252f2b96..e1cb96fb883 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -176,7 +176,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit); * while preemption is disabled. * * RETURNS: - * Found partition on success, NULL if there's no matching partition. + * Found partition on success, part0 is returned if no partition matches */ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) { @@ -189,7 +189,7 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) sector < part->start_sect + part->nr_sects) return part; } - return NULL; + return &disk->part0; } EXPORT_SYMBOL_GPL(disk_map_sector_rcu); @@ -580,24 +580,24 @@ void __init printk_all_partitions(void) * numbers in hex - the same format as the root= * option takes. */ - printk("%s %10llu %s", - bdevt_str(disk_devt(disk), devt_buf), - (unsigned long long)get_capacity(disk) >> 1, - disk_name(disk, 0, name_buf)); - if (disk->driverfs_dev != NULL && - disk->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - disk->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); + while ((part = disk_part_iter_next(&piter))) { + bool is_part0 = part == &disk->part0; - /* now show the partitions */ - disk_part_iter_init(&piter, disk, 0); - while ((part = disk_part_iter_next(&piter))) - printk(" %s %10llu %s\n", + printk("%s%s %10llu %s", is_part0 ? "" : " ", bdevt_str(part_devt(part), devt_buf), (unsigned long long)part->nr_sects >> 1, disk_name(disk, part->partno, name_buf)); + if (is_part0) { + if (disk->driverfs_dev != NULL && + disk->driverfs_dev->driver != NULL) + printk(" driver: %s\n", + disk->driverfs_dev->driver->name); + else + printk(" (driver?)\n"); + } else + printk("\n"); + } disk_part_iter_exit(&piter); } class_dev_iter_exit(&iter); @@ -674,12 +674,7 @@ static int show_partition(struct seq_file *seqf, void *v) return 0; /* show the full disk and all non-0 size partitions of it */ - seq_printf(seqf, "%4d %7d %10llu %s\n", - MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)), - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - - disk_part_iter_init(&piter, sgp, 0); + disk_part_iter_init(&piter, sgp, DISK_PITER_INCL_PART0); while ((part = disk_part_iter_next(&piter))) seq_printf(seqf, "%4d %7d %10llu %s\n", MAJOR(part_devt(part)), MINOR(part_devt(part)), @@ -768,40 +763,13 @@ static ssize_t disk_capability_show(struct device *dev, return sprintf(buf, "%x\n", disk->flags); } -static ssize_t disk_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - int cpu; - - cpu = disk_stat_lock(); - disk_round_stats(cpu, disk); - disk_stat_unlock(); - return sprintf(buf, - "%8lu %8lu %8llu %8u " - "%8lu %8lu %8llu %8u " - "%8u %8u %8u" - "\n", - disk_stat_read(disk, ios[READ]), - disk_stat_read(disk, merges[READ]), - (unsigned long long)disk_stat_read(disk, sectors[READ]), - jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), - disk_stat_read(disk, ios[WRITE]), - disk_stat_read(disk, merges[WRITE]), - (unsigned long long)disk_stat_read(disk, sectors[WRITE]), - jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), - disk->in_flight, - jiffies_to_msecs(disk_stat_read(disk, io_ticks)), - jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); -} - static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); -static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); +static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); #ifdef CONFIG_FAIL_MAKE_REQUEST static struct device_attribute dev_attr_fail = __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); @@ -836,7 +804,7 @@ static void disk_release(struct device *dev) kfree(disk->random); kfree(disk->__part); - free_disk_stats(disk); + free_part_stats(&disk->part0); kfree(disk); } struct class block_class = { @@ -873,28 +841,11 @@ static int diskstats_show(struct seq_file *seqf, void *v) "\n\n"); */ - cpu = disk_stat_lock(); - disk_round_stats(cpu, gp); - disk_stat_unlock(); - seq_printf(seqf, "%4d %7d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", - MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)), - disk_name(gp, 0, buf), - disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), - (unsigned long long)disk_stat_read(gp, sectors[0]), - jiffies_to_msecs(disk_stat_read(gp, ticks[0])), - disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), - (unsigned long long)disk_stat_read(gp, sectors[1]), - jiffies_to_msecs(disk_stat_read(gp, ticks[1])), - gp->in_flight, - jiffies_to_msecs(disk_stat_read(gp, io_ticks)), - jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); - - /* now show all non-0 size partitions of it */ - disk_part_iter_init(&piter, gp, 0); + disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0); while ((hd = disk_part_iter_next(&piter))) { - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part_round_stats(cpu, hd); - disk_stat_unlock(); + part_stat_unlock(); seq_printf(seqf, "%4d %7d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", MAJOR(part_devt(hd)), MINOR(part_devt(hd)), @@ -1000,7 +951,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) int tot_minors = minors + ext_minors; int size = tot_minors * sizeof(struct hd_struct *); - if (!init_disk_stats(disk)) { + if (!init_part_stats(&disk->part0)) { kfree(disk); return NULL; } @@ -1008,7 +959,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, node_id); if (!disk->__part) { - free_disk_stats(disk); + free_part_stats(&disk->part0); kfree(disk); return NULL; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 934800f979c..961d29a53ca 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -758,15 +758,15 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector struct hd_struct *part; int cpu; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part = disk_map_sector_rcu(disk, sector); - all_stat_inc(cpu, disk, part, ios[rw], sector); - all_stat_add(cpu, disk, part, ticks[rw], duration, sector); - all_stat_add(cpu, disk, part, sectors[rw], n_sect, sector); - all_stat_add(cpu, disk, part, io_ticks, duration, sector); + part_stat_inc(cpu, part, ios[rw]); + part_stat_add(cpu, part, ticks[rw], duration); + part_stat_add(cpu, part, sectors[rw], n_sect); + part_stat_add(cpu, part, io_ticks, duration); - disk_stat_unlock(); + part_stat_unlock(); } void diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 637806695bb..327de03a5bd 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -381,10 +381,10 @@ static void start_io_acct(struct dm_io *io) io->start_time = jiffies; - cpu = disk_stat_lock(); - disk_round_stats(cpu, dm_disk(md)); - disk_stat_unlock(); - dm_disk(md)->in_flight = atomic_inc_return(&md->pending); + cpu = part_stat_lock(); + part_round_stats(cpu, &dm_disk(md)->part0); + part_stat_unlock(); + dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending); } static int end_io_acct(struct dm_io *io) @@ -395,12 +395,13 @@ static int end_io_acct(struct dm_io *io) int pending, cpu; int rw = bio_data_dir(bio); - cpu = disk_stat_lock(); - disk_round_stats(cpu, dm_disk(md)); - disk_stat_add(cpu, dm_disk(md), ticks[rw], duration); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_round_stats(cpu, &dm_disk(md)->part0); + part_stat_add(cpu, &dm_disk(md)->part0, ticks[rw], duration); + part_stat_unlock(); - dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + dm_disk(md)->part0.in_flight = pending = + atomic_dec_return(&md->pending); return !pending; } @@ -899,10 +900,10 @@ static int dm_request(struct request_queue *q, struct bio *bio) down_read(&md->io_lock); - cpu = disk_stat_lock(); - disk_stat_inc(cpu, dm_disk(md), ios[rw]); - disk_stat_add(cpu, dm_disk(md), sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &dm_disk(md)->part0, ios[rw]); + part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio)); + part_stat_unlock(); /* * If we're suspended we have to queue diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 00cbc8e4729..c80ea90593d 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -325,10 +325,11 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) return 0; } - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); tmp_dev = which_dev(mddev, bio->bi_sector); block = bio->bi_sector >> 1; diff --git a/drivers/md/md.c b/drivers/md/md.c index 2bd9cf41612..0a3a4bdcd4a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5546,8 +5546,8 @@ static int is_mddev_idle(mddev_t *mddev) rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) { struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events = disk_stat_read(disk, sectors[0]) + - disk_stat_read(disk, sectors[1]) - + curr_events = part_stat_read(&disk->part0, sectors[0]) + + part_stat_read(&disk->part0, sectors[1]) - atomic_read(&disk->sync_io); /* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 182f5a94cdc..8bb8794129b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -159,10 +159,11 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->master_bio = bio; mp_bh->mddev = mddev; - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index e26030fa59a..f52f442a735 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -406,10 +406,11 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) return 0; } - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); chunk_size = mddev->chunk_size >> 10; chunk_sects = mddev->chunk_size >> 9; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index babb13036f9..b9764429d85 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -804,10 +804,11 @@ static int make_request(struct request_queue *q, struct bio * bio) bitmap = mddev->bitmap; - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); /* * make_request() can abort the operation when READA is being diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5ec80da0a9d..5f990133f5e 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -844,10 +844,11 @@ static int make_request(struct request_queue *q, struct bio * bio) */ wait_barrier(conf); - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bio)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5899f211515..ae16794bef2 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3396,10 +3396,11 @@ static int make_request(struct request_queue *q, struct bio * bi) md_write_start(mddev, bi); - cpu = disk_stat_lock(); - disk_stat_inc(cpu, mddev->gendisk, ios[rw]); - disk_stat_add(cpu, mddev->gendisk, sectors[rw], bio_sectors(bi)); - disk_stat_unlock(); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bi)); + part_stat_unlock(); if (rw == READ && mddev->reshape_position == MaxSector && diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 60592d9f43b..f517869e8d1 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -210,15 +210,15 @@ ssize_t part_size_show(struct device *dev, return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); } -static ssize_t part_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); int cpu; - cpu = disk_stat_lock(); + cpu = part_stat_lock(); part_round_stats(cpu, p); - disk_stat_unlock(); + part_stat_unlock(); return sprintf(buf, "%8lu %8lu %8llu %8u " "%8lu %8lu %8llu %8u " @@ -575,8 +575,8 @@ void del_gendisk(struct gendisk *disk) set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; unlink_gendisk(disk); - disk_stat_set_all(disk, 0); - disk->stamp = 0; + part_stat_set_all(&disk->part0, 0); + disk->part0.stamp = 0; kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 3d15b42dc35..c90e1b4fbe5 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -145,13 +145,6 @@ struct gendisk { struct timer_rand_state *random; atomic_t sync_io; /* RAID */ - unsigned long stamp; - int in_flight; -#ifdef CONFIG_SMP - struct disk_stats *dkstats; -#else - struct disk_stats dkstats; -#endif struct work_struct async_notify; #ifdef CONFIG_BLK_DEV_INTEGRITY struct blk_integrity *integrity; @@ -232,46 +225,18 @@ extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, * internal use only. */ #ifdef CONFIG_SMP -#define disk_stat_lock() ({ rcu_read_lock(); get_cpu(); }) -#define disk_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0) - -#define disk_stat_add(cpu, gendiskp, field, addnd) \ - (per_cpu_ptr(gendiskp->dkstats, cpu)->field += addnd) - -#define disk_stat_read(gendiskp, field) \ -({ \ - typeof(gendiskp->dkstats->field) res = 0; \ - int i; \ - for_each_possible_cpu(i) \ - res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ - res; \ -}) - -static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) -{ - int i; - - for_each_possible_cpu(i) - memset(per_cpu_ptr(gendiskp->dkstats, i), value, - sizeof(struct disk_stats)); -} +#define part_stat_lock() ({ rcu_read_lock(); get_cpu(); }) +#define part_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0) -#define part_stat_add(cpu, part, field, addnd) \ - (per_cpu_ptr(part->dkstats, cpu)->field += addnd) - -#define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - part_stat_add(cpu, part, field, addnd); \ - disk_stat_add(cpu, gendiskp, field, addnd); \ -}) +#define __part_stat_add(cpu, part, field, addnd) \ + (per_cpu_ptr((part)->dkstats, (cpu))->field += (addnd)) #define part_stat_read(part, field) \ ({ \ - typeof(part->dkstats->field) res = 0; \ + typeof((part)->dkstats->field) res = 0; \ int i; \ for_each_possible_cpu(i) \ - res += per_cpu_ptr(part->dkstats, i)->field; \ + res += per_cpu_ptr((part)->dkstats, i)->field; \ res; \ }) @@ -284,109 +249,73 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) sizeof(struct disk_stats)); } -#else /* !CONFIG_SMP */ -#define disk_stat_lock() ({ rcu_read_lock(); 0; }) -#define disk_stat_unlock() rcu_read_unlock() - -#define disk_stat_add(cpu, gendiskp, field, addnd) \ - (gendiskp->dkstats.field += addnd) -#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) - -static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) +static inline int init_part_stats(struct hd_struct *part) { - memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); + part->dkstats = alloc_percpu(struct disk_stats); + if (!part->dkstats) + return 0; + return 1; } -#define part_stat_add(cpu, part, field, addnd) \ - (part->dkstats.field += addnd) - -#define all_stat_add(cpu, gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - part_stat_add(cpu, part, field, addnd); \ - disk_stat_add(cpu, gendiskp, field, addnd); \ -}) - -#define part_stat_read(part, field) (part->dkstats.field) - -static inline void part_stat_set_all(struct hd_struct *part, int value) +static inline void free_part_stats(struct hd_struct *part) { - memset(&part->dkstats, value, sizeof(struct disk_stats)); + free_percpu(part->dkstats); } -#endif /* CONFIG_SMP */ - -#define disk_stat_dec(cpu, gendiskp, field) \ - disk_stat_add(cpu, gendiskp, field, -1) -#define disk_stat_inc(cpu, gendiskp, field) \ - disk_stat_add(cpu, gendiskp, field, 1) -#define disk_stat_sub(cpu, gendiskp, field, subnd) \ - disk_stat_add(cpu, gendiskp, field, -subnd) - -#define part_stat_dec(cpu, gendiskp, field) \ - part_stat_add(cpu, gendiskp, field, -1) -#define part_stat_inc(cpu, gendiskp, field) \ - part_stat_add(cpu, gendiskp, field, 1) -#define part_stat_sub(cpu, gendiskp, field, subnd) \ - part_stat_add(cpu, gendiskp, field, -subnd) +#else /* !CONFIG_SMP */ +#define part_stat_lock() ({ rcu_read_lock(); 0; }) +#define part_stat_unlock() rcu_read_unlock() -#define all_stat_dec(cpu, gendiskp, field, sector) \ - all_stat_add(cpu, gendiskp, field, -1, sector) -#define all_stat_inc(cpu, gendiskp, part, field, sector) \ - all_stat_add(cpu, gendiskp, part, field, 1, sector) -#define all_stat_sub(cpu, gendiskp, part, field, subnd, sector) \ - all_stat_add(cpu, gendiskp, part, field, -subnd, sector) +#define __part_stat_add(cpu, part, field, addnd) \ + ((part)->dkstats.field += addnd) -/* Inlines to alloc and free disk stats in struct gendisk */ -#ifdef CONFIG_SMP -static inline int init_disk_stats(struct gendisk *disk) -{ - disk->dkstats = alloc_percpu(struct disk_stats); - if (!disk->dkstats) - return 0; - return 1; -} +#define part_stat_read(part, field) ((part)->dkstats.field) -static inline void free_disk_stats(struct gendisk *disk) +static inline void part_stat_set_all(struct hd_struct *part, int value) { - free_percpu(disk->dkstats); + memset(&part->dkstats, value, sizeof(struct disk_stats)); } static inline int init_part_stats(struct hd_struct *part) { - part->dkstats = alloc_percpu(struct disk_stats); - if (!part->dkstats) - return 0; return 1; } static inline void free_part_stats(struct hd_struct *part) { - free_percpu(part->dkstats); } -#else /* CONFIG_SMP */ -static inline int init_disk_stats(struct gendisk *disk) -{ - return 1; -} +#endif /* CONFIG_SMP */ -static inline void free_disk_stats(struct gendisk *disk) -{ -} +#define part_stat_add(cpu, part, field, addnd) do { \ + __part_stat_add((cpu), (part), field, addnd); \ + if ((part)->partno) \ + __part_stat_add((cpu), &part_to_disk((part))->part0, \ + field, addnd); \ +} while (0) -static inline int init_part_stats(struct hd_struct *part) +#define part_stat_dec(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, -1) +#define part_stat_inc(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, 1) +#define part_stat_sub(cpu, gendiskp, field, subnd) \ + part_stat_add(cpu, gendiskp, field, -subnd) + +static inline void part_inc_in_flight(struct hd_struct *part) { - return 1; + part->in_flight++; + if (part->partno) + part_to_disk(part)->part0.in_flight++; } -static inline void free_part_stats(struct hd_struct *part) +static inline void part_dec_in_flight(struct hd_struct *part) { + part->in_flight--; + if (part->partno) + part_to_disk(part)->part0.in_flight--; } -#endif /* CONFIG_SMP */ /* drivers/block/ll_rw_blk.c */ -extern void disk_round_stats(int cpu, struct gendisk *disk); extern void part_round_stats(int cpu, struct hd_struct *part); /* drivers/block/genhd.c */ @@ -595,6 +524,8 @@ extern void blk_unregister_region(dev_t devt, unsigned long range); extern ssize_t part_size_show(struct device *dev, struct device_attribute *attr, char *buf); +extern ssize_t part_stat_show(struct device *dev, + struct device_attribute *attr, char *buf); #ifdef CONFIG_FAIL_MAKE_REQUEST extern ssize_t part_fail_show(struct device *dev, struct device_attribute *attr, char *buf); -- GitLab From 540eed5637b766bb1e881ef744c42617760b4815 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:15 +0900 Subject: [PATCH 3431/5416] block: make partition array dynamic disk->__part used to be statically allocated to the maximum possible number of partitions. This patch makes partition array allocation dynamic. The added overhead is minimal as only real change is one memory dereference changed to RCU one. This saves both a bit of memory and cpu cycles iterating through unoccupied slots and makes increasing partition limit easier. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 129 +++++++++++++++++++++++++++++++++++------- block/ioctl.c | 2 +- fs/partitions/check.c | 31 ++++++++-- include/linux/genhd.h | 19 ++++++- 4 files changed, 154 insertions(+), 27 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index e1cb96fb883..c2b14aa69d5 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -52,14 +52,21 @@ static struct device_type disk_type; */ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) { - struct hd_struct *part; + struct hd_struct *part = NULL; + struct disk_part_tbl *ptbl; - if (unlikely(partno < 0 || partno >= disk_max_parts(disk))) + if (unlikely(partno < 0)) return NULL; + rcu_read_lock(); - part = rcu_dereference(disk->__part[partno]); - if (part) - get_device(part_to_dev(part)); + + ptbl = rcu_dereference(disk->part_tbl); + if (likely(partno < ptbl->len)) { + part = rcu_dereference(ptbl->part[partno]); + if (part) + get_device(part_to_dev(part)); + } + rcu_read_unlock(); return part; @@ -80,17 +87,24 @@ EXPORT_SYMBOL_GPL(disk_get_part); void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, unsigned int flags) { + struct disk_part_tbl *ptbl; + + rcu_read_lock(); + ptbl = rcu_dereference(disk->part_tbl); + piter->disk = disk; piter->part = NULL; if (flags & DISK_PITER_REVERSE) - piter->idx = disk_max_parts(piter->disk) - 1; + piter->idx = ptbl->len - 1; else if (flags & DISK_PITER_INCL_PART0) piter->idx = 0; else piter->idx = 1; piter->flags = flags; + + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(disk_part_iter_init); @@ -105,13 +119,16 @@ EXPORT_SYMBOL_GPL(disk_part_iter_init); */ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) { + struct disk_part_tbl *ptbl; int inc, end; /* put the last partition */ disk_put_part(piter->part); piter->part = NULL; + /* get part_tbl */ rcu_read_lock(); + ptbl = rcu_dereference(piter->disk->part_tbl); /* determine iteration parameters */ if (piter->flags & DISK_PITER_REVERSE) { @@ -122,14 +139,14 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) end = 0; } else { inc = 1; - end = disk_max_parts(piter->disk); + end = ptbl->len; } /* iterate to the next partition */ for (; piter->idx != end; piter->idx += inc) { struct hd_struct *part; - part = rcu_dereference(piter->disk->__part[piter->idx]); + part = rcu_dereference(ptbl->part[piter->idx]); if (!part) continue; if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) @@ -180,10 +197,13 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit); */ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) { + struct disk_part_tbl *ptbl; int i; - for (i = 1; i < disk_max_parts(disk); i++) { - struct hd_struct *part = rcu_dereference(disk->__part[i]); + ptbl = rcu_dereference(disk->part_tbl); + + for (i = 1; i < ptbl->len; i++) { + struct hd_struct *part = rcu_dereference(ptbl->part[i]); if (part && part->start_sect <= sector && sector < part->start_sect + part->nr_sects) @@ -798,12 +818,86 @@ static struct attribute_group *disk_attr_groups[] = { NULL }; +static void disk_free_ptbl_rcu_cb(struct rcu_head *head) +{ + struct disk_part_tbl *ptbl = + container_of(head, struct disk_part_tbl, rcu_head); + + kfree(ptbl); +} + +/** + * disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way + * @disk: disk to replace part_tbl for + * @new_ptbl: new part_tbl to install + * + * Replace disk->part_tbl with @new_ptbl in RCU-safe way. The + * original ptbl is freed using RCU callback. + * + * LOCKING: + * Matching bd_mutx locked. + */ +static void disk_replace_part_tbl(struct gendisk *disk, + struct disk_part_tbl *new_ptbl) +{ + struct disk_part_tbl *old_ptbl = disk->part_tbl; + + rcu_assign_pointer(disk->part_tbl, new_ptbl); + if (old_ptbl) + call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); +} + +/** + * disk_expand_part_tbl - expand disk->part_tbl + * @disk: disk to expand part_tbl for + * @partno: expand such that this partno can fit in + * + * Expand disk->part_tbl such that @partno can fit in. disk->part_tbl + * uses RCU to allow unlocked dereferencing for stats and other stuff. + * + * LOCKING: + * Matching bd_mutex locked, might sleep. + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int disk_expand_part_tbl(struct gendisk *disk, int partno) +{ + struct disk_part_tbl *old_ptbl = disk->part_tbl; + struct disk_part_tbl *new_ptbl; + int len = old_ptbl ? old_ptbl->len : 0; + int target = partno + 1; + size_t size; + int i; + + /* disk_max_parts() is zero during initialization, ignore if so */ + if (disk_max_parts(disk) && target > disk_max_parts(disk)) + return -EINVAL; + + if (target <= len) + return 0; + + size = sizeof(*new_ptbl) + target * sizeof(new_ptbl->part[0]); + new_ptbl = kzalloc_node(size, GFP_KERNEL, disk->node_id); + if (!new_ptbl) + return -ENOMEM; + + INIT_RCU_HEAD(&new_ptbl->rcu_head); + new_ptbl->len = target; + + for (i = 0; i < len; i++) + rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]); + + disk_replace_part_tbl(disk, new_ptbl); + return 0; +} + static void disk_release(struct device *dev) { struct gendisk *disk = dev_to_disk(dev); kfree(disk->random); - kfree(disk->__part); + disk_replace_part_tbl(disk, NULL); free_part_stats(&disk->part0); kfree(disk); } @@ -948,22 +1042,16 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL | __GFP_ZERO, node_id); if (disk) { - int tot_minors = minors + ext_minors; - int size = tot_minors * sizeof(struct hd_struct *); - if (!init_part_stats(&disk->part0)) { kfree(disk); return NULL; } - - disk->__part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, - node_id); - if (!disk->__part) { - free_part_stats(&disk->part0); + if (disk_expand_part_tbl(disk, 0)) { + free_part_stats(&disk->part0); kfree(disk); return NULL; } - disk->__part[0] = &disk->part0; + disk->part_tbl->part[0] = &disk->part0; disk->minors = minors; disk->ext_minors = ext_minors; @@ -973,6 +1061,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) device_initialize(disk_to_dev(disk)); INIT_WORK(&disk->async_notify, media_change_notify_thread); + disk->node_id = node_id; } return disk; } diff --git a/block/ioctl.c b/block/ioctl.c index 64e7c67a64b..38bee321e1f 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -30,7 +30,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user if (bdev != bdev->bd_contains) return -EINVAL; partno = p.pno; - if (partno <= 0 || partno >= disk_max_parts(disk)) + if (partno <= 0) return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f517869e8d1..772b2ed8d23 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -312,14 +312,18 @@ static void delete_partition_rcu_cb(struct rcu_head *head) void delete_partition(struct gendisk *disk, int partno) { + struct disk_part_tbl *ptbl = disk->part_tbl; struct hd_struct *part; - part = disk->__part[partno]; + if (partno >= ptbl->len) + return; + + part = ptbl->part[partno]; if (!part) return; blk_free_devt(part_devt(part)); - rcu_assign_pointer(disk->__part[partno], NULL); + rcu_assign_pointer(ptbl->part[partno], NULL); kobject_put(part->holder_dir); device_del(part_to_dev(part)); @@ -341,10 +345,16 @@ int add_partition(struct gendisk *disk, int partno, dev_t devt = MKDEV(0, 0); struct device *ddev = disk_to_dev(disk); struct device *pdev; + struct disk_part_tbl *ptbl; const char *dname; int err; - if (disk->__part[partno]) + err = disk_expand_part_tbl(disk, partno); + if (err) + return err; + ptbl = disk->part_tbl; + + if (ptbl->part[partno]) return -EBUSY; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -398,7 +408,7 @@ int add_partition(struct gendisk *disk, int partno, /* everything is up and running, commence */ INIT_RCU_HEAD(&p->rcu_head); - rcu_assign_pointer(disk->__part[partno], p); + rcu_assign_pointer(ptbl->part[partno], p); /* suppress uevent if the disk supresses it */ if (!ddev->uevent_suppress) @@ -487,7 +497,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) struct disk_part_iter piter; struct hd_struct *part; struct parsed_partitions *state; - int p, res; + int p, highest, res; if (bdev->bd_part_count) return -EBUSY; @@ -511,6 +521,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) /* tell userspace that the media / partition table may have changed */ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); + /* Detect the highest partition number and preallocate + * disk->part_tbl. This is an optimization and not strictly + * necessary. + */ + for (p = 1, highest = 0; p < state->limit; p++) + if (state->parts[p].size) + highest = p; + + disk_expand_part_tbl(disk, highest); + + /* add partitions */ for (p = 1; p < state->limit; p++) { sector_t size = state->parts[p].size; sector_t from = state->parts[p].from; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c90e1b4fbe5..ecf649c3dee 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -113,6 +113,21 @@ struct hd_struct { #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +#define BLK_SCSI_MAX_CMDS (256) +#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) + +struct blk_scsi_cmd_filter { + unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; + unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; + struct kobject kobj; +}; + +struct disk_part_tbl { + struct rcu_head rcu_head; + int len; + struct hd_struct *part[]; +}; + struct gendisk { /* major, first_minor, minors and ext_minors are input * parameters only, don't use directly. Use disk_devt() and @@ -131,7 +146,7 @@ struct gendisk { * non-critical accesses use RCU. Always access through * helpers. */ - struct hd_struct **__part; + struct disk_part_tbl *part_tbl; struct hd_struct part0; struct block_device_operations *fops; @@ -149,6 +164,7 @@ struct gendisk { #ifdef CONFIG_BLK_DEV_INTEGRITY struct blk_integrity *integrity; #endif + int node_id; }; static inline struct gendisk *part_to_disk(struct hd_struct *part) @@ -503,6 +519,7 @@ extern void blk_free_devt(dev_t devt); extern dev_t blk_lookup_devt(const char *name, int partno); extern char *disk_name (struct gendisk *hd, int partno, char *buf); +extern int disk_expand_part_tbl(struct gendisk *disk, int target); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int); extern void delete_partition(struct gendisk *, int); -- GitLab From 689d6fac40b41c7bf154f362deaf442548e4dc81 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:16 +0900 Subject: [PATCH 3432/5416] block: replace @ext_minors with GENHD_FL_EXT_DEVT With previous changes, it's meaningless to limit the number of partitions. Replace @ext_minors with GENHD_FL_EXT_DEVT such that setting the flag allows the disk to have maximum number of allowed partitions (only limited by the number of entries in parsed_partitions as determined by MAX_PART constant). This kills not-too-pretty alloc_disk_ext[_node]() functions and makes @minors parameter to alloc_disk[_node]() unnecessary. The parameter is left alone to avoid disturbing the users. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 16 +--------------- drivers/ide/ide-disk.c | 14 +++++--------- drivers/scsi/sd.c | 9 ++------- fs/partitions/check.h | 4 +--- include/linux/genhd.h | 16 ++++++++-------- 5 files changed, 17 insertions(+), 42 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index c2b14aa69d5..eedab5b4685 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1024,18 +1024,9 @@ struct gendisk *alloc_disk(int minors) { return alloc_disk_node(minors, -1); } +EXPORT_SYMBOL(alloc_disk); struct gendisk *alloc_disk_node(int minors, int node_id) -{ - return alloc_disk_ext_node(minors, 0, node_id); -} - -struct gendisk *alloc_disk_ext(int minors, int ext_minors) -{ - return alloc_disk_ext_node(minors, ext_minors, -1); -} - -struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) { struct gendisk *disk; @@ -1054,7 +1045,6 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) disk->part_tbl->part[0] = &disk->part0; disk->minors = minors; - disk->ext_minors = ext_minors; rand_initialize_disk(disk); disk_to_dev(disk)->class = &block_class; disk_to_dev(disk)->type = &disk_type; @@ -1065,11 +1055,7 @@ struct gendisk *alloc_disk_ext_node(int minors, int ext_minors, int node_id) } return disk; } - -EXPORT_SYMBOL(alloc_disk); EXPORT_SYMBOL(alloc_disk_node); -EXPORT_SYMBOL(alloc_disk_ext); -EXPORT_SYMBOL(alloc_disk_ext_node); struct kobject *get_disk(struct gendisk *disk) { diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a072df5053a..29c8ae75268 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -41,16 +41,12 @@ #include #include -#define IDE_DISK_PARTS (1 << PARTN_BITS) - #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) -#define IDE_DISK_MINORS IDE_DISK_PARTS +#define IDE_DISK_MINORS (1 << PARTN_BITS) #else #define IDE_DISK_MINORS 1 #endif -#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) - struct ide_disk_obj { ide_drive_t *drive; ide_driver_t *driver; @@ -1161,8 +1157,7 @@ static int ide_disk_probe(ide_drive_t *drive) if (!idkp) goto failed; - g = alloc_disk_ext_node(IDE_DISK_MINORS, IDE_DISK_EXT_MINORS, - hwif_to_node(drive->hwif)); + g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; @@ -1189,9 +1184,10 @@ static int ide_disk_probe(ide_drive_t *drive) drive->attach = 1; g->minors = IDE_DISK_MINORS; - g->ext_minors = IDE_DISK_EXT_MINORS; g->driverfs_dev = &drive->gendev; - g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; + g->flags |= GENHD_FL_EXT_DEVT; + if (drive->removable) + g->flags |= GENHD_FL_REMOVABLE; set_capacity(g, idedisk_capacity(drive)); g->fops = &idedisk_ops; add_disk(g); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 280d231a86e..6598024531d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -86,16 +86,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); -#define SD_PARTS 64 - #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define SD_MINORS 16 #else #define SD_MINORS 1 #endif -#define SD_EXT_MINORS (SD_PARTS - SD_MINORS) - static int sd_revalidate_disk(struct gendisk *); static int sd_probe(struct device *); static int sd_remove(struct device *); @@ -1811,7 +1807,7 @@ static int sd_probe(struct device *dev) if (!sdkp) goto out; - gd = alloc_disk_ext(SD_MINORS, SD_EXT_MINORS); + gd = alloc_disk(SD_MINORS); if (!gd) goto out_free; @@ -1856,7 +1852,6 @@ static int sd_probe(struct device *dev) gd->major = sd_major((index & 0xf0) >> 4); gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); gd->minors = SD_MINORS; - gd->ext_minors = SD_EXT_MINORS; gd->fops = &sd_fops; if (index < 26) { @@ -1880,7 +1875,7 @@ static int sd_probe(struct device *dev) blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); gd->driverfs_dev = &sdp->sdev_gendev; - gd->flags = GENHD_FL_DRIVERFS; + gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; diff --git a/fs/partitions/check.h b/fs/partitions/check.h index 17ae8ecd9e8..98dbe1a8452 100644 --- a/fs/partitions/check.h +++ b/fs/partitions/check.h @@ -5,15 +5,13 @@ * add_gd_partition adds a partitions details to the devices partition * description. */ -enum { MAX_PART = 256 }; - struct parsed_partitions { char name[BDEVNAME_SIZE]; struct { sector_t from; sector_t size; int flags; - } parts[MAX_PART]; + } parts[DISK_MAX_PARTS]; int next; int limit; }; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index ecf649c3dee..04524c213de 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -58,6 +58,8 @@ enum { UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ }; +#define DISK_MAX_PARTS 256 + #include #include #include @@ -112,6 +114,7 @@ struct hd_struct { #define GENHD_FL_CD 8 #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 +#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ #define BLK_SCSI_MAX_CMDS (256) #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) @@ -129,15 +132,13 @@ struct disk_part_tbl { }; struct gendisk { - /* major, first_minor, minors and ext_minors are input - * parameters only, don't use directly. Use disk_devt() and - * disk_max_parts(). + /* major, first_minor and minors are input parameters only, + * don't use directly. Use disk_devt() and disk_max_parts(). */ int major; /* major number of driver */ int first_minor; int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ - int ext_minors; /* number of extended dynamic minors */ char disk_name[32]; /* name of major driver */ @@ -180,7 +181,9 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) static inline int disk_max_parts(struct gendisk *disk) { - return disk->minors + disk->ext_minors; + if (disk->flags & GENHD_FL_EXT_DEVT) + return DISK_MAX_PARTS; + return disk->minors; } static inline bool disk_partitionable(struct gendisk *disk) @@ -527,9 +530,6 @@ extern void printk_all_partitions(void); extern struct gendisk *alloc_disk_node(int minors, int node_id); extern struct gendisk *alloc_disk(int minors); -extern struct gendisk *alloc_disk_ext_node(int minors, int ext_minrs, - int node_id); -extern struct gendisk *alloc_disk_ext(int minors, int ext_minors); extern struct kobject *get_disk(struct gendisk *disk); extern void put_disk(struct gendisk *disk); extern void blk_register_region(dev_t devt, unsigned long range, -- GitLab From 3e1a7ff8a0a7b948f2684930166954f9e8e776fe Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 25 Aug 2008 19:56:17 +0900 Subject: [PATCH 3433/5416] block: allow disk to have extended device number Now that disk and partition handlings are mostly unified, it's easy to allow disk to have extended device number. This patch makes add_disk() use extended device number if disk->minors is zero. Both sd and ide-disk are updated to use this. * sd_format_disk_name() is implemented which can generically determine the drive name. This removes disk number restriction stemming from limited device names. * If sd index goes over SD_MAX_DISKS (which can be increased now BTW), sd simply doesn't initialize minors letting block layer choose extended device number. * If CONFIG_DEBUG_EXT_DEVT is set, both sd and ide-disk always set minors to 0 and use extended device numbers. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 25 +++++++++++++- drivers/ide/ide-disk.c | 2 +- drivers/scsi/sd.c | 74 ++++++++++++++++++++++++++++++------------ fs/partitions/check.c | 1 + include/linux/genhd.h | 3 +- 5 files changed, 82 insertions(+), 23 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index eedab5b4685..d9de3e482d1 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -478,14 +478,37 @@ static int exact_lock(dev_t devt, void *data) * * This function registers the partitioning information in @disk * with the kernel. + * + * FIXME: error handling */ void add_disk(struct gendisk *disk) { struct backing_dev_info *bdi; + dev_t devt; int retval; + /* minors == 0 indicates to use ext devt from part0 and should + * be accompanied with EXT_DEVT flag. Make sure all + * parameters make sense. + */ + WARN_ON(disk->minors && !(disk->major || disk->first_minor)); + WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT)); + disk->flags |= GENHD_FL_UP; - disk_to_dev(disk)->devt = MKDEV(disk->major, disk->first_minor); + + retval = blk_alloc_devt(&disk->part0, &devt); + if (retval) { + WARN_ON(1); + return; + } + disk_to_dev(disk)->devt = devt; + + /* ->major and ->first_minor aren't supposed to be + * dereferenced from here on, but set them just in case. + */ + disk->major = MAJOR(devt); + disk->first_minor = MINOR(devt); + blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); register_disk(disk); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 29c8ae75268..33ea8c04871 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -44,7 +44,7 @@ #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define IDE_DISK_MINORS (1 << PARTN_BITS) #else -#define IDE_DISK_MINORS 1 +#define IDE_DISK_MINORS 0 #endif struct ide_disk_obj { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6598024531d..bcb04b2a767 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -89,7 +89,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) #define SD_MINORS 16 #else -#define SD_MINORS 1 +#define SD_MINORS 0 #endif static int sd_revalidate_disk(struct gendisk *); @@ -1769,6 +1769,52 @@ static int sd_revalidate_disk(struct gendisk *disk) return 0; } +/** + * sd_format_disk_name - format disk name + * @prefix: name prefix - ie. "sd" for SCSI disks + * @index: index of the disk to format name for + * @buf: output buffer + * @buflen: length of the output buffer + * + * SCSI disk names starts at sda. The 26th device is sdz and the + * 27th is sdaa. The last one for two lettered suffix is sdzz + * which is followed by sdaaa. + * + * This is basically 26 base counting with one extra 'nil' entry + * at the beggining from the second digit on and can be + * determined using similar method as 26 base conversion with the + * index shifted -1 after each digit is computed. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) +{ + const int base = 'z' - 'a' + 1; + char *begin = buf + strlen(prefix); + char *end = buf + buflen; + char *p; + int unit; + + p = end - 1; + *p = '\0'; + unit = base; + do { + if (p == begin) + return -EINVAL; + *--p = 'a' + (index % unit); + index = (index / unit) - 1; + } while (index >= 0); + + memmove(begin, p, end - p); + memcpy(buf, prefix, strlen(prefix)); + + return 0; +} + /** * sd_probe - called during driver initialization and whenever a * new scsi device is attached to the system. It is called once @@ -1821,8 +1867,8 @@ static int sd_probe(struct device *dev) if (error) goto out_put; - error = -EBUSY; - if (index >= SD_MAX_DISKS) + error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); + if (error) goto out_free_index; sdkp->device = sdp; @@ -1849,24 +1895,12 @@ static int sd_probe(struct device *dev) get_device(&sdp->sdev_gendev); - gd->major = sd_major((index & 0xf0) >> 4); - gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); - gd->minors = SD_MINORS; - gd->fops = &sd_fops; - - if (index < 26) { - sprintf(gd->disk_name, "sd%c", 'a' + index % 26); - } else if (index < (26 + 1) * 26) { - sprintf(gd->disk_name, "sd%c%c", - 'a' + index / 26 - 1,'a' + index % 26); - } else { - const unsigned int m1 = (index / 26 - 1) / 26 - 1; - const unsigned int m2 = (index / 26 - 1) % 26; - const unsigned int m3 = index % 26; - sprintf(gd->disk_name, "sd%c%c%c", - 'a' + m1, 'a' + m2, 'a' + m3); + if (index < SD_MAX_DISKS) { + gd->major = sd_major((index & 0xf0) >> 4); + gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); + gd->minors = SD_MINORS; } - + gd->fops = &sd_fops; gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 772b2ed8d23..0e411603fdf 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -593,6 +593,7 @@ void del_gendisk(struct gendisk *disk) disk_part_iter_exit(&piter); invalidate_partition(disk, 0); + blk_free_devt(disk_to_dev(disk)->devt); set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; unlink_gendisk(disk); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 04524c213de..206cdf96c3a 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -59,6 +59,7 @@ enum { }; #define DISK_MAX_PARTS 256 +#define DISK_NAME_LEN 32 #include #include @@ -140,7 +141,7 @@ struct gendisk { int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ - char disk_name[32]; /* name of major driver */ + char disk_name[DISK_NAME_LEN]; /* name of major driver */ /* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other -- GitLab From 0835da67c11e879ed5dc23160934d8970470a2ce Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 26 Aug 2008 09:15:47 +0200 Subject: [PATCH 3434/5416] block: use linux/uaccess.h in elevator.c instead of asm variant Signed-off-by: Jens Axboe --- block/elevator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 269615e6dbf..8e3fc3afc77 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -34,8 +34,7 @@ #include #include #include - -#include +#include static DEFINE_SPINLOCK(elv_list_lock); static LIST_HEAD(elv_list); -- GitLab From b646fc59b332ef307895558c9cd1359dc2d25813 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 28 Jul 2008 13:06:00 +0200 Subject: [PATCH 3435/5416] block: split softirq handling into blk-softirq.c Signed-off-by: Jens Axboe --- block/Makefile | 4 +- block/blk-core.c | 88 ------------------------------------- block/blk-softirq.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 90 deletions(-) create mode 100644 block/blk-softirq.c diff --git a/block/Makefile b/block/Makefile index 208000b0750..0da976ce67d 100644 --- a/block/Makefile +++ b/block/Makefile @@ -4,8 +4,8 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \ blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \ - blk-exec.o blk-merge.o ioctl.o genhd.o scsi_ioctl.o \ - cmd-filter.o + blk-exec.o blk-merge.o blk-softirq.o ioctl.o genhd.o \ + scsi_ioctl.o cmd-filter.o obj-$(CONFIG_BLK_DEV_BSG) += bsg.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o diff --git a/block/blk-core.c b/block/blk-core.c index 98138f00252..527b3382a61 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include @@ -50,8 +48,6 @@ struct kmem_cache *blk_requestq_cachep; */ static struct workqueue_struct *kblockd_workqueue; -static DEFINE_PER_CPU(struct list_head, blk_cpu_done); - static void drive_stat_acct(struct request *rq, int new_io) { struct hd_struct *part; @@ -1643,82 +1639,6 @@ static int __end_that_request_first(struct request *req, int error, return 1; } -/* - * splice the completion data to a local structure and hand off to - * process_completion_queue() to complete the requests - */ -static void blk_done_softirq(struct softirq_action *h) -{ - struct list_head *cpu_list, local_list; - - local_irq_disable(); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_replace_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq; - - rq = list_entry(local_list.next, struct request, donelist); - list_del_init(&rq->donelist); - rq->q->softirq_done_fn(rq); - } -} - -static int __cpuinit blk_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * If a CPU goes away, splice its entries to the current CPU - * and trigger a run of the softirq - */ - if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { - int cpu = (unsigned long) hcpu; - - local_irq_disable(); - list_splice_init(&per_cpu(blk_cpu_done, cpu), - &__get_cpu_var(blk_cpu_done)); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - local_irq_enable(); - } - - return NOTIFY_OK; -} - - -static struct notifier_block blk_cpu_notifier __cpuinitdata = { - .notifier_call = blk_cpu_notify, -}; - -/** - * blk_complete_request - end I/O on a request - * @req: the request being processed - * - * Description: - * Ends all I/O on a request. It does not handle partial completions, - * unless the driver actually implements this in its completion callback - * through requeueing. The actual completion happens out-of-order, - * through a softirq handler. The user must have registered a completion - * callback through blk_queue_softirq_done(). - **/ - -void blk_complete_request(struct request *req) -{ - struct list_head *cpu_list; - unsigned long flags; - - BUG_ON(!req->q->softirq_done_fn); - - local_irq_save(flags); - - cpu_list = &__get_cpu_var(blk_cpu_done); - list_add_tail(&req->donelist, cpu_list); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - - local_irq_restore(flags); -} -EXPORT_SYMBOL(blk_complete_request); - /* * queue lock must be held */ @@ -2053,8 +1973,6 @@ EXPORT_SYMBOL(kblockd_flush_work); int __init blk_dev_init(void) { - int i; - kblockd_workqueue = create_workqueue("kblockd"); if (!kblockd_workqueue) panic("Failed to create kblockd\n"); @@ -2065,12 +1983,6 @@ int __init blk_dev_init(void) blk_requestq_cachep = kmem_cache_create("blkdev_queue", sizeof(struct request_queue), 0, SLAB_PANIC, NULL); - for_each_possible_cpu(i) - INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); - - open_softirq(BLOCK_SOFTIRQ, blk_done_softirq); - register_hotcpu_notifier(&blk_cpu_notifier); - return 0; } diff --git a/block/blk-softirq.c b/block/blk-softirq.c new file mode 100644 index 00000000000..9e1c43bff66 --- /dev/null +++ b/block/blk-softirq.c @@ -0,0 +1,103 @@ +/* + * Functions related to softirq rq completions + */ +#include +#include +#include +#include +#include +#include +#include + +#include "blk.h" + +static DEFINE_PER_CPU(struct list_head, blk_cpu_done); + +static int __cpuinit blk_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + /* + * If a CPU goes away, splice its entries to the current CPU + * and trigger a run of the softirq + */ + if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { + int cpu = (unsigned long) hcpu; + + local_irq_disable(); + list_splice_init(&per_cpu(blk_cpu_done, cpu), + &__get_cpu_var(blk_cpu_done)); + raise_softirq_irqoff(BLOCK_SOFTIRQ); + local_irq_enable(); + } + + return NOTIFY_OK; +} + + +static struct notifier_block blk_cpu_notifier __cpuinitdata = { + .notifier_call = blk_cpu_notify, +}; + +/* + * splice the completion data to a local structure and hand off to + * process_completion_queue() to complete the requests + */ +static void blk_done_softirq(struct softirq_action *h) +{ + struct list_head *cpu_list, local_list; + + local_irq_disable(); + cpu_list = &__get_cpu_var(blk_cpu_done); + list_replace_init(cpu_list, &local_list); + local_irq_enable(); + + while (!list_empty(&local_list)) { + struct request *rq; + + rq = list_entry(local_list.next, struct request, donelist); + list_del_init(&rq->donelist); + rq->q->softirq_done_fn(rq); + } +} + +/** + * blk_complete_request - end I/O on a request + * @req: the request being processed + * + * Description: + * Ends all I/O on a request. It does not handle partial completions, + * unless the driver actually implements this in its completion callback + * through requeueing. The actual completion happens out-of-order, + * through a softirq handler. The user must have registered a completion + * callback through blk_queue_softirq_done(). + **/ + +void blk_complete_request(struct request *req) +{ + struct list_head *cpu_list; + unsigned long flags; + + BUG_ON(!req->q->softirq_done_fn); + + local_irq_save(flags); + + cpu_list = &__get_cpu_var(blk_cpu_done); + list_add_tail(&req->donelist, cpu_list); + raise_softirq_irqoff(BLOCK_SOFTIRQ); + + local_irq_restore(flags); +} +EXPORT_SYMBOL(blk_complete_request); + +int __init blk_softirq_init(void) +{ + int i; + + for_each_possible_cpu(i) + INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); + + open_softirq(BLOCK_SOFTIRQ, blk_done_softirq); + register_hotcpu_notifier(&blk_cpu_notifier); + return 0; +} +subsys_initcall(blk_softirq_init); -- GitLab From 18887ad910e56066233a07fd3cfb2fa11338b782 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 28 Jul 2008 13:08:45 +0200 Subject: [PATCH 3436/5416] block: make kblockd_schedule_work() take the queue as parameter Preparatory patch for checking queuing affinity. Signed-off-by: Jens Axboe --- block/as-iosched.c | 6 +++--- block/blk-core.c | 8 ++++---- block/cfq-iosched.c | 2 +- include/linux/blkdev.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index cf4eb0eefbb..80af9257e64 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -462,7 +462,7 @@ static void as_antic_stop(struct as_data *ad) del_timer(&ad->antic_timer); ad->antic_status = ANTIC_FINISHED; /* see as_work_handler */ - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(ad->q, &ad->antic_work); } } @@ -483,7 +483,7 @@ static void as_antic_timeout(unsigned long data) aic = ad->io_context->aic; ad->antic_status = ANTIC_FINISHED; - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(q, &ad->antic_work); if (aic->ttime_samples == 0) { /* process anticipated on has exited or timed out*/ @@ -844,7 +844,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq) if (ad->changed_batch && ad->nr_dispatched == 1) { ad->current_batch_expires = jiffies + ad->batch_expire[ad->batch_data_dir]; - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(q, &ad->antic_work); ad->changed_batch = 0; if (ad->batch_data_dir == REQ_SYNC) diff --git a/block/blk-core.c b/block/blk-core.c index 527b3382a61..9c6f818d0c3 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -305,7 +305,7 @@ void blk_unplug_timeout(unsigned long data) blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL, q->rq.count[READ] + q->rq.count[WRITE]); - kblockd_schedule_work(&q->unplug_work); + kblockd_schedule_work(q, &q->unplug_work); } void blk_unplug(struct request_queue *q) @@ -346,7 +346,7 @@ void blk_start_queue(struct request_queue *q) queue_flag_clear(QUEUE_FLAG_REENTER, q); } else { blk_plug_device(q); - kblockd_schedule_work(&q->unplug_work); + kblockd_schedule_work(q, &q->unplug_work); } } EXPORT_SYMBOL(blk_start_queue); @@ -411,7 +411,7 @@ void __blk_run_queue(struct request_queue *q) queue_flag_clear(QUEUE_FLAG_REENTER, q); } else { blk_plug_device(q); - kblockd_schedule_work(&q->unplug_work); + kblockd_schedule_work(q, &q->unplug_work); } } } @@ -1959,7 +1959,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->rq_disk = bio->bi_bdev->bd_disk; } -int kblockd_schedule_work(struct work_struct *work) +int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) { return queue_work(kblockd_workqueue, work); } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1e2aff812ee..5f6fd287c18 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -244,7 +244,7 @@ static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) { if (cfqd->busy_queues) { cfq_log(cfqd, "schedule dispatch"); - kblockd_schedule_work(&cfqd->unplug_work); + kblockd_schedule_work(cfqd->queue, &cfqd->unplug_work); } } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1adb03827bd..10aa46c8f17 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -912,7 +912,7 @@ static inline void put_dev_sector(Sector p) } struct work_struct; -int kblockd_schedule_work(struct work_struct *work); +int kblockd_schedule_work(struct request_queue *q, struct work_struct *work); void kblockd_flush_work(struct work_struct *work); #define MODULE_ALIAS_BLOCKDEV(major,minor) \ -- GitLab From c7c22e4d5c1fdebfac4dba76de7d0338c2b0d832 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 13 Sep 2008 20:26:01 +0200 Subject: [PATCH 3437/5416] block: add support for IO CPU affinity This patch adds support for controlling the IO completion CPU of either all requests on a queue, or on a per-request basis. We export a sysfs variable (rq_affinity) which, if set, migrates completions of requests to the CPU that originally submitted it. A bio helper (bio_set_completion_cpu()) is also added, so that queuers can ask for completion on that specific CPU. In testing, this has been show to cut the system time by as much as 20-40% on synthetic workloads where CPU affinity is desired. This requires a little help from the architecture, so it'll only work as designed for archs that are using the new generic smp helper infrastructure. Signed-off-by: Jens Axboe --- block/blk-core.c | 46 +++++++------- block/blk-settings.c | 2 +- block/blk-softirq.c | 126 +++++++++++++++++++++++++++++---------- block/blk-sysfs.c | 31 ++++++++++ block/blk.h | 12 ++++ fs/bio.c | 1 + include/linux/bio.h | 11 ++++ include/linux/blkdev.h | 5 +- include/linux/elevator.h | 8 +-- 9 files changed, 182 insertions(+), 60 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 9c6f818d0c3..5484838f46e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -110,7 +110,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq) memset(rq, 0, sizeof(*rq)); INIT_LIST_HEAD(&rq->queuelist); - INIT_LIST_HEAD(&rq->donelist); + rq->cpu = -1; rq->q = q; rq->sector = rq->hard_sector = (sector_t) -1; INIT_HLIST_NODE(&rq->hash); @@ -322,6 +322,21 @@ void blk_unplug(struct request_queue *q) } EXPORT_SYMBOL(blk_unplug); +static void blk_invoke_request_fn(struct request_queue *q) +{ + /* + * one level of recursion is ok and is much faster than kicking + * the unplug handling + */ + if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { + q->request_fn(q); + queue_flag_clear(QUEUE_FLAG_REENTER, q); + } else { + queue_flag_set(QUEUE_FLAG_PLUGGED, q); + kblockd_schedule_work(q, &q->unplug_work); + } +} + /** * blk_start_queue - restart a previously stopped queue * @q: The &struct request_queue in question @@ -336,18 +351,7 @@ void blk_start_queue(struct request_queue *q) WARN_ON(!irqs_disabled()); queue_flag_clear(QUEUE_FLAG_STOPPED, q); - - /* - * one level of recursion is ok and is much faster than kicking - * the unplug handling - */ - if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { - q->request_fn(q); - queue_flag_clear(QUEUE_FLAG_REENTER, q); - } else { - blk_plug_device(q); - kblockd_schedule_work(q, &q->unplug_work); - } + blk_invoke_request_fn(q); } EXPORT_SYMBOL(blk_start_queue); @@ -405,15 +409,8 @@ void __blk_run_queue(struct request_queue *q) * Only recurse once to avoid overrunning the stack, let the unplug * handling reinvoke the handler shortly if we already got there. */ - if (!elv_queue_empty(q)) { - if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { - q->request_fn(q); - queue_flag_clear(QUEUE_FLAG_REENTER, q); - } else { - blk_plug_device(q); - kblockd_schedule_work(q, &q->unplug_work); - } - } + if (!elv_queue_empty(q)) + blk_invoke_request_fn(q); } EXPORT_SYMBOL(__blk_run_queue); @@ -1056,6 +1053,7 @@ EXPORT_SYMBOL(blk_put_request); void init_request_from_bio(struct request *req, struct bio *bio) { + req->cpu = bio->bi_comp_cpu; req->cmd_type = REQ_TYPE_FS; /* @@ -1198,13 +1196,15 @@ get_rq: init_request_from_bio(req, bio); spin_lock_irq(q->queue_lock); + if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) || + bio_flagged(bio, BIO_CPU_AFFINE)) + req->cpu = blk_cpu_to_group(smp_processor_id()); if (elv_queue_empty(q)) blk_plug_device(q); add_request(q, req); out: if (sync) __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); return 0; diff --git a/block/blk-settings.c b/block/blk-settings.c index d70692badcd..a60e959a12c 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -443,7 +443,7 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask) } EXPORT_SYMBOL(blk_queue_update_dma_alignment); -static int __init blk_settings_init(void) +int __init blk_settings_init(void) { blk_max_low_pfn = max_low_pfn - 1; blk_max_pfn = max_pfn - 1; diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 9e1c43bff66..3a1af551191 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -13,6 +13,70 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done); +/* + * Softirq action handler - move entries to local list and loop over them + * while passing them to the queue registered handler. + */ +static void blk_done_softirq(struct softirq_action *h) +{ + struct list_head *cpu_list, local_list; + + local_irq_disable(); + cpu_list = &__get_cpu_var(blk_cpu_done); + list_replace_init(cpu_list, &local_list); + local_irq_enable(); + + while (!list_empty(&local_list)) { + struct request *rq; + + rq = list_entry(local_list.next, struct request, csd.list); + list_del_init(&rq->csd.list); + rq->q->softirq_done_fn(rq); + } +} + +#if defined(CONFIG_SMP) && defined(CONFIG_USE_GENERIC_SMP_HELPERS) +static void trigger_softirq(void *data) +{ + struct request *rq = data; + unsigned long flags; + struct list_head *list; + + local_irq_save(flags); + list = &__get_cpu_var(blk_cpu_done); + list_add_tail(&rq->csd.list, list); + + if (list->next == &rq->csd.list) + raise_softirq_irqoff(BLOCK_SOFTIRQ); + + local_irq_restore(flags); +} + +/* + * Setup and invoke a run of 'trigger_softirq' on the given cpu. + */ +static int raise_blk_irq(int cpu, struct request *rq) +{ + if (cpu_online(cpu)) { + struct call_single_data *data = &rq->csd; + + data->func = trigger_softirq; + data->info = rq; + data->flags = 0; + + __smp_call_function_single(cpu, data); + return 0; + } + + return 1; +} +#else /* CONFIG_SMP && CONFIG_USE_GENERIC_SMP_HELPERS */ +static int raise_blk_irq(int cpu, struct request *rq) +{ + return 1; +} +#endif + static int __cpuinit blk_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -33,33 +97,10 @@ static int __cpuinit blk_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } - -static struct notifier_block blk_cpu_notifier __cpuinitdata = { +static struct notifier_block __cpuinitdata blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; -/* - * splice the completion data to a local structure and hand off to - * process_completion_queue() to complete the requests - */ -static void blk_done_softirq(struct softirq_action *h) -{ - struct list_head *cpu_list, local_list; - - local_irq_disable(); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_replace_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq; - - rq = list_entry(local_list.next, struct request, donelist); - list_del_init(&rq->donelist); - rq->q->softirq_done_fn(rq); - } -} - /** * blk_complete_request - end I/O on a request * @req: the request being processed @@ -71,25 +112,48 @@ static void blk_done_softirq(struct softirq_action *h) * through a softirq handler. The user must have registered a completion * callback through blk_queue_softirq_done(). **/ - void blk_complete_request(struct request *req) { - struct list_head *cpu_list; + struct request_queue *q = req->q; unsigned long flags; + int ccpu, cpu, group_cpu; - BUG_ON(!req->q->softirq_done_fn); + BUG_ON(!q->softirq_done_fn); local_irq_save(flags); + cpu = smp_processor_id(); + group_cpu = blk_cpu_to_group(cpu); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_add_tail(&req->donelist, cpu_list); - raise_softirq_irqoff(BLOCK_SOFTIRQ); + /* + * Select completion CPU + */ + if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1) + ccpu = req->cpu; + else + ccpu = cpu; + + if (ccpu == cpu || ccpu == group_cpu) { + struct list_head *list; +do_local: + list = &__get_cpu_var(blk_cpu_done); + list_add_tail(&req->csd.list, list); + + /* + * if the list only contains our just added request, + * signal a raise of the softirq. If there are already + * entries there, someone already raised the irq but it + * hasn't run yet. + */ + if (list->next == &req->csd.list) + raise_softirq_irqoff(BLOCK_SOFTIRQ); + } else if (raise_blk_irq(ccpu, req)) + goto do_local; local_irq_restore(flags); } EXPORT_SYMBOL(blk_complete_request); -int __init blk_softirq_init(void) +__init int blk_softirq_init(void) { int i; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index b9a6ed16664..21e275d7eed 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -156,6 +156,30 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page, return ret; } +static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page) +{ + unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags); + + return queue_var_show(set != 0, page); +} + +static ssize_t +queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count) +{ + ssize_t ret = -EINVAL; +#if defined(CONFIG_USE_GENERIC_SMP_HELPERS) + unsigned long val; + + ret = queue_var_store(&val, page, count); + spin_lock_irq(q->queue_lock); + if (val) + queue_flag_set(QUEUE_FLAG_SAME_COMP, q); + else + queue_flag_clear(QUEUE_FLAG_SAME_COMP, q); + spin_unlock_irq(q->queue_lock); +#endif + return ret; +} static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, @@ -197,6 +221,12 @@ static struct queue_sysfs_entry queue_nomerges_entry = { .store = queue_nomerges_store, }; +static struct queue_sysfs_entry queue_rq_affinity_entry = { + .attr = {.name = "rq_affinity", .mode = S_IRUGO | S_IWUSR }, + .show = queue_rq_affinity_show, + .store = queue_rq_affinity_store, +}; + static struct attribute *default_attrs[] = { &queue_requests_entry.attr, &queue_ra_entry.attr, @@ -205,6 +235,7 @@ static struct attribute *default_attrs[] = { &queue_iosched_entry.attr, &queue_hw_sector_size_entry.attr, &queue_nomerges_entry.attr, + &queue_rq_affinity_entry.attr, NULL, }; diff --git a/block/blk.h b/block/blk.h index c79f30e1df5..de74254cb91 100644 --- a/block/blk.h +++ b/block/blk.h @@ -59,4 +59,16 @@ static inline int queue_congestion_off_threshold(struct request_queue *q) #endif /* BLK_DEV_INTEGRITY */ +static inline int blk_cpu_to_group(int cpu) +{ +#ifdef CONFIG_SCHED_MC + cpumask_t mask = cpu_coregroup_map(cpu); + return first_cpu(mask); +#elif defined(CONFIG_SCHED_SMT) + return first_cpu(per_cpu(cpu_sibling_map, cpu)); +#else + return cpu; +#endif +} + #endif diff --git a/fs/bio.c b/fs/bio.c index bee4deca774..6a637b5c24b 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -111,6 +111,7 @@ void bio_init(struct bio *bio) { memset(bio, 0, sizeof(*bio)); bio->bi_flags = 1 << BIO_UPTODATE; + bio->bi_comp_cpu = -1; atomic_set(&bio->bi_cnt, 1); } diff --git a/include/linux/bio.h b/include/linux/bio.h index 2c0c09034fd..13aba20edb2 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -81,6 +81,8 @@ struct bio { unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ + unsigned int bi_comp_cpu; /* completion CPU */ + struct bio_vec *bi_io_vec; /* the actual vec list */ bio_end_io_t *bi_end_io; @@ -105,6 +107,7 @@ struct bio { #define BIO_BOUNCED 5 /* bio is a bounce bio */ #define BIO_USER_MAPPED 6 /* contains user pages */ #define BIO_EOPNOTSUPP 7 /* not supported */ +#define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) /* @@ -342,6 +345,14 @@ void zero_fill_bio(struct bio *bio); extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *); extern unsigned int bvec_nr_vecs(unsigned short idx); +/* + * Allow queuer to specify a completion CPU for this bio + */ +static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu) +{ + bio->bi_comp_cpu = cpu; +} + /* * bio_set is used to allow other portions of the IO system to * allocate their own private memory pools for bio and iovec structures. diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 10aa46c8f17..93204bf7b29 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -139,7 +140,8 @@ enum rq_flag_bits { */ struct request { struct list_head queuelist; - struct list_head donelist; + struct call_single_data csd; + int cpu; struct request_queue *q; @@ -420,6 +422,7 @@ struct request_queue #define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */ #define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */ #define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ +#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ static inline int queue_is_locked(struct request_queue *q) { diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 639624b55fb..bb791c311a5 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -173,15 +173,15 @@ enum { #define rb_entry_rq(node) rb_entry((node), struct request, rb_node) /* - * Hack to reuse the donelist list_head as the fifo time holder while + * Hack to reuse the csd.list list_head as the fifo time holder while * the request is in the io scheduler. Saves an unsigned long in rq. */ -#define rq_fifo_time(rq) ((unsigned long) (rq)->donelist.next) -#define rq_set_fifo_time(rq,exp) ((rq)->donelist.next = (void *) (exp)) +#define rq_fifo_time(rq) ((unsigned long) (rq)->csd.list.next) +#define rq_set_fifo_time(rq,exp) ((rq)->csd.list.next = (void *) (exp)) #define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) #define rq_fifo_clear(rq) do { \ list_del_init(&(rq)->queuelist); \ - INIT_LIST_HEAD(&(rq)->donelist); \ + INIT_LIST_HEAD(&(rq)->csd.list); \ } while (0) /* -- GitLab From ab780f1ece0dc8d5e8e8e85435acc5e4747ccda3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 26 Aug 2008 10:25:02 +0200 Subject: [PATCH 3438/5416] block: inherit CPU completion on bio->rq and rq->rq merges Somewhat incomplete, as we do allow merges of requests and bios that have different completion CPUs given. This is done on the assumption that a larger IO is still more beneficial than CPU locality. Signed-off-by: Jens Axboe --- block/blk-core.c | 4 ++++ block/blk-merge.c | 2 ++ include/linux/blkdev.h | 1 + 3 files changed, 7 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 5484838f46e..b9a252cae4d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1134,6 +1134,8 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); + if (!blk_rq_cpu_valid(req)) + req->cpu = bio->bi_comp_cpu; drive_stat_acct(req, 0); if (!attempt_back_merge(q, req)) elv_merged_request(q, req, el_ret); @@ -1161,6 +1163,8 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->sector = req->hard_sector = bio->bi_sector; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); + if (!blk_rq_cpu_valid(req)) + req->cpu = bio->bi_comp_cpu; drive_stat_acct(req, 0); if (!attempt_front_merge(q, req)) elv_merged_request(q, req, el_ret); diff --git a/block/blk-merge.c b/block/blk-merge.c index c77196d5589..908d3e11ac5 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -400,6 +400,8 @@ static int attempt_merge(struct request_queue *q, struct request *req, } req->ioprio = ioprio_best(req->ioprio, next->ioprio); + if (blk_rq_cpu_valid(next)) + req->cpu = next->cpu; __blk_put_request(q, next); return 1; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 93204bf7b29..12df8efeef1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -545,6 +545,7 @@ enum { #define blk_pm_request(rq) \ (blk_pm_suspend_request(rq) || blk_pm_resume_request(rq)) +#define blk_rq_cpu_valid(rq) ((rq)->cpu != -1) #define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED) #define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) -- GitLab From 605401618ce4409045bc4db86e88d4b38f2ad585 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 26 Aug 2008 13:34:34 +0200 Subject: [PATCH 3439/5416] block: don't use bio_has_data() in the completion path We should just check for rq->bio, as that is really the information we are looking for. Even if the bio attached doesn't carry data, we still need to do IO post processing on it. Signed-off-by: Jens Axboe --- block/blk-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index b9a252cae4d..5bf806adc77 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1817,7 +1817,7 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, struct request_queue *q = rq->q; unsigned long flags = 0UL; - if (bio_has_data(rq->bio) || blk_discard_rq(rq)) { + if (rq->bio) { if (__end_that_request_first(rq, error, nr_bytes)) return 1; @@ -1875,8 +1875,7 @@ EXPORT_SYMBOL_GPL(blk_end_request); **/ int __blk_end_request(struct request *rq, int error, unsigned int nr_bytes) { - if ((bio_has_data(rq->bio) || blk_discard_rq(rq)) && - __end_that_request_first(rq, error, nr_bytes)) + if (rq->bio && __end_that_request_first(rq, error, nr_bytes)) return 1; add_disk_randomness(rq->rq_disk); -- GitLab From 45333d5a31296d0af886d94f1d08f128231cab8e Mon Sep 17 00:00:00 2001 From: Aaron Carroll Date: Tue, 26 Aug 2008 15:52:36 +0200 Subject: [PATCH 3440/5416] cfq-iosched: fix queue depth detection CFQ's detection of queueing devices assumes a non-queuing device and detects if the queue depth reaches a certain threshold. Under some workloads (e.g. synchronous reads), CFQ effectively forces a unit queue depth, thus defeating the detection logic. This leads to poor performance on queuing hardware, since the idle window remains enabled. This patch inverts the sense of the logic: assume a queuing-capable device, and detect if the depth does not exceed the threshold. Signed-off-by: Aaron Carroll Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 47 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5f6fd287c18..494b6fdcb18 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -39,6 +39,7 @@ static int cfq_slice_idle = HZ / 125; #define CFQ_MIN_TT (2) #define CFQ_SLICE_SCALE (5) +#define CFQ_HW_QUEUE_MIN (5) #define RQ_CIC(rq) \ ((struct cfq_io_context *) (rq)->elevator_private) @@ -86,7 +87,14 @@ struct cfq_data { int rq_in_driver; int sync_flight; + + /* + * queue-depth detection + */ + int rq_queued; int hw_tag; + int hw_tag_samples; + int rq_in_driver_peak; /* * idle window management @@ -654,15 +662,6 @@ static void cfq_activate_request(struct request_queue *q, struct request *rq) cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d", cfqd->rq_in_driver); - /* - * If the depth is larger 1, it really could be queueing. But lets - * make the mark a little higher - idling could still be good for - * low queueing, and a low queueing number could also just indicate - * a SCSI mid layer like behaviour where limit+1 is often seen. - */ - if (!cfqd->hw_tag && cfqd->rq_in_driver > 4) - cfqd->hw_tag = 1; - cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors; } @@ -686,6 +685,7 @@ static void cfq_remove_request(struct request *rq) list_del_init(&rq->queuelist); cfq_del_rq_rb(rq); + cfqq->cfqd->rq_queued--; if (rq_is_meta(rq)) { WARN_ON(!cfqq->meta_pending); cfqq->meta_pending--; @@ -1833,6 +1833,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, { struct cfq_io_context *cic = RQ_CIC(rq); + cfqd->rq_queued++; if (rq_is_meta(rq)) cfqq->meta_pending++; @@ -1880,6 +1881,31 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) cfq_rq_enqueued(cfqd, cfqq, rq); } +/* + * Update hw_tag based on peak queue depth over 50 samples under + * sufficient load. + */ +static void cfq_update_hw_tag(struct cfq_data *cfqd) +{ + if (cfqd->rq_in_driver > cfqd->rq_in_driver_peak) + cfqd->rq_in_driver_peak = cfqd->rq_in_driver; + + if (cfqd->rq_queued <= CFQ_HW_QUEUE_MIN && + cfqd->rq_in_driver <= CFQ_HW_QUEUE_MIN) + return; + + if (cfqd->hw_tag_samples++ < 50) + return; + + if (cfqd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN) + cfqd->hw_tag = 1; + else + cfqd->hw_tag = 0; + + cfqd->hw_tag_samples = 0; + cfqd->rq_in_driver_peak = 0; +} + static void cfq_completed_request(struct request_queue *q, struct request *rq) { struct cfq_queue *cfqq = RQ_CFQQ(rq); @@ -1890,6 +1916,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) now = jiffies; cfq_log_cfqq(cfqd, cfqq, "complete"); + cfq_update_hw_tag(cfqd); + WARN_ON(!cfqd->rq_in_driver); WARN_ON(!cfqq->dispatched); cfqd->rq_in_driver--; @@ -2200,6 +2228,7 @@ static void *cfq_init_queue(struct request_queue *q) cfqd->cfq_slice[1] = cfq_slice_sync; cfqd->cfq_slice_async_rq = cfq_slice_async_rq; cfqd->cfq_slice_idle = cfq_slice_idle; + cfqd->hw_tag = 1; return cfqd; } -- GitLab From a3bce90edd8f6cafe3f63b1a943800792e830178 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 16:17:05 +0900 Subject: [PATCH 3441/5416] block: add gfp_mask argument to blk_rq_map_user and blk_rq_map_user_iov Currently, blk_rq_map_user and blk_rq_map_user_iov always do GFP_KERNEL allocation. This adds gfp_mask argument to blk_rq_map_user and blk_rq_map_user_iov so sg can use it (sg always does GFP_ATOMIC allocation). Signed-off-by: FUJITA Tomonori Signed-off-by: Douglas Gilbert Cc: Mike Christie Cc: James Bottomley Signed-off-by: Jens Axboe --- block/blk-map.c | 20 ++++++++++++-------- block/bsg.c | 5 +++-- block/scsi_ioctl.c | 5 +++-- drivers/cdrom/cdrom.c | 2 +- drivers/scsi/scsi_tgt_lib.c | 2 +- fs/bio.c | 33 +++++++++++++++++++-------------- include/linux/bio.h | 9 +++++---- include/linux/blkdev.h | 5 +++-- 8 files changed, 47 insertions(+), 34 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index ea1bf53929e..ac21b7397e1 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -41,7 +41,8 @@ static int __blk_rq_unmap_user(struct bio *bio) } static int __blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned int len) + void __user *ubuf, unsigned int len, + gfp_t gfp_mask) { unsigned long uaddr; unsigned int alignment; @@ -57,9 +58,9 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, uaddr = (unsigned long) ubuf; alignment = queue_dma_alignment(q) | q->dma_pad_mask; if (!(uaddr & alignment) && !(len & alignment)) - bio = bio_map_user(q, NULL, uaddr, len, reading); + bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); else - bio = bio_copy_user(q, uaddr, len, reading); + bio = bio_copy_user(q, uaddr, len, reading, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); @@ -90,6 +91,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * @rq: request structure to fill * @ubuf: the user buffer * @len: length of user data + * @gfp_mask: memory allocation flags * * Description: * Data will be mapped directly for zero copy I/O, if possible. Otherwise @@ -105,7 +107,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * unmapping. */ int blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned long len) + void __user *ubuf, unsigned long len, gfp_t gfp_mask) { unsigned long bytes_read = 0; struct bio *bio = NULL; @@ -132,7 +134,7 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, if (end - start > BIO_MAX_PAGES) map_len -= PAGE_SIZE; - ret = __blk_rq_map_user(q, rq, ubuf, map_len); + ret = __blk_rq_map_user(q, rq, ubuf, map_len, gfp_mask); if (ret < 0) goto unmap_rq; if (!bio) @@ -160,6 +162,7 @@ EXPORT_SYMBOL(blk_rq_map_user); * @iov: pointer to the iovec * @iov_count: number of elements in the iovec * @len: I/O byte count + * @gfp_mask: memory allocation flags * * Description: * Data will be mapped directly for zero copy I/O, if possible. Otherwise @@ -175,7 +178,8 @@ EXPORT_SYMBOL(blk_rq_map_user); * unmapping. */ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, - struct sg_iovec *iov, int iov_count, unsigned int len) + struct sg_iovec *iov, int iov_count, unsigned int len, + gfp_t gfp_mask) { struct bio *bio; int i, read = rq_data_dir(rq) == READ; @@ -194,9 +198,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, } if (unaligned || (q->dma_pad_mask & len)) - bio = bio_copy_user_iov(q, iov, iov_count, read); + bio = bio_copy_user_iov(q, iov, iov_count, read, gfp_mask); else - bio = bio_map_user_iov(q, NULL, iov, iov_count, read); + bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); diff --git a/block/bsg.c b/block/bsg.c index 0aae8d7ba99..e7a142e9916 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -283,7 +283,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) next_rq->cmd_type = rq->cmd_type; dxferp = (void*)(unsigned long)hdr->din_xferp; - ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len); + ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len, + GFP_KERNEL); if (ret) goto out; } @@ -298,7 +299,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) dxfer_len = 0; if (dxfer_len) { - ret = blk_rq_map_user(q, rq, dxferp, dxfer_len); + ret = blk_rq_map_user(q, rq, dxferp, dxfer_len, GFP_KERNEL); if (ret) goto out; } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 3aab80a4c48..f49d6a11a69 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -315,10 +315,11 @@ static int sg_io(struct file *file, struct request_queue *q, } ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, - hdr->dxfer_len); + hdr->dxfer_len, GFP_KERNEL); kfree(iov); } else if (hdr->dxfer_len) - ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); + ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len, + GFP_KERNEL); if (ret) goto out; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 74031de517e..e861d24a6d3 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2097,7 +2097,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; - ret = blk_rq_map_user(q, rq, ubuf, len); + ret = blk_rq_map_user(q, rq, ubuf, len, GFP_KERNEL); if (ret) break; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 257e097c39a..2a4fd820d61 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -362,7 +362,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, int err; dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, (void *)uaddr, len); + err = blk_rq_map_user(q, rq, (void *)uaddr, len, GFP_KERNEL); if (err) { /* * TODO: need to fixup sg_tablesize, max_segment_size, diff --git a/fs/bio.c b/fs/bio.c index 6a637b5c24b..3d2e9ad2472 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -558,13 +558,14 @@ int bio_uncopy_user(struct bio *bio) * @iov: the iovec. * @iov_count: number of elements in the iovec * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Prepares and returns a bio for indirect user io, bouncing data * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, - int iov_count, int write_to_vm) + int iov_count, int write_to_vm, gfp_t gfp_mask) { struct bio_map_data *bmd; struct bio_vec *bvec; @@ -587,12 +588,12 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, len += iov[i].iov_len; } - bmd = bio_alloc_map_data(nr_pages, iov_count, GFP_KERNEL); + bmd = bio_alloc_map_data(nr_pages, iov_count, gfp_mask); if (!bmd) return ERR_PTR(-ENOMEM); ret = -ENOMEM; - bio = bio_alloc(GFP_KERNEL, nr_pages); + bio = bio_alloc(gfp_mask, nr_pages); if (!bio) goto out_bmd; @@ -605,7 +606,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, if (bytes > len) bytes = len; - page = alloc_page(q->bounce_gfp | GFP_KERNEL); + page = alloc_page(q->bounce_gfp | gfp_mask); if (!page) { ret = -ENOMEM; break; @@ -647,26 +648,27 @@ out_bmd: * @uaddr: start of user address * @len: length in bytes * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Prepares and returns a bio for indirect user io, bouncing data * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, - unsigned int len, int write_to_vm) + unsigned int len, int write_to_vm, gfp_t gfp_mask) { struct sg_iovec iov; iov.iov_base = (void __user *)uaddr; iov.iov_len = len; - return bio_copy_user_iov(q, &iov, 1, write_to_vm); + return bio_copy_user_iov(q, &iov, 1, write_to_vm, gfp_mask); } static struct bio *__bio_map_user_iov(struct request_queue *q, struct block_device *bdev, struct sg_iovec *iov, int iov_count, - int write_to_vm) + int write_to_vm, gfp_t gfp_mask) { int i, j; int nr_pages = 0; @@ -692,12 +694,12 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, if (!nr_pages) return ERR_PTR(-EINVAL); - bio = bio_alloc(GFP_KERNEL, nr_pages); + bio = bio_alloc(gfp_mask, nr_pages); if (!bio) return ERR_PTR(-ENOMEM); ret = -ENOMEM; - pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); + pages = kcalloc(nr_pages, sizeof(struct page *), gfp_mask); if (!pages) goto out; @@ -776,19 +778,21 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, * @uaddr: start of user address * @len: length in bytes * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Map the user space address into a bio suitable for io to a block * device. Returns an error pointer in case of error. */ struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev, - unsigned long uaddr, unsigned int len, int write_to_vm) + unsigned long uaddr, unsigned int len, int write_to_vm, + gfp_t gfp_mask) { struct sg_iovec iov; iov.iov_base = (void __user *)uaddr; iov.iov_len = len; - return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm); + return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm, gfp_mask); } /** @@ -798,18 +802,19 @@ struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev, * @iov: the iovec. * @iov_count: number of elements in the iovec * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Map the user space address into a bio suitable for io to a block * device. Returns an error pointer in case of error. */ struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev, struct sg_iovec *iov, int iov_count, - int write_to_vm) + int write_to_vm, gfp_t gfp_mask) { struct bio *bio; - bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm); - + bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm, + gfp_mask); if (IS_ERR(bio)) return bio; diff --git a/include/linux/bio.h b/include/linux/bio.h index 13aba20edb2..200b185c3e8 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -325,11 +325,11 @@ extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, unsigned int, unsigned int); extern int bio_get_nr_vecs(struct block_device *); extern struct bio *bio_map_user(struct request_queue *, struct block_device *, - unsigned long, unsigned int, int); + unsigned long, unsigned int, int, gfp_t); struct sg_iovec; extern struct bio *bio_map_user_iov(struct request_queue *, struct block_device *, - struct sg_iovec *, int, int); + struct sg_iovec *, int, int, gfp_t); extern void bio_unmap_user(struct bio *); extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int, gfp_t); @@ -337,9 +337,10 @@ extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int, gfp_t, int); extern void bio_set_pages_dirty(struct bio *bio); extern void bio_check_pages_dirty(struct bio *bio); -extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int); +extern struct bio *bio_copy_user(struct request_queue *, unsigned long, + unsigned int, int, gfp_t); extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *, - int, int); + int, int, gfp_t); extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 12df8efeef1..00e388d0e22 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -710,11 +710,12 @@ extern void __blk_stop_queue(struct request_queue *q); extern void __blk_run_queue(struct request_queue *); extern void blk_run_queue(struct request_queue *); extern void blk_start_queueing(struct request_queue *); -extern int blk_rq_map_user(struct request_queue *, struct request *, void __user *, unsigned long); +extern int blk_rq_map_user(struct request_queue *, struct request *, + void __user *, unsigned long, gfp_t); extern int blk_rq_unmap_user(struct bio *); extern int blk_rq_map_kern(struct request_queue *, struct request *, void *, unsigned int, gfp_t); extern int blk_rq_map_user_iov(struct request_queue *, struct request *, - struct sg_iovec *, int, unsigned int); + struct sg_iovec *, int, unsigned int, gfp_t); extern int blk_execute_rq(struct request_queue *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, -- GitLab From 152e283fdfea0cd11e297d982378b55937842dde Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 16:17:06 +0900 Subject: [PATCH 3442/5416] block: introduce struct rq_map_data to use reserved pages This patch introduces struct rq_map_data to enable bio_copy_use_iov() use reserved pages. Currently, bio_copy_user_iov allocates bounce pages but drivers/scsi/sg.c wants to allocate pages by itself and use them. struct rq_map_data can be used to pass allocated pages to bio_copy_user_iov. The current users of bio_copy_user_iov simply passes NULL (they don't want to use pre-allocated pages). Signed-off-by: FUJITA Tomonori Cc: Jens Axboe Cc: Douglas Gilbert Cc: Mike Christie Cc: James Bottomley Signed-off-by: Jens Axboe --- block/blk-map.c | 26 ++++++++++------- block/bsg.c | 7 +++-- block/scsi_ioctl.c | 4 +-- drivers/cdrom/cdrom.c | 2 +- drivers/scsi/scsi_tgt_lib.c | 2 +- fs/bio.c | 58 ++++++++++++++++++++++++++----------- include/linux/bio.h | 8 +++-- include/linux/blkdev.h | 12 ++++++-- 8 files changed, 80 insertions(+), 39 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index ac21b7397e1..dad6a290783 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -41,8 +41,8 @@ static int __blk_rq_unmap_user(struct bio *bio) } static int __blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned int len, - gfp_t gfp_mask) + struct rq_map_data *map_data, void __user *ubuf, + unsigned int len, gfp_t gfp_mask) { unsigned long uaddr; unsigned int alignment; @@ -57,10 +57,10 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, */ uaddr = (unsigned long) ubuf; alignment = queue_dma_alignment(q) | q->dma_pad_mask; - if (!(uaddr & alignment) && !(len & alignment)) + if (!(uaddr & alignment) && !(len & alignment) && !map_data) bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); else - bio = bio_copy_user(q, uaddr, len, reading, gfp_mask); + bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); @@ -89,6 +89,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * blk_rq_map_user - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request structure to fill + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @ubuf: the user buffer * @len: length of user data * @gfp_mask: memory allocation flags @@ -107,7 +108,8 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * unmapping. */ int blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned long len, gfp_t gfp_mask) + struct rq_map_data *map_data, void __user *ubuf, + unsigned long len, gfp_t gfp_mask) { unsigned long bytes_read = 0; struct bio *bio = NULL; @@ -134,7 +136,8 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, if (end - start > BIO_MAX_PAGES) map_len -= PAGE_SIZE; - ret = __blk_rq_map_user(q, rq, ubuf, map_len, gfp_mask); + ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, + gfp_mask); if (ret < 0) goto unmap_rq; if (!bio) @@ -159,6 +162,7 @@ EXPORT_SYMBOL(blk_rq_map_user); * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to map data to + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @iov: pointer to the iovec * @iov_count: number of elements in the iovec * @len: I/O byte count @@ -178,8 +182,8 @@ EXPORT_SYMBOL(blk_rq_map_user); * unmapping. */ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, - struct sg_iovec *iov, int iov_count, unsigned int len, - gfp_t gfp_mask) + struct rq_map_data *map_data, struct sg_iovec *iov, + int iov_count, unsigned int len, gfp_t gfp_mask) { struct bio *bio; int i, read = rq_data_dir(rq) == READ; @@ -197,8 +201,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, } } - if (unaligned || (q->dma_pad_mask & len)) - bio = bio_copy_user_iov(q, iov, iov_count, read, gfp_mask); + if (unaligned || (q->dma_pad_mask & len) || map_data) + bio = bio_copy_user_iov(q, map_data, iov, iov_count, read, + gfp_mask); else bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); @@ -220,6 +225,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, rq->buffer = rq->data = NULL; return 0; } +EXPORT_SYMBOL(blk_rq_map_user_iov); /** * blk_rq_unmap_user - unmap a request with user data diff --git a/block/bsg.c b/block/bsg.c index e7a142e9916..56cb343c76d 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -283,8 +283,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) next_rq->cmd_type = rq->cmd_type; dxferp = (void*)(unsigned long)hdr->din_xferp; - ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len, - GFP_KERNEL); + ret = blk_rq_map_user(q, next_rq, NULL, dxferp, + hdr->din_xfer_len, GFP_KERNEL); if (ret) goto out; } @@ -299,7 +299,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) dxfer_len = 0; if (dxfer_len) { - ret = blk_rq_map_user(q, rq, dxferp, dxfer_len, GFP_KERNEL); + ret = blk_rq_map_user(q, rq, NULL, dxferp, dxfer_len, + GFP_KERNEL); if (ret) goto out; } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index f49d6a11a69..c34272a348f 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -314,11 +314,11 @@ static int sg_io(struct file *file, struct request_queue *q, goto out; } - ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, + ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, hdr->dxfer_len, GFP_KERNEL); kfree(iov); } else if (hdr->dxfer_len) - ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len, + ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, GFP_KERNEL); if (ret) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index e861d24a6d3..d47f2f80acc 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2097,7 +2097,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; - ret = blk_rq_map_user(q, rq, ubuf, len, GFP_KERNEL); + ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); if (ret) break; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 2a4fd820d61..3117bb106b5 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -362,7 +362,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, int err; dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, (void *)uaddr, len, GFP_KERNEL); + err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL); if (err) { /* * TODO: need to fixup sg_tablesize, max_segment_size, diff --git a/fs/bio.c b/fs/bio.c index 3d2e9ad2472..a2f072647cd 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -439,16 +439,19 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, struct bio_map_data { struct bio_vec *iovecs; - int nr_sgvecs; struct sg_iovec *sgvecs; + int nr_sgvecs; + int is_our_pages; }; static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, - struct sg_iovec *iov, int iov_count) + struct sg_iovec *iov, int iov_count, + int is_our_pages) { memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt); memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count); bmd->nr_sgvecs = iov_count; + bmd->is_our_pages = is_our_pages; bio->bi_private = bmd; } @@ -483,7 +486,8 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, } static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, - struct sg_iovec *iov, int iov_count, int uncopy) + struct sg_iovec *iov, int iov_count, int uncopy, + int do_free_page) { int ret = 0, i; struct bio_vec *bvec; @@ -526,7 +530,7 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, } } - if (uncopy) + if (do_free_page) __free_page(bvec->bv_page); } @@ -545,7 +549,8 @@ int bio_uncopy_user(struct bio *bio) struct bio_map_data *bmd = bio->bi_private; int ret; - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1); + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1, + bmd->is_our_pages); bio_free_map_data(bmd); bio_put(bio); @@ -555,6 +560,7 @@ int bio_uncopy_user(struct bio *bio) /** * bio_copy_user_iov - copy user data to bio * @q: destination block queue + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @iov: the iovec. * @iov_count: number of elements in the iovec * @write_to_vm: bool indicating writing to pages or not @@ -564,8 +570,10 @@ int bio_uncopy_user(struct bio *bio) * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ -struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, - int iov_count, int write_to_vm, gfp_t gfp_mask) +struct bio *bio_copy_user_iov(struct request_queue *q, + struct rq_map_data *map_data, + struct sg_iovec *iov, int iov_count, + int write_to_vm, gfp_t gfp_mask) { struct bio_map_data *bmd; struct bio_vec *bvec; @@ -600,13 +608,26 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, bio->bi_rw |= (!write_to_vm << BIO_RW); ret = 0; + i = 0; while (len) { - unsigned int bytes = PAGE_SIZE; + unsigned int bytes; + + if (map_data) + bytes = 1U << (PAGE_SHIFT + map_data->page_order); + else + bytes = PAGE_SIZE; if (bytes > len) bytes = len; - page = alloc_page(q->bounce_gfp | gfp_mask); + if (map_data) { + if (i == map_data->nr_entries) { + ret = -ENOMEM; + break; + } + page = map_data->pages[i++]; + } else + page = alloc_page(q->bounce_gfp | gfp_mask); if (!page) { ret = -ENOMEM; break; @@ -625,16 +646,17 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, * success */ if (!write_to_vm) { - ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0); + ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); if (ret) goto cleanup; } - bio_set_map_data(bmd, bio, iov, iov_count); + bio_set_map_data(bmd, bio, iov, iov_count, map_data ? 0 : 1); return bio; cleanup: - bio_for_each_segment(bvec, bio, i) - __free_page(bvec->bv_page); + if (!map_data) + bio_for_each_segment(bvec, bio, i) + __free_page(bvec->bv_page); bio_put(bio); out_bmd: @@ -645,6 +667,7 @@ out_bmd: /** * bio_copy_user - copy user data to bio * @q: destination block queue + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @uaddr: start of user address * @len: length in bytes * @write_to_vm: bool indicating writing to pages or not @@ -654,15 +677,16 @@ out_bmd: * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ -struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, - unsigned int len, int write_to_vm, gfp_t gfp_mask) +struct bio *bio_copy_user(struct request_queue *q, struct rq_map_data *map_data, + unsigned long uaddr, unsigned int len, + int write_to_vm, gfp_t gfp_mask) { struct sg_iovec iov; iov.iov_base = (void __user *)uaddr; iov.iov_len = len; - return bio_copy_user_iov(q, &iov, 1, write_to_vm, gfp_mask); + return bio_copy_user_iov(q, map_data, &iov, 1, write_to_vm, gfp_mask); } static struct bio *__bio_map_user_iov(struct request_queue *q, @@ -1028,7 +1052,7 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, bio->bi_private = bmd; bio->bi_end_io = bio_copy_kern_endio; - bio_set_map_data(bmd, bio, &iov, 1); + bio_set_map_data(bmd, bio, &iov, 1, 1); return bio; cleanup: bio_for_each_segment(bvec, bio, i) diff --git a/include/linux/bio.h b/include/linux/bio.h index 200b185c3e8..bc386cd5e99 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -327,6 +327,7 @@ extern int bio_get_nr_vecs(struct block_device *); extern struct bio *bio_map_user(struct request_queue *, struct block_device *, unsigned long, unsigned int, int, gfp_t); struct sg_iovec; +struct rq_map_data; extern struct bio *bio_map_user_iov(struct request_queue *, struct block_device *, struct sg_iovec *, int, int, gfp_t); @@ -337,9 +338,10 @@ extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int, gfp_t, int); extern void bio_set_pages_dirty(struct bio *bio); extern void bio_check_pages_dirty(struct bio *bio); -extern struct bio *bio_copy_user(struct request_queue *, unsigned long, - unsigned int, int, gfp_t); -extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *, +extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *, + unsigned long, unsigned int, int, gfp_t); +extern struct bio *bio_copy_user_iov(struct request_queue *, + struct rq_map_data *, struct sg_iovec *, int, int, gfp_t); extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 00e388d0e22..358ac423ed2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -642,6 +642,12 @@ static inline void blk_queue_bounce(struct request_queue *q, struct bio **bio) } #endif /* CONFIG_MMU */ +struct rq_map_data { + struct page **pages; + int page_order; + int nr_entries; +}; + struct req_iterator { int i; struct bio *bio; @@ -711,11 +717,13 @@ extern void __blk_run_queue(struct request_queue *); extern void blk_run_queue(struct request_queue *); extern void blk_start_queueing(struct request_queue *); extern int blk_rq_map_user(struct request_queue *, struct request *, - void __user *, unsigned long, gfp_t); + struct rq_map_data *, void __user *, unsigned long, + gfp_t); extern int blk_rq_unmap_user(struct bio *); extern int blk_rq_map_kern(struct request_queue *, struct request *, void *, unsigned int, gfp_t); extern int blk_rq_map_user_iov(struct request_queue *, struct request *, - struct sg_iovec *, int, unsigned int, gfp_t); + struct rq_map_data *, struct sg_iovec *, int, + unsigned int, gfp_t); extern int blk_execute_rq(struct request_queue *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, -- GitLab From 10865dfa34e7552c4c64606edcdf1e21a110c985 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 16:17:07 +0900 Subject: [PATCH 3443/5416] sg: convert the non-data path to use the block layer This patch converts the non data path to use the block layer functions (blk_get_request, blk_execute_rq_nowait, etc) instead of uses scsi_execute_async(). Signed-off-by: FUJITA Tomonori Signed-off-by: Douglas Gilbert Cc: Mike Christie Cc: James Bottomley Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 53 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 661f9f21650..487c7776cc4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -137,6 +137,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ char orphan; /* 1 -> drop on sight, 0 -> normal */ char sg_io_owned; /* 1 -> packet belongs to SG_IO */ volatile char done; /* 0->before bh, 1->before read, 2->read */ + struct request *rq; } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ @@ -176,7 +177,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ static int sg_fasync(int fd, struct file *filp, int mode); /* tasklet or soft irq callback */ static void sg_cmd_done(void *data, char *sense, int result, int resid); -static int sg_start_req(Sg_request * srp); +static int sg_start_req(Sg_request *srp, unsigned char *cmd); static void sg_finish_rem_req(Sg_request * srp); static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, @@ -229,6 +230,11 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) cmd, filp->f_mode & FMODE_WRITE); } +static void sg_rq_end_io(struct request *rq, int uptodate) +{ + sg_cmd_done(rq->end_io_data, rq->sense, rq->errors, rq->data_len); +} + static int sg_open(struct inode *inode, struct file *filp) { @@ -732,7 +738,8 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) cmnd[0], (int) hp->cmd_len)); - if ((k = sg_start_req(srp))) { + k = sg_start_req(srp, cmnd); + if (k) { SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ @@ -765,6 +772,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->duration = jiffies_to_msecs(jiffies); /* Now send everything of to mid-level. The next time we hear about this packet is when sg_cmd_done() is called (i.e. a callback). */ + if (srp->rq) { + srp->rq->timeout = timeout; + blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, + srp->rq, 1, sg_rq_end_io); + return 0; + } if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, hp->dxfer_len, srp->data.k_use_sg, timeout, SG_DEFAULT_RETRIES, srp, sg_cmd_done, @@ -1634,8 +1647,32 @@ exit_sg(void) idr_destroy(&sg_index_idr); } -static int -sg_start_req(Sg_request * srp) +static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp, + unsigned char *cmd) +{ + struct sg_fd *sfp = srp->parentfp; + struct request_queue *q = sfp->parentdp->device->request_queue; + struct request *rq; + int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + + rq = blk_get_request(q, rw, GFP_ATOMIC); + if (!rq) + return -ENOMEM; + + memcpy(rq->cmd, cmd, hp->cmd_len); + + rq->cmd_len = hp->cmd_len; + rq->cmd_type = REQ_TYPE_BLOCK_PC; + + srp->rq = rq; + rq->end_io_data = srp; + rq->sense = srp->sense_b; + rq->retries = SG_DEFAULT_RETRIES; + + return 0; +} + +static int sg_start_req(Sg_request *srp, unsigned char *cmd) { int res; Sg_fd *sfp = srp->parentfp; @@ -1646,8 +1683,10 @@ sg_start_req(Sg_request * srp) Sg_scatter_hold *rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); + if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) - return 0; + return __sg_start_req(srp, hp, cmd); + if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && (!sfp->parentdp->device->host->unchecked_isa_dma)) { @@ -1678,6 +1717,10 @@ sg_finish_rem_req(Sg_request * srp) sg_unlink_reserve(sfp, srp); else sg_remove_scat(req_schp); + + if (srp->rq) + blk_put_request(srp->rq); + sg_remove_request(sfp, srp); } -- GitLab From 6e5a30cba5e7c03b2cd564e968f1dd667a0f7c42 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 16:17:08 +0900 Subject: [PATCH 3444/5416] sg: convert the direct IO path to use the block layer This patch converts the direct IO path (SG_FLAG_DIRECT_IO) to use the block layer functions (blk_get_request, blk_execute_rq_nowait, blk_rq_map_user, etc) instead of scsi_execute_async(). Signed-off-by: FUJITA Tomonori Signed-off-by: Douglas Gilbert Cc: Mike Christie Cc: James Bottomley Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 173 ++++++++-------------------------------------- 1 file changed, 27 insertions(+), 146 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 487c7776cc4..cb6de0752ee 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -138,6 +138,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ char sg_io_owned; /* 1 -> packet belongs to SG_IO */ volatile char done; /* 0->before bh, 1->before read, 2->read */ struct request *rq; + struct bio *bio; } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ @@ -1679,21 +1680,29 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) sg_io_hdr_t *hp = &srp->header; int dxfer_len = (int) hp->dxfer_len; int dxfer_dir = hp->dxfer_direction; + unsigned long uaddr = (unsigned long)hp->dxferp; Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; + struct request_queue *q = sfp->parentdp->device->request_queue; + unsigned long alignment = queue_dma_alignment(q) | q->dma_pad_mask; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return __sg_start_req(srp, hp, cmd); +#ifdef SG_ALLOW_DIO_CODE if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && - (!sfp->parentdp->device->host->unchecked_isa_dma)) { - res = sg_build_direct(srp, sfp, dxfer_len); - if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */ - return res; + (!sfp->parentdp->device->host->unchecked_isa_dma) && + !(uaddr & alignment) && !(dxfer_len & alignment)) { + res = __sg_start_req(srp, hp, cmd); + if (!res) + res = sg_build_direct(srp, sfp, dxfer_len); + + return res; } +#endif if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) sg_link_reserve(sfp, srp, dxfer_len); else { @@ -1718,8 +1727,11 @@ sg_finish_rem_req(Sg_request * srp) else sg_remove_scat(req_schp); - if (srp->rq) + if (srp->rq) { + if (srp->bio) + blk_rq_unmap_user(srp->bio); blk_put_request(srp->rq); + } sg_remove_request(sfp, srp); } @@ -1746,151 +1758,23 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) return tablesize; /* number of scat_gath elements allocated */ } -#ifdef SG_ALLOW_DIO_CODE -/* vvvvvvvv following code borrowed from st driver's direct IO vvvvvvvvv */ - /* TODO: hopefully we can use the generic block layer code */ - -/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if - - mapping of all pages not successful - (i.e., either completely successful or fails) -*/ -static int -st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, - unsigned long uaddr, size_t count, int rw) -{ - unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = uaddr >> PAGE_SHIFT; - const int nr_pages = end - start; - int res, i, j; - struct page **pages; - - /* User attempted Overflow! */ - if ((uaddr + count) < uaddr) - return -EINVAL; - - /* Too big */ - if (nr_pages > max_pages) - return -ENOMEM; - - /* Hmm? */ - if (count == 0) - return 0; - - if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_ATOMIC)) == NULL) - return -ENOMEM; - - /* Try to fault in all of the necessary pages */ - down_read(¤t->mm->mmap_sem); - /* rw==READ means read from drive, write into memory area */ - res = get_user_pages( - current, - current->mm, - uaddr, - nr_pages, - rw == READ, - 0, /* don't force */ - pages, - NULL); - up_read(¤t->mm->mmap_sem); - - /* Errors and no page mapped should return here */ - if (res < nr_pages) - goto out_unmap; - - for (i=0; i < nr_pages; i++) { - /* FIXME: flush superflous for rw==READ, - * probably wrong function for rw==WRITE - */ - flush_dcache_page(pages[i]); - /* ?? Is locking needed? I don't think so */ - /* if (!trylock_page(pages[i])) - goto out_unlock; */ - } - - sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK); - if (nr_pages > 1) { - sgl[0].length = PAGE_SIZE - sgl[0].offset; - count -= sgl[0].length; - for (i=1; i < nr_pages ; i++) - sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0); - } - else { - sgl[0].length = count; - } - - kfree(pages); - return nr_pages; - - out_unmap: - if (res > 0) { - for (j=0; j < res; j++) - page_cache_release(pages[j]); - res = 0; - } - kfree(pages); - return res; -} - - -/* And unmap them... */ -static int -st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, - int dirtied) -{ - int i; - - for (i=0; i < nr_pages; i++) { - struct page *page = sg_page(&sgl[i]); - - if (dirtied) - SetPageDirty(page); - /* unlock_page(page); */ - /* FIXME: cache flush missing for rw==READ - * FIXME: call the correct reference counting function - */ - page_cache_release(page); - } - - return 0; -} - -/* ^^^^^^^^ above code borrowed from st driver's direct IO ^^^^^^^^^ */ -#endif - - /* Returns: -ve -> error, 0 -> done, 1 -> try indirect */ static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len) { -#ifdef SG_ALLOW_DIO_CODE sg_io_hdr_t *hp = &srp->header; Sg_scatter_hold *schp = &srp->data; - int sg_tablesize = sfp->parentdp->sg_tablesize; - int mx_sc_elems, res; - struct scsi_device *sdev = sfp->parentdp->device; - - if (((unsigned long)hp->dxferp & - queue_dma_alignment(sdev->request_queue)) != 0) - return 1; + int res; + struct request *rq = srp->rq; + struct request_queue *q = sfp->parentdp->device->request_queue; - mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); - if (mx_sc_elems <= 0) { - return 1; - } - res = st_map_user_pages(schp->buffer, mx_sc_elems, - (unsigned long)hp->dxferp, dxfer_len, - (SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0); - if (res <= 0) { - sg_remove_scat(schp); - return 1; - } - schp->k_use_sg = res; + res = blk_rq_map_user(q, rq, NULL, hp->dxferp, dxfer_len, GFP_ATOMIC); + if (res) + return res; + srp->bio = rq->bio; schp->dio_in_use = 1; hp->info |= SG_INFO_DIRECT_IO; return 0; -#else - return 1; -#endif } static int @@ -2069,11 +1953,7 @@ sg_remove_scat(Sg_scatter_hold * schp) if (schp->buffer && (schp->sglist_len > 0)) { struct scatterlist *sg = schp->buffer; - if (schp->dio_in_use) { -#ifdef SG_ALLOW_DIO_CODE - st_unmap_user_pages(sg, schp->k_use_sg, TRUE); -#endif - } else { + if (!schp->dio_in_use) { int k; for (k = 0; (k < schp->k_use_sg) && sg_page(sg); @@ -2083,8 +1963,9 @@ sg_remove_scat(Sg_scatter_hold * schp) k, sg_page(sg), sg->length)); sg_page_free(sg_page(sg), sg->length); } + + kfree(schp->buffer); } - kfree(schp->buffer); } memset(schp, 0, sizeof (*schp)); } -- GitLab From 10db10d144c0248f285242f79daf6b9de6b00a62 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 29 Aug 2008 12:32:18 +0200 Subject: [PATCH 3445/5416] sg: convert the indirect IO path to use the block layer This patch converts the indirect IO path (including mmap IO and old struct sg_header) to use the block layer functions (blk_get_request, blk_execute_rq_nowait, blk_rq_map_user, etc) instead of scsi_execute_async(). [Jens: fixed compile error with SCSI logging enabled] Signed-off-by: FUJITA Tomonori Signed-off-by: Douglas Gilbert Cc: Mike Christie Cc: James Bottomley Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 397 ++++++++++++---------------------------------- 1 file changed, 105 insertions(+), 292 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cb6de0752ee..d6391666502 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -47,7 +47,6 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include #include #include -#include #include #include @@ -119,7 +118,8 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */ unsigned bufflen; /* Size of (aggregate) data buffer */ unsigned b_malloc_len; /* actual len malloc'ed in buffer */ - struct scatterlist *buffer;/* scatter list */ + struct page **pages; + int page_order; char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */ unsigned char cmd_opcode; /* first byte of command */ } Sg_scatter_hold; @@ -190,8 +190,6 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, int read_only, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); -static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, - int wr_xf, int *countp, unsigned char __user **up); static int sg_write_xfer(Sg_request * srp); static int sg_read_xfer(Sg_request * srp); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); @@ -199,8 +197,6 @@ static void sg_remove_scat(Sg_scatter_hold * schp); static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); -static struct page *sg_page_malloc(int rqSz, int lowDma, int *retSzp); -static void sg_page_free(struct page *page, int size); static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev); static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); @@ -771,26 +767,11 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, break; } hp->duration = jiffies_to_msecs(jiffies); -/* Now send everything of to mid-level. The next time we hear about this - packet is when sg_cmd_done() is called (i.e. a callback). */ - if (srp->rq) { - srp->rq->timeout = timeout; - blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, - srp->rq, 1, sg_rq_end_io); - return 0; - } - if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, - hp->dxfer_len, srp->data.k_use_sg, timeout, - SG_DEFAULT_RETRIES, srp, sg_cmd_done, - GFP_ATOMIC)) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: scsi_execute_async failed\n")); - /* - * most likely out of mem, but could also be a bad map - */ - sg_finish_rem_req(srp); - return -ENOMEM; - } else - return 0; + + srp->rq->timeout = timeout; + blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, + srp->rq, 1, sg_rq_end_io); + return 0; } static int @@ -1206,8 +1187,7 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) Sg_fd *sfp; unsigned long offset, len, sa; Sg_scatter_hold *rsv_schp; - struct scatterlist *sg; - int k; + int k, length; if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data))) return VM_FAULT_SIGBUS; @@ -1217,15 +1197,14 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_SIGBUS; SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n", offset, rsv_schp->k_use_sg)); - sg = rsv_schp->buffer; sa = vma->vm_start; - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + length = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { len = vma->vm_end - sa; - len = (len < sg->length) ? len : sg->length; + len = (len < length) ? len : length; if (offset < len) { - struct page *page; - page = virt_to_page(page_address(sg_page(sg)) + offset); + struct page *page = nth_page(rsv_schp->pages[k], + offset >> PAGE_SHIFT); get_page(page); /* increment page count */ vmf->page = page; return 0; /* success */ @@ -1247,8 +1226,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) Sg_fd *sfp; unsigned long req_sz, len, sa; Sg_scatter_hold *rsv_schp; - int k; - struct scatterlist *sg; + int k, length; if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) return -ENXIO; @@ -1262,11 +1240,10 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return -ENOMEM; /* cannot map more than reserved buffer */ sa = vma->vm_start; - sg = rsv_schp->buffer; - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + length = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { len = vma->vm_end - sa; - len = (len < sg->length) ? len : sg->length; + len = (len < length) ? len : length; sa += len; } @@ -1310,7 +1287,6 @@ sg_cmd_done(void *data, char *sense, int result, int resid) if (0 != result) { struct scsi_sense_hdr sshdr; - memcpy(srp->sense_b, sense, sizeof (srp->sense_b)); srp->header.status = 0xff & result; srp->header.masked_status = status_byte(result); srp->header.msg_status = msg_byte(result); @@ -1685,34 +1661,51 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) Sg_scatter_hold *rsv_schp = &sfp->reserve; struct request_queue *q = sfp->parentdp->device->request_queue; unsigned long alignment = queue_dma_alignment(q) | q->dma_pad_mask; + struct rq_map_data map_data; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); + res = __sg_start_req(srp, hp, cmd); + if (res) + return res; + if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) - return __sg_start_req(srp, hp, cmd); + return 0; #ifdef SG_ALLOW_DIO_CODE if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && (!sfp->parentdp->device->host->unchecked_isa_dma) && - !(uaddr & alignment) && !(dxfer_len & alignment)) { - res = __sg_start_req(srp, hp, cmd); - if (!res) - res = sg_build_direct(srp, sfp, dxfer_len); - - return res; - } + !(uaddr & alignment) && !(dxfer_len & alignment)) + return sg_build_direct(srp, sfp, dxfer_len); #endif if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) sg_link_reserve(sfp, srp, dxfer_len); - else { + else res = sg_build_indirect(req_schp, sfp, dxfer_len); - if (res) { - sg_remove_scat(req_schp); - return res; - } + + if (!res) { + struct request *rq = srp->rq; + Sg_scatter_hold *schp = &srp->data; + int iovec_count = (int) hp->iovec_count; + + map_data.pages = schp->pages; + map_data.page_order = schp->page_order; + map_data.nr_entries = schp->k_use_sg; + + if (iovec_count) + res = blk_rq_map_user_iov(q, rq, &map_data, hp->dxferp, + iovec_count, + hp->dxfer_len, GFP_ATOMIC); + else + res = blk_rq_map_user(q, rq, &map_data, hp->dxferp, + hp->dxfer_len, GFP_ATOMIC); + + if (!res) + srp->bio = rq->bio; } - return 0; + + return res; } static void @@ -1730,6 +1723,7 @@ sg_finish_rem_req(Sg_request * srp) if (srp->rq) { if (srp->bio) blk_rq_unmap_user(srp->bio); + blk_put_request(srp->rq); } @@ -1739,21 +1733,12 @@ sg_finish_rem_req(Sg_request * srp) static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) { - int sg_bufflen = tablesize * sizeof(struct scatterlist); + int sg_bufflen = tablesize * sizeof(struct page *); gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN; - /* - * TODO: test without low_dma, we should not need it since - * the block layer will bounce the buffer for us - * - * XXX(hch): we shouldn't need GFP_DMA for the actual S/G list. - */ - if (sfp->low_dma) - gfp_flags |= GFP_DMA; - schp->buffer = kzalloc(sg_bufflen, gfp_flags); - if (!schp->buffer) + schp->pages = kzalloc(sg_bufflen, gfp_flags); + if (!schp->pages) return -ENOMEM; - sg_init_table(schp->buffer, tablesize); schp->sglist_len = sg_bufflen; return tablesize; /* number of scat_gath elements allocated */ } @@ -1780,11 +1765,10 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len) static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) { - struct scatterlist *sg; - int ret_sz = 0, k, rem_sz, num, mx_sc_elems; + int ret_sz = 0, i, k, rem_sz, num, mx_sc_elems; int sg_tablesize = sfp->parentdp->sg_tablesize; - int blk_size = buff_size; - struct page *p = NULL; + int blk_size = buff_size, order; + gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; if (blk_size < 0) return -EFAULT; @@ -1808,15 +1792,26 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) } else scatter_elem_sz_prev = num; } - for (k = 0, sg = schp->buffer, rem_sz = blk_size; - (rem_sz > 0) && (k < mx_sc_elems); - ++k, rem_sz -= ret_sz, sg = sg_next(sg)) { - + + if (sfp->low_dma) + gfp_mask |= GFP_DMA; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + gfp_mask |= __GFP_ZERO; + + order = get_order(num); +retry: + ret_sz = 1 << (PAGE_SHIFT + order); + + for (k = 0, rem_sz = blk_size; rem_sz > 0 && k < mx_sc_elems; + k++, rem_sz -= ret_sz) { + num = (rem_sz > scatter_elem_sz_prev) ? - scatter_elem_sz_prev : rem_sz; - p = sg_page_malloc(num, sfp->low_dma, &ret_sz); - if (!p) - return -ENOMEM; + scatter_elem_sz_prev : rem_sz; + + schp->pages[k] = alloc_pages(gfp_mask, order); + if (!schp->pages[k]) + goto out; if (num == scatter_elem_sz_prev) { if (unlikely(ret_sz > scatter_elem_sz_prev)) { @@ -1824,12 +1819,12 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = ret_sz; } } - sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0); SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " "ret_sz=%d\n", k, num, ret_sz)); } /* end of for loop */ + schp->page_order = order; schp->k_use_sg = k; SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " "rem_sz=%d\n", k, rem_sz)); @@ -1837,8 +1832,15 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) schp->bufflen = blk_size; if (rem_sz > 0) /* must have failed */ return -ENOMEM; - return 0; +out: + for (i = 0; i < k; i++) + __free_pages(schp->pages[k], order); + + if (--order >= 0) + goto retry; + + return -ENOMEM; } static int @@ -1846,13 +1848,8 @@ sg_write_xfer(Sg_request * srp) { sg_io_hdr_t *hp = &srp->header; Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; int num_xfer = 0; - int j, k, onum, usglen, ksglen, res; - int iovec_count = (int) hp->iovec_count; int dxfer_dir = hp->dxfer_direction; - unsigned char *p; - unsigned char __user *up; int new_interface = ('\0' == hp->interface_id) ? 0 : 1; if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) || @@ -1866,83 +1863,9 @@ sg_write_xfer(Sg_request * srp) && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) return 0; - SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n", - num_xfer, iovec_count, schp->k_use_sg)); - if (iovec_count) { - onum = iovec_count; - if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum)) - return -EFAULT; - } else - onum = 1; - - ksglen = sg->length; - p = page_address(sg_page(sg)); - for (j = 0, k = 0; j < onum; ++j) { - res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up); - if (res) - return res; - - for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg_page(sg))) { - if (usglen <= 0) - break; - if (ksglen > usglen) { - if (usglen >= num_xfer) { - if (__copy_from_user(p, up, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_from_user(p, up, usglen)) - return -EFAULT; - p += usglen; - ksglen -= usglen; - break; - } else { - if (ksglen >= num_xfer) { - if (__copy_from_user(p, up, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_from_user(p, up, ksglen)) - return -EFAULT; - up += ksglen; - usglen -= ksglen; - } - ++k; - if (k >= schp->k_use_sg) - return 0; - } - } - - return 0; -} + SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, k_use_sg=%d\n", + num_xfer, schp->k_use_sg)); -static int -sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, - int wr_xf, int *countp, unsigned char __user **up) -{ - int num_xfer = (int) hp->dxfer_len; - unsigned char __user *p = hp->dxferp; - int count; - - if (0 == sg_num) { - if (wr_xf && ('\0' == hp->interface_id)) - count = (int) hp->flags; /* holds "old" input_size */ - else - count = num_xfer; - } else { - sg_iovec_t iovec; - if (__copy_from_user(&iovec, p + ind*SZ_SG_IOVEC, SZ_SG_IOVEC)) - return -EFAULT; - p = iovec.iov_base; - count = (int) iovec.iov_len; - } - if (!access_ok(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count)) - return -EFAULT; - if (up) - *up = p; - if (countp) - *countp = count; return 0; } @@ -1950,21 +1873,18 @@ static void sg_remove_scat(Sg_scatter_hold * schp) { SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); - if (schp->buffer && (schp->sglist_len > 0)) { - struct scatterlist *sg = schp->buffer; - + if (schp->pages && schp->sglist_len > 0) { if (!schp->dio_in_use) { int k; - for (k = 0; (k < schp->k_use_sg) && sg_page(sg); - ++k, sg = sg_next(sg)) { + for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { SCSI_LOG_TIMEOUT(5, printk( - "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", - k, sg_page(sg), sg->length)); - sg_page_free(sg_page(sg), sg->length); + "sg_remove_scat: k=%d, pg=0x%p\n", + k, schp->pages[k])); + __free_pages(schp->pages[k], schp->page_order); } - kfree(schp->buffer); + kfree(schp->pages); } } memset(schp, 0, sizeof (*schp)); @@ -1975,13 +1895,8 @@ sg_read_xfer(Sg_request * srp) { sg_io_hdr_t *hp = &srp->header; Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; int num_xfer = 0; - int j, k, onum, usglen, ksglen, res; - int iovec_count = (int) hp->iovec_count; int dxfer_dir = hp->dxfer_direction; - unsigned char *p; - unsigned char __user *up; int new_interface = ('\0' == hp->interface_id) ? 0 : 1; if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir) @@ -1996,53 +1911,7 @@ sg_read_xfer(Sg_request * srp) return 0; SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n", - num_xfer, iovec_count, schp->k_use_sg)); - if (iovec_count) { - onum = iovec_count; - if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum)) - return -EFAULT; - } else - onum = 1; - - p = page_address(sg_page(sg)); - ksglen = sg->length; - for (j = 0, k = 0; j < onum; ++j) { - res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up); - if (res) - return res; - - for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg_page(sg))) { - if (usglen <= 0) - break; - if (ksglen > usglen) { - if (usglen >= num_xfer) { - if (__copy_to_user(up, p, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_to_user(up, p, usglen)) - return -EFAULT; - p += usglen; - ksglen -= usglen; - break; - } else { - if (ksglen >= num_xfer) { - if (__copy_to_user(up, p, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_to_user(up, p, ksglen)) - return -EFAULT; - up += ksglen; - usglen -= ksglen; - } - ++k; - if (k >= schp->k_use_sg) - return 0; - } - } - + num_xfer, (int)hp->iovec_count, schp->k_use_sg)); return 0; } @@ -2050,7 +1919,6 @@ static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) { Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; int k, num; SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n", @@ -2058,15 +1926,18 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) if ((!outp) || (num_read_xfer <= 0)) return 0; - for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) { - num = sg->length; + blk_rq_unmap_user(srp->bio); + srp->bio = NULL; + + num = 1 << (PAGE_SHIFT + schp->page_order); + for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { if (num > num_read_xfer) { - if (__copy_to_user(outp, page_address(sg_page(sg)), + if (__copy_to_user(outp, page_address(schp->pages[k]), num_read_xfer)) return -EFAULT; break; } else { - if (__copy_to_user(outp, page_address(sg_page(sg)), + if (__copy_to_user(outp, page_address(schp->pages[k]), num)) return -EFAULT; num_read_xfer -= num; @@ -2101,24 +1972,22 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) { Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; - struct scatterlist *sg = rsv_schp->buffer; int k, num, rem; srp->res_used = 1; SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); rem = size; - for (k = 0; k < rsv_schp->k_use_sg; ++k, sg = sg_next(sg)) { - num = sg->length; + num = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg; k++) { if (rem <= num) { - sfp->save_scat_len = num; - sg->length = rem; req_schp->k_use_sg = k + 1; req_schp->sglist_len = rsv_schp->sglist_len; - req_schp->buffer = rsv_schp->buffer; + req_schp->pages = rsv_schp->pages; req_schp->bufflen = size; req_schp->b_malloc_len = rsv_schp->b_malloc_len; + req_schp->page_order = rsv_schp->page_order; break; } else rem -= num; @@ -2132,22 +2001,13 @@ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) { Sg_scatter_hold *req_schp = &srp->data; - Sg_scatter_hold *rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n", (int) req_schp->k_use_sg)); - if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) { - struct scatterlist *sg = rsv_schp->buffer; - - if (sfp->save_scat_len > 0) - (sg + (req_schp->k_use_sg - 1))->length = - (unsigned) sfp->save_scat_len; - else - SCSI_LOG_TIMEOUT(1, printk ("sg_unlink_reserve: BAD save_scat_len\n")); - } req_schp->k_use_sg = 0; req_schp->bufflen = 0; - req_schp->buffer = NULL; + req_schp->pages = NULL; + req_schp->page_order = 0; req_schp->sglist_len = 0; sfp->save_scat_len = 0; srp->res_used = 0; @@ -2405,53 +2265,6 @@ sg_res_in_use(Sg_fd * sfp) return srp ? 1 : 0; } -/* The size fetched (value output via retSzp) set when non-NULL return */ -static struct page * -sg_page_malloc(int rqSz, int lowDma, int *retSzp) -{ - struct page *resp = NULL; - gfp_t page_mask; - int order, a_size; - int resSz; - - if ((rqSz <= 0) || (NULL == retSzp)) - return resp; - - if (lowDma) - page_mask = GFP_ATOMIC | GFP_DMA | __GFP_COMP | __GFP_NOWARN; - else - page_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; - - for (order = 0, a_size = PAGE_SIZE; a_size < rqSz; - order++, a_size <<= 1) ; - resSz = a_size; /* rounded up if necessary */ - resp = alloc_pages(page_mask, order); - while ((!resp) && order) { - --order; - a_size >>= 1; /* divide by 2, until PAGE_SIZE */ - resp = alloc_pages(page_mask, order); /* try half */ - resSz = a_size; - } - if (resp) { - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - memset(page_address(resp), 0, resSz); - *retSzp = resSz; - } - return resp; -} - -static void -sg_page_free(struct page *page, int size) -{ - int order, a_size; - - if (!page) - return; - for (order = 0, a_size = PAGE_SIZE; a_size < size; - order++, a_size <<= 1) ; - __free_pages(page, order); -} - #ifdef CONFIG_SCSI_PROC_FS static int sg_idr_max_id(int id, void *p, void *data) -- GitLab From 4d8ab62e087d9300883b82c2662e73e6eef803a3 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 15:05:57 +0900 Subject: [PATCH 3446/5416] bio: convert bio_copy_kern to use bio_copy_user bio_copy_kern and bio_copy_user are very similar. This converts bio_copy_kern to use bio_copy_user. Signed-off-by: FUJITA Tomonori Cc: Jens Axboe Signed-off-by: Jens Axboe --- fs/bio.c | 54 ++++-------------------------------------------------- 1 file changed, 4 insertions(+), 50 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index a2f072647cd..9d68ddb89b7 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -995,48 +995,13 @@ static void bio_copy_kern_endio(struct bio *bio, int err) struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, gfp_t gfp_mask, int reading) { - unsigned long kaddr = (unsigned long)data; - unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = kaddr >> PAGE_SHIFT; - const int nr_pages = end - start; struct bio *bio; struct bio_vec *bvec; - struct bio_map_data *bmd; - int i, ret; - struct sg_iovec iov; - - iov.iov_base = data; - iov.iov_len = len; - - bmd = bio_alloc_map_data(nr_pages, 1, gfp_mask); - if (!bmd) - return ERR_PTR(-ENOMEM); - - ret = -ENOMEM; - bio = bio_alloc(gfp_mask, nr_pages); - if (!bio) - goto out_bmd; - - while (len) { - struct page *page; - unsigned int bytes = PAGE_SIZE; - - if (bytes > len) - bytes = len; - - page = alloc_page(q->bounce_gfp | gfp_mask); - if (!page) { - ret = -ENOMEM; - goto cleanup; - } - - if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) { - ret = -EINVAL; - goto cleanup; - } + int i; - len -= bytes; - } + bio = bio_copy_user(q, NULL, (unsigned long)data, len, 1, gfp_mask); + if (IS_ERR(bio)) + return bio; if (!reading) { void *p = data; @@ -1049,20 +1014,9 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, } } - bio->bi_private = bmd; bio->bi_end_io = bio_copy_kern_endio; - bio_set_map_data(bmd, bio, &iov, 1, 1); return bio; -cleanup: - bio_for_each_segment(bvec, bio, i) - __free_page(bvec->bv_page); - - bio_put(bio); -out_bmd: - bio_free_map_data(bmd); - - return ERR_PTR(ret); } /* -- GitLab From 879040742cf09f2360a9ac41846288707e4e567c Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 15:05:58 +0900 Subject: [PATCH 3447/5416] block: add blk_rq_aligned helper function This adds blk_rq_aligned helper function to see if alignment and padding requirement is satisfied for DMA transfer. This also converts blk_rq_map_kern and __blk_rq_map_user to use the helper function. Signed-off-by: FUJITA Tomonori Cc: Jens Axboe Signed-off-by: Jens Axboe --- block/blk-map.c | 12 ++---------- include/linux/blkdev.h | 7 +++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index dad6a290783..572140cda5f 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -45,7 +45,6 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, unsigned int len, gfp_t gfp_mask) { unsigned long uaddr; - unsigned int alignment; struct bio *bio, *orig_bio; int reading, ret; @@ -56,8 +55,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * direct dma. else, set up kernel bounce buffers */ uaddr = (unsigned long) ubuf; - alignment = queue_dma_alignment(q) | q->dma_pad_mask; - if (!(uaddr & alignment) && !(len & alignment) && !map_data) + if (blk_rq_aligned(q, ubuf, len) && !map_data) bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); else bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask); @@ -274,8 +272,6 @@ EXPORT_SYMBOL(blk_rq_unmap_user); int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, unsigned int len, gfp_t gfp_mask) { - unsigned long kaddr; - unsigned int alignment; int reading = rq_data_dir(rq) == READ; int do_copy = 0; struct bio *bio; @@ -285,11 +281,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, if (!len || !kbuf) return -EINVAL; - kaddr = (unsigned long)kbuf; - alignment = queue_dma_alignment(q) | q->dma_pad_mask; - do_copy = ((kaddr & alignment) || (len & alignment) || - object_is_on_stack(kbuf)); - + do_copy = !blk_rq_aligned(q, kbuf, len) || object_is_on_stack(kbuf); if (do_copy) bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); else diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 358ac423ed2..9c254926042 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -899,6 +899,13 @@ static inline int queue_dma_alignment(struct request_queue *q) return q ? q->dma_alignment : 511; } +static inline int blk_rq_aligned(struct request_queue *q, void *addr, + unsigned int len) +{ + unsigned int alignment = queue_dma_alignment(q) | q->dma_pad_mask; + return !((unsigned long)addr & alignment) && !(len & alignment); +} + /* assumes size > 256 */ static inline unsigned int blksize_bits(unsigned int size) { -- GitLab From 01cfcddd98f09e05a2e36031654ed46643b76f23 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 28 Aug 2008 15:05:59 +0900 Subject: [PATCH 3448/5416] sg: use blk_rq_aligned helper function Signed-off-by: FUJITA Tomonori Cc: Douglas Gilbert Cc: Jens Axboe Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index d6391666502..ed69292babd 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1656,11 +1656,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) sg_io_hdr_t *hp = &srp->header; int dxfer_len = (int) hp->dxfer_len; int dxfer_dir = hp->dxfer_direction; - unsigned long uaddr = (unsigned long)hp->dxferp; Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; struct request_queue *q = sfp->parentdp->device->request_queue; - unsigned long alignment = queue_dma_alignment(q) | q->dma_pad_mask; struct rq_map_data map_data; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); @@ -1676,7 +1674,7 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && (!sfp->parentdp->device->host->unchecked_isa_dma) && - !(uaddr & alignment) && !(dxfer_len & alignment)) + blk_rq_aligned(q, hp->dxferp, dxfer_len)) return sg_build_direct(srp, sfp, dxfer_len); #endif if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) -- GitLab From aeb3d3a81e81c6323a17fe914e91eb228b3f1aa1 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Thu, 28 Aug 2008 09:27:42 +0200 Subject: [PATCH 3449/5416] block: kmalloc args reversed, small function definition fixes Noticed by sparse: block/blk-softirq.c:156:12: warning: symbol 'blk_softirq_init' was not declared. Should it be static? block/genhd.c:583:28: warning: function 'bdget_disk' with external linkage has definition block/genhd.c:659:17: warning: incorrect type in argument 1 (different base types) block/genhd.c:659:17: expected unsigned int [unsigned] [usertype] size block/genhd.c:659:17: got restricted gfp_t block/genhd.c:659:29: warning: incorrect type in argument 2 (different base types) block/genhd.c:659:29: expected restricted gfp_t [usertype] flags block/genhd.c:659:29: got unsigned int block: kmalloc args reversed Signed-off-by: Harvey Harrison Signed-off-by: Jens Axboe --- block/blk-settings.c | 2 +- block/genhd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index a60e959a12c..d70692badcd 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -443,7 +443,7 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask) } EXPORT_SYMBOL(blk_queue_update_dma_alignment); -int __init blk_settings_init(void) +static int __init blk_settings_init(void) { blk_max_low_pfn = max_low_pfn - 1; blk_max_pfn = max_pfn - 1; diff --git a/block/genhd.c b/block/genhd.c index d9de3e482d1..32ee73c6756 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -578,7 +578,7 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) * RETURNS: * Resulting block_device on success, NULL on failure. */ -extern struct block_device *bdget_disk(struct gendisk *disk, int partno) +struct block_device *bdget_disk(struct gendisk *disk, int partno) { struct hd_struct *part; struct block_device *bdev = NULL; @@ -654,7 +654,7 @@ static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos) struct class_dev_iter *iter; struct device *dev; - iter = kmalloc(GFP_KERNEL, sizeof(*iter)); + iter = kmalloc(sizeof(*iter), GFP_KERNEL); if (!iter) return ERR_PTR(-ENOMEM); -- GitLab From 759f8ca3048f7438aa3129268d7252552505d662 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 29 Aug 2008 09:06:29 +0200 Subject: [PATCH 3450/5416] Change default value of CONFIG_DEBUG_BLOCK_EXT_DEVT to 'n' It's a debug option that you would explicitly enable to test this feature, we should default it to 'n' to prevent accidental surprises for now. Signed-off-by: Jens Axboe --- lib/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 5a536f703a8..4378d5e923c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -628,7 +628,7 @@ config DEBUG_BLOCK_EXT_DEVT bool "Force extended block device numbers and spread them" depends on DEBUG_KERNEL depends on BLOCK - default y + default n help Conventionally, block device numbers are allocated from predetermined contiguous area. However, extended block area -- GitLab From 2bbedcb4c1abac498f18e5770d62ae66ff235ada Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Aug 2008 11:41:51 +0200 Subject: [PATCH 3451/5416] block: don't test for partition size in bdget_disk() and blk_lookup_devt() bdget_disk() and blk_lookup_devt() never cared whether the specified partition (or disk) is zero sized or not. I got confused while converting those not to depend on consecutive minor numbers in commit 5a6411b1178baf534aa9138052864dfa89d3eada and later when dev0 was added it broke callers which expected to get valid return for zero sized disk devices. So, they never needed nr_sects checks in the first place. Kill them. This problem was spotted and debugged by Bartlmoiej Zolnierkiewicz. Signed-off-by: Tejun Heo Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Jens Axboe --- block/genhd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 32ee73c6756..ed926b760ca 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -584,7 +584,7 @@ struct block_device *bdget_disk(struct gendisk *disk, int partno) struct block_device *bdev = NULL; part = disk_get_part(disk, partno); - if (part && (part->nr_sects || partno == 0)) + if (part) bdev = bdget(part_devt(part)); disk_put_part(part); @@ -1031,7 +1031,7 @@ dev_t blk_lookup_devt(const char *name, int partno) continue; part = disk_get_part(disk, partno); - if (part && (part->nr_sects || partno == 0)) { + if (part) { devt = part_devt(part); disk_put_part(part); break; -- GitLab From 55dc7db70a73a3809a2334063c9b5b0d8ccebdaa Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 1 Sep 2008 13:44:35 +0200 Subject: [PATCH 3452/5416] init: DEBUG_BLOCK_EXT_DEVT requires explicit root= param DEBUG_BLOCK_EXT_DEVT shuffles SCSI and IDE device numbers and root device number set using rdev become meaningless. Root devices should be explicitly specified using textual names. Warn about it if root can't be found and DEBUG_BLOCK_EXT_DEVT is enabled. Also, add warning to the help text. Signed-off-by: Tejun Heo Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Jens Axboe --- init/do_mounts.c | 4 ++++ lib/Kconfig.debug | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/init/do_mounts.c b/init/do_mounts.c index 3715feb8446..d055b1914c3 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -263,6 +263,10 @@ retry: printk("Please append a correct \"root=\" boot option; here are the available partitions:\n"); printk_all_partitions(); +#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT + printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify " + "explicit textual name for \"root=\" boot option.\n"); +#endif panic("VFS: Unable to mount root fs on %s", b); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 4378d5e923c..c556896abe5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -638,6 +638,12 @@ config DEBUG_BLOCK_EXT_DEVT userland code paths which assume predetermined contiguous device number allocation. + Note that turning on this debug option shuffles all the + device numbers for all IDE and SCSI devices including libata + ones, so root partition specified using device number + directly (via rdev or root=MAJ:MIN) won't work anymore. + Textual device names (root=/dev/sdXn) will continue to work. + Say N if you are unsure. config LKDTM -- GitLab From 839e96afba87117befd39cf4e43f156edc8047a7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 2 Sep 2008 09:25:21 +0200 Subject: [PATCH 3453/5416] block: update comment on end_request() It refers to functions that no longer exist after the IO completion changes. Signed-off-by: Jens Axboe --- block/blk-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 5bf806adc77..f25eb9786d9 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1780,9 +1780,9 @@ EXPORT_SYMBOL(end_dequeued_request); * they have a residual value to account for. For that case this function * isn't really useful, unless the residual just happens to be the * full current segment. In other words, don't use this function in new - * code. Either use end_request_completely(), or the - * end_that_request_chunk() (along with end_that_request_last()) for - * partial completions. + * code. Use blk_end_request() or __blk_end_request() to end partial parts + * of a request, or end_dequeued_request() and end_queued_request() to + * completely end IO on a dequeued/queued request. * **/ void end_request(struct request *req, int uptodate) -- GitLab From 818827669d85b84241696ffef2de485db46b0b5e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 16:20:19 +0900 Subject: [PATCH 3454/5416] block: make blk_rq_map_user take a NULL user-space buffer This patch changes blk_rq_map_user to accept a NULL user-space buffer with a READ command if rq_map_data is not NULL. Thus a caller can pass page frames to lk_rq_map_user to just set up a request and bios with page frames propely. bio_uncopy_user (called via blk_rq_unmap_user) doesn't copy data to user space with such request. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- block/blk-map.c | 16 ++++++++++++---- fs/bio.c | 8 ++++---- include/linux/bio.h | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index 572140cda5f..4849fa36161 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -42,7 +42,7 @@ static int __blk_rq_unmap_user(struct bio *bio) static int __blk_rq_map_user(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, void __user *ubuf, - unsigned int len, gfp_t gfp_mask) + unsigned int len, int null_mapped, gfp_t gfp_mask) { unsigned long uaddr; struct bio *bio, *orig_bio; @@ -63,6 +63,9 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, if (IS_ERR(bio)) return PTR_ERR(bio); + if (null_mapped) + bio->bi_flags |= (1 << BIO_NULL_MAPPED); + orig_bio = bio; blk_queue_bounce(q, &bio); @@ -111,12 +114,17 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, { unsigned long bytes_read = 0; struct bio *bio = NULL; - int ret; + int ret, null_mapped = 0; if (len > (q->max_hw_sectors << 9)) return -EINVAL; - if (!len || !ubuf) + if (!len) return -EINVAL; + if (!ubuf) { + if (!map_data || rq_data_dir(rq) != READ) + return -EINVAL; + null_mapped = 1; + } while (bytes_read != len) { unsigned long map_len, end, start; @@ -135,7 +143,7 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, map_len -= PAGE_SIZE; ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, - gfp_mask); + null_mapped, gfp_mask); if (ret < 0) goto unmap_rq; if (!bio) diff --git a/fs/bio.c b/fs/bio.c index 9d68ddb89b7..355302985e2 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -547,11 +547,11 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, int bio_uncopy_user(struct bio *bio) { struct bio_map_data *bmd = bio->bi_private; - int ret; - - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1, - bmd->is_our_pages); + int ret = 0; + if (!bio_flagged(bio, BIO_NULL_MAPPED)) + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, + bmd->nr_sgvecs, 1, bmd->is_our_pages); bio_free_map_data(bmd); bio_put(bio); return ret; diff --git a/include/linux/bio.h b/include/linux/bio.h index bc386cd5e99..7af373f253d 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -108,6 +108,7 @@ struct bio { #define BIO_USER_MAPPED 6 /* contains user pages */ #define BIO_EOPNOTSUPP 7 /* not supported */ #define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ +#define BIO_NULL_MAPPED 9 /* contains invalid user pages */ #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) /* -- GitLab From fad7f01e61bf737fe8a3740d803f000db57ecac6 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 16:20:20 +0900 Subject: [PATCH 3455/5416] sg: set dxferp to NULL for READ with the older SG interface With the older SG interface, we don't know a user-space address to trasfer data when executing a SCSI command. So we can't pass a user-space address to blk_rq_map_user. This patch fixes sg to pass a NULL user-space address to blk_rq_map_user so that it just sets up a request and bios with page frames propely without data transfer. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ed69292babd..50c07bca727 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -615,7 +615,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) else hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; hp->dxfer_len = mxsize; - hp->dxferp = (char __user *)buf + cmd_size; + if (hp->dxfer_direction == SG_DXFER_TO_DEV) + hp->dxferp = (char __user *)buf + cmd_size; + else + hp->dxferp = NULL; hp->sbp = NULL; hp->timeout = old_hdr.reply_len; /* structure abuse ... */ hp->flags = input_size; /* structure abuse ... */ -- GitLab From 243294dae09c909c0442c8f04d470b69c3c19d6e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 4 Sep 2008 09:17:31 +0200 Subject: [PATCH 3456/5416] block: fix duplicate headers for /proc/partitions seqf can be started multiple times for a read and the header should be printed only for the initial one. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- block/genhd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/genhd.c b/block/genhd.c index ed926b760ca..8acaff0154e 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -697,7 +697,7 @@ static void *show_partition_start(struct seq_file *seqf, loff_t *pos) static void *p; p = disk_seqf_start(seqf, pos); - if (!IS_ERR(p) && p) + if (!IS_ERR(p) && p && !*pos) seq_puts(seqf, "major minor #blocks name\n\n"); return p; } -- GitLab From 0c002c2f74e10baa9021d3ecc50585c6eafea568 Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:20 -0600 Subject: [PATCH 3457/5416] Wrapper for lower-level revalidate_disk routines. This is a wrapper for the lower-level revalidate_disk call-backs such as sd_revalidate_disk(). It allows us to perform pre and post operations when calling them. We will use this wrapper in a later patch to adjust block device sizes after an online resize (a _post_ operation). Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- fs/block_dev.c | 21 +++++++++++++++++++++ include/linux/fs.h | 1 + 2 files changed, 22 insertions(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index c3fa19bd64d..4eeb69a8873 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -852,6 +852,27 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) EXPORT_SYMBOL(open_by_devnum); +/** + * revalidate_disk - wrapper for lower-level driver's revalidate_disk + * call-back + * + * @disk: struct gendisk to be revalidated + * + * This routine is a wrapper for lower-level driver's revalidate_disk + * call-backs. It is used to do common pre and post operations needed + * for all revalidate_disk operations. + */ +int revalidate_disk(struct gendisk *disk) +{ + int ret = 0; + + if (disk->fops->revalidate_disk) + ret = disk->fops->revalidate_disk(disk); + + return ret; +} +EXPORT_SYMBOL(revalidate_disk); + /* * This routine checks whether a removable media has been changed, * and invalidates all buffer-cache-entries in that case. This diff --git a/include/linux/fs.h b/include/linux/fs.h index 02a9fb5a830..d63461f9798 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1722,6 +1722,7 @@ extern int fs_may_remount_ro(struct super_block *); */ #define bio_data_dir(bio) ((bio)->bi_rw & 1) +extern int revalidate_disk(struct gendisk *); extern int check_disk_change(struct block_device *); extern int __invalidate_device(struct block_device *); extern int invalidate_partition(struct gendisk *, int); -- GitLab From c3279d1454cdfed02a557d789d8a6d08ab4cbe70 Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:25 -0600 Subject: [PATCH 3458/5416] Adjust block device size after an online resize of a disk. The revalidate_disk routine now checks if a disk has been resized by comparing the gendisk capacity to the bdev inode size. If they are different (usually because the disk has been resized underneath the kernel) the bdev inode size is adjusted to match the capacity. Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- fs/block_dev.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index 4eeb69a8873..b721955d382 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -852,6 +852,34 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) EXPORT_SYMBOL(open_by_devnum); +/** + * check_disk_size_change - checks for disk size change and adjusts + * bdev size. + * + * @disk: struct gendisk to check + * @bdev: struct bdev to adjust. + * + * This routine checks to see if the bdev size does not match the disk size + * and adjusts it if it differs. + */ +void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) +{ + loff_t disk_size, bdev_size; + + disk_size = (loff_t)get_capacity(disk) << 9; + bdev_size = i_size_read(bdev->bd_inode); + if (disk_size != bdev_size) { + char name[BDEVNAME_SIZE]; + + disk_name(disk, 0, name); + printk(KERN_INFO + "%s: detected capacity change from %lld to %lld\n", + name, bdev_size, disk_size); + i_size_write(bdev->bd_inode, disk_size); + } +} +EXPORT_SYMBOL(check_disk_size_change); + /** * revalidate_disk - wrapper for lower-level driver's revalidate_disk * call-back @@ -864,11 +892,20 @@ EXPORT_SYMBOL(open_by_devnum); */ int revalidate_disk(struct gendisk *disk) { + struct block_device *bdev; int ret = 0; if (disk->fops->revalidate_disk) ret = disk->fops->revalidate_disk(disk); + bdev = bdget_disk(disk, 0); + if (!bdev) + return ret; + + mutex_lock(&bdev->bd_mutex); + check_disk_size_change(disk, bdev); + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); return ret; } EXPORT_SYMBOL(revalidate_disk); diff --git a/include/linux/fs.h b/include/linux/fs.h index d63461f9798..32477e8872d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1722,6 +1722,8 @@ extern int fs_may_remount_ro(struct super_block *); */ #define bio_data_dir(bio) ((bio)->bi_rw & 1) +extern void check_disk_size_change(struct gendisk *disk, + struct block_device *bdev); extern int revalidate_disk(struct gendisk *); extern int check_disk_change(struct block_device *); extern int __invalidate_device(struct block_device *); -- GitLab From 9bc3ffbfbdf71fefda8a261ef8d6fdc388a29b42 Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:30 -0600 Subject: [PATCH 3459/5416] Check for device resize when rescanning partitions Check for device resize in the rescan_partitions() routine. If the device has been resized, the bdev size is set to match. The rescan_partitions() routine is called when opening the device and when calling the BLKRRPART ioctl. Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- fs/partitions/check.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 0e411603fdf..7408227c49c 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -504,7 +504,6 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) res = invalidate_partition(disk, 0); if (res) return res; - bdev->bd_invalidated = 0; disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); while ((part = disk_part_iter_next(&piter))) @@ -513,6 +512,8 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); + check_disk_size_change(disk, bdev); + bdev->bd_invalidated = 0; if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) return 0; if (IS_ERR(state)) /* I/O error reading the partition table */ -- GitLab From f98a8cae12f2b2a8f9bfd7a53c990a1a405e880e Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:35 -0600 Subject: [PATCH 3460/5416] SCSI sd driver calls revalidate_disk wrapper. Modify the SCSI disk driver to call the revalidate_disk() wrapper. This allows us to do some housekeeping such as accounting for a disk being resized online. The wrapper will call sd_revalidate_disk() at the appropriate time. Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bcb04b2a767..cb115d1bf22 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -165,7 +165,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, sd_print_sense_hdr(sdkp, &sshdr); return -EINVAL; } - sd_revalidate_disk(sdkp->disk); + revalidate_disk(sdkp->disk); return count; } @@ -916,7 +916,7 @@ static void sd_rescan(struct device *dev) struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (sdkp) { - sd_revalidate_disk(sdkp->disk); + revalidate_disk(sdkp->disk); scsi_disk_put(sdkp); } } -- GitLab From 56ade44b46780fa291fa68b824f1dafdcb11b0ca Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:40 -0600 Subject: [PATCH 3461/5416] Added flush_disk to factor out common buffer cache flushing code. We need to be able to flush the buffer cache for for more than just when a disk is changed, so we factor out common cache flush code in check_disk_change() to an internal flush_disk() routine. This routine will then be used for both disk changes and disk resizes (in a later patch). Include the disk name in the text indicating that there are busy inodes on the device and increase the KERN severity of the message. Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- fs/block_dev.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index b721955d382..33650fc537c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -852,6 +852,32 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) EXPORT_SYMBOL(open_by_devnum); +/** + * flush_disk - invalidates all buffer-cache entries on a disk + * + * @bdev: struct block device to be flushed + * + * Invalidates all buffer-cache entries on a disk. It should be called + * when a disk has been changed -- either by a media change or online + * resize. + */ +static void flush_disk(struct block_device *bdev) +{ + if (__invalidate_device(bdev)) { + char name[BDEVNAME_SIZE] = ""; + + if (bdev->bd_disk) + disk_name(bdev->bd_disk, 0, name); + printk(KERN_WARNING "VFS: busy inodes on changed media or " + "resized disk %s\n", name); + } + + if (!bdev->bd_disk) + return; + if (disk_partitionable(bdev->bd_disk)) + bdev->bd_invalidated = 1; +} + /** * check_disk_size_change - checks for disk size change and adjusts * bdev size. @@ -929,13 +955,9 @@ int check_disk_change(struct block_device *bdev) if (!bdops->media_changed(bdev->bd_disk)) return 0; - if (__invalidate_device(bdev)) - printk("VFS: busy inodes on changed media.\n"); - + flush_disk(bdev); if (bdops->revalidate_disk) bdops->revalidate_disk(bdev->bd_disk); - if (disk_partitionable(bdev->bd_disk)) - bdev->bd_invalidated = 1; return 1; } -- GitLab From 608aeef17a91747d6303de4df5e2c2e6899a95e8 Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Thu, 4 Sep 2008 14:27:45 -0600 Subject: [PATCH 3462/5416] Call flush_disk() after detecting an online resize. We call flush_disk() to make sure the buffer cache for the disk is flushed after a disk resize. There are two resize cases, growing and shrinking. Given that users can shrink/then grow a disk before revalidate_disk() is called, we treat the grow case identically to shrinking. We need to flush the buffer cache after an online shrink because, as James Bottomley puts it, The two use cases for shrinking I can see are 1. planned: the fs is already shrunk to within the new boundaries and all data is relocated, so invalidate is fine (any dirty buffers that might exist in the shrunk region are there only because they were relocated but not yet written to their original location). 2. unplanned: In this case, the fs is probably toast, so whether we invalidate or not isn't going to make a whole lot of difference; it's still going to try to read or write from sectors beyond the new size and get I/O errors. Immediately invalidating shrunk disks will cause errors for outstanding I/Os for reads/write beyond the new end of the disk to be generated earlier then if we waited for the normal buffer cache operation. It also removes a potential security hole where we might keep old data around from beyond the end of the shrunk disk if the disk was not invalidated. Signed-off-by: Andrew Patterson Signed-off-by: Jens Axboe --- fs/block_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index 33650fc537c..57e2786dd2a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -902,6 +902,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) "%s: detected capacity change from %lld to %lld\n", name, bdev_size, disk_size); i_size_write(bdev->bd_inode, disk_size); + flush_disk(bdev); } } EXPORT_SYMBOL(check_disk_size_change); -- GitLab From 242f9dcb8ba6f68fcd217a119a7648a4f69290e9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 14 Sep 2008 05:55:09 -0700 Subject: [PATCH 3463/5416] block: unify request timeout handling Right now SCSI and others do their own command timeout handling. Move those bits to the block layer. Instead of having a timer per command, we try to be a bit more clever and simply have one per-queue. This avoids the overhead of having to tear down and setup a timer for each command, so it will result in a lot less timer fiddling. Signed-off-by: Mike Anderson Signed-off-by: Jens Axboe --- block/Makefile | 4 +- block/blk-core.c | 7 ++ block/blk-settings.c | 12 +++ block/blk-softirq.c | 30 +++--- block/blk-timeout.c | 155 +++++++++++++++++++++++++++ block/blk.h | 24 +++++ block/elevator.c | 8 ++ drivers/ata/libata-eh.c | 13 +-- drivers/ata/libata.h | 2 +- drivers/scsi/aacraid/aachba.c | 2 +- drivers/scsi/gdth.c | 60 +++++++---- drivers/scsi/gdth.h | 2 +- drivers/scsi/gdth_proc.c | 66 ------------ drivers/scsi/gdth_proc.h | 3 - drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- drivers/scsi/ide-scsi.c | 2 +- drivers/scsi/ipr.c | 3 +- drivers/scsi/ips.c | 2 +- drivers/scsi/libiscsi.c | 17 +-- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_internal.h | 2 +- drivers/scsi/libsas/sas_scsi_host.c | 30 +++--- drivers/scsi/megaraid/megaraid_sas.c | 6 +- drivers/scsi/ncr53c8xx.c | 4 +- drivers/scsi/qla1280.c | 4 +- drivers/scsi/qla4xxx/ql4_os.c | 4 +- drivers/scsi/scsi.c | 92 +++------------- drivers/scsi/scsi_error.c | 90 +++------------- drivers/scsi/scsi_lib.c | 17 ++- drivers/scsi/scsi_priv.h | 7 +- drivers/scsi/scsi_sysfs.c | 7 +- drivers/scsi/scsi_transport_fc.c | 6 +- drivers/scsi/sd.c | 9 +- drivers/scsi/sr.c | 5 +- drivers/scsi/sym53c8xx_2/sym_glue.c | 4 +- include/linux/blkdev.h | 20 ++++ include/scsi/scsi_cmnd.h | 3 - include/scsi/scsi_host.h | 9 +- include/scsi/scsi_transport.h | 3 +- 39 files changed, 399 insertions(+), 339 deletions(-) create mode 100644 block/blk-timeout.c diff --git a/block/Makefile b/block/Makefile index 0da976ce67d..bfe73049f93 100644 --- a/block/Makefile +++ b/block/Makefile @@ -4,8 +4,8 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \ blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \ - blk-exec.o blk-merge.o blk-softirq.o ioctl.o genhd.o \ - scsi_ioctl.o cmd-filter.o + blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \ + ioctl.o genhd.o scsi_ioctl.o cmd-filter.o obj-$(CONFIG_BLK_DEV_BSG) += bsg.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o diff --git a/block/blk-core.c b/block/blk-core.c index f25eb9786d9..d768a8ddc17 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -110,6 +110,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq) memset(rq, 0, sizeof(*rq)); INIT_LIST_HEAD(&rq->queuelist); + INIT_LIST_HEAD(&rq->timeout_list); rq->cpu = -1; rq->q = q; rq->sector = rq->hard_sector = (sector_t) -1; @@ -490,6 +491,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) } init_timer(&q->unplug_timer); + setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); + INIT_LIST_HEAD(&q->timeout_list); kobject_init(&q->kobj, &blk_queue_ktype); @@ -897,6 +900,8 @@ EXPORT_SYMBOL(blk_start_queueing); */ void blk_requeue_request(struct request_queue *q, struct request *rq) { + blk_delete_timer(rq); + blk_clear_rq_complete(rq); blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); if (blk_rq_tagged(rq)) @@ -1650,6 +1655,8 @@ static void end_that_request_last(struct request *req, int error) { struct gendisk *disk = req->rq_disk; + blk_delete_timer(req); + if (blk_rq_tagged(req)) blk_queue_end_tag(req->q, req); diff --git a/block/blk-settings.c b/block/blk-settings.c index d70692badcd..1d0330d0b40 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -77,6 +77,18 @@ void blk_queue_softirq_done(struct request_queue *q, softirq_done_fn *fn) } EXPORT_SYMBOL(blk_queue_softirq_done); +void blk_queue_rq_timeout(struct request_queue *q, unsigned int timeout) +{ + q->rq_timeout = timeout; +} +EXPORT_SYMBOL_GPL(blk_queue_rq_timeout); + +void blk_queue_rq_timed_out(struct request_queue *q, rq_timed_out_fn *fn) +{ + q->rq_timed_out_fn = fn; +} +EXPORT_SYMBOL_GPL(blk_queue_rq_timed_out); + /** * blk_queue_make_request - define an alternate make_request function for a device * @q: the request queue for the device to be affected diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 3a1af551191..7ab344afb16 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -101,18 +101,7 @@ static struct notifier_block __cpuinitdata blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; -/** - * blk_complete_request - end I/O on a request - * @req: the request being processed - * - * Description: - * Ends all I/O on a request. It does not handle partial completions, - * unless the driver actually implements this in its completion callback - * through requeueing. The actual completion happens out-of-order, - * through a softirq handler. The user must have registered a completion - * callback through blk_queue_softirq_done(). - **/ -void blk_complete_request(struct request *req) +void __blk_complete_request(struct request *req) { struct request_queue *q = req->q; unsigned long flags; @@ -151,6 +140,23 @@ do_local: local_irq_restore(flags); } + +/** + * blk_complete_request - end I/O on a request + * @req: the request being processed + * + * Description: + * Ends all I/O on a request. It does not handle partial completions, + * unless the driver actually implements this in its completion callback + * through requeueing. The actual completion happens out-of-order, + * through a softirq handler. The user must have registered a completion + * callback through blk_queue_softirq_done(). + **/ +void blk_complete_request(struct request *req) +{ + if (!blk_mark_rq_complete(req)) + __blk_complete_request(req); +} EXPORT_SYMBOL(blk_complete_request); __init int blk_softirq_init(void) diff --git a/block/blk-timeout.c b/block/blk-timeout.c new file mode 100644 index 00000000000..b36d07bf0af --- /dev/null +++ b/block/blk-timeout.c @@ -0,0 +1,155 @@ +/* + * Functions related to generic timeout handling of requests. + */ +#include +#include +#include + +#include "blk.h" + +/* + * blk_delete_timer - Delete/cancel timer for a given function. + * @req: request that we are canceling timer for + * + */ +void blk_delete_timer(struct request *req) +{ + struct request_queue *q = req->q; + + /* + * Nothing to detach + */ + if (!q->rq_timed_out_fn || !req->deadline) + return; + + list_del_init(&req->timeout_list); + + if (list_empty(&q->timeout_list)) + del_timer(&q->timeout); +} + +static void blk_rq_timed_out(struct request *req) +{ + struct request_queue *q = req->q; + enum blk_eh_timer_return ret; + + ret = q->rq_timed_out_fn(req); + switch (ret) { + case BLK_EH_HANDLED: + __blk_complete_request(req); + break; + case BLK_EH_RESET_TIMER: + blk_clear_rq_complete(req); + blk_add_timer(req); + break; + case BLK_EH_NOT_HANDLED: + /* + * LLD handles this for now but in the future + * we can send a request msg to abort the command + * and we can move more of the generic scsi eh code to + * the blk layer. + */ + break; + default: + printk(KERN_ERR "block: bad eh return: %d\n", ret); + break; + } +} + +void blk_rq_timed_out_timer(unsigned long data) +{ + struct request_queue *q = (struct request_queue *) data; + unsigned long flags, uninitialized_var(next), next_set = 0; + struct request *rq, *tmp; + + spin_lock_irqsave(q->queue_lock, flags); + + list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) { + if (time_after_eq(jiffies, rq->deadline)) { + list_del_init(&rq->timeout_list); + + /* + * Check if we raced with end io completion + */ + if (blk_mark_rq_complete(rq)) + continue; + blk_rq_timed_out(rq); + } + if (!next_set) { + next = rq->deadline; + next_set = 1; + } else if (time_after(next, rq->deadline)) + next = rq->deadline; + } + + if (next_set && !list_empty(&q->timeout_list)) + mod_timer(&q->timeout, round_jiffies(next)); + + spin_unlock_irqrestore(q->queue_lock, flags); +} + +/** + * blk_abort_request -- Request request recovery for the specified command + * @req: pointer to the request of interest + * + * This function requests that the block layer start recovery for the + * request by deleting the timer and calling the q's timeout function. + * LLDDs who implement their own error recovery MAY ignore the timeout + * event if they generated blk_abort_req. Must hold queue lock. + */ +void blk_abort_request(struct request *req) +{ + blk_delete_timer(req); + blk_rq_timed_out(req); +} +EXPORT_SYMBOL_GPL(blk_abort_request); + +/** + * blk_add_timer - Start timeout timer for a single request + * @req: request that is about to start running. + * + * Notes: + * Each request has its own timer, and as it is added to the queue, we + * set up the timer. When the request completes, we cancel the timer. + */ +void blk_add_timer(struct request *req) +{ + struct request_queue *q = req->q; + unsigned long expiry; + + if (!q->rq_timed_out_fn) + return; + + BUG_ON(!list_empty(&req->timeout_list)); + BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); + + if (req->timeout) + req->deadline = jiffies + req->timeout; + else { + req->deadline = jiffies + q->rq_timeout; + /* + * Some LLDs, like scsi, peek at the timeout to prevent + * a command from being retried forever. + */ + req->timeout = q->rq_timeout; + } + list_add_tail(&req->timeout_list, &q->timeout_list); + + /* + * If the timer isn't already pending or this timeout is earlier + * than an existing one, modify the timer. Round to next nearest + * second. + */ + expiry = round_jiffies(req->deadline); + + /* + * We use ->deadline == 0 to detect whether a timer was added or + * not, so just increase to next jiffy for that specific case + */ + if (unlikely(!req->deadline)) + req->deadline = 1; + + if (!timer_pending(&q->timeout) || + time_before(expiry, q->timeout.expires)) + mod_timer(&q->timeout, expiry); +} diff --git a/block/blk.h b/block/blk.h index de74254cb91..a4f4a50aefa 100644 --- a/block/blk.h +++ b/block/blk.h @@ -17,6 +17,30 @@ void __blk_queue_free_tags(struct request_queue *q); void blk_unplug_work(struct work_struct *work); void blk_unplug_timeout(unsigned long data); +void blk_rq_timed_out_timer(unsigned long data); +void blk_delete_timer(struct request *); +void blk_add_timer(struct request *); + +/* + * Internal atomic flags for request handling + */ +enum rq_atomic_flags { + REQ_ATOM_COMPLETE = 0, +}; + +/* + * EH timer and IO completion will both attempt to 'grab' the request, make + * sure that only one of them suceeds + */ +static inline int blk_mark_rq_complete(struct request *rq) +{ + return test_and_set_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); +} + +static inline void blk_clear_rq_complete(struct request *rq) +{ + clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); +} struct io_context *current_io_context(gfp_t gfp_flags, int node); diff --git a/block/elevator.c b/block/elevator.c index 8e3fc3afc77..a91fc59edd0 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -36,6 +36,8 @@ #include #include +#include "blk.h" + static DEFINE_SPINLOCK(elv_list_lock); static LIST_HEAD(elv_list); @@ -771,6 +773,12 @@ struct request *elv_next_request(struct request_queue *q) */ rq->cmd_flags |= REQ_STARTED; blk_add_trace_rq(q, rq, BLK_TA_ISSUE); + + /* + * We are now handing the request to the hardware, + * add the timeout handler + */ + blk_add_timer(rq); } if (!q->boundary_rq || q->boundary_rq == rq) { diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c1db2f234d2..bd0b2bc76f1 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -33,6 +33,7 @@ */ #include +#include #include #include #include @@ -457,29 +458,29 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret; + enum blk_eh_timer_return ret; DPRINTK("ENTER\n"); if (ap->ops->error_handler) { - ret = EH_NOT_HANDLED; + ret = BLK_EH_NOT_HANDLED; goto out; } - ret = EH_HANDLED; + ret = BLK_EH_HANDLED; spin_lock_irqsave(ap->lock, flags); qc = ata_qc_from_tag(ap, ap->link.active_tag); if (qc) { WARN_ON(qc->scsicmd != cmd); qc->flags |= ATA_QCFLAG_EH_SCHEDULED; qc->err_mask |= AC_ERR_TIMEOUT; - ret = EH_NOT_HANDLED; + ret = BLK_EH_NOT_HANDLED; } spin_unlock_irqrestore(ap->lock, flags); @@ -831,7 +832,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) * Note that ATA_QCFLAG_FAILED is unconditionally set after * this function completes. */ - scsi_req_abort_cmd(qc->scsicmd); + blk_abort_request(qc->scsicmd->request); } /** diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ade5c75b614..24f5005478b 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -152,7 +152,7 @@ extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd); extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd); -extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); +extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_eh_fastdrain_timerfn(unsigned long arg); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index aa4e77c2527..8abfd06b5a7 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1139,7 +1139,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd srbcmd->id = cpu_to_le32(scmd_id(cmd)); srbcmd->lun = cpu_to_le32(cmd->device->lun); srbcmd->flags = cpu_to_le32(flag); - timeout = cmd->timeout_per_command/HZ; + timeout = cmd->request->timeout/HZ; if (timeout == 0) timeout = 1; srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 822d5214692..c387c15a212 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -464,7 +464,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, /* use request field to save the ptr. to completion struct. */ scp->request = (struct request *)&wait; - scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; @@ -1995,23 +1994,12 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; ulong flags; - unchar b, t; TRACE(("gdth_putq() priority %d\n",priority)); spin_lock_irqsave(&ha->smp_lock, flags); - if (!cmndinfo->internal_command) { + if (!cmndinfo->internal_command) cmndinfo->priority = priority; - b = scp->device->channel; - t = scp->device->id; - if (priority >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b==ha->virt_bus && thdr[t].lock)) { - TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); - } - } - } if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -3899,6 +3887,39 @@ static const char *gdth_info(struct Scsi_Host *shp) return ((const char *)ha->binfo.type_string); } +static enum blk_eh_timer_return gdth_timed_out(struct scsi_cmnd *scp) +{ + gdth_ha_str *ha = shost_priv(scp->device->host); + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + unchar b, t; + ulong flags; + enum blk_eh_timer_return retval = BLK_EH_NOT_HANDLED; + + TRACE(("%s() cmd 0x%x\n", scp->cmnd[0], __func__)); + b = scp->device->channel; + t = scp->device->id; + + /* + * We don't really honor the command timeout, but we try to + * honor 6 times of the actual command timeout! So reset the + * timer if this is less than 6th timeout on this command! + */ + if (++cmndinfo->timeout_count < 6) + retval = BLK_EH_RESET_TIMER; + + /* Reset the timeout if it is locked IO */ + spin_lock_irqsave(&ha->smp_lock, flags); + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha, b)].lock) || + (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { + TRACE2(("%s(): locked IO, reset timeout\n", __func__)); + retval = BLK_EH_RESET_TIMER; + } + spin_unlock_irqrestore(&ha->smp_lock, flags); + + return retval; +} + + static int gdth_eh_bus_reset(Scsi_Cmnd *scp) { gdth_ha_str *ha = shost_priv(scp->device->host); @@ -3992,7 +4013,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp, BUG_ON(!cmndinfo); scp->scsi_done = done; - gdth_update_timeout(scp, scp->timeout_per_command * 6); + cmndinfo->timeout_count = 0; cmndinfo->priority = DEFAULT_PRI; return __gdth_queuecommand(ha, scp, cmndinfo); @@ -4096,12 +4117,10 @@ static int ioc_lockdrv(void __user *arg) ha->hdr[j].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); gdth_wait_completion(ha, ha->bus_cnt, j); - gdth_stop_timeout(ha, ha->bus_cnt, j); } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[j].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - gdth_start_timeout(ha, ha->bus_cnt, j); gdth_next(ha); } } @@ -4539,18 +4558,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); - for (j = 0; j < ha->tid_cnt; ++j) { + for (j = 0; j < ha->tid_cnt; ++j) gdth_wait_completion(ha, i, j); - gdth_stop_timeout(ha, i, j); - } } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - for (j = 0; j < ha->tid_cnt; ++j) { - gdth_start_timeout(ha, i, j); + for (j = 0; j < ha->tid_cnt; ++j) gdth_next(ha); - } } } break; @@ -4644,6 +4659,7 @@ static struct scsi_host_template gdth_template = { .slave_configure = gdth_slave_configure, .bios_param = gdth_bios_param, .proc_info = gdth_proc_info, + .eh_timed_out = gdth_timed_out, .proc_name = "gdth", .can_queue = GDTH_MAXCMDS, .this_id = -1, diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index ca92476727c..1646444e9bd 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -916,7 +916,7 @@ typedef struct { gdth_cmd_str *internal_cmd_str; /* crier for internal messages*/ dma_addr_t sense_paddr; /* sense dma-addr */ unchar priority; - int timeout; + int timeout_count; /* # of timeout calls */ volatile int wait_for_completion; ushort status; ulong32 info; diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index ce0228e26ae..59349a316e1 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -748,69 +748,3 @@ static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) } spin_unlock_irqrestore(&ha->smp_lock, flags); } - -static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id) -{ - ulong flags; - Scsi_Cmnd *scp; - unchar b, t; - - spin_lock_irqsave(&ha->smp_lock, flags); - - for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); - } - } - } - spin_unlock_irqrestore(&ha->smp_lock, flags); -} - -static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id) -{ - ulong flags; - Scsi_Cmnd *scp; - unchar b, t; - - spin_lock_irqsave(&ha->smp_lock, flags); - - for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(scp, cmndinfo->timeout); - } - } - } - spin_unlock_irqrestore(&ha->smp_lock, flags); -} - -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout) -{ - int oldto; - - oldto = scp->timeout_per_command; - scp->timeout_per_command = timeout; - - if (timeout == 0) { - del_timer(&scp->eh_timeout); - scp->eh_timeout.data = (unsigned long) NULL; - scp->eh_timeout.expires = 0; - } else { - if (scp->eh_timeout.data != (unsigned long) NULL) - del_timer(&scp->eh_timeout); - scp->eh_timeout.data = (unsigned long) scp; - scp->eh_timeout.expires = jiffies + timeout; - add_timer(&scp->eh_timeout); - } - - return oldto; -} diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index 45e6fdacf36..9b900cc9ebe 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -20,9 +20,6 @@ static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, ulong64 *paddr); static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr); static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id); -static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id); -static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id); -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout); #endif diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 7b1502c0ab6..87e09f35d3d 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -756,7 +756,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, init_event_struct(evt_struct, handle_cmd_rsp, VIOSRP_SRP_FORMAT, - cmnd->timeout_per_command/HZ); + cmnd->request->timeout/HZ); evt_struct->cmnd = cmnd; evt_struct->cmnd_done = done; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 461331d3dc4..81c16cba541 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -612,7 +612,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, pc->req_xfer = pc->buf_size = scsi_bufflen(cmd); pc->scsi_cmd = cmd; pc->done = done; - pc->timeout = jiffies + cmd->timeout_per_command; + pc->timeout = jiffies + cmd->request->timeout; if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e7a3a655442..d30eb7ba018 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3670,7 +3670,8 @@ static int ipr_slave_configure(struct scsi_device *sdev) sdev->no_uld_attach = 1; } if (ipr_is_vset_device(res)) { - sdev->timeout = IPR_VSET_RW_TIMEOUT; + blk_queue_rq_timeout(sdev->request_queue, + IPR_VSET_RW_TIMEOUT); blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); } if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index bc9e6ddf41d..ef683f0d2b5 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -3818,7 +3818,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb) scb->cmd.dcdb.segment_4G = 0; scb->cmd.dcdb.enhanced_sg = 0; - TimeOut = scb->scsi_cmd->timeout_per_command; + TimeOut = scb->scsi_cmd->request->timeout; if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */ if (!scb->sg_len) { diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 299e075a7b3..1eca82420aa 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1476,12 +1476,12 @@ static void iscsi_start_tx(struct iscsi_conn *conn) scsi_queue_work(conn->session->host, &conn->xmitwork); } -static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) +static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; - enum scsi_eh_timer_return rc = EH_NOT_HANDLED; + enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; cls_session = starget_to_session(scsi_target(scmd->device)); session = cls_session->dd_data; @@ -1494,14 +1494,14 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) * We are probably in the middle of iscsi recovery so let * that complete and handle the error. */ - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; goto done; } conn = session->leadconn; if (!conn) { /* In the middle of shuting down */ - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; goto done; } @@ -1513,20 +1513,21 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) */ if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; /* * if we are about to check the transport then give the command * more time */ if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), jiffies)) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; /* if in the middle of checking the transport then give us more time */ if (conn->ping_task) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; done: spin_unlock(&session->lock); - debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh"); + debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ? + "timer reset" : "nh"); return rc; } diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 48ee8c7f5bd..837b095ba90 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -398,7 +398,7 @@ void sas_ata_task_abort(struct sas_task *task) /* Bounce SCSI-initiated commands to the SCSI EH */ if (qc->scsicmd) { - scsi_req_abort_cmd(qc->scsicmd); + blk_abort_request(qc->scsicmd->request); scsi_schedule_eh(qc->scsicmd->device->host); return; } diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index b4f9368f116..0001374bd6b 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -55,7 +55,7 @@ void sas_unregister_phys(struct sas_ha_struct *sas_ha); int sas_register_ports(struct sas_ha_struct *sas_ha); void sas_unregister_ports(struct sas_ha_struct *sas_ha); -enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); +enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); int sas_init_queue(struct sas_ha_struct *sas_ha); int sas_init_events(struct sas_ha_struct *sas_ha); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a8e3ef30907..744838780ad 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -673,43 +673,43 @@ out: return; } -enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) +enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) { struct sas_task *task = TO_SAS_TASK(cmd); unsigned long flags; if (!task) { - cmd->timeout_per_command /= 2; + cmd->request->timeout /= 2; SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n", - cmd, task, (cmd->timeout_per_command ? - "EH_RESET_TIMER" : "EH_NOT_HANDLED")); - if (!cmd->timeout_per_command) - return EH_NOT_HANDLED; - return EH_RESET_TIMER; + cmd, task, (cmd->request->timeout ? + "BLK_EH_RESET_TIMER" : "BLK_EH_NOT_HANDLED")); + if (!cmd->request->timeout) + return BLK_EH_NOT_HANDLED; + return BLK_EH_RESET_TIMER; } spin_lock_irqsave(&task->task_state_lock, flags); BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED); if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", - cmd, task); - return EH_HANDLED; + SAS_DPRINTK("command 0x%p, task 0x%p, timed out: " + "BLK_EH_HANDLED\n", cmd, task); + return BLK_EH_HANDLED; } if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: " - "EH_RESET_TIMER\n", + "BLK_EH_RESET_TIMER\n", cmd, task); - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; } task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_NOT_HANDLED\n", + SAS_DPRINTK("command 0x%p, task 0x%p, timed out: BLK_EH_NOT_HANDLED\n", cmd, task); - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) @@ -1039,7 +1039,7 @@ void sas_task_abort(struct sas_task *task) return; } - scsi_req_abort_cmd(sc); + blk_abort_request(sc->request); scsi_schedule_eh(sc->device->host); } diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 97b763378e7..afe1de99876 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -1167,7 +1167,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd) * cmd has not been completed within the timeout period. */ static enum -scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) +blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) { struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr; struct megasas_instance *instance; @@ -1175,7 +1175,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) if (time_after(jiffies, scmd->jiffies_at_alloc + (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) { - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } instance = cmd->instance; @@ -1189,7 +1189,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) spin_unlock_irqrestore(instance->host->host_lock, flags); } - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; } /** diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index c57c94c0ffd..3b7240e4081 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4170,8 +4170,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) ** **---------------------------------------------------- */ - if (np->settle_time && cmd->timeout_per_command >= HZ) { - u_long tlimit = jiffies + cmd->timeout_per_command - HZ; + if (np->settle_time && cmd->request->timeout >= HZ) { + u_long tlimit = jiffies + cmd->request->timeout - HZ; if (time_after(np->settle_time, tlimit)) np->settle_time = tlimit; } diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 37f9ba0cd79..b6cd12b2e99 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2845,7 +2845,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ); + pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ); /* Set device target ID and LUN */ pkt->lun = SCSI_LUN_32(cmd); @@ -3114,7 +3114,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ); + pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ); /* Set device target ID and LUN */ pkt->lun = SCSI_LUN_32(cmd); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 88bebb13bc5..de8279ad7d8 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1542,7 +1542,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) DEBUG2(printk(KERN_INFO "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x," "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no, - cmd, jiffies, cmd->timeout_per_command / HZ, + cmd, jiffies, cmd->request->timeout / HZ, ha->dpc_flags, cmd->result, cmd->allowed)); /* FIXME: wait for hba to go online */ @@ -1598,7 +1598,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) DEBUG2(printk(KERN_INFO "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, " "to=%x,dpc_flags=%lx, status=%x allowed=%d\n", - ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ, + ha->host_no, cmd, jiffies, cmd->request->timeout / HZ, ha->dpc_flags, cmd->result, cmd->allowed)); stat = qla4xxx_reset_target(ha, ddb_entry); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ee6be596503..dbeb86cafc0 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -291,7 +291,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) unsigned long flags; cmd->device = dev; - init_timer(&cmd->eh_timeout); INIT_LIST_HEAD(&cmd->list); spin_lock_irqsave(&dev->list_lock, flags); list_add_tail(&cmd->list, &dev->cmd_list); @@ -652,14 +651,19 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long timeout; int rtn = 0; + /* + * We will use a queued command if possible, otherwise we will + * emulate the queuing and calling of completion function ourselves. + */ + atomic_inc(&cmd->device->iorequest_cnt); + /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { /* in SDEV_DEL we error all commands. DID_NO_CONNECT * returns an immediate error upwards, and signals * that the device is no longer present */ cmd->result = DID_NO_CONNECT << 16; - atomic_inc(&cmd->device->iorequest_cnt); - __scsi_done(cmd); + scsi_done(cmd); /* return 0 (because the command has been processed) */ goto out; } @@ -672,6 +676,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * future requests should not occur until the device * transitions out of the suspend state. */ + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n")); @@ -714,20 +719,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) host->resetting = 0; } - /* - * AK: unlikely race here: for some reason the timer could - * expire before the serial number is set up below. - */ - scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out); - scsi_log_send(cmd); - /* - * We will use a queued command if possible, otherwise we will - * emulate the queuing and calling of completion function ourselves. - */ - atomic_inc(&cmd->device->iorequest_cnt); - /* * Before we queue this command, check if the command * length exceeds what the host adapter can handle. @@ -744,6 +737,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) } spin_lock_irqsave(host->host_lock, flags); + /* + * AK: unlikely race here: for some reason the timer could + * expire before the serial number is set up below. + * + * TODO: kill serial or move to blk layer + */ scsi_cmd_get_serial(host, cmd); if (unlikely(host->shost_state == SHOST_DEL)) { @@ -754,12 +753,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) } spin_unlock_irqrestore(host->host_lock, flags); if (rtn) { - if (scsi_delete_timer(cmd)) { - atomic_inc(&cmd->device->iodone_cnt); - scsi_queue_insert(cmd, - (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? - rtn : SCSI_MLQUEUE_HOST_BUSY); - } + scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? + rtn : SCSI_MLQUEUE_HOST_BUSY); SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n")); } @@ -769,24 +764,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) return rtn; } -/** - * scsi_req_abort_cmd -- Request command recovery for the specified command - * @cmd: pointer to the SCSI command of interest - * - * This function requests that SCSI Core start recovery for the - * command by deleting the timer and adding the command to the eh - * queue. It can be called by either LLDDs or SCSI Core. LLDDs who - * implement their own error recovery MAY ignore the timeout event if - * they generated scsi_req_abort_cmd. - */ -void scsi_req_abort_cmd(struct scsi_cmnd *cmd) -{ - if (!scsi_delete_timer(cmd)) - return; - scsi_times_out(cmd); -} -EXPORT_SYMBOL(scsi_req_abort_cmd); - /** * scsi_done - Enqueue the finished SCSI command into the done queue. * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives @@ -802,42 +779,7 @@ EXPORT_SYMBOL(scsi_req_abort_cmd); */ static void scsi_done(struct scsi_cmnd *cmd) { - /* - * We don't have to worry about this one timing out anymore. - * If we are unable to remove the timer, then the command - * has already timed out. In which case, we have no choice but to - * let the timeout function run, as we have no idea where in fact - * that function could really be. It might be on another processor, - * etc, etc. - */ - if (!scsi_delete_timer(cmd)) - return; - __scsi_done(cmd); -} - -/* Private entry to scsi_done() to complete a command when the timer - * isn't running --- used by scsi_times_out */ -void __scsi_done(struct scsi_cmnd *cmd) -{ - struct request *rq = cmd->request; - - /* - * Set the serial numbers back to zero - */ - cmd->serial_number = 0; - - atomic_inc(&cmd->device->iodone_cnt); - if (cmd->result) - atomic_inc(&cmd->device->ioerr_cnt); - - BUG_ON(!rq); - - /* - * The uptodate/nbytes values don't matter, as we allow partial - * completes and thus will check this in the softirq callback - */ - rq->completion_data = cmd; - blk_complete_request(rq); + blk_complete_request(cmd->request); } /* Move this to a header if it becomes more generally useful */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 39ce3aba1da..fecefa05cb6 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -111,70 +111,9 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) return ret; } -/** - * scsi_add_timer - Start timeout timer for a single scsi command. - * @scmd: scsi command that is about to start running. - * @timeout: amount of time to allow this command to run. - * @complete: timeout function to call if timer isn't canceled. - * - * Notes: - * This should be turned into an inline function. Each scsi command - * has its own timer, and as it is added to the queue, we set up the - * timer. When the command completes, we cancel the timer. - */ -void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, - void (*complete)(struct scsi_cmnd *)) -{ - - /* - * If the clock was already running for this command, then - * first delete the timer. The timer handling code gets rather - * confused if we don't do this. - */ - if (scmd->eh_timeout.function) - del_timer(&scmd->eh_timeout); - - scmd->eh_timeout.data = (unsigned long)scmd; - scmd->eh_timeout.expires = jiffies + timeout; - scmd->eh_timeout.function = (void (*)(unsigned long)) complete; - - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:" - " %d, (%p)\n", __func__, - scmd, timeout, complete)); - - add_timer(&scmd->eh_timeout); -} - -/** - * scsi_delete_timer - Delete/cancel timer for a given function. - * @scmd: Cmd that we are canceling timer for - * - * Notes: - * This should be turned into an inline function. - * - * Return value: - * 1 if we were able to detach the timer. 0 if we blew it, and the - * timer function has already started to run. - */ -int scsi_delete_timer(struct scsi_cmnd *scmd) -{ - int rtn; - - rtn = del_timer(&scmd->eh_timeout); - - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p," - " rtn: %d\n", __func__, - scmd, rtn)); - - scmd->eh_timeout.data = (unsigned long)NULL; - scmd->eh_timeout.function = NULL; - - return rtn; -} - /** * scsi_times_out - Timeout function for normal scsi commands. - * @scmd: Cmd that is timing out. + * @req: request that is timing out. * * Notes: * We do not need to lock this. There is the potential for a race @@ -182,9 +121,11 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) * normal completion function determines that the timer has already * fired, then it mustn't do anything. */ -void scsi_times_out(struct scsi_cmnd *scmd) +enum blk_eh_timer_return scsi_times_out(struct request *req) { - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + struct scsi_cmnd *scmd = req->special; + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED; scsi_log_completion(scmd, TIMEOUT_ERROR); @@ -196,22 +137,20 @@ void scsi_times_out(struct scsi_cmnd *scmd) eh_timed_out = NULL; if (eh_timed_out) - switch (eh_timed_out(scmd)) { - case EH_HANDLED: - __scsi_done(scmd); - return; - case EH_RESET_TIMER: - scsi_add_timer(scmd, scmd->timeout_per_command, - scsi_times_out); - return; - case EH_NOT_HANDLED: + rtn = eh_timed_out(scmd); + switch (rtn) { + case BLK_EH_NOT_HANDLED: break; + default: + return rtn; } if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { scmd->result |= DID_TIME_OUT << 16; - __scsi_done(scmd); + return BLK_EH_HANDLED; } + + return BLK_EH_NOT_HANDLED; } /** @@ -1793,7 +1732,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) blk_rq_init(NULL, &req); scmd->request = &req; - memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); scmd->cmnd = req.cmd; @@ -1804,8 +1742,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->sc_data_direction = DMA_BIDIRECTIONAL; - init_timer(&scmd->eh_timeout); - spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 62307bd794a..e7686500e9d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1181,7 +1181,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->transfersize = req->data_len; cmd->allowed = req->retries; - cmd->timeout_per_command = req->timeout; return BLKPREP_OK; } EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); @@ -1416,17 +1415,26 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) spin_unlock(shost->host_lock); spin_lock(sdev->request_queue->queue_lock); - __scsi_done(cmd); + blk_complete_request(req); } static void scsi_softirq_done(struct request *rq) { - struct scsi_cmnd *cmd = rq->completion_data; - unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command; + struct scsi_cmnd *cmd = rq->special; + unsigned long wait_for = (cmd->allowed + 1) * rq->timeout; int disposition; INIT_LIST_HEAD(&cmd->eh_entry); + /* + * Set the serial numbers back to zero + */ + cmd->serial_number = 0; + + atomic_inc(&cmd->device->iodone_cnt); + if (cmd->result) + atomic_inc(&cmd->device->ioerr_cnt); + disposition = scsi_decide_disposition(cmd); if (disposition != SUCCESS && time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { @@ -1675,6 +1683,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_prep_rq(q, scsi_prep_fn); blk_queue_softirq_done(q, scsi_softirq_done); + blk_queue_rq_timed_out(q, scsi_times_out); return q; } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 79f0f751120..6cddd5dd323 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -4,6 +4,7 @@ #include struct request_queue; +struct request; struct scsi_cmnd; struct scsi_device; struct scsi_host_template; @@ -27,7 +28,6 @@ extern void scsi_exit_hosts(void); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); -extern void __scsi_done(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd); void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); @@ -49,10 +49,7 @@ extern int __init scsi_init_devinfo(void); extern void scsi_exit_devinfo(void); /* scsi_error.c */ -extern void scsi_add_timer(struct scsi_cmnd *, int, - void (*)(struct scsi_cmnd *)); -extern int scsi_delete_timer(struct scsi_cmnd *); -extern void scsi_times_out(struct scsi_cmnd *cmd); +extern enum blk_eh_timer_return scsi_times_out(struct request *req); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ab3c71869be..7f618ee5ece 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -560,12 +560,15 @@ sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +/* + * TODO: can we make these symlinks to the block layer ones? + */ static ssize_t sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf) { struct scsi_device *sdev; sdev = to_scsi_device(dev); - return snprintf (buf, 20, "%d\n", sdev->timeout / HZ); + return snprintf(buf, 20, "%d\n", sdev->request_queue->rq_timeout / HZ); } static ssize_t @@ -576,7 +579,7 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr, int timeout; sdev = to_scsi_device(dev); sscanf (buf, "%d\n", &timeout); - sdev->timeout = timeout * HZ; + blk_queue_rq_timeout(sdev->request_queue, timeout * HZ); return count; } static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 56823fd1fb8..9168883d0df 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1950,15 +1950,15 @@ static int fc_vport_match(struct attribute_container *cont, * Notes: * This routine assumes no locks are held on entry. */ -static enum scsi_eh_timer_return +static enum blk_eh_timer_return fc_timed_out(struct scsi_cmnd *scmd) { struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); if (rport->port_state == FC_PORTSTATE_BLOCKED) - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } /* diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cb115d1bf22..c0cf4acda7d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -383,7 +383,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) sector_t block = rq->sector; sector_t threshold; unsigned int this_count = rq->nr_sectors; - unsigned int timeout = sdp->timeout; int ret; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { @@ -584,7 +583,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->transfersize = sdp->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = SD_MAX_RETRIES; - SCpnt->timeout_per_command = timeout; /* * This indicates that the command is ready from our end to be @@ -1878,11 +1876,12 @@ static int sd_probe(struct device *dev) sdkp->openers = 0; sdkp->previous_state = 1; - if (!sdp->timeout) { + if (!sdp->request_queue->rq_timeout) { if (sdp->type != TYPE_MOD) - sdp->timeout = SD_TIMEOUT; + blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); else - sdp->timeout = SD_MOD_TIMEOUT; + blk_queue_rq_timeout(sdp->request_queue, + SD_MOD_TIMEOUT); } device_initialize(&sdkp->dev); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 8dbe3798d5f..0f17009c99d 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -331,7 +331,7 @@ static int sr_done(struct scsi_cmnd *SCpnt) static int sr_prep_fn(struct request_queue *q, struct request *rq) { - int block=0, this_count, s_size, timeout = SR_TIMEOUT; + int block = 0, this_count, s_size; struct scsi_cd *cd; struct scsi_cmnd *SCpnt; struct scsi_device *sdp = q->queuedata; @@ -461,7 +461,6 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = MAX_RETRIES; - SCpnt->timeout_per_command = timeout; /* * This indicates that the command is ready from our end to be @@ -620,6 +619,8 @@ static int sr_probe(struct device *dev) disk->fops = &sr_bdops; disk->flags = GENHD_FL_CD; + blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); + cd->device = sdev; cd->disk = disk; cd->driver = &sr_template; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index d39107b7669..f4e6cde1fd0 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -519,8 +519,8 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, * Shorten our settle_time if needed for * this command not to time out. */ - if (np->s.settle_time_valid && cmd->timeout_per_command) { - unsigned long tlimit = jiffies + cmd->timeout_per_command; + if (np->s.settle_time_valid && cmd->request->timeout) { + unsigned long tlimit = jiffies + cmd->request->timeout; tlimit -= SYM_CONF_TIMER_INTERVAL*2; if (time_after(np->s.settle_time, tlimit)) { np->s.settle_time = tlimit; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9c254926042..067f28b8007 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -147,6 +147,7 @@ struct request { unsigned int cmd_flags; enum rq_cmd_type_bits cmd_type; + unsigned long atomic_flags; /* Maintain bio traversal state for part by part I/O submission. * hard_* are block layer internals, no driver should touch them! @@ -214,6 +215,8 @@ struct request { void *data; void *sense; + unsigned long deadline; + struct list_head timeout_list; unsigned int timeout; int retries; @@ -266,6 +269,14 @@ typedef void (prepare_flush_fn) (struct request_queue *, struct request *); typedef void (softirq_done_fn)(struct request *); typedef int (dma_drain_needed_fn)(struct request *); +enum blk_eh_timer_return { + BLK_EH_NOT_HANDLED, + BLK_EH_HANDLED, + BLK_EH_RESET_TIMER, +}; + +typedef enum blk_eh_timer_return (rq_timed_out_fn)(struct request *); + enum blk_queue_state { Queue_down, Queue_up, @@ -311,6 +322,7 @@ struct request_queue merge_bvec_fn *merge_bvec_fn; prepare_flush_fn *prepare_flush_fn; softirq_done_fn *softirq_done_fn; + rq_timed_out_fn *rq_timed_out_fn; dma_drain_needed_fn *dma_drain_needed; /* @@ -386,6 +398,10 @@ struct request_queue unsigned int nr_sorted; unsigned int in_flight; + unsigned int rq_timeout; + struct timer_list timeout; + struct list_head timeout_list; + /* * sg stuff */ @@ -770,6 +786,8 @@ extern int blk_end_request_callback(struct request *rq, int error, unsigned int nr_bytes, int (drv_callback)(struct request *)); extern void blk_complete_request(struct request *); +extern void __blk_complete_request(struct request *); +extern void blk_abort_request(struct request *); /* * blk_end_request() takes bytes instead of sectors as a complete size. @@ -811,6 +829,8 @@ extern void blk_queue_dma_alignment(struct request_queue *, int); extern void blk_queue_update_dma_alignment(struct request_queue *, int); extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); extern void blk_queue_set_discard(struct request_queue *, prepare_discard_fn *); +extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); +extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); extern int blk_do_ordered(struct request_queue *, struct request **); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index f9f6e793575..855bf95963e 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -75,7 +75,6 @@ struct scsi_cmnd { int retries; int allowed; - int timeout_per_command; unsigned char prot_op; unsigned char prot_type; @@ -86,7 +85,6 @@ struct scsi_cmnd { /* These elements define the operation we are about to perform */ unsigned char *cmnd; - struct timer_list eh_timeout; /* Used to time out the command. */ /* These elements define the operation we ultimately want to perform */ struct scsi_data_buffer sdb; @@ -139,7 +137,6 @@ extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); extern void scsi_finish_command(struct scsi_cmnd *cmd); -extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t *offset, size_t *len); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 44a55d1bf53..d123ca84e73 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -43,13 +43,6 @@ struct blk_queue_tags; #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 -enum scsi_eh_timer_return { - EH_NOT_HANDLED, - EH_HANDLED, - EH_RESET_TIMER, -}; - - struct scsi_host_template { struct module *module; const char *name; @@ -347,7 +340,7 @@ struct scsi_host_template { * * Status: OPTIONAL */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); /* * Name of proc directory diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index 490bd13a634..0de32cd4e8a 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -21,6 +21,7 @@ #define SCSI_TRANSPORT_H #include +#include #include #include @@ -64,7 +65,7 @@ struct scsi_transport_template { * begin counting again * EH_NOT_HANDLED Begin normal error recovery */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); /* * Used as callback for the completion of i_t_nexus request -- GitLab From 11914a53d2ec2974a565311af327b8983d8c820d Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Sat, 13 Sep 2008 20:31:27 +0200 Subject: [PATCH 3464/5416] block: Add interface to abort queued requests Signed-off-by: Mike Anderson Signed-off-by: Jens Axboe --- block/blk-timeout.c | 22 ++++++++++++++++++++++ block/elevator.c | 13 +++++++++++++ include/linux/blkdev.h | 1 + include/linux/blktrace_api.h | 2 ++ include/linux/elevator.h | 1 + 5 files changed, 39 insertions(+) diff --git a/block/blk-timeout.c b/block/blk-timeout.c index b36d07bf0af..6e5c781c5af 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -153,3 +153,25 @@ void blk_add_timer(struct request *req) time_before(expiry, q->timeout.expires)) mod_timer(&q->timeout, expiry); } + +/** + * blk_abort_queue -- Abort all request on given queue + * @queue: pointer to queue + * + */ +void blk_abort_queue(struct request_queue *q) +{ + unsigned long flags; + struct request *rq, *tmp; + + spin_lock_irqsave(q->queue_lock, flags); + + elv_abort_queue(q); + + list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) + blk_abort_request(rq); + + spin_unlock_irqrestore(q->queue_lock, flags); + +} +EXPORT_SYMBOL_GPL(blk_abort_queue); diff --git a/block/elevator.c b/block/elevator.c index a91fc59edd0..8a74eedc353 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -914,6 +914,19 @@ int elv_may_queue(struct request_queue *q, int rw) return ELV_MQUEUE_MAY; } +void elv_abort_queue(struct request_queue *q) +{ + struct request *rq; + + while (!list_empty(&q->queue_head)) { + rq = list_entry_rq(q->queue_head.next); + rq->cmd_flags |= REQ_QUIET; + blk_add_trace_rq(q, rq, BLK_TA_ABORT); + end_queued_request(rq, 0); + } +} +EXPORT_SYMBOL(elv_abort_queue); + void elv_completed_request(struct request_queue *q, struct request *rq) { elevator_t *e = q->elevator; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 067f28b8007..37781d6fe04 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -788,6 +788,7 @@ extern int blk_end_request_callback(struct request *rq, int error, extern void blk_complete_request(struct request *); extern void __blk_complete_request(struct request *); extern void blk_abort_request(struct request *); +extern void blk_abort_queue(struct request_queue *); /* * blk_end_request() takes bytes instead of sectors as a complete size. diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 27da2cc682e..dcaf2452ed1 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -48,6 +48,7 @@ enum blktrace_act { __BLK_TA_SPLIT, /* bio was split */ __BLK_TA_BOUNCE, /* bio was bounced */ __BLK_TA_REMAP, /* bio was remapped */ + __BLK_TA_ABORT, /* request aborted */ }; /* @@ -78,6 +79,7 @@ enum blktrace_notify { #define BLK_TA_SPLIT (__BLK_TA_SPLIT) #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_ABORT (__BLK_TA_ABORT | BLK_TC_ACT(BLK_TC_QUEUE)) #define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY)) #define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY)) diff --git a/include/linux/elevator.h b/include/linux/elevator.h index bb791c311a5..92f6f634e3e 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -112,6 +112,7 @@ extern struct request *elv_latter_request(struct request_queue *, struct request extern int elv_register_queue(struct request_queue *q); extern void elv_unregister_queue(struct request_queue *q); extern int elv_may_queue(struct request_queue *, int); +extern void elv_abort_queue(struct request_queue *); extern void elv_completed_request(struct request_queue *, struct request *); extern int elv_set_request(struct request_queue *, struct request *, gfp_t); extern void elv_put_request(struct request_queue *, struct request *); -- GitLab From 224cb3e981f1b2f9f93dbd49eaef505d17d894c2 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Fri, 29 Aug 2008 09:36:09 +0200 Subject: [PATCH 3465/5416] dm: Call blk_abort_queue on failed paths Signed-off-by: Mike Anderson Signed-off-by: Jens Axboe --- drivers/md/dm-mpath.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index c2fcf28b4c7..3d3848132c6 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -33,6 +33,7 @@ struct pgpath { unsigned fail_count; /* Cumulative failure count */ struct dm_path path; + struct work_struct deactivate_path; }; #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) @@ -112,6 +113,7 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd; static void process_queued_ios(struct work_struct *work); static void trigger_event(struct work_struct *work); static void activate_path(struct work_struct *work); +static void deactivate_path(struct work_struct *work); /*----------------------------------------------- @@ -122,8 +124,10 @@ static struct pgpath *alloc_pgpath(void) { struct pgpath *pgpath = kzalloc(sizeof(*pgpath), GFP_KERNEL); - if (pgpath) + if (pgpath) { pgpath->path.is_active = 1; + INIT_WORK(&pgpath->deactivate_path, deactivate_path); + } return pgpath; } @@ -133,6 +137,14 @@ static void free_pgpath(struct pgpath *pgpath) kfree(pgpath); } +static void deactivate_path(struct work_struct *work) +{ + struct pgpath *pgpath = + container_of(work, struct pgpath, deactivate_path); + + blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue); +} + static struct priority_group *alloc_priority_group(void) { struct priority_group *pg; @@ -870,6 +882,7 @@ static int fail_path(struct pgpath *pgpath) pgpath->path.dev->name, m->nr_valid_paths); queue_work(kmultipathd, &m->trigger_event); + queue_work(kmultipathd, &pgpath->deactivate_path); out: spin_unlock_irqrestore(&m->lock, flags); -- GitLab From a91a3a20e06621b9931793888583efe37db4e4e8 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:01 +0900 Subject: [PATCH 3466/5416] sg: rename sg_cmd_done sg_rq_end_io old sg_rq_end_io() was used to wrap sg_cmd_done during converting sg to use the block layer (in order to cover the difference scsi_execute_async and blk_execute_rq_nowait). Now we don't need it so let's remove it. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 50c07bca727..d18f90d1d9a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -177,7 +177,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ static int sg_fasync(int fd, struct file *filp, int mode); /* tasklet or soft irq callback */ -static void sg_cmd_done(void *data, char *sense, int result, int resid); +static void sg_rq_end_io(struct request *rq, int uptodate); static int sg_start_req(Sg_request *srp, unsigned char *cmd); static void sg_finish_rem_req(Sg_request * srp); static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); @@ -227,11 +227,6 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) cmd, filp->f_mode & FMODE_WRITE); } -static void sg_rq_end_io(struct request *rq, int uptodate) -{ - sg_cmd_done(rq->end_io_data, rq->sense, rq->errors, rq->data_len); -} - static int sg_open(struct inode *inode, struct file *filp) { @@ -1257,16 +1252,19 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } -/* This function is a "bottom half" handler that is called by the - * mid level when a command is completed (or has failed). */ -static void -sg_cmd_done(void *data, char *sense, int result, int resid) +/* + * This function is a "bottom half" handler that is called by the mid + * level when a command is completed (or has failed). + */ +static void sg_rq_end_io(struct request *rq, int uptodate) { - Sg_request *srp = data; + struct sg_request *srp = rq->end_io_data; Sg_device *sdp = NULL; Sg_fd *sfp; unsigned long iflags; unsigned int ms; + char *sense; + int result, resid; if (NULL == srp) { printk(KERN_ERR "sg_cmd_done: NULL request\n"); @@ -1280,6 +1278,9 @@ sg_cmd_done(void *data, char *sense, int result, int resid) return; } + sense = rq->sense; + result = rq->errors; + resid = rq->data_len; SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", sdp->disk->disk_name, srp->header.pack_id, result)); -- GitLab From 7e56cb0f7e7a132803ffefa0a5a15fb2079afaf1 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:02 +0900 Subject: [PATCH 3467/5416] sg: remove SG_ALLOW_DIO_CODE define sg had lots of the own functions for the direct IO but now sg uses the block layer functions for it. There are only five lines for the direct IO. SG_ALLOW_DIO_CODE define was used to compile out the direct IO code but we don't need the define. If someone wants to remove the direct IO code, he can do easily without the define. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index d18f90d1d9a..2c30331abbe 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -68,7 +68,6 @@ static void sg_proc_cleanup(void); #endif #define SG_ALLOW_DIO_DEF 0 -#define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ #define SG_MAX_DEVS 32768 @@ -1674,13 +1673,12 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return 0; -#ifdef SG_ALLOW_DIO_CODE if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && (!sfp->parentdp->device->host->unchecked_isa_dma) && blk_rq_aligned(q, hp->dxferp, dxfer_len)) return sg_build_direct(srp, sfp, dxfer_len); -#endif + if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) sg_link_reserve(sfp, srp, dxfer_len); else -- GitLab From fd1c1de0766844af4cfc39298e109ad273e72a9e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:03 +0900 Subject: [PATCH 3468/5416] sg: remove b_malloc_len in sg_scatter_hold struct It's not used for anything useful after the block layer conversion. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2c30331abbe..ccce31a400e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -116,7 +116,6 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */ unsigned bufflen; /* Size of (aggregate) data buffer */ - unsigned b_malloc_len; /* actual len malloc'ed in buffer */ struct page **pages; int page_order; char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */ @@ -1986,7 +1985,6 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) req_schp->pages = rsv_schp->pages; req_schp->bufflen = size; - req_schp->b_malloc_len = rsv_schp->b_malloc_len; req_schp->page_order = rsv_schp->page_order; break; } else -- GitLab From 44c7b0eaa041007066e30ab4869d5bbf8dad5989 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:04 +0900 Subject: [PATCH 3469/5416] sg: remove __sg_start_req __sg_start_req() was used temporarily to call blk_get_request() during converting sg to use the block layer. Now sg always calls blk_get_request() so we can move blk_get_request() to sg_start_req(). We don't need __sg_start_req anymore. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ccce31a400e..9a56c0d320b 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1626,14 +1626,23 @@ exit_sg(void) idr_destroy(&sg_index_idr); } -static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp, - unsigned char *cmd) +static int sg_start_req(Sg_request *srp, unsigned char *cmd) { - struct sg_fd *sfp = srp->parentfp; - struct request_queue *q = sfp->parentdp->device->request_queue; + int res = 0; struct request *rq; + Sg_fd *sfp = srp->parentfp; + sg_io_hdr_t *hp = &srp->header; + int dxfer_len = (int) hp->dxfer_len; + int dxfer_dir = hp->dxfer_direction; + Sg_scatter_hold *req_schp = &srp->data; + Sg_scatter_hold *rsv_schp = &sfp->reserve; + struct request_queue *q = sfp->parentdp->device->request_queue; + struct rq_map_data map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", + dxfer_len)); + rq = blk_get_request(q, rw, GFP_ATOMIC); if (!rq) return -ENOMEM; @@ -1648,27 +1657,6 @@ static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp, rq->sense = srp->sense_b; rq->retries = SG_DEFAULT_RETRIES; - return 0; -} - -static int sg_start_req(Sg_request *srp, unsigned char *cmd) -{ - int res; - Sg_fd *sfp = srp->parentfp; - sg_io_hdr_t *hp = &srp->header; - int dxfer_len = (int) hp->dxfer_len; - int dxfer_dir = hp->dxfer_direction; - Sg_scatter_hold *req_schp = &srp->data; - Sg_scatter_hold *rsv_schp = &sfp->reserve; - struct request_queue *q = sfp->parentdp->device->request_queue; - struct rq_map_data map_data; - - SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); - - res = __sg_start_req(srp, hp, cmd); - if (res) - return res; - if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return 0; -- GitLab From 626710c9d665ff381c7ec666b6a023f064ca5fef Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:05 +0900 Subject: [PATCH 3470/5416] sg: incorporate sg_build_direct into sg_start_req Calling blk_rq_map_user() at a single place is better than at different two places. It makes the code more understandable. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 80 +++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9a56c0d320b..c0b6866eece 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -202,7 +202,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); -static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); static Sg_device *sg_get_dev(int dev); #ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void); @@ -1628,16 +1627,17 @@ exit_sg(void) static int sg_start_req(Sg_request *srp, unsigned char *cmd) { - int res = 0; + int res; struct request *rq; Sg_fd *sfp = srp->parentfp; sg_io_hdr_t *hp = &srp->header; int dxfer_len = (int) hp->dxfer_len; int dxfer_dir = hp->dxfer_direction; + unsigned int iov_count = hp->iovec_count; Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; struct request_queue *q = sfp->parentdp->device->request_queue; - struct rq_map_data map_data; + struct rq_map_data *md, map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", @@ -1660,38 +1660,43 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return 0; - if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && - (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && - (!sfp->parentdp->device->host->unchecked_isa_dma) && + if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO && + dxfer_dir != SG_DXFER_UNKNOWN && !iov_count && + !sfp->parentdp->device->host->unchecked_isa_dma && blk_rq_aligned(q, hp->dxferp, dxfer_len)) - return sg_build_direct(srp, sfp, dxfer_len); + md = NULL; + else + md = &map_data; + + if (md) { + if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen) + sg_link_reserve(sfp, srp, dxfer_len); + else { + res = sg_build_indirect(req_schp, sfp, dxfer_len); + if (res) + return res; + } - if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) - sg_link_reserve(sfp, srp, dxfer_len); + md->pages = req_schp->pages; + md->page_order = req_schp->page_order; + md->nr_entries = req_schp->k_use_sg; + } + + if (iov_count) + res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count, + hp->dxfer_len, GFP_ATOMIC); else - res = sg_build_indirect(req_schp, sfp, dxfer_len); + res = blk_rq_map_user(q, rq, md, hp->dxferp, + hp->dxfer_len, GFP_ATOMIC); if (!res) { - struct request *rq = srp->rq; - Sg_scatter_hold *schp = &srp->data; - int iovec_count = (int) hp->iovec_count; - - map_data.pages = schp->pages; - map_data.page_order = schp->page_order; - map_data.nr_entries = schp->k_use_sg; - - if (iovec_count) - res = blk_rq_map_user_iov(q, rq, &map_data, hp->dxferp, - iovec_count, - hp->dxfer_len, GFP_ATOMIC); - else - res = blk_rq_map_user(q, rq, &map_data, hp->dxferp, - hp->dxfer_len, GFP_ATOMIC); + srp->bio = rq->bio; - if (!res) - srp->bio = rq->bio; + if (!md) { + req_schp->dio_in_use = 1; + hp->info |= SG_INFO_DIRECT_IO; + } } - return res; } @@ -1730,25 +1735,6 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) return tablesize; /* number of scat_gath elements allocated */ } -/* Returns: -ve -> error, 0 -> done, 1 -> try indirect */ -static int -sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len) -{ - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - int res; - struct request *rq = srp->rq; - struct request_queue *q = sfp->parentdp->device->request_queue; - - res = blk_rq_map_user(q, rq, NULL, hp->dxferp, dxfer_len, GFP_ATOMIC); - if (res) - return res; - srp->bio = rq->bio; - schp->dio_in_use = 1; - hp->info |= SG_INFO_DIRECT_IO; - return 0; -} - static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) { -- GitLab From c3919af2354fff673026dcbeac6f009d2ce5ceee Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:06 +0900 Subject: [PATCH 3471/5416] sg: remove sg_write_xfer sg_write_xfer was used to copy data from user space for WRITE commands. blk_rq_map_user_iov and blk_rq_map_user do the job so sg_write_xfer does nothing useful. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index c0b6866eece..07bd6833130 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -188,7 +188,6 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, int read_only, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); -static int sg_write_xfer(Sg_request * srp); static int sg_read_xfer(Sg_request * srp); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); static void sg_remove_scat(Sg_scatter_hold * schp); @@ -736,11 +735,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ } - if ((k = sg_write_xfer(srp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n")); - sg_finish_rem_req(srp); - return k; - } if (sdp->detached) { sg_finish_rem_req(srp); return -ENODEV; @@ -1816,32 +1810,6 @@ out: return -ENOMEM; } -static int -sg_write_xfer(Sg_request * srp) -{ - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - int num_xfer = 0; - int dxfer_dir = hp->dxfer_direction; - int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - - if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) || - (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { - num_xfer = (int) (new_interface ? hp->dxfer_len : hp->flags); - if (schp->bufflen < num_xfer) - num_xfer = schp->bufflen; - } - if ((num_xfer <= 0) || (schp->dio_in_use) || - (new_interface - && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) - return 0; - - SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, k_use_sg=%d\n", - num_xfer, schp->k_use_sg)); - - return 0; -} - static void sg_remove_scat(Sg_scatter_hold * schp) { -- GitLab From 0b6cb26c6686f1f24607c41f0a6d21ce54191710 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:07 +0900 Subject: [PATCH 3472/5416] sg: remove sg_read_xfer sg_read_xfer was used to copy data to user space for READ commands. blk_rq_unmap_user does the job so sg_read_xfer does nothing useful. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 07bd6833130..df8bf67b171 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -188,7 +188,6 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, int read_only, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); -static int sg_read_xfer(Sg_request * srp); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); static void sg_remove_scat(Sg_scatter_hold * schp); static void sg_build_reserve(Sg_fd * sfp, int req_size); @@ -523,8 +522,11 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) err = -EFAULT; goto err_out; } - err = sg_read_xfer(srp); - err_out: + if (srp->bio) { + err = blk_rq_unmap_user(srp->bio); + srp->bio = NULL; + } +err_out: sg_finish_rem_req(srp); return (0 == err) ? count : err; } @@ -1831,31 +1833,6 @@ sg_remove_scat(Sg_scatter_hold * schp) memset(schp, 0, sizeof (*schp)); } -static int -sg_read_xfer(Sg_request * srp) -{ - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - int num_xfer = 0; - int dxfer_dir = hp->dxfer_direction; - int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - - if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir) - || (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { - num_xfer = hp->dxfer_len; - if (schp->bufflen < num_xfer) - num_xfer = schp->bufflen; - } - if ((num_xfer <= 0) || (schp->dio_in_use) || - (new_interface - && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) - return 0; - - SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n", - num_xfer, (int)hp->iovec_count, schp->k_use_sg)); - return 0; -} - static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) { -- GitLab From 4677735f03f5b6b6f2182f457a921855cadfb85b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 2 Sep 2008 22:50:08 +0900 Subject: [PATCH 3473/5416] sg: remove unnecessary blk_rq_unmap_user blk_rq_unmap_user in sg_finish_rem_req can take care of all the cases. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index df8bf67b171..ba9b9bbd4e7 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -522,10 +522,6 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) err = -EFAULT; goto err_out; } - if (srp->bio) { - err = blk_rq_unmap_user(srp->bio); - srp->bio = NULL; - } err_out: sg_finish_rem_req(srp); return (0 == err) ? count : err; @@ -1844,9 +1840,6 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) if ((!outp) || (num_read_xfer <= 0)) return 0; - blk_rq_unmap_user(srp->bio); - srp->bio = NULL; - num = 1 << (PAGE_SHIFT + schp->page_order); for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { if (num > num_read_xfer) { -- GitLab From 3e6053d76dcbd92b2f9f4ad5ece9bce83149523e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 11 Sep 2008 10:57:55 +0200 Subject: [PATCH 3474/5416] block: adjust blkdev_issue_discard for swap Two mods to blkdev_issue_discard(), thinking ahead to its use on swap: 1. Add gfp_mask argument, so swap allocation can use it where GFP_KERNEL might deadlock but GFP_NOIO is safe. 2. Enlarge nr_sects argument from unsigned to sector_t: unsigned long is enough to cover a whole swap area, but sector_t suits any partition. Change sb_issue_discard()'s nr_blocks to sector_t too; but no need seen for a gfp_mask there, just pass GFP_KERNEL down to blkdev_issue_discard(). Signed-off-by: Hugh Dickins Signed-off-by: Jens Axboe --- block/blk-barrier.c | 7 ++++--- include/linux/blkdev.h | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 988b63479b2..5c99ff8d2db 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -332,12 +332,13 @@ static void blkdev_discard_end_io(struct bio *bio, int err) * @bdev: blockdev to issue discard for * @sector: start sector * @nr_sects: number of sectors to discard + * @gfp_mask: memory allocation flags (for bio_alloc) * * Description: * Issue a discard request for the sectors in question. Does not wait. */ -int blkdev_issue_discard(struct block_device *bdev, sector_t sector, - unsigned nr_sects) +int blkdev_issue_discard(struct block_device *bdev, + sector_t sector, sector_t nr_sects, gfp_t gfp_mask) { struct request_queue *q; struct bio *bio; @@ -354,7 +355,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, return -EOPNOTSUPP; while (nr_sects && !ret) { - bio = bio_alloc(GFP_KERNEL, 0); + bio = bio_alloc(gfp_mask, 0); if (!bio) return -ENOMEM; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 37781d6fe04..b47767c72ce 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -873,15 +874,15 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, } extern int blkdev_issue_flush(struct block_device *, sector_t *); -extern int blkdev_issue_discard(struct block_device *, sector_t sector, - unsigned nr_sects); +extern int blkdev_issue_discard(struct block_device *, + sector_t sector, sector_t nr_sects, gfp_t); static inline int sb_issue_discard(struct super_block *sb, - sector_t block, unsigned nr_blocks) + sector_t block, sector_t nr_blocks) { block <<= (sb->s_blocksize_bits - 9); nr_blocks <<= (sb->s_blocksize_bits - 9); - return blkdev_issue_discard(sb->s_bdev, block, nr_blocks); + return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_KERNEL); } /* -- GitLab From 0a0d96b03a1f3bfd6bc3ea08008699e8e59fccd9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 11 Sep 2008 13:17:37 +0200 Subject: [PATCH 3475/5416] block: add bio_kmalloc() Not all callers need (or want!) the mempool backing guarentee, it essentially means that you can only use bio_alloc() for short allocations and not for preallocating some bio's at setup or init time. So add bio_kmalloc() which does the same thing as bio_alloc(), except it just uses kmalloc() as the backing instead of the bio mempools. Signed-off-by: Jens Axboe --- fs/bio.c | 96 +++++++++++++++++++++++++++++++++++---------- include/linux/bio.h | 1 + 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index 355302985e2..e56e7685af9 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -60,25 +60,46 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct struct bio_vec *bvl; /* - * see comment near bvec_array define! + * If 'bs' is given, lookup the pool and do the mempool alloc. + * If not, this is a bio_kmalloc() allocation and just do a + * kzalloc() for the exact number of vecs right away. */ - switch (nr) { - case 1 : *idx = 0; break; - case 2 ... 4: *idx = 1; break; - case 5 ... 16: *idx = 2; break; - case 17 ... 64: *idx = 3; break; - case 65 ... 128: *idx = 4; break; - case 129 ... BIO_MAX_PAGES: *idx = 5; break; + if (bs) { + /* + * see comment near bvec_array define! + */ + switch (nr) { + case 1: + *idx = 0; + break; + case 2 ... 4: + *idx = 1; + break; + case 5 ... 16: + *idx = 2; + break; + case 17 ... 64: + *idx = 3; + break; + case 65 ... 128: + *idx = 4; + break; + case 129 ... BIO_MAX_PAGES: + *idx = 5; + break; default: return NULL; - } - /* - * idx now points to the pool we want to allocate from - */ + } - bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); - if (bvl) - memset(bvl, 0, bvec_nr_vecs(*idx) * sizeof(struct bio_vec)); + /* + * idx now points to the pool we want to allocate from + */ + bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); + if (bvl) + memset(bvl, 0, + bvec_nr_vecs(*idx) * sizeof(struct bio_vec)); + } else + bvl = kzalloc(nr * sizeof(struct bio_vec), gfp_mask); return bvl; } @@ -107,6 +128,12 @@ static void bio_fs_destructor(struct bio *bio) bio_free(bio, fs_bio_set); } +static void bio_kmalloc_destructor(struct bio *bio) +{ + kfree(bio->bi_io_vec); + kfree(bio); +} + void bio_init(struct bio *bio) { memset(bio, 0, sizeof(*bio)); @@ -119,19 +146,25 @@ void bio_init(struct bio *bio) * bio_alloc_bioset - allocate a bio for I/O * @gfp_mask: the GFP_ mask given to the slab allocator * @nr_iovecs: number of iovecs to pre-allocate - * @bs: the bio_set to allocate from + * @bs: the bio_set to allocate from. If %NULL, just use kmalloc * * Description: - * bio_alloc_bioset will first try it's on mempool to satisfy the allocation. + * bio_alloc_bioset will first try its own mempool to satisfy the allocation. * If %__GFP_WAIT is set then we will block on the internal pool waiting - * for a &struct bio to become free. + * for a &struct bio to become free. If a %NULL @bs is passed in, we will + * fall back to just using @kmalloc to allocate the required memory. * * allocate bio and iovecs from the memory pools specified by the - * bio_set structure. + * bio_set structure, or @kmalloc if none given. **/ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) { - struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); + struct bio *bio; + + if (bs) + bio = mempool_alloc(bs->bio_pool, gfp_mask); + else + bio = kmalloc(sizeof(*bio), gfp_mask); if (likely(bio)) { struct bio_vec *bvl = NULL; @@ -142,7 +175,10 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); if (unlikely(!bvl)) { - mempool_free(bio, bs->bio_pool); + if (bs) + mempool_free(bio, bs->bio_pool); + else + kfree(bio); bio = NULL; goto out; } @@ -165,6 +201,23 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) return bio; } +/* + * Like bio_alloc(), but doesn't use a mempool backing. This means that + * it CAN fail, but while bio_alloc() can only be used for allocations + * that have a short (finite) life span, bio_kmalloc() should be used + * for more permanent bio allocations (like allocating some bio's for + * initalization or setup purposes). + */ +struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs) +{ + struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, NULL); + + if (bio) + bio->bi_destructor = bio_kmalloc_destructor; + + return bio; +} + void zero_fill_bio(struct bio *bio) { unsigned long flags; @@ -1349,6 +1402,7 @@ static int __init init_bio(void) subsys_initcall(init_bio); EXPORT_SYMBOL(bio_alloc); +EXPORT_SYMBOL(bio_kmalloc); EXPORT_SYMBOL(bio_put); EXPORT_SYMBOL(bio_free); EXPORT_SYMBOL(bio_endio); diff --git a/include/linux/bio.h b/include/linux/bio.h index 7af373f253d..6520ee1a3f6 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -308,6 +308,7 @@ extern struct bio_set *bioset_create(int, int); extern void bioset_free(struct bio_set *); extern struct bio *bio_alloc(gfp_t, int); +extern struct bio *bio_kmalloc(gfp_t, int); extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); -- GitLab From 581d4e28d9195aa8b2231383dbabc288988d615e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 14 Sep 2008 05:56:33 -0700 Subject: [PATCH 3476/5416] block: add fault injection mechanism for faking request timeouts Only works for the generic request timer handling. Allows one to sporadically ignore request completions, thus exercising the timeout handling. Signed-off-by: Jens Axboe --- block/blk-softirq.c | 2 ++ block/blk-timeout.c | 59 ++++++++++++++++++++++++++++++++++++++++++ block/blk.h | 12 +++++++++ block/genhd.c | 8 ++++++ include/linux/blkdev.h | 1 + lib/Kconfig.debug | 13 +++++++++- 6 files changed, 94 insertions(+), 1 deletion(-) diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 7ab344afb16..e660d26ca65 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -154,6 +154,8 @@ do_local: **/ void blk_complete_request(struct request *req) { + if (unlikely(blk_should_fake_timeout(req->q))) + return; if (!blk_mark_rq_complete(req)) __blk_complete_request(req); } diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 6e5c781c5af..9b4ad138bb3 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -4,9 +4,68 @@ #include #include #include +#include #include "blk.h" +#ifdef CONFIG_FAIL_IO_TIMEOUT + +static DECLARE_FAULT_ATTR(fail_io_timeout); + +static int __init setup_fail_io_timeout(char *str) +{ + return setup_fault_attr(&fail_io_timeout, str); +} +__setup("fail_io_timeout=", setup_fail_io_timeout); + +int blk_should_fake_timeout(struct request_queue *q) +{ + if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags)) + return 0; + + return should_fail(&fail_io_timeout, 1); +} + +static int __init fail_io_timeout_debugfs(void) +{ + return init_fault_attr_dentries(&fail_io_timeout, "fail_io_timeout"); +} + +late_initcall(fail_io_timeout_debugfs); + +ssize_t part_timeout_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gendisk *disk = dev_to_disk(dev); + int set = test_bit(QUEUE_FLAG_FAIL_IO, &disk->queue->queue_flags); + + return sprintf(buf, "%d\n", set != 0); +} + +ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gendisk *disk = dev_to_disk(dev); + int val; + + if (count) { + struct request_queue *q = disk->queue; + char *p = (char *) buf; + + val = simple_strtoul(p, &p, 10); + spin_lock_irq(q->queue_lock); + if (val) + queue_flag_set(QUEUE_FLAG_FAIL_IO, q); + else + queue_flag_clear(QUEUE_FLAG_FAIL_IO, q); + spin_unlock_irq(q->queue_lock); + } + + return count; +} + +#endif /* CONFIG_FAIL_IO_TIMEOUT */ + /* * blk_delete_timer - Delete/cancel timer for a given function. * @req: request that we are canceling timer for diff --git a/block/blk.h b/block/blk.h index a4f4a50aefa..e5c57976996 100644 --- a/block/blk.h +++ b/block/blk.h @@ -42,6 +42,18 @@ static inline void blk_clear_rq_complete(struct request *rq) clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); } +#ifdef CONFIG_FAIL_IO_TIMEOUT +int blk_should_fake_timeout(struct request_queue *); +ssize_t part_timeout_show(struct device *, struct device_attribute *, char *); +ssize_t part_timeout_store(struct device *, struct device_attribute *, + const char *, size_t); +#else +static inline int blk_should_fake_timeout(struct request_queue *q) +{ + return 0; +} +#endif + struct io_context *current_io_context(gfp_t gfp_flags, int node); int ll_back_merge_fn(struct request_queue *q, struct request *req, diff --git a/block/genhd.c b/block/genhd.c index 8acaff0154e..4cd3433c99a 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -817,6 +817,11 @@ static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); static struct device_attribute dev_attr_fail = __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); #endif +#ifdef CONFIG_FAIL_IO_TIMEOUT +static struct device_attribute dev_attr_fail_timeout = + __ATTR(io-timeout-fail, S_IRUGO|S_IWUSR, part_timeout_show, + part_timeout_store); +#endif static struct attribute *disk_attrs[] = { &dev_attr_range.attr, @@ -828,6 +833,9 @@ static struct attribute *disk_attrs[] = { &dev_attr_stat.attr, #ifdef CONFIG_FAIL_MAKE_REQUEST &dev_attr_fail.attr, +#endif +#ifdef CONFIG_FAIL_IO_TIMEOUT + &dev_attr_fail_timeout.attr, #endif NULL }; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b47767c72ce..e34999d14c1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -440,6 +440,7 @@ struct request_queue #define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */ #define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ #define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ +#define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ static inline int queue_is_locked(struct request_queue *q) { diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c556896abe5..7d7a31d0dde 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -683,10 +683,21 @@ config FAIL_PAGE_ALLOC config FAIL_MAKE_REQUEST bool "Fault-injection capability for disk IO" - depends on FAULT_INJECTION + depends on FAULT_INJECTION && BLOCK help Provide fault-injection capability for disk IO. +config FAIL_IO_TIMEOUT + bool "Faul-injection capability for faking disk interrupts" + depends on FAULT_INJECTION && BLOCK + help + Provide fault-injection capability on end IO handling. This + will make the block layer "forget" an interrupt as configured, + thus exercising the error handling. + + Only works with drivers that use the generic timeout handling, + for others it wont do anything. + config FAULT_INJECTION_DEBUG_FS bool "Debugfs entries for fault-injection capabilities" depends on FAULT_INJECTION && SYSFS && DEBUG_FS -- GitLab From 7ba1fbaa4a478f72fbaf5a56af9c82a77966b4c7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 16 Sep 2008 09:54:11 -0700 Subject: [PATCH 3477/5416] block: use rq complete marking in blk_abort_request() We cannot abort a request if we raced with the timeout handler already, or with the IO completion. So make blk_abort_request() mark the request as complete, and only continue if we succeeded. Found and suggested by Mike Anderson Signed-off-by: Jens Axboe --- block/blk-timeout.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 9b4ad138bb3..972a63f848f 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -158,6 +158,8 @@ void blk_rq_timed_out_timer(unsigned long data) */ void blk_abort_request(struct request *req) { + if (blk_mark_rq_complete(req)) + return; blk_delete_timer(req); blk_rq_timed_out(req); } -- GitLab From 9c02f2b02e29a2244e36c6e1f246080d8afc6cff Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 18 Sep 2008 09:31:53 -0700 Subject: [PATCH 3478/5416] block: cleanup some of the integrity stuff in blkdev.h Don't put functions that are only used in fs/bio-integrity.c in blkdev.h, it's much cleaner to just keep it in there. Also kill completely unused bdev_get_tag_size() Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 31 ++++++++++++++++++++++++++++++ include/linux/blkdev.h | 43 ------------------------------------------ 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index c3e174b35fe..ba4ada08564 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -150,6 +150,29 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, } EXPORT_SYMBOL(bio_integrity_add_page); +static struct blk_integrity *bdev_get_integrity(struct block_device *bdev) +{ + return bdev->bd_disk->integrity; +} + +static int bdev_integrity_enabled(struct block_device *bdev, int rw) +{ + struct blk_integrity *bi = bdev_get_integrity(bdev); + + if (bi == NULL) + return 0; + + if (rw == READ && bi->verify_fn != NULL && + (bi->flags & INTEGRITY_FLAG_READ)) + return 1; + + if (rw == WRITE && bi->generate_fn != NULL && + (bi->flags & INTEGRITY_FLAG_WRITE)) + return 1; + + return 0; +} + /** * bio_integrity_enabled - Check whether integrity can be passed * @bio: bio to check @@ -313,6 +336,14 @@ static void bio_integrity_generate(struct bio *bio) } } +static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) +{ + if (bi) + return bi->tuple_size; + + return 0; +} + /** * bio_integrity_prep - Prepare bio for integrity I/O * @bio: bio to prepare diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e34999d14c1..e23b838825b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1004,47 +1004,6 @@ extern int blk_integrity_compare(struct block_device *, struct block_device *); extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); extern int blk_rq_count_integrity_sg(struct request *); -static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) -{ - if (bi) - return bi->tuple_size; - - return 0; -} - -static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev) -{ - return bdev->bd_disk->integrity; -} - -static inline unsigned int bdev_get_tag_size(struct block_device *bdev) -{ - struct blk_integrity *bi = bdev_get_integrity(bdev); - - if (bi) - return bi->tag_size; - - return 0; -} - -static inline int bdev_integrity_enabled(struct block_device *bdev, int rw) -{ - struct blk_integrity *bi = bdev_get_integrity(bdev); - - if (bi == NULL) - return 0; - - if (rw == READ && bi->verify_fn != NULL && - (bi->flags & INTEGRITY_FLAG_READ)) - return 1; - - if (rw == WRITE && bi->generate_fn != NULL && - (bi->flags & INTEGRITY_FLAG_WRITE)) - return 1; - - return 0; -} - static inline int blk_integrity_rq(struct request *rq) { if (rq->bio == NULL) @@ -1058,8 +1017,6 @@ static inline int blk_integrity_rq(struct request *rq) #define blk_integrity_rq(rq) (0) #define blk_rq_count_integrity_sg(a) (0) #define blk_rq_map_integrity_sg(a, b) (0) -#define bdev_get_integrity(a) (0) -#define bdev_get_tag_size(a) (0) #define blk_integrity_compare(a, b) (0) #define blk_integrity_register(a, b) (0) #define blk_integrity_unregister(a) do { } while (0); -- GitLab From 9246b5f06deeea541e7c62437c2ad19a0b1172c0 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Wed, 17 Sep 2008 14:30:32 -0700 Subject: [PATCH 3479/5416] block: Expand Xen blkfront for > 16 xvd Until recently, the maximum number of xvd block devices you could attach to a Xen domU was 16. This limitation turned out to be problematic for some users, so it was expanded to handle a much larger number of disks. However, this requires a couple of changes in the way that blkfront scans for disks. This functionality is already present in the Xen linux-2.6.18-xen.hg tree; the attached patch adds this functionality to the mainline xen-blkfront implementation. I successfully tested it on a 2.6.25 tree, and build tested it on 2.6.27-rc3. Signed-off-by: Chris Lalancette Acked-by: Jeremy Fitzhardinge Signed-off-by: Jens Axboe --- drivers/block/xen-blkfront.c | 76 ++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 3ca643cafcc..bff602ccccf 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -105,15 +105,17 @@ static DEFINE_SPINLOCK(blkif_io_lock); #define GRANT_INVALID_REF 0 #define PARTS_PER_DISK 16 +#define PARTS_PER_EXT_DISK 256 #define BLKIF_MAJOR(dev) ((dev)>>8) #define BLKIF_MINOR(dev) ((dev) & 0xff) -#define DEV_NAME "xvd" /* name in /dev */ +#define EXT_SHIFT 28 +#define EXTENDED (1<gd != NULL); BUG_ON(info->rq != NULL); - if ((minor % PARTS_PER_DISK) == 0) - nr_minors = PARTS_PER_DISK; + if ((info->vdevice>>EXT_SHIFT) > 1) { + /* this is above the extended range; something is wrong */ + printk(KERN_WARNING "blkfront: vdevice 0x%x is above the extended range; ignoring\n", info->vdevice); + return -ENODEV; + } + + if (!VDEV_IS_EXTENDED(info->vdevice)) { + minor = BLKIF_MINOR(info->vdevice); + nr_parts = PARTS_PER_DISK; + } else { + minor = BLKIF_MINOR_EXT(info->vdevice); + nr_parts = PARTS_PER_EXT_DISK; + } + + if ((minor % nr_parts) == 0) + nr_minors = nr_parts; gd = alloc_disk(nr_minors); if (gd == NULL) goto out; - if (nr_minors > 1) - sprintf(gd->disk_name, "%s%c", DEV_NAME, - 'a' + minor / PARTS_PER_DISK); - else - sprintf(gd->disk_name, "%s%c%d", DEV_NAME, - 'a' + minor / PARTS_PER_DISK, - minor % PARTS_PER_DISK); + offset = minor / nr_parts; + + if (nr_minors > 1) { + if (offset < 26) + sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); + else + sprintf(gd->disk_name, "%s%c%c", DEV_NAME, + 'a' + ((offset / 26)-1), 'a' + (offset % 26)); + } else { + if (offset < 26) + sprintf(gd->disk_name, "%s%c%d", DEV_NAME, + 'a' + offset, + minor & (nr_parts - 1)); + else + sprintf(gd->disk_name, "%s%c%c%d", DEV_NAME, + 'a' + ((offset / 26) - 1), + 'a' + (offset % 26), + minor & (nr_parts - 1)); + } gd->major = XENVBD_MAJOR; gd->first_minor = minor; @@ -699,8 +730,13 @@ static int blkfront_probe(struct xenbus_device *dev, err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device", "%i", &vdevice); if (err != 1) { - xenbus_dev_fatal(dev, err, "reading virtual-device"); - return err; + /* go looking in the extended area instead */ + err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext", + "%i", &vdevice); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading virtual-device"); + return err; + } } info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -861,9 +897,7 @@ static void blkfront_connect(struct blkfront_info *info) if (err) info->feature_barrier = 0; - err = xlvbd_alloc_gendisk(BLKIF_MINOR(info->vdevice), - sectors, info->vdevice, - binfo, sector_size, info); + err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); if (err) { xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", info->xbdev->otherend); -- GitLab From e3335de94067dbebe22e3962632ead34e832cb60 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 18 Sep 2008 09:22:54 -0700 Subject: [PATCH 3480/5416] block: blk_cleanup_queue() should call blk_sync_queue() When a driver calls blk_cleanup_queue(), the device should be fully idle. However, the block layer may have pending plugging timers and the IO schedulers may have pending work in the work queues. So quisce the device by waiting for the timer and flushing the work queues. Signed-off-by: Jens Axboe --- block/blk-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index d768a8ddc17..37fba001bdc 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -436,6 +436,14 @@ void blk_put_queue(struct request_queue *q) void blk_cleanup_queue(struct request_queue *q) { + /* + * We know we have process context here, so we can be a little + * cautious and ensure that pending block actions on this device + * are done before moving on. Going into this function, we should + * not have processes doing IO to this device. + */ + blk_sync_queue(q); + mutex_lock(&q->sysfs_lock); queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); mutex_unlock(&q->sysfs_lock); -- GitLab From 32fab448e5e86694beade415e750363538ea5f49 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 18 Sep 2008 10:45:09 -0400 Subject: [PATCH 3481/5416] block: add request update interface This patch adds blk_update_request(), which updates struct request with completing its data part, but doesn't complete the struct request itself. Though it looks like end_that_request_first() of older kernels, blk_update_request() should be used only by request stacking drivers. Request-based dm will use it in bio->bi_end_io callback to update the original request when a data part of a cloned request completes. Followings are additional background information of why request-based dm needs this interface. - Request stacking drivers can't use blk_end_request() directly from the lower driver's completion context (bio->bi_end_io or rq->end_io), because some device drivers (e.g. ide) may try to complete their request with queue lock held, and it may cause deadlock. See below for detailed description of possible deadlock: - To solve that, request-based dm offloads the completion of cloned struct request to softirq context (i.e. using blk_complete_request() from rq->end_io). - Though it is possible to use the same solution from bio->bi_end_io, it will delay the notification of bio completion to the original submitter. Also, it will cause inefficient partial completion, because the lower driver can't perform the cloned request anymore and request-based dm needs to requeue and redispatch it to the lower driver again later. That's not good. - So request-based dm needs blk_update_request() to perform the bio completion in the lower driver's completion context, which is more efficient. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/blk-core.c | 57 +++++++++++++++++++++++++++++++++++------- include/linux/blkdev.h | 2 ++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 37fba001bdc..527d43e982b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1806,6 +1806,22 @@ void end_request(struct request *req, int uptodate) } EXPORT_SYMBOL(end_request); +static int end_that_request_data(struct request *rq, int error, + unsigned int nr_bytes, unsigned int bidi_bytes) +{ + if (rq->bio) { + if (__end_that_request_first(rq, error, nr_bytes)) + return 1; + + /* Bidi request must be completed as a whole */ + if (blk_bidi_rq(rq) && + __end_that_request_first(rq->next_rq, error, bidi_bytes)) + return 1; + } + + return 0; +} + /** * blk_end_io - Generic end_io function to complete a request. * @rq: the request being processed @@ -1832,15 +1848,8 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, struct request_queue *q = rq->q; unsigned long flags = 0UL; - if (rq->bio) { - if (__end_that_request_first(rq, error, nr_bytes)) - return 1; - - /* Bidi request must be completed as a whole */ - if (blk_bidi_rq(rq) && - __end_that_request_first(rq->next_rq, error, bidi_bytes)) - return 1; - } + if (end_that_request_data(rq, error, nr_bytes, bidi_bytes)) + return 1; /* Special feature for tricky drivers */ if (drv_callback && drv_callback(rq)) @@ -1922,6 +1931,36 @@ int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, } EXPORT_SYMBOL_GPL(blk_end_bidi_request); +/** + * blk_update_request - Special helper function for request stacking drivers + * @rq: the request being processed + * @error: %0 for success, < %0 for error + * @nr_bytes: number of bytes to complete @rq + * + * Description: + * Ends I/O on a number of bytes attached to @rq, but doesn't complete + * the request structure even if @rq doesn't have leftover. + * If @rq has leftover, sets it up for the next range of segments. + * + * This special helper function is only for request stacking drivers + * (e.g. request-based dm) so that they can handle partial completion. + * Actual device drivers should use blk_end_request instead. + */ +void blk_update_request(struct request *rq, int error, unsigned int nr_bytes) +{ + if (!end_that_request_data(rq, error, nr_bytes, 0)) { + /* + * These members are not updated in end_that_request_data() + * when all bios are completed. + * Update them so that the request stacking driver can find + * how many bytes remain in the request later. + */ + rq->nr_sectors = rq->hard_nr_sectors = 0; + rq->current_nr_sectors = rq->hard_cur_sectors = 0; + } +} +EXPORT_SYMBOL_GPL(blk_update_request); + /** * blk_end_request_callback - Special helper function for tricky drivers * @rq: the request being processed diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e23b838825b..e82a84c9f37 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -791,6 +791,8 @@ extern void blk_complete_request(struct request *); extern void __blk_complete_request(struct request *); extern void blk_abort_request(struct request *); extern void blk_abort_queue(struct request_queue *); +extern void blk_update_request(struct request *rq, int error, + unsigned int nr_bytes); /* * blk_end_request() takes bytes instead of sectors as a complete size. -- GitLab From 82124d60354846623a4b94af335717a5e142a074 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 18 Sep 2008 10:45:38 -0400 Subject: [PATCH 3482/5416] block: add request submission interface This patch adds blk_insert_cloned_request(), a generic request submission interface for request stacking drivers. Request-based dm will use it to submit their clones to underlying devices. blk_rq_check_limits() is also added because it is possible that the lower queue has stronger limitations than the upper queue if multiple drivers are stacking at request-level. Not only for blk_insert_cloned_request()'s internal use, the function will be used by request-based dm when the queue limitation is modified (e.g. by replacing dm's table). Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/blk-core.c | 81 ++++++++++++++++++++++++++++++++++++++++++ include/linux/blkdev.h | 3 ++ 2 files changed, 84 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 527d43e982b..b8ffbfe85ca 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1529,6 +1529,87 @@ void submit_bio(int rw, struct bio *bio) } EXPORT_SYMBOL(submit_bio); +/** + * blk_rq_check_limits - Helper function to check a request for the queue limit + * @q: the queue + * @rq: the request being checked + * + * Description: + * @rq may have been made based on weaker limitations of upper-level queues + * in request stacking drivers, and it may violate the limitation of @q. + * Since the block layer and the underlying device driver trust @rq + * after it is inserted to @q, it should be checked against @q before + * the insertion using this generic function. + * + * This function should also be useful for request stacking drivers + * in some cases below, so export this fuction. + * Request stacking drivers like request-based dm may change the queue + * limits while requests are in the queue (e.g. dm's table swapping). + * Such request stacking drivers should check those requests agaist + * the new queue limits again when they dispatch those requests, + * although such checkings are also done against the old queue limits + * when submitting requests. + */ +int blk_rq_check_limits(struct request_queue *q, struct request *rq) +{ + if (rq->nr_sectors > q->max_sectors || + rq->data_len > q->max_hw_sectors << 9) { + printk(KERN_ERR "%s: over max size limit.\n", __func__); + return -EIO; + } + + /* + * queue's settings related to segment counting like q->bounce_pfn + * may differ from that of other stacking queues. + * Recalculate it to check the request correctly on this queue's + * limitation. + */ + blk_recalc_rq_segments(rq); + if (rq->nr_phys_segments > q->max_phys_segments || + rq->nr_phys_segments > q->max_hw_segments) { + printk(KERN_ERR "%s: over max segments limit.\n", __func__); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(blk_rq_check_limits); + +/** + * blk_insert_cloned_request - Helper for stacking drivers to submit a request + * @q: the queue to submit the request + * @rq: the request being queued + */ +int blk_insert_cloned_request(struct request_queue *q, struct request *rq) +{ + unsigned long flags; + + if (blk_rq_check_limits(q, rq)) + return -EIO; + +#ifdef CONFIG_FAIL_MAKE_REQUEST + if (rq->rq_disk && rq->rq_disk->part0.make_it_fail && + should_fail(&fail_make_request, blk_rq_bytes(rq))) + return -EIO; +#endif + + spin_lock_irqsave(q->queue_lock, flags); + + /* + * Submitting request must be dequeued before calling this function + * because it will be linked to another request_queue + */ + BUG_ON(blk_queued_rq(rq)); + + drive_stat_acct(rq, 1); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); + + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(blk_insert_cloned_request); + /** * __end_that_request_first - end I/O on a request * @req: the request being processed diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e82a84c9f37..964c246bc27 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -693,6 +693,9 @@ extern void __blk_put_request(struct request_queue *, struct request *); extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern void blk_insert_request(struct request_queue *, struct request *, int, void *); extern void blk_requeue_request(struct request_queue *, struct request *); +extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); +extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); extern void blk_plug_device(struct request_queue *); extern void blk_plug_device_unlocked(struct request_queue *); extern int blk_remove_plug(struct request_queue *); -- GitLab From 4ee5eaf4516a60f8ef64d3c246c64c6be0cf8c3a Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Thu, 18 Sep 2008 10:46:13 -0400 Subject: [PATCH 3483/5416] block: add a queue flag for request stacking support This patch adds a queue flag to indicate the block device can be used for request stacking. Request stacking drivers need to stack their devices on top of only devices of which q->request_fn is functional. Since bio stacking drivers (e.g. md, loop) basically initialize their queue using blk_alloc_queue() and don't set q->request_fn, the check of (q->request_fn == NULL) looks enough for that purpose. However, dm will become both types of stacking driver (bio-based and request-based). And dm will always set q->request_fn even if the dm device is bio-based of which q->request_fn is not functional actually. So we need something else to distinguish the type of the device. Adding a queue flag is a solution for that. The reason why dm always sets q->request_fn is to keep the compatibility of dm user-space tools. Currently, all dm user-space tools are using bio-based dm without specifying the type of the dm device they use. To use request-based dm without changing such tools, the kernel must decide the type of the dm device automatically. The automatic type decision can't be done at the device creation time and needs to be deferred until such tools load a mapping table, since the actual type is decided by dm target type included in the mapping table. So a dm device has to be initialized using blk_init_queue() so that we can load either type of table. Then, all queue stuffs are set (e.g. q->request_fn) and we have no element to distinguish that it is bio-based or request-based, even after a table is loaded and the type of the device is decided. By the way, some stuffs of the queue (e.g. request_list, elevator) are needless when the dm device is used as bio-based. But the memory size is not so large (about 20[KB] per queue on ia64), so I hope the memory loss can be acceptable for bio-based dm users. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/blk-core.c | 3 ++- include/linux/blkdev.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index b8ffbfe85ca..fa212348c4c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -574,7 +574,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) q->request_fn = rfn; q->prep_rq_fn = NULL; q->unplug_fn = generic_unplug_device; - q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); + q->queue_flags = (1 << QUEUE_FLAG_CLUSTER | + 1 << QUEUE_FLAG_STACKABLE); q->queue_lock = lock; blk_queue_segment_boundary(q, 0xffffffff); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 964c246bc27..86f77ef127f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -441,6 +441,7 @@ struct request_queue #define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ #define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ #define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ +#define QUEUE_FLAG_STACKABLE 13 /* supports request stacking */ static inline int queue_is_locked(struct request_queue *q) { @@ -547,6 +548,8 @@ enum { #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags) #define blk_queue_flushing(q) ((q)->ordseq) +#define blk_queue_stackable(q) \ + test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) #define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS) #define blk_pc_request(rq) ((rq)->cmd_type == REQ_TYPE_BLOCK_PC) -- GitLab From 79eb014578b79fcfb9d9e7dc979d1316079220aa Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 18 Sep 2008 09:35:28 -0700 Subject: [PATCH 3484/5416] fix an example of scatterlists handling in DMA-API.txt This example isn't the proper way to handle scatterlists (can't handle sg chaining). Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- Documentation/DMA-API.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index d8b63d164e4..b8e86460046 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -337,7 +337,7 @@ With scatterlists, you use the resulting mapping like this: int i, count = dma_map_sg(dev, sglist, nents, direction); struct scatterlist *sg; - for (i = 0, sg = sglist; i < count; i++, sg++) { + for_each_sg(sglist, sg, count, i) { hw_address[i] = sg_dma_address(sg); hw_len[i] = sg_dma_len(sg); } -- GitLab From 905bd78f2188da69e74966918e3d71df3dff382b Mon Sep 17 00:00:00 2001 From: "scameron@beardog.cca.cpqcorp.net" Date: Fri, 19 Sep 2008 18:27:47 -0700 Subject: [PATCH 3485/5416] cciss: Fix cciss SCSI rescan code to better notice device changes Fix cciss SCSI rescan code to better notice device changes. If you hot-unplug a tape drive, then hot-plug a different tape drive into the same slot in a storage enclosure, the cciss driver wouldn't notice anything had changed, as it was only looking at the LUN address and device type. Now it looks at the inquiry page 0x83 device identifier, and vendor and model strings as well. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss_scsi.c | 151 ++++++++++++++++++++++++------------- drivers/block/cciss_scsi.h | 4 + 2 files changed, 102 insertions(+), 53 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index e1233aabda7..a3fd87b4144 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -365,7 +365,7 @@ struct scsi2map { static int cciss_scsi_add_entry(int ctlr, int hostno, - unsigned char *scsi3addr, int devtype, + struct cciss_scsi_dev_t *device, struct scsi2map *added, int *nadded) { /* assumes hba[ctlr]->scsi_ctlr->lock is held */ @@ -384,12 +384,12 @@ cciss_scsi_add_entry(int ctlr, int hostno, lun = 0; /* Is this device a non-zero lun of a multi-lun device */ /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */ - if (scsi3addr[4] != 0) { + if (device->scsi3addr[4] != 0) { /* Search through our list and find the device which */ /* has the same 8 byte LUN address, excepting byte 4. */ /* Assign the same bus and target for this new LUN. */ /* Use the logical unit number from the firmware. */ - memcpy(addr1, scsi3addr, 8); + memcpy(addr1, device->scsi3addr, 8); addr1[4] = 0; for (i = 0; i < n; i++) { sd = &ccissscsi[ctlr].dev[i]; @@ -399,7 +399,7 @@ cciss_scsi_add_entry(int ctlr, int hostno, if (memcmp(addr1, addr2, 8) == 0) { bus = sd->bus; target = sd->target; - lun = scsi3addr[4]; + lun = device->scsi3addr[4]; break; } } @@ -420,8 +420,12 @@ cciss_scsi_add_entry(int ctlr, int hostno, added[*nadded].lun = sd->lun; (*nadded)++; - memcpy(&sd->scsi3addr[0], scsi3addr, 8); - sd->devtype = devtype; + memcpy(sd->scsi3addr, device->scsi3addr, 8); + memcpy(sd->vendor, device->vendor, sizeof(sd->vendor)); + memcpy(sd->revision, device->revision, sizeof(sd->revision)); + memcpy(sd->device_id, device->device_id, sizeof(sd->device_id)); + sd->devtype = device->devtype; + ccissscsi[ctlr].ndevices++; /* initially, (before registering with scsi layer) we don't @@ -487,6 +491,22 @@ static void fixup_botched_add(int ctlr, char *scsi3addr) CPQ_TAPE_UNLOCK(ctlr, flags); } +static int device_is_the_same(struct cciss_scsi_dev_t *dev1, + struct cciss_scsi_dev_t *dev2) +{ + return dev1->devtype == dev2->devtype && + memcmp(dev1->scsi3addr, dev2->scsi3addr, + sizeof(dev1->scsi3addr)) == 0 && + memcmp(dev1->device_id, dev2->device_id, + sizeof(dev1->device_id)) == 0 && + memcmp(dev1->vendor, dev2->vendor, + sizeof(dev1->vendor)) == 0 && + memcmp(dev1->model, dev2->model, + sizeof(dev1->model)) == 0 && + memcmp(dev1->revision, dev2->revision, + sizeof(dev1->revision)) == 0; +} + static int adjust_cciss_scsi_table(int ctlr, int hostno, struct cciss_scsi_dev_t sd[], int nsds) @@ -532,7 +552,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, for (j=0;jscsi3addr)) { - if (sd[j].devtype == csd->devtype) + if (device_is_the_same(&sd[j], csd)) found=2; else found=1; @@ -548,22 +568,26 @@ adjust_cciss_scsi_table(int ctlr, int hostno, cciss_scsi_remove_entry(ctlr, hostno, i, removed, &nremoved); /* remove ^^^, hence i not incremented */ - } - else if (found == 1) { /* device is different kind */ + } else if (found == 1) { /* device is different in some way */ changes++; - printk("cciss%d: device c%db%dt%dl%d type changed " - "(device type now %s).\n", - ctlr, hostno, csd->bus, csd->target, csd->lun, - scsi_device_type(csd->devtype)); + printk("cciss%d: device c%db%dt%dl%d has changed.\n", + ctlr, hostno, csd->bus, csd->target, csd->lun); cciss_scsi_remove_entry(ctlr, hostno, i, removed, &nremoved); /* remove ^^^, hence i not incremented */ - if (cciss_scsi_add_entry(ctlr, hostno, - &sd[j].scsi3addr[0], sd[j].devtype, + if (cciss_scsi_add_entry(ctlr, hostno, &sd[j], added, &nadded) != 0) /* we just removed one, so add can't fail. */ BUG(); csd->devtype = sd[j].devtype; + memcpy(csd->device_id, sd[j].device_id, + sizeof(csd->device_id)); + memcpy(csd->vendor, sd[j].vendor, + sizeof(csd->vendor)); + memcpy(csd->model, sd[j].model, + sizeof(csd->model)); + memcpy(csd->revision, sd[j].revision, + sizeof(csd->revision)); } else /* device is same as it ever was, */ i++; /* so just move along. */ } @@ -577,7 +601,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, csd = &ccissscsi[ctlr].dev[j]; if (SCSI3ADDR_EQ(sd[i].scsi3addr, csd->scsi3addr)) { - if (sd[i].devtype == csd->devtype) + if (device_is_the_same(&sd[i], csd)) found=2; /* found device */ else found=1; /* found a bug. */ @@ -586,16 +610,14 @@ adjust_cciss_scsi_table(int ctlr, int hostno, } if (!found) { changes++; - if (cciss_scsi_add_entry(ctlr, hostno, - - &sd[i].scsi3addr[0], sd[i].devtype, + if (cciss_scsi_add_entry(ctlr, hostno, &sd[i], added, &nadded) != 0) break; } else if (found == 1) { /* should never happen... */ changes++; - printk("cciss%d: device unexpectedly changed type\n", - ctlr); + printk(KERN_WARNING "cciss%d: device " + "unexpectedly changed\n", ctlr); /* but if it does happen, we just ignore that device */ } } @@ -1012,7 +1034,8 @@ cciss_scsi_interpret_error(CommandList_struct *cp) static int cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, - unsigned char *buf, unsigned char bufsize) + unsigned char page, unsigned char *buf, + unsigned char bufsize) { int rc; CommandList_struct *cp; @@ -1032,8 +1055,8 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, ei = cp->err_info; cdb[0] = CISS_INQUIRY; - cdb[1] = 0; - cdb[2] = 0; + cdb[1] = (page != 0); + cdb[2] = page; cdb[3] = 0; cdb[4] = bufsize; cdb[5] = 0; @@ -1053,6 +1076,25 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, return rc; } +/* Get the device id from inquiry page 0x83 */ +static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr, + unsigned char *device_id, int buflen) +{ + int rc; + unsigned char *buf; + + if (buflen > 16) + buflen = 16; + buf = kzalloc(64, GFP_KERNEL); + if (!buf) + return -1; + rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64); + if (rc == 0) + memcpy(device_id, &buf[8], buflen); + kfree(buf); + return rc != 0; +} + static int cciss_scsi_do_report_phys_luns(ctlr_info_t *c, ReportLunData_struct *buf, int bufsize) @@ -1142,25 +1184,21 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) ctlr_info_t *c; __u32 num_luns=0; unsigned char *ch; - /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ - struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; + struct cciss_scsi_dev_t *currentsd, *this_device; int ncurrent=0; int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; int i; c = (ctlr_info_t *) hba[cntl_num]; ld_buff = kzalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; + currentsd = kzalloc(sizeof(*currentsd) * + (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL); + if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + goto out; } - + this_device = ¤tsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { ch = &ld_buff->LUNListLength[0]; num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; @@ -1179,23 +1217,34 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) /* adjust our table of devices */ - for(i=0; iLUN[i][3] & 0xC0) continue; memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); - if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, - (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { + if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff, + (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) /* Inquiry failed (msg printed already) */ - devtype = 0; /* so we will skip this device. */ - } else /* what kind of device is this? */ - devtype = (inq_buff[0] & 0x1f); - - switch (devtype) + continue; /* so we will skip this device. */ + + this_device->devtype = (inq_buff[0] & 0x1f); + this_device->bus = -1; + this_device->target = -1; + this_device->lun = -1; + memcpy(this_device->scsi3addr, scsi3addr, 8); + memcpy(this_device->vendor, &inq_buff[8], + sizeof(this_device->vendor)); + memcpy(this_device->model, &inq_buff[16], + sizeof(this_device->model)); + memcpy(this_device->revision, &inq_buff[32], + sizeof(this_device->revision)); + memset(this_device->device_id, 0, + sizeof(this_device->device_id)); + cciss_scsi_get_device_id(hba[cntl_num], scsi3addr, + this_device->device_id, sizeof(this_device->device_id)); + + switch (this_device->devtype) { case 0x05: /* CD-ROM */ { @@ -1220,15 +1269,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { printk(KERN_INFO "cciss%d: %s ignored, " "too many devices.\n", cntl_num, - scsi_device_type(devtype)); + scsi_device_type(this_device->devtype)); break; } - memcpy(¤tsd[ncurrent].scsi3addr[0], - &scsi3addr[0], 8); - currentsd[ncurrent].devtype = devtype; - currentsd[ncurrent].bus = -1; - currentsd[ncurrent].target = -1; - currentsd[ncurrent].lun = -1; + currentsd[ncurrent] = *this_device; ncurrent++; break; default: @@ -1240,6 +1284,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) out: kfree(inq_buff); kfree(ld_buff); + kfree(currentsd); return; } diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h index d9c2c586502..7b750245ae7 100644 --- a/drivers/block/cciss_scsi.h +++ b/drivers/block/cciss_scsi.h @@ -66,6 +66,10 @@ struct cciss_scsi_dev_t { int devtype; int bus, target, lun; /* as presented to the OS */ unsigned char scsi3addr[8]; /* as presented to the HW */ + unsigned char device_id[16]; /* from inquiry pg. 0x83 */ + unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ + unsigned char model[16]; /* bytes 16-31 of inquiry data */ + unsigned char revision[4]; /* bytes 32-35 of inquiry data */ }; struct cciss_scsi_hba_t { -- GitLab From 061837bc8687edc2739ef02f721b7ae0b8076390 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Sep 2008 14:57:16 -0700 Subject: [PATCH 3486/5416] drivers/block: Use DIV_ROUND_UP The kernel.h macro DIV_ROUND_UP performs the computation (((n) + (d) - 1) / (d)) but is perhaps more readable. An extract of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ #include @depends on haskernel@ expression n,d; @@ ( - (n + d - 1) / d + DIV_ROUND_UP(n,d) | - (n + (d - 1)) / d + DIV_ROUND_UP(n,d) ) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP((n),d) + DIV_ROUND_UP(n,d) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP(n,(d)) + DIV_ROUND_UP(n,d) // Signed-off-by: Julia Lawall Cc: Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 8 ++++---- drivers/block/cpqarray.c | 2 +- drivers/block/floppy.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b73116ef923..1e1f9153000 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3460,8 +3460,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not"); hba[i]->cmd_pool_bits = - kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG - - 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL); + kmalloc(DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG) + * sizeof(unsigned long), GFP_KERNEL); hba[i]->cmd_pool = (CommandList_struct *) pci_alloc_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct), @@ -3493,8 +3493,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* command and error info recs zeroed out before they are used */ memset(hba[i]->cmd_pool_bits, 0, - ((hba[i]->nr_cmds + BITS_PER_LONG - - 1) / BITS_PER_LONG) * sizeof(unsigned long)); + DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG) + * sizeof(unsigned long)); hba[i]->num_luns = 0; hba[i]->highest_lun = -1; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 09c14341e6e..3d967525e9a 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -424,7 +424,7 @@ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), &(hba[i]->cmd_pool_dhandle)); hba[i]->cmd_pool_bits = kcalloc( - (NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG, sizeof(unsigned long), + DIV_ROUND_UP(NR_CMDS, BITS_PER_LONG), sizeof(unsigned long), GFP_KERNEL); if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 395f8ea7981..9c0b494f5e8 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1355,20 +1355,20 @@ static void fdc_specify(void) } /* Convert step rate from microseconds to milliseconds and 4 bits */ - srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR; + srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); if (slow_floppy) { srt = srt / 4; } SUPBOUND(srt, 0xf); INFBOUND(srt, 0); - hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR; + hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR); if (hlt < 0x01) hlt = 0x01; else if (hlt > 0x7f) hlt = hlt_max_code; - hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR; + hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR); if (hut < 0x1) hut = 0x1; else if (hut > 0xf) @@ -2385,7 +2385,7 @@ static void rw_interrupt(void) #ifdef FLOPPY_SANITY_CHECK if (nr_sectors / ssize > - (in_sector_offset + current_count_sectors + ssize - 1) / ssize) { + DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); -- GitLab From 9e49184c82e9ec3ab4d45f9ea5a17ccaf43869f0 Mon Sep 17 00:00:00 2001 From: Keith Wansbrough Date: Mon, 22 Sep 2008 14:57:17 -0700 Subject: [PATCH 3487/5416] floppy: support arbitrary first-sector numbers The current floppy_struct allows floppies to number sectors starting from 0 or 1. This patch allows arbitrary first-sector numbers - for example, 0xC1 for Amstrad CPC disks. This extends the existing 1-bit field (FD_ZEROBASED, bit 2 of stretch) to 8 bits (FD_SECTMASK, bits 2 to 9). Currently 0x00 denotes a first sector number of 1, and 0x01 denotes a first sector number of 0. We extend this by interpreting FD_SECTMASK as the first sector number with the LSB flipped. Signed-off-by: Keith Wansbrough Cc: Alain Knaff Cc: Michael Kerrisk Cc: Karel Zak Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 23 +++++++++++++++-------- include/linux/fd.h | 8 +++++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9c0b494f5e8..cf64ddf5d83 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -423,8 +423,15 @@ static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical * side 0 is on physical side 0 (but with the misnamed sector IDs). * 'stretch' should probably be renamed to something more general, like - * 'options'. Other parameters should be self-explanatory (see also - * setfdprm(8)). + * 'options'. + * + * Bits 2 through 9 of 'stretch' tell the number of the first sector. + * The LSB (bit 2) is flipped. For most disks, the first sector + * is 1 (represented by 0x00<<2). For some CP/M and music sampler + * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2). + * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2). + * + * Other parameters should be self-explanatory (see also setfdprm(8)). */ /* Size @@ -2236,9 +2243,9 @@ static void setup_format_params(int track) } } } - if (_floppy->stretch & FD_ZEROBASED) { + if (_floppy->stretch & FD_SECTBASEMASK) { for (count = 0; count < F_SECT_PER_TRACK; count++) - here[count].sect--; + here[count].sect += FD_SECTBASE(_floppy) - 1; } } @@ -2649,7 +2656,7 @@ static int make_raw_rw_request(void) } HEAD = fsector_t / _floppy->sect; - if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) || + if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect) max_sector = _floppy->sect; @@ -2679,7 +2686,7 @@ static int make_raw_rw_request(void) CODE2SIZE; SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + - ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1); + FD_SECTBASE(_floppy); /* tracksize describes the size which can be filled up with sectors * of size ssize. @@ -3311,7 +3318,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, g->head <= 0 || g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || /* check if reserved bits are set */ - (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0) + (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) return -EINVAL; if (type) { if (!capable(CAP_SYS_ADMIN)) @@ -3356,7 +3363,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack || ((user_params[drive].sect ^ oldStretch) & - (FD_SWAPSIDES | FD_ZEROBASED))) + (FD_SWAPSIDES | FD_SECTBASEMASK))) invalidate_drive(bdev); else process_fd_request(); diff --git a/include/linux/fd.h b/include/linux/fd.h index b6bd41d2b46..f5d194af07a 100644 --- a/include/linux/fd.h +++ b/include/linux/fd.h @@ -15,10 +15,16 @@ struct floppy_struct { sect, /* sectors per track */ head, /* nr of heads */ track, /* nr of tracks */ - stretch; /* !=0 means double track steps */ + stretch; /* bit 0 !=0 means double track steps */ + /* bit 1 != 0 means swap sides */ + /* bits 2..9 give the first sector */ + /* number (the LSB is flipped) */ #define FD_STRETCH 1 #define FD_SWAPSIDES 2 #define FD_ZEROBASED 4 +#define FD_SECTBASEMASK 0x3FC +#define FD_MKSECTBASE(s) (((s) ^ 1) << 2) +#define FD_SECTBASE(floppy) ((((floppy)->stretch & FD_SECTBASEMASK) >> 2) ^ 1) unsigned char gap, /* gap1 size */ -- GitLab From a68bbddba486020c9c74825ce90c4c1ec463e0e8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Sep 2008 13:03:33 +0200 Subject: [PATCH 3488/5416] block: add queue flag for SSD/non-rotational devices We don't want to idle in AS/CFQ if the device doesn't have a seek penalty. So add a QUEUE_FLAG_NONROT to indicate a non-rotational device, low level drivers should set this flag upon discovery of an SSD or similar device type. Signed-off-by: Jens Axboe --- block/as-iosched.c | 6 ++++++ block/cfq-iosched.c | 6 ++++++ include/linux/blkdev.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/block/as-iosched.c b/block/as-iosched.c index 80af9257e64..4c6fafbba93 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -745,6 +745,12 @@ static int as_can_break_anticipation(struct as_data *ad, struct request *rq) */ static int as_can_anticipate(struct as_data *ad, struct request *rq) { + /* + * SSD device without seek penalty, disable idling + */ + if (blk_queue_nonrot(ad->q)) + return 0; + if (!ad->io_context) /* * Last request submitted was a write diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 494b6fdcb18..03a5953bb5d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -878,6 +878,12 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) struct cfq_io_context *cic; unsigned long sl; + /* + * SSD device without seek penalty, disable idling + */ + if (blk_queue_nonrot(cfqd->queue)) + return; + WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list)); WARN_ON(cfq_cfqq_slice_new(cfqq)); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 86f77ef127f..0cf3e619fb2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -442,6 +442,7 @@ struct request_queue #define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ #define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ #define QUEUE_FLAG_STACKABLE 13 /* supports request stacking */ +#define QUEUE_FLAG_NONROT 14 /* non-rotational device (SSD) */ static inline int queue_is_locked(struct request_queue *q) { @@ -547,6 +548,7 @@ enum { #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags) +#define blk_queue_nonrot(q) test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags) #define blk_queue_flushing(q) ((q)->ordseq) #define blk_queue_stackable(q) \ test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) -- GitLab From 8bff7c6b0f63c7ee9c5e3a076338d74125b8debb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Sep 2008 13:05:10 +0200 Subject: [PATCH 3489/5416] libata: set queue SSD flag for SSD devices SSD devices should give an RPM setting of 1 in word 217 of the ID page. If we see such a device, tell the block layer about it. Signed-off-by: Jens Axboe --- drivers/ata/libata-scsi.c | 4 ++++ include/linux/ata.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b9d3ba423cb..054370700ab 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -977,6 +977,10 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { + if (ata_id_is_ssd(dev->id)) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, + sdev->request_queue); + /* ATA devices must be sector aligned */ blk_queue_update_dma_alignment(sdev->request_queue, ATA_SECT_SIZE - 1); diff --git a/include/linux/ata.h b/include/linux/ata.h index 8a12d718c16..c1c8b4a4ba2 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -88,6 +88,7 @@ enum { ATA_ID_DLF = 128, ATA_ID_CSFO = 129, ATA_ID_CFA_POWER = 160, + ATA_ID_ROT_SPEED = 217, ATA_ID_PIO4 = (1 << 1), ATA_ID_SERNO_LEN = 20, @@ -691,6 +692,11 @@ static inline int ata_id_is_cfa(const u16 *id) return 0; } +static inline int ata_id_is_ssd(const u16 *id) +{ + return id[ATA_ID_ROT_SPEED] == 0x01; +} + static inline int ata_drive_40wire(const u16 *dev_id) { if (ata_id_is_sata(dev_id)) -- GitLab From f7d7b7a7a3db6526a84ea755c1c54a051e9a52de Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 25 Sep 2008 11:37:50 +0200 Subject: [PATCH 3490/5416] block: as/cfq ssd idle check update We really need to know about the hardware tagging support as well, since if the SSD does not do tagging then we still want to idle. Otherwise have the same dependent sync IO vs flooding async IO problem as on rotational media. Signed-off-by: Jens Axboe --- block/as-iosched.c | 4 +++- block/cfq-iosched.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index 4c6fafbba93..71f0abb219e 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -745,11 +745,13 @@ static int as_can_break_anticipation(struct as_data *ad, struct request *rq) */ static int as_can_anticipate(struct as_data *ad, struct request *rq) { +#if 0 /* disable for now, we need to check tag level as well */ /* * SSD device without seek penalty, disable idling */ - if (blk_queue_nonrot(ad->q)) + if (blk_queue_nonrot(ad->q)) axman return 0; +#endif if (!ad->io_context) /* diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 03a5953bb5d..6a062eebbd1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -879,9 +879,11 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) unsigned long sl; /* - * SSD device without seek penalty, disable idling + * SSD device without seek penalty, disable idling. But only do so + * for devices that support queuing, otherwise we still have a problem + * with sync vs async workloads. */ - if (blk_queue_nonrot(cfqd->queue)) + if (blk_queue_nonrot(cfqd->queue) && cfqd->hw_tag) return; WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list)); -- GitLab From e3ba9ae58a5599226e3976b29c8093041ae7c332 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 25 Sep 2008 11:42:41 +0200 Subject: [PATCH 3491/5416] block: reserve some tags just for sync IO By only allowing async IO to consume 3/4 ths of the tag depth, we always have slots free to serve sync IO. This is important to avoid having writes fill the entire tag queue, thus starving reads. Original patch and idea from Linus Torvalds Signed-off-by: Jens Axboe --- block/blk-tag.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/block/blk-tag.c b/block/blk-tag.c index 8a99688eb1b..c0d419e84ce 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -337,6 +337,7 @@ EXPORT_SYMBOL(blk_queue_end_tag); int blk_queue_start_tag(struct request_queue *q, struct request *rq) { struct blk_queue_tag *bqt = q->queue_tags; + unsigned max_depth, offset; int tag; if (unlikely((rq->cmd_flags & REQ_QUEUED))) { @@ -350,10 +351,19 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) /* * Protect against shared tag maps, as we may not have exclusive * access to the tag map. + * + * We reserve a few tags just for sync IO, since we don't want + * to starve sync IO on behalf of flooding async IO. */ + max_depth = bqt->max_depth; + if (rq_is_sync(rq)) + offset = 0; + else + offset = max_depth >> 2; + do { - tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); - if (tag >= bqt->max_depth) + tag = find_next_zero_bit(bqt->tag_map, max_depth, offset); + if (tag >= max_depth) return 1; } while (test_and_set_bit_lock(tag, bqt->tag_map)); -- GitLab From c0ddffa84a7d12da9943a94d04dadbfb1883b904 Mon Sep 17 00:00:00 2001 From: Sven Schuetz Date: Fri, 26 Sep 2008 10:58:02 +0200 Subject: [PATCH 3492/5416] include blktrace_api.h in headers_install This header file is of interest for user space programming, i.e. for tools that process blktrace data. We would like to use it for a tool on-top of blktrace which processes data provided by blktrace. For this purpose, it would be helpful if the blktrace API would make it to /usr/include/linux. The git tree for the blktrace tools comes with its own copy of this header file. I didn't manage to replace that copy with the file generated by the patch below yet. A few more cleanups would be needed. For example, the blktrace ioctl numbers, which are currently defined in usr/include/fs.h, might need to be moved. Should be feasible, though. Signed-off-by: Sven Schuetz Signed-off-by: Martin Peschke Signed-off-by: Jens Axboe --- include/linux/Kbuild | 1 + include/linux/blktrace_api.h | 58 ++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b68ec09399b..31474e89c59 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -180,6 +180,7 @@ unifdef-y += audit.h unifdef-y += auto_fs.h unifdef-y += auxvec.h unifdef-y += binfmts.h +unifdef-y += blktrace_api.h unifdef-y += capability.h unifdef-y += capi.h unifdef-y += cciss_ioctl.h diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index dcaf2452ed1..a2a7d0ca275 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -1,8 +1,10 @@ #ifndef BLKTRACE_H #define BLKTRACE_H +#ifdef __KERNEL__ #include #include +#endif /* * Trace categories @@ -92,17 +94,17 @@ enum blktrace_notify { * The trace itself */ struct blk_io_trace { - u32 magic; /* MAGIC << 8 | version */ - u32 sequence; /* event number */ - u64 time; /* in microseconds */ - u64 sector; /* disk offset */ - u32 bytes; /* transfer length */ - u32 action; /* what happened */ - u32 pid; /* who did it */ - u32 device; /* device number */ - u32 cpu; /* on what cpu did it happen */ - u16 error; /* completion error */ - u16 pdu_len; /* length of data after this trace */ + __u32 magic; /* MAGIC << 8 | version */ + __u32 sequence; /* event number */ + __u64 time; /* in microseconds */ + __u64 sector; /* disk offset */ + __u32 bytes; /* transfer length */ + __u32 action; /* what happened */ + __u32 pid; /* who did it */ + __u32 device; /* device number */ + __u32 cpu; /* on what cpu did it happen */ + __u16 error; /* completion error */ + __u16 pdu_len; /* length of data after this trace */ }; /* @@ -120,6 +122,25 @@ enum { Blktrace_stopped, }; +/* + * User setup structure passed with BLKTRACESTART + */ +struct blk_user_trace_setup { +#ifdef __KERNEL__ + char name[BDEVNAME_SIZE]; /* output */ +#else + char name[32]; /* output */ +#endif + __u16 act_mask; /* input */ + __u32 buf_size; /* input */ + __u32 buf_nr; /* input */ + __u64 start_lba; + __u64 end_lba; + __u32 pid; +}; + +#ifdef __KERNEL__ +#if defined(CONFIG_BLK_DEV_IO_TRACE) struct blk_trace { int trace_state; struct rchan *rchan; @@ -136,21 +157,6 @@ struct blk_trace { atomic_t dropped; }; -/* - * User setup structure passed with BLKTRACESTART - */ -struct blk_user_trace_setup { - char name[BDEVNAME_SIZE]; /* output */ - u16 act_mask; /* input */ - u32 buf_size; /* input */ - u32 buf_nr; /* input */ - u64 start_lba; - u64 end_lba; - u32 pid; -}; - -#ifdef __KERNEL__ -#if defined(CONFIG_BLK_DEV_IO_TRACE) extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); extern void blk_trace_shutdown(struct request_queue *); extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); -- GitLab From 336c3d8ce771608815b65bcfa27a17a83b297328 Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Wed, 1 Oct 2008 16:02:33 +0200 Subject: [PATCH 3493/5416] block: Fix blk_start_queueing() to not kick a stopped queue blk_start_queueing() should act like the generic queue unplugging and kicking and ignore a stopped queue. Such a queue may not be run until after a call to blk_start_queue(). Signed-off-by: Elias Oltmanns Signed-off-by: Jens Axboe --- block/blk-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index fa212348c4c..c66333d8e48 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -890,9 +890,11 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_start_queueing(struct request_queue *q) { - if (!blk_queue_plugged(q)) + if (!blk_queue_plugged(q)) { + if (unlikely(blk_queue_stopped(q))) + return; q->request_fn(q); - else + } else __generic_unplug_device(q); } EXPORT_SYMBOL(blk_start_queueing); -- GitLab From ef9e3facdf1fe1228721a7c295a76d1b7a0e57ec Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 16:12:15 +0200 Subject: [PATCH 3494/5416] block: add lld busy state exporting interface This patch adds an new interface, blk_lld_busy(), to check lld's busy state from the block layer. blk_lld_busy() calls down into low-level drivers for the checking if the drivers set q->lld_busy_fn() using blk_queue_lld_busy(). This resolves a performance problem on request stacking devices below. Some drivers like scsi mid layer stop dispatching request when they detect busy state on its low-level device like host/target/device. It allows other requests to stay in the I/O scheduler's queue for a chance of merging. Request stacking drivers like request-based dm should follow the same logic. However, there is no generic interface for the stacked device to check if the underlying device(s) are busy. If the request stacking driver dispatches and submits requests to the busy underlying device, the requests will stay in the underlying device's queue without a chance of merging. This causes performance problem on burst I/O load. With this patch, busy state of the underlying device is exported via q->lld_busy_fn(). So the request stacking driver can check it and stop dispatching requests if busy. The underlying device driver must return the busy state appropriately: 1: when the device driver can't process requests immediately. 0: when the device driver can process requests immediately, including abnormal situations where the device driver needs to kill all requests. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Cc: Andrew Morton Signed-off-by: Jens Axboe --- block/blk-core.c | 28 ++++++++++++++++++++++++++++ block/blk-settings.c | 6 ++++++ include/linux/blkdev.h | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index c66333d8e48..b2d0ac8b760 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2100,6 +2100,34 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->rq_disk = bio->bi_bdev->bd_disk; } +/** + * blk_lld_busy - Check if underlying low-level drivers of a device are busy + * @q : the queue of the device being checked + * + * Description: + * Check if underlying low-level drivers of a device are busy. + * If the drivers want to export their busy state, they must set own + * exporting function using blk_queue_lld_busy() first. + * + * Basically, this function is used only by request stacking drivers + * to stop dispatching requests to underlying devices when underlying + * devices are busy. This behavior helps more I/O merging on the queue + * of the request stacking driver and prevents I/O throughput regression + * on burst I/O load. + * + * Return: + * 0 - Not busy (The request stacking driver should dispatch request) + * 1 - Busy (The request stacking driver should stop dispatching request) + */ +int blk_lld_busy(struct request_queue *q) +{ + if (q->lld_busy_fn) + return q->lld_busy_fn(q); + + return 0; +} +EXPORT_SYMBOL_GPL(blk_lld_busy); + int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) { return queue_work(kblockd_workqueue, work); diff --git a/block/blk-settings.c b/block/blk-settings.c index 1d0330d0b40..b21dcdb6415 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -89,6 +89,12 @@ void blk_queue_rq_timed_out(struct request_queue *q, rq_timed_out_fn *fn) } EXPORT_SYMBOL_GPL(blk_queue_rq_timed_out); +void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn) +{ + q->lld_busy_fn = fn; +} +EXPORT_SYMBOL_GPL(blk_queue_lld_busy); + /** * blk_queue_make_request - define an alternate make_request function for a device * @q: the request queue for the device to be affected diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0cf3e619fb2..9e0ee1a8254 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -269,6 +269,7 @@ typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *, typedef void (prepare_flush_fn) (struct request_queue *, struct request *); typedef void (softirq_done_fn)(struct request *); typedef int (dma_drain_needed_fn)(struct request *); +typedef int (lld_busy_fn) (struct request_queue *q); enum blk_eh_timer_return { BLK_EH_NOT_HANDLED, @@ -325,6 +326,7 @@ struct request_queue softirq_done_fn *softirq_done_fn; rq_timed_out_fn *rq_timed_out_fn; dma_drain_needed_fn *dma_drain_needed; + lld_busy_fn *lld_busy_fn; /* * Dispatch queue sorting @@ -699,6 +701,7 @@ extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern void blk_insert_request(struct request_queue *, struct request *, int, void *); extern void blk_requeue_request(struct request_queue *, struct request *); extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); +extern int blk_lld_busy(struct request_queue *q); extern int blk_insert_cloned_request(struct request_queue *q, struct request *rq); extern void blk_plug_device(struct request_queue *); @@ -835,6 +838,7 @@ extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int); extern int blk_queue_dma_drain(struct request_queue *q, dma_drain_needed_fn *dma_drain_needed, void *buf, unsigned int size); +extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn); extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); -- GitLab From 0497b345e7d067109e0dd9bf9f4978a6847ee13b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 1 Oct 2008 16:16:25 +0200 Subject: [PATCH 3495/5416] blktrace: use BLKTRACE_BDEV_SIZE as the name size for setup structure Define as 32, which is is what BDEVNAME_SIZE is/was as well. This keeps the user interface the same and gets rid of the difference between kernel and user api here. Signed-off-by: Jens Axboe --- block/blktrace.c | 3 ++- include/linux/blktrace_api.h | 8 +++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/block/blktrace.c b/block/blktrace.c index 9e0212c90b2..85049a7e7a1 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -369,7 +369,8 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, if (!buts->buf_size || !buts->buf_nr) return -EINVAL; - strcpy(buts->name, name); + strncpy(buts->name, name, BLKTRACE_BDEV_SIZE); + buts->name[BLKTRACE_BDEV_SIZE - 1] = '\0'; /* * some device names have larger paths - convert the slashes diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index a2a7d0ca275..3a31eb50616 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -122,15 +122,13 @@ enum { Blktrace_stopped, }; +#define BLKTRACE_BDEV_SIZE 32 + /* * User setup structure passed with BLKTRACESTART */ struct blk_user_trace_setup { -#ifdef __KERNEL__ - char name[BDEVNAME_SIZE]; /* output */ -#else - char name[32]; /* output */ -#endif + char name[BLKTRACE_BDEV_SIZE]; /* output */ __u16 act_mask; /* input */ __u32 buf_size; /* input */ __u32 buf_nr; /* input */ -- GitLab From 8316982ac06d7d8875dc8738efbb030791dc33bb Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 10:11:20 -0400 Subject: [PATCH 3496/5416] virtio_blk: change to use __blk_end_request() This patch converts virtio_blk to use __blk_end_request() directly so that end_{queued|dequeued}_request() can be removed. Related 'uptodate' argument is converted to 'error'. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Cc: Rusty Russell Signed-off-by: Jens Axboe --- drivers/block/virtio_blk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 879506a2c23..6ec5fc05278 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -47,20 +47,20 @@ static void blk_done(struct virtqueue *vq) spin_lock_irqsave(&vblk->lock, flags); while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { - int uptodate; + int error; switch (vbr->status) { case VIRTIO_BLK_S_OK: - uptodate = 1; + error = 0; break; case VIRTIO_BLK_S_UNSUPP: - uptodate = -ENOTTY; + error = -ENOTTY; break; default: - uptodate = 0; + error = -EIO; break; } - end_dequeued_request(vbr->req, uptodate); + __blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req)); list_del(&vbr->list); mempool_free(vbr, vblk->pool); } -- GitLab From 2a9df5055a99df25533daf4041fdb99f0ed3463c Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 10:12:15 -0400 Subject: [PATCH 3497/5416] memstick: change to use __blk_end_request() This patch converts memstick to use __blk_end_request() directly so that end_{queued|dequeued}_request() can be removed. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Cc: Alex Dubov Signed-off-by: Jens Axboe --- drivers/memstick/core/mspro_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 82bf649ef13..6e291bf8237 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -828,7 +828,7 @@ static void mspro_block_submit_req(struct request_queue *q) if (msb->eject) { while ((req = elv_next_request(q)) != NULL) - end_queued_request(req, -ENODEV); + __blk_end_request(req, -ENODEV, blk_rq_bytes(req)); return; } -- GitLab From 7afb3a6e752503d5ebeb038336aa0fa886a51b44 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 10:13:02 -0400 Subject: [PATCH 3498/5416] gdrom: change to use __blk_end_request() This patch converts gdrom to use __blk_end_request() directly so that end_{queued|dequeued}_request() can be removed. gd.transfer is '1' in error cases and '0' in non-error cases, so gdrom hasn't been propagating any error code to the block layer. We can just convert error cases to '-EIO'. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Cc: Adrian McMenamin Signed-off-by: Jens Axboe --- drivers/cdrom/gdrom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 1231d95aa69..d6ba77a2dd7 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -624,14 +624,14 @@ static void gdrom_readdisk_dma(struct work_struct *work) ctrl_outb(1, GDROM_DMA_STATUS_REG); wait_event_interruptible_timeout(request_queue, gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); - err = gd.transfer; + err = gd.transfer ? -EIO : 0; gd.transfer = 0; gd.pending = 0; /* now seek to take the request spinlock * before handling ending the request */ spin_lock(&gdrom_lock); list_del_init(&req->queuelist); - end_dequeued_request(req, 1 - err); + __blk_end_request(req, err, blk_rq_bytes(req)); } spin_unlock(&gdrom_lock); kfree(read_command); -- GitLab From 99cd3386f290eaf61f2b7596d5a4cc2007771174 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 10:13:44 -0400 Subject: [PATCH 3499/5416] block: change elevator to use __blk_end_request() This patch converts elevator to use __blk_end_request() directly so that end_{queued|dequeued}_request() can be removed. Related 'uptodate' arguments is converted to 'error'. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/elevator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 8a74eedc353..04518921db3 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -754,7 +754,7 @@ struct request *elv_next_request(struct request_queue *q) * not ever see it. */ if (blk_empty_barrier(rq)) { - end_queued_request(rq, 1); + __blk_end_request(rq, 0, blk_rq_bytes(rq)); continue; } if (!(rq->cmd_flags & REQ_STARTED)) { @@ -825,7 +825,7 @@ struct request *elv_next_request(struct request_queue *q) break; } else if (ret == BLKPREP_KILL) { rq->cmd_flags |= REQ_QUIET; - end_queued_request(rq, 0); + __blk_end_request(rq, -EIO, blk_rq_bytes(rq)); } else { printk(KERN_ERR "%s: bad return=%d\n", __func__, ret); break; @@ -922,7 +922,7 @@ void elv_abort_queue(struct request_queue *q) rq = list_entry_rq(q->queue_head.next); rq->cmd_flags |= REQ_QUIET; blk_add_trace_rq(q, rq, BLK_TA_ABORT); - end_queued_request(rq, 0); + __blk_end_request(rq, -EIO, blk_rq_bytes(rq)); } } EXPORT_SYMBOL(elv_abort_queue); -- GitLab From d00e29fd99dd63d1c51917604e35dee824ed567f Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Wed, 1 Oct 2008 10:14:46 -0400 Subject: [PATCH 3500/5416] block: remove end_{queued|dequeued}_request() This patch removes end_queued_request() and end_dequeued_request(), which are no longer used. As a results, users of __end_request() became only end_request(). So the actual code in __end_request() is moved to end_request() and __end_request() is removed. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Jens Axboe --- block/blk-core.c | 58 +++++------------------------------------- include/linux/blkdev.h | 2 -- 2 files changed, 7 insertions(+), 53 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index b2d0ac8b760..2d053b58441 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1790,17 +1790,6 @@ static void end_that_request_last(struct request *req, int error) } } -static inline void __end_request(struct request *rq, int uptodate, - unsigned int nr_bytes) -{ - int error = 0; - - if (uptodate <= 0) - error = uptodate ? uptodate : -EIO; - - __blk_end_request(rq, error, nr_bytes); -} - /** * blk_rq_bytes - Returns bytes left to complete in the entire request * @rq: the request being processed @@ -1830,41 +1819,6 @@ unsigned int blk_rq_cur_bytes(struct request *rq) } EXPORT_SYMBOL_GPL(blk_rq_cur_bytes); -/** - * end_queued_request - end all I/O on a queued request - * @rq: the request being processed - * @uptodate: error value or %0/%1 uptodate flag - * - * Description: - * Ends all I/O on a request, and removes it from the block layer queues. - * Not suitable for normal I/O completion, unless the driver still has - * the request attached to the block layer. - * - **/ -void end_queued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, blk_rq_bytes(rq)); -} -EXPORT_SYMBOL(end_queued_request); - -/** - * end_dequeued_request - end all I/O on a dequeued request - * @rq: the request being processed - * @uptodate: error value or %0/%1 uptodate flag - * - * Description: - * Ends all I/O on a request. The request must already have been - * dequeued using blkdev_dequeue_request(), as is normally the case - * for most drivers. - * - **/ -void end_dequeued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, blk_rq_bytes(rq)); -} -EXPORT_SYMBOL(end_dequeued_request); - - /** * end_request - end I/O on the current segment of the request * @req: the request being processed @@ -1879,14 +1833,16 @@ EXPORT_SYMBOL(end_dequeued_request); * they have a residual value to account for. For that case this function * isn't really useful, unless the residual just happens to be the * full current segment. In other words, don't use this function in new - * code. Use blk_end_request() or __blk_end_request() to end partial parts - * of a request, or end_dequeued_request() and end_queued_request() to - * completely end IO on a dequeued/queued request. - * + * code. Use blk_end_request() or __blk_end_request() to end a request. **/ void end_request(struct request *req, int uptodate) { - __end_request(req, uptodate, req->hard_cur_sectors << 9); + int error = 0; + + if (uptodate <= 0) + error = uptodate ? uptodate : -EIO; + + __blk_end_request(req, error, req->hard_cur_sectors << 9); } EXPORT_SYMBOL(end_request); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9e0ee1a8254..bfc18e497c7 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -793,8 +793,6 @@ extern int __blk_end_request(struct request *rq, int error, extern int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes); extern void end_request(struct request *, int); -extern void end_queued_request(struct request *, int); -extern void end_dequeued_request(struct request *, int); extern int blk_end_request_callback(struct request *rq, int error, unsigned int nr_bytes, int (drv_callback)(struct request *)); -- GitLab From 8deaf7210728c453295dc1cb2a5b66c68183ac85 Mon Sep 17 00:00:00 2001 From: Alberto Bertogli Date: Thu, 2 Oct 2008 12:46:53 +0200 Subject: [PATCH 3501/5416] bio.h: Remove unused conditional code The whole bio_integrity() definition is inside an #ifdef CONFIG_BLK_DEV_INTEGRITY, there's no need for the conditional code. Signed-off-by: Alberto Bertogli Signed-off-by: Jens Axboe --- include/linux/bio.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/include/linux/bio.h b/include/linux/bio.h index 6520ee1a3f6..98c2d057065 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -457,14 +457,7 @@ static inline int bio_has_data(struct bio *bio) #define bip_for_each_vec(bvl, bip, i) \ __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx) -static inline int bio_integrity(struct bio *bio) -{ -#if defined(CONFIG_BLK_DEV_INTEGRITY) - return bio->bi_integrity != NULL; -#else - return 0; -#endif -} +#define bio_integrity(bio) (bio->bi_integrity != NULL) extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); -- GitLab From b04accc425d52ca59699290661e0dfd09b0feeeb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 2 Oct 2008 12:53:22 +0200 Subject: [PATCH 3502/5416] block: revert part of d7533ad0e132f92e75c1b2eb7c26387b25a583c1 We need bdev_get_integrity() to support the pending md/dm patches. Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 5 ----- include/linux/blkdev.h | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index ba4ada08564..6e28dcdd23a 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -150,11 +150,6 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, } EXPORT_SYMBOL(bio_integrity_add_page); -static struct blk_integrity *bdev_get_integrity(struct block_device *bdev) -{ - return bdev->bd_disk->integrity; -} - static int bdev_integrity_enabled(struct block_device *bdev, int rw) { struct blk_integrity *bi = bdev_get_integrity(bdev); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bfc18e497c7..bc693f5c388 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1016,6 +1016,12 @@ extern int blk_integrity_compare(struct block_device *, struct block_device *); extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); extern int blk_rq_count_integrity_sg(struct request *); +static inline +struct blk_integrity *bdev_get_integrity(struct block_device *bdev) +{ + return bdev->bd_disk->integrity; +} + static inline int blk_integrity_rq(struct request *rq) { if (rq->bio == NULL) @@ -1029,6 +1035,7 @@ static inline int blk_integrity_rq(struct request *rq) #define blk_integrity_rq(rq) (0) #define blk_rq_count_integrity_sg(a) (0) #define blk_rq_map_integrity_sg(a, b) (0) +#define bdev_get_integrity(a) (0) #define blk_integrity_compare(a, b) (0) #define blk_integrity_register(a, b) (0) #define blk_integrity_unregister(a) do { } while (0); -- GitLab From 74aa8c2cc010035a7eef2b4ca4d6430e0dae206a Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 1 Oct 2008 03:38:37 -0400 Subject: [PATCH 3503/5416] block: Introduce integrity data ownership flag A filesystem might supply its own integrity metadata. Introduce a flag that indicates whether the filesystem or the block layer owns the integrity buffer. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 3 ++- include/linux/bio.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 6e28dcdd23a..19caf7c962a 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -107,7 +107,8 @@ void bio_integrity_free(struct bio *bio, struct bio_set *bs) BUG_ON(bip == NULL); /* A cloned bio doesn't own the integrity metadata */ - if (!bio_flagged(bio, BIO_CLONED) && bip->bip_buf != NULL) + if (!bio_flagged(bio, BIO_CLONED) && !bio_flagged(bio, BIO_FS_INTEGRITY) + && bip->bip_buf != NULL) kfree(bip->bip_buf); mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]); diff --git a/include/linux/bio.h b/include/linux/bio.h index 98c2d057065..d86d39d490e 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -109,6 +109,7 @@ struct bio { #define BIO_EOPNOTSUPP 7 /* not supported */ #define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ #define BIO_NULL_MAPPED 9 /* contains invalid user pages */ +#define BIO_FS_INTEGRITY 10 /* fs owns integrity data, not block layer */ #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) /* -- GitLab From 0c032ab889e7b20b8a5a7d09313e4aca214a15f7 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 1 Oct 2008 03:38:38 -0400 Subject: [PATCH 3504/5416] block: Fix double put in blk_integrity_unregister - kobject_del already puts the parent. - Set integrity profile to NULL to prevent stale data. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- block/blk-integrity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 69023da6315..e3817a016a1 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -376,7 +376,7 @@ void blk_integrity_unregister(struct gendisk *disk) kobject_uevent(&bi->kobj, KOBJ_REMOVE); kobject_del(&bi->kobj); - kobject_put(&disk_to_dev(disk)->kobj); kmem_cache_free(integrity_cachep, bi); + disk->integrity = NULL; } EXPORT_SYMBOL(blk_integrity_unregister); -- GitLab From ad7fce93147d32ae53d25d9ea1a8ba31a239deee Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 1 Oct 2008 03:38:39 -0400 Subject: [PATCH 3505/5416] block: Switch blk_integrity_compare from bdev to gendisk The DM and MD integrity support now depends on being able to use gendisks instead of block_devices when comparing integrity profiles. Change function parameters accordingly. Also update comparison logic so that two NULL profiles are a valid configuration. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- block/blk-integrity.c | 28 ++++++++++++++-------------- include/linux/blkdev.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index e3817a016a1..61a8e2f8fdd 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -108,51 +108,51 @@ new_segment: EXPORT_SYMBOL(blk_rq_map_integrity_sg); /** - * blk_integrity_compare - Compare integrity profile of two block devices - * @bd1: Device to compare - * @bd2: Device to compare + * blk_integrity_compare - Compare integrity profile of two disks + * @gd1: Disk to compare + * @gd2: Disk to compare * * Description: Meta-devices like DM and MD need to verify that all * sub-devices use the same integrity format before advertising to * upper layers that they can send/receive integrity metadata. This - * function can be used to check whether two block devices have + * function can be used to check whether two gendisk devices have * compatible integrity formats. */ -int blk_integrity_compare(struct block_device *bd1, struct block_device *bd2) +int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) { - struct blk_integrity *b1 = bd1->bd_disk->integrity; - struct blk_integrity *b2 = bd2->bd_disk->integrity; + struct blk_integrity *b1 = gd1->integrity; + struct blk_integrity *b2 = gd2->integrity; - BUG_ON(bd1->bd_disk == NULL); - BUG_ON(bd2->bd_disk == NULL); + if (!b1 && !b2) + return 0; if (!b1 || !b2) - return 0; + return -1; if (b1->sector_size != b2->sector_size) { printk(KERN_ERR "%s: %s/%s sector sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->sector_size, b2->sector_size); return -1; } if (b1->tuple_size != b2->tuple_size) { printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->tuple_size, b2->tuple_size); return -1; } if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->tag_size, b2->tag_size); return -1; } if (strcmp(b1->name, b2->name)) { printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->name, b2->name); return -1; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bc693f5c388..00d340b0f75 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1012,7 +1012,7 @@ struct blk_integrity { extern int blk_integrity_register(struct gendisk *, struct blk_integrity *); extern void blk_integrity_unregister(struct gendisk *); -extern int blk_integrity_compare(struct block_device *, struct block_device *); +extern int blk_integrity_compare(struct gendisk *, struct gendisk *); extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); extern int blk_rq_count_integrity_sg(struct request *); -- GitLab From b02739b01c5309d74a59859f2ce92c931d1f1955 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 2 Oct 2008 18:47:49 +0200 Subject: [PATCH 3506/5416] block: gendisk integrity wrapper This is a wrapper for accessing a gendisk's integrity bits. It allows the integrity support in MD to be compiled with BLK_DEV_INTEGRITY off. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- include/linux/blkdev.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 00d340b0f75..a92d9e4ea96 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1022,6 +1022,11 @@ struct blk_integrity *bdev_get_integrity(struct block_device *bdev) return bdev->bd_disk->integrity; } +static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) +{ + return disk->integrity; +} + static inline int blk_integrity_rq(struct request *rq) { if (rq->bio == NULL) @@ -1036,6 +1041,7 @@ static inline int blk_integrity_rq(struct request *rq) #define blk_rq_count_integrity_sg(a) (0) #define blk_rq_map_integrity_sg(a, b) (0) #define bdev_get_integrity(a) (0) +#define blk_get_integrity(a) (0) #define blk_integrity_compare(a, b) (0) #define blk_integrity_register(a, b) (0) #define blk_integrity_unregister(a) do { } while (0); -- GitLab From ad3316bf4eeb53c89164f759767f911072b56203 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 1 Oct 2008 22:42:53 -0400 Subject: [PATCH 3507/5416] block: Find bio sector offset given idx and offset Helper function to find the sector offset in a bio given bvec index and page offset. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- fs/bio.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/bio.h | 1 + 2 files changed, 37 insertions(+) diff --git a/fs/bio.c b/fs/bio.c index e56e7685af9..a5af5809f56 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1300,6 +1300,42 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) return bp; } +/** + * bio_sector_offset - Find hardware sector offset in bio + * @bio: bio to inspect + * @index: bio_vec index + * @offset: offset in bv_page + * + * Return the number of hardware sectors between beginning of bio + * and an end point indicated by a bio_vec index and an offset + * within that vector's page. + */ +sector_t bio_sector_offset(struct bio *bio, unsigned short index, + unsigned int offset) +{ + unsigned int sector_sz = queue_hardsect_size(bio->bi_bdev->bd_disk->queue); + struct bio_vec *bv; + sector_t sectors; + int i; + + sectors = 0; + + if (index >= bio->bi_idx) + index = bio->bi_vcnt - 1; + + __bio_for_each_segment(bv, bio, i, 0) { + if (i == index) { + if (offset > bv->bv_offset) + sectors += (offset - bv->bv_offset) / sector_sz; + break; + } + + sectors += bv->bv_len / sector_sz; + } + + return sectors; +} +EXPORT_SYMBOL(bio_sector_offset); /* * create memory pools for biovec's in a bio_set. diff --git a/include/linux/bio.h b/include/linux/bio.h index d86d39d490e..fe12d0f9eba 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -327,6 +327,7 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, unsigned int, unsigned int); extern int bio_get_nr_vecs(struct block_device *); +extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int); extern struct bio *bio_map_user(struct request_queue *, struct block_device *, unsigned long, unsigned int, int, gfp_t); struct sg_iovec; -- GitLab From 6feef531f55cf4a20fd9eb39f5352e5745203603 Mon Sep 17 00:00:00 2001 From: Denis ChengRq Date: Thu, 9 Oct 2008 08:57:05 +0200 Subject: [PATCH 3508/5416] block: mark bio_split_pool static Since all bio_split calls refer the same single bio_split_pool, the bio_split function can use bio_split_pool directly instead of the mempool_t parameter; then the mempool_t parameter can be removed from bio_split param list, and bio_split_pool is only referred in fs/bio.c file, can be marked static. Signed-off-by: Denis ChengRq Signed-off-by: Jens Axboe --- drivers/block/pktcdvd.c | 2 +- drivers/md/linear.c | 2 +- drivers/md/raid0.c | 2 +- drivers/md/raid10.c | 2 +- fs/bio.c | 9 ++++----- include/linux/bio.h | 4 +--- 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index e1a90bbb474..0e077150568 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2544,7 +2544,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) if (last_zone != zone) { BUG_ON(last_zone != zone + pd->settings.size); first_sectors = last_zone - bio->bi_sector; - bp = bio_split(bio, bio_split_pool, first_sectors); + bp = bio_split(bio, first_sectors); BUG_ON(!bp); pkt_make_request(q, &bp->bio1); pkt_make_request(q, &bp->bio2); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index c80ea90593d..b9cbee688fa 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -353,7 +353,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) * split it. */ struct bio_pair *bp; - bp = bio_split(bio, bio_split_pool, + bp = bio_split(bio, ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector); if (linear_make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f52f442a735..53508a8a981 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -427,7 +427,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, bio_split_pool, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); + bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1))); if (raid0_make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); if (raid0_make_request(q, &bp->bio2)) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5f990133f5e..8bdc9bfc288 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -817,7 +817,7 @@ static int make_request(struct request_queue *q, struct bio * bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, bio_split_pool, + bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); if (make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); diff --git a/fs/bio.c b/fs/bio.c index a5af5809f56..77a55bcceed 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -30,7 +30,7 @@ static struct kmem_cache *bio_slab __read_mostly; -mempool_t *bio_split_pool __read_mostly; +static mempool_t *bio_split_pool __read_mostly; /* * if you change this list, also change bvec_alloc or things will @@ -1256,9 +1256,9 @@ static void bio_pair_end_2(struct bio *bi, int err) * split a bio - only worry about a bio with a single page * in it's iovec */ -struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) +struct bio_pair *bio_split(struct bio *bi, int first_sectors) { - struct bio_pair *bp = mempool_alloc(pool, GFP_NOIO); + struct bio_pair *bp = mempool_alloc(bio_split_pool, GFP_NOIO); if (!bp) return bp; @@ -1292,7 +1292,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) bp->bio2.bi_end_io = bio_pair_end_2; bp->bio1.bi_private = bi; - bp->bio2.bi_private = pool; + bp->bio2.bi_private = bio_split_pool; if (bio_integrity(bi)) bio_integrity_split(bi, bp, first_sectors); @@ -1455,7 +1455,6 @@ EXPORT_SYMBOL(bio_map_kern); EXPORT_SYMBOL(bio_copy_kern); EXPORT_SYMBOL(bio_pair_release); EXPORT_SYMBOL(bio_split); -EXPORT_SYMBOL(bio_split_pool); EXPORT_SYMBOL(bio_copy_user); EXPORT_SYMBOL(bio_uncopy_user); EXPORT_SYMBOL(bioset_create); diff --git a/include/linux/bio.h b/include/linux/bio.h index fe12d0f9eba..fb97221d7c3 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -300,9 +300,7 @@ struct bio_pair { atomic_t cnt; int error; }; -extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, - int first_sectors); -extern mempool_t *bio_split_pool; +extern struct bio_pair *bio_split(struct bio *bi, int first_sectors); extern void bio_pair_release(struct bio_pair *dbio); extern struct bio_set *bioset_create(int, int); -- GitLab From af5639424008ffe96f89b059bea1aec15e0115a9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 9 Oct 2008 09:01:10 +0200 Subject: [PATCH 3509/5416] block: add some comments around the bio read-write flags Signed-off-by: Jens Axboe --- include/linux/bio.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/linux/bio.h b/include/linux/bio.h index fb97221d7c3..ff5b4cf9e2d 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -123,13 +123,23 @@ struct bio { /* * bio bi_rw flags * - * bit 0 -- read (not set) or write (set) + * bit 0 -- data direction + * If not set, bio is a read from device. If set, it's a write to device. * bit 1 -- rw-ahead when set * bit 2 -- barrier + * Insert a serialization point in the IO queue, forcing previously + * submitted IO to be completed before this oen is issued. * bit 3 -- fail fast, don't want low level driver retries * bit 4 -- synchronous I/O hint: the block layer will unplug immediately + * Note that this does NOT indicate that the IO itself is sync, just + * that the block layer will not postpone issue of this IO by plugging. * bit 5 -- metadata request + * Used for tracing to differentiate metadata and data IO. May also + * get some preferential treatment in the IO scheduler * bit 6 -- discard sectors + * Informs the lower level device that this range of sectors is no longer + * used by the file system and may thus be freed by the device. Used + * for flash based storage. */ #define BIO_RW 0 /* Must match RW in req flags (blkdev.h) */ #define BIO_RW_AHEAD 1 /* Must match FAILFAST in req flags */ -- GitLab From dabaad5b90dec6909c984d95330f6f41c325f9a8 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:17:36 +0800 Subject: [PATCH 3510/5416] Blackfin arch: fix bug -- PTRACE_PEEKDATA does not seem to work which breaks umoven() in strace Don't add arbitrary offset when peeking at data Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 66 ++++++++++++++++------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index bf1a51d8e60..9ce80d05e2c 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -46,7 +46,6 @@ #include #include -#define MAX_SHARED_LIBS 3 #define TEXT_OFFSET 0 /* * does not yet catch signals sent when the child dies. @@ -192,14 +191,12 @@ void ptrace_disable(struct task_struct *child) long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; - int add = 0; unsigned long __user *datap = (unsigned long __user *)data; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKDATA: pr_debug("ptrace: PEEKDATA\n"); - add = MAX_SHARED_LIBS * 4; /* space between text and data */ /* fall through */ case PTRACE_PEEKTEXT: /* read word at location addr. */ { @@ -207,39 +204,38 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied; ret = -EIO; - pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add, - sizeof(data)); - if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0) + pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data)); + if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) break; pr_debug("ptrace: user address is valid\n"); #if L1_CODE_LENGTH != 0 - if (addr + add >= L1_CODE_START - && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { - safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_CODE_START + && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { + safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif #if L1_DATA_A_LENGTH != 0 - if (addr + add >= L1_DATA_A_START - && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_DATA_A_START + && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif #if L1_DATA_B_LENGTH != 0 - if (addr + add >= L1_DATA_B_START - && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= L1_DATA_B_START + && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else #endif - if (addr + add >= FIXED_CODE_START - && addr + add + sizeof(tmp) <= FIXED_CODE_END) { - memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); + if (addr >= FIXED_CODE_START + && addr + sizeof(tmp) <= FIXED_CODE_END) { + memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); } else - copied = access_process_vm(child, addr + add, &tmp, + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); if (copied != sizeof(tmp)) @@ -291,39 +287,39 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied; ret = -EIO; - pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n", - addr, add, sizeof(data), data); - if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0) + pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n", + addr, sizeof(data), data); + if (is_user_addr_valid(child, addr, sizeof(data)) < 0) break; pr_debug("ptrace: user address is valid\n"); #if L1_CODE_LENGTH != 0 - if (addr + add >= L1_CODE_START - && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { - safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_CODE_START + && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { + safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif #if L1_DATA_A_LENGTH != 0 - if (addr + add >= L1_DATA_A_START - && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_DATA_A_START + && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif #if L1_DATA_B_LENGTH != 0 - if (addr + add >= L1_DATA_B_START - && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= L1_DATA_B_START + && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else #endif - if (addr + add >= FIXED_CODE_START - && addr + add + sizeof(data) <= FIXED_CODE_END) { - memcpy((void *)(addr + add), &data, sizeof(data)); + if (addr >= FIXED_CODE_START + && addr + sizeof(data) <= FIXED_CODE_END) { + memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); } else - copied = access_process_vm(child, addr + add, &data, + copied = access_process_vm(child, addr, &data, sizeof(data), 1); pr_debug("ptrace: copied size %d\n", copied); if (copied != sizeof(data)) -- GitLab From d3ab3a62f57f3aaeed5a7e2ef136937ffd16448a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:19:50 +0800 Subject: [PATCH 3511/5416] Blackfin arch: ptrace - cleanup debug messages and style Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 9ce80d05e2c..b3f4ac792cf 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -280,7 +280,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKEDATA: - printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n"); + pr_debug("ptrace: PTRACE_PEEKDATA\n"); /* fall through */ case PTRACE_POKETEXT: /* write the word at location addr. */ { @@ -351,7 +351,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { /* restart after signal. */ long tmp; - pr_debug("ptrace_cont\n"); + pr_debug("ptrace: syscall/cont\n"); ret = -EIO; if (!valid_signal(data)) @@ -365,7 +365,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); put_reg(child, PT_SYSCFG, tmp); - pr_debug("before wake_up_process\n"); + pr_debug("ptrace: before wake_up_process\n"); wake_up_process(child); ret = 0; break; @@ -394,7 +394,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { /* set the trap flag. */ long tmp; - pr_debug("single step\n"); + pr_debug("ptrace: single step\n"); ret = -EIO; if (!valid_signal(data)) break; @@ -411,21 +411,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } case PTRACE_GETREGS: - { - - /* Get all gp regs from the child. */ - ret = ptrace_getregs(child, datap); - break; - } + /* Get all gp regs from the child. */ + ret = ptrace_getregs(child, datap); + break; case PTRACE_SETREGS: - { - printk(KERN_NOTICE - "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); - /* Set all gp regs in the child. */ - ret = 0; - break; - } + printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); + /* Set all gp regs in the child. */ + ret = 0; + break; + default: ret = ptrace_request(child, request, addr, data); break; @@ -436,7 +431,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) asmlinkage void syscall_trace(void) { - if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; -- GitLab From cb4c173d94e90f9d8c7b621d1a8dfc8b741874a2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:21:05 +0800 Subject: [PATCH 3512/5416] Blackfin arch: use existing ptrace_disable() func to clear TRACE_BITS and create the opposite ptrace_enable() Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 87 +++++++++++++++-------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index b3f4ac792cf..e8172eece04 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -175,6 +175,13 @@ static inline int is_user_addr_valid(struct task_struct *child, return -EIO; } +void ptrace_enable(struct task_struct *child) +{ + unsigned long tmp; + tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); + put_reg(child, PT_SYSCFG, tmp); +} + /* * Called by kernel/ptrace.c when detaching.. * @@ -347,29 +354,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: - { /* restart after signal. */ - long tmp; - - pr_debug("ptrace: syscall/cont\n"); + case PTRACE_CONT: /* restart after signal. */ + pr_debug("ptrace: syscall/cont\n"); - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - child->exit_code = data; - /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); - pr_debug("ptrace: before wake_up_process\n"); - wake_up_process(child); - ret = 0; + ret = -EIO; + if (!valid_signal(data)) break; - } + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; + ptrace_disable(child); + pr_debug("ptrace: before wake_up_process\n"); + wake_up_process(child); + ret = 0; + break; /* * make the child exit. Best I can do is send it a sigkill. @@ -377,38 +377,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * exit. */ case PTRACE_KILL: - { - long tmp; - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); - wake_up_process(child); + ret = 0; + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; - } - - case PTRACE_SINGLESTEP: - { /* set the trap flag. */ - long tmp; - - pr_debug("ptrace: single step\n"); - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); - put_reg(child, PT_SYSCFG, tmp); + child->exit_code = SIGKILL; + ptrace_disable(child); + wake_up_process(child); + break; - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; + case PTRACE_SINGLESTEP: /* set the trap flag. */ + pr_debug("ptrace: single step\n"); + ret = -EIO; + if (!valid_signal(data)) break; - } + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + ptrace_enable(child); + child->exit_code = data; + wake_up_process(child); + ret = 0; + break; case PTRACE_GETREGS: /* Get all gp regs from the child. */ -- GitLab From f5a817e3f707759882e423060badd2f2e52b66a4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:22:56 +0800 Subject: [PATCH 3513/5416] Blackfin arch: ptrace - make sure PT_ORIG_R0 and PT_ORIG_P0 offsets are declared Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/ptrace.h | 2 ++ arch/blackfin/kernel/asm-offsets.c | 1 + 2 files changed, 3 insertions(+) diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h index a45a80e54ad..e3f086dc726 100644 --- a/arch/blackfin/include/asm/ptrace.h +++ b/arch/blackfin/include/asm/ptrace.h @@ -158,6 +158,8 @@ extern void show_regs(struct pt_regs *); #define PT_SEQSTAT 8 #define PT_IPEND 4 +#define PT_ORIG_R0 208 +#define PT_ORIG_P0 212 #define PT_SYSCFG 216 #define PT_TEXT_ADDR 220 #define PT_TEXT_END_ADDR 224 diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 881afe9082c..9bb85dd5ccb 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -60,6 +60,7 @@ int main(void) DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); /* offsets into the pt_regs */ + DEFINE(PT_ORIG_R0, offsetof(struct pt_regs, orig_r0)); DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0)); DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc)); DEFINE(PT_R0, offsetof(struct pt_regs, r0)); -- GitLab From 47664c1f86c833c4b6398885fdb2b80fc4945c6a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 15:32:18 +0800 Subject: [PATCH 3514/5416] Blackfin arch: give sys_strace proper entry markings a global _sys_trace will cause the assembler to fail, it should be fixed in toolchain side firstly. Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 76c42d3b5e8..c13fa8da28c 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -704,6 +704,9 @@ ENTRY(_system_call) rts; ENDPROC(_system_call) +/* Do not mark as ENTRY() to avoid error in assembler ... + * this symbol need not be global anyways, so ... + */ _sys_trace: call _syscall_trace; -- GitLab From 55f2feae3a1e075d9b4b0e73a6024f3e25717878 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Thu, 9 Oct 2008 15:37:47 +0800 Subject: [PATCH 3515/5416] Blackfin arch: correct icache size in show_cpuinfo(), let c_start() return proper pointer Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index ea4f60978c6..e9054e0b455 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1000,7 +1000,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "cpu family\t: 0x%x\n" "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" "stepping\t: %d\n", - 0, + *(unsigned int *)v, vendor, (bfin_read_CHIPID() & CHIPID_FAMILY), cpu, cclk/1000000, sclk/1000000, @@ -1048,7 +1048,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) dcache_size = 0; - if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB)) + if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB)) icache_size = 0; seq_printf(m, "cache size\t: %d KB(L1 icache) " @@ -1137,12 +1137,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { - return *pos < NR_CPUS ? ((void *)0x12345678) : NULL; + if (*pos == 0) + *pos = first_cpu(cpu_online_map); + if (*pos >= num_online_cpus()) + return NULL; + + return pos; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - ++*pos; + *pos = next_cpu(*pos, cpu_online_map); + return c_start(m, pos); } -- GitLab From 57d1b5366f46fe434e565b710baf683daff78dd8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 9 Oct 2008 10:42:38 +0200 Subject: [PATCH 3516/5416] block_dev: fix kernel-doc in new functions Fix kernel-doc in new functions: Error(mmotm-2008-1002-1617//fs/block_dev.c:895): duplicate section name 'Description' Error(mmotm-2008-1002-1617//fs/block_dev.c:924): duplicate section name 'Description' Warning(mmotm-2008-1002-1617//fs/block_dev.c:1282): No description found for parameter 'pathname' Signed-off-by: Randy Dunlap cc: Andrew Patterson Signed-off-by: Jens Axboe --- fs/block_dev.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 57e2786dd2a..d84f0469a01 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -879,9 +879,7 @@ static void flush_disk(struct block_device *bdev) } /** - * check_disk_size_change - checks for disk size change and adjusts - * bdev size. - * + * check_disk_size_change - checks for disk size change and adjusts bdev size. * @disk: struct gendisk to check * @bdev: struct bdev to adjust. * @@ -908,9 +906,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) EXPORT_SYMBOL(check_disk_size_change); /** - * revalidate_disk - wrapper for lower-level driver's revalidate_disk - * call-back - * + * revalidate_disk - wrapper for lower-level driver's revalidate_disk call-back * @disk: struct gendisk to be revalidated * * This routine is a wrapper for lower-level driver's revalidate_disk @@ -1266,10 +1262,9 @@ EXPORT_SYMBOL(ioctl_by_bdev); /** * lookup_bdev - lookup a struct block_device by name + * @pathname: special file representing the block device * - * @path: special file representing the block device - * - * Get a reference to the blockdevice at @path in the current + * Get a reference to the blockdevice at @pathname in the current * namespace if possible and return it. Return ERR_PTR(error) * otherwise. */ -- GitLab From 1d5ff7e27d2ca30cd3f61afd353b03dd67330818 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Thu, 9 Oct 2008 17:06:32 +0800 Subject: [PATCH 3517/5416] Blackfin arch: Fix bug - HW Errors never recover on BF548 The kernel does not properly clear the EBIU Error Master (EBIU_ERRMST) Register on BF548, which causes the kernel to panic. We need to make sure that we clear the EBIU_ERRMST (necessary on BF54x) Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 15 +++++++++++++-- arch/blackfin/mach-common/interrupt.S | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 1a3c4daf557..709c247b701 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -1025,8 +1025,19 @@ void show_regs(struct pt_regs *fp) printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", (long)fp->seqstat, fp->ipend, fp->syscfg); - printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", - (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); + if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { + printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", + (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); +#ifdef EBIU_ERRMST + /* If the error was from the EBIU, print it out */ + if (bfin_read_EBIU_ERRMST() & CORE_ERROR) { + printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", + bfin_read_EBIU_ERRMST()); + printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", + bfin_read_EBIU_ERRADD()); + } +#endif + } printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); for (i = 6; i <= 15 ; i++) { diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 647f0f52291..4a2ec7a9675 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -179,7 +179,16 @@ ENTRY(_evt_ivhw) call _trap_c; SP += 12; +#ifdef EBIU_ERRMST + /* make sure EBIU_ERRMST is clear */ + p0.l = LO(EBIU_ERRMST); + p0.h = HI(EBIU_ERRMST); + r0.l = (CORE_ERROR | CORE_MERROR); + w[p0] = r0.l; +#endif + call _ret_from_exception; + .Lcommon_restore_all_sys: RESTORE_ALL_SYS rti; -- GitLab From 6c3fc69a173868c0a3c20bc1bba5ede463b5029c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:13:39 +0800 Subject: [PATCH 3518/5416] Blackfin arch: avoid using actual config name in comment avoid using actual config name in comment as a text search is done to see what files need to be rebuilt Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin-global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index e1f9cbd00a0..f842ea3bfc1 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -106,7 +106,7 @@ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[], _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[], _ebss_l2[], _l2_lma_start[]; -/* only used when CONFIG_MTD_UCLINUX */ +/* only used when MTD_UCLINUX */ extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size; #ifdef CONFIG_BFIN_ICACHE_LOCK -- GitLab From 8d163b3fa52bb532a4d431c195352fcf356b4977 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 7 Oct 2008 20:20:15 +0100 Subject: [PATCH 3519/5416] [ARM] 5296/1: [KS8695] Replace macro's with trailing underscores. Replace Macro names that have trailing underscores. Also use the IOPD() macro instead of a hard-coded bit-shift (for better readability). Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-ks8695/gpio.c | 20 +++++++++---------- arch/arm/mach-ks8695/include/mach/regs-gpio.h | 4 ++-- arch/arm/mach-ks8695/include/mach/regs-lan.h | 4 ++-- arch/arm/mach-ks8695/include/mach/regs-wan.h | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c index 3624e65cd89..55cee776ff5 100644 --- a/arch/arm/mach-ks8695/gpio.c +++ b/arch/arm/mach-ks8695/gpio.c @@ -72,7 +72,7 @@ int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type) /* set pin as input */ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM_(pin); + x &= ~IOPM(pin); __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); local_irq_restore(flags); @@ -108,7 +108,7 @@ int __init_or_module gpio_direction_input(unsigned int pin) /* set pin as input */ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM_(pin); + x &= ~IOPM(pin); __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); local_irq_restore(flags); @@ -136,14 +136,14 @@ int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state) /* set line state */ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); if (state) - x |= (1 << pin); + x |= IOPD(pin); else - x &= ~(1 << pin); + x &= ~IOPD(pin); __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); /* set pin as output */ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x |= IOPM_(pin); + x |= IOPM(pin); __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); local_irq_restore(flags); @@ -168,9 +168,9 @@ void gpio_set_value(unsigned int pin, unsigned int state) /* set output line state */ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); if (state) - x |= (1 << pin); + x |= IOPD(pin); else - x &= ~(1 << pin); + x &= ~IOPD(pin); __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); local_irq_restore(flags); @@ -189,7 +189,7 @@ int gpio_get_value(unsigned int pin) return -EINVAL; x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - return (x & (1 << pin)) != 0; + return (x & IOPD(pin)) != 0; } EXPORT_SYMBOL(gpio_get_value); @@ -240,7 +240,7 @@ static int ks8695_gpio_show(struct seq_file *s, void *unused) for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { seq_printf(s, "%i:\t", i); - seq_printf(s, "%s\t", (mode & IOPM_(i)) ? "Output" : "Input"); + seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); if (i <= KS8695_GPIO_3) { if (ctrl & enable[i]) { @@ -273,7 +273,7 @@ static int ks8695_gpio_show(struct seq_file *s, void *unused) seq_printf(s, "\t"); - seq_printf(s, "%i\n", (data & IOPD_(i)) ? 1 : 0); + seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); } return 0; } diff --git a/arch/arm/mach-ks8695/include/mach/regs-gpio.h b/arch/arm/mach-ks8695/include/mach/regs-gpio.h index 0df6fe61d1c..90614a7d054 100644 --- a/arch/arm/mach-ks8695/include/mach/regs-gpio.h +++ b/arch/arm/mach-ks8695/include/mach/regs-gpio.h @@ -24,7 +24,7 @@ /* Port Mode Register */ -#define IOPM_(x) (1 << (x)) /* Mode for GPIO Pin x */ +#define IOPM(x) (1 << (x)) /* Mode for GPIO Pin x */ /* Port Control Register */ #define IOPC_IOTIM1EN (1 << 17) /* GPIO Pin for Timer1 Enable */ @@ -50,6 +50,6 @@ #define IOPC_TM_EDGE (6) /* Both Edge Detection */ /* Port Data Register */ -#define IOPD_(x) (1 << (x)) /* Signal Level of GPIO Pin x */ +#define IOPD(x) (1 << (x)) /* Signal Level of GPIO Pin x */ #endif diff --git a/arch/arm/mach-ks8695/include/mach/regs-lan.h b/arch/arm/mach-ks8695/include/mach/regs-lan.h index 9ef409901e7..82c5f3791af 100644 --- a/arch/arm/mach-ks8695/include/mach/regs-lan.h +++ b/arch/arm/mach-ks8695/include/mach/regs-lan.h @@ -29,8 +29,8 @@ #define KS8695_LRDLB (0x14) /* Receive Descriptor List Base Address */ #define KS8695_LMAL (0x18) /* MAC Station Address Low */ #define KS8695_LMAH (0x1c) /* MAC Station Address High */ -#define KS8695_LMAAL_(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */ -#define KS8695_LMAAH_(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */ +#define KS8695_LMAAL(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */ +#define KS8695_LMAAH(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */ /* DMA Transmit Control Register */ diff --git a/arch/arm/mach-ks8695/include/mach/regs-wan.h b/arch/arm/mach-ks8695/include/mach/regs-wan.h index eb494ec6e95..c475bed22b8 100644 --- a/arch/arm/mach-ks8695/include/mach/regs-wan.h +++ b/arch/arm/mach-ks8695/include/mach/regs-wan.h @@ -29,8 +29,8 @@ #define KS8695_WRDLB (0x14) /* Receive Descriptor List Base Address */ #define KS8695_WMAL (0x18) /* MAC Station Address Low */ #define KS8695_WMAH (0x1c) /* MAC Station Address High */ -#define KS8695_WMAAL_(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */ -#define KS8695_WMAAH_(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */ +#define KS8695_WMAAL(n) (0x80 + ((n)*8)) /* MAC Additional Station Address (0..15) Low */ +#define KS8695_WMAAH(n) (0x84 + ((n)*8)) /* MAC Additional Station Address (0..15) High */ /* DMA Transmit Control Register */ -- GitLab From 8e6c81fe289e90b188203ec1db1dc2f3e992ebde Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 7 Oct 2008 20:44:07 +0100 Subject: [PATCH 3520/5416] [ARM] 5297/1: [KS8695] Fix two compile-time warnings Fix two warnings when compiling for the KS8695 processor. arch/arm/include/asm/dma-mapping.h: In function 'dma_to_virt': arch/arm/include/asm/dma-mapping.h:40: warning: return makes pointer from integer without a cast Section mismatch in reference from the function pcibios_fixup_bus() to the (unknown reference) .devinit.text:(unknown) The function pcibios_fixup_bus() references the (unknown reference) __devinit (unknown). This is often because pcibios_fixup_bus lacks a __devinit annotation or the annotation of (unknown) is wrong. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-ks8695/include/mach/memory.h | 4 ++-- arch/arm/mach-ks8695/pci.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index dadbe66cb75..8fbc4c76c38 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h @@ -31,8 +31,8 @@ /* Platform-bus mapping */ extern struct bus_type platform_bus_type; #define is_lbus_device(dev) (dev && dev->bus == &platform_bus_type) -#define __arch_dma_to_virt(dev, x) ({ is_lbus_device(dev) ? \ - __phys_to_virt(x) : __bus_to_virt(x); }) +#define __arch_dma_to_virt(dev, x) ({ (void *) (is_lbus_device(dev) ? \ + __phys_to_virt(x) : __bus_to_virt(x)); }) #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) #define __arch_page_to_dma(dev, x) __arch_virt_to_dma(dev, page_address(x)) diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c index 1746c67af17..507933c8379 100644 --- a/arch/arm/mach-ks8695/pci.c +++ b/arch/arm/mach-ks8695/pci.c @@ -141,7 +141,7 @@ static struct pci_ops ks8695_pci_ops = { .write = ks8695_pci_writeconfig, }; -static struct pci_bus *ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys) +static struct pci_bus* __init ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys) { return pci_scan_bus(sys->busnr, &ks8695_pci_ops, sys); } -- GitLab From 664d0403f96ff5f4fb43a4b3a54b5642589c57d2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:28:36 +0800 Subject: [PATCH 3521/5416] Blackfin arch: fix end address for parallel flash and increase kernel partition size to 4meg Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/boards/ezkit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 7c08b9f1838..5288187a3ac 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -462,7 +462,7 @@ static struct mtd_partition ezkit_partitions[] = { .offset = 0, }, { .name = "linux kernel(nor)", - .size = 0x1C0000, + .size = 0x400000, .offset = MTDPART_OFS_APPEND, }, { .name = "file system(nor)", @@ -479,7 +479,7 @@ static struct physmap_flash_data ezkit_flash_data = { static struct resource ezkit_flash_resource = { .start = 0x20000000, - .end = 0x20ffffff, + .end = 0x21ffffff, .flags = IORESOURCE_MEM, }; -- GitLab From 0c0497c257c12c9ecb8825490a339bfce8a0532f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 Oct 2008 17:32:28 +0800 Subject: [PATCH 3522/5416] Blackfin arch: Move all the silicon rev handling to one place Move all the silicon rev handling to one place (Kconfig) and make sure we warn if you are running on silicon that has not been tested on Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 13 +++++++++++++ arch/blackfin/kernel/setup.c | 3 ++- arch/blackfin/mach-bf527/include/mach/bf527.h | 2 -- arch/blackfin/mach-bf533/include/mach/bf533.h | 2 -- arch/blackfin/mach-bf537/include/mach/bf537.h | 2 -- arch/blackfin/mach-bf548/include/mach/bf548.h | 2 -- arch/blackfin/mach-bf561/include/mach/bf561.h | 2 -- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 10c97efbd91..8102c79aaa9 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -166,6 +166,19 @@ config BF561 endchoice +config BF_REV_MIN + int + default 0 if (BF52x || BF54x) + default 2 if (BF537 || BF536 || BF534) + default 3 if (BF561 ||BF533 || BF532 || BF531) + +config BF_REV_MAX + int + default 2 if (BF52x || BF54x) + default 3 if (BF537 || BF536 || BF534) + default 5 if (BF561) + default 6 if (BF533 || BF532 || BF531) + choice prompt "Silicon Rev" default BF_REV_0_1 if (BF52x || BF54x) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index e9054e0b455..4267523912b 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -821,9 +821,10 @@ void __init setup_arch(char **cmdline_p) printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", bfin_compiled_revid(), bfin_revid()); } - if (bfin_revid() < SUPPORTED_REVID) + if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", CPU, bfin_revid()); + printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", diff --git a/arch/blackfin/mach-bf527/include/mach/bf527.h b/arch/blackfin/mach-bf527/include/mach/bf527.h index 056eb4b9cd2..330041fde54 100644 --- a/arch/blackfin/mach-bf527/include/mach/bf527.h +++ b/arch/blackfin/mach-bf527/include/mach/bf527.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF527_H__ #define __MACH_BF527_H__ -#define SUPPORTED_REVID 2 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf533/include/mach/bf533.h b/arch/blackfin/mach-bf533/include/mach/bf533.h index 12a41693199..94980111230 100644 --- a/arch/blackfin/mach-bf533/include/mach/bf533.h +++ b/arch/blackfin/mach-bf533/include/mach/bf533.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF533_H__ #define __MACH_BF533_H__ -#define SUPPORTED_REVID 2 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h index cfe2a221112..7a047e04e38 100644 --- a/arch/blackfin/mach-bf537/include/mach/bf537.h +++ b/arch/blackfin/mach-bf537/include/mach/bf537.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF537_H__ #define __MACH_BF537_H__ -#define SUPPORTED_REVID 2 - /* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */ #define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE) /* SPI_STAT */ diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index e748588e893..14f8a7b8454 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF548_H__ #define __MACH_BF548_H__ -#define SUPPORTED_REVID 0 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ diff --git a/arch/blackfin/mach-bf561/include/mach/bf561.h b/arch/blackfin/mach-bf561/include/mach/bf561.h index 3ef9e5f3613..7787caad355 100644 --- a/arch/blackfin/mach-bf561/include/mach/bf561.h +++ b/arch/blackfin/mach-bf561/include/mach/bf561.h @@ -30,8 +30,6 @@ #ifndef __MACH_BF561_H__ #define __MACH_BF561_H__ -#define SUPPORTED_REVID 0x3 - #define OFFSET_(x) ((x) & 0x0000FFFF) /*some misc defines*/ -- GitLab From 0cfbb3234c8b18fc2a4934bed418be47c8382b72 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 9 Oct 2008 17:39:37 +0800 Subject: [PATCH 3523/5416] Blackfin arch: early prink code still use uart core console functions to parse and set configure option string Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 2cb0a3080d7..f08aea4fc5e 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -184,6 +184,7 @@ config DEBUG_BFIN_NO_KERN_HWTRACE config EARLY_PRINTK bool "Early printk" default n + select SERIAL_CORE_CONSOLE help This option enables special console drivers which allow the kernel to print messages very early in the bootup process. -- GitLab From 45138439e171111a93273e9c0008b41ac56d0731 Mon Sep 17 00:00:00 2001 From: Javier Herrero Date: Thu, 9 Oct 2008 18:06:47 +0800 Subject: [PATCH 3524/5416] Blackfin arch: flash memory map and dm9000 resources updating Signed-off-by: Javier Herrero Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf533/boards/H8606.c | 34 ++++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c index c66a68f3023..72ac3ac8ef7 100644 --- a/arch/blackfin/mach-bf533/boards/H8606.c +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -9,7 +9,7 @@ * Modified: * Copyright 2005 National ICT Australia (NICTA) * Copyright 2004-2006 Analog Devices Inc - * Copyright 2007 HV Sistemas S.L. + * Copyright 2007,2008 HV Sistemas S.L. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -64,18 +64,18 @@ static struct platform_device rtc_device = { static struct resource dm9000_resources[] = { [0] = { .start = 0x20300000, - .end = 0x20300000 + 1, + .end = 0x20300002, .flags = IORESOURCE_MEM, }, [1] = { - .start = 0x20300000 + 4, - .end = 0x20300000 + 5, + .start = 0x20300004, + .end = 0x20300006, .flags = IORESOURCE_MEM, }, [2] = { .start = IRQ_PF10, .end = IRQ_PF10, - .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH), }, }; @@ -140,18 +140,22 @@ static struct platform_device net2272_bfin_device = { #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) static struct mtd_partition bfin_spi_flash_partitions[] = { { - .name = "bootloader(spi)", - .size = 0x00060000, + .name = "bootloader (spi)", + .size = 0x40000, .offset = 0, .mask_flags = MTD_CAP_ROM }, { - .name = "linux kernel(spi)", - .size = 0x100000, - .offset = 0x60000 + .name = "fpga (spi)", + .size = 0x30000, + .offset = 0x40000 }, { - .name = "file system(spi)", - .size = 0x6a0000, - .offset = 0x00160000, + .name = "linux kernel (spi)", + .size = 0x150000, + .offset = 0x70000 + }, { + .name = "jffs2 root file system (spi)", + .size = 0x640000, + .offset = 0x1c0000, } }; @@ -340,7 +344,7 @@ static struct platform_device bfin_sir_device = { static struct plat_serial8250_port serial8250_platform_data [] = { { - .membase = 0x20200000, + .membase = (void *)0x20200000, .mapbase = 0x20200000, .irq = IRQ_PF8, .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE, @@ -348,7 +352,7 @@ static struct plat_serial8250_port serial8250_platform_data [] = { .regshift = 1, .uartclk = 66666667, }, { - .membase = 0x20200010, + .membase = (void *)0x20200010, .mapbase = 0x20200010, .irq = IRQ_PF8, .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE, -- GitLab From eefb47f6a1e855653d275cb90592a3587ea93a09 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 8 Oct 2008 13:01:39 -0700 Subject: [PATCH 3525/5416] xen: use spin_lock_nest_lock when pinning a pagetable When pinning/unpinning a pagetable with split pte locks, we can end up holding multiple pte locks at once (we need to hold the locks while there's a pending batched hypercall affecting the pte page). Because all the pte locks are in the same lock class, lockdep thinks that we're potentially taking a lock recursively. This warning is spurious because we always take the pte locks while holding mm->page_table_lock. lockdep now has spin_lock_nest_lock to express this kind of dominant lock use, so use it here so that lockdep knows what's going on. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/mmu.c | 74 ++++++++++++++++++++++++++++++---------------- arch/x86/xen/mmu.h | 3 -- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 64e58681767..ae173f6edd8 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -651,9 +651,12 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val) * For 64-bit, we must skip the Xen hole in the middle of the address * space, just after the big x86-64 virtual hole. */ -static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), +static int xen_pgd_walk(struct mm_struct *mm, + int (*func)(struct mm_struct *mm, struct page *, + enum pt_level), unsigned long limit) { + pgd_t *pgd = mm->pgd; int flush = 0; unsigned hole_low, hole_high; unsigned pgdidx_limit, pudidx_limit, pmdidx_limit; @@ -698,7 +701,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), pud = pud_offset(&pgd[pgdidx], 0); if (PTRS_PER_PUD > 1) /* not folded */ - flush |= (*func)(virt_to_page(pud), PT_PUD); + flush |= (*func)(mm, virt_to_page(pud), PT_PUD); for (pudidx = 0; pudidx < PTRS_PER_PUD; pudidx++) { pmd_t *pmd; @@ -713,7 +716,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), pmd = pmd_offset(&pud[pudidx], 0); if (PTRS_PER_PMD > 1) /* not folded */ - flush |= (*func)(virt_to_page(pmd), PT_PMD); + flush |= (*func)(mm, virt_to_page(pmd), PT_PMD); for (pmdidx = 0; pmdidx < PTRS_PER_PMD; pmdidx++) { struct page *pte; @@ -727,7 +730,7 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), continue; pte = pmd_page(pmd[pmdidx]); - flush |= (*func)(pte, PT_PTE); + flush |= (*func)(mm, pte, PT_PTE); } } } @@ -735,20 +738,20 @@ static int xen_pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level), out: /* Do the top level last, so that the callbacks can use it as a cue to do final things like tlb flushes. */ - flush |= (*func)(virt_to_page(pgd), PT_PGD); + flush |= (*func)(mm, virt_to_page(pgd), PT_PGD); return flush; } /* If we're using split pte locks, then take the page's lock and return a pointer to it. Otherwise return NULL. */ -static spinlock_t *xen_pte_lock(struct page *page) +static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm) { spinlock_t *ptl = NULL; #if USE_SPLIT_PTLOCKS ptl = __pte_lockptr(page); - spin_lock(ptl); + spin_lock_nest_lock(ptl, &mm->page_table_lock); #endif return ptl; @@ -772,7 +775,8 @@ static void xen_do_pin(unsigned level, unsigned long pfn) MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); } -static int xen_pin_page(struct page *page, enum pt_level level) +static int xen_pin_page(struct mm_struct *mm, struct page *page, + enum pt_level level) { unsigned pgfl = TestSetPagePinned(page); int flush; @@ -813,7 +817,7 @@ static int xen_pin_page(struct page *page, enum pt_level level) */ ptl = NULL; if (level == PT_PTE) - ptl = xen_pte_lock(page); + ptl = xen_pte_lock(page, mm); MULTI_update_va_mapping(mcs.mc, (unsigned long)pt, pfn_pte(pfn, PAGE_KERNEL_RO), @@ -834,11 +838,11 @@ static int xen_pin_page(struct page *page, enum pt_level level) /* This is called just after a mm has been created, but it has not been used yet. We need to make sure that its pagetable is all read-only, and can be pinned. */ -void xen_pgd_pin(pgd_t *pgd) +static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd) { xen_mc_batch(); - if (xen_pgd_walk(pgd, xen_pin_page, USER_LIMIT)) { + if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) { /* re-enable interrupts for kmap_flush_unused */ xen_mc_issue(0); kmap_flush_unused(); @@ -852,25 +856,35 @@ void xen_pgd_pin(pgd_t *pgd) xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(pgd))); if (user_pgd) { - xen_pin_page(virt_to_page(user_pgd), PT_PGD); + xen_pin_page(mm, virt_to_page(user_pgd), PT_PGD); xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(user_pgd))); } } #else /* CONFIG_X86_32 */ #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is pinnable */ - xen_pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_pin_page(mm, virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), + PT_PMD); #endif xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd))); #endif /* CONFIG_X86_64 */ xen_mc_issue(0); } +static void xen_pgd_pin(struct mm_struct *mm) +{ + __xen_pgd_pin(mm, mm->pgd); +} + /* * On save, we need to pin all pagetables to make sure they get their * mfns turned into pfns. Search the list for any unpinned pgds and pin * them (unpinned pgds are not currently in use, probably because the * process is under construction or destruction). + * + * Expected to be called in stop_machine() ("equivalent to taking + * every spinlock in the system"), so the locking doesn't really + * matter all that much. */ void xen_mm_pin_all(void) { @@ -881,7 +895,7 @@ void xen_mm_pin_all(void) list_for_each_entry(page, &pgd_list, lru) { if (!PagePinned(page)) { - xen_pgd_pin((pgd_t *)page_address(page)); + __xen_pgd_pin(&init_mm, (pgd_t *)page_address(page)); SetPageSavePinned(page); } } @@ -894,7 +908,8 @@ void xen_mm_pin_all(void) * that's before we have page structures to store the bits. So do all * the book-keeping now. */ -static __init int xen_mark_pinned(struct page *page, enum pt_level level) +static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page, + enum pt_level level) { SetPagePinned(page); return 0; @@ -902,10 +917,11 @@ static __init int xen_mark_pinned(struct page *page, enum pt_level level) void __init xen_mark_init_mm_pinned(void) { - xen_pgd_walk(init_mm.pgd, xen_mark_pinned, FIXADDR_TOP); + xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); } -static int xen_unpin_page(struct page *page, enum pt_level level) +static int xen_unpin_page(struct mm_struct *mm, struct page *page, + enum pt_level level) { unsigned pgfl = TestClearPagePinned(page); @@ -923,7 +939,7 @@ static int xen_unpin_page(struct page *page, enum pt_level level) * partially-pinned state. */ if (level == PT_PTE) { - ptl = xen_pte_lock(page); + ptl = xen_pte_lock(page, mm); if (ptl) xen_do_pin(MMUEXT_UNPIN_TABLE, pfn); @@ -945,7 +961,7 @@ static int xen_unpin_page(struct page *page, enum pt_level level) } /* Release a pagetables pages back as normal RW */ -static void xen_pgd_unpin(pgd_t *pgd) +static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd) { xen_mc_batch(); @@ -957,21 +973,27 @@ static void xen_pgd_unpin(pgd_t *pgd) if (user_pgd) { xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(user_pgd))); - xen_unpin_page(virt_to_page(user_pgd), PT_PGD); + xen_unpin_page(mm, virt_to_page(user_pgd), PT_PGD); } } #endif #ifdef CONFIG_X86_PAE /* Need to make sure unshared kernel PMD is unpinned */ - xen_unpin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD); + xen_unpin_page(mm, virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), + PT_PMD); #endif - xen_pgd_walk(pgd, xen_unpin_page, USER_LIMIT); + xen_pgd_walk(mm, xen_unpin_page, USER_LIMIT); xen_mc_issue(0); } +static void xen_pgd_unpin(struct mm_struct *mm) +{ + __xen_pgd_unpin(mm, mm->pgd); +} + /* * On resume, undo any pinning done at save, so that the rest of the * kernel doesn't see any unexpected pinned pagetables. @@ -986,7 +1008,7 @@ void xen_mm_unpin_all(void) list_for_each_entry(page, &pgd_list, lru) { if (PageSavePinned(page)) { BUG_ON(!PagePinned(page)); - xen_pgd_unpin((pgd_t *)page_address(page)); + __xen_pgd_unpin(&init_mm, (pgd_t *)page_address(page)); ClearPageSavePinned(page); } } @@ -997,14 +1019,14 @@ void xen_mm_unpin_all(void) void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) { spin_lock(&next->page_table_lock); - xen_pgd_pin(next->pgd); + xen_pgd_pin(next); spin_unlock(&next->page_table_lock); } void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) { spin_lock(&mm->page_table_lock); - xen_pgd_pin(mm->pgd); + xen_pgd_pin(mm); spin_unlock(&mm->page_table_lock); } @@ -1095,7 +1117,7 @@ void xen_exit_mmap(struct mm_struct *mm) /* pgd may not be pinned in the error exit path of execve */ if (xen_page_pinned(mm->pgd)) - xen_pgd_unpin(mm->pgd); + xen_pgd_unpin(mm); spin_unlock(&mm->page_table_lock); } diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 0f59bd03f9e..98d71659da5 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -18,9 +18,6 @@ void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next); void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); void xen_exit_mmap(struct mm_struct *mm); -void xen_pgd_pin(pgd_t *pgd); -//void xen_pgd_unpin(pgd_t *pgd); - pteval_t xen_pte_val(pte_t); pmdval_t xen_pmd_val(pmd_t); pgdval_t xen_pgd_val(pgd_t); -- GitLab From 04dcd84bc79d9f756bf5b9fc16c7df3344823ca8 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 9 Oct 2008 15:33:57 +0200 Subject: [PATCH 3526/5416] eeepc-laptop: Fix hwmon interface Creates a name file in the sysfs directory, that is needed for the libsensors library to work. Also rename fan1_pwm to pwm1 and scale its value as needed. This fixes bug #11520: http://bugzilla.kernel.org/show_bug.cgi?id=11520 Signed-off-by: Corentin Chary Signed-off-by: Jean Delvare --- drivers/misc/eeepc-laptop.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index facdb9893c8..1ee8501e90f 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -450,12 +450,14 @@ static int eeepc_get_fan_pwm(void) int value = 0; read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); + value = value * 255 / 100; return (value); } static void eeepc_set_fan_pwm(int value) { - value = SENSORS_LIMIT(value, 0, 100); + value = SENSORS_LIMIT(value, 0, 255); + value = value * 100 / 255; ec_write(EEEPC_EC_SC02, value); } @@ -520,15 +522,23 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); -EEEPC_CREATE_SENSOR_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, +EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, eeepc_get_fan_pwm, eeepc_set_fan_pwm); EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); +static ssize_t +show_name(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "eeepc\n"); +} +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_fan1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_name.dev_attr.attr, NULL }; -- GitLab From 98dd22c3e086d76058083432d4d8fb85f04bab90 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 9 Oct 2008 15:33:58 +0200 Subject: [PATCH 3527/5416] hwmon: (it87) Prevent power-off on Shuttle SN68PT On the Shuttle SN68PT, FAN_CTL2 is apparently not connected to a fan, but to something else. One user has reported instant system power-off when changing the PWM2 duty cycle, so we disable it. I use the board name string as the trigger in case the same board is ever used in other systems. This closes lm-sensors ticket #2349: pwmconfig causes a hard poweroff http://www.lm-sensors.org/ticket/2349 Signed-off-by: Jean Delvare --- drivers/hwmon/it87.c | 70 ++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index f1133081cc4..d793cc01199 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #define DRVNAME "it87" @@ -236,6 +238,8 @@ struct it87_sio_data { /* Values read from Super-I/O config space */ u8 revision; u8 vid_value; + /* Values set based on DMI strings */ + u8 skip_pwm; }; /* For each registered chip, we need to keep some data in memory. @@ -964,6 +968,7 @@ static int __init it87_find(unsigned short *address, { int err = -ENODEV; u16 chip_type; + const char *board_vendor, *board_name; superio_enter(); chip_type = force_id ? force_id : superio_inw(DEVID); @@ -1022,6 +1027,24 @@ static int __init it87_find(unsigned short *address, pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); } + /* Disable specific features based on DMI strings */ + board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); + board_name = dmi_get_system_info(DMI_BOARD_NAME); + if (board_vendor && board_name) { + if (strcmp(board_vendor, "nVIDIA") == 0 + && strcmp(board_name, "FN68PT") == 0) { + /* On the Shuttle SN68PT, FAN_CTL2 is apparently not + connected to a fan, but to something else. One user + has reported instant system power-off when changing + the PWM2 duty cycle, so we disable it. + I use the board name string as the trigger in case + the same board is ever used in other systems. */ + pr_info("it87: Disabling pwm2 due to " + "hardware constraints\n"); + sio_data->skip_pwm = (1 << 1); + } + } + exit: superio_exit(); return err; @@ -1168,25 +1191,33 @@ static int __devinit it87_probe(struct platform_device *pdev) } if (enable_pwm_interface) { - if ((err = device_create_file(dev, - &sensor_dev_attr_pwm1_enable.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm2_enable.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm3_enable.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm1.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm2.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm3.dev_attr)) - || (err = device_create_file(dev, - &dev_attr_pwm1_freq)) - || (err = device_create_file(dev, - &dev_attr_pwm2_freq)) - || (err = device_create_file(dev, - &dev_attr_pwm3_freq))) - goto ERROR4; + if (!(sio_data->skip_pwm & (1 << 0))) { + if ((err = device_create_file(dev, + &sensor_dev_attr_pwm1_enable.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm1.dev_attr)) + || (err = device_create_file(dev, + &dev_attr_pwm1_freq))) + goto ERROR4; + } + if (!(sio_data->skip_pwm & (1 << 1))) { + if ((err = device_create_file(dev, + &sensor_dev_attr_pwm2_enable.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm2.dev_attr)) + || (err = device_create_file(dev, + &dev_attr_pwm2_freq))) + goto ERROR4; + } + if (!(sio_data->skip_pwm & (1 << 2))) { + if ((err = device_create_file(dev, + &sensor_dev_attr_pwm3_enable.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm3.dev_attr)) + || (err = device_create_file(dev, + &dev_attr_pwm3_freq))) + goto ERROR4; + } } if (data->type == it8712 || data->type == it8716 @@ -1546,6 +1577,7 @@ static int __init sm_it87_init(void) unsigned short isa_address=0; struct it87_sio_data sio_data; + memset(&sio_data, 0, sizeof(struct it87_sio_data)); err = it87_find(&isa_address, &sio_data); if (err) return err; -- GitLab From ddedc658fc56bb5b9b200d7f4df6e93e1d0d8048 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 9 Oct 2008 15:33:58 +0200 Subject: [PATCH 3528/5416] hwmon: Define sysfs interface for energy consumption register Describe the sysfs files that were introduced in the ibmaem driver. Signed-off-by: Darrick J. Wong Signed-off-by: Jean Delvare --- Documentation/hwmon/sysfs-interface | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 2d845730d4e..6dbfd5efd99 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -329,6 +329,10 @@ power[1-*]_average Average power use Unit: microWatt RO +power[1-*]_average_interval Power use averaging interval + Unit: milliseconds + RW + power[1-*]_average_highest Historical average maximum power use Unit: microWatt RO @@ -353,6 +357,14 @@ power[1-*]_reset_history Reset input_highest, input_lowest, average_highest and average_lowest. WO +********** +* Energy * +********** + +energy[1-*]_input Cumulative energy use + Unit: microJoule + RO + ********** * Alarms * ********** -- GitLab From c73c556c1ae3619d8a7c55254b0ddcf10034a914 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 9 Oct 2008 15:33:58 +0200 Subject: [PATCH 3529/5416] hwmon: (adt7473) Fix some bogosity in documentation file Signed-off-by: Darrick J. Wong Signed-off-by: Jean Delvare --- Documentation/hwmon/adt7473 | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/Documentation/hwmon/adt7473 b/Documentation/hwmon/adt7473 index 2126de34c71..1cbf671822e 100644 --- a/Documentation/hwmon/adt7473 +++ b/Documentation/hwmon/adt7473 @@ -14,14 +14,14 @@ Description This driver implements support for the Analog Devices ADT7473 chip family. -The LM85 uses the 2-wire interface compatible with the SMBUS 2.0 +The ADT7473 uses the 2-wire interface compatible with the SMBUS 2.0 specification. Using an analog to digital converter it measures three (3) -temperatures and two (2) voltages. It has three (3) 16-bit counters for +temperatures and two (2) voltages. It has four (4) 16-bit counters for measuring fan speed. There are three (3) PWM outputs that can be used to control fan speed. A sophisticated control system for the PWM outputs is designed into the -LM85 that allows fan speed to be adjusted automatically based on any of the +ADT7473 that allows fan speed to be adjusted automatically based on any of the three temperature sensors. Each PWM output is individually adjustable and programmable. Once configured, the ADT7473 will adjust the PWM outputs in response to the measured temperatures without further host intervention. @@ -46,14 +46,6 @@ from the raw value to get the temperature value. The Analog Devices datasheet is very detailed and describes a procedure for determining an optimal configuration for the automatic PWM control. -Hardware Configurations ------------------------ - -The ADT7473 chips have an optional SMBALERT output that can be used to -signal the chipset in case a limit is exceeded or the temperature sensors -fail. Individual sensor interrupts can be masked so they won't trigger -SMBALERT. The SMBALERT output if configured replaces the PWM2 function. - Configuration Notes ------------------- @@ -61,8 +53,8 @@ Besides standard interfaces driver adds the following: * PWM Control -* pwm#_auto_point1_pwm and pwm#_auto_point1_temp and -* pwm#_auto_point2_pwm and pwm#_auto_point2_temp - +* pwm#_auto_point1_pwm and temp#_auto_point1_temp and +* pwm#_auto_point2_pwm and temp#_auto_point2_temp - point1: Set the pwm speed at a lower temperature bound. point2: Set the pwm speed at a higher temperature bound. -- GitLab From 8748a71e8c2d1310b66c2feed1632de8620cd2f1 Mon Sep 17 00:00:00 2001 From: Alistair John Strachan Date: Thu, 9 Oct 2008 15:33:59 +0200 Subject: [PATCH 3530/5416] hwmon: (abituguru3) Enable reading from AUX3 fan on Abit AT8 32X The table for the Abit AT8 32X was incorrectly missing an entry for the sixth ("AUX3") fan. Add this entry, exporting the fan reading to userspace. Closes lm-sensors.org ticket #2339. Signed-off-by: Alistair John Strachan Tested-by: Daniel Exner Acked-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/abituguru3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index d568c65c137..4545194a004 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -303,6 +303,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "SYS Fan", 34, 2, 60, 1, 0 }, { "AUX1 Fan", 35, 2, 60, 1, 0 }, { "AUX2 Fan", 36, 2, 60, 1, 0 }, + { "AUX3 Fan", 37, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, { 0x0012, NULL /* Abit AN8 32X, need DMI string */, { -- GitLab From 5e5cddbc3f2936c9fefbae64633c522e242c350d Mon Sep 17 00:00:00 2001 From: Alistair John Strachan Date: Thu, 9 Oct 2008 15:33:59 +0200 Subject: [PATCH 3531/5416] hwmon: (abituguru3) Enable DMI probing feature on Abit AT8 32X Enable driver checking of the DMI product name (when enabled) on an Abit AT8 32X, instead of falling back to a manual probe. This eliminates false negatives and eventually will help avoid unnecessary bus probes on unsupported mainboards. Signed-off-by: Alistair John Strachan Tested-by: Daniel Exner Acked-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/abituguru3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 4545194a004..d9e7a49d6cb 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "OTES1 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0011, NULL /* Abit AT8 32X, need DMI string */, { + { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 20, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, -- GitLab From d8aa0251f12546e9bd1e9ee1d9782d6492819a04 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 9 Oct 2008 13:36:24 +0100 Subject: [PATCH 3532/5416] [ARM] 5298/1: Drop desc_handle_irq() desc_handle_irq() was declared as obsolete since long ago. Replace it with generic_handle_irq() Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/common/it8152.c | 14 +++---------- arch/arm/common/locomo.c | 26 ++++++++---------------- arch/arm/kernel/ecard.c | 6 ++---- arch/arm/kernel/irq.c | 11 +++++----- arch/arm/mach-at91/gpio.c | 3 +-- arch/arm/mach-davinci/gpio.c | 5 +---- arch/arm/mach-ep93xx/core.c | 7 +++---- arch/arm/mach-footbridge/isa-irq.c | 3 +-- arch/arm/mach-h720x/common.c | 4 +--- arch/arm/mach-h720x/cpu-h7202.c | 4 +--- arch/arm/mach-imx/irq.c | 4 +--- arch/arm/mach-integrator/integrator_cp.c | 3 +-- arch/arm/mach-iop13xx/msi.c | 3 +-- arch/arm/mach-ixp2000/core.c | 6 ++---- arch/arm/mach-ixp2000/ixdp2x00.c | 4 +--- arch/arm/mach-ixp2000/ixdp2x01.c | 4 +--- arch/arm/mach-ixp23xx/core.c | 4 +--- arch/arm/mach-ixp23xx/ixdp2351.c | 8 ++------ arch/arm/mach-lh7a40x/arch-kev7a400.c | 2 +- arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 4 ++-- arch/arm/mach-lh7a40x/common.h | 1 - arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 4 ++-- arch/arm/mach-netx/generic.c | 5 +---- arch/arm/mach-ns9xxx/board-a9m9750dev.c | 5 +---- arch/arm/mach-omap1/board-voiceblue.c | 1 + arch/arm/mach-omap1/fpga.c | 4 +--- arch/arm/mach-orion5x/irq.c | 2 +- arch/arm/mach-pxa/gpio.c | 2 +- arch/arm/mach-pxa/lpd270.c | 3 +-- arch/arm/mach-pxa/lubbock.c | 3 +-- arch/arm/mach-pxa/mainstone.c | 3 +-- arch/arm/mach-pxa/pcm990-baseboard.c | 3 +-- arch/arm/mach-s3c2410/bast-irq.c | 3 +-- arch/arm/mach-s3c2412/irq.c | 4 ++-- arch/arm/mach-s3c2440/irq.c | 7 ++----- arch/arm/mach-s3c2443/irq.c | 5 +---- arch/arm/mach-sa1100/irq.c | 4 +--- arch/arm/mach-sa1100/neponset.c | 11 +++------- arch/arm/mach-versatile/core.c | 3 +-- arch/arm/plat-omap/gpio.c | 5 +---- arch/arm/plat-s3c24xx/irq.c | 24 +++++++--------------- arch/arm/plat-s3c24xx/s3c244x-irq.c | 7 ++----- 42 files changed, 72 insertions(+), 162 deletions(-) diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 5fe9588db07..2793447621c 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -66,14 +66,6 @@ static void it8152_unmask_irq(unsigned int irq) } } -static inline void it8152_irq(int irq) -{ - struct irq_desc *desc; - - desc = irq_desc + irq; - desc_handle_irq(irq, desc); -} - static struct irq_chip it8152_irq_chip = { .name = "it8152", .ack = it8152_mask_irq, @@ -128,21 +120,21 @@ void it8152_irq_demux(unsigned int irq, struct irq_desc *desc) bits_pd &= ((1 << IT8152_PD_IRQ_COUNT) - 1); while (bits_pd) { i = __ffs(bits_pd); - it8152_irq(IT8152_PD_IRQ(i)); + generic_handle_irq(IT8152_PD_IRQ(i)); bits_pd &= ~(1 << i); } bits_lp &= ((1 << IT8152_LP_IRQ_COUNT) - 1); while (bits_lp) { i = __ffs(bits_lp); - it8152_irq(IT8152_LP_IRQ(i)); + generic_handle_irq(IT8152_LP_IRQ(i)); bits_lp &= ~(1 << i); } bits_ld &= ((1 << IT8152_LD_IRQ_COUNT) - 1); while (bits_ld) { i = __ffs(bits_ld); - it8152_irq(IT8152_LD_IRQ(i)); + generic_handle_irq(IT8152_LD_IRQ(i)); bits_ld &= ~(1 << i); } } diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 283051eaf93..8f473b7c349 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -169,7 +169,6 @@ static struct locomo_dev_info locomo_devices[] = { static void locomo_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irq_desc *d; void __iomem *mapbase = get_irq_chip_data(irq); /* Acknowledge the parent IRQ */ @@ -181,10 +180,9 @@ static void locomo_handler(unsigned int irq, struct irq_desc *desc) if (req) { /* generate the next interrupt(s) */ irq = LOCOMO_IRQ_START; - d = irq_desc + irq; - for (i = 0; i <= 3; i++, d++, irq++) { + for (i = 0; i <= 3; i++, irq++) { if (req & (0x0100 << i)) { - desc_handle_irq(irq, d); + generic_handle_irq(irq); } } @@ -222,12 +220,10 @@ static struct irq_chip locomo_chip = { static void locomo_key_handler(unsigned int irq, struct irq_desc *desc) { - struct irq_desc *d; void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { - d = irq_desc + LOCOMO_IRQ_KEY_START; - desc_handle_irq(LOCOMO_IRQ_KEY_START, d); + generic_handle_irq(LOCOMO_IRQ_KEY_START); } } @@ -268,7 +264,6 @@ static struct irq_chip locomo_key_chip = { static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irq_desc *d; void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_GIR) & @@ -277,10 +272,9 @@ static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc) if (req) { irq = LOCOMO_IRQ_GPIO_START; - d = irq_desc + LOCOMO_IRQ_GPIO_START; - for (i = 0; i <= 15; i++, irq++, d++) { + for (i = 0; i <= 15; i++, irq++) { if (req & (0x0001 << i)) { - desc_handle_irq(irq, d); + generic_handle_irq(irq); } } } @@ -361,12 +355,10 @@ static struct irq_chip locomo_gpio_chip = { static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc) { - struct irq_desc *d; void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { - d = irq_desc + LOCOMO_IRQ_LT_START; - desc_handle_irq(LOCOMO_IRQ_LT_START, d); + generic_handle_irq(LOCOMO_IRQ_LT_START); } } @@ -407,17 +399,15 @@ static struct irq_chip locomo_lt_chip = { static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irq_desc *d; void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F; if (req) { irq = LOCOMO_IRQ_SPI_START; - d = irq_desc + irq; - for (i = 0; i <= 3; i++, irq++, d++) { + for (i = 0; i <= 3; i++, irq++) { if (req & (0x0001 << i)) { - desc_handle_irq(irq, d); + generic_handle_irq(irq); } } } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 7a50575a8d4..60c079d8535 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -587,8 +587,7 @@ ecard_irq_handler(unsigned int irq, struct irq_desc *desc) pending = ecard_default_ops.irqpending(ec); if (pending) { - struct irq_desc *d = irq_desc + ec->irq; - desc_handle_irq(ec->irq, d); + generic_handle_irq(ec->irq); called ++; } } @@ -622,7 +621,6 @@ ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc) ecard_t *ec = slot_to_ecard(slot); if (ec->claimed) { - struct irq_desc *d = irq_desc + ec->irq; /* * this ugly code is so that we can operate a * prioritorising system: @@ -635,7 +633,7 @@ ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc) * Serial cards should go in 0/1, ethernet/scsi in 2/3 * otherwise you will lose serial data at high speeds! */ - desc_handle_irq(ec->irq, d); + generic_handle_irq(ec->irq); } else { printk(KERN_WARNING "card%d: interrupt from unclaimed " "card???\n", slot); diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index f88efb135b7..2f3eb795fa6 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -112,18 +112,17 @@ static struct irq_desc bad_irq_desc = { asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - struct irq_desc *desc = irq_desc + irq; + + irq_enter(); /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq >= NR_IRQS) - desc = &bad_irq_desc; - - irq_enter(); - - desc_handle_irq(irq, desc); + handle_bad_irq(irq, &bad_irq_desc); + else + generic_handle_irq(irq); /* AT91 specific workaround */ irq_finish(irq); diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 8392d5b517f..94c2f96811f 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -404,7 +404,6 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) } pin = bank->chipbase; - gpio = &irq_desc[pin]; while (isr) { if (isr & 1) { @@ -417,7 +416,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) gpio_irq_mask(pin); } else - desc_handle_irq(pin, gpio); + generic_handle_irq(pin); } pin++; gpio++; diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index c9cb4f09b18..574cb810a50 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -201,7 +201,6 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) desc->chip->ack(irq); while (1) { u32 status; - struct irq_desc *gpio; int n; int res; @@ -215,12 +214,10 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) /* now demux them to the right lowlevel handler */ n = (int)get_irq_data(irq); - gpio = &irq_desc[n]; while (status) { res = ffs(status); n += res; - gpio += res; - desc_handle_irq(n - 1, gpio - 1); + generic_handle_irq(n - 1); status >>= res; } } diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index f99f4366939..68ee82b4959 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -192,8 +192,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < 8; i++) { if (status & (1 << i)) { int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; - desc = irq_desc + gpio_irq; - desc_handle_irq(gpio_irq, desc); + generic_handle_irq(gpio_irq); } } @@ -202,7 +201,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) if (status & (1 << i)) { int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; desc = irq_desc + gpio_irq; - desc_handle_irq(gpio_irq, desc); + generic_handle_irq(gpio_irq); } } } @@ -217,7 +216,7 @@ static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; - desc_handle_irq(gpio_irq, irq_desc + gpio_irq); + generic_handle_irq(gpio_irq); } static void ep93xx_gpio_irq_ack(unsigned int irq) diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index 7132e522c36..d5a29a0e7d9 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -94,8 +94,7 @@ isa_irq_handler(unsigned int irq, struct irq_desc *desc) return; } - desc = irq_desc + isa_irq; - desc_handle_irq(isa_irq, desc); + generic_handle_irq(isa_irq); } static struct irqaction irq_cascade = { diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c index b5f9741ae13..c1fa44cff38 100644 --- a/arch/arm/mach-h720x/common.c +++ b/arch/arm/mach-h720x/common.c @@ -104,14 +104,12 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq, struct irq_desc *desc) { IRQDBG("%s irq: %d\n", __func__, irq); - desc = irq_desc + irq; while (mask) { if (mask & 1) { IRQDBG("handling irq %d\n", irq); - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } irq++; - desc++; mask >>= 1; } } diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index 53e1f62f2e7..fd33a19c813 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c @@ -120,12 +120,10 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc) mask >>= 1; irq = IRQ_TIMER1; - desc = irq_desc + irq; while (mask) { if (mask & 1) - desc_handle_irq(irq, desc); + generic_handle_irq(irq); irq++; - desc++; mask >>= 1; } } diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c index 798f221eb3b..cbdd7d1dac9 100644 --- a/arch/arm/mach-imx/irq.c +++ b/arch/arm/mach-imx/irq.c @@ -182,14 +182,12 @@ static void imx_gpio_handler(unsigned int mask, unsigned int irq, struct irq_desc *desc) { - desc = irq_desc + irq; while (mask) { if (mask & 1) { DEBUG_IRQ("handling irq %d\n", irq); - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } irq++; - desc++; mask >>= 1; } } diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 6b99e9c258b..0c9a91d6ec8 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -217,8 +217,7 @@ sic_handle_irq(unsigned int irq, struct irq_desc *desc) irq += IRQ_SIC_START; - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } while (status); } diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index 63ef1124ca5..f34b0ed8063 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -110,8 +110,7 @@ static void iop13xx_msi_handler(unsigned int irq, struct irq_desc *desc) do { j = find_first_bit(&status, 32); (write_imipr[i])(1 << j); /* write back to clear bit */ - desc = irq_desc + IRQ_IOP13XX_MSI_0 + j + (32*i); - desc_handle_irq(IRQ_IOP13XX_MSI_0 + j + (32*i), desc); + generic_handle_irq(IRQ_IOP13XX_MSI_0 + j + (32*i)); status = (read_imipr[i])(); } while (status); } diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index a6a4f93085f..e193a34e417 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -311,8 +311,7 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i <= 7; i++) { if (status & (1<= 0; i--) { if(status & (1 << i)) { - desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; - desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc); + generic_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i); } } } diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c index 5a781fd9757..4c749d49024 100644 --- a/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/arch/arm/mach-ixp2000/ixdp2x00.c @@ -129,10 +129,8 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc) for(i = 0; i < board_irq_count; i++) { if(ex_interrupt & (1 << i)) { - struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; - cpld_desc = irq_desc + cpld_irq; - desc_handle_irq(cpld_irq, cpld_desc); + generic_handle_irq(cpld_irq); } } diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 78a2341dee2..b78c08d1f63 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -79,10 +79,8 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < IXP2000_BOARD_IRQS; i++) { if (ex_interrupt & (1 << i)) { - struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; - cpld_desc = irq_desc + cpld_irq; - desc_handle_irq(cpld_irq, cpld_desc); + generic_handle_irq(cpld_irq); } } diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index 68b4ac5b248..aa4c4420ff3 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -253,7 +253,6 @@ static void pci_handler(unsigned int irq, struct irq_desc *desc) { u32 pci_interrupt; unsigned int irqno; - struct irq_desc *int_desc; pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS; @@ -268,8 +267,7 @@ static void pci_handler(unsigned int irq, struct irq_desc *desc) BUG(); } - int_desc = irq_desc + irqno; - desc_handle_irq(irqno, int_desc); + generic_handle_irq(irqno); desc->chip->unmask(irq); } diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c index b6e0bfa44df..f1b124a709a 100644 --- a/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/arch/arm/mach-ixp23xx/ixdp2351.c @@ -68,11 +68,9 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); - cpld_desc = irq_desc + cpld_irq; - desc_handle_irq(cpld_irq, cpld_desc); + generic_handle_irq(cpld_irq); } } @@ -105,11 +103,9 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); - cpld_desc = irq_desc + cpld_irq; - desc_handle_irq(cpld_irq, cpld_desc); + generic_handle_irq(cpld_irq); } } diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c index 551b9726182..3d7bd50b909 100644 --- a/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -77,7 +77,7 @@ static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) irq = IRQ_KEV7A400_CPLD; for (; mask; mask >>= 1, ++irq) if (mask & 1) - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } void __init lh7a40x_init_board_irq (void) diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index e373fb8e269..cb15e5d3212 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -214,11 +214,11 @@ static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) desc->chip->ack (irq); if ((mask & (1<<0)) == 0) /* WLAN */ - IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); + generic_handle_irq(IRQ_LPD7A40X_ETH_INT); #if defined (IRQ_TOUCH) if ((mask & (1<<1)) == 0) /* Touch */ - IRQ_DISPATCH (IRQ_TOUCH); + generic_handle_irq(IRQ_TOUCH); #endif desc->chip->unmask (irq); /* Level-triggered need this */ diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h index 0ca20c6c83b..6ed3f6b6db7 100644 --- a/arch/arm/mach-lh7a40x/common.h +++ b/arch/arm/mach-lh7a40x/common.h @@ -15,4 +15,3 @@ extern void lh7a404_init_irq (void); extern void lh7a40x_clcd_init (void); extern void lh7a40x_init_board_irq (void); -#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq)) diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c index 0d5063ebda1..fd033bb4342 100644 --- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c @@ -63,10 +63,10 @@ static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) desc->chip->ack (irq); if ((mask & 0x1) == 0) /* WLAN */ - IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); + generic_handle_irq(IRQ_LPD7A40X_ETH_INT); if ((mask & 0x2) == 0) /* Touch */ - IRQ_DISPATCH (IRQ_LPD7A400_TS); + generic_handle_irq(IRQ_LPD7A400_TS); desc->chip->unmask (irq); /* Level-triggered need this */ } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index 1b40483ea75..3830eca2438 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -77,15 +77,12 @@ netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc) stat = ((readl(NETX_DPMAS_INT_EN) & readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f; - desc = irq_desc + NETX_IRQ_HIF_CHAINED(0); - while (stat) { if (stat & 1) { DEBUG_IRQ("handling irq %d\n", irq); - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } irq++; - desc++; stat >>= 1; } } diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c index a22a608a7ab..b45bb3b802f 100644 --- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c +++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c @@ -86,13 +86,10 @@ static void a9m9750dev_fpga_demux_handler(unsigned int irq, while (stat != 0) { int irqno = fls(stat) - 1; - struct irq_desc *fpgadesc; stat &= ~(1 << irqno); - fpgadesc = irq_desc + FPGA_IRQ(irqno); - - desc_handle_irq(FPGA_IRQ(irqno), fpgadesc); + generic_handle_irq(FPGA_IRQ(irqno)); } desc->chip->unmask(irq); diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 213b4878710..45a01311669 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index 4449d86095f..23f2c3aeb38 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c @@ -86,7 +86,6 @@ static void fpga_mask_ack_irq(unsigned int irq) void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) { - struct irq_desc *d; u32 stat; int fpga_irq; @@ -99,8 +98,7 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) (fpga_irq < OMAP_FPGA_IRQ_END) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { - d = irq_desc + fpga_irq; - desc_handle_irq(fpga_irq, d); + generic_handle_irq(fpga_irq); } } } diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c index 2545ff9e583..15f27aa7f53 100644 --- a/arch/arm/mach-orion5x/irq.c +++ b/arch/arm/mach-orion5x/irq.c @@ -162,7 +162,7 @@ static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) polarity ^= 1 << pin; writel(polarity, GPIO_IN_POL); } - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } } } diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 07acc1b2385..e92bec510e5 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c @@ -275,7 +275,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) loop = 1; n = PXA_GPIO_IRQ_BASE + bit; - desc_handle_irq(n, irq_desc + n); + generic_handle_irq(n); bit = find_next_bit(gedr, GEDR_BITS, bit + 1); } diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index 92728a37298..de3f67daaac 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -125,8 +125,7 @@ static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ if (likely(pending)) { irq = LPD270_IRQ(0) + __ffs(pending); - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index ecbfbb9f46a..bff704354c1 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -155,8 +155,7 @@ static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc) GEDR(0) = GPIO_bit(0); /* clear our parent irq */ if (likely(pending)) { irq = LUBBOCK_IRQ(0) + __ffs(pending); - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; } while (pending); diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index a02edfd4fc0..f2c7ad8f2b6 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -162,8 +162,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc) GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ if (likely(pending)) { irq = MAINSTONE_IRQ(0) + __ffs(pending); - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } pending = MST_INTSETCLR & mainstone_irq_enabled; } while (pending); diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index e9efb80bb33..f601425f1b1 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -262,8 +262,7 @@ static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) GPIO_bit(PCM990_CTRL_INT_IRQ_GPIO); if (likely(pending)) { irq = PCM027_IRQ(0) + __ffs(pending); - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled; } while (pending); diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c index c66021b5fa4..44140bd99ed 100644 --- a/arch/arm/mach-s3c2410/bast-irq.c +++ b/arch/arm/mach-s3c2410/bast-irq.c @@ -130,8 +130,7 @@ bast_irq_pc104_demux(unsigned int irq, for (i = 0; stat != 0; i++, stat >>= 1) { if (stat & 1) { irqno = bast_pc104_irqs[i]; - desc = irq_desc + irqno; - desc_handle_irq(irqno, desc); + generic_handle_irq(irqno); } } } diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c index ac62b79044f..72159d31966 100644 --- a/arch/arm/mach-s3c2412/irq.c +++ b/arch/arm/mach-s3c2412/irq.c @@ -123,10 +123,10 @@ static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc) subsrc &= ~submsk; if (subsrc & INTBIT(IRQ_S3C2412_SDI)) - desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI); + generic_handle_irq(IRQ_S3C2412_SDI); if (subsrc & INTBIT(IRQ_S3C2412_CF)) - desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF); + generic_handle_irq(IRQ_S3C2412_CF); } #define INTMSK_CFSDI (1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0)) diff --git a/arch/arm/mach-s3c2440/irq.c b/arch/arm/mach-s3c2440/irq.c index 276b823f4e2..ad68b4d8835 100644 --- a/arch/arm/mach-s3c2440/irq.c +++ b/arch/arm/mach-s3c2440/irq.c @@ -44,7 +44,6 @@ static void s3c_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) { unsigned int subsrc, submsk; - struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -58,12 +57,10 @@ static void s3c_irq_demux_wdtac97(unsigned int irq, if (subsrc != 0) { if (subsrc & 1) { - mydesc = irq_desc + IRQ_S3C2440_WDT; - desc_handle_irq(IRQ_S3C2440_WDT, mydesc); + generic_handle_irq(IRQ_S3C2440_WDT); } if (subsrc & 2) { - mydesc = irq_desc + IRQ_S3C2440_AC97; - desc_handle_irq(IRQ_S3C2440_AC97, mydesc); + generic_handle_irq(IRQ_S3C2440_AC97); } } } diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c index 9674de7223f..1570d3a6e15 100644 --- a/arch/arm/mach-s3c2443/irq.c +++ b/arch/arm/mach-s3c2443/irq.c @@ -44,7 +44,6 @@ static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) { unsigned int subsrc, submsk; unsigned int end; - struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -57,13 +56,11 @@ static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) subsrc &= (1 << len)-1; end = len + irq; - mydesc = irq_desc + irq; for (; irq < end && subsrc; irq++) { if (subsrc & 1) - desc_handle_irq(irq, mydesc); + generic_handle_irq(irq); - mydesc++; subsrc >>= 1; } } diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index 86369a8f0ce..3093d46a9c6 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -122,14 +122,12 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) GEDR = mask; irq = IRQ_GPIO11; - desc = irq_desc + irq; mask >>= 11; do { if (mask & 1) - desc_handle_irq(irq, desc); + generic_handle_irq(irq); mask >>= 1; irq++; - desc++; } while (mask); mask = GEDR & 0xfffff800; diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 4856a6bd248..6ccd175bc4c 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -33,8 +33,6 @@ neponset_irq_handler(unsigned int irq, struct irq_desc *desc) unsigned int irr; while (1) { - struct irq_desc *d; - /* * Acknowledge the parent IRQ. */ @@ -67,21 +65,18 @@ neponset_irq_handler(unsigned int irq, struct irq_desc *desc) desc->chip->ack(irq); if (irr & IRR_ETHERNET) { - d = irq_desc + IRQ_NEPONSET_SMC9196; - desc_handle_irq(IRQ_NEPONSET_SMC9196, d); + generic_handle_irq(IRQ_NEPONSET_SMC9196); } if (irr & IRR_USAR) { - d = irq_desc + IRQ_NEPONSET_USAR; - desc_handle_irq(IRQ_NEPONSET_USAR, d); + generic_handle_irq(IRQ_NEPONSET_USAR); } desc->chip->unmask(irq); } if (irr & IRR_SA1111) { - d = irq_desc + IRQ_NEPONSET_SA1111; - desc_handle_irq(IRQ_NEPONSET_SA1111, d); + generic_handle_irq(IRQ_NEPONSET_SA1111); } } } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index d75e795c893..c3468bf2841 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -95,8 +95,7 @@ sic_handle_irq(unsigned int irq, struct irq_desc *desc) irq += IRQ_SIC_START; - desc = irq_desc + irq; - desc_handle_irq(irq, desc); + generic_handle_irq(irq); } while (status); } diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 9e1341ebc14..960040aa71f 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -1051,13 +1051,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) gpio_irq = bank->virtual_irq_start; for (; isr != 0; isr >>= 1, gpio_irq++) { - struct irq_desc *d; - if (!(isr & 1)) continue; - d = irq_desc + gpio_irq; - desc_handle_irq(gpio_irq, d); + generic_handle_irq(gpio_irq); } } /* if bank has any level sensitive GPIO pin interrupt diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 36cefe17683..b6c84f4f7a1 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -468,7 +468,6 @@ static void s3c_irq_demux_adc(unsigned int irq, { unsigned int subsrc, submsk; unsigned int offset = 9; - struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -482,12 +481,10 @@ static void s3c_irq_demux_adc(unsigned int irq, if (subsrc != 0) { if (subsrc & 1) { - mydesc = irq_desc + IRQ_TC; - desc_handle_irq(IRQ_TC, mydesc); + generic_handle_irq(IRQ_TC); } if (subsrc & 2) { - mydesc = irq_desc + IRQ_ADC; - desc_handle_irq(IRQ_ADC, mydesc); + generic_handle_irq(IRQ_ADC); } } } @@ -496,7 +493,6 @@ static void s3c_irq_demux_uart(unsigned int start) { unsigned int subsrc, submsk; unsigned int offset = start - IRQ_S3CUART_RX0; - struct irq_desc *desc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -512,20 +508,14 @@ static void s3c_irq_demux_uart(unsigned int start) subsrc &= 7; if (subsrc != 0) { - desc = irq_desc + start; - if (subsrc & 1) - desc_handle_irq(start, desc); - - desc++; + generic_handle_irq(start); if (subsrc & 2) - desc_handle_irq(start+1, desc); - - desc++; + generic_handle_irq(start+1); if (subsrc & 4) - desc_handle_irq(start+2, desc); + generic_handle_irq(start+2); } } @@ -572,7 +562,7 @@ s3c_irq_demux_extint8(unsigned int irq, eintpnd &= ~(1< Date: Fri, 29 Aug 2008 15:53:24 +0100 Subject: [PATCH 3533/5416] [ARM] 5239/1: Palm Zire 72 power management support This patch contains Palm Zire 72 power management support. Depends on #5238/1 Signed-off-by: Sergey Lapin Signed-off-by: Russell King --- arch/arm/mach-pxa/include/mach/palmz72.h | 13 +++++ arch/arm/mach-pxa/palmz72.c | 74 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/arch/arm/mach-pxa/include/mach/palmz72.h b/arch/arm/mach-pxa/include/mach/palmz72.h index 8fd30bcecb7..5032307ebf7 100644 --- a/arch/arm/mach-pxa/include/mach/palmz72.h +++ b/arch/arm/mach-pxa/include/mach/palmz72.h @@ -63,5 +63,18 @@ #define PALMZ72_PRESCALER 0x3F #define PALMZ72_PERIOD_NS 3500 +#ifdef CONFIG_PM +struct palmz72_resume_info { + u32 magic0; /* 0x0 */ + u32 magic1; /* 0x4 */ + u32 resume_addr; /* 0x8 */ + u32 pad[11]; /* 0xc..0x37 */ + u32 arm_control; /* 0x38 */ + u32 aux_control; /* 0x3c */ + u32 ttb; /* 0x40 */ + u32 domain_access; /* 0x44 */ + u32 process_id; /* 0x48 */ +}; +#endif #endif diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index a90b4d77a20..2f730da3bba 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -449,6 +449,80 @@ static struct pxafb_mach_info palmz72_lcd_screen = { .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, }; +#ifdef CONFIG_PM + +/* We have some black magic here + * PalmOS ROM on recover expects special struct physical address + * to be transferred via PSPR. Using this struct PalmOS restores + * its state after sleep. As for Linux, we need to setup it the + * same way. More than that, PalmOS ROM changes some values in memory. + * For now only one location is found, which needs special treatment. + * Thanks to Alex Osborne, Andrzej Zaborowski, and lots of other people + * for reading backtraces for me :) + */ + +#define PALMZ72_SAVE_DWORD ((unsigned long *)0xc0000050) + +static struct palmz72_resume_info palmz72_resume_info = { + .magic0 = 0xb4e6, + .magic1 = 1, + + /* reset state, MMU off etc */ + .arm_control = 0, + .aux_control = 0, + .ttb = 0, + .domain_access = 0, + .process_id = 0, +}; + +static unsigned long store_ptr; + +/* sys_device for Palm Zire 72 PM */ + +static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg) +{ + /* setup the resume_info struct for the original bootloader */ + palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume; + + /* Storing memory touched by ROM */ + store_ptr = *PALMZ72_SAVE_DWORD; + + /* Setting PSPR to a proper value */ + PSPR = virt_to_phys(&palmz72_resume_info); + + return 0; +} + +static int palmz72_pm_resume(struct sys_device *dev) +{ + *PALMZ72_SAVE_DWORD = store_ptr; + return 0; +} + +static struct sysdev_class palmz72_pm_sysclass = { + .name = "palmz72_pm", + .suspend = palmz72_pm_suspend, + .resume = palmz72_pm_resume, +}; + +static struct sys_device palmz72_pm_device = { + .cls = &palmz72_pm_sysclass, +}; + +static int __init palmz72_pm_init(void) +{ + int ret = -ENODEV; + if (machine_is_palmz72()) { + ret = sysdev_class_register(&palmz72_pm_sysclass); + if (ret == 0) + ret = sysdev_register(&palmz72_pm_device); + } + return ret; +} + +device_initcall(palmz72_pm_init); +#endif + /****************************************************************************** * Machine init ******************************************************************************/ -- GitLab From 2e7509e5b3acc4b8653faa1966e5ac234d36ac82 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 9 Oct 2008 17:51:28 +0300 Subject: [PATCH 3534/5416] ARM: OMAP2: Fix sparse, checkpatch warnings in OMAP2/3 IRQ code Fix sparse warnings in mach-omap2/irq.c. Fix by defining intc_bank_write_reg() and intc_bank_read_reg(), and convert INTC module register access to use them rather than __raw_{read,write}l. Also clear up some checkpatch warnings involving includes from asm/ rather than linux/. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/irq.c | 69 +++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index a5c748a4a56..c39e26dc5ee 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -13,17 +13,23 @@ #include #include #include +#include #include #include -#include -#include -#define INTC_REVISION 0x0000 -#define INTC_SYSCONFIG 0x0010 -#define INTC_SYSSTATUS 0x0014 -#define INTC_CONTROL 0x0048 -#define INTC_MIR_CLEAR0 0x0088 -#define INTC_MIR_SET0 0x008c + +/* selected INTC register offsets */ + +#define INTC_REVISION 0x0000 +#define INTC_SYSCONFIG 0x0010 +#define INTC_SYSSTATUS 0x0014 +#define INTC_CONTROL 0x0048 +#define INTC_MIR_CLEAR0 0x0088 +#define INTC_MIR_SET0 0x008c +#define INTC_PENDING_IRQ0 0x0098 + +/* Number of IRQ state bits in each MIR register */ +#define IRQ_BITS_PER_REG 32 /* * OMAP2 has a number of different interrupt controllers, each interrupt @@ -42,36 +48,40 @@ static struct omap_irq_bank { }, }; +/* INTC bank register get/set */ + +static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg) +{ + __raw_writel(val, bank->base_reg + reg); +} + +static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) +{ + return __raw_readl(bank->base_reg + reg); +} + /* XXX: FIQ and additional INTC support (only MPU at the moment) */ static void omap_ack_irq(unsigned int irq) { - __raw_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL); + intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL); } static void omap_mask_irq(unsigned int irq) { - int offset = (irq >> 5) << 5; + int offset = irq & (~(IRQ_BITS_PER_REG - 1)); - if (irq >= 64) { - irq %= 64; - } else if (irq >= 32) { - irq %= 32; - } + irq &= (IRQ_BITS_PER_REG - 1); - __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset); + intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset); } static void omap_unmask_irq(unsigned int irq) { - int offset = (irq >> 5) << 5; + int offset = irq & (~(IRQ_BITS_PER_REG - 1)); - if (irq >= 64) { - irq %= 64; - } else if (irq >= 32) { - irq %= 32; - } + irq &= (IRQ_BITS_PER_REG - 1); - __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset); + intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset); } static void omap_mask_ack_irq(unsigned int irq) @@ -91,20 +101,20 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) { unsigned long tmp; - tmp = __raw_readl(bank->base_reg + INTC_REVISION) & 0xff; + tmp = intc_bank_read_reg(bank, INTC_REVISION) & 0xff; printk(KERN_INFO "IRQ: Found an INTC at 0x%p " "(revision %ld.%ld) with %d interrupts\n", bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs); - tmp = __raw_readl(bank->base_reg + INTC_SYSCONFIG); + tmp = intc_bank_read_reg(bank, INTC_SYSCONFIG); tmp |= 1 << 1; /* soft reset */ - __raw_writel(tmp, bank->base_reg + INTC_SYSCONFIG); + intc_bank_write_reg(tmp, bank, INTC_SYSCONFIG); - while (!(__raw_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1)) + while (!(intc_bank_read_reg(bank, INTC_SYSSTATUS) & 0x1)) /* Wait for reset to complete */; /* Enable autoidle */ - __raw_writel(1 << 0, bank->base_reg + INTC_SYSCONFIG); + intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG); } void __init omap_init_irq(void) @@ -117,7 +127,8 @@ void __init omap_init_irq(void) struct omap_irq_bank *bank = irq_banks + i; if (cpu_is_omap24xx()) - bank->base_reg = IO_ADDRESS(OMAP24XX_IC_BASE); + bank->base_reg = OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE); + omap_irq_bank_init_one(bank); nr_irqs += bank->nr_irqs; -- GitLab From cc26b3b01bc96a8b8c36671b0dc4898b2a152ea8 Mon Sep 17 00:00:00 2001 From: "Syed Mohammed, Khasim" Date: Thu, 9 Oct 2008 17:51:41 +0300 Subject: [PATCH 3535/5416] ARM: OMAP3: Add minimal omap3430 support Add minimal omap3430 support based on earlier patches from Syed Mohammed Khasim. Also merge in omap34xx SRAM support from Karthik Dasu and use consistent naming for sram init functions. Also do following changes that make 34xx support usable: - Remove unused sram.c functions for 34xx - Rename IRQ_SIR_IRQ to INTCPS_SIR_IRQ and define it locally in entry-macro.S - Update mach-omap2/io.c to support 2420, 2430, and 34xx - Also merge in 34xx GPMC changes to add fields wr_access and wr_data_mux_bus from Adrian Hunter - Remove memory initialization call omap2_init_memory() until until more generic memory initialization patches are posted. It's OK to rely on bootloader initialization until then. Signed-off-by: Syed Mohammed, Khasim Signed-off-by: Karthik Dasu Signed-off-by: Adrian Hunter Signed-off-by: Tony Lindgren --- arch/arm/Makefile | 1 + arch/arm/mach-omap2/Kconfig | 11 +- arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/gpmc.c | 5 + arch/arm/mach-omap2/io.c | 126 ++++++++++-- arch/arm/mach-omap2/irq.c | 2 + arch/arm/mach-omap2/memory.c | 14 ++ arch/arm/mach-omap2/mux.c | 67 +++++-- arch/arm/mach-omap2/sram34xx.S | 179 ++++++++++++++++++ arch/arm/plat-omap/Kconfig | 9 +- arch/arm/plat-omap/devices.c | 15 +- arch/arm/plat-omap/include/mach/debug-macro.S | 12 ++ arch/arm/plat-omap/include/mach/entry-macro.S | 12 +- arch/arm/plat-omap/include/mach/gpmc.h | 4 + arch/arm/plat-omap/include/mach/io.h | 3 - arch/arm/plat-omap/include/mach/irqs.h | 35 ++++ arch/arm/plat-omap/include/mach/mcbsp.h | 2 +- arch/arm/plat-omap/include/mach/memory.h | 2 +- arch/arm/plat-omap/include/mach/mux.h | 26 ++- arch/arm/plat-omap/include/mach/omap24xx.h | 1 - arch/arm/plat-omap/include/mach/sdrc.h | 4 +- arch/arm/plat-omap/include/mach/sram.h | 10 + arch/arm/plat-omap/include/mach/system.h | 2 +- arch/arm/plat-omap/io.c | 32 +++- arch/arm/plat-omap/sram.c | 53 ++---- 25 files changed, 538 insertions(+), 90 deletions(-) create mode 100644 arch/arm/mach-omap2/sram34xx.S diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 703a44fa0f9..552ea6d71ea 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -118,6 +118,7 @@ endif machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx machine-$(CONFIG_ARCH_OMAP1) := omap1 machine-$(CONFIG_ARCH_OMAP2) := omap2 + machine-$(CONFIG_ARCH_OMAP3) := omap2 plat-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 7069c9d536f..e2481e4045e 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -15,8 +15,17 @@ config ARCH_OMAP2430 bool "OMAP2430 support" depends on ARCH_OMAP24XX +config ARCH_OMAP34XX + bool "OMAP34xx Based System" + depends on ARCH_OMAP3 + +config ARCH_OMAP3430 + bool "OMAP3430 support" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + select ARCH_OMAP_OTG + comment "OMAP Board Type" - depends on ARCH_OMAP2 + depends on ARCH_OMAP2 || ARCH_OMAP3 config MACH_OMAP_GENERIC bool "Generic OMAP board" diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 800639e7c6a..0dc40db3811 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o # Functions loaded to SRAM obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o +obj-$(CONFIG_ARCH_OMAP3) += sram34xx.o # Power Management ifeq ($(CONFIG_PM),y) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 149bfba43cf..375ad27479c 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -220,6 +220,11 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + if (cpu_is_omap34xx()) { + GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); + } + /* caller is expected to have initialized CONFIG1 to cover * at least sync vs async */ diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 03c6ab1a3b1..71a9de382d2 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -43,7 +43,9 @@ * The machine specific code may provide the extra mapping besides the * default mapping provided here. */ -static struct map_desc omap2_io_desc[] __initdata = { + +#ifdef CONFIG_ARCH_OMAP24XX +static struct map_desc omap24xx_io_desc[] __initdata = { { .virtual = L3_24XX_VIRT, .pfn = __phys_to_pfn(L3_24XX_PHYS), @@ -51,12 +53,39 @@ static struct map_desc omap2_io_desc[] __initdata = { .type = MT_DEVICE }, { - .virtual = L4_24XX_VIRT, - .pfn = __phys_to_pfn(L4_24XX_PHYS), - .length = L4_24XX_SIZE, - .type = MT_DEVICE + .virtual = L4_24XX_VIRT, + .pfn = __phys_to_pfn(L4_24XX_PHYS), + .length = L4_24XX_SIZE, + .type = MT_DEVICE + }, +}; + +#ifdef CONFIG_ARCH_OMAP2420 +static struct map_desc omap242x_io_desc[] __initdata = { + { + .virtual = DSP_MEM_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), + .length = DSP_MEM_24XX_SIZE, + .type = MT_DEVICE + }, + { + .virtual = DSP_IPI_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), + .length = DSP_IPI_24XX_SIZE, + .type = MT_DEVICE }, + { + .virtual = DSP_MMU_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), + .length = DSP_MMU_24XX_SIZE, + .type = MT_DEVICE + }, +}; + +#endif + #ifdef CONFIG_ARCH_OMAP2430 +static struct map_desc omap243x_io_desc[] __initdata = { { .virtual = L4_WK_243X_VIRT, .pfn = __phys_to_pfn(L4_WK_243X_PHYS), @@ -69,30 +98,90 @@ static struct map_desc omap2_io_desc[] __initdata = { .length = OMAP243X_GPMC_SIZE, .type = MT_DEVICE }, + { + .virtual = OMAP243X_SDRC_VIRT, + .pfn = __phys_to_pfn(OMAP243X_SDRC_PHYS), + .length = OMAP243X_SDRC_SIZE, + .type = MT_DEVICE + }, + { + .virtual = OMAP243X_SMS_VIRT, + .pfn = __phys_to_pfn(OMAP243X_SMS_PHYS), + .length = OMAP243X_SMS_SIZE, + .type = MT_DEVICE + }, +}; #endif +#endif + +#ifdef CONFIG_ARCH_OMAP34XX +static struct map_desc omap34xx_io_desc[] __initdata = { { - .virtual = DSP_MEM_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), - .length = DSP_MEM_24XX_SIZE, + .virtual = L3_34XX_VIRT, + .pfn = __phys_to_pfn(L3_34XX_PHYS), + .length = L3_34XX_SIZE, .type = MT_DEVICE }, { - .virtual = DSP_IPI_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), - .length = DSP_IPI_24XX_SIZE, + .virtual = L4_34XX_VIRT, + .pfn = __phys_to_pfn(L4_34XX_PHYS), + .length = L4_34XX_SIZE, .type = MT_DEVICE }, { - .virtual = DSP_MMU_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), - .length = DSP_MMU_24XX_SIZE, + .virtual = L4_WK_34XX_VIRT, + .pfn = __phys_to_pfn(L4_WK_34XX_PHYS), + .length = L4_WK_34XX_SIZE, + .type = MT_DEVICE + }, + { + .virtual = OMAP34XX_GPMC_VIRT, + .pfn = __phys_to_pfn(OMAP34XX_GPMC_PHYS), + .length = OMAP34XX_GPMC_SIZE, + .type = MT_DEVICE + }, + { + .virtual = OMAP343X_SMS_VIRT, + .pfn = __phys_to_pfn(OMAP343X_SMS_PHYS), + .length = OMAP343X_SMS_SIZE, + .type = MT_DEVICE + }, + { + .virtual = OMAP343X_SDRC_VIRT, + .pfn = __phys_to_pfn(OMAP343X_SDRC_PHYS), + .length = OMAP343X_SDRC_SIZE, .type = MT_DEVICE - } + }, + { + .virtual = L4_PER_34XX_VIRT, + .pfn = __phys_to_pfn(L4_PER_34XX_PHYS), + .length = L4_PER_34XX_SIZE, + .type = MT_DEVICE + }, + { + .virtual = L4_EMU_34XX_VIRT, + .pfn = __phys_to_pfn(L4_EMU_34XX_PHYS), + .length = L4_EMU_34XX_SIZE, + .type = MT_DEVICE + }, }; +#endif void __init omap2_map_common_io(void) { - iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc)); +#if defined(CONFIG_ARCH_OMAP2420) + iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); + iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc)); +#endif + +#if defined(CONFIG_ARCH_OMAP2430) + iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); + iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc)); +#endif + +#if defined(CONFIG_ARCH_OMAP34XX) + iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc)); +#endif /* Normally devicemaps_init() would flush caches and tlb after * mdesc->map_io(), but we must also do it here because of the CPU @@ -112,11 +201,6 @@ void __init omap2_init_common_hw(void) pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); omap2_clk_init(); -/* - * Need to Fix this for 2430 - */ -#ifndef CONFIG_ARCH_OMAP2430 omap2_init_memory(); -#endif gpmc_init(); } diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index c39e26dc5ee..d354e0fe447 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -128,6 +128,8 @@ void __init omap_init_irq(void) if (cpu_is_omap24xx()) bank->base_reg = OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE); + else if (cpu_is_omap34xx()) + bank->base_reg = OMAP2_IO_ADDRESS(OMAP34XX_IC_BASE); omap_irq_bank_init_one(bank); diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c index 6b49cc9cbdc..48b01f4cebc 100644 --- a/arch/arm/mach-omap2/memory.c +++ b/arch/arm/mach-omap2/memory.c @@ -102,6 +102,17 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force) return prev; } +#if !defined(CONFIG_ARCH_OMAP2) +void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, + u32 base_cs, u32 force_unlock) +{ +} +void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, + u32 mem_type) +{ +} +#endif + void omap2_init_memory_params(u32 force_lock_to_unlock_mode) { unsigned long dll_cnt; @@ -166,6 +177,9 @@ void __init omap2_init_memory(void) { u32 l; + if (!cpu_is_omap2420()) + return; + l = sms_read_reg(SMS_SYSCONFIG); l &= ~(0x3 << 3); l |= (0x2 << 3); diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 6188e2f9785..5558803cd99 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -298,13 +298,13 @@ MUX_CFG_34XX("T2_3430_USB2HS_PHY_D7", 0x1d6, /* TLL - HSUSB: 12-pin TLL Port 1*/ MUX_CFG_34XX("Y8_3430_USB1HS_TLL_CLK", 0x5da, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("Y9_3430_USB1HS_TLL_STP", 0x5d8, OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("Y9_3430_USB1HS_TLL_STP", 0x5d8, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP) MUX_CFG_34XX("AA14_3430_USB1HS_TLL_DIR", 0x5ec, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AA11_3430_USB1HS_TLL_NXT", 0x5ee, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("W13_3430_USB1HS_TLL_D0", 0x5dc, OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("W12_3430_USB1HS_TLL_D1", 0x5de, @@ -324,13 +324,13 @@ MUX_CFG_34XX("Y13_3430_USB1HS_TLL_D7", 0x5e2, /* TLL - HSUSB: 12-pin TLL Port 2*/ MUX_CFG_34XX("AA8_3430_USB2HS_TLL_CLK", 0x5f0, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AA10_3430_USB2HS_TLL_STP", 0x5f2, OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AA10_3430_USB2HS_TLL_STP", 0x5f2, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP) MUX_CFG_34XX("AA9_3430_USB2HS_TLL_DIR", 0x5f4, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AB11_3430_USB2HS_TLL_NXT", 0x5f6, - OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AB10_3430_USB2HS_TLL_D0", 0x5f8, OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AB9_3430_USB2HS_TLL_D1", 0x5fa, @@ -350,13 +350,13 @@ MUX_CFG_34XX("T2_3430_USB2HS_TLL_D7", 0x1d6, /* TLL - HSUSB: 12-pin TLL Port 3*/ MUX_CFG_34XX("AA6_3430_USB3HS_TLL_CLK", 0x180, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) -MUX_CFG_34XX("AB3_3430_USB3HS_TLL_STP", 0x166, OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AB3_3430_USB3HS_TLL_STP", 0x166, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLUP) MUX_CFG_34XX("AA3_3430_USB3HS_TLL_DIR", 0x168, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("Y3_3430_USB3HS_TLL_NXT", 0x16a, - OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AA5_3430_USB3HS_TLL_D0", 0x186, OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("Y4_3430_USB3HS_TLL_D1", 0x184, @@ -373,6 +373,49 @@ MUX_CFG_34XX("AA13_3430_USB3HS_TLL_D6", 0x170, OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) MUX_CFG_34XX("AA12_3430_USB3HS_TLL_D7", 0x172, OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) + +/* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */ +MUX_CFG_34XX("AF10_3430_USB1FS_PHY_MM1_RXDP", 0x5d8, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AG9_3430_USB1FS_PHY_MM1_RXDM", 0x5ee, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("W13_3430_USB1FS_PHY_MM1_RXRCV", 0x5dc, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("W12_3430_USB1FS_PHY_MM1_TXSE0", 0x5de, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("W11_3430_USB1FS_PHY_MM1_TXDAT", 0x5e0, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("Y11_3430_USB1FS_PHY_MM1_TXEN_N", 0x5ea, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) + +/* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */ +MUX_CFG_34XX("AF7_3430_USB2FS_PHY_MM2_RXDP", 0x5f2, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AH7_3430_USB2FS_PHY_MM2_RXDM", 0x5f6, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AB10_3430_USB2FS_PHY_MM2_RXRCV", 0x5f8, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AB9_3430_USB2FS_PHY_MM2_TXSE0", 0x5fa, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("W3_3430_USB2FS_PHY_MM2_TXDAT", 0x1d4, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("T4_3430_USB2FS_PHY_MM2_TXEN_N", 0x1de, + OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT) + +/* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */ +MUX_CFG_34XX("AH3_3430_USB3FS_PHY_MM3_RXDP", 0x166, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AE3_3430_USB3FS_PHY_MM3_RXDM", 0x16a, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AD1_3430_USB3FS_PHY_MM3_RXRCV", 0x186, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AE1_3430_USB3FS_PHY_MM3_TXSE0", 0x184, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AD2_3430_USB3FS_PHY_MM3_TXDAT", 0x188, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("AC1_3430_USB3FS_PHY_MM3_TXEN_N", 0x18a, + OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT) + }; #define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins) diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S new file mode 100644 index 00000000000..2c714613634 --- /dev/null +++ b/arch/arm/mach-omap2/sram34xx.S @@ -0,0 +1,179 @@ +/* + * linux/arch/arm/mach-omap3/sram.S + * + * Omap3 specific functions that need to be run in internal SRAM + * + * (C) Copyright 2007 + * Texas Instruments Inc. + * Rajendra Nayak + * + * (C) Copyright 2004 + * Texas Instruments, + * Richard Woodruff + * + * 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 "sdrc.h" +#include "cm.h" + + .text + +/* + * Change frequency of core dpll + * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2 + */ +ENTRY(omap3_sram_configure_core_dpll) + stmfd sp!, {r1-r12, lr} @ store regs to stack + cmp r3, #0x2 + blne configure_sdrc + cmp r3, #0x2 + blne lock_dll + cmp r3, #0x1 + blne unlock_dll + bl sdram_in_selfrefresh @ put the SDRAM in self refresh + bl configure_core_dpll + bl enable_sdrc + cmp r3, #0x1 + blne wait_dll_unlock + cmp r3, #0x2 + blne wait_dll_lock + cmp r3, #0x1 + blne configure_sdrc + mov r0, #0 @ return value + ldmfd sp!, {r1-r12, pc} @ restore regs and return +unlock_dll: + ldr r4, omap3_sdrc_dlla_ctrl + ldr r5, [r4] + orr r5, r5, #0x4 + str r5, [r4] + bx lr +lock_dll: + ldr r4, omap3_sdrc_dlla_ctrl + ldr r5, [r4] + bic r5, r5, #0x4 + str r5, [r4] + bx lr +sdram_in_selfrefresh: + mov r5, #0x0 @ Move 0 to R5 + mcr p15, 0, r5, c7, c10, 5 @ memory barrier + ldr r4, omap3_sdrc_power @ read the SDRC_POWER register + ldr r5, [r4] @ read the contents of SDRC_POWER + orr r5, r5, #0x40 @ enable self refresh on idle req + str r5, [r4] @ write back to SDRC_POWER register + ldr r4, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg + ldr r5, [r4] + bic r5, r5, #0x2 @ disable iclk bit for SRDC + str r5, [r4] +wait_sdrc_idle: + ldr r4, omap3_cm_idlest1_core + ldr r5, [r4] + and r5, r5, #0x2 @ check for SDRC idle + cmp r5, #2 + bne wait_sdrc_idle + bx lr +configure_core_dpll: + ldr r4, omap3_cm_clksel1_pll + ldr r5, [r4] + ldr r6, core_m2_mask_val @ modify m2 for core dpll + and r5, r5, r6 + orr r5, r5, r3, lsl #0x1B @ r3 contains the M2 val + str r5, [r4] + mov r5, #0x800 @ wait for the clock to stabilise + cmp r3, #2 + bne wait_clk_stable + bx lr +wait_clk_stable: + subs r5, r5, #1 + bne wait_clk_stable + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + bx lr +enable_sdrc: + ldr r4, omap3_cm_iclken1_core + ldr r5, [r4] + orr r5, r5, #0x2 @ enable iclk bit for SDRC + str r5, [r4] +wait_sdrc_idle1: + ldr r4, omap3_cm_idlest1_core + ldr r5, [r4] + and r5, r5, #0x2 + cmp r5, #0 + bne wait_sdrc_idle1 + ldr r4, omap3_sdrc_power + ldr r5, [r4] + bic r5, r5, #0x40 + str r5, [r4] + bx lr +wait_dll_lock: + ldr r4, omap3_sdrc_dlla_status + ldr r5, [r4] + and r5, r5, #0x4 + cmp r5, #0x4 + bne wait_dll_lock + bx lr +wait_dll_unlock: + ldr r4, omap3_sdrc_dlla_status + ldr r5, [r4] + and r5, r5, #0x4 + cmp r5, #0x0 + bne wait_dll_unlock + bx lr +configure_sdrc: + ldr r4, omap3_sdrc_rfr_ctrl + str r0, [r4] + ldr r4, omap3_sdrc_actim_ctrla + str r1, [r4] + ldr r4, omap3_sdrc_actim_ctrlb + str r2, [r4] + bx lr + +omap3_sdrc_power: + .word OMAP34XX_SDRC_REGADDR(SDRC_POWER) +omap3_cm_clksel1_pll: + .word OMAP34XX_CM_REGADDR(PLL_MOD, CM_CLKSEL1) +omap3_cm_idlest1_core: + .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST) +omap3_cm_iclken1_core: + .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1) +omap3_sdrc_rfr_ctrl: + .word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0) +omap3_sdrc_actim_ctrla: + .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_0) +omap3_sdrc_actim_ctrlb: + .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_0) +omap3_sdrc_dlla_status: + .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS) +omap3_sdrc_dlla_ctrl: + .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) +core_m2_mask_val: + .word 0x07FFFFFF + +ENTRY(omap3_sram_configure_core_dpll_sz) + .word . - omap3_sram_configure_core_dpll diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ef62bf21e17..a94f0c44ebc 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -15,6 +15,9 @@ config ARCH_OMAP1 config ARCH_OMAP2 bool "TI OMAP2" +config ARCH_OMAP3 + bool "TI OMAP3" + endchoice comment "OMAP Feature Selections" @@ -112,13 +115,13 @@ config OMAP_MPU_TIMER config OMAP_32K_TIMER bool "Use 32KHz timer" - depends on ARCH_OMAP16XX || ARCH_OMAP24XX + depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX help Select this option if you want to enable the OMAP 32KHz timer. This timer saves power compared to the OMAP_MPU_TIMER, and has support for no tick during idle. The 32KHz timer provides less intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is - currently only available for OMAP16XX and 24XX. + currently only available for OMAP16XX, 24XX and 34XX. endchoice @@ -133,7 +136,7 @@ config OMAP_32K_TIMER_HZ config OMAP_DM_TIMER bool "Use dual-mode timer" - depends on ARCH_OMAP16XX || ARCH_OMAP24XX + depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX help Select this option if you want to use OMAP Dual-Mode timers. diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 1c1d831a0c0..2625ce32e60 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -94,6 +94,10 @@ static inline void omap_init_dsp(void) { } static void omap_init_kp(void) { + /* 2430 and 34xx keypad is on TWL4030 */ + if (cpu_is_omap2430() || cpu_is_omap34xx()) + return; + if (machine_is_omap_h2() || machine_is_omap_h3()) { omap_cfg_reg(F18_1610_KBC0); omap_cfg_reg(D20_1610_KBC1); @@ -395,8 +399,17 @@ static inline void omap_init_uwire(void) {} #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) -#ifdef CONFIG_ARCH_OMAP24XX +#if defined(CONFIG_ARCH_OMAP34XX) +#define OMAP_WDT_BASE 0x48314000 +#elif defined(CONFIG_ARCH_OMAP24XX) + +#ifdef CONFIG_ARCH_OMAP2430 +/* WDT2 */ +#define OMAP_WDT_BASE 0x49016000 +#else #define OMAP_WDT_BASE 0x48022000 +#endif + #else #define OMAP_WDT_BASE 0xfffeb000 #endif diff --git a/arch/arm/plat-omap/include/mach/debug-macro.S b/arch/arm/plat-omap/include/mach/debug-macro.S index 1b0039bdeb4..1b11f5c6a2d 100644 --- a/arch/arm/plat-omap/include/mach/debug-macro.S +++ b/arch/arm/plat-omap/include/mach/debug-macro.S @@ -35,6 +35,18 @@ #ifdef CONFIG_OMAP_LL_DEBUG_UART3 add \rx, \rx, #0x00004000 @ UART 3 #endif + +#elif CONFIG_ARCH_OMAP3 + moveq \rx, #0x48000000 @ physical base address + movne \rx, #0xd8000000 @ virtual base + orr \rx, \rx, #0x0006a000 +#ifdef CONFIG_OMAP_LL_DEBUG_UART2 + add \rx, \rx, #0x00002000 @ UART 2 +#endif +#ifdef CONFIG_OMAP_LL_DEBUG_UART3 + add \rx, \rx, #0x00fb0000 @ UART 3 + add \rx, \rx, #0x00006000 +#endif #endif .endm diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S index d4e9043bf20..030118ee204 100644 --- a/arch/arm/plat-omap/include/mach/entry-macro.S +++ b/arch/arm/plat-omap/include/mach/entry-macro.S @@ -55,9 +55,17 @@ 1510: .endm -#elif defined(CONFIG_ARCH_OMAP24XX) +#endif +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) #include +#endif +#if defined(CONFIG_ARCH_OMAP34XX) +#include +#endif + +#define INTCPS_SIR_IRQ_OFFSET 0x0040 /* Active interrupt number */ .macro disable_fiq .endm @@ -79,7 +87,7 @@ ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ cmp \irqnr, #0x0 2222: - ldrne \irqnr, [\base, #IRQ_SIR_IRQ] + ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] .endm diff --git a/arch/arm/plat-omap/include/mach/gpmc.h b/arch/arm/plat-omap/include/mach/gpmc.h index 3c7b425c585..45b678439bb 100644 --- a/arch/arm/plat-omap/include/mach/gpmc.h +++ b/arch/arm/plat-omap/include/mach/gpmc.h @@ -84,6 +84,10 @@ struct gpmc_timings { u16 access; /* Start-cycle to first data valid delay */ u16 rd_cycle; /* Total read cycle time */ u16 wr_cycle; /* Total write cycle time */ + + /* The following are only on OMAP3430 */ + u16 wr_access; /* WRACCESSTIME */ + u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */ }; extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h index dd0cf069431..adc83b7b820 100644 --- a/arch/arm/plat-omap/include/mach/io.h +++ b/arch/arm/plat-omap/include/mach/io.h @@ -73,7 +73,6 @@ #define L4_24XX_VIRT 0xd8000000 #define L4_24XX_SIZE SZ_1M /* 1MB of 128MB used, want 1MB sect */ -#ifdef CONFIG_ARCH_OMAP2430 #define L4_WK_243X_PHYS L4_WK_243X_BASE /* 0x49000000 */ #define L4_WK_243X_VIRT 0xd9000000 #define L4_WK_243X_SIZE SZ_1M @@ -87,8 +86,6 @@ #define OMAP243X_SMS_VIRT 0xFC000000 #define OMAP243X_SMS_SIZE SZ_1M -#endif - #define IO_OFFSET 0x90000000 #define __IO_ADDRESS(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */ #define __OMAP2_IO_ADDRESS(pa) ((pa) + IO_OFFSET) /* Works for L3 and L4 */ diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index e9fd63055cb..9ee04969d36 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -286,6 +286,41 @@ #define INT_24XX_USB_IRQ_OTG 80 #define INT_24XX_MMC_IRQ 83 +#define INT_34XX_BENCH_MPU_EMUL 3 +#define INT_34XX_ST_MCBSP2_IRQ 4 +#define INT_34XX_ST_MCBSP3_IRQ 5 +#define INT_34XX_SSM_ABORT_IRQ 6 +#define INT_34XX_SYS_NIRQ 7 +#define INT_34XX_D2D_FW_IRQ 8 +#define INT_34XX_PRCM_MPU_IRQ 11 +#define INT_34XX_MCBSP1_IRQ 16 +#define INT_34XX_MCBSP2_IRQ 17 +#define INT_34XX_MCBSP3_IRQ 22 +#define INT_34XX_MCBSP4_IRQ 23 +#define INT_34XX_CAM_IRQ 24 +#define INT_34XX_MCBSP5_IRQ 27 +#define INT_34XX_GPIO_BANK1 29 +#define INT_34XX_GPIO_BANK2 30 +#define INT_34XX_GPIO_BANK3 31 +#define INT_34XX_GPIO_BANK4 32 +#define INT_34XX_GPIO_BANK5 33 +#define INT_34XX_GPIO_BANK6 34 +#define INT_34XX_USIM_IRQ 35 +#define INT_34XX_WDT3_IRQ 36 +#define INT_34XX_SPI4_IRQ 48 +#define INT_34XX_SHA1MD52_IRQ 49 +#define INT_34XX_FPKA_READY_IRQ 50 +#define INT_34XX_SHA1MD51_IRQ 51 +#define INT_34XX_RNG_IRQ 52 +#define INT_34XX_I2C3_IRQ 61 +#define INT_34XX_FPKA_ERROR_IRQ 64 +#define INT_34XX_PBIAS_IRQ 75 +#define INT_34XX_OHCI_IRQ 76 +#define INT_34XX_EHCI_IRQ 77 +#define INT_34XX_TLL_IRQ 78 +#define INT_34XX_PARTHASH_IRQ 79 +#define INT_34XX_MMC3_IRQ 94 +#define INT_34XX_GPT12_IRQ 95 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and * 16 MPUIO lines */ #define OMAP_MAX_GPIO_LINES 192 diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index a3074f2fb7c..c8d0aa118be 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -91,7 +91,7 @@ #define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX #define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX -#elif defined(CONFIG_ARCH_OMAP24XX) +#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #define OMAP_MCBSP_REG_DRR2 0x00 #define OMAP_MCBSP_REG_DRR1 0x04 diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h index a325caf80d0..d40cac60b95 100644 --- a/arch/arm/plat-omap/include/mach/memory.h +++ b/arch/arm/plat-omap/include/mach/memory.h @@ -38,7 +38,7 @@ */ #if defined(CONFIG_ARCH_OMAP1) #define PHYS_OFFSET UL(0x10000000) -#elif defined(CONFIG_ARCH_OMAP2) +#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) #define PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h index 5670d563f37..6bbf1789bed 100644 --- a/arch/arm/plat-omap/include/mach/mux.h +++ b/arch/arm/plat-omap/include/mach/mux.h @@ -723,7 +723,31 @@ enum omap34xx_index { AB12_3430_USB3HS_TLL_DATA4, AB13_3430_USB3HS_TLL_DATA5, AA13_3430_USB3HS_TLL_DATA6, - AA12_3430_USB3HS_TLL_DATA7 + AA12_3430_USB3HS_TLL_DATA7, + + /* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */ + AF10_3430_USB1FS_PHY_MM1_RXDP, + AG9_3430_USB1FS_PHY_MM1_RXDM, + W13_3430_USB1FS_PHY_MM1_RXRCV, + W12_3430_USB1FS_PHY_MM1_TXSE0, + W11_3430_USB1FS_PHY_MM1_TXDAT, + Y11_3430_USB1FS_PHY_MM1_TXEN_N, + + /* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */ + AF7_3430_USB2FS_PHY_MM2_RXDP, + AH7_3430_USB2FS_PHY_MM2_RXDM, + AB10_3430_USB2FS_PHY_MM2_RXRCV, + AB9_3430_USB2FS_PHY_MM2_TXSE0, + W3_3430_USB2FS_PHY_MM2_TXDAT, + T4_3430_USB2FS_PHY_MM2_TXEN_N, + + /* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */ + AH3_3430_USB3FS_PHY_MM3_RXDP, + AE3_3430_USB3FS_PHY_MM3_RXDM, + AD1_3430_USB3FS_PHY_MM3_RXRCV, + AE1_3430_USB3FS_PHY_MM3_TXSE0, + AD2_3430_USB3FS_PHY_MM3_TXDAT, + AC1_3430_USB3FS_PHY_MM3_TXEN_N, }; diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 556f0eb4d55..24335d4932f 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -39,7 +39,6 @@ /* interrupt controller */ #define OMAP24XX_IC_BASE (L4_24XX_BASE + 0xfe000) #define OMAP24XX_IVA_INTC_BASE 0x40000000 -#define IRQ_SIR_IRQ 0x0040 #define OMAP2420_CTRL_BASE L4_24XX_BASE #define OMAP2420_32KSYNCT_BASE (L4_24XX_BASE + 0x4000) diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h index 25ee3819faa..a98c6c3beb2 100644 --- a/arch/arm/plat-omap/include/mach/sdrc.h +++ b/arch/arm/plat-omap/include/mach/sdrc.h @@ -25,8 +25,8 @@ #define SDRC_DLLB_STATUS 0x06C #define SDRC_POWER 0x070 #define SDRC_MR_0 0x084 -#define SDRC_ACTIM_CTRL_A 0x09c -#define SDRC_ACTIM_CTRL_B 0x0a0 +#define SDRC_ACTIM_CTRL_A_0 0x09c +#define SDRC_ACTIM_CTRL_B_0 0x0a0 #define SDRC_RFR_CTRL_0 0x0a4 /* diff --git a/arch/arm/plat-omap/include/mach/sram.h b/arch/arm/plat-omap/include/mach/sram.h index e0932344998..ab35d622dcf 100644 --- a/arch/arm/plat-omap/include/mach/sram.h +++ b/arch/arm/plat-omap/include/mach/sram.h @@ -21,6 +21,10 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type); extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); +extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, + u32 sdrc_actim_ctrla, + u32 sdrc_actim_ctrlb, u32 m2); + /* Do not use these */ extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl); extern unsigned long omap1_sram_reprogram_clock_sz; @@ -53,4 +57,10 @@ extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type); extern unsigned long omap243x_sram_reprogram_sdrc_sz; + +extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl, + u32 sdrc_actim_ctrla, + u32 sdrc_actim_ctrlb, u32 m2); +extern unsigned long omap3_sram_configure_core_dpll_sz; + #endif diff --git a/arch/arm/plat-omap/include/mach/system.h b/arch/arm/plat-omap/include/mach/system.h index 06a28c7b98d..06923f26154 100644 --- a/arch/arm/plat-omap/include/mach/system.h +++ b/arch/arm/plat-omap/include/mach/system.h @@ -40,7 +40,7 @@ static inline void omap1_arch_reset(char mode) static inline void arch_reset(char mode) { - if (!cpu_is_omap24xx()) + if (!cpu_class_is_omap2()) omap1_arch_reset(mode); else omap_prcm_arch_reset(mode); diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c index 0253c456ed5..af326efc1ad 100644 --- a/arch/arm/plat-omap/io.c +++ b/arch/arm/plat-omap/io.c @@ -47,11 +47,13 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) } #endif #ifdef CONFIG_ARCH_OMAP2 - if (cpu_class_is_omap2()) { + if (cpu_is_omap24xx()) { if (BETWEEN(p, L3_24XX_PHYS, L3_24XX_SIZE)) return XLATE(p, L3_24XX_PHYS, L3_24XX_VIRT); if (BETWEEN(p, L4_24XX_PHYS, L4_24XX_SIZE)) return XLATE(p, L4_24XX_PHYS, L4_24XX_VIRT); + } + if (cpu_is_omap2420()) { if (BETWEEN(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_SIZE)) return XLATE(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_VIRT); if (BETWEEN(p, DSP_IPI_24XX_PHYS, DSP_IPI_24XX_SIZE)) @@ -59,14 +61,36 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) if (BETWEEN(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_SIZE)) return XLATE(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_VIRT); } -#ifdef CONFIG_ARCH_OMAP2430 if (cpu_is_omap2430()) { if (BETWEEN(p, L4_WK_243X_PHYS, L4_WK_243X_SIZE)) - return XLATE(L4_WK_243X_PHYS, L4_WK_243X_VIRT); + return XLATE(p, L4_WK_243X_PHYS, L4_WK_243X_VIRT); if (BETWEEN(p, OMAP243X_GPMC_PHYS, OMAP243X_GPMC_SIZE)) - return XLATE(OMAP243X_GPMC_PHYS, OMAP243X_GPMC_VIRT); + return XLATE(p, OMAP243X_GPMC_PHYS, OMAP243X_GPMC_VIRT); + if (BETWEEN(p, OMAP243X_SDRC_PHYS, OMAP243X_SDRC_SIZE)) + return XLATE(p, OMAP243X_SDRC_PHYS, OMAP243X_SDRC_VIRT); + if (BETWEEN(p, OMAP243X_SMS_PHYS, OMAP243X_SMS_SIZE)) + return XLATE(p, OMAP243X_SMS_PHYS, OMAP243X_SMS_VIRT); } #endif +#ifdef CONFIG_ARCH_OMAP3 + if (cpu_is_omap34xx()) { + if (BETWEEN(p, L3_34XX_PHYS, L3_34XX_SIZE)) + return XLATE(p, L3_34XX_PHYS, L3_34XX_VIRT); + if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE)) + return XLATE(p, L4_34XX_PHYS, L4_34XX_VIRT); + if (BETWEEN(p, L4_WK_34XX_PHYS, L4_WK_34XX_SIZE)) + return XLATE(p, L4_WK_34XX_PHYS, L4_WK_34XX_VIRT); + if (BETWEEN(p, OMAP34XX_GPMC_PHYS, OMAP34XX_GPMC_SIZE)) + return XLATE(p, OMAP34XX_GPMC_PHYS, OMAP34XX_GPMC_VIRT); + if (BETWEEN(p, OMAP343X_SMS_PHYS, OMAP343X_SMS_SIZE)) + return XLATE(p, OMAP343X_SMS_PHYS, OMAP343X_SMS_VIRT); + if (BETWEEN(p, OMAP343X_SDRC_PHYS, OMAP343X_SDRC_SIZE)) + return XLATE(p, OMAP343X_SDRC_PHYS, OMAP343X_SDRC_VIRT); + if (BETWEEN(p, L4_PER_34XX_PHYS, L4_PER_34XX_SIZE)) + return XLATE(p, L4_PER_34XX_PHYS, L4_PER_34XX_VIRT); + if (BETWEEN(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_SIZE)) + return XLATE(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_VIRT); + } #endif return __arm_ioremap(p, size, type); diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index ac67eeb6ca6..4d22452a074 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -271,7 +271,7 @@ int __init omap1_sram_init(void) #define omap1_sram_init() do {} while (0) #endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, u32 base_cs, u32 force_unlock); @@ -352,23 +352,19 @@ static inline int omap243x_sram_init(void) #ifdef CONFIG_ARCH_OMAP3 -static u32 (*_omap2_sram_reprogram_gpmc)(u32 perf_level); -u32 omap2_sram_reprogram_gpmc(u32 perf_level) -{ - if (!_omap2_sram_reprogram_gpmc) - omap_sram_error(); - - return _omap2_sram_reprogram_gpmc(perf_level); -} - -static u32 (*_omap2_sram_configure_core_dpll)(u32 m, u32 n, - u32 freqsel, u32 m2); -u32 omap2_sram_configure_core_dpll(u32 m, u32 n, u32 freqsel, u32 m2) +static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, + u32 sdrc_actim_ctrla, + u32 sdrc_actim_ctrlb, + u32 m2); +u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, + u32 sdrc_actim_ctrlb, u32 m2) { - if (!_omap2_sram_configure_core_dpll) + if (!_omap3_sram_configure_core_dpll) omap_sram_error(); - return _omap2_sram_configure_core_dpll(m, n, freqsel, m2); + return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, + sdrc_actim_ctrla, + sdrc_actim_ctrlb, m2); } /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */ @@ -376,31 +372,16 @@ void restore_sram_functions(void) { omap_sram_ceil = omap_sram_base + omap_sram_size; - _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc, - omap34xx_sram_reprogram_gpmc_sz); - - _omap2_sram_configure_core_dpll = - omap_sram_push(omap34xx_sram_configure_core_dpll, - omap34xx_sram_configure_core_dpll_sz); + _omap3_sram_configure_core_dpll = + omap_sram_push(omap3_sram_configure_core_dpll, + omap3_sram_configure_core_dpll_sz); } int __init omap34xx_sram_init(void) { - _omap2_sram_ddr_init = omap_sram_push(omap34xx_sram_ddr_init, - omap34xx_sram_ddr_init_sz); - - _omap2_sram_reprogram_sdrc = omap_sram_push(omap34xx_sram_reprogram_sdrc, - omap34xx_sram_reprogram_sdrc_sz); - - _omap2_set_prcm = omap_sram_push(omap34xx_sram_set_prcm, - omap34xx_sram_set_prcm_sz); - - _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc, - omap34xx_sram_reprogram_gpmc_sz); - - _omap2_sram_configure_core_dpll = - omap_sram_push(omap34xx_sram_configure_core_dpll, - omap34xx_sram_configure_core_dpll_sz); + _omap3_sram_configure_core_dpll = + omap_sram_push(omap3_sram_configure_core_dpll, + omap3_sram_configure_core_dpll_sz); return 0; } -- GitLab From 2885f00049f80287b14192145699774fa55c14f7 Mon Sep 17 00:00:00 2001 From: "Syed Mohammed, Khasim" Date: Thu, 9 Oct 2008 17:51:42 +0300 Subject: [PATCH 3536/5416] ARM: OMAP3: Add minimal Beagle board support Add minimal Beagle board support. Based on earlier patches by Syed Mohammed Khasim with some fixes from linux-omap tree. Signed-off-by: Syed Mohammed Khasim Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 4 + arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/board-omap3beagle.c | 244 ++++++++++++++++++ arch/arm/mm/Kconfig | 2 +- .../include/mach/board-omap3beagle.h | 33 +++ arch/arm/plat-omap/include/mach/hardware.h | 4 + 6 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-omap2/board-omap3beagle.c create mode 100644 arch/arm/plat-omap/include/mach/board-omap3beagle.h diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index e2481e4045e..23fd1cc034a 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -44,3 +44,7 @@ config MACH_OMAP_2430SDP bool "OMAP 2430 SDP board" depends on ARCH_OMAP2 && ARCH_OMAP24XX +config MACH_OMAP3_BEAGLE + bool "OMAP3 BEAGLE board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 0dc40db3811..420ad9acceb 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -29,4 +29,5 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o +obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c new file mode 100644 index 00000000000..baa79674e9d --- /dev/null +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -0,0 +1,244 @@ +/* + * linux/arch/arm/mach-omap2/board-omap3beagle.c + * + * Copyright (C) 2008 Texas Instruments + * + * Modified from mach-omap2/board-3430sdp.c + * + * Initial code: Syed Mohammed Khasim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 + +#define NAND_BLOCK_SIZE SZ_128K + +static struct mtd_partition omap3beagle_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = "X-Loader", + .offset = 0, + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ + .size = 15 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot Env", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */ + .size = 1 * NAND_BLOCK_SIZE, + }, + { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ + .size = 32 * NAND_BLOCK_SIZE, + }, + { + .name = "File System", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_nand_platform_data omap3beagle_nand_data = { + .options = NAND_BUSWIDTH_16, + .parts = omap3beagle_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .nand_setup = NULL, + .dev_ready = NULL, +}; + +static struct resource omap3beagle_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device omap3beagle_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &omap3beagle_nand_data, + }, + .num_resources = 1, + .resource = &omap3beagle_nand_resource, +}; + +static struct omap_uart_config omap3_beagle_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static void __init omap3_beagle_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); +} + +static struct platform_device omap3_beagle_lcd_device = { + .name = "omap3beagle_lcd", + .id = -1, +}; + +static struct omap_lcd_config omap3_beagle_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct gpio_led gpio_leds[] = { + { + .name = "beagleboard::usr0", + .default_trigger = "heartbeat", + .gpio = 150, + }, + { + .name = "beagleboard::usr1", + .default_trigger = "mmc0", + .gpio = 149, + }, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device leds_gpio = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_led_info, + }, +}; + +static struct gpio_keys_button gpio_buttons[] = { + { + .code = BTN_EXTRA, + .gpio = 7, + .desc = "user", + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data gpio_key_info = { + .buttons = gpio_buttons, + .nbuttons = ARRAY_SIZE(gpio_buttons), +}; + +static struct platform_device keys_gpio = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &gpio_key_info, + }, +}; + +static struct omap_board_config_kernel omap3_beagle_config[] __initdata = { + { OMAP_TAG_UART, &omap3_beagle_uart_config }, + { OMAP_TAG_LCD, &omap3_beagle_lcd_config }, +}; + +static struct platform_device *omap3_beagle_devices[] __initdata = { + &omap3_beagle_lcd_device, + &leds_gpio, + &keys_gpio, +}; + +static void __init omap3beagle_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3beagle_nand_data.cs = nandcs; + omap3beagle_nand_data.gpmc_cs_baseaddr = (void *) + (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); + omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (platform_device_register(&omap3beagle_nand_device) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + +static void __init omap3_beagle_init(void) +{ + platform_add_devices(omap3_beagle_devices, + ARRAY_SIZE(omap3_beagle_devices)); + omap_board_config = omap3_beagle_config; + omap_board_config_size = ARRAY_SIZE(omap3_beagle_config); + omap_serial_init(); + omap3beagle_flash_init(); +} + +static void __init omap3_beagle_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") + /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3_beagle_map_io, + .init_irq = omap3_beagle_init_irq, + .init_machine = omap3_beagle_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ed15f876c72..546d7e7db74 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -428,7 +428,7 @@ config CPU_32v6K # ARMv7 config CPU_V7 bool "Support ARM V7 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB + depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP3 select CPU_32v6K select CPU_32v7 select CPU_ABRT_EV7 diff --git a/arch/arm/plat-omap/include/mach/board-omap3beagle.h b/arch/arm/plat-omap/include/mach/board-omap3beagle.h new file mode 100644 index 00000000000..3080d52d877 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/board-omap3beagle.h @@ -0,0 +1,33 @@ +/* + * arch/arm/plat-omap/include/mach/board-omap3beagle.h + * + * Hardware definitions for TI OMAP3 BEAGLE. + * + * Initial creation by Syed Mohammed Khasim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OMAP3_BEAGLE_H +#define __ASM_ARCH_OMAP3_BEAGLE_H + +#endif /* __ASM_ARCH_OMAP3_BEAGLE_H */ + diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 29c849f5f18..80f6d7ec53e 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -322,6 +322,10 @@ #include "board-2430sdp.h" #endif +#ifdef CONFIG_MACH_OMAP3_BEAGLE +#include "board-omap3beagle.h" +#endif + #ifdef CONFIG_MACH_OMAP_APOLLON #include "board-apollon.h" #endif -- GitLab From 22b401bfa9a02650362aa376ae73fd3db7546d3c Mon Sep 17 00:00:00 2001 From: "Syed Mohammed, Khasim" Date: Thu, 9 Oct 2008 17:51:42 +0300 Subject: [PATCH 3537/5416] ARM: OMAP3: Add Beagle defconfig Add Beagle defconfig Signed-off-by: Syed Mohammed, Khasim Signed-off-by: Tony Lindgren --- arch/arm/configs/omap3_beagle_defconfig | 1321 +++++++++++++++++++++++ 1 file changed, 1321 insertions(+) create mode 100644 arch/arm/configs/omap3_beagle_defconfig diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig new file mode 100644 index 00000000000..e042d27eae1 --- /dev/null +++ b/arch/arm/configs/omap3_beagle_defconfig @@ -0,0 +1,1321 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc8 +# Wed Oct 1 17:14:22 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM7X00A is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +# CONFIG_OMAP_MUX is not set +# CONFIG_OMAP_MCBSP is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_ISP1301_OMAP is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +CONFIG_USB_MUSB_HOST=y +# CONFIG_USB_MUSB_PERIPHERAL is not set +# CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA25X is not set +CONFIG_USB_GADGET_M66592=y +CONFIG_USB_M66592=y +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From eba2645aeb41d430c4601f6624c44bc971488fe2 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Thu, 9 Oct 2008 17:51:43 +0300 Subject: [PATCH 3538/5416] ARM: OMAP3: Add support for the Gumstix Overo board (rev 3) This patch adds minimal overo support. Signed-off-by: Steve Sakoman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 3 + arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/board-overo.c | 242 ++++++++++++++++++ arch/arm/plat-omap/include/mach/board-overo.h | 26 ++ 4 files changed, 272 insertions(+) create mode 100644 arch/arm/mach-omap2/board-overo.c create mode 100644 arch/arm/plat-omap/include/mach/board-overo.h diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 23fd1cc034a..aef043b87b4 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -48,3 +48,6 @@ config MACH_OMAP3_BEAGLE bool "OMAP3 BEAGLE board" depends on ARCH_OMAP3 && ARCH_OMAP34XX +config MACH_OVERO + bool "Gumstix Overo board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 420ad9acceb..feb9caf771d 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -30,4 +30,5 @@ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o +obj-$(CONFIG_MACH_OVERO) += board-overo.o diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c new file mode 100644 index 00000000000..e09aa59a399 --- /dev/null +++ b/arch/arm/mach-omap2/board-overo.c @@ -0,0 +1,242 @@ +/* + * board-overo.c (Gumstix Overo) + * + * Initial code: Steve Sakoman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define NAND_BLOCK_SIZE SZ_128K +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 + +static struct mtd_partition overo_nand_partitions[] = { + { + .name = "xloader", + .offset = 0, /* Offset = 0x00000 */ + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE + }, + { + .name = "uboot", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ + .size = 14 * NAND_BLOCK_SIZE, + }, + { + .name = "uboot environment", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x240000 */ + .size = 2 * NAND_BLOCK_SIZE, + }, + { + .name = "linux", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ + .size = 32 * NAND_BLOCK_SIZE, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_nand_platform_data overo_nand_data = { + .parts = overo_nand_partitions, + .nr_parts = ARRAY_SIZE(overo_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ +}; + +static struct resource overo_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device overo_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &overo_nand_data, + }, + .num_resources = 1, + .resource = &overo_nand_resource, +}; + + +static void __init overo_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + overo_nand_data.cs = nandcs; + overo_nand_data.gpmc_cs_baseaddr = (void *) + (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); + overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (platform_device_register(&overo_nand_device) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} +static struct omap_uart_config overo_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static int __init overo_i2c_init(void) +{ + /* i2c2 pins are used for gpio */ + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + +static void __init overo_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); +} + +static struct platform_device overo_lcd_device = { + .name = "overo_lcd", + .id = -1, +}; + +static struct omap_lcd_config overo_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel overo_config[] __initdata = { + { OMAP_TAG_UART, &overo_uart_config }, + { OMAP_TAG_LCD, &overo_lcd_config }, +}; + +static struct platform_device *overo_devices[] __initdata = { + &overo_lcd_device, +}; + +static void __init overo_init(void) +{ + overo_i2c_init(); + platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices)); + omap_board_config = overo_config; + omap_board_config_size = ARRAY_SIZE(overo_config); + omap_serial_init(); + overo_flash_init(); + + if ((gpio_request(OVERO_GPIO_W2W_NRESET, + "OVERO_GPIO_W2W_NRESET") == 0) && + (gpio_direction_output(OVERO_GPIO_W2W_NRESET, 1) == 0)) { + gpio_export(OVERO_GPIO_W2W_NRESET, 0); + gpio_set_value(OVERO_GPIO_W2W_NRESET, 0); + udelay(10); + gpio_set_value(OVERO_GPIO_W2W_NRESET, 1); + } else { + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_W2W_NRESET\n"); + } + + if ((gpio_request(OVERO_GPIO_BT_XGATE, "OVERO_GPIO_BT_XGATE") == 0) && + (gpio_direction_output(OVERO_GPIO_BT_XGATE, 0) == 0)) + gpio_export(OVERO_GPIO_BT_XGATE, 0); + else + printk(KERN_ERR "could not obtain gpio for OVERO_GPIO_BT_XGATE\n"); + + if ((gpio_request(OVERO_GPIO_BT_NRESET, "OVERO_GPIO_BT_NRESET") == 0) && + (gpio_direction_output(OVERO_GPIO_BT_NRESET, 1) == 0)) { + gpio_export(OVERO_GPIO_BT_NRESET, 0); + gpio_set_value(OVERO_GPIO_BT_NRESET, 0); + mdelay(6); + gpio_set_value(OVERO_GPIO_BT_NRESET, 1); + } else { + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_BT_NRESET\n"); + } + + if ((gpio_request(OVERO_GPIO_USBH_CPEN, "OVERO_GPIO_USBH_CPEN") == 0) && + (gpio_direction_output(OVERO_GPIO_USBH_CPEN, 1) == 0)) + gpio_export(OVERO_GPIO_USBH_CPEN, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_USBH_CPEN\n"); + + if ((gpio_request(OVERO_GPIO_USBH_NRESET, + "OVERO_GPIO_USBH_NRESET") == 0) && + (gpio_direction_output(OVERO_GPIO_USBH_NRESET, 1) == 0)) + gpio_export(OVERO_GPIO_USBH_NRESET, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_USBH_NRESET\n"); +} + +static void __init overo_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OVERO, "Gumstix Overo") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = overo_map_io, + .init_irq = overo_init_irq, + .init_machine = overo_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/plat-omap/include/mach/board-overo.h b/arch/arm/plat-omap/include/mach/board-overo.h new file mode 100644 index 00000000000..7ecae66966d --- /dev/null +++ b/arch/arm/plat-omap/include/mach/board-overo.h @@ -0,0 +1,26 @@ +/* + * board-overo.h (Gumstix Overo) + * + * Initial code: Steve Sakoman + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OVERO_H +#define __ASM_ARCH_OVERO_H + +#define OVERO_GPIO_BT_XGATE 15 +#define OVERO_GPIO_W2W_NRESET 16 +#define OVERO_GPIO_BT_NRESET 164 +#define OVERO_GPIO_USBH_CPEN 168 +#define OVERO_GPIO_USBH_NRESET 183 + +#endif /* ____ASM_ARCH_OVERO_H */ + -- GitLab From a5d8c3483a6e19aca95ef6a2c5890e33bfa5b293 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 9 Oct 2008 11:35:51 +0200 Subject: [PATCH 3539/5416] sched debug: add name to sched_domain sysctl entries add /proc/sys/kernel/sched_domain/cpu0/domain0/name, to make it easier to see which specific scheduler domain remained at that entry. Since we process the scheduler domain tree and simplify it, it's not always immediately clear during debugging which domain came from where. depends on CONFIG_SCHED_DEBUG=y. Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched.c | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index d8e699b5585..5d0819ee442 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -824,6 +824,9 @@ struct sched_domain { unsigned int ttwu_move_affine; unsigned int ttwu_move_balance; #endif +#ifdef CONFIG_SCHED_DEBUG + char *name; +#endif }; extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, diff --git a/kernel/sched.c b/kernel/sched.c index 9715f4ce6cf..6f230596bd0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6351,7 +6351,7 @@ set_table_entry(struct ctl_table *entry, static struct ctl_table * sd_alloc_ctl_domain_table(struct sched_domain *sd) { - struct ctl_table *table = sd_alloc_ctl_entry(12); + struct ctl_table *table = sd_alloc_ctl_entry(13); if (table == NULL) return NULL; @@ -6379,7 +6379,9 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[10], "flags", &sd->flags, sizeof(int), 0644, proc_dointvec_minmax); - /* &table[11] is terminator */ + set_table_entry(&table[11], "name", sd->name, + CORENAME_MAX_SIZE, 0444, proc_dostring); + /* &table[12] is terminator */ return table; } @@ -7263,13 +7265,21 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd) * Non-inlined to reduce accumulated stack pressure in build_sched_domains() */ +#ifdef CONFIG_SCHED_DEBUG +# define SD_INIT_NAME(sd, type) sd->name = #type +#else +# define SD_INIT_NAME(sd, type) do { } while (0) +#endif + #define SD_INIT(sd, type) sd_init_##type(sd) + #define SD_INIT_FUNC(type) \ static noinline void sd_init_##type(struct sched_domain *sd) \ { \ memset(sd, 0, sizeof(*sd)); \ *sd = SD_##type##_INIT; \ sd->level = SD_LV_##type; \ + SD_INIT_NAME(sd, type); \ } SD_INIT_FUNC(CPU) -- GitLab From ec2a5652ea53c102306f08cdf516f98e32bd4b61 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 9 Oct 2008 09:45:04 -0700 Subject: [PATCH 3540/5416] phylib: two dynamic mii_bus allocation fallout fixes 1. arch/powerpc/platforms/pasemi/gpio_mdio.c also needs to be converted over to mdiobus_{alloc,free}(). 2. drivers/net/phy/fixed.c used to embed a struct mii_bus into its struct fixed_mdio_bus and then use container_of() to go from the former to the latter. Since mii bus structures are no longer embedded, we need to do something like use the mii bus private pointer to go from mii_bus to fixed_mdio_bus instead. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- arch/powerpc/platforms/pasemi/gpio_mdio.c | 4 ++-- drivers/net/phy/fixed.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 798c7abe160..75cc165d5be 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -230,7 +230,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, if (!priv) goto out; - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + new_bus = mdiobus_alloc(); if (!new_bus) goto out_free_priv; @@ -306,7 +306,7 @@ static int gpio_mdio_remove(struct of_device *dev) kfree(bus->priv); bus->priv = NULL; - kfree(bus); + mdiobus_free(bus); return 0; } diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index b5e13f8d5e3..cf24cc34deb 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -115,8 +115,7 @@ static int fixed_phy_update_regs(struct fixed_phy *fp) static int fixed_mdio_read(struct mii_bus *bus, int phy_id, int reg_num) { - struct fixed_mdio_bus *fmb = container_of(bus, struct fixed_mdio_bus, - mii_bus); + struct fixed_mdio_bus *fmb = bus->priv; struct fixed_phy *fp; if (reg_num >= MII_REGS_NUM) @@ -221,6 +220,7 @@ static int __init fixed_mdio_bus_init(void) snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "0"); fmb->mii_bus->name = "Fixed MDIO Bus"; + fmb->mii_bus->priv = fmb; fmb->mii_bus->parent = &pdev->dev; fmb->mii_bus->read = &fixed_mdio_read; fmb->mii_bus->write = &fixed_mdio_write; -- GitLab From 03254e65a60d3113164672dbbadc023c4a56ecd1 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 9 Oct 2008 13:27:55 -0400 Subject: [PATCH 3541/5416] NFS: Fix attribute updates This fixes a regression seen when running the Connectathon testsuite against an ext3 filesystem. The reason was that the inode was constantly being marked as 'just updated' by the jiffy wraparound test. This again meant that newer GETATTR calls were failing to pass the nfs_inode_attrs_need_update() test unless the changes caused a ctime update on the server, since they were perceived as having been started before the latest inode update. Given that nfs_inode_attrs_need_update() already checks for wraparound of nfsi->last_updated, we can drop the buggy "protection" in nfs_update_inode(). Also make a slight micro-optimisation of nfs_inode_attrs_need_update(): we are more often going to see time_after(fattr->time_start, nfsi->last_updated) be true, rather than seeing an update of ctime/size, so put that test first to ensure that we optimise away the ctime/size tests. Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e25009f35cc..6554281e24a 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -933,10 +933,10 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n { const struct nfs_inode *nfsi = NFS_I(inode); - return nfs_ctime_need_update(inode, fattr) || - nfs_size_need_update(inode, fattr) || - time_after(fattr->time_start, nfsi->last_updated) || - time_after(nfsi->last_updated, jiffies); + return time_after(fattr->time_start, nfsi->last_updated) || + nfs_ctime_need_update(inode, fattr) || + nfs_size_need_update(inode, fattr) || + time_after(nfsi->last_updated, jiffies); } static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) @@ -1167,11 +1167,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); nfsi->attrtimeo_timestamp = now; } - /* - * Avoid jiffy wraparound issues with nfsi->last_updated - */ - if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now)) - nfsi->last_updated = nfsi->read_cache_jiffies; } invalid &= ~NFS_INO_INVALID_ATTR; /* Don't invalidate the data if we were to blame */ -- GitLab From 8d5922572038bae9f7b16fcb974eee806727b44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9meth=20M=C3=A1rton?= Date: Thu, 9 Oct 2008 14:59:17 +0200 Subject: [PATCH 3542/5416] [CPUFREQ] correct broken links and email addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the no longer working links and email address in the documentation and in source code. Signed-off-by: Márton Németh Signed-off-by: Dave Jones --- Documentation/cpu-freq/index.txt | 10 ++++------ arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | 2 +- arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Documentation/cpu-freq/index.txt b/Documentation/cpu-freq/index.txt index ffdb5323df3..3d0b915035b 100644 --- a/Documentation/cpu-freq/index.txt +++ b/Documentation/cpu-freq/index.txt @@ -35,11 +35,9 @@ Mailing List ------------ There is a CPU frequency changing CVS commit and general list where you can report bugs, problems or submit patches. To post a message, -send an email to cpufreq@lists.linux.org.uk, to subscribe go to -http://lists.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the -mailing list are available to subscribers at -http://lists.linux.org.uk/mailman/private/cpufreq/. - +send an email to cpufreq@vger.kernel.org, to subscribe go to +http://vger.kernel.org/vger-lists.html#cpufreq and follow the +instructions there. Links ----- @@ -50,7 +48,7 @@ how to access the CVS repository: * http://cvs.arm.linux.org.uk/ the CPUFreq Mailing list: -* http://lists.linux.org.uk/mailman/listinfo/cpufreq +* http://vger.kernel.org/vger-lists.html#cpufreq Clock and voltage scaling for the SA-1100: * http://www.lartmaker.nl/projects/scaling diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index f1685fb91fb..b8e05ee4f73 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -171,7 +171,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) } if (c->x86 != 0xF) { - printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); + printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); return 0; } diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 15e13c01cc3..3b5f06423e7 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c @@ -26,7 +26,7 @@ #include #define PFX "speedstep-centrino: " -#define MAINTAINER "cpufreq@lists.linux.org.uk" +#define MAINTAINER "cpufreq@vger.kernel.org" #define dprintk(msg...) \ cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) -- GitLab From 18c6faa9624bf5d9d7da3906a8a1b909dba5899b Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 28 Jul 2008 13:00:49 +0200 Subject: [PATCH 3543/5416] [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/elanfreq.c Before: total: 15 errors, 10 warnings, 308 lines checked After: total: 0 errors, 4 warnings, 308 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/elafreq.o.* add1d36c2f077c5aab7682e8642a9f34 /tmp/elafreq.o.after add1d36c2f077c5aab7682e8642a9f34 /tmp/elafreq.o.before paolo@paolo-desktop:~/linux.trees.git$ size /tmp/elafreq.o.* text data bss dec hex filename 934 270 4 1208 4b8 /tmp/elafreq.o.after 934 270 4 1208 4b8 /tmp/elafreq.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/elanfreq.c | 42 +++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index e4a4bf870e9..fe613c93b36 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ #define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ @@ -82,7 +82,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) u8 clockspeed_reg; /* Clock Speed Register */ local_irq_disable(); - outb_p(0x80,REG_CSCIR); + outb_p(0x80, REG_CSCIR); clockspeed_reg = inb_p(REG_CSCDR); local_irq_enable(); @@ -98,10 +98,10 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) } /* 33 MHz is not 32 MHz... */ - if ((clockspeed_reg & 0xE0)==0xA0) + if ((clockspeed_reg & 0xE0) == 0xA0) return 33000; - return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000); + return (1<<((clockspeed_reg & 0xE0) >> 5)) * 1000; } @@ -117,7 +117,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) * There is no return value. */ -static void elanfreq_set_cpu_state (unsigned int state) +static void elanfreq_set_cpu_state(unsigned int state) { struct cpufreq_freqs freqs; @@ -144,20 +144,20 @@ static void elanfreq_set_cpu_state (unsigned int state) */ local_irq_disable(); - outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */ - outb_p(0x00,REG_CSCDR); + outb_p(0x40, REG_CSCIR); /* Disable hyperspeed mode */ + outb_p(0x00, REG_CSCDR); local_irq_enable(); /* wait till internal pipelines and */ udelay(1000); /* buffers have cleaned up */ local_irq_disable(); /* now, set the CPU clock speed register (0x80) */ - outb_p(0x80,REG_CSCIR); - outb_p(elan_multiplier[state].val80h,REG_CSCDR); + outb_p(0x80, REG_CSCIR); + outb_p(elan_multiplier[state].val80h, REG_CSCDR); /* now, the hyperspeed bit in PMU Force Mode Register (0x40) */ - outb_p(0x40,REG_CSCIR); - outb_p(elan_multiplier[state].val40h,REG_CSCDR); + outb_p(0x40, REG_CSCIR); + outb_p(elan_multiplier[state].val40h, REG_CSCDR); udelay(10000); local_irq_enable(); @@ -173,12 +173,12 @@ static void elanfreq_set_cpu_state (unsigned int state) * for the hardware supported by the driver. */ -static int elanfreq_verify (struct cpufreq_policy *policy) +static int elanfreq_verify(struct cpufreq_policy *policy) { return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]); } -static int elanfreq_target (struct cpufreq_policy *policy, +static int elanfreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -205,7 +205,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) /* capability check */ if ((c->x86_vendor != X86_VENDOR_AMD) || - (c->x86 != 4) || (c->x86_model!=10)) + (c->x86 != 4) || (c->x86_model != 10)) return -ENODEV; /* max freq */ @@ -213,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) max_freq = elanfreq_get_cpu_frequency(0); /* table init */ - for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { if (elanfreq_table[i].frequency > max_freq) elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID; } @@ -224,7 +224,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table); if (result) - return (result); + return result; cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); return 0; @@ -260,7 +260,7 @@ __setup("elanfreq=", elanfreq_setup); #endif -static struct freq_attr* elanfreq_attr[] = { +static struct freq_attr *elanfreq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; @@ -284,9 +284,9 @@ static int __init elanfreq_init(void) /* Test if we have the right hardware */ if ((c->x86_vendor != X86_VENDOR_AMD) || - (c->x86 != 4) || (c->x86_model!=10)) { + (c->x86 != 4) || (c->x86_model != 10)) { printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); - return -ENODEV; + return -ENODEV; } return cpufreq_register_driver(&elanfreq_driver); } @@ -298,7 +298,7 @@ static void __exit elanfreq_exit(void) } -module_param (max_freq, int, 0444); +module_param(max_freq, int, 0444); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Robert Schwebel , Sven Geggus "); -- GitLab From 8d2d2051e50c4ca0207a42b243369e22f7d90a5c Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Mon, 28 Jul 2008 21:08:16 +0200 Subject: [PATCH 3544/5416] [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/powernow-k6.c Before: total: 11 errors, 15 warnings, 255 lines checked After: total: 0 errors, 6 warnings, 254 lines checked paolo@paolo-desktop:~/linux.trees.git$ md5sum /tmp/powernow-k6.o.* 476932f5e1ffe365db9d1dfb3f860369 /tmp/powernow-k6.o.after 476932f5e1ffe365db9d1dfb3f860369 /tmp/powernow-k6.o.before Signed-off-by: Paolo Ciarrocchi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/powernow-k6.c | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index eb9b62b0830..b5ced806a31 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c @@ -15,12 +15,11 @@ #include #include -#include -#include +#include +#include - -#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long - as it is unused */ +#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long + as it is unused */ static unsigned int busfreq; /* FSB, in 10 kHz */ static unsigned int max_multiplier; @@ -53,7 +52,7 @@ static int powernow_k6_get_cpu_multiplier(void) msrval = POWERNOW_IOPORT + 0x1; wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ - invalue=inl(POWERNOW_IOPORT + 0x8); + invalue = inl(POWERNOW_IOPORT + 0x8); msrval = POWERNOW_IOPORT + 0x0; wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ @@ -67,9 +66,9 @@ static int powernow_k6_get_cpu_multiplier(void) * * Tries to change the PowerNow! multiplier */ -static void powernow_k6_set_state (unsigned int best_i) +static void powernow_k6_set_state(unsigned int best_i) { - unsigned long outvalue=0, invalue=0; + unsigned long outvalue = 0, invalue = 0; unsigned long msrval; struct cpufreq_freqs freqs; @@ -90,10 +89,10 @@ static void powernow_k6_set_state (unsigned int best_i) msrval = POWERNOW_IOPORT + 0x1; wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ - invalue=inl(POWERNOW_IOPORT + 0x8); + invalue = inl(POWERNOW_IOPORT + 0x8); invalue = invalue & 0xf; outvalue = outvalue | invalue; - outl(outvalue ,(POWERNOW_IOPORT + 0x8)); + outl(outvalue , (POWERNOW_IOPORT + 0x8)); msrval = POWERNOW_IOPORT + 0x0; wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ @@ -124,7 +123,7 @@ static int powernow_k6_verify(struct cpufreq_policy *policy) * * sets a new CPUFreq policy */ -static int powernow_k6_target (struct cpufreq_policy *policy, +static int powernow_k6_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -152,7 +151,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) busfreq = cpu_khz / max_multiplier; /* table init */ - for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { if (clock_ratio[i].index > max_multiplier) clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID; else @@ -165,7 +164,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); if (result) - return (result); + return result; cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu); @@ -176,8 +175,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) { unsigned int i; - for (i=0; i<8; i++) { - if (i==max_multiplier) + for (i = 0; i < 8; i++) { + if (i == max_multiplier) powernow_k6_set_state(i); } cpufreq_frequency_table_put_attr(policy->cpu); @@ -189,7 +188,7 @@ static unsigned int powernow_k6_get(unsigned int cpu) return busfreq * powernow_k6_get_cpu_multiplier(); } -static struct freq_attr* powernow_k6_attr[] = { +static struct freq_attr *powernow_k6_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; @@ -227,7 +226,7 @@ static int __init powernow_k6_init(void) } if (cpufreq_register_driver(&powernow_k6_driver)) { - release_region (POWERNOW_IOPORT, 16); + release_region(POWERNOW_IOPORT, 16); return -EINVAL; } @@ -243,13 +242,13 @@ static int __init powernow_k6_init(void) static void __exit powernow_k6_exit(void) { cpufreq_unregister_driver(&powernow_k6_driver); - release_region (POWERNOW_IOPORT, 16); + release_region(POWERNOW_IOPORT, 16); } -MODULE_AUTHOR ("Arjan van de Ven , Dave Jones , Dominik Brodowski "); -MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors."); -MODULE_LICENSE ("GPL"); +MODULE_AUTHOR("Arjan van de Ven , Dave Jones , Dominik Brodowski "); +MODULE_DESCRIPTION("PowerNow! driver for AMD K6-2+ / K6-3+ processors."); +MODULE_LICENSE("GPL"); module_init(powernow_k6_init); module_exit(powernow_k6_exit); -- GitLab From 847aef6ffd85787b62395b64719f8f7c5975bf1b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 14 Jul 2008 11:59:44 +0900 Subject: [PATCH 3545/5416] [CPUFREQ] acpi-cpufreq: add error handling for cpufreq_register_driver() error add error handling for cpufreq_register_driver() error Signed-off-by: Akinobu Mita Cc: cpufreq@lists.linux.org.uk Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index dd097b83583..1def5b06fa4 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -785,7 +785,11 @@ static int __init acpi_cpufreq_init(void) if (ret) return ret; - return cpufreq_register_driver(&acpi_cpufreq_driver); + ret = cpufreq_register_driver(&acpi_cpufreq_driver); + if (ret) + free_percpu(acpi_perf_data); + + return ret; } static void __exit acpi_cpufreq_exit(void) @@ -795,8 +799,6 @@ static void __exit acpi_cpufreq_exit(void) cpufreq_unregister_driver(&acpi_cpufreq_driver); free_percpu(acpi_perf_data); - - return; } module_param(acpi_pstate_strict, uint, 0644); -- GitLab From 888a794cacd8950ac6be701db20b62a4ab2ce90c Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 14 Jul 2008 12:00:45 +0900 Subject: [PATCH 3546/5416] [CPUFREQ] add error handling for cpufreq_register_governor() error Add error handling for cpufreq_register_governor() error Signed-off-by: Akinobu Mita Cc: cpufreq@lists.linux.org.uk Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 33855cb3cf1..67c9d4f9edc 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -589,12 +589,18 @@ EXPORT_SYMBOL(cpufreq_gov_ondemand); static int __init cpufreq_gov_dbs_init(void) { + int err; + kondemand_wq = create_workqueue("kondemand"); if (!kondemand_wq) { printk(KERN_ERR "Creation of kondemand failed\n"); return -EFAULT; } - return cpufreq_register_governor(&cpufreq_gov_ondemand); + err = cpufreq_register_governor(&cpufreq_gov_ondemand); + if (err) + destroy_workqueue(kondemand_wq); + + return err; } static void __exit cpufreq_gov_dbs_exit(void) -- GitLab From f1829e4a371f26430185a9d5b97b8d9d19824e08 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 25 Jul 2008 22:44:53 +0200 Subject: [PATCH 3547/5416] [CPUFREQ] drivers/cpufreq/cpufreq.c: Adjust error handling code involving cpufreq_cpu_put After calling cpufreq_cpu_get, error handling code should call cpufreq_cpu_put. The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r@ expression x,E; statement S; position p1,p2,p3; @@ ( if ((x = cpufreq_cpu_get@p1(...)) == NULL || ...) S | x = cpufreq_cpu_get@p1(...) ... when != x if (x == NULL || ...) S ) <... if@p3 (...) { ... when != cpufreq_cpu_put(x) when != if (x) { ... cpufreq_cpu_put(x); ...} return@p2 ...; } ...> ( return x; | return 0; | x = E | E = x | cpufreq_cpu_put(x) ) @exists@ position r.p1,r.p2,r.p3; expression x; int ret != 0; statement S; @@ * x = cpufreq_cpu_get@p1(...) <... * if@p3 (...) S ...> * return@p2 \(NULL\|ret\); // Signed-off-by: Julia Lawall Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8a67f16987d..9bbdc258624 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1467,20 +1467,22 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - int ret; + int ret = -EINVAL; policy = cpufreq_cpu_get(policy->cpu); if (!policy) - return -EINVAL; + goto no_policy; if (unlikely(lock_policy_rwsem_write(policy->cpu))) - return -EINVAL; + goto fail; ret = __cpufreq_driver_target(policy, target_freq, relation); unlock_policy_rwsem_write(policy->cpu); +fail: cpufreq_cpu_put(policy); +no_policy: return ret; } EXPORT_SYMBOL_GPL(cpufreq_driver_target); @@ -1717,13 +1719,17 @@ int cpufreq_update_policy(unsigned int cpu) { struct cpufreq_policy *data = cpufreq_cpu_get(cpu); struct cpufreq_policy policy; - int ret = 0; + int ret; - if (!data) - return -ENODEV; + if (!data) { + ret = -ENODEV; + goto no_policy; + } - if (unlikely(lock_policy_rwsem_write(cpu))) - return -EINVAL; + if (unlikely(lock_policy_rwsem_write(cpu))) { + ret = -EINVAL; + goto fail; + } dprintk("updating policy for CPU %u\n", cpu); memcpy(&policy, data, sizeof(struct cpufreq_policy)); @@ -1750,7 +1756,9 @@ int cpufreq_update_policy(unsigned int cpu) unlock_policy_rwsem_write(cpu); +fail: cpufreq_cpu_put(data); +no_policy: return ret; } EXPORT_SYMBOL(cpufreq_update_policy); -- GitLab From 8217e4f4c93e5fb59bb3cd1e6135213889349f86 Mon Sep 17 00:00:00 2001 From: Ben Slusky Date: Mon, 7 Jul 2008 13:16:20 -0400 Subject: [PATCH 3548/5416] [CPUFREQ] use deferrable delayed work init in conservative governor Venki Pallipadi made a similar change to the ondemand governor a while back (in commit 28287033e12463c8ff89f1ea8038783d0360391c). It seems to work just as well in the conservative governor, leading to fewer wakeups as reported by powertop. Signed-off-by: Ben Slusky Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index ac0bbf2d234..4ee53a4c6d2 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -460,6 +460,7 @@ static void do_dbs_timer(struct work_struct *work) static inline void dbs_timer_init(void) { + init_timer_deferrable(&dbs_work.timer); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); return; -- GitLab From bf0b90e357c883e8efd72954432efe652de74c76 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:07 -0700 Subject: [PATCH 3549/5416] [CPUFREQ][1/6] cpufreq: Add cpu number parameter to __cpufreq_driver_getavg() Add a cpu parameter to __cpufreq_driver_getavg(). This is needed for software cpufreq coordination where policy->cpu may not be same as the CPU on which we want to getavg frequency. A follow-on patch will use this parameter to getavg freq from all cpus in policy->cpus. Change since last patch. Fix the offline/online and suspend/resume oops reported by Youquan Song Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 5 +++-- drivers/cpufreq/cpufreq.c | 6 +++--- drivers/cpufreq/cpufreq_ondemand.c | 2 +- include/linux/cpufreq.h | 7 +++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 1def5b06fa4..c24c4a487b7 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -256,7 +256,8 @@ static u32 get_cur_val(const cpumask_t *mask) * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and * no meaning should be associated with absolute values of these MSRs. */ -static unsigned int get_measured_perf(unsigned int cpu) +static unsigned int get_measured_perf(struct cpufreq_policy *policy, + unsigned int cpu) { union { struct { @@ -326,7 +327,7 @@ static unsigned int get_measured_perf(unsigned int cpu) #endif - retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100; + retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100; put_cpu(); set_cpus_allowed_ptr(current, &saved_mask); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9bbdc258624..31d6f535a79 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1487,7 +1487,7 @@ no_policy: } EXPORT_SYMBOL_GPL(cpufreq_driver_target); -int __cpufreq_driver_getavg(struct cpufreq_policy *policy) +int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) { int ret = 0; @@ -1495,8 +1495,8 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy) if (!policy) return -EINVAL; - if (cpu_online(policy->cpu) && cpufreq_driver->getavg) - ret = cpufreq_driver->getavg(policy->cpu); + if (cpu_online(cpu) && cpufreq_driver->getavg) + ret = cpufreq_driver->getavg(policy, cpu); cpufreq_cpu_put(policy); return ret; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 67c9d4f9edc..f56debd9a8d 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -415,7 +415,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) if (load < (dbs_tuners_ins.up_threshold - 10)) { unsigned int freq_next, freq_cur; - freq_cur = __cpufreq_driver_getavg(policy); + freq_cur = __cpufreq_driver_getavg(policy, policy->cpu); if (!freq_cur) freq_cur = policy->cur; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 6fd5668aa57..1ee608fd7b7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -187,7 +187,8 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation); -extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy); +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); @@ -226,7 +227,9 @@ struct cpufreq_driver { unsigned int (*get) (unsigned int cpu); /* optional */ - unsigned int (*getavg) (unsigned int cpu); + unsigned int (*getavg) (struct cpufreq_policy *policy, + unsigned int cpu); + int (*exit) (struct cpufreq_policy *policy); int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg); int (*resume) (struct cpufreq_policy *policy); -- GitLab From c43aa3bd99a67009a167430e80c5fde6f37288d8 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:08 -0700 Subject: [PATCH 3550/5416] [CPUFREQ][2/6] cpufreq: Change load calculation in ondemand for software coordination Change the load calculation algorithm in ondemand to work well with software coordination of frequency across the dependent cpus. Multiply individual CPU utilization with the average freq of that logical CPU during the measurement interval (using getavg call). And find the max CPU utilization number in terms of CPU freq. That number is then used to get to the target freq for next sampling interval. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 65 ++++++++++++++++-------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index f56debd9a8d..42fcb146ba2 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -334,9 +334,7 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) { - unsigned int idle_ticks, total_ticks; - unsigned int load = 0; - cputime64_t cur_jiffies; + unsigned int max_load_freq; struct cpufreq_policy *policy; unsigned int j; @@ -346,13 +344,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) this_dbs_info->freq_lo = 0; policy = this_dbs_info->cur_policy; - cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); - total_ticks = (unsigned int) cputime64_sub(cur_jiffies, - this_dbs_info->prev_cpu_wall); - this_dbs_info->prev_cpu_wall = get_jiffies_64(); - if (!total_ticks) - return; /* * Every sampling_rate, we check, if current idle time is less * than 20% (default), then we try to increase frequency @@ -365,27 +357,46 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * 5% (default) of current frequency */ - /* Get Idle Time */ - idle_ticks = UINT_MAX; + /* Get Absolute Load - in terms of freq */ + max_load_freq = 0; + for_each_cpu_mask_nr(j, policy->cpus) { - cputime64_t total_idle_ticks; - unsigned int tmp_idle_ticks; struct cpu_dbs_info_s *j_dbs_info; + cputime64_t cur_wall_time, cur_idle_time; + unsigned int idle_time, wall_time; + unsigned int load, load_freq; + int freq_avg; j_dbs_info = &per_cpu(cpu_dbs_info, j); - total_idle_ticks = get_cpu_idle_time(j); - tmp_idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks, + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + wall_time = (unsigned int) cputime64_sub(cur_wall_time, + j_dbs_info->prev_cpu_wall); + j_dbs_info->prev_cpu_wall = cur_wall_time; + + cur_idle_time = get_cpu_idle_time(j); + idle_time = (unsigned int) cputime64_sub(cur_idle_time, j_dbs_info->prev_cpu_idle); - j_dbs_info->prev_cpu_idle = total_idle_ticks; + j_dbs_info->prev_cpu_idle = cur_idle_time; - if (tmp_idle_ticks < idle_ticks) - idle_ticks = tmp_idle_ticks; + if (unlikely(wall_time <= idle_time || + (cputime_to_msecs(wall_time) < + dbs_tuners_ins.sampling_rate / (2 * 1000)))) { + continue; + } + + load = 100 * (wall_time - idle_time) / wall_time; + + freq_avg = __cpufreq_driver_getavg(policy, j); + if (freq_avg <= 0) + freq_avg = policy->cur; + + load_freq = load * freq_avg; + if (load_freq > max_load_freq) + max_load_freq = load_freq; } - if (likely(total_ticks > idle_ticks)) - load = (100 * (total_ticks - idle_ticks)) / total_ticks; /* Check for frequency increase */ - if (load > dbs_tuners_ins.up_threshold) { + if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { /* if we are already at full speed then break out early */ if (!dbs_tuners_ins.powersave_bias) { if (policy->cur == policy->max) @@ -412,15 +423,9 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * can support the current CPU usage without triggering the up * policy. To be safe, we focus 10 points under the threshold. */ - if (load < (dbs_tuners_ins.up_threshold - 10)) { - unsigned int freq_next, freq_cur; - - freq_cur = __cpufreq_driver_getavg(policy, policy->cpu); - if (!freq_cur) - freq_cur = policy->cur; - - freq_next = (freq_cur * load) / - (dbs_tuners_ins.up_threshold - 10); + if (max_load_freq < (dbs_tuners_ins.up_threshold - 10) * policy->cur) { + unsigned int freq_next; + freq_next = max_load_freq / (dbs_tuners_ins.up_threshold - 10); if (!dbs_tuners_ins.powersave_bias) { __cpufreq_driver_target(policy, freq_next, -- GitLab From 3430502d356284ff4f7782d75bb01a402fd3d45e Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:09 -0700 Subject: [PATCH 3551/5416] [CPUFREQ][3/6] cpufreq: get_cpu_idle_time() changes in ondemand for idle-microaccounting Preparatory changes for doing idle micro-accounting in ondemand governor. get_cpu_idle_time() gets extra parameter and returns idle time and also the wall time that corresponds to the idle time measurement. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 42fcb146ba2..b935092aab2 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -94,13 +94,13 @@ static struct dbs_tuners { .powersave_bias = 0, }; -static inline cputime64_t get_cpu_idle_time(unsigned int cpu) +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) { cputime64_t idle_time; - cputime64_t cur_jiffies; + cputime64_t cur_wall_time; cputime64_t busy_time; - cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user, kstat_cpu(cpu).cpustat.system); @@ -113,7 +113,10 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu) kstat_cpu(cpu).cpustat.nice); } - idle_time = cputime64_sub(cur_jiffies, busy_time); + idle_time = cputime64_sub(cur_wall_time, busy_time); + if (wall) + *wall = cur_wall_time; + return idle_time; } @@ -277,8 +280,8 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, for_each_online_cpu(j) { struct cpu_dbs_info_s *dbs_info; dbs_info = &per_cpu(cpu_dbs_info, j); - dbs_info->prev_cpu_idle = get_cpu_idle_time(j); - dbs_info->prev_cpu_wall = get_jiffies_64(); + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->prev_cpu_wall); } mutex_unlock(&dbs_mutex); @@ -368,21 +371,19 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) int freq_avg; j_dbs_info = &per_cpu(cpu_dbs_info, j); - cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + wall_time = (unsigned int) cputime64_sub(cur_wall_time, j_dbs_info->prev_cpu_wall); j_dbs_info->prev_cpu_wall = cur_wall_time; - cur_idle_time = get_cpu_idle_time(j); idle_time = (unsigned int) cputime64_sub(cur_idle_time, j_dbs_info->prev_cpu_idle); j_dbs_info->prev_cpu_idle = cur_idle_time; - if (unlikely(wall_time <= idle_time || - (cputime_to_msecs(wall_time) < - dbs_tuners_ins.sampling_rate / (2 * 1000)))) { + if (unlikely(!wall_time || wall_time < idle_time)) continue; - } load = 100 * (wall_time - idle_time) / wall_time; @@ -531,8 +532,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j); - j_dbs_info->prev_cpu_wall = get_jiffies_64(); + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &j_dbs_info->prev_cpu_wall); } this_dbs_info->cpu = cpu; /* -- GitLab From e9d95bf7eb929b9ddc9af9f4327b76c77ed4c7d6 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:10 -0700 Subject: [PATCH 3552/5416] [CPUFREQ][4/6] cpufreq_ondemand: Parameterize down differential Use a parameter for down differential, instead of hardcoded 10%. Follow-on patch changes the down-differential dynamically, based on whether we are using idle micro-accounting or not. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index b935092aab2..3f898606e68 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -24,6 +24,7 @@ * It helps to keep variable names smaller, simpler */ +#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) #define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) @@ -86,10 +87,12 @@ static struct workqueue_struct *kondemand_wq; static struct dbs_tuners { unsigned int sampling_rate; unsigned int up_threshold; + unsigned int down_differential; unsigned int ignore_nice; unsigned int powersave_bias; } dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, .ignore_nice = 0, .powersave_bias = 0, }; @@ -424,9 +427,13 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * can support the current CPU usage without triggering the up * policy. To be safe, we focus 10 points under the threshold. */ - if (max_load_freq < (dbs_tuners_ins.up_threshold - 10) * policy->cur) { + if (max_load_freq < + (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) * + policy->cur) { unsigned int freq_next; - freq_next = max_load_freq / (dbs_tuners_ins.up_threshold - 10); + freq_next = max_load_freq / + (dbs_tuners_ins.up_threshold - + dbs_tuners_ins.down_differential); if (!dbs_tuners_ins.powersave_bias) { __cpufreq_driver_target(policy, freq_next, -- GitLab From 8083e4ad970e4eb567e31037060cdd4ba346f0c0 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:11 -0700 Subject: [PATCH 3553/5416] [CPUFREQ][5/6] cpufreq: Changes to get_cpu_idle_time_us(), used by ondemand governor export get_cpu_idle_time_us() for it to be used in ondemand governor. Last update time can be current time when the CPU is currently non-idle, accounting for the busy time since last idle. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- include/linux/tick.h | 2 +- kernel/time/tick-sched.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/linux/tick.h b/include/linux/tick.h index 8cf8cfe2cc9..98921a3e1aa 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -126,7 +126,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void) return len; } static inline void tick_nohz_stop_idle(int cpu) { } -static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return 0; } +static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } # endif /* !NO_HZ */ #endif diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index cb02324bdb8..a4d21939816 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -190,9 +191,17 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); - *last_update_time = ktime_to_us(ts->idle_lastupdate); + if (!tick_nohz_enabled) + return -1; + + if (ts->idle_active) + *last_update_time = ktime_to_us(ts->idle_lastupdate); + else + *last_update_time = ktime_to_us(ktime_get()); + return ktime_to_us(ts->idle_sleeptime); } +EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); /** * tick_nohz_stop_sched_tick - stop the idle tick from the idle task -- GitLab From 808009131046b62ac434dbc796c0fe8accaab415 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Mon, 4 Aug 2008 11:59:12 -0700 Subject: [PATCH 3554/5416] [CPUFREQ][6/6] cpufreq: Add idle microaccounting in ondemand governor Use get_cpu_idle_time_us() to get micro-accounted idle information. This enables ondemand to get more accurate idle and busy timings than the jiffy based calculation. As a result, we can decrease the ondemand safety gaurd band from 80-10 to 95-3. Results in more aggressive power savings. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 45 +++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 3f898606e68..39253d6d51e 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include /* * dbs is used in this file as a shortform for demandbased switching @@ -26,6 +29,8 @@ #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) +#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) +#define MICRO_FREQUENCY_UP_THRESHOLD (95) #define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) @@ -58,6 +63,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; cputime64_t prev_cpu_wall; + cputime64_t prev_cpu_nice; struct cpufreq_policy *cur_policy; struct delayed_work work; struct cpufreq_frequency_table *freq_table; @@ -97,7 +103,8 @@ static struct dbs_tuners { .powersave_bias = 0, }; -static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) +static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, + cputime64_t *wall) { cputime64_t idle_time; cputime64_t cur_wall_time; @@ -123,6 +130,33 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) return idle_time; } +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, wall); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + + if (dbs_tuners_ins.ignore_nice) { + cputime64_t cur_nice; + unsigned long cur_nice_jiffies; + struct cpu_dbs_info_s *dbs_info; + + dbs_info = &per_cpu(cpu_dbs_info, cpu); + cur_nice = cputime64_sub(kstat_cpu(cpu).cpustat.nice, + dbs_info->prev_cpu_nice); + /* + * Assumption: nice time between sampling periods will be + * less than 2^32 jiffies for 32 bit sys + */ + cur_nice_jiffies = (unsigned long) + cputime64_to_jiffies64(cur_nice); + dbs_info->prev_cpu_nice = kstat_cpu(cpu).cpustat.nice; + return idle_time + jiffies_to_usecs(cur_nice_jiffies); + } + return idle_time; +} + /* * Find right freq to be set now with powersave_bias on. * Returns the freq_hi to be used right now and will set freq_hi_jiffies, @@ -603,6 +637,15 @@ EXPORT_SYMBOL(cpufreq_gov_ondemand); static int __init cpufreq_gov_dbs_init(void) { int err; + cputime64_t wall; + u64 idle_time = get_cpu_idle_time_us(smp_processor_id(), &wall); + + if (idle_time != -1ULL) { + /* Idle micro accounting is supported. Use finer thresholds */ + dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; + dbs_tuners_ins.down_differential = + MICRO_FREQUENCY_DOWN_DIFFERENTIAL; + } kondemand_wq = create_workqueue("kondemand"); if (!kondemand_wq) { -- GitLab From c4d14bc0bb5d13e316890651ae4518b764c3344c Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Sat, 20 Sep 2008 16:50:08 +0200 Subject: [PATCH 3555/5416] [CPUFREQ] Don't export governors for default governor We don't need to export the governors for use as the default governor, because the default governor will be built-in anyway and we can access the symbol directly. This also fixes the following sparse warnings: drivers/cpufreq/cpufreq_conservative.c:578:25: warning: symbol 'cpufreq_gov_conservative' was not declared. Should it be static? drivers/cpufreq/cpufreq_ondemand.c:582:25: warning: symbol 'cpufreq_gov_ondemand' was not declared. Should it be static? drivers/cpufreq/cpufreq_performance.c:39:25: warning: symbol 'cpufreq_gov_performance' was not declared. Should it be static? drivers/cpufreq/cpufreq_powersave.c:38:25: warning: symbol 'cpufreq_gov_powersave' was not declared. Should it be static? drivers/cpufreq/cpufreq_userspace.c:190:25: warning: symbol 'cpufreq_gov_userspace' was not declared. Should it be static? Signed-off-by: Sven Wegener Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 4 +++- drivers/cpufreq/cpufreq_ondemand.c | 4 +++- drivers/cpufreq/cpufreq_performance.c | 4 +++- drivers/cpufreq/cpufreq_powersave.c | 4 +++- drivers/cpufreq/cpufreq_userspace.c | 4 +++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 4ee53a4c6d2..e2657837d95 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -576,13 +576,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return 0; } +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +static +#endif struct cpufreq_governor cpufreq_gov_conservative = { .name = "conservative", .governor = cpufreq_governor_dbs, .max_transition_latency = TRANSITION_LATENCY_LIMIT, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_conservative); static int __init cpufreq_gov_dbs_init(void) { diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 39253d6d51e..bd069349bca 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -626,13 +626,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return 0; } +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static +#endif struct cpufreq_governor cpufreq_gov_ondemand = { .name = "ondemand", .governor = cpufreq_governor_dbs, .max_transition_latency = TRANSITION_LATENCY_LIMIT, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_ondemand); static int __init cpufreq_gov_dbs_init(void) { diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index e8e1451ef1c..7e2e515087f 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -36,12 +36,14 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy, return 0; } +#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE +static +#endif struct cpufreq_governor cpufreq_gov_performance = { .name = "performance", .governor = cpufreq_governor_performance, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_performance); static int __init cpufreq_gov_performance_init(void) diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index 88d2f44fba4..e6db5faf3eb 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -35,12 +35,14 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, return 0; } +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +static +#endif struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_powersave); static int __init cpufreq_gov_powersave_init(void) { diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 32244aa7cc0..1442bbada05 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -187,6 +187,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, } +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +static +#endif struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, @@ -194,7 +197,6 @@ struct cpufreq_governor cpufreq_gov_userspace = { .show_setspeed = show_speed, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_userspace); static int __init cpufreq_gov_userspace_init(void) { -- GitLab From 4f6e6b9f97b0ce98a8d1da65adbaf743bd0486a9 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Thu, 18 Sep 2008 10:43:40 +0000 Subject: [PATCH 3556/5416] [CPUFREQ] Fix BUG: using smp_processor_id() in preemptible code Use get_cpu()/put_cpu() in cpufreq_ondemand init routine, instead of smp_processor_id() to avoid the following BUG: [ 35.313118] BUG: using smp_processor_id() in preemptible [00000000] code=: modprobe/4952 [ 35.313132] caller is cpufreq_gov_dbs_init+0xa/0x8f [cpufreq_ondemand] [ 35.313140] Pid: 4952, comm: modprobe Not tainted 2.6.27-rc5-mm1 #23 [ 35.313145] Call Trace: [ 35.313158] [] debug_smp_processor_id+0xd7/0xe0 [ 35.313167] [] cpufreq_gov_dbs_init+0xa/0x8f [cpufreq_ondemand] [ 35.313176] [] _stext+0x3b/0x160 [ 35.313185] [] __mutex_unlock_slowpath+0xe5/0x190 [ 35.313195] [] trace_hardirqs_on_caller+0xca/0x140 [ 35.313205] [] sys_init_module+0xdc/0x210 [ 35.313212] [] system_call_fastpath+0x16/0x1b Signed-off-by: Andrea Righi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd069349bca..2ab3c12b88a 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -640,8 +640,11 @@ static int __init cpufreq_gov_dbs_init(void) { int err; cputime64_t wall; - u64 idle_time = get_cpu_idle_time_us(smp_processor_id(), &wall); + u64 idle_time; + int cpu = get_cpu(); + idle_time = get_cpu_idle_time_us(cpu, &wall); + put_cpu(); if (idle_time != -1ULL) { /* Idle micro accounting is supported. Use finer thresholds */ dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; -- GitLab From c95b819ad75b13102139aad0e7062d927be23cc6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Oct 2008 11:58:54 -0700 Subject: [PATCH 3557/5416] gre: Use needed_headroom Now that we have dev->needed_headroom, we can use it instead of having a bogus dev->hard_header_len. This also allows us to include dev->hard_header_len in the MTU computation so that when we do have a meaningful hard_harder_len in future it is included automatically in figuring out the MTU. Incidentally, this fixes a bug where we ignored the needed_headroom field of the underlying device in calculating our own hard_header_len. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2a61158ea72..fd192d67695 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -637,7 +637,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) df = tiph->frag_off; if (df) - mtu = dst_mtu(&rt->u.dst) - tunnel->hlen; + mtu = dst_mtu(&rt->u.dst) - dev->hard_header_len - tunnel->hlen; else mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; @@ -785,7 +785,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; - /* Guess output device to choose reasonable mtu and hard_header_len */ + /* Guess output device to choose reasonable mtu and needed_headroom */ if (iph->daddr) { struct flowi fl = { .oif = tunnel->parms.link, @@ -806,7 +806,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); if (tdev) { - hlen = tdev->hard_header_len; + hlen = tdev->hard_header_len + tdev->needed_headroom; mtu = tdev->mtu; } dev->iflink = tunnel->parms.link; @@ -820,8 +820,8 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) if (tunnel->parms.o_flags&GRE_SEQ) addend += 4; } - dev->hard_header_len = hlen + addend; - dev->mtu = mtu - addend; + dev->needed_headroom = addend + hlen; + dev->mtu = mtu - dev->hard_header_len - addend; tunnel->hlen = addend; } @@ -959,7 +959,8 @@ done: static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) { struct ip_tunnel *tunnel = netdev_priv(dev); - if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen) + if (new_mtu < 68 || + new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen) return -EINVAL; dev->mtu = new_mtu; return 0; @@ -1085,7 +1086,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) dev->change_mtu = ipgre_tunnel_change_mtu; dev->type = ARPHRD_IPGRE; - dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr) + 4; + dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4; dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4; dev->flags = IFF_NOARP; dev->iflink = 0; -- GitLab From 42aa916265d740d66ac1f17290366e9494c884c2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Oct 2008 11:59:32 -0700 Subject: [PATCH 3558/5416] gre: Move MTU setting out of ipgre_tunnel_bind_dev This patch moves the dev->mtu setting out of ipgre_tunnel_bind_dev. This is in prepartion of using rtnl_link where we'll need to make the MTU setting conditional on whether the user has supplied an MTU. This also requires the move of the ipgre_tunnel_bind_dev call out of the dev->init function so that we can access the user parameters later. This patch also adds a check to prevent setting the MTU below the minimum of 68. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index fd192d67695..80622dd6fb3 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -119,6 +119,7 @@ static int ipgre_tunnel_init(struct net_device *dev); static void ipgre_tunnel_setup(struct net_device *dev); +static int ipgre_tunnel_bind_dev(struct net_device *dev); /* Fallback tunnel: no source, no destination, no key, no options */ @@ -289,6 +290,8 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, nt = netdev_priv(dev); nt->parms = *parms; + dev->mtu = ipgre_tunnel_bind_dev(dev); + if (register_netdevice(dev) < 0) goto failed_free; @@ -773,7 +776,7 @@ tx_error: return 0; } -static void ipgre_tunnel_bind_dev(struct net_device *dev) +static int ipgre_tunnel_bind_dev(struct net_device *dev) { struct net_device *tdev = NULL; struct ip_tunnel *tunnel; @@ -821,9 +824,14 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) addend += 4; } dev->needed_headroom = addend + hlen; - dev->mtu = mtu - dev->hard_header_len - addend; + mtu -= dev->hard_header_len - addend; + + if (mtu < 68) + mtu = 68; + tunnel->hlen = addend; + return mtu; } static int @@ -917,7 +925,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t->parms.iph.frag_off = p.iph.frag_off; if (t->parms.link != p.link) { t->parms.link = p.link; - ipgre_tunnel_bind_dev(dev); + dev->mtu = ipgre_tunnel_bind_dev(dev); netdev_state_change(dev); } } @@ -1108,8 +1116,6 @@ static int ipgre_tunnel_init(struct net_device *dev) memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); - ipgre_tunnel_bind_dev(dev); - if (iph->daddr) { #ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast(iph->daddr)) { -- GitLab From c19e654ddbe3831252f61e76a74d661e1a755530 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Oct 2008 11:59:55 -0700 Subject: [PATCH 3559/5416] gre: Add netlink interface This patch adds a netlink interface that will eventually displace the existing ioctl interface. It utilises the elegant rtnl_link_ops mechanism. This also means that user-space no longer needs to rely on the tunnel interface being of type GRE to identify GRE tunnels. The identification can now occur using rtnl_link_ops. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/if_tunnel.h | 19 +++ net/ipv4/ip_gre.c | 247 +++++++++++++++++++++++++++++++++++++- 2 files changed, 262 insertions(+), 4 deletions(-) diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index d4efe401470..aeab2cb32a9 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -2,6 +2,7 @@ #define _IF_TUNNEL_H_ #include +#include #define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) #define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) @@ -47,4 +48,22 @@ struct ip_tunnel_prl { /* PRL flags */ #define PRL_DEFAULT 0x0001 +enum +{ + IFLA_GRE_UNSPEC, + IFLA_GRE_LINK, + IFLA_GRE_IFLAGS, + IFLA_GRE_OFLAGS, + IFLA_GRE_IKEY, + IFLA_GRE_OKEY, + IFLA_GRE_LOCAL, + IFLA_GRE_REMOTE, + IFLA_GRE_TTL, + IFLA_GRE_TOS, + IFLA_GRE_PMTUDISC, + __IFLA_GRE_MAX, +}; + +#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) + #endif /* _IF_TUNNEL_H_ */ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 80622dd6fb3..25d2c77a7f3 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_IPV6 #include @@ -117,6 +118,7 @@ Alexey Kuznetsov. */ +static struct rtnl_link_ops ipgre_link_ops __read_mostly; static int ipgre_tunnel_init(struct net_device *dev); static void ipgre_tunnel_setup(struct net_device *dev); static int ipgre_tunnel_bind_dev(struct net_device *dev); @@ -286,9 +288,9 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, goto failed_free; } - dev->init = ipgre_tunnel_init; nt = netdev_priv(dev); nt->parms = *parms; + dev->rtnl_link_ops = &ipgre_link_ops; dev->mtu = ipgre_tunnel_bind_dev(dev); @@ -1087,6 +1089,7 @@ static int ipgre_close(struct net_device *dev) static void ipgre_tunnel_setup(struct net_device *dev) { + dev->init = ipgre_tunnel_init; dev->uninit = ipgre_tunnel_uninit; dev->destructor = free_netdev; dev->hard_start_xmit = ipgre_tunnel_xmit; @@ -1196,6 +1199,7 @@ static int ipgre_init_net(struct net *net) ign->fb_tunnel_dev->init = ipgre_fb_tunnel_init; dev_net_set(ign->fb_tunnel_dev, net); + ign->fb_tunnel_dev->rtnl_link_ops = &ipgre_link_ops; if ((err = register_netdev(ign->fb_tunnel_dev))) goto err_reg_dev; @@ -1228,6 +1232,229 @@ static struct pernet_operations ipgre_net_ops = { .exit = ipgre_exit_net, }; +static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + __be16 flags; + + if (!data) + return 0; + + flags = 0; + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (flags & (GRE_VERSION|GRE_ROUTING)) + return -EINVAL; + + return 0; +} + +static void ipgre_netlink_parms(struct nlattr *data[], + struct ip_tunnel_parm *parms) +{ + memset(parms, 0, sizeof(parms)); + + parms->iph.protocol = IPPROTO_GRE; + + if (!data) + return; + + if (data[IFLA_GRE_LINK]) + parms->link = nla_get_u32(data[IFLA_GRE_LINK]); + + if (data[IFLA_GRE_IFLAGS]) + parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]); + + if (data[IFLA_GRE_OFLAGS]) + parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]); + + if (data[IFLA_GRE_IKEY]) + parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); + + if (data[IFLA_GRE_OKEY]) + parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); + + if (data[IFLA_GRE_LOCAL]) + memcpy(&parms->iph.saddr, nla_data(data[IFLA_GRE_LOCAL]), 4); + + if (data[IFLA_GRE_REMOTE]) + memcpy(&parms->iph.daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); + + if (data[IFLA_GRE_TTL]) + parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); + + if (data[IFLA_GRE_TOS]) + parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); + + if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) + parms->iph.frag_off = htons(IP_DF); +} + +static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +{ + struct ip_tunnel *nt; + struct net *net = dev_net(dev); + struct ipgre_net *ign = net_generic(net, ipgre_net_id); + int mtu; + int err; + + nt = netdev_priv(dev); + ipgre_netlink_parms(data, &nt->parms); + + if (ipgre_tunnel_locate(net, &nt->parms, 0)) + return -EEXIST; + + mtu = ipgre_tunnel_bind_dev(dev); + if (!tb[IFLA_MTU]) + dev->mtu = mtu; + + err = register_netdevice(dev); + if (err) + goto out; + + dev_hold(dev); + ipgre_tunnel_link(ign, nt); + +out: + return err; +} + +static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +{ + struct ip_tunnel *t, *nt; + struct net *net = dev_net(dev); + struct ipgre_net *ign = net_generic(net, ipgre_net_id); + struct ip_tunnel_parm p; + int mtu; + + if (dev == ign->fb_tunnel_dev) + return -EINVAL; + + nt = netdev_priv(dev); + ipgre_netlink_parms(data, &p); + + t = ipgre_tunnel_locate(net, &p, 0); + + if (t) { + if (t->dev != dev) + return -EEXIST; + } else { + unsigned nflags = 0; + + t = nt; + + if (ipv4_is_multicast(p.iph.daddr)) + nflags = IFF_BROADCAST; + else if (p.iph.daddr) + nflags = IFF_POINTOPOINT; + + if ((dev->flags ^ nflags) & + (IFF_POINTOPOINT | IFF_BROADCAST)) + return -EINVAL; + + ipgre_tunnel_unlink(ign, t); + t->parms.iph.saddr = p.iph.saddr; + t->parms.iph.daddr = p.iph.daddr; + t->parms.i_key = p.i_key; + memcpy(dev->dev_addr, &p.iph.saddr, 4); + memcpy(dev->broadcast, &p.iph.daddr, 4); + ipgre_tunnel_link(ign, t); + netdev_state_change(dev); + } + + t->parms.o_key = p.o_key; + t->parms.iph.ttl = p.iph.ttl; + t->parms.iph.tos = p.iph.tos; + t->parms.iph.frag_off = p.iph.frag_off; + + if (t->parms.link != p.link) { + t->parms.link = p.link; + mtu = ipgre_tunnel_bind_dev(dev); + if (!tb[IFLA_MTU]) + dev->mtu = mtu; + netdev_state_change(dev); + } + + return 0; +} + +static size_t ipgre_get_size(const struct net_device *dev) +{ + return + /* IFLA_GRE_LINK */ + nla_total_size(4) + + /* IFLA_GRE_IFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_OFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_IKEY */ + nla_total_size(4) + + /* IFLA_GRE_OKEY */ + nla_total_size(4) + + /* IFLA_GRE_LOCAL */ + nla_total_size(4) + + /* IFLA_GRE_REMOTE */ + nla_total_size(4) + + /* IFLA_GRE_TTL */ + nla_total_size(1) + + /* IFLA_GRE_TOS */ + nla_total_size(1) + + /* IFLA_GRE_PMTUDISC */ + nla_total_size(1) + + 0; +} + +static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct ip_tunnel *t = netdev_priv(dev); + struct ip_tunnel_parm *p = &t->parms; + + NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link); + NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags); + NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags); + NLA_PUT_BE32(skb, IFLA_GRE_IFLAGS, p->i_flags); + NLA_PUT_BE32(skb, IFLA_GRE_OFLAGS, p->o_flags); + NLA_PUT(skb, IFLA_GRE_LOCAL, 4, &p->iph.saddr); + NLA_PUT(skb, IFLA_GRE_REMOTE, 4, &p->iph.daddr); + NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl); + NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos); + NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF))); + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .len = 4 }, + [IFLA_GRE_REMOTE] = { .len = 4 }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_TOS] = { .type = NLA_U8 }, + [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, +}; + +static struct rtnl_link_ops ipgre_link_ops __read_mostly = { + .kind = "gre", + .maxtype = IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = ipgre_tunnel_setup, + .validate = ipgre_tunnel_validate, + .newlink = ipgre_newlink, + .changelink = ipgre_changelink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +}; + /* * And now the modules code and kernel interface. */ @@ -1245,19 +1472,31 @@ static int __init ipgre_init(void) err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops); if (err < 0) - inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); + goto gen_device_failed; + err = rtnl_link_register(&ipgre_link_ops); + if (err < 0) + goto rtnl_link_failed; + +out: return err; + +rtnl_link_failed: + unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); +gen_device_failed: + inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); + goto out; } static void __exit ipgre_fini(void) { + rtnl_link_unregister(&ipgre_link_ops); + unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); - - unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); } module_init(ipgre_init); module_exit(ipgre_fini); MODULE_LICENSE("GPL"); +MODULE_ALIAS("rtnl-link-gre"); -- GitLab From e1a8000228e16212c93b23cfbed4d622e2ec7a6b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Oct 2008 12:00:17 -0700 Subject: [PATCH 3560/5416] gre: Add Transparent Ethernet Bridging This patch adds support for Ethernet over GRE encapsulation. This is exposed to user-space with a new link type of "gretap" instead of "gre". It will create an ARPHRD_ETHER device in lieu of the usual ARPHRD_IPGRE. Note that to preserver backwards compatibility all Transparent Ethernet Bridging packets are passed to an ARPHRD_IPGRE tunnel if its key matches and there is no ARPHRD_ETHER device whose key matches more closely. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/if_ether.h | 1 + net/ipv4/ip_gre.c | 206 +++++++++++++++++++++++++++++++++------ 2 files changed, 175 insertions(+), 32 deletions(-) diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index a0099e98b5c..bf1a53b2682 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -56,6 +56,7 @@ #define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ #define ETH_P_CUST 0x6006 /* DEC Customer use */ #define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ #define ETH_P_ATALK 0x809B /* Appletalk DDP */ #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 25d2c77a7f3..44ed9487fa1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -166,38 +167,64 @@ static DEFINE_RWLOCK(ipgre_lock); /* Given src, dst and key, find appropriate for input tunnel. */ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, - __be32 remote, __be32 local, __be32 key) + __be32 remote, __be32 local, + __be32 key, __be16 gre_proto) { unsigned h0 = HASH(remote); unsigned h1 = HASH(key); struct ip_tunnel *t; + struct ip_tunnel *t2 = NULL; struct ipgre_net *ign = net_generic(net, ipgre_net_id); + int dev_type = (gre_proto == htons(ETH_P_TEB)) ? + ARPHRD_ETHER : ARPHRD_IPGRE; for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { - if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) - return t; + if (t->parms.i_key == key && t->dev->flags & IFF_UP) { + if (t->dev->type == dev_type) + return t; + if (t->dev->type == ARPHRD_IPGRE && !t2) + t2 = t; + } } } + for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { if (remote == t->parms.iph.daddr) { - if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) - return t; + if (t->parms.i_key == key && t->dev->flags & IFF_UP) { + if (t->dev->type == dev_type) + return t; + if (t->dev->type == ARPHRD_IPGRE && !t2) + t2 = t; + } } } + for (t = ign->tunnels_l[h1]; t; t = t->next) { if (local == t->parms.iph.saddr || (local == t->parms.iph.daddr && ipv4_is_multicast(local))) { - if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) - return t; + if (t->parms.i_key == key && t->dev->flags & IFF_UP) { + if (t->dev->type == dev_type) + return t; + if (t->dev->type == ARPHRD_IPGRE && !t2) + t2 = t; + } } } + for (t = ign->tunnels_wc[h1]; t; t = t->next) { - if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) - return t; + if (t->parms.i_key == key && t->dev->flags & IFF_UP) { + if (t->dev->type == dev_type) + return t; + if (t->dev->type == ARPHRD_IPGRE && !t2) + t2 = t; + } } + if (t2) + return t2; + if (ign->fb_tunnel_dev->flags&IFF_UP) return netdev_priv(ign->fb_tunnel_dev); return NULL; @@ -252,25 +279,37 @@ static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t) } } -static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, - struct ip_tunnel_parm *parms, int create) +static struct ip_tunnel *ipgre_tunnel_find(struct net *net, + struct ip_tunnel_parm *parms, + int type) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; __be32 key = parms->i_key; - struct ip_tunnel *t, **tp, *nt; + struct ip_tunnel *t, **tp; + struct ipgre_net *ign = net_generic(net, ipgre_net_id); + + for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && + key == t->parms.i_key && + type == t->dev->type) + break; + + return t; +} + +static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, + struct ip_tunnel_parm *parms, int create) +{ + struct ip_tunnel *t, *nt; struct net_device *dev; char name[IFNAMSIZ]; struct ipgre_net *ign = net_generic(net, ipgre_net_id); - for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) { - if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { - if (key == t->parms.i_key) - return t; - } - } - if (!create) - return NULL; + t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE); + if (t || !create) + return t; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); @@ -385,8 +424,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info) read_lock(&ipgre_lock); t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr, - (flags&GRE_KEY) ? - *(((__be32*)p) + (grehlen>>2) - 1) : 0); + flags & GRE_KEY ? + *(((__be32 *)p) + (grehlen / 4) - 1) : 0, + p[1]); if (t == NULL || t->parms.iph.daddr == 0 || ipv4_is_multicast(t->parms.iph.daddr)) goto out; @@ -436,6 +476,7 @@ static int ipgre_rcv(struct sk_buff *skb) u32 seqno = 0; struct ip_tunnel *tunnel; int offset = 4; + __be16 gre_proto; if (!pskb_may_pull(skb, 16)) goto drop_nolock; @@ -475,20 +516,22 @@ static int ipgre_rcv(struct sk_buff *skb) } } + gre_proto = *(__be16 *)(h + 2); + read_lock(&ipgre_lock); if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), - iph->saddr, iph->daddr, key)) != NULL) { + iph->saddr, iph->daddr, key, + gre_proto))) { struct net_device_stats *stats = &tunnel->dev->stats; secpath_reset(skb); - skb->protocol = *(__be16*)(h + 2); + skb->protocol = gre_proto; /* WCCP version 1 and 2 protocol decoding. * - Change protocol to IP * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header */ - if (flags == 0 && - skb->protocol == htons(ETH_P_WCCP)) { + if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) { skb->protocol = htons(ETH_P_IP); if ((*(h + offset) & 0xF0) != 0x40) offset += 4; @@ -496,7 +539,6 @@ static int ipgre_rcv(struct sk_buff *skb) skb->mac_header = skb->network_header; __pskb_pull(skb, offset); - skb_reset_network_header(skb); skb_postpull_rcsum(skb, skb_transport_header(skb), offset); skb->pkt_type = PACKET_HOST; #ifdef CONFIG_NET_IPGRE_BROADCAST @@ -524,13 +566,30 @@ static int ipgre_rcv(struct sk_buff *skb) } tunnel->i_seqno = seqno + 1; } + + /* Warning: All skb pointers will be invalidated! */ + if (tunnel->dev->type == ARPHRD_ETHER) { + if (!pskb_may_pull(skb, ETH_HLEN)) { + stats->rx_length_errors++; + stats->rx_errors++; + goto drop; + } + + iph = ip_hdr(skb); + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + } + stats->rx_packets++; stats->rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; nf_reset(skb); + + skb_reset_network_header(skb); ipgre_ecn_decapsulate(iph, skb); + netif_rx(skb); read_unlock(&ipgre_lock); return(0); @@ -565,7 +624,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_error; } - if (dev->header_ops) { + if (dev->type == ARPHRD_ETHER) + IPCB(skb)->flags = 0; + + if (dev->header_ops && dev->type == ARPHRD_IPGRE) { gre_hlen = 0; tiph = (struct iphdr*)skb->data; } else { @@ -741,8 +803,9 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); } - ((__be16*)(iph+1))[0] = tunnel->parms.o_flags; - ((__be16*)(iph+1))[1] = skb->protocol; + ((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags; + ((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ? + htons(ETH_P_TEB) : skb->protocol; if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4); @@ -804,7 +867,9 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) tdev = rt->u.dst.dev; ip_rt_put(rt); } - dev->flags |= IFF_POINTOPOINT; + + if (dev->type != ARPHRD_ETHER) + dev->flags |= IFF_POINTOPOINT; } if (!tdev && tunnel->parms.link) @@ -1250,6 +1315,30 @@ static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) return 0; } +static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + __be32 daddr; + + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + + if (!data) + goto out; + + if (data[IFLA_GRE_REMOTE]) { + memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); + if (!daddr) + return -EINVAL; + } + +out: + return ipgre_tunnel_validate(tb, data); +} + static void ipgre_netlink_parms(struct nlattr *data[], struct ip_tunnel_parm *parms) { @@ -1291,6 +1380,35 @@ static void ipgre_netlink_parms(struct nlattr *data[], parms->iph.frag_off = htons(IP_DF); } +static int ipgre_tap_init(struct net_device *dev) +{ + struct ip_tunnel *tunnel; + + tunnel = netdev_priv(dev); + + tunnel->dev = dev; + strcpy(tunnel->parms.name, dev->name); + + ipgre_tunnel_bind_dev(dev); + + return 0; +} + +static void ipgre_tap_setup(struct net_device *dev) +{ + + ether_setup(dev); + + dev->init = ipgre_tap_init; + dev->uninit = ipgre_tunnel_uninit; + dev->destructor = free_netdev; + dev->hard_start_xmit = ipgre_tunnel_xmit; + dev->change_mtu = ipgre_tunnel_change_mtu; + + dev->iflink = 0; + dev->features |= NETIF_F_NETNS_LOCAL; +} + static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { @@ -1303,9 +1421,12 @@ static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], nt = netdev_priv(dev); ipgre_netlink_parms(data, &nt->parms); - if (ipgre_tunnel_locate(net, &nt->parms, 0)) + if (ipgre_tunnel_find(net, &nt->parms, dev->type)) return -EEXIST; + if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) + random_ether_addr(dev->dev_addr); + mtu = ipgre_tunnel_bind_dev(dev); if (!tb[IFLA_MTU]) dev->mtu = mtu; @@ -1455,6 +1576,19 @@ static struct rtnl_link_ops ipgre_link_ops __read_mostly = { .fill_info = ipgre_fill_info, }; +static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { + .kind = "gretap", + .maxtype = IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = ipgre_tap_setup, + .validate = ipgre_tap_validate, + .newlink = ipgre_newlink, + .changelink = ipgre_changelink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +}; + /* * And now the modules code and kernel interface. */ @@ -1478,9 +1612,15 @@ static int __init ipgre_init(void) if (err < 0) goto rtnl_link_failed; + err = rtnl_link_register(&ipgre_tap_ops); + if (err < 0) + goto tap_ops_failed; + out: return err; +tap_ops_failed: + rtnl_link_unregister(&ipgre_link_ops); rtnl_link_failed: unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); gen_device_failed: @@ -1490,6 +1630,7 @@ gen_device_failed: static void __exit ipgre_fini(void) { + rtnl_link_unregister(&ipgre_tap_ops); rtnl_link_unregister(&ipgre_link_ops); unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) @@ -1500,3 +1641,4 @@ module_init(ipgre_init); module_exit(ipgre_fini); MODULE_LICENSE("GPL"); MODULE_ALIAS("rtnl-link-gre"); +MODULE_ALIAS("rtnl-link-gretap"); -- GitLab From 64194c31a0b6f5d84703b772113aafc400eeaad6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Oct 2008 12:03:17 -0700 Subject: [PATCH 3561/5416] inet: Make tunnel RX/TX byte counters more consistent This patch makes the RX/TX byte counters for IPIP, GRE and SIT more consistent. Previously we included the external IP headers on the way out but not when the packet is inbound. The new scheme is to count payload only in both directions. For IPIP and SIT this simply means the exclusion of the external IP header. For GRE this means that we exclude the GRE header as well. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/ipip.h | 2 +- net/ipv4/ip_gre.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/net/ipip.h b/include/net/ipip.h index a85bda64b85..fdf9bd74370 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -37,7 +37,7 @@ struct ip_tunnel_prl_entry #define IPTUNNEL_XMIT() do { \ int err; \ - int pkt_len = skb->len; \ + int pkt_len = skb->len - skb_transport_offset(skb); \ \ skb->ip_summed = CHECKSUM_NONE; \ ip_select_ident(iph, &rt->u.dst, NULL); \ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 44ed9487fa1..0d5e35b0ed5 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -477,6 +477,7 @@ static int ipgre_rcv(struct sk_buff *skb) struct ip_tunnel *tunnel; int offset = 4; __be16 gre_proto; + unsigned int len; if (!pskb_may_pull(skb, 16)) goto drop_nolock; @@ -567,6 +568,8 @@ static int ipgre_rcv(struct sk_buff *skb) tunnel->i_seqno = seqno + 1; } + len = skb->len; + /* Warning: All skb pointers will be invalidated! */ if (tunnel->dev->type == ARPHRD_ETHER) { if (!pskb_may_pull(skb, ETH_HLEN)) { @@ -581,7 +584,7 @@ static int ipgre_rcv(struct sk_buff *skb) } stats->rx_packets++; - stats->rx_bytes += skb->len; + stats->rx_bytes += len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; @@ -770,7 +773,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) old_iph = ip_hdr(skb); } - skb->transport_header = skb->network_header; + skb_reset_transport_header(skb); skb_push(skb, gre_hlen); skb_reset_network_header(skb); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); -- GitLab From 70096a561d1e09120bae1f293f3632cedbfd5c68 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Wed, 8 Oct 2008 14:51:57 -0500 Subject: [PATCH 3562/5416] SLOB: fix bogus ksize calculation fix This fixes the previous fix, which was completely wrong on closer inspection. This version has been manually tested with a user-space test harness and generates sane values. A nearly identical patch has been boot-tested. The problem arose from changing how kmalloc/kfree handled alignment padding without updating ksize to match. This brings it in sync. Signed-off-by: Matt Mackall Signed-off-by: Linus Torvalds --- mm/slob.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mm/slob.c b/mm/slob.c index 62b679dc660..cb675d12679 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -514,9 +514,11 @@ size_t ksize(const void *block) return 0; sp = (struct slob_page *)virt_to_page(block); - if (slob_page(sp)) - return (((slob_t *)block - 1)->units - 1) * SLOB_UNIT; - else + if (slob_page(sp)) { + int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + unsigned int *m = (unsigned int *)(block - align); + return SLOB_UNITS(*m) * SLOB_UNIT; + } else return sp->page.private; } -- GitLab From 74bf4ba3d367aacbc04fef167289767f162cd730 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 9 Oct 2008 12:21:08 -0700 Subject: [PATCH 3563/5416] bnx2: Add bnx2_shutdown_chip(). This logic is used in bnx2_close() and bnx2_suspend() and so should be separated out into a separate function. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 883e0a72410..b35f440361d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -5072,6 +5072,21 @@ bnx2_init_nic(struct bnx2 *bp, int reset_phy) return 0; } +static int +bnx2_shutdown_chip(struct bnx2 *bp) +{ + u32 reset_code; + + if (bp->flags & BNX2_FLAG_NO_WOL) + reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; + else if (bp->wol) + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; + else + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; + + return bnx2_reset_chip(bp, reset_code); +} + static int bnx2_test_registers(struct bnx2 *bp) { @@ -6095,20 +6110,13 @@ static int bnx2_close(struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); - u32 reset_code; cancel_work_sync(&bp->reset_task); bnx2_disable_int_sync(bp); bnx2_napi_disable(bp); del_timer_sync(&bp->timer); - if (bp->flags & BNX2_FLAG_NO_WOL) - reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; - else if (bp->wol) - reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; - else - reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; - bnx2_reset_chip(bp, reset_code); + bnx2_shutdown_chip(bp); bnx2_free_irq(bp); bnx2_free_skbs(bp); bnx2_free_mem(bp); @@ -7777,7 +7785,6 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct bnx2 *bp = netdev_priv(dev); - u32 reset_code; /* PCI register 4 needs to be saved whether netif_running() or not. * MSI address and data need to be saved if using MSI and @@ -7791,13 +7798,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) bnx2_netif_stop(bp); netif_device_detach(dev); del_timer_sync(&bp->timer); - if (bp->flags & BNX2_FLAG_NO_WOL) - reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; - else if (bp->wol) - reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; - else - reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; - bnx2_reset_chip(bp, reset_code); + bnx2_shutdown_chip(bp); bnx2_free_skbs(bp); bnx2_set_power_state(bp, pci_choose_state(pdev, state)); return 0; -- GitLab From 9f52b564b7162ede5a73a4f4b421ccf93c55b025 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 9 Oct 2008 12:21:46 -0700 Subject: [PATCH 3564/5416] bnx2: Check netif_running() in all ethtool operations. We need to check netif_running() state in most ethtool operations and properly handle the !netif_running() state where the chip is in an uninitailzed state or low power state that may not accept any MMIO. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b35f440361d..21711c753a0 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3248,6 +3248,9 @@ bnx2_set_rx_mode(struct net_device *dev) struct dev_addr_list *uc_ptr; int i; + if (!netif_running(dev)) + return; + spin_lock_bh(&bp->phy_lock); rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS | @@ -5521,6 +5524,9 @@ bnx2_test_link(struct bnx2 *bp) { u32 bmsr; + if (!netif_running(bp->dev)) + return -ENODEV; + if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) { if (bp->link_up) return 0; @@ -6485,6 +6491,9 @@ bnx2_nway_reset(struct net_device *dev) struct bnx2 *bp = netdev_priv(dev); u32 bmcr; + if (!netif_running(dev)) + return -EAGAIN; + if (!(bp->autoneg & AUTONEG_SPEED)) { return -EINVAL; } @@ -6540,6 +6549,9 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, struct bnx2 *bp = netdev_priv(dev); int rc; + if (!netif_running(dev)) + return -EAGAIN; + /* parameters already validated in ethtool_get_eeprom */ rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); @@ -6554,6 +6566,9 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, struct bnx2 *bp = netdev_priv(dev); int rc; + if (!netif_running(dev)) + return -EAGAIN; + /* parameters already validated in ethtool_set_eeprom */ rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); @@ -6718,11 +6733,11 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) bp->autoneg &= ~AUTONEG_FLOW_CTRL; } - spin_lock_bh(&bp->phy_lock); - - bnx2_setup_phy(bp, bp->phy_port); - - spin_unlock_bh(&bp->phy_lock); + if (netif_running(dev)) { + spin_lock_bh(&bp->phy_lock); + bnx2_setup_phy(bp, bp->phy_port); + spin_unlock_bh(&bp->phy_lock); + } return 0; } @@ -6913,6 +6928,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) { struct bnx2 *bp = netdev_priv(dev); + bnx2_set_power_state(bp, PCI_D0); + memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); if (etest->flags & ETH_TEST_FL_OFFLINE) { int i; @@ -6932,9 +6949,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) if ((buf[2] = bnx2_test_loopback(bp)) != 0) etest->flags |= ETH_TEST_FL_FAILED; - if (!netif_running(bp->dev)) { - bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); - } + if (!netif_running(bp->dev)) + bnx2_shutdown_chip(bp); else { bnx2_init_nic(bp, 1); bnx2_netif_start(bp); @@ -6962,6 +6978,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) etest->flags |= ETH_TEST_FL_FAILED; } + if (!netif_running(bp->dev)) + bnx2_set_power_state(bp, PCI_D3hot); } static void @@ -7027,6 +7045,8 @@ bnx2_phys_id(struct net_device *dev, u32 data) int i; u32 save; + bnx2_set_power_state(bp, PCI_D0); + if (data == 0) data = 2; @@ -7051,6 +7071,10 @@ bnx2_phys_id(struct net_device *dev, u32 data) } REG_WR(bp, BNX2_EMAC_LED, 0); REG_WR(bp, BNX2_MISC_CFG, save); + + if (!netif_running(dev)) + bnx2_set_power_state(bp, PCI_D3hot); + return 0; } -- GitLab From d5321e309c2fd1a1d534fc7bb674a1fff9f25d94 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 9 Oct 2008 12:22:38 -0700 Subject: [PATCH 3565/5416] bnx2: Update 5706/5708 firmware. With this new firmware, the driver no longer has to modify the TCP/IP header fields when transmitting TSO packets. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2_fw.h | 8654 ++++++++++++++++++++--------------------- 1 file changed, 4304 insertions(+), 4350 deletions(-) diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index e4b1de43556..24c3cc40c23 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -15,854 +15,854 @@ */ static u8 bnx2_COM_b06FwText[] = { - 0xcd, 0x7c, 0x0d, 0x70, 0x5c, 0xd5, 0x95, 0xe6, 0xe9, 0xd7, 0xdd, 0x52, - 0x4b, 0x96, 0xe5, 0x27, 0xb9, 0x51, 0x1a, 0xa2, 0x24, 0xef, 0xa9, 0x9f, - 0xa4, 0x06, 0x29, 0xe4, 0xd9, 0x08, 0x10, 0x49, 0x0f, 0x34, 0xdd, 0x92, - 0x11, 0x89, 0x77, 0x24, 0x40, 0x61, 0xbc, 0x3b, 0xae, 0xac, 0xa6, 0x2d, - 0x13, 0x42, 0x31, 0x35, 0xae, 0x0a, 0x3b, 0x71, 0xb2, 0x04, 0x37, 0x2d, - 0x99, 0x38, 0x8c, 0xec, 0x56, 0x64, 0x59, 0x66, 0x67, 0xd8, 0xd9, 0x4e, - 0x4b, 0xb2, 0x19, 0xa6, 0xed, 0xc6, 0x90, 0x1f, 0xa6, 0x92, 0x0c, 0x5a, - 0xe3, 0x00, 0x93, 0xcd, 0x56, 0x41, 0x2a, 0xb5, 0xcb, 0x6c, 0x51, 0xbb, - 0x5e, 0x27, 0x4c, 0xb2, 0xa9, 0xda, 0x0a, 0x3b, 0x93, 0xda, 0x65, 0xf2, - 0x33, 0x6f, 0xbf, 0xef, 0xbe, 0xfb, 0xa4, 0x96, 0xac, 0x38, 0x4c, 0xa6, - 0x52, 0x35, 0xaa, 0xea, 0xba, 0xef, 0xde, 0x77, 0x7f, 0xce, 0x3d, 0xf7, - 0xdc, 0x73, 0xbe, 0x73, 0xee, 0x7d, 0xba, 0x55, 0xa4, 0x59, 0xf4, 0xdf, - 0x56, 0xfc, 0x06, 0x7e, 0xff, 0x0f, 0xf6, 0xdd, 0x78, 0xbd, 0x7b, 0x3d, - 0xf3, 0x46, 0x54, 0x22, 0x4c, 0xc3, 0xf8, 0xc5, 0xf1, 0xdb, 0xa9, 0x9f, - 0x37, 0xfb, 0x33, 0xf1, 0xbb, 0x29, 0x24, 0x32, 0xf1, 0x23, 0x91, 0xd0, - 0x86, 0x77, 0xb1, 0x4d, 0xea, 0x7b, 0xde, 0x2f, 0xe9, 0x48, 0xff, 0x19, - 0xf8, 0x59, 0x57, 0xae, 0xb2, 0x3a, 0xee, 0xaf, 0xfb, 0x17, 0xd6, 0xcd, - 0xb7, 0xea, 0x9f, 0xc4, 0x8c, 0xf4, 0xc5, 0xdf, 0xce, 0x3a, 0x12, 0x0b, - 0xa7, 0xbf, 0x3b, 0xba, 0xcf, 0x11, 0xc9, 0x54, 0xfb, 0xac, 0x9c, 0xfc, - 0xc2, 0x2b, 0xc4, 0x23, 0xc2, 0xf2, 0xf7, 0xa4, 0x7f, 0x7e, 0xe8, 0x1b, - 0x37, 0xdb, 0x6f, 0x95, 0xc3, 0x12, 0x33, 0xd3, 0x6f, 0x8b, 0xd9, 0x23, - 0xb1, 0x4e, 0xb4, 0x79, 0xb2, 0xf7, 0x29, 0x43, 0x5a, 0x83, 0xbe, 0xcc, - 0x89, 0x70, 0x5a, 0xc6, 0x26, 0x67, 0x0e, 0x79, 0x86, 0x23, 0x85, 0x6b, - 0xd2, 0x8e, 0x55, 0x94, 0x96, 0xc1, 0xe9, 0x81, 0x9b, 0x05, 0xf9, 0xb1, - 0xc9, 0x6a, 0x4c, 0xb2, 0xb5, 0x42, 0x8b, 0xe1, 0x38, 0x48, 0x63, 0x85, - 0x77, 0xa7, 0x25, 0xd6, 0x90, 0x9e, 0x6f, 0x7c, 0xc9, 0xe1, 0xf8, 0x89, - 0xd1, 0xac, 0xf3, 0x6e, 0x89, 0x38, 0x9e, 0x37, 0x8d, 0xf1, 0x77, 0x55, - 0x7f, 0xe1, 0x3d, 0x1a, 0xf1, 0xc7, 0x36, 0xd2, 0x07, 0xc3, 0x4c, 0x43, - 0x69, 0x6b, 0xb4, 0xab, 0xaa, 0xf2, 0x0d, 0x7e, 0xde, 0xd1, 0xf9, 0x58, - 0xb3, 0x4f, 0xbb, 0x34, 0x81, 0xf6, 0x58, 0x24, 0x9d, 0x6e, 0x42, 0x1f, - 0xb1, 0x68, 0xfa, 0x99, 0xdf, 0x5a, 0x56, 0xf5, 0xee, 0xd7, 0xf5, 0xee, - 0x8f, 0xfa, 0xed, 0x26, 0x47, 0x7b, 0xaa, 0x4c, 0x1f, 0x1a, 0xed, 0x56, - 0xe9, 0xc3, 0xa3, 0x49, 0x95, 0x16, 0x54, 0xbd, 0x50, 0x7a, 0x7a, 0xd4, - 0x51, 0x69, 0xa7, 0x2e, 0x4f, 0x8d, 0x5a, 0x2a, 0xed, 0xd7, 0xa9, 0xab, - 0xd3, 0x01, 0x9d, 0x0e, 0xea, 0x34, 0xad, 0xd3, 0x8c, 0x4e, 0x87, 0x74, - 0x3f, 0x23, 0x3a, 0xbf, 0x5b, 0xa7, 0x63, 0x3a, 0x1d, 0xd7, 0xe9, 0x1e, - 0x9d, 0xee, 0xd5, 0x74, 0x4d, 0xe8, 0xf4, 0x41, 0x5d, 0x7e, 0x40, 0xd3, - 0x79, 0x10, 0xf4, 0x7c, 0xa6, 0x51, 0xcb, 0x2d, 0xe6, 0x6b, 0xc9, 0xbe, - 0x99, 0x98, 0x14, 0x4b, 0x61, 0xc9, 0xa9, 0xf5, 0xfc, 0x7c, 0x54, 0x9a, - 0x63, 0x32, 0x55, 0x8b, 0xc9, 0x45, 0x25, 0xae, 0x3f, 0xf4, 0xbe, 0xd1, - 0x6b, 0xca, 0x33, 0xb5, 0xb8, 0xbc, 0x50, 0x93, 0xd0, 0x58, 0x6f, 0x93, - 0x18, 0x73, 0xd7, 0x48, 0xc6, 0x0c, 0x49, 0x58, 0xf1, 0xd5, 0x92, 0xec, - 0x4c, 0x07, 0xf2, 0x76, 0x42, 0xe4, 0xe5, 0xa8, 0xbf, 0x8e, 0x31, 0x09, - 0x2f, 0x70, 0x5d, 0x16, 0x46, 0x5f, 0x9a, 0x4f, 0x48, 0xe4, 0x98, 0x85, - 0xfe, 0x5b, 0x24, 0xba, 0x20, 0x9d, 0x61, 0xe9, 0x4e, 0xdc, 0x87, 0x1a, - 0x43, 0xd5, 0x88, 0x0c, 0x57, 0x43, 0x58, 0xab, 0x18, 0xe4, 0xa4, 0x05, - 0x3f, 0x13, 0xbf, 0x38, 0x7e, 0x09, 0xfc, 0x3c, 0xf4, 0xd3, 0x29, 0xb9, - 0x2a, 0xfb, 0xc4, 0xb8, 0x25, 0x8c, 0x5f, 0xb2, 0xcd, 0x09, 0x21, 0x4d, - 0x09, 0xf9, 0x46, 0xaf, 0x4f, 0xd3, 0x0b, 0xb5, 0x58, 0x28, 0x7b, 0x52, - 0x0e, 0xe4, 0x5c, 0xb1, 0x0c, 0xa7, 0x59, 0xf2, 0x66, 0xc8, 0x9a, 0x4c, - 0xb5, 0x4b, 0x61, 0x1c, 0xef, 0x4a, 0x92, 0x31, 0xd0, 0x77, 0xde, 0x94, - 0x09, 0xff, 0x1d, 0xcb, 0xfe, 0x1e, 0xfb, 0xd5, 0x36, 0x29, 0xb8, 0x2f, - 0x94, 0xfe, 0x02, 0xcf, 0xec, 0xeb, 0xcd, 0x88, 0x4f, 0xf3, 0xdb, 0xc8, - 0xb3, 0xfc, 0x67, 0xdb, 0xfc, 0x3c, 0x9f, 0x59, 0x37, 0x18, 0x33, 0x98, - 0x2b, 0xc7, 0xee, 0xc5, 0x7c, 0x39, 0xfe, 0xea, 0x7c, 0x41, 0x47, 0x4b, - 0x28, 0x77, 0xd2, 0x92, 0xc3, 0xa5, 0x5b, 0x25, 0xeb, 0x7a, 0xde, 0x3e, - 0x57, 0xe2, 0x86, 0x74, 0x9b, 0x39, 0xbc, 0xad, 0x54, 0x25, 0x94, 0x2d, - 0x05, 0xfc, 0x60, 0xbf, 0x11, 0x94, 0x75, 0xa0, 0x7e, 0x6b, 0x68, 0xe8, - 0x24, 0x68, 0x4f, 0x93, 0x2f, 0x90, 0x59, 0xb7, 0x3b, 0x31, 0x89, 0xf1, - 0x16, 0xab, 0xdd, 0xee, 0x79, 0x31, 0xd1, 0x67, 0x3b, 0xea, 0x90, 0x47, - 0xec, 0x8b, 0x7d, 0xb2, 0xbf, 0x16, 0xb4, 0x8d, 0xe3, 0x1d, 0x69, 0xf2, - 0xbc, 0xac, 0x6b, 0x32, 0x2f, 0x65, 0xf0, 0xad, 0x4c, 0xbe, 0x35, 0x77, - 0xca, 0xa9, 0x2a, 0xc7, 0xd8, 0x8c, 0xee, 0xeb, 0xfe, 0x99, 0xd1, 0x9d, - 0x40, 0xff, 0x71, 0xa4, 0x5b, 0x42, 0xd9, 0xe3, 0x1e, 0xc6, 0x4f, 0xe0, - 0x79, 0xb3, 0x39, 0x5c, 0xd4, 0x32, 0x98, 0x00, 0xed, 0x71, 0x39, 0xa7, - 0xe4, 0x70, 0x8b, 0x84, 0x21, 0x87, 0x5c, 0xe3, 0xb6, 0x85, 0x1b, 0x25, - 0x1f, 0xb7, 0x2d, 0xea, 0xce, 0xae, 0x9d, 0x4d, 0x98, 0xa3, 0xd6, 0x82, - 0xc7, 0xe2, 0x90, 0xc3, 0xf3, 0x6d, 0x06, 0x4a, 0x0c, 0xb1, 0xcd, 0x7f, - 0x25, 0x05, 0xc9, 0x2d, 0x7d, 0x2a, 0x24, 0xcd, 0x06, 0xea, 0x5d, 0x1b, - 0xf2, 0x79, 0x40, 0xfe, 0x64, 0xc0, 0x9f, 0x90, 0xf8, 0xfb, 0x3a, 0x23, - 0x5d, 0x55, 0xbe, 0xef, 0xb3, 0x0c, 0xf5, 0x6e, 0x08, 0xef, 0x22, 0x92, - 0xdc, 0x19, 0xbc, 0x1f, 0xc2, 0xfb, 0x6b, 0x64, 0xc2, 0x04, 0x2d, 0xa5, - 0xe7, 0x8d, 0x2c, 0x68, 0xbc, 0x3d, 0xa2, 0xe6, 0x8a, 0xba, 0x13, 0x75, - 0xfd, 0x4c, 0xa0, 0xde, 0x1f, 0x63, 0x2c, 0xd0, 0x5b, 0xb2, 0x40, 0x4b, - 0x07, 0x68, 0x21, 0x8d, 0x05, 0x23, 0x5b, 0x8b, 0x20, 0x3f, 0x6d, 0xe4, - 0x4e, 0x1f, 0xc1, 0xb3, 0x98, 0x46, 0xfa, 0x79, 0xa6, 0x68, 0xbf, 0xb7, - 0xae, 0xfd, 0x5e, 0xb4, 0xe7, 0x18, 0x6c, 0xef, 0xcb, 0x7f, 0x41, 0xc9, - 0xa2, 0x75, 0x05, 0x7e, 0x84, 0x7f, 0x0d, 0x7e, 0x7c, 0x4d, 0xf3, 0xe3, - 0x67, 0xf2, 0x9b, 0xe7, 0xc7, 0x7f, 0xff, 0x0d, 0xf1, 0x43, 0x24, 0x7f, - 0x9c, 0xcf, 0x11, 0x29, 0x28, 0xbd, 0xc5, 0x7d, 0x4b, 0x79, 0xa7, 0xce, - 0x22, 0x9f, 0x28, 0xc7, 0xd8, 0x03, 0xb5, 0x08, 0xd2, 0xa7, 0x90, 0x6e, - 0x09, 0x8d, 0x1d, 0xbf, 0x84, 0xf5, 0xf7, 0xc4, 0xdc, 0x19, 0xd8, 0x8d, - 0x42, 0xc2, 0x94, 0x4e, 0x31, 0xaf, 0x87, 0xd1, 0xee, 0xb0, 0xcd, 0xbc, - 0xbc, 0x89, 0xf7, 0xbf, 0x08, 0x05, 0xf6, 0x3d, 0x3b, 0xd3, 0xf4, 0x76, - 0x46, 0x3d, 0x45, 0xc9, 0xcf, 0x8c, 0x91, 0x8e, 0x84, 0x72, 0x25, 0x6b, - 0xc2, 0x48, 0xc7, 0xa1, 0xa7, 0x98, 0x1f, 0x0c, 0xf9, 0x34, 0x0f, 0xa0, - 0x6e, 0xa0, 0xb3, 0x02, 0xda, 0x07, 0x40, 0xfb, 0x46, 0xdd, 0x95, 0x01, - 0x2d, 0xa4, 0x81, 0x74, 0x55, 0xc2, 0x9a, 0xf7, 0xe8, 0xe7, 0xa0, 0xea, - 0x27, 0x9c, 0x1e, 0x14, 0xda, 0xd0, 0xfc, 0x0c, 0xf7, 0x01, 0xdb, 0xb1, - 0x2f, 0x5f, 0x27, 0xe7, 0xab, 0x41, 0x1f, 0x85, 0xba, 0x3e, 0x0a, 0xa0, - 0x47, 0xb6, 0x19, 0x4e, 0x14, 0x6b, 0xcf, 0xae, 0x8e, 0xe0, 0xdd, 0x93, - 0x92, 0x3d, 0x7d, 0xb3, 0x81, 0x39, 0xa0, 0x5f, 0xf2, 0x68, 0x0c, 0x3a, - 0x9b, 0xfb, 0x2c, 0x26, 0xb9, 0x38, 0xcb, 0x3e, 0xa6, 0xc7, 0x8d, 0x48, - 0x46, 0xe5, 0x5f, 0x69, 0x5d, 0xa3, 0xe3, 0x79, 0x3d, 0x9f, 0x34, 0xe6, - 0x43, 0x1a, 0x82, 0xb9, 0xa4, 0xeb, 0xe6, 0x12, 0xf0, 0x9a, 0xbc, 0x30, - 0xa1, 0xe3, 0x63, 0xda, 0x86, 0xb0, 0xdd, 0x74, 0xdd, 0xda, 0x4d, 0xa3, - 0x0d, 0x79, 0x8f, 0x3a, 0x1b, 0xec, 0x0a, 0x6d, 0xca, 0x10, 0xfa, 0x29, - 0xce, 0x1b, 0x92, 0x73, 0x61, 0xab, 0xdd, 0x77, 0x6b, 0x79, 0x5d, 0x93, - 0xa5, 0xe8, 0xa6, 0xb2, 0x74, 0xc8, 0xf0, 0xf5, 0x35, 0x6c, 0x0b, 0xec, - 0xcf, 0xd4, 0xbc, 0x9d, 0x0a, 0x64, 0xa9, 0x38, 0xf3, 0x4e, 0x64, 0x29, - 0x68, 0x1f, 0x83, 0xec, 0x06, 0x63, 0x6c, 0xa4, 0x39, 0xa8, 0x03, 0x1a, - 0x4b, 0x59, 0x8d, 0x51, 0x38, 0x8e, 0x6f, 0x1b, 0xca, 0xeb, 0x6c, 0xc3, - 0x11, 0xb4, 0x95, 0x50, 0xae, 0xb7, 0x45, 0xf6, 0xcf, 0x07, 0x7d, 0x1c, - 0x51, 0x32, 0x3b, 0x39, 0x63, 0x9b, 0xc3, 0x61, 0xc9, 0x0c, 0xcf, 0x0e, - 0xca, 0x50, 0xad, 0x13, 0x6b, 0xfa, 0xb6, 0x07, 0xdb, 0x79, 0x7d, 0x54, - 0x1c, 0xe8, 0x45, 0xcc, 0x79, 0x00, 0x3c, 0xae, 0x45, 0xc5, 0x48, 0xbb, - 0x48, 0xeb, 0x31, 0x56, 0x24, 0x32, 0xbc, 0x2e, 0xdf, 0x80, 0x3a, 0xe8, - 0x7b, 0x60, 0x63, 0x3d, 0xc8, 0x27, 0x78, 0x9b, 0x75, 0x7f, 0xe1, 0xc1, - 0x0e, 0x6b, 0x9b, 0xc5, 0x52, 0xea, 0x89, 0x40, 0x47, 0x7c, 0x14, 0xfb, - 0x5b, 0xed, 0x85, 0x82, 0x91, 0x3e, 0x80, 0x3e, 0x44, 0xc9, 0x69, 0xb1, - 0xf6, 0x4c, 0xb0, 0xef, 0x55, 0xf9, 0xae, 0x01, 0xca, 0x5e, 0x19, 0x98, - 0x80, 0x73, 0x5a, 0x52, 0x7b, 0x3d, 0x67, 0xc6, 0x65, 0xba, 0xc4, 0xf9, - 0x2c, 0x49, 0xb2, 0xfa, 0xa7, 0x92, 0x3b, 0x2d, 0xf2, 0xad, 0x19, 0xd6, - 0xfb, 0xba, 0xae, 0xf7, 0x3c, 0xea, 0x25, 0xad, 0xa1, 0x90, 0x0d, 0x3b, - 0x60, 0x63, 0x9b, 0xf4, 0x59, 0x48, 0xcd, 0x11, 0xfc, 0x86, 0x68, 0x64, - 0x50, 0xcf, 0xc7, 0x40, 0xcf, 0x83, 0x1f, 0x22, 0x77, 0x95, 0x1a, 0xa1, - 0x4f, 0xfe, 0x27, 0x68, 0x8d, 0xcb, 0xe3, 0x98, 0xc7, 0x4b, 0x33, 0xc4, - 0x59, 0x5f, 0x97, 0xe5, 0x19, 0xe2, 0xae, 0xe7, 0x65, 0x7a, 0x26, 0xe9, - 0x7e, 0x0b, 0x7c, 0x3e, 0x25, 0x9c, 0x4b, 0x9f, 0x8b, 0x14, 0x18, 0xd0, - 0xb6, 0x1e, 0x83, 0x3e, 0xeb, 0xdd, 0xe9, 0xf7, 0xd7, 0xad, 0xfb, 0x73, - 0xaa, 0xb6, 0x5c, 0x34, 0xa9, 0x9f, 0x2e, 0xdf, 0xe3, 0x59, 0xbd, 0xc7, - 0xc7, 0xdc, 0x4e, 0x31, 0xb0, 0xaf, 0x33, 0xe3, 0x05, 0x58, 0x3f, 0xee, - 0xeb, 0xff, 0x6b, 0xac, 0xe1, 0x9f, 0x04, 0xb0, 0xaa, 0xad, 0xec, 0xdd, - 0x3f, 0x6e, 0x8f, 0xd7, 0xef, 0x6d, 0x8e, 0xdf, 0x8a, 0x36, 0x11, 0xa4, - 0x57, 0xde, 0xd7, 0xe8, 0xa3, 0xae, 0xed, 0x20, 0xf7, 0x05, 0xda, 0xfc, - 0x09, 0x78, 0x41, 0xfe, 0xbf, 0x93, 0xfd, 0xdc, 0x17, 0x7e, 0x47, 0xfb, - 0x79, 0xfc, 0x4a, 0xfb, 0xb9, 0x7e, 0x2f, 0x9f, 0x25, 0x2f, 0x30, 0xb6, - 0xcc, 0xfa, 0xb2, 0xd5, 0x0d, 0x5e, 0x5b, 0x90, 0x53, 0xd0, 0x50, 0xfa, - 0x07, 0x2f, 0x13, 0xf1, 0xf1, 0x9c, 0x2f, 0x4f, 0xac, 0x17, 0xd4, 0xf1, - 0x75, 0xef, 0x50, 0xed, 0xa2, 0xd2, 0xb3, 0xe7, 0x94, 0x9e, 0xb5, 0x8f, - 0x14, 0x84, 0xf2, 0x76, 0x43, 0x98, 0x7c, 0x7f, 0xc6, 0xfd, 0x2c, 0x68, - 0xb4, 0x2d, 0xcb, 0xe8, 0x2e, 0x18, 0xc6, 0x67, 0xe5, 0xc0, 0xe2, 0x43, - 0x72, 0xa0, 0xc4, 0x3e, 0xd2, 0x78, 0xef, 0xa0, 0xac, 0x09, 0xba, 0x96, - 0x3a, 0xfd, 0xed, 0x90, 0x3f, 0x96, 0x01, 0xfb, 0xb5, 0x12, 0xba, 0xab, - 0x76, 0x21, 0x94, 0x5d, 0xe4, 0xde, 0x45, 0x79, 0xad, 0x5e, 0xe7, 0x07, - 0xfa, 0xbe, 0x5e, 0xb7, 0x17, 0x42, 0x63, 0xa5, 0x69, 0xe2, 0x40, 0x23, - 0xeb, 0x46, 0xb5, 0xee, 0xf8, 0x9a, 0x29, 0xad, 0xb0, 0x2d, 0xc6, 0x3c, - 0x78, 0x45, 0x9c, 0x4a, 0xde, 0xa5, 0x24, 0x13, 0x21, 0x9e, 0xe4, 0xb3, - 0x78, 0xe1, 0x34, 0xf7, 0x9e, 0x44, 0xc2, 0xe9, 0x2e, 0xf0, 0x8e, 0x75, - 0x6e, 0x05, 0xad, 0xb0, 0x7b, 0xee, 0xfb, 0x84, 0x72, 0xf9, 0x42, 0xe9, - 0x36, 0xe4, 0x23, 0x9a, 0xbf, 0x51, 0xd4, 0x61, 0x7f, 0x3f, 0x6d, 0x90, - 0xd6, 0xe3, 0xd0, 0x15, 0x41, 0xbf, 0xac, 0x93, 0xd0, 0x75, 0x5a, 0x74, - 0x9d, 0x5b, 0xf0, 0x7e, 0x0e, 0xf5, 0x6c, 0x57, 0x84, 0x7c, 0x60, 0x59, - 0x3b, 0xe6, 0x85, 0xba, 0x8b, 0xe9, 0xf0, 0x7a, 0xba, 0x6e, 0xaa, 0xab, - 0xcb, 0xfc, 0x66, 0x58, 0x97, 0xf2, 0x24, 0x5a, 0x97, 0xb1, 0x6c, 0x10, - 0xcf, 0x5d, 0x32, 0xb1, 0x98, 0x81, 0x4e, 0xba, 0x5d, 0xf5, 0x13, 0x75, - 0xd6, 0xd9, 0x3a, 0xd0, 0x64, 0x69, 0x9a, 0xb6, 0x04, 0xfa, 0x18, 0x65, - 0xae, 0x2e, 0x6b, 0xa8, 0x2b, 0x0b, 0xe4, 0xe7, 0x5f, 0x83, 0x76, 0x8e, - 0x3d, 0xa2, 0x71, 0x98, 0xe7, 0xe5, 0x28, 0x77, 0xfd, 0xff, 0x52, 0xf3, - 0xa2, 0x60, 0x86, 0xd5, 0x5e, 0xa9, 0xfe, 0xf6, 0xda, 0x5e, 0x01, 0x6e, - 0x57, 0xbd, 0x70, 0x8e, 0xa4, 0xa5, 0x05, 0x6b, 0x3b, 0x04, 0x5a, 0xb1, - 0x86, 0x1d, 0x21, 0xcc, 0xb7, 0x45, 0xf2, 0xb5, 0xb4, 0x7e, 0xc7, 0xf2, - 0x88, 0x8c, 0xc5, 0x83, 0xf9, 0x7d, 0xc0, 0xf4, 0xb1, 0x37, 0xea, 0x94, - 0xb6, 0x44, 0xfc, 0xbd, 0x68, 0x4a, 0xfe, 0xe4, 0x10, 0x64, 0x9e, 0xd8, - 0xb0, 0x01, 0x32, 0x1f, 0x57, 0x36, 0xc7, 0x70, 0x58, 0x1f, 0xef, 0x4e, - 0xff, 0xbb, 0xb0, 0xdf, 0x86, 0xf5, 0x82, 0x36, 0xc1, 0xd8, 0xed, 0xab, - 0x6d, 0xc7, 0x5c, 0x43, 0xc2, 0x6a, 0x7c, 0x94, 0x9d, 0x5e, 0x3f, 0xbe, - 0xd1, 0x11, 0x8c, 0xff, 0xa7, 0xba, 0xaf, 0xf6, 0xba, 0xbe, 0xe2, 0x57, - 0x18, 0x1f, 0xef, 0x4e, 0xff, 0xee, 0x76, 0xbf, 0x4d, 0xbc, 0xae, 0x4d, - 0xc7, 0x86, 0x36, 0xac, 0x1f, 0x8c, 0x81, 0x77, 0xa7, 0xef, 0x6b, 0xf1, - 0xdb, 0xb0, 0x5e, 0x03, 0x6c, 0x2c, 0xdf, 0x71, 0x0f, 0x1e, 0xa8, 0xdb, - 0x83, 0x07, 0xb0, 0x07, 0x03, 0xd9, 0xde, 0x88, 0xd7, 0x03, 0xbf, 0x8b, - 0xfe, 0x16, 0x31, 0xde, 0x9a, 0x7f, 0x15, 0x59, 0x68, 0x01, 0x7e, 0x6a, - 0xa5, 0x4f, 0xa5, 0xf1, 0x39, 0x7d, 0x2c, 0xe2, 0x71, 0x71, 0x22, 0xd2, - 0x0d, 0x5d, 0xd9, 0x9d, 0xd8, 0xcf, 0x8d, 0x5f, 0x8d, 0x2b, 0xdc, 0x9e, - 0xd1, 0x63, 0xd0, 0xbf, 0x22, 0xdf, 0x99, 0xcf, 0xad, 0xfa, 0x5b, 0x9d, - 0xf0, 0xc7, 0x88, 0xbb, 0x89, 0xdb, 0x02, 0xfa, 0x03, 0x7a, 0x0e, 0x1a, - 0x6b, 0x7b, 0x33, 0x63, 0x0c, 0xd5, 0x86, 0x0c, 0x7f, 0x6f, 0xf2, 0xfd, - 0x41, 0x6d, 0x5b, 0x37, 0xd2, 0xfb, 0x9e, 0x0d, 0xf4, 0x12, 0xdf, 0x59, - 0x32, 0x05, 0x19, 0x89, 0x2c, 0x50, 0xd7, 0x2f, 0x8c, 0x2e, 0xcf, 0x13, - 0xc7, 0xf4, 0x83, 0x2f, 0xa4, 0x97, 0xfc, 0xa3, 0x4e, 0x69, 0x85, 0x9e, - 0xea, 0x4e, 0x55, 0x50, 0x9f, 0x7e, 0xfe, 0x84, 0xf2, 0x0f, 0x5b, 0x90, - 0xc2, 0x89, 0x03, 0xad, 0x13, 0xa0, 0x75, 0x42, 0xfb, 0x86, 0xfb, 0x61, - 0x47, 0x22, 0xc7, 0x02, 0x5a, 0x6f, 0x89, 0x04, 0x6b, 0xb3, 0x9e, 0xf6, - 0x7a, 0xfb, 0xe7, 0xe3, 0xc0, 0xbb, 0x7a, 0xd5, 0x9e, 0x2c, 0x10, 0x3b, - 0x4e, 0x9c, 0x0e, 0xf6, 0xa3, 0xf8, 0x7b, 0xa9, 0x35, 0xc0, 0x01, 0x9c, - 0x0f, 0x71, 0x08, 0x75, 0x4f, 0x30, 0x87, 0x16, 0xe9, 0x5a, 0xe0, 0x1c, - 0x56, 0xe9, 0x8f, 0x33, 0xca, 0x72, 0x00, 0xfa, 0x3b, 0xaf, 0x68, 0xdd, - 0x2d, 0x93, 0xa5, 0xf7, 0x69, 0xfa, 0x5b, 0x40, 0xff, 0x18, 0x64, 0x7b, - 0x4d, 0x77, 0xe5, 0xab, 0xe3, 0xc8, 0xfb, 0x98, 0x90, 0x3c, 0xce, 0x57, - 0xa9, 0xc7, 0xf4, 0x7c, 0x9a, 0x39, 0x9f, 0x8d, 0x3a, 0x6e, 0x33, 0xbe, - 0xbe, 0x77, 0x03, 0x5f, 0x45, 0xf3, 0x35, 0x26, 0x0d, 0x0b, 0xca, 0xbf, - 0x46, 0xbf, 0xe4, 0x35, 0xed, 0xe8, 0xc2, 0xe8, 0xf4, 0xbc, 0xf4, 0x33, - 0x08, 0x95, 0x07, 0xdf, 0x50, 0x36, 0xd0, 0x20, 0xdd, 0xee, 0x05, 0xcc, - 0x3b, 0x8f, 0xf5, 0x36, 0x8e, 0xf9, 0xf2, 0x4d, 0xfe, 0xe6, 0xab, 0xcd, - 0xf0, 0xe9, 0x39, 0x36, 0x79, 0x46, 0xfa, 0x4d, 0x45, 0xcf, 0x2a, 0xbf, - 0x41, 0xdf, 0x7d, 0xd5, 0x8d, 0xbc, 0xad, 0xd7, 0x33, 0x41, 0xec, 0xe0, - 0x35, 0xd3, 0xdf, 0x17, 0x9b, 0xc5, 0x0e, 0x5a, 0xa0, 0xa3, 0x23, 0x8c, - 0x13, 0x80, 0xf7, 0x8c, 0xf3, 0x5c, 0x8a, 0xd0, 0x17, 0x78, 0xa1, 0x04, - 0x3d, 0x73, 0x9c, 0xd8, 0xa5, 0x55, 0xef, 0x8f, 0x1b, 0xb4, 0x0d, 0x8b, - 0x2a, 0xdb, 0x21, 0x86, 0x49, 0x7c, 0x84, 0x32, 0xe4, 0x17, 0x99, 0x0f, - 0xe8, 0xb8, 0x7b, 0x4f, 0xd4, 0x79, 0x21, 0x12, 0xe8, 0x84, 0x35, 0xba, - 0xea, 0x63, 0x03, 0x1e, 0x30, 0xe5, 0xfb, 0x20, 0xb7, 0xb7, 0xc3, 0xff, - 0xb7, 0x24, 0x9f, 0xe2, 0x3e, 0x1a, 0x54, 0x3e, 0x92, 0xe1, 0xec, 0x47, - 0x59, 0x13, 0xca, 0x60, 0x4c, 0x4d, 0xcc, 0xdf, 0xf9, 0x3d, 0x99, 0x80, - 0x8c, 0xe7, 0x53, 0x7d, 0xa0, 0x83, 0xf8, 0x0e, 0x58, 0xcb, 0x49, 0x31, - 0x7e, 0x80, 0xbf, 0x7b, 0xa3, 0xfe, 0xbc, 0xf6, 0x20, 0xdf, 0x8c, 0x3a, - 0x5d, 0xba, 0xce, 0x16, 0x61, 0x1c, 0x2a, 0x6f, 0xb6, 0x22, 0xed, 0xd9, - 0x50, 0xf7, 0x43, 0xc8, 0xdf, 0xa2, 0xfb, 0x2f, 0xe0, 0xfd, 0x4d, 0xf8, - 0x0d, 0xa1, 0xec, 0x66, 0x94, 0xb9, 0x28, 0xbb, 0x11, 0xf9, 0x0f, 0xe9, - 0xb8, 0x44, 0xd0, 0xa6, 0x15, 0xf9, 0x47, 0xf1, 0x1e, 0xba, 0xc2, 0x7c, - 0x05, 0xef, 0x6f, 0xc1, 0xef, 0xfa, 0x0d, 0x75, 0xda, 0x37, 0xe4, 0x4f, - 0xae, 0xf2, 0xe0, 0x85, 0xd2, 0x55, 0xfa, 0x99, 0xf2, 0xcc, 0xfc, 0x2b, - 0x3a, 0x7f, 0xfb, 0x86, 0xf2, 0xfb, 0x83, 0x7c, 0xdd, 0x1a, 0xc2, 0x0e, - 0x9a, 0x01, 0xd6, 0xbd, 0xda, 0xf4, 0xd7, 0xe0, 0x3d, 0x7e, 0xbc, 0xa0, - 0x14, 0xb4, 0x23, 0xf6, 0xbd, 0x3d, 0xbc, 0xbe, 0xaf, 0xff, 0xd6, 0xb0, - 0x96, 0x6f, 0x09, 0x0d, 0x9f, 0x64, 0xd9, 0x4f, 0x1b, 0xd6, 0xd7, 0x79, - 0x5f, 0xe3, 0x5a, 0x7e, 0x6b, 0x68, 0xf8, 0x38, 0xcb, 0xee, 0x6b, 0x5c, - 0x5f, 0x67, 0xb8, 0x71, 0x6d, 0x1e, 0x6b, 0xba, 0x30, 0x92, 0xae, 0x50, - 0x8e, 0xb1, 0x17, 0xaa, 0xa3, 0xd9, 0x19, 0xcf, 0x9b, 0x72, 0x57, 0x12, - 0x61, 0xa1, 0x0d, 0x22, 0x66, 0x66, 0xf9, 0x53, 0x28, 0x07, 0xa6, 0xaa, - 0x8d, 0x09, 0x75, 0xd2, 0xe6, 0xd8, 0xd8, 0xd2, 0xd8, 0x58, 0x65, 0x23, - 0x59, 0x85, 0x65, 0x9f, 0x18, 0x05, 0xf6, 0xd2, 0xcf, 0x4f, 0xe2, 0xd9, - 0xaa, 0xc7, 0xdf, 0xe8, 0xb7, 0x3c, 0x9a, 0x9d, 0xa7, 0xcd, 0x5b, 0x1a, - 0xdd, 0x37, 0xcf, 0x3d, 0x7f, 0x0a, 0x7b, 0x3e, 0x24, 0xd3, 0xca, 0xfe, - 0x91, 0x0e, 0xb6, 0x2b, 0x8f, 0x76, 0x2d, 0x31, 0xad, 0x8c, 0x3a, 0x4b, - 0x61, 0xd9, 0x1f, 0xf7, 0xdb, 0x32, 0x6f, 0x2d, 0x05, 0x7b, 0xa0, 0x59, - 0xa2, 0x69, 0xca, 0xa4, 0x9d, 0x82, 0x0f, 0x80, 0xf9, 0x1c, 0x19, 0x9d, - 0x76, 0x28, 0x9f, 0x9f, 0x82, 0xdd, 0x6f, 0x96, 0x06, 0xa5, 0x6f, 0x1e, - 0xd7, 0x63, 0x9d, 0xc2, 0x58, 0xdb, 0xd4, 0x7e, 0xca, 0x3a, 0x91, 0x04, - 0xc6, 0x39, 0x64, 0x38, 0x7d, 0x18, 0x8f, 0x1e, 0x7b, 0xa7, 0x4c, 0xd5, - 0xb8, 0x6f, 0xf6, 0x44, 0xd7, 0xfc, 0xf4, 0x39, 0xb4, 0x0b, 0xfc, 0x43, - 0x8e, 0x57, 0x01, 0x3e, 0x84, 0x2c, 0xa7, 0x6d, 0x33, 0x1b, 0x86, 0x9d, - 0x9f, 0x0f, 0xea, 0x90, 0xa6, 0x63, 0xa3, 0xc9, 0xa5, 0x24, 0xfa, 0xea, - 0xa4, 0x0e, 0x83, 0xee, 0x0a, 0xe3, 0xc7, 0xbe, 0xd9, 0x0e, 0xb6, 0x68, - 0x90, 0x76, 0x64, 0x0e, 0x76, 0xa4, 0x53, 0x0e, 0x97, 0x54, 0x1f, 0x16, - 0xfb, 0x28, 0xea, 0xb6, 0x5d, 0x4b, 0x0d, 0xf0, 0xb1, 0x92, 0xe6, 0x8b, - 0xb2, 0xd6, 0x76, 0x58, 0xfc, 0x76, 0x7e, 0xdf, 0x3f, 0xf1, 0x32, 0xf1, - 0xfa, 0xbd, 0xdf, 0x2c, 0x61, 0xd0, 0x91, 0x43, 0x1f, 0x1c, 0x7f, 0xad, - 0xef, 0xa0, 0xbf, 0xa4, 0x79, 0xfe, 0xb2, 0xbe, 0xb6, 0x69, 0xfc, 0x66, - 0x5b, 0xb9, 0x5f, 0x6b, 0x6c, 0xce, 0xf7, 0x09, 0xc8, 0x83, 0x44, 0x72, - 0xbd, 0xd0, 0x8b, 0xb5, 0x41, 0x2d, 0x23, 0x4f, 0xa2, 0xac, 0xde, 0xc7, - 0xf2, 0xe5, 0xab, 0x00, 0x6c, 0x59, 0xc4, 0x3e, 0x0f, 0xa7, 0x33, 0x6d, - 0x7e, 0xcc, 0xeb, 0x4a, 0x7e, 0x15, 0xe4, 0x06, 0x7d, 0x16, 0x57, 0xdb, - 0x72, 0x4e, 0x4f, 0x8e, 0xbe, 0x34, 0x93, 0xc0, 0x9c, 0x7c, 0xbb, 0xe0, - 0xf3, 0x9a, 0x36, 0x27, 0x24, 0xcb, 0x8e, 0x05, 0xff, 0x9d, 0x36, 0xde, - 0x92, 0x97, 0x9d, 0xc0, 0xfe, 0xd0, 0x16, 0xa1, 0x7e, 0x8d, 0xb4, 0x91, - 0xf6, 0x39, 0xcc, 0xcd, 0x93, 0x59, 0xd7, 0x97, 0xc1, 0x5e, 0xd8, 0x91, - 0xff, 0x18, 0xb1, 0x8f, 0xd0, 0xcf, 0xbb, 0x18, 0xa9, 0x9f, 0x4f, 0x80, - 0x15, 0x9e, 0xd0, 0x31, 0xe8, 0x39, 0x2d, 0x2f, 0x65, 0xc8, 0x4b, 0x9f, - 0x65, 0x4a, 0x0f, 0x68, 0x47, 0x9d, 0xfe, 0x6e, 0xf8, 0x5b, 0xf4, 0xe5, - 0x13, 0xa0, 0xc7, 0x84, 0xee, 0xd8, 0xa6, 0x7d, 0x87, 0xb7, 0xa2, 0xb4, - 0x6d, 0x6d, 0x2a, 0xbe, 0x3d, 0xa7, 0xe4, 0xd9, 0x97, 0xef, 0xb0, 0x7e, - 0x1f, 0xc8, 0x54, 0x98, 0x90, 0x46, 0xd6, 0xe2, 0xb8, 0xac, 0xbf, 0xa0, - 0xeb, 0xcf, 0xa3, 0x7e, 0x08, 0x73, 0xf2, 0xbc, 0x49, 0x45, 0xef, 0x02, - 0xf8, 0x1e, 0x96, 0xe2, 0xaa, 0xcc, 0x2f, 0x40, 0xe6, 0x29, 0xdf, 0x73, - 0xd8, 0xaf, 0x20, 0xfe, 0x6e, 0xca, 0x7d, 0x45, 0x86, 0x4e, 0xef, 0x6f, - 0x60, 0xcc, 0xd5, 0x32, 0xe8, 0x03, 0x53, 0x26, 0x3b, 0xe5, 0xb1, 0x52, - 0xd2, 0x9c, 0xaa, 0x5b, 0xcb, 0x5d, 0xeb, 0xd6, 0x92, 0x32, 0xa0, 0xea, - 0xa7, 0x58, 0xbf, 0x52, 0x27, 0x03, 0x8b, 0xf3, 0x57, 0x6a, 0x47, 0x19, - 0x60, 0xbb, 0xcd, 0xfc, 0x05, 0xc6, 0x28, 0x3d, 0x6f, 0xd9, 0x25, 0xfe, - 0x6f, 0x94, 0x82, 0x92, 0xb1, 0x90, 0x14, 0x5d, 0xee, 0xab, 0xac, 0x15, - 0x11, 0x1b, 0x58, 0xe9, 0xf7, 0x41, 0x67, 0x26, 0x15, 0x15, 0x3f, 0xa6, - 0x31, 0x81, 0x35, 0x58, 0x31, 0x3d, 0xef, 0x25, 0x47, 0xa4, 0x02, 0x1f, - 0x78, 0x19, 0x69, 0xb1, 0x8a, 0x3d, 0xdb, 0x1c, 0x81, 0x0e, 0x08, 0x64, - 0x3c, 0x26, 0x65, 0xd4, 0x59, 0xc4, 0xbb, 0xc7, 0xaa, 0x81, 0xc4, 0x78, - 0x9e, 0x01, 0x1e, 0xed, 0x73, 0x7e, 0xea, 0xe5, 0xe3, 0xf5, 0x75, 0x03, - 0x4c, 0x4c, 0x2c, 0x4b, 0x6c, 0x4a, 0x4c, 0xc9, 0x77, 0xc4, 0x89, 0x87, - 0x40, 0x0b, 0xf7, 0x6c, 0xab, 0xc4, 0xd2, 0x76, 0x62, 0x44, 0x02, 0xdb, - 0xff, 0x3a, 0x64, 0xa9, 0xe0, 0x35, 0x3a, 0x9d, 0xf2, 0x1c, 0xe4, 0xe6, - 0xd9, 0x55, 0x1c, 0x63, 0x41, 0x8e, 0x68, 0x47, 0x3d, 0x39, 0xe7, 0x3a, - 0xd6, 0xe7, 0x90, 0x7e, 0xc7, 0xfd, 0x00, 0xf9, 0xf6, 0x84, 0x48, 0x3f, - 0x7c, 0x32, 0xe8, 0xf5, 0xd9, 0x00, 0xdb, 0xb7, 0xd2, 0x37, 0xd4, 0xb2, - 0x74, 0x11, 0x7d, 0xda, 0xa6, 0x01, 0x50, 0x7b, 0x07, 0xea, 0xf9, 0x7b, - 0x23, 0x28, 0x3b, 0x84, 0xba, 0xa4, 0x81, 0x7e, 0xfb, 0x77, 0xb1, 0x67, - 0x3d, 0xef, 0x1e, 0xf7, 0xe5, 0x3a, 0x5d, 0xb3, 0x80, 0xf5, 0x57, 0x72, - 0x3e, 0xd0, 0x26, 0x8c, 0xf3, 0x4a, 0x7f, 0xbb, 0xf2, 0x2b, 0xf9, 0x0c, - 0x79, 0x1f, 0x20, 0x16, 0xb2, 0x14, 0xd6, 0x24, 0x6e, 0x78, 0x16, 0xbc, - 0xff, 0xa4, 0xc2, 0x34, 0xc4, 0x6f, 0xa0, 0xbf, 0x44, 0x4c, 0xe1, 0x63, - 0x69, 0x1f, 0xd7, 0x11, 0x5b, 0xa4, 0xb8, 0x36, 0x1a, 0x5f, 0xb0, 0x2d, - 0xeb, 0xb1, 0x6d, 0xfd, 0xfa, 0xb1, 0xce, 0xb6, 0x50, 0xee, 0x38, 0xe5, - 0x99, 0xf6, 0xb1, 0x4d, 0xf6, 0xa7, 0x1a, 0xc1, 0xf7, 0x76, 0x6d, 0xc7, - 0x3f, 0x08, 0xcc, 0x06, 0xec, 0x6d, 0xd2, 0x87, 0x0a, 0x78, 0x7d, 0x23, - 0xca, 0x7e, 0x0e, 0xfe, 0xb3, 0x0c, 0xfe, 0x95, 0xb2, 0x93, 0x0f, 0x61, - 0x2f, 0x97, 0xb7, 0xf9, 0x31, 0x34, 0xae, 0x43, 0x80, 0x13, 0x02, 0xdc, - 0x67, 0x6a, 0xbc, 0xcf, 0xb5, 0xf1, 0xe3, 0x6d, 0x86, 0xaa, 0x4b, 0x5f, - 0xab, 0xde, 0xc7, 0xe5, 0x1e, 0xf6, 0xbc, 0x73, 0x6e, 0x80, 0x23, 0xeb, - 0xfd, 0xc4, 0xc0, 0x07, 0x8c, 0x89, 0xd5, 0x4e, 0x4c, 0xf1, 0x47, 0x0d, - 0x6b, 0x58, 0xe6, 0x1f, 0xbc, 0xb0, 0x43, 0x9f, 0x93, 0x38, 0x26, 0xf0, - 0x07, 0x59, 0x97, 0xd8, 0xe6, 0x51, 0x8c, 0x11, 0x16, 0xab, 0x83, 0xf9, - 0x1f, 0xeb, 0x36, 0x7c, 0xf6, 0xa4, 0x67, 0x67, 0xbd, 0x3c, 0x0f, 0xfa, - 0xfe, 0x62, 0x73, 0x10, 0x03, 0xee, 0x54, 0xfa, 0x64, 0x4d, 0x2e, 0x02, - 0x9a, 0x82, 0x71, 0x7d, 0xff, 0xb4, 0x1d, 0xb4, 0xdd, 0x05, 0x9b, 0xb2, - 0xb3, 0xdd, 0xae, 0xf3, 0x45, 0xeb, 0x69, 0xaa, 0xc7, 0x57, 0x16, 0xc6, - 0x68, 0x94, 0x9d, 0x1d, 0xe4, 0x5d, 0xa7, 0xb2, 0x2d, 0x6b, 0xeb, 0x41, - 0xdb, 0xcf, 0xb1, 0x37, 0x96, 0xdf, 0x52, 0x47, 0xd7, 0x46, 0xcc, 0x47, - 0x1f, 0xd7, 0xc7, 0x7c, 0x99, 0xb8, 0x27, 0xbb, 0xdc, 0x00, 0xdf, 0xd5, - 0xd3, 0x41, 0x8c, 0x47, 0x9a, 0xa3, 0x75, 0x3e, 0xf2, 0xef, 0xea, 0x33, - 0xaa, 0x39, 0x3d, 0x97, 0xc0, 0x97, 0x4e, 0xa2, 0xfe, 0x7f, 0x00, 0xdd, - 0x7c, 0x26, 0xed, 0x01, 0x1e, 0x4c, 0xfa, 0x6d, 0x9b, 0x37, 0xc3, 0xfd, - 0xdc, 0x27, 0x01, 0x6f, 0xda, 0xf5, 0xba, 0xd4, 0xfb, 0xe3, 0xea, 0xe7, - 0xae, 0xd7, 0x1d, 0x37, 0xd6, 0xcd, 0xa9, 0x5f, 0x0a, 0x8b, 0x94, 0x85, - 0xf7, 0x23, 0x0d, 0xfc, 0xa1, 0x01, 0xd8, 0x8e, 0x0c, 0xfc, 0x1f, 0xfa, - 0x45, 0x97, 0xf9, 0x44, 0x3c, 0xc3, 0x1c, 0xcf, 0xc3, 0x47, 0x56, 0xb6, - 0xc3, 0xb7, 0x8b, 0xc8, 0x43, 0x87, 0xd4, 0xee, 0xa6, 0x5c, 0x8d, 0x4f, - 0x54, 0xdd, 0xf1, 0xc9, 0xea, 0xc0, 0x38, 0x7d, 0x07, 0x5f, 0xce, 0x50, - 0xbf, 0x2a, 0x13, 0x06, 0xda, 0x65, 0x55, 0x3b, 0x15, 0xcb, 0xd8, 0xa4, - 0x1f, 0xe1, 0x1e, 0x9c, 0xf0, 0xc7, 0x8a, 0x8d, 0xe7, 0xa0, 0x77, 0x16, - 0x67, 0x61, 0xd7, 0x1c, 0x3b, 0x43, 0x59, 0xdc, 0xe7, 0xda, 0x23, 0x4a, - 0xde, 0xe2, 0xf6, 0x18, 0xd7, 0xaf, 0x32, 0xfb, 0x5e, 0xe8, 0x4d, 0x4f, - 0xee, 0x84, 0xfe, 0x7b, 0x00, 0xf2, 0x29, 0x67, 0xa0, 0xfc, 0xce, 0x40, - 0x61, 0x9d, 0x89, 0x8b, 0x71, 0xa2, 0x53, 0xa2, 0x47, 0x13, 0x12, 0x39, - 0x4a, 0xff, 0x2b, 0x69, 0xde, 0x29, 0x02, 0x3b, 0xf8, 0xe2, 0xcd, 0x86, - 0xd8, 0x83, 0x19, 0x49, 0xc2, 0x87, 0xec, 0x33, 0x2b, 0x48, 0x8b, 0x92, - 0x4c, 0x9d, 0x46, 0x5f, 0xd1, 0x33, 0xa8, 0x8b, 0x76, 0x4d, 0xcb, 0x16, - 0x7e, 0x1d, 0xd2, 0xbc, 0xec, 0xef, 0x8f, 0xe6, 0xe5, 0xf5, 0xf1, 0x9b, - 0xa1, 0xd5, 0xf8, 0x0d, 0xdf, 0xbf, 0xad, 0xe3, 0x4e, 0x5f, 0xd2, 0xbe, - 0x0c, 0xe5, 0x82, 0xf6, 0x4c, 0xf9, 0x63, 0xd0, 0xdd, 0x5f, 0x82, 0xff, - 0xeb, 0x48, 0xae, 0x04, 0x9c, 0x9e, 0xf6, 0xe4, 0x69, 0xb7, 0xe0, 0x65, - 0x07, 0x3c, 0x79, 0xdd, 0x75, 0x0a, 0x79, 0xb1, 0xdf, 0xa6, 0x8e, 0xfb, - 0xb1, 0xfb, 0x21, 0xd9, 0xd3, 0x66, 0xef, 0xc9, 0x84, 0x0a, 0x5e, 0x8b, - 0xd3, 0x2c, 0x57, 0xa7, 0x0f, 0xc9, 0xbe, 0x1d, 0x2b, 0x66, 0x58, 0x32, - 0x57, 0x03, 0x0b, 0x26, 0xf2, 0x4a, 0x3f, 0xbd, 0xa1, 0x7c, 0xea, 0xfb, - 0xbb, 0x0f, 0xc9, 0xd6, 0x1d, 0xb6, 0x79, 0x29, 0x4c, 0x9c, 0x76, 0x08, - 0xf8, 0xdf, 0x4e, 0xe4, 0xc2, 0x8e, 0xb9, 0x5b, 0xec, 0x91, 0x4f, 0x0b, - 0xcf, 0x8c, 0x1d, 0xe9, 0x3a, 0xea, 0x24, 0x1e, 0x0c, 0xf5, 0x1c, 0x78, - 0x90, 0x3e, 0xdd, 0x19, 0xe6, 0x3d, 0x89, 0xed, 0x30, 0xf1, 0x1c, 0x97, - 0xae, 0x13, 0x96, 0x24, 0xc1, 0x97, 0x5e, 0xc5, 0x13, 0x9e, 0x5d, 0x25, - 0xa4, 0xe7, 0x28, 0x71, 0x93, 0xe2, 0x4d, 0x2f, 0x78, 0x93, 0x02, 0x6f, - 0xe0, 0x47, 0xf5, 0x99, 0x97, 0x90, 0x9e, 0x97, 0xe4, 0xe0, 0x9b, 0xe0, - 0x4d, 0x2f, 0x78, 0xd3, 0x73, 0xc6, 0x42, 0x7b, 0xf4, 0xb1, 0xdc, 0x85, - 0xb4, 0x59, 0x3e, 0x72, 0x55, 0x07, 0x9e, 0x1d, 0x49, 0x1e, 0x8d, 0x61, - 0x8c, 0x90, 0xec, 0xea, 0x2e, 0xc8, 0xf0, 0x0e, 0xf8, 0x63, 0xf1, 0x43, - 0x72, 0x01, 0xb6, 0xa7, 0x04, 0xbf, 0xe0, 0xe9, 0x41, 0x7b, 0x6c, 0x05, - 0xfa, 0xb3, 0x76, 0x97, 0x27, 0xaf, 0xec, 0xf8, 0x2b, 0x2f, 0x71, 0x95, - 0xbd, 0x47, 0x42, 0x03, 0x32, 0x5d, 0x52, 0x36, 0x21, 0x91, 0x0d, 0x2b, - 0x2c, 0x86, 0x39, 0x16, 0x60, 0x57, 0x78, 0x16, 0xee, 0x40, 0xbf, 0x7f, - 0x5a, 0x1e, 0x28, 0x4f, 0xe1, 0x07, 0x1f, 0x73, 0x86, 0x75, 0x0f, 0xc0, - 0x87, 0x7b, 0x48, 0xf6, 0xcf, 0x00, 0x2f, 0xa6, 0x41, 0xf7, 0x80, 0x03, - 0x1f, 0xee, 0x7c, 0xa3, 0xb4, 0xa2, 0x0c, 0xbc, 0x1d, 0xab, 0x6d, 0xf4, - 0xdd, 0x56, 0xb0, 0x0e, 0x83, 0xf2, 0x97, 0xb5, 0x01, 0xf9, 0x6a, 0xad, - 0x5f, 0xbe, 0x0c, 0x7b, 0xf2, 0x6c, 0xad, 0x13, 0x7b, 0x25, 0x81, 0x35, - 0x49, 0x63, 0x7d, 0x5c, 0xf9, 0x4a, 0x2d, 0x25, 0x5f, 0x02, 0xaf, 0x9e, - 0xc3, 0x6f, 0xb8, 0x94, 0x92, 0x5d, 0xa5, 0x7e, 0xbd, 0x46, 0x5c, 0x1f, - 0x07, 0xf4, 0x38, 0x98, 0xbb, 0xfd, 0x54, 0x01, 0xfb, 0x6f, 0xb1, 0xe6, - 0xbc, 0x55, 0x91, 0xc7, 0x1a, 0x19, 0x5f, 0x3e, 0xb5, 0x6a, 0x53, 0x0a, - 0x9e, 0xe9, 0xd8, 0x47, 0x26, 0xb0, 0x0e, 0x15, 0xec, 0xd3, 0x31, 0xc5, - 0xfb, 0x35, 0x7b, 0x53, 0xf1, 0xed, 0x4d, 0x30, 0xbf, 0xd9, 0xbc, 0x7c, - 0x47, 0xb2, 0x73, 0xd3, 0xb2, 0xef, 0xb8, 0x27, 0xbf, 0xe3, 0x7a, 0x90, - 0x63, 0xea, 0xdf, 0x01, 0xea, 0x75, 0x6b, 0x22, 0x6c, 0x28, 0xff, 0xc9, - 0xc7, 0x2a, 0xbd, 0xdb, 0xb1, 0x67, 0x53, 0x19, 0x63, 0x4a, 0x92, 0x73, - 0x53, 0xd2, 0x35, 0x07, 0x59, 0x70, 0xd9, 0xd7, 0x8a, 0x69, 0x5c, 0x26, - 0x0f, 0x1c, 0xc7, 0x1e, 0xcc, 0x89, 0x63, 0xbe, 0x25, 0x29, 0x8c, 0x7f, - 0x50, 0xba, 0xd1, 0xc6, 0x41, 0x9b, 0x4b, 0x6a, 0xec, 0x16, 0x8c, 0xdd, - 0x28, 0x87, 0xe3, 0x36, 0x64, 0x8d, 0x76, 0xfb, 0xff, 0x48, 0xb6, 0xc2, - 0xf4, 0x6f, 0x25, 0x7b, 0xea, 0x91, 0x98, 0x34, 0xf3, 0x19, 0xaa, 0x61, - 0x81, 0xe5, 0x5d, 0x48, 0x59, 0xee, 0xc0, 0x77, 0xfe, 0x89, 0x64, 0xcf, - 0x72, 0xec, 0xb7, 0x50, 0xfe, 0x8a, 0x64, 0x8f, 0xfd, 0x1c, 0xf9, 0x0b, - 0x48, 0xdf, 0x46, 0x3a, 0x26, 0x5d, 0xc7, 0x24, 0x94, 0x3d, 0xfb, 0x6d, - 0xe4, 0x23, 0x48, 0x0f, 0xa3, 0xde, 0x6d, 0xa0, 0xef, 0xaf, 0xd1, 0x5f, - 0x06, 0x7a, 0xee, 0xc3, 0x9a, 0x7e, 0x96, 0xb3, 0x8c, 0xef, 0x0e, 0x43, - 0xa7, 0xfd, 0x0f, 0x8f, 0xf1, 0x44, 0xf5, 0xbc, 0xc8, 0x3c, 0x75, 0x1b, - 0x9f, 0xa7, 0xc0, 0x93, 0x83, 0xc8, 0x7b, 0xf2, 0x90, 0x4b, 0x1b, 0x73, - 0x93, 0x8c, 0x9b, 0x05, 0xaf, 0x19, 0x58, 0xa2, 0x05, 0xfb, 0x60, 0x6a, - 0xe7, 0xe6, 0xfb, 0xe0, 0x48, 0xcf, 0x21, 0x69, 0xda, 0x11, 0xcc, 0x3f, - 0x98, 0xaf, 0x63, 0xfe, 0x48, 0xf1, 0xc1, 0x2e, 0x3c, 0x28, 0x9c, 0x87, - 0x93, 0x78, 0xdc, 0xe8, 0xd9, 0xf3, 0x00, 0xf6, 0x81, 0x71, 0x96, 0x79, - 0x7f, 0x1f, 0x18, 0x67, 0xa1, 0x1b, 0x16, 0xe0, 0x17, 0x2e, 0x74, 0x4a, - 0xe3, 0xb1, 0xb5, 0x7d, 0xd0, 0x70, 0xec, 0x57, 0xef, 0x83, 0xc6, 0xb3, - 0xa8, 0x77, 0x96, 0x3c, 0x43, 0x1f, 0xa7, 0xc8, 0xb3, 0x0e, 0xa4, 0x9f, - 0xc6, 0x5c, 0x49, 0x7b, 0x23, 0x68, 0xf7, 0xb1, 0xd0, 0xcd, 0x90, 0xf7, - 0xfb, 0x77, 0x1c, 0xd4, 0xe5, 0xff, 0xd9, 0x1b, 0x89, 0xdb, 0x65, 0x09, - 0x91, 0xa7, 0xa8, 0x5b, 0x21, 0x0f, 0x6f, 0x69, 0x92, 0xe6, 0x03, 0xd2, - 0x45, 0xfe, 0x55, 0x76, 0x23, 0x5f, 0xf0, 0xa2, 0x4e, 0x8b, 0xe6, 0x27, - 0xb0, 0xd1, 0x00, 0xcb, 0x5f, 0x83, 0xcc, 0x10, 0xa3, 0xbe, 0x21, 0xfb, - 0x66, 0x3c, 0x19, 0x77, 0x39, 0xff, 0xef, 0x63, 0xfe, 0x99, 0x1d, 0x71, - 0x59, 0xb1, 0xe2, 0xe0, 0xc9, 0x22, 0x74, 0xfb, 0x05, 0xf1, 0xf9, 0xc0, - 0x33, 0x89, 0x5d, 0xe2, 0x24, 0x86, 0xc5, 0x49, 0xbd, 0x09, 0x3e, 0x0c, - 0x43, 0xf6, 0x73, 0x35, 0xca, 0xce, 0xab, 0x32, 0x04, 0x99, 0xf8, 0x9e, - 0x6b, 0xa7, 0x80, 0x7f, 0xa0, 0x2f, 0x28, 0x17, 0x94, 0x89, 0x56, 0xa5, - 0x93, 0x16, 0x5c, 0xfb, 0x89, 0x8a, 0x5c, 0x27, 0x0b, 0xed, 0xa4, 0x1d, - 0xef, 0x8e, 0x29, 0x7b, 0x91, 0x9a, 0x30, 0xba, 0xa1, 0xa3, 0x53, 0x62, - 0xf6, 0x7c, 0xb1, 0x31, 0xb8, 0xbf, 0x92, 0x9f, 0x0b, 0xc9, 0x54, 0x0f, - 0xd7, 0x8a, 0xfd, 0x22, 0x5f, 0x29, 0x78, 0x11, 0xe7, 0x2d, 0xef, 0x64, - 0x87, 0x25, 0x9f, 0xec, 0x59, 0x95, 0xcb, 0xb2, 0x88, 0xbf, 0x2f, 0x86, - 0xd4, 0x7a, 0x04, 0x74, 0x07, 0x73, 0x09, 0xde, 0xf5, 0xd7, 0xbd, 0xe3, - 0x5c, 0x28, 0xeb, 0xab, 0x7b, 0xc7, 0xba, 0x9c, 0xd6, 0x9f, 0x41, 0x9e, - 0xec, 0x27, 0x8a, 0xf2, 0x3a, 0x64, 0x0f, 0x3c, 0x3c, 0xcb, 0x94, 0x3c, - 0x9c, 0x82, 0xdc, 0xbf, 0x26, 0xbb, 0xe6, 0xb8, 0x67, 0x5e, 0xc3, 0x5c, - 0x95, 0x2e, 0x81, 0x8e, 0x60, 0x7f, 0x9e, 0x4c, 0xbb, 0xdd, 0xa9, 0x53, - 0x72, 0x5d, 0x62, 0x12, 0x7e, 0xe6, 0x84, 0xe9, 0xc9, 0xb2, 0x5b, 0x90, - 0xe5, 0x41, 0xb4, 0xa9, 0x7c, 0x1a, 0xbf, 0x79, 0x3d, 0xb7, 0x47, 0xc0, - 0x77, 0xdb, 0x2a, 0x1b, 0x9f, 0x01, 0xdf, 0x1f, 0x92, 0xe4, 0xb1, 0x55, - 0x5d, 0x03, 0xb9, 0xf3, 0x75, 0x4d, 0xf2, 0xac, 0x29, 0x95, 0x92, 0x23, - 0x1f, 0xa3, 0x0e, 0x29, 0x71, 0x5e, 0xd0, 0x31, 0x3c, 0xdf, 0x2f, 0x41, - 0xcf, 0x94, 0xa0, 0x53, 0xa0, 0x43, 0xbe, 0x8c, 0xf2, 0x2f, 0xa1, 0xce, - 0x73, 0xf0, 0x99, 0x9e, 0x05, 0xde, 0x3b, 0x07, 0x1c, 0xf1, 0x4c, 0x29, - 0xa3, 0xfd, 0x57, 0x35, 0x5f, 0xd8, 0x2c, 0xe5, 0xef, 0x48, 0xa5, 0x4c, - 0x7e, 0xfc, 0x44, 0xad, 0x6d, 0xd6, 0xdd, 0x46, 0x6c, 0x05, 0xca, 0x44, - 0xca, 0xe5, 0x80, 0x27, 0xd4, 0x7d, 0x3c, 0x1b, 0x0a, 0x74, 0x65, 0xcb, - 0x06, 0x5d, 0x29, 0xf2, 0x62, 0xd5, 0xc7, 0x90, 0xc4, 0xc4, 0xc5, 0x19, - 0x6b, 0xf5, 0x0c, 0xb5, 0x08, 0xbb, 0x79, 0x1e, 0xbe, 0x45, 0x2c, 0xfd, - 0x2d, 0x89, 0x9d, 0xf0, 0xbc, 0x1f, 0xc0, 0x6e, 0x16, 0xb0, 0x26, 0x46, - 0x08, 0xe5, 0x4b, 0x7c, 0x47, 0xb9, 0xa7, 0x6c, 0x87, 0x78, 0x96, 0x22, - 0x2f, 0xa3, 0xac, 0xa2, 0x7c, 0xae, 0x6f, 0x83, 0x1e, 0x4d, 0x9f, 0x2a, - 0x63, 0xbd, 0x46, 0xc9, 0x8d, 0xa7, 0xe0, 0xd7, 0xf4, 0x99, 0x8d, 0x68, - 0x5f, 0x5e, 0x62, 0x1b, 0x7b, 0x90, 0x57, 0xb9, 0x5e, 0x5e, 0x62, 0x79, - 0xa7, 0x5c, 0x80, 0xff, 0x49, 0x1a, 0x2a, 0xf3, 0x69, 0xf1, 0xe3, 0xc5, - 0xd4, 0x57, 0xa4, 0x15, 0x79, 0xf0, 0x2b, 0x5b, 0xa2, 0x9d, 0x8d, 0x48, - 0x21, 0x41, 0x5e, 0x27, 0xe4, 0xfc, 0xcc, 0x1f, 0x37, 0x31, 0x1e, 0x9b, - 0x75, 0xf8, 0x1c, 0xc4, 0x37, 0xcc, 0x77, 0x10, 0xdf, 0x60, 0x4c, 0x23, - 0x02, 0x5b, 0xa6, 0xe2, 0x1c, 0x48, 0xad, 0x3a, 0x9f, 0x97, 0xef, 0x7d, - 0x6c, 0xb4, 0x86, 0x19, 0x89, 0x21, 0x39, 0x5f, 0xbb, 0xb0, 0x02, 0xfd, - 0xd1, 0x9e, 0x7e, 0x49, 0xee, 0x5e, 0xf0, 0xe7, 0x67, 0x9c, 0x12, 0xde, - 0xe3, 0x91, 0x4b, 0xf3, 0xb6, 0x7b, 0x51, 0x78, 0x06, 0xe2, 0x62, 0xbd, - 0xfe, 0xa0, 0x09, 0xfa, 0x6b, 0x30, 0x63, 0x7c, 0xbb, 0xc9, 0xc7, 0x67, - 0x11, 0x99, 0x9a, 0xe1, 0x99, 0x2b, 0x74, 0x1b, 0x70, 0xe3, 0xef, 0x45, - 0xf0, 0x5c, 0x65, 0x1e, 0x7e, 0xa8, 0xef, 0xc3, 0xe2, 0xd9, 0xef, 0x8f, - 0x3c, 0x37, 0x16, 0x38, 0xf7, 0x90, 0xdc, 0x0d, 0x74, 0x22, 0xe8, 0xbf, - 0x4b, 0x8f, 0xd5, 0x75, 0x2a, 0xc5, 0xf8, 0xb5, 0x24, 0xa1, 0x2f, 0xb2, - 0xf0, 0x1f, 0x73, 0xf1, 0x4e, 0x8d, 0xc7, 0xf9, 0x6e, 0x23, 0xde, 0x0c, - 0xfc, 0xba, 0x94, 0x7c, 0xbe, 0x14, 0x60, 0xbd, 0x14, 0x6c, 0xac, 0x44, - 0x46, 0x7a, 0x3d, 0xf9, 0x81, 0x4b, 0x7e, 0xf5, 0x23, 0xef, 0xca, 0x91, - 0xda, 0x2f, 0x3b, 0x5b, 0xad, 0xff, 0x6b, 0x01, 0x8d, 0xfc, 0x81, 0x3e, - 0xe0, 0x23, 0xd2, 0x6e, 0xc0, 0x9e, 0x17, 0x81, 0xbb, 0x8c, 0x33, 0x9d, - 0xea, 0x9d, 0x01, 0x6c, 0x50, 0x99, 0x81, 0x6e, 0x3c, 0xc3, 0xf3, 0x66, - 0xe8, 0xb6, 0x33, 0x51, 0x29, 0xce, 0x52, 0x2e, 0xa5, 0xdd, 0xc0, 0x7a, - 0xb1, 0x7e, 0x65, 0xa6, 0x13, 0x69, 0x0b, 0x52, 0x4b, 0xf5, 0x53, 0x99, - 0x71, 0x54, 0xfb, 0xca, 0x4c, 0x4a, 0xb5, 0xab, 0xcc, 0xf4, 0x23, 0x75, - 0xa5, 0xe1, 0x0c, 0x9c, 0xa5, 0x33, 0x3d, 0x32, 0x75, 0x12, 0xf6, 0x65, - 0xc0, 0x50, 0x77, 0x35, 0x26, 0x60, 0x7f, 0x22, 0xf0, 0xac, 0x2e, 0x9a, - 0x83, 0xc0, 0x58, 0x37, 0x01, 0x83, 0xdc, 0x24, 0xce, 0x09, 0xce, 0x9f, - 0xba, 0xf7, 0x3c, 0x63, 0x5e, 0x89, 0x4f, 0x48, 0x46, 0xf6, 0xcf, 0x36, - 0x62, 0xbf, 0x46, 0xcc, 0xa2, 0x74, 0x9b, 0xc3, 0xc8, 0xe7, 0xcb, 0xe4, - 0xdb, 0xbd, 0xca, 0x5f, 0xcb, 0xba, 0x37, 0x34, 0x4b, 0x73, 0x1a, 0x63, - 0xbc, 0x93, 0xf6, 0xbd, 0x90, 0x3f, 0x47, 0xf7, 0x91, 0x06, 0x3d, 0xf5, - 0xfc, 0xe0, 0x39, 0x73, 0xe6, 0x57, 0x9c, 0x33, 0x53, 0xae, 0xc9, 0xdf, - 0x7b, 0xe5, 0xbc, 0x93, 0x96, 0x97, 0x9d, 0x94, 0x5c, 0x70, 0x76, 0xca, - 0x37, 0x61, 0xa7, 0x5f, 0x72, 0xce, 0x34, 0x11, 0x0b, 0x54, 0xd4, 0xd9, - 0x5d, 0xb0, 0x56, 0x8e, 0x8e, 0x9d, 0xff, 0x50, 0x96, 0x67, 0x88, 0x9d, - 0xbd, 0xdb, 0xf6, 0xb9, 0x05, 0xda, 0x2d, 0xd0, 0x40, 0xac, 0x56, 0x80, - 0xfd, 0x3b, 0x24, 0xc3, 0x2e, 0xed, 0x9e, 0xb2, 0x51, 0x89, 0x61, 0x7f, - 0x3f, 0xbb, 0x79, 0xe8, 0xd5, 0xf3, 0xb3, 0xd8, 0x4f, 0x42, 0xf9, 0xc7, - 0x73, 0x99, 0xeb, 0xee, 0xc8, 0xe3, 0x25, 0xce, 0xb3, 0xb8, 0xbd, 0x59, - 0xc2, 0x32, 0xa2, 0xf0, 0x42, 0xab, 0xbc, 0xb8, 0xb4, 0x45, 0x0c, 0x58, - 0x28, 0xe3, 0xda, 0xa8, 0xba, 0xe5, 0x42, 0x9f, 0x5b, 0xda, 0x78, 0xb6, - 0xf6, 0x87, 0xe0, 0x0d, 0xfd, 0x7f, 0xcc, 0xad, 0x8d, 0x33, 0x09, 0xf2, - 0xfd, 0xd8, 0x5f, 0x7c, 0x0e, 0x49, 0xce, 0x89, 0xe3, 0x99, 0x29, 0xf7, - 0x1c, 0x63, 0x63, 0x61, 0xf1, 0x31, 0xf7, 0x21, 0xf5, 0xbe, 0xd1, 0xb9, - 0x15, 0xb8, 0x8e, 0xf2, 0x8a, 0x74, 0xd9, 0x1f, 0x37, 0x07, 0x1c, 0x97, - 0xef, 0xe7, 0x1d, 0x1b, 0x3b, 0x55, 0xc0, 0x5e, 0x98, 0x50, 0xf5, 0x07, - 0xe4, 0xa5, 0x99, 0x52, 0xb3, 0xbf, 0x3f, 0x06, 0xf5, 0x33, 0xdf, 0xd3, - 0xa7, 0x62, 0x8c, 0xe4, 0x99, 0xd1, 0x69, 0xe7, 0xa2, 0xde, 0x3f, 0x12, - 0xba, 0xb3, 0x17, 0x38, 0xf4, 0x68, 0x03, 0xe6, 0x62, 0x5b, 0x56, 0xc8, - 0xe8, 0x30, 0x80, 0xe3, 0x87, 0x95, 0xcd, 0xed, 0x55, 0x31, 0xe8, 0x53, - 0xa9, 0x56, 0xa9, 0x98, 0x8e, 0xba, 0x93, 0xb7, 0x62, 0xee, 0x20, 0xd6, - 0xc7, 0xaf, 0x09, 0x65, 0xdd, 0x48, 0x1b, 0x91, 0xbe, 0x5f, 0x8a, 0xc7, - 0xcf, 0xe8, 0xf1, 0xa2, 0x1b, 0xf2, 0x1f, 0xd1, 0xe9, 0x67, 0xb5, 0x3f, - 0xc5, 0x71, 0xa2, 0xe2, 0x7c, 0xa1, 0x45, 0xba, 0x8f, 0x9a, 0xc0, 0xb6, - 0x09, 0x60, 0xdd, 0x4e, 0x49, 0x1d, 0xb5, 0xe4, 0xda, 0xa3, 0x41, 0x9c, - 0xe9, 0x2b, 0xa3, 0x49, 0x15, 0xd7, 0xfc, 0xf2, 0xa8, 0x53, 0x56, 0xe7, - 0xed, 0xfa, 0xee, 0xe0, 0x8a, 0xbe, 0x53, 0xf8, 0xca, 0x68, 0xaf, 0x4a, - 0xbf, 0x3d, 0x9a, 0x52, 0xe9, 0xab, 0xa3, 0xd7, 0x56, 0x7d, 0xff, 0xa8, - 0xb8, 0x98, 0x92, 0xcf, 0x95, 0x88, 0x2f, 0x07, 0x80, 0x1d, 0x5d, 0xe8, - 0x99, 0x7e, 0xe8, 0x99, 0x14, 0xf4, 0xcc, 0x20, 0xf5, 0x0c, 0xf4, 0xf6, - 0xab, 0xd0, 0xdb, 0xae, 0x7c, 0x0f, 0xf2, 0xfa, 0x8c, 0xdb, 0x08, 0x5c, - 0xe8, 0x79, 0xfe, 0x5c, 0xed, 0x27, 0x56, 0xb0, 0xbe, 0x95, 0xd3, 0x12, - 0x6b, 0x83, 0x0e, 0xda, 0xb1, 0xd0, 0x20, 0x8b, 0x71, 0xcf, 0x9b, 0x73, - 0x1d, 0xb9, 0x84, 0xfa, 0x59, 0x87, 0xfb, 0xf8, 0x6f, 0x9a, 0xe9, 0x8f, - 0x5d, 0x9a, 0xd9, 0x09, 0x9d, 0x44, 0x79, 0x8f, 0x49, 0x65, 0x3c, 0x21, - 0x4b, 0xf0, 0xcf, 0xd6, 0xea, 0xa4, 0xf0, 0xcc, 0xfd, 0xff, 0x13, 0xd4, - 0x4d, 0xc1, 0x3e, 0x98, 0xb2, 0xdc, 0x6b, 0xc9, 0xa9, 0x5e, 0x7b, 0xd0, - 0x32, 0xa8, 0xbb, 0x2c, 0x29, 0xc3, 0xbf, 0xaf, 0x94, 0x58, 0x9f, 0xf5, - 0xb0, 0x3f, 0x4b, 0x7e, 0xbb, 0xe9, 0x52, 0xa0, 0x27, 0x06, 0x18, 0x7b, - 0x8c, 0xe4, 0x7a, 0x7d, 0x1b, 0x60, 0x18, 0x8d, 0x90, 0x03, 0x17, 0xfc, - 0x1f, 0x47, 0xf9, 0x00, 0xef, 0x9a, 0xa0, 0x8c, 0x58, 0x28, 0xb6, 0x85, - 0x18, 0x31, 0xe7, 0x8e, 0xa3, 0x8c, 0x6d, 0xec, 0x44, 0x12, 0xe5, 0x63, - 0x92, 0x4c, 0xe4, 0xd5, 0xbd, 0xb7, 0x0e, 0x94, 0xb1, 0x8f, 0xb0, 0x8e, - 0xc1, 0x74, 0x6c, 0xf1, 0xcf, 0x7d, 0x83, 0xf2, 0x3e, 0x15, 0x0f, 0xc8, - 0x98, 0x2e, 0xf6, 0x03, 0xcb, 0x92, 0x26, 0xdb, 0xe5, 0x5c, 0x57, 0xe9, - 0xc2, 0x7b, 0xaa, 0x3c, 0xb7, 0x8b, 0xc9, 0xdd, 0xd5, 0x16, 0xc9, 0x55, - 0x1b, 0xae, 0xa0, 0xff, 0x83, 0x3d, 0x79, 0x3e, 0x61, 0x0a, 0xef, 0x60, - 0xf8, 0xfb, 0x3c, 0xb2, 0x93, 0x7b, 0x02, 0x7c, 0x87, 0xfd, 0x7d, 0x0e, - 0xf3, 0x7d, 0x16, 0xf6, 0xf7, 0x1c, 0xec, 0xef, 0x33, 0xa5, 0x35, 0xfd, - 0xe1, 0xdb, 0x5d, 0xea, 0x80, 0xa7, 0xb0, 0x66, 0x63, 0xc0, 0xfd, 0xbb, - 0xe1, 0x0f, 0x8c, 0x00, 0xfb, 0x0f, 0x61, 0xfd, 0xd2, 0x58, 0xbb, 0x71, - 0xde, 0x55, 0xc2, 0x3a, 0x0e, 0xaa, 0xb3, 0xe5, 0x59, 0x75, 0xdf, 0xe3, - 0x87, 0xca, 0xf6, 0x3e, 0x56, 0x32, 0x60, 0x1f, 0x0a, 0xde, 0x76, 0xc7, - 0x06, 0xfe, 0x5b, 0xdd, 0xcf, 0x83, 0x2f, 0x42, 0xaf, 0xfc, 0x1d, 0xe8, - 0x7a, 0x76, 0x96, 0xf6, 0x1c, 0x75, 0x7c, 0xbc, 0xed, 0x32, 0xbe, 0x85, - 0xfd, 0x7c, 0xe4, 0xbc, 0xac, 0x00, 0x77, 0x64, 0x28, 0xc7, 0xf0, 0x1f, - 0xec, 0x67, 0xca, 0xd2, 0x43, 0x1d, 0x58, 0xe6, 0x5e, 0x19, 0x38, 0x96, - 0x00, 0xd6, 0x03, 0x92, 0x57, 0x67, 0xa9, 0x78, 0x3e, 0xbb, 0x55, 0x0c, - 0xe2, 0x3d, 0xf7, 0x2a, 0x94, 0x51, 0x6f, 0x04, 0x18, 0x69, 0x65, 0xb0, - 0x5d, 0x32, 0x3b, 0xda, 0x95, 0xee, 0xb0, 0xdd, 0x97, 0x31, 0xee, 0x2e, - 0x69, 0x04, 0x86, 0x2b, 0x60, 0x8c, 0x83, 0xf2, 0x37, 0x2e, 0xe3, 0x52, - 0xbe, 0xef, 0x07, 0x5a, 0x62, 0xe0, 0x59, 0xd3, 0x3e, 0xc7, 0x8c, 0xed, - 0xaa, 0xb1, 0xff, 0x98, 0xc2, 0x58, 0x39, 0x61, 0xff, 0xb0, 0x13, 0x18, - 0x33, 0x79, 0x8c, 0xb2, 0xdf, 0x87, 0x75, 0xfb, 0x2d, 0x60, 0x20, 0x72, - 0xf5, 0x5b, 0x5b, 0xfc, 0xfd, 0x42, 0xfa, 0x57, 0x88, 0x27, 0x18, 0xf7, - 0xf7, 0xfd, 0xf2, 0x55, 0xda, 0x06, 0x40, 0xef, 0x73, 0x5b, 0x82, 0xf3, - 0xe3, 0xae, 0x63, 0xbe, 0xbd, 0xee, 0x3a, 0x8b, 0x56, 0x73, 0xd2, 0xc1, - 0x93, 0x68, 0x43, 0xae, 0x95, 0xdb, 0x23, 0x7e, 0x3f, 0xc6, 0x82, 0x09, - 0x59, 0xa5, 0x1e, 0xe8, 0x80, 0x9c, 0x33, 0x4f, 0x9d, 0x42, 0x9d, 0x40, - 0x59, 0x70, 0xa4, 0x58, 0x83, 0x4e, 0x68, 0xed, 0x94, 0x32, 0x79, 0xb6, - 0x40, 0x3d, 0xf1, 0x43, 0x99, 0xde, 0xa0, 0x2b, 0x87, 0x24, 0xf0, 0x6b, - 0x5b, 0x24, 0x9a, 0x76, 0xcc, 0x7b, 0xd4, 0x1c, 0x7d, 0x7d, 0xb9, 0x9f, - 0xf8, 0x73, 0x36, 0x63, 0xb7, 0x8b, 0xc6, 0x9e, 0x0a, 0x3f, 0x7d, 0x1f, - 0x73, 0x65, 0x1f, 0x8a, 0x4f, 0x83, 0x43, 0xbe, 0x2f, 0xa0, 0xe2, 0x7c, - 0xc0, 0xc1, 0x89, 0xbf, 0x83, 0xae, 0xcd, 0x11, 0x97, 0x80, 0xcf, 0x5d, - 0x73, 0x94, 0xa3, 0xed, 0xd4, 0x65, 0xc0, 0x79, 0x29, 0xea, 0x6b, 0x59, - 0x3a, 0x06, 0xcc, 0x65, 0xdc, 0x2a, 0x79, 0xca, 0x2b, 0xef, 0x48, 0x2c, - 0x19, 0x32, 0x3d, 0xdf, 0x2a, 0xdd, 0x0b, 0x8c, 0xa9, 0x7e, 0xb3, 0x59, - 0x5a, 0x19, 0x57, 0xa5, 0x0d, 0x1a, 0x90, 0x1c, 0xca, 0xbb, 0x16, 0xc2, - 0x2a, 0x06, 0x56, 0x36, 0xc8, 0xa3, 0x7e, 0xe8, 0x03, 0x3b, 0xb5, 0x62, - 0x7c, 0xb4, 0xc9, 0xc7, 0x90, 0x90, 0xa5, 0x12, 0x64, 0xac, 0x04, 0x19, - 0x2b, 0x41, 0xc6, 0x4a, 0x90, 0x31, 0x60, 0xbf, 0x67, 0xb1, 0xff, 0xce, - 0x95, 0x06, 0xb5, 0x5d, 0xdf, 0xa3, 0xec, 0xfa, 0xe1, 0xd2, 0xab, 0x1e, - 0xd3, 0x2f, 0x29, 0xdf, 0xb4, 0x1f, 0x32, 0x48, 0x5f, 0x34, 0xf0, 0x51, - 0x5f, 0x95, 0xa7, 0x66, 0x5f, 0x93, 0x53, 0xb3, 0x6b, 0x38, 0x70, 0xaa, - 0xe4, 0xc9, 0xcb, 0x2e, 0xfc, 0xcf, 0x45, 0x62, 0xaa, 0x4c, 0x5b, 0xa3, - 0xc2, 0x56, 0x87, 0x24, 0xaf, 0x70, 0xb2, 0xb2, 0x23, 0xc0, 0x57, 0x0a, - 0x17, 0x72, 0x6f, 0x4a, 0xfb, 0x8e, 0xd7, 0xe5, 0x1c, 0xec, 0xf8, 0x52, - 0xed, 0x0d, 0x79, 0x4e, 0xe1, 0x71, 0xf2, 0xe1, 0x7d, 0xf2, 0xb7, 0xa6, - 0x7f, 0x86, 0x7f, 0x0a, 0x58, 0x63, 0xa9, 0x97, 0xba, 0x23, 0x02, 0x5b, - 0x60, 0x17, 0xba, 0xb0, 0xaf, 0x0f, 0x18, 0xef, 0x02, 0xa6, 0xe1, 0xfb, - 0xad, 0xf2, 0xe2, 0x6c, 0xa1, 0x4e, 0x26, 0xa8, 0x1f, 0xec, 0x23, 0x62, - 0xd0, 0x4e, 0xd1, 0x6e, 0x72, 0xbe, 0xb4, 0x53, 0x6d, 0x2d, 0xbc, 0x3f, - 0x56, 0x39, 0x7e, 0xc3, 0x16, 0xc6, 0x18, 0xe3, 0x0e, 0x79, 0xfa, 0xba, - 0x1c, 0xa8, 0xb2, 0xec, 0x35, 0xac, 0x0f, 0xd3, 0x37, 0xbd, 0xbb, 0xe3, - 0x1c, 0x8f, 0xfd, 0x02, 0x37, 0x75, 0x60, 0xae, 0xa5, 0xcf, 0x6a, 0xcc, - 0xdd, 0xaf, 0x70, 0xf4, 0xe5, 0x78, 0x99, 0x7c, 0x72, 0xc1, 0xa7, 0xd7, - 0x55, 0x0c, 0x70, 0x93, 0xd8, 0xf0, 0x13, 0xd8, 0x57, 0x85, 0x8b, 0xc2, - 0x38, 0x25, 0x63, 0xb8, 0x8c, 0x0f, 0xd7, 0x6b, 0x0c, 0x75, 0x57, 0x40, - 0xee, 0x82, 0x7e, 0xb9, 0x1b, 0xfa, 0xe5, 0x9e, 0xcb, 0xee, 0x5f, 0x07, - 0x71, 0xff, 0xee, 0x42, 0xd8, 0xe8, 0x94, 0xb1, 0x6a, 0x7d, 0x5b, 0xc6, - 0x6e, 0x37, 0x8b, 0xd5, 0x32, 0x8e, 0x9b, 0xda, 0x10, 0xff, 0xa3, 0x6c, - 0x78, 0xf2, 0x92, 0xcb, 0xb8, 0x5b, 0x70, 0x67, 0x7f, 0x33, 0xfc, 0x65, - 0xb5, 0x04, 0x71, 0xe6, 0x48, 0xfa, 0xa2, 0xf0, 0xee, 0x7e, 0x71, 0x86, - 0x78, 0x20, 0xae, 0xee, 0xd9, 0x19, 0x2a, 0xce, 0xe7, 0xb7, 0x2d, 0xce, - 0xa8, 0x73, 0xa5, 0x02, 0xe3, 0xd5, 0xe6, 0x4e, 0xdb, 0x1c, 0x0b, 0xfb, - 0xf7, 0x65, 0xb8, 0x97, 0x7d, 0x5d, 0x06, 0x59, 0xac, 0xad, 0xdd, 0xb1, - 0x1c, 0x52, 0xfa, 0xe2, 0x22, 0xf6, 0x00, 0xd7, 0x0b, 0xfe, 0x02, 0xf6, - 0xc9, 0x14, 0xf4, 0x53, 0x5e, 0xf5, 0x17, 0xa3, 0x5c, 0x64, 0xb2, 0x61, - 0x43, 0xa2, 0x27, 0xe8, 0x0b, 0xf9, 0xb1, 0x96, 0x5c, 0xd8, 0x56, 0xfa, - 0x1b, 0xb4, 0x03, 0x9f, 0x71, 0x7f, 0x5a, 0x13, 0x8d, 0xe9, 0x06, 0xd8, - 0x55, 0xac, 0x5f, 0x8d, 0x31, 0x01, 0xec, 0xdd, 0xe5, 0xef, 0xca, 0xfe, - 0xf9, 0xe1, 0x16, 0x5f, 0xfe, 0x19, 0x3b, 0xe6, 0xfc, 0x02, 0x1a, 0xd6, - 0xf7, 0x6d, 0x9c, 0x90, 0x58, 0x33, 0x6c, 0xda, 0x87, 0xe1, 0x67, 0xec, - 0x82, 0xac, 0xac, 0xc4, 0xd9, 0xaf, 0xbf, 0x67, 0xa6, 0x4b, 0xec, 0xfb, - 0xbb, 0x32, 0x3c, 0x7f, 0xb6, 0x85, 0xb6, 0x64, 0x19, 0x7a, 0xe0, 0xbc, - 0x49, 0x1b, 0x3a, 0x0e, 0x1b, 0xd7, 0x21, 0xdf, 0x9f, 0xa7, 0x7d, 0x4c, - 0x9a, 0xa7, 0xa4, 0x2f, 0x71, 0x0a, 0x34, 0x7d, 0xde, 0x8d, 0xd0, 0x47, - 0xf3, 0x86, 0x50, 0xf6, 0x4d, 0x49, 0x9a, 0x5d, 0x21, 0x3e, 0xf7, 0x99, - 0x8f, 0x03, 0xc3, 0x66, 0xcc, 0xa4, 0x79, 0x5d, 0x88, 0x72, 0x04, 0x9f, - 0x7b, 0x79, 0x8d, 0xce, 0x37, 0xe7, 0x95, 0x9f, 0xa4, 0xf4, 0xcc, 0xb2, - 0xcb, 0xf1, 0x40, 0xb7, 0xd2, 0x59, 0xd7, 0x41, 0x9f, 0xc4, 0xf4, 0x99, - 0x1b, 0xda, 0x10, 0xdb, 0xb8, 0x11, 0x9d, 0x7f, 0x44, 0xb2, 0x27, 0xe3, - 0xd0, 0x67, 0xec, 0x2b, 0xf0, 0x1d, 0x68, 0x23, 0x03, 0xbc, 0x4d, 0x7b, - 0x77, 0x2b, 0xec, 0xde, 0x35, 0x8a, 0x9e, 0x11, 0xb7, 0x5f, 0xa6, 0x8e, - 0x73, 0xec, 0x5e, 0xe8, 0xf2, 0x84, 0x92, 0xdb, 0x62, 0xe9, 0x7c, 0x22, - 0x06, 0x9d, 0x1c, 0xdb, 0x41, 0x7e, 0x7e, 0x50, 0xee, 0x70, 0xc6, 0xe5, - 0x4e, 0xc8, 0xce, 0x90, 0xe3, 0xca, 0x30, 0xd6, 0x62, 0x97, 0x03, 0xbb, - 0xa3, 0x30, 0x74, 0x23, 0xfc, 0x2e, 0x8e, 0xdd, 0xa1, 0xef, 0x5c, 0xf8, - 0xf8, 0xf1, 0xcf, 0x6a, 0x3e, 0x8f, 0xb2, 0xf3, 0x2f, 0x2b, 0xde, 0x8c, - 0xb8, 0x37, 0x69, 0x3b, 0xdb, 0x2a, 0x39, 0x55, 0xef, 0x26, 0x65, 0x8f, - 0x8b, 0x4b, 0xf7, 0x22, 0x85, 0x6d, 0x5e, 0x82, 0xbe, 0x01, 0xe6, 0x2e, - 0x56, 0x77, 0x22, 0x0f, 0x1b, 0xba, 0x94, 0x46, 0xfa, 0x41, 0xa4, 0xac, - 0xfb, 0xb9, 0x16, 0x3f, 0x96, 0x5b, 0x7f, 0x87, 0xcc, 0xbf, 0x7f, 0xfa, - 0x61, 0x85, 0x4b, 0x2f, 0xaa, 0xfb, 0x87, 0x06, 0xb0, 0x4e, 0x16, 0x7a, - 0xa5, 0x05, 0x18, 0x68, 0xe6, 0x84, 0x9d, 0x1a, 0x0e, 0xdd, 0x26, 0x1f, - 0x81, 0x2f, 0x5f, 0x71, 0xb9, 0x96, 0x3b, 0xe5, 0x13, 0xb7, 0x50, 0x46, - 0x6e, 0x93, 0x7d, 0xb7, 0x84, 0x64, 0x5f, 0xbf, 0x9d, 0x21, 0xdd, 0xd7, - 0xbe, 0x3f, 0xf0, 0xa7, 0xbb, 0x47, 0x92, 0xa1, 0x01, 0x79, 0x1c, 0x32, - 0x56, 0x80, 0x7c, 0x0d, 0xd7, 0xc8, 0x73, 0xea, 0x7b, 0xea, 0xf9, 0x14, - 0xb0, 0x72, 0x80, 0xfd, 0x1c, 0x99, 0xa9, 0x35, 0x88, 0x75, 0x15, 0xe3, - 0xc9, 0x96, 0x7f, 0xae, 0x71, 0x15, 0x65, 0x02, 0x3e, 0xc8, 0x55, 0xfe, - 0xfe, 0x54, 0xf7, 0xfe, 0xae, 0xf2, 0xed, 0x0a, 0xfc, 0x5f, 0x8f, 0x38, - 0xcf, 0xbf, 0x5f, 0x70, 0x51, 0xeb, 0xd2, 0xe4, 0xd6, 0x55, 0x7c, 0xd7, - 0x4a, 0xff, 0xe1, 0xeb, 0x2d, 0x6b, 0xdf, 0x2d, 0x6c, 0x94, 0xc5, 0x20, - 0xee, 0x56, 0xc6, 0x9c, 0x69, 0xd3, 0x6d, 0x93, 0xba, 0xb0, 0xcd, 0xd9, - 0x23, 0x7f, 0x09, 0xfb, 0xfe, 0xd5, 0x55, 0xfb, 0xbe, 0x17, 0xfc, 0xd8, - 0x88, 0x01, 0x1c, 0xf3, 0x2e, 0xcc, 0x65, 0x04, 0xeb, 0x79, 0x27, 0x7e, - 0x77, 0x94, 0xd6, 0xc5, 0xf1, 0x66, 0x0b, 0xc0, 0x93, 0x0d, 0x0e, 0xfb, - 0x5b, 0x17, 0xcf, 0x2b, 0xe4, 0x65, 0x35, 0x56, 0x38, 0x78, 0x49, 0x68, - 0xf7, 0xde, 0x92, 0x68, 0x8f, 0xf3, 0x56, 0x57, 0xc8, 0x79, 0xde, 0x08, - 0xf1, 0xec, 0xdb, 0x95, 0xd3, 0x35, 0xe2, 0xb0, 0x0b, 0x62, 0x9c, 0x25, - 0x06, 0x7b, 0x45, 0xc5, 0xa0, 0x2a, 0xa5, 0x6f, 0x23, 0x45, 0x7d, 0xe8, - 0xc7, 0xb0, 0x1f, 0xa7, 0x50, 0x58, 0x85, 0x7a, 0xf6, 0x4e, 0xac, 0xc3, - 0x14, 0x7e, 0x5d, 0x3b, 0xae, 0xc3, 0xfe, 0xa5, 0x9c, 0x32, 0xf6, 0xd5, - 0x63, 0xee, 0x08, 0xf1, 0xdd, 0x66, 0x71, 0xb0, 0xef, 0x48, 0x64, 0x0e, - 0xb6, 0xce, 0xa0, 0x7e, 0xe0, 0x3c, 0x68, 0x27, 0x4d, 0x59, 0x3c, 0xce, - 0xbd, 0xbe, 0x59, 0xfd, 0xa0, 0x6e, 0x30, 0x17, 0x65, 0x37, 0x32, 0x79, - 0xc6, 0x38, 0x4b, 0x5c, 0x03, 0x17, 0x6b, 0xe0, 0xc9, 0x09, 0xb7, 0x0d, - 0x7a, 0x3b, 0x2e, 0xe1, 0x13, 0x9e, 0x0c, 0x29, 0xec, 0xda, 0x07, 0xcc, - 0xb5, 0x55, 0xe3, 0x86, 0xb8, 0x44, 0x4e, 0x74, 0x4a, 0x23, 0x70, 0x75, - 0xc3, 0x51, 0xda, 0xc8, 0xa4, 0x35, 0x04, 0x21, 0x88, 0xa8, 0xbb, 0xac, - 0xf6, 0xe0, 0xf7, 0xa5, 0xcf, 0xfa, 0xbe, 0x10, 0x2f, 0xfd, 0x7b, 0xac, - 0x9f, 0xed, 0x5e, 0xd8, 0xa4, 0x7e, 0x71, 0xad, 0x3e, 0xe4, 0x88, 0xb1, - 0x35, 0xb6, 0x61, 0xac, 0x2d, 0x39, 0xf8, 0x3d, 0xc6, 0xd8, 0xe0, 0x6b, - 0x36, 0x9c, 0xf1, 0x69, 0x30, 0x96, 0xdb, 0xa5, 0x72, 0x92, 0x7b, 0x94, - 0x71, 0x16, 0xd3, 0xf7, 0x53, 0x4b, 0xf4, 0x57, 0xf9, 0xde, 0xd2, 0xef, - 0xbb, 0xf4, 0x7b, 0xfa, 0xa3, 0x05, 0xaf, 0x01, 0x3c, 0xdd, 0x05, 0xfd, - 0x79, 0xef, 0x4e, 0x47, 0xe1, 0x86, 0x7b, 0x57, 0xd7, 0x6c, 0xb7, 0xba, - 0x4f, 0x54, 0x29, 0x1d, 0x12, 0x67, 0xc7, 0x4a, 0x2a, 0x22, 0x63, 0x58, - 0x0b, 0xe6, 0x33, 0xa4, 0x27, 0x75, 0x58, 0x0e, 0xa8, 0xb5, 0xa9, 0x1c, - 0xb7, 0x8f, 0x58, 0xa1, 0x29, 0x31, 0x2a, 0x7c, 0xfe, 0x34, 0xd2, 0xc3, - 0xc0, 0x3b, 0x7e, 0xec, 0xd2, 0xa8, 0xac, 0xe7, 0x25, 0x30, 0x86, 0xb9, - 0x6b, 0x5d, 0x1c, 0x6b, 0x2d, 0xc6, 0xc5, 0xf7, 0x43, 0xea, 0x7d, 0x6a, - 0x5d, 0x9c, 0x2b, 0x67, 0x10, 0xcb, 0x04, 0xef, 0xb9, 0x16, 0x5c, 0x2f, - 0xd8, 0xe2, 0xe3, 0x41, 0xcc, 0xab, 0x55, 0xaf, 0x0b, 0xd7, 0x67, 0x46, - 0xce, 0x99, 0xf6, 0x08, 0xe5, 0xef, 0x86, 0x9d, 0x57, 0xcb, 0x44, 0x07, - 0xe3, 0x6d, 0xf5, 0x34, 0x6c, 0x8c, 0xa3, 0xd5, 0x8f, 0xbf, 0x31, 0xfe, - 0xc6, 0xb1, 0xfd, 0x18, 0x5b, 0x76, 0x5d, 0x8c, 0xad, 0x7e, 0x3c, 0x8e, - 0xb5, 0x15, 0xfe, 0x53, 0xc1, 0x8b, 0x3b, 0x5c, 0xa3, 0x6e, 0x6b, 0x9e, - 0xf9, 0x2f, 0x1a, 0x58, 0xc7, 0x38, 0xec, 0x08, 0xd7, 0x32, 0x38, 0x6f, - 0xe6, 0x9a, 0x26, 0xad, 0xc3, 0xfe, 0x7a, 0x0e, 0xfa, 0xeb, 0xee, 0xaf, - 0xff, 0x85, 0xd5, 0x75, 0xa4, 0x7d, 0xe0, 0x3a, 0x76, 0x88, 0x40, 0xcf, - 0x1a, 0x47, 0xb9, 0x86, 0x4c, 0xb9, 0x86, 0x7c, 0xc7, 0x35, 0xec, 0xd2, - 0xef, 0xb8, 0x7e, 0xc0, 0x69, 0x5f, 0xe0, 0x3d, 0xd5, 0xac, 0xfa, 0x06, - 0xab, 0xab, 0x27, 0xd8, 0x8b, 0x29, 0x79, 0x6e, 0xb1, 0x59, 0xcc, 0xb4, - 0x3f, 0xaf, 0xf1, 0x75, 0xf1, 0x76, 0x9e, 0x5f, 0xf5, 0x13, 0x7b, 0x06, - 0xf3, 0x4a, 0x70, 0x5e, 0x07, 0xe4, 0x75, 0xc9, 0xcf, 0x44, 0xe0, 0x03, - 0xa6, 0x80, 0x73, 0xfa, 0xa1, 0x6f, 0x19, 0x1f, 0x45, 0x59, 0x95, 0x78, - 0x85, 0xb6, 0x2e, 0x85, 0xbd, 0x42, 0x1d, 0x4c, 0x3c, 0xf2, 0x9a, 0xe4, - 0xca, 0x81, 0x8e, 0x41, 0xff, 0x46, 0xd0, 0x3f, 0xf9, 0x9c, 0xb9, 0x76, - 0xbb, 0xac, 0x58, 0xdb, 0xc5, 0xb6, 0x96, 0x64, 0x6d, 0x5d, 0xc7, 0x37, - 0xe7, 0xbb, 0x7b, 0x6f, 0x78, 0x4d, 0x36, 0xc6, 0x37, 0x59, 0xfb, 0x49, - 0x09, 0xde, 0x07, 0x6b, 0xbf, 0xe9, 0x3a, 0x14, 0x5e, 0x15, 0xae, 0x05, - 0x79, 0x40, 0x3c, 0x1c, 0x95, 0x7f, 0x13, 0xe7, 0x7e, 0x2c, 0xa8, 0x33, - 0xcd, 0xa4, 0xd1, 0xa3, 0x74, 0xc6, 0x90, 0xeb, 0xcb, 0x6b, 0x01, 0xe3, - 0xc4, 0xba, 0xff, 0xd0, 0x1b, 0x8a, 0xc3, 0xcf, 0xed, 0xa6, 0x7e, 0x09, - 0xf6, 0x74, 0xb3, 0xda, 0xd3, 0x9f, 0x77, 0x43, 0x52, 0x74, 0x42, 0x32, - 0xe5, 0x1c, 0x52, 0x18, 0xff, 0xa3, 0xe8, 0xeb, 0x13, 0xba, 0xaf, 0x29, - 0xe9, 0xd1, 0xfa, 0xe7, 0x20, 0xe4, 0xdc, 0x93, 0x7b, 0xdc, 0x9d, 0x72, - 0x43, 0x1b, 0xf7, 0x40, 0x30, 0xff, 0x43, 0xd2, 0xbd, 0x73, 0xc5, 0x82, - 0x67, 0x70, 0x6d, 0x74, 0x95, 0x07, 0xdc, 0x67, 0x81, 0x7c, 0xfb, 0x7c, - 0xf0, 0xe7, 0xbf, 0x6e, 0xae, 0x7a, 0x9e, 0x9c, 0x33, 0xeb, 0x71, 0xae, - 0x3e, 0x96, 0x5f, 0x9b, 0x6b, 0x50, 0xbf, 0x05, 0xb2, 0x64, 0x5b, 0x12, - 0xaa, 0xe7, 0xcd, 0xaa, 0x8e, 0x1a, 0x61, 0x8c, 0x64, 0xc5, 0xb4, 0x53, - 0x56, 0x28, 0x88, 0x45, 0xfb, 0x58, 0xb7, 0x0b, 0x38, 0xdc, 0xe9, 0xe9, - 0x49, 0xe5, 0x55, 0x8c, 0xd4, 0x50, 0xf3, 0x9a, 0x02, 0x26, 0x5b, 0x74, - 0x5f, 0xf5, 0x3e, 0x09, 0xcc, 0x3a, 0x21, 0x0f, 0x49, 0x78, 0x5d, 0x2c, - 0x17, 0xf9, 0xb3, 0x8c, 0xe7, 0xda, 0x56, 0x06, 0x6b, 0xfc, 0x3b, 0xf0, - 0xe1, 0x2b, 0xd0, 0xfb, 0x1f, 0xa3, 0x6d, 0x28, 0xc1, 0x5e, 0x00, 0x97, - 0x7c, 0xf5, 0x8a, 0x18, 0x7e, 0xa2, 0x2e, 0x96, 0xeb, 0xe3, 0xd3, 0x73, - 0x0a, 0x93, 0x12, 0xb7, 0x1f, 0x09, 0xdd, 0xd5, 0x1b, 0x86, 0x9f, 0x51, - 0xf0, 0x62, 0x0e, 0x71, 0xdc, 0x21, 0xb9, 0x03, 0xeb, 0x73, 0x7a, 0xb1, - 0x10, 0xda, 0x55, 0x0a, 0x64, 0x15, 0x7e, 0x65, 0xcd, 0x4e, 0x9d, 0x07, - 0x3f, 0x9e, 0xd2, 0x98, 0x8f, 0xe7, 0x35, 0x15, 0xed, 0xb3, 0x30, 0x36, - 0x54, 0xac, 0x1d, 0x92, 0x69, 0x97, 0xb1, 0x9d, 0x6e, 0x29, 0xc6, 0x33, - 0x57, 0x37, 0xae, 0xf2, 0xc8, 0x36, 0xe1, 0xf3, 0xa5, 0xa8, 0xbf, 0x2b, - 0xfa, 0xbc, 0xe3, 0x29, 0x25, 0x5f, 0x41, 0x5c, 0x98, 0xfe, 0x11, 0xcf, - 0xab, 0xba, 0xcd, 0x11, 0x3e, 0x97, 0x29, 0x03, 0xca, 0x67, 0x02, 0x2f, - 0xef, 0x90, 0xcc, 0x98, 0xa5, 0x70, 0xcb, 0x63, 0x25, 0xee, 0x17, 0xe2, - 0xff, 0xd7, 0x81, 0xfd, 0x23, 0x58, 0x33, 0xfa, 0x01, 0x1c, 0x9b, 0xfb, - 0x02, 0x65, 0x55, 0xf3, 0x97, 0xec, 0x8b, 0x0f, 0x6d, 0x23, 0xc6, 0x78, - 0xa1, 0xf4, 0x98, 0xe2, 0xdf, 0x8a, 0x04, 0xb1, 0x73, 0x85, 0x05, 0x0b, - 0xd9, 0x70, 0x48, 0x92, 0x73, 0xff, 0x16, 0x32, 0xd4, 0x0f, 0x1f, 0x89, - 0xf5, 0x44, 0x9d, 0x5f, 0x0d, 0x01, 0x73, 0x19, 0xce, 0xbb, 0xa4, 0x68, - 0x46, 0xa5, 0xa8, 0xee, 0xfe, 0xf1, 0x3c, 0x37, 0xac, 0x62, 0x3b, 0x45, - 0x93, 0x98, 0x3f, 0xbd, 0x2d, 0xb8, 0xfb, 0x57, 0x34, 0xd9, 0x8e, 0x79, - 0x96, 0x4f, 0x49, 0x74, 0xee, 0xa0, 0x34, 0xcc, 0x3d, 0x24, 0x8d, 0xc7, - 0x88, 0xf1, 0x18, 0xbb, 0x37, 0x6e, 0x6d, 0x14, 0x62, 0xee, 0x6f, 0x61, - 0xec, 0x43, 0xf2, 0x03, 0x37, 0xa0, 0xe9, 0xba, 0xad, 0xd2, 0xca, 0x3a, - 0x41, 0x9e, 0xcf, 0xc4, 0x09, 0x3c, 0x17, 0x77, 0xfc, 0x18, 0xa9, 0x3a, - 0x57, 0x41, 0x5a, 0xe1, 0xb9, 0x38, 0xdf, 0xbf, 0x66, 0xfa, 0xa9, 0x8f, - 0xf7, 0x7d, 0xdf, 0x83, 0x6d, 0x52, 0x75, 0xd8, 0x62, 0xfd, 0xf7, 0xa1, - 0x39, 0x94, 0xe7, 0xe7, 0x83, 0x3b, 0x3a, 0x06, 0x7c, 0x5f, 0xbb, 0x40, - 0x9f, 0xc1, 0xe4, 0xb7, 0x98, 0xf3, 0x05, 0xf0, 0xf9, 0x1a, 0x75, 0xbf, - 0x87, 0x77, 0x24, 0x50, 0xcf, 0xf2, 0x31, 0x1f, 0xf3, 0x09, 0xf0, 0xf9, - 0xfd, 0x9d, 0x46, 0xfa, 0x7f, 0x5f, 0x9d, 0x1d, 0x20, 0xa6, 0xd8, 0xc6, - 0xb3, 0x3f, 0x60, 0x55, 0xae, 0xed, 0x77, 0xb1, 0xb6, 0x8d, 0xea, 0xac, - 0xa5, 0x58, 0xa2, 0x0f, 0x95, 0xc7, 0x9a, 0xf1, 0x9e, 0x1c, 0x7d, 0xad, - 0xbc, 0x8e, 0x81, 0x92, 0x4e, 0xe2, 0xe8, 0x00, 0x93, 0xb3, 0xcf, 0xcd, - 0xee, 0x03, 0x07, 0x7e, 0x12, 0xd7, 0x38, 0xa1, 0x68, 0x1e, 0xde, 0xe0, - 0x23, 0x1c, 0xc6, 0xfe, 0x5b, 0x84, 0x0c, 0x4d, 0x42, 0xef, 0x0c, 0x85, - 0xb9, 0x27, 0x9a, 0xb5, 0xff, 0xe8, 0xd0, 0x57, 0x0e, 0x8d, 0xa1, 0x0f, - 0xe3, 0xd8, 0x1b, 0x32, 0x05, 0x9d, 0x3b, 0x5d, 0x4b, 0xaa, 0x6f, 0x78, - 0x32, 0x09, 0xde, 0xdb, 0x62, 0xf9, 0x7f, 0x81, 0x8c, 0xbc, 0x01, 0x0c, - 0xba, 0x05, 0xfc, 0x34, 0xf4, 0xbd, 0x90, 0x0f, 0xe8, 0xf8, 0x4f, 0x8c, - 0xf1, 0x6f, 0xe8, 0xaa, 0xa2, 0x8f, 0xef, 0xe2, 0xd3, 0x48, 0xbf, 0xd0, - 0xec, 0xcb, 0xc8, 0xcb, 0x7a, 0x8d, 0x9b, 0x50, 0xfe, 0xa8, 0x8a, 0xfb, - 0xf9, 0x73, 0xb2, 0xb5, 0x7f, 0x10, 0xc5, 0x3a, 0x73, 0x5e, 0x5f, 0x41, - 0x3d, 0xae, 0x6f, 0xaf, 0x3e, 0x0f, 0x6d, 0x56, 0x3a, 0x29, 0xe7, 0x5a, - 0xf0, 0x75, 0x89, 0x89, 0x80, 0xa9, 0x5d, 0xb6, 0x7b, 0x76, 0x1b, 0xcf, - 0x1b, 0x1b, 0x1c, 0x85, 0xe7, 0x3b, 0xc2, 0x12, 0x94, 0xdd, 0x8e, 0x32, - 0xc6, 0x25, 0xde, 0x85, 0xb5, 0x61, 0x59, 0x16, 0x79, 0x8e, 0x75, 0xb5, - 0x1e, 0x87, 0x63, 0x0c, 0xb7, 0xac, 0xa7, 0x89, 0x73, 0xe9, 0xd8, 0xf0, - 0xfd, 0x00, 0xcb, 0xde, 0xa5, 0xcb, 0x22, 0x7a, 0x7e, 0xb7, 0xeb, 0x6f, - 0x67, 0xed, 0x23, 0x99, 0x55, 0x3c, 0x4a, 0xfa, 0x62, 0xaa, 0x5d, 0xc6, - 0xf4, 0x65, 0xe7, 0x30, 0xd6, 0x23, 0x92, 0xf6, 0xda, 0xb9, 0x47, 0x86, - 0xc2, 0x81, 0x5f, 0x98, 0x50, 0xbe, 0x9e, 0x65, 0xf8, 0x77, 0x84, 0xce, - 0x5d, 0x76, 0x0f, 0xda, 0xbf, 0x53, 0x3e, 0xdc, 0xdb, 0x24, 0x8b, 0xb3, - 0x31, 0x7d, 0x3f, 0x31, 0xa1, 0xf6, 0x49, 0x7e, 0x9c, 0xf9, 0x1f, 0x6d, - 0xe3, 0x77, 0xcb, 0x86, 0xc3, 0xf2, 0x0e, 0xcd, 0xdf, 0x77, 0xa9, 0xfb, - 0x3c, 0xbc, 0x67, 0x52, 0x2c, 0xff, 0x44, 0xbd, 0x3f, 0x3d, 0xdf, 0xa0, - 0xea, 0x9f, 0x9e, 0xdf, 0x78, 0x27, 0x87, 0x65, 0xef, 0x66, 0x4c, 0x41, - 0x96, 0x66, 0x1a, 0x64, 0x79, 0xde, 0xa2, 0x8f, 0x94, 0x6e, 0x5c, 0xfb, - 0xf6, 0x45, 0x7f, 0xa7, 0xe6, 0xc9, 0x30, 0xd6, 0x6f, 0x71, 0x70, 0x5a, - 0x2a, 0x83, 0xf4, 0x01, 0xd4, 0xbd, 0x3b, 0xc8, 0x48, 0x03, 0xf0, 0x5f, - 0xc1, 0xab, 0x38, 0x8c, 0xbd, 0xb6, 0x6a, 0x1f, 0xea, 0xc7, 0xda, 0xcf, - 0x22, 0x8f, 0x0c, 0xc9, 0xf5, 0x4f, 0x29, 0xba, 0x2a, 0x8a, 0x57, 0xc1, - 0xb7, 0x45, 0xec, 0x9f, 0xdf, 0x17, 0x85, 0x35, 0x7e, 0x7c, 0x50, 0xf3, - 0xfc, 0xaf, 0x75, 0xfa, 0x88, 0xec, 0x3b, 0xfe, 0x19, 0xd0, 0xda, 0xe4, - 0xdf, 0x2d, 0x92, 0xfa, 0xef, 0x36, 0x22, 0xea, 0xdb, 0x95, 0x88, 0xf3, - 0x08, 0xca, 0x18, 0x7b, 0x7a, 0x44, 0xcd, 0x83, 0xf7, 0xd7, 0x0a, 0xf2, - 0xab, 0xee, 0x64, 0x04, 0xfe, 0x0f, 0xef, 0x08, 0x35, 0xeb, 0xfe, 0x76, - 0xe9, 0x75, 0x1c, 0x97, 0x7d, 0xd0, 0xef, 0x79, 0xe0, 0x40, 0xde, 0xab, - 0x9a, 0x08, 0xd7, 0x8f, 0x19, 0xc8, 0xb2, 0xef, 0x5b, 0x07, 0x67, 0xfd, - 0x61, 0xe5, 0x03, 0xac, 0xfa, 0xe9, 0xba, 0x7c, 0x5c, 0xf6, 0x97, 0x94, - 0xbf, 0xae, 0xce, 0xe8, 0xa6, 0xb1, 0x27, 0x87, 0x94, 0x0e, 0x8f, 0x85, - 0x86, 0xab, 0x69, 0xc9, 0x9f, 0xdc, 0x8d, 0x71, 0x18, 0xfb, 0xca, 0xe8, - 0xb3, 0xb0, 0xbd, 0xb2, 0xaf, 0xe6, 0x8f, 0x3d, 0x59, 0xe2, 0xfb, 0x24, - 0xec, 0x22, 0xdf, 0xe7, 0x12, 0x61, 0x15, 0xcd, 0xbf, 0x0e, 0x6d, 0x1b, - 0x34, 0x6f, 0x79, 0x9f, 0x9e, 0xed, 0xb9, 0xff, 0x3e, 0x6e, 0x4a, 0x73, - 0x0e, 0xef, 0xd9, 0x26, 0xe8, 0x6f, 0x12, 0x7a, 0x9a, 0xfe, 0xe8, 0xc3, - 0xb2, 0x52, 0x9e, 0x96, 0xf3, 0xe5, 0x40, 0xce, 0x78, 0xb7, 0x99, 0xb4, - 0xdf, 0xa9, 0xef, 0x36, 0x67, 0xb0, 0x0e, 0xeb, 0x79, 0x95, 0x5b, 0xf7, - 0xfd, 0xd1, 0x5f, 0x98, 0xfe, 0x37, 0x80, 0xb7, 0xa9, 0x7b, 0x4a, 0xeb, - 0xe5, 0x9d, 0xfd, 0x2c, 0x9b, 0x8c, 0xed, 0xfb, 0x77, 0xad, 0x3a, 0xea, - 0xde, 0xc7, 0xf5, 0xfd, 0xa6, 0xe7, 0xf4, 0x9d, 0x78, 0xf2, 0x73, 0x4c, - 0xd3, 0x7b, 0x1d, 0xf6, 0x1e, 0xfb, 0x7c, 0x54, 0xaf, 0x1b, 0xd2, 0x45, - 0x3e, 0x53, 0x0f, 0xad, 0xe8, 0xf3, 0x4e, 0x53, 0x8f, 0x51, 0x7f, 0xbf, - 0xac, 0xa1, 0x6e, 0x5c, 0xb6, 0xe7, 0xb7, 0x48, 0xc1, 0x5d, 0x6b, 0x96, - 0x1d, 0xd7, 0xf7, 0xd8, 0x82, 0xbb, 0xd5, 0x2c, 0x0b, 0xee, 0x5b, 0x91, - 0x5f, 0x8c, 0xe1, 0x21, 0xad, 0x8d, 0xe9, 0xe7, 0xb1, 0xba, 0x6f, 0x74, - 0x82, 0x3e, 0x23, 0xe8, 0xe3, 0xf6, 0xf0, 0xe5, 0x77, 0xb1, 0xf9, 0xdd, - 0x14, 0x65, 0xd1, 0xe0, 0x37, 0xdd, 0xf4, 0x7b, 0x80, 0x55, 0xb6, 0xca, - 0xa4, 0xa2, 0xa7, 0xa0, 0xee, 0x27, 0x64, 0xdd, 0x26, 0x19, 0x32, 0xfd, - 0xfc, 0xe4, 0xe2, 0x46, 0x39, 0x65, 0xf9, 0xf5, 0x31, 0x69, 0x2e, 0x60, - 0x1c, 0xbe, 0xdf, 0xec, 0x1b, 0x81, 0xa8, 0xfe, 0x4e, 0xc9, 0x45, 0x9b, - 0xcf, 0x53, 0xde, 0x0b, 0x85, 0xd5, 0xbb, 0x90, 0x05, 0x15, 0x97, 0x14, - 0x23, 0xb8, 0x93, 0xc8, 0x6f, 0xd6, 0x45, 0x9e, 0xa9, 0xf2, 0xbb, 0xad, - 0xdb, 0xd4, 0xbd, 0x11, 0xff, 0x2c, 0x8e, 0x74, 0x75, 0x2b, 0x9d, 0x5c, - 0xa9, 0x16, 0xc9, 0x53, 0x1d, 0x87, 0x8d, 0xea, 0x38, 0x2c, 0x79, 0x3c, - 0x02, 0x1e, 0xff, 0x3f, 0xbd, 0x2e, 0xc1, 0x77, 0x5f, 0x3c, 0xeb, 0xe1, - 0x79, 0xd0, 0xa3, 0x6a, 0x2e, 0xd4, 0xd1, 0x68, 0xfb, 0xde, 0xb0, 0xda, - 0xbb, 0xea, 0x9b, 0x78, 0xc8, 0x27, 0xbf, 0x71, 0x87, 0x7e, 0x2d, 0xf1, - 0x5b, 0xf6, 0x11, 0xf5, 0x3d, 0x47, 0xa5, 0xca, 0x75, 0xe5, 0x37, 0xec, - 0x63, 0x75, 0xf2, 0x18, 0xd6, 0x63, 0x6d, 0x69, 0x93, 0x66, 0x7f, 0xdd, - 0xf9, 0x2d, 0x48, 0xa5, 0x1a, 0xdc, 0xa3, 0xdc, 0xb2, 0xc2, 0x3d, 0x21, - 0xbe, 0x5f, 0xab, 0xbe, 0x67, 0xa9, 0xa8, 0xef, 0x43, 0x2c, 0x7e, 0x67, - 0x09, 0xdb, 0xb1, 0x07, 0xcf, 0x3c, 0x47, 0xdd, 0x8b, 0x14, 0x3a, 0xa7, - 0x3a, 0x81, 0xf4, 0x21, 0xc9, 0xa9, 0x38, 0x57, 0x0b, 0xf2, 0x93, 0x6a, - 0xec, 0x62, 0xf5, 0x7e, 0xd9, 0x77, 0xf2, 0x01, 0x7e, 0x43, 0xa3, 0xbe, - 0xc3, 0xcf, 0xba, 0xa4, 0x31, 0x2e, 0x53, 0x6a, 0xde, 0x85, 0xb5, 0x6f, - 0x33, 0x7c, 0x39, 0x6a, 0xe3, 0x9a, 0x16, 0xaa, 0x2d, 0xa0, 0x31, 0xa4, - 0xef, 0x52, 0x12, 0xff, 0x06, 0xf3, 0x6f, 0xe6, 0xfd, 0x3c, 0x8f, 0xe7, - 0x65, 0xfb, 0x4a, 0xbc, 0x2b, 0x99, 0xd4, 0x7e, 0x31, 0x63, 0x65, 0x8c, - 0xc7, 0x53, 0xc6, 0xed, 0xd4, 0x04, 0xb4, 0x7f, 0x54, 0x12, 0x3c, 0xcb, - 0xd5, 0x73, 0x69, 0xa9, 0x9b, 0x0b, 0xef, 0x87, 0xfa, 0xf3, 0xe1, 0x37, - 0x27, 0xf9, 0x52, 0xfd, 0xf7, 0x32, 0xea, 0x9b, 0x70, 0xf5, 0x7d, 0xca, - 0x44, 0xf5, 0x41, 0xb9, 0xaf, 0xb4, 0x55, 0x7f, 0x2b, 0x13, 0x93, 0xfb, - 0xaa, 0x6f, 0x28, 0x9e, 0xe6, 0xd5, 0x77, 0x3e, 0x51, 0xbd, 0x66, 0x71, - 0xd5, 0xc7, 0xda, 0xf7, 0x3e, 0x76, 0xdd, 0xb7, 0x1f, 0x51, 0x99, 0x58, - 0xfc, 0x65, 0xdf, 0xfc, 0x3c, 0x2c, 0xfc, 0xee, 0xe3, 0x25, 0x77, 0x5a, - 0x1e, 0x2b, 0x7b, 0xde, 0x1d, 0x2e, 0xb1, 0xd4, 0x16, 0x39, 0x1f, 0xcf, - 0x0c, 0x7e, 0xcf, 0x69, 0x0f, 0x55, 0x66, 0x1b, 0xa1, 0xaf, 0x1b, 0x95, - 0x2d, 0x61, 0x7e, 0x71, 0x96, 0x7b, 0x3e, 0x82, 0x39, 0xda, 0xe6, 0x25, - 0xf9, 0x54, 0x1b, 0xe3, 0x4c, 0x77, 0xc0, 0x77, 0xfb, 0xb8, 0xeb, 0xeb, - 0xe5, 0xcf, 0x2d, 0xed, 0x96, 0xcf, 0x55, 0x63, 0xa1, 0xca, 0x0c, 0xef, - 0xd7, 0xd9, 0x23, 0x65, 0x49, 0xa2, 0x1e, 0xfb, 0x87, 0xbc, 0x24, 0xb6, - 0xcb, 0xd3, 0xc7, 0x7f, 0xee, 0x5d, 0x72, 0xf0, 0x1e, 0xba, 0xe6, 0xbc, - 0x1b, 0xc4, 0xd2, 0xe0, 0x37, 0x1f, 0x65, 0xbd, 0xed, 0x90, 0x03, 0xd8, - 0x6d, 0xec, 0x39, 0xfa, 0x75, 0x97, 0xb4, 0xde, 0x32, 0x8e, 0x5e, 0x23, - 0x97, 0x56, 0xef, 0xe4, 0xbe, 0x0e, 0xd9, 0xb6, 0x7c, 0xfe, 0xab, 0xd8, - 0xf3, 0x41, 0x09, 0x7f, 0x01, 0x76, 0xe2, 0x0b, 0x0d, 0x4a, 0xb7, 0xd3, - 0x9e, 0x01, 0xf3, 0x03, 0xd7, 0x47, 0xd0, 0xcf, 0xfe, 0x36, 0x5f, 0x66, - 0xa7, 0x45, 0xbe, 0xd8, 0x24, 0x99, 0x36, 0xfa, 0x8d, 0xf2, 0x2b, 0xf4, - 0x57, 0xfd, 0x3e, 0x4b, 0xc9, 0x9f, 0x71, 0x8f, 0xd7, 0x38, 0x97, 0x64, - 0xe2, 0x7f, 0xc9, 0x27, 0x65, 0x22, 0xc1, 0xb9, 0x3c, 0x2c, 0x85, 0xf2, - 0xa3, 0xf8, 0x71, 0x9e, 0xa4, 0xfb, 0x5f, 0xe8, 0xb3, 0xfb, 0x31, 0x29, - 0xce, 0xa4, 0x65, 0x6a, 0x7e, 0x92, 0xdf, 0xe4, 0x8e, 0xdc, 0xa1, 0xce, - 0xb4, 0xec, 0x44, 0x32, 0xd4, 0x67, 0x4d, 0xf1, 0xae, 0x82, 0x9a, 0xcf, - 0x24, 0xe6, 0xf3, 0x4a, 0x1b, 0xef, 0x78, 0x5f, 0x82, 0xfe, 0x35, 0x4e, - 0x50, 0x0e, 0x6d, 0xb3, 0x2b, 0xc4, 0xfc, 0x5e, 0xf8, 0xab, 0x2c, 0xdb, - 0x2b, 0xe1, 0xa3, 0xab, 0x7a, 0x1e, 0xe5, 0xfa, 0x6c, 0x55, 0xb5, 0xff, - 0xaf, 0x68, 0x8b, 0x7a, 0x47, 0x83, 0xb6, 0x41, 0x1d, 0xb6, 0xe5, 0x3c, - 0x77, 0xc3, 0x4f, 0x0e, 0xe8, 0x82, 0x1c, 0x26, 0xea, 0xf9, 0xdd, 0xbc, - 0x81, 0xdf, 0x11, 0xe2, 0x4d, 0xf0, 0x8b, 0x3c, 0x0e, 0x6b, 0x1e, 0xff, - 0x3d, 0xfa, 0x0f, 0xd6, 0xe0, 0x0e, 0x94, 0x99, 0xfa, 0x1b, 0xbc, 0x77, - 0xc2, 0x77, 0xf2, 0x9c, 0xf5, 0xf7, 0xb7, 0xf9, 0xb2, 0x46, 0x7a, 0x36, - 0xe3, 0xf9, 0x7b, 0xdb, 0xfd, 0x75, 0xd9, 0x0b, 0x7e, 0xf1, 0x1e, 0x65, - 0x9f, 0xba, 0x8f, 0x9f, 0x19, 0xdf, 0x0b, 0xd9, 0x09, 0xe6, 0xd5, 0x07, - 0x19, 0xe3, 0x39, 0x01, 0xeb, 0xd7, 0xf3, 0xc4, 0xb7, 0x7b, 0x61, 0xfa, - 0xfa, 0x0e, 0xe7, 0x0a, 0x4c, 0xf8, 0x45, 0xf5, 0xfd, 0x0d, 0xf4, 0xe4, - 0xbb, 0x57, 0xbf, 0xbf, 0xb9, 0xf2, 0x1a, 0x0f, 0xb4, 0xfb, 0x36, 0xca, - 0x04, 0x4f, 0x5a, 0x75, 0x9b, 0xbd, 0xc0, 0xa7, 0x8c, 0x7f, 0x26, 0x13, - 0x9f, 0x90, 0x60, 0x1c, 0xef, 0x36, 0xfa, 0x79, 0x43, 0x03, 0x7d, 0xf0, - 0x69, 0xd5, 0x1d, 0x95, 0x04, 0xef, 0xbc, 0x24, 0x43, 0x7b, 0xd5, 0x7d, - 0x85, 0x17, 0xd6, 0x7d, 0x43, 0x95, 0x92, 0xa7, 0xd7, 0x64, 0x65, 0xe4, - 0x47, 0x62, 0x8b, 0x75, 0x35, 0x65, 0x85, 0xfd, 0x4e, 0x72, 0x9e, 0x89, - 0x07, 0xd4, 0x3c, 0x4d, 0xf8, 0x4d, 0xbc, 0x5b, 0x60, 0x86, 0x2a, 0xf3, - 0x5c, 0x77, 0xa4, 0x4b, 0x7c, 0x0e, 0xce, 0x37, 0x95, 0x5e, 0xc1, 0xb8, - 0x2c, 0xa3, 0x6e, 0xe4, 0xfb, 0xb4, 0x3e, 0xff, 0xbc, 0xa7, 0x9d, 0x67, - 0xf0, 0x79, 0x94, 0x95, 0x97, 0x36, 0xa7, 0xed, 0xe3, 0x4a, 0x0e, 0x1e, - 0x06, 0xdf, 0xff, 0x04, 0x75, 0x1f, 0x45, 0xca, 0x39, 0xa6, 0x57, 0xd7, - 0x9d, 0xfc, 0xfe, 0xb0, 0x0c, 0x42, 0x2e, 0x98, 0x7f, 0x58, 0x8a, 0xea, - 0xee, 0x10, 0xd2, 0x32, 0x9f, 0xa9, 0xeb, 0x1d, 0x6d, 0x4f, 0x49, 0xcb, - 0x5e, 0xfd, 0xdd, 0x56, 0x20, 0x4f, 0x7b, 0x74, 0xbb, 0xf1, 0x55, 0x5e, - 0x3d, 0x70, 0x19, 0xde, 0x88, 0xae, 0xe2, 0x0d, 0x7f, 0xac, 0x62, 0x7b, - 0x80, 0x35, 0xfc, 0x39, 0xf8, 0x58, 0xc3, 0x97, 0xf3, 0x49, 0x89, 0x40, - 0x8e, 0xc3, 0x6b, 0x72, 0x0c, 0xdc, 0xe3, 0xef, 0x99, 0x29, 0x9e, 0xdb, - 0x29, 0x3e, 0x53, 0x0e, 0x29, 0xbf, 0x5c, 0xc7, 0xfa, 0xb5, 0xbe, 0xf1, - 0x97, 0xac, 0xf5, 0x85, 0xf6, 0x00, 0x3f, 0xfc, 0xd3, 0xf6, 0xc1, 0xd7, - 0xda, 0xd7, 0xf6, 0xc1, 0x35, 0xbf, 0xa1, 0x7d, 0xb0, 0x51, 0x2e, 0xeb, - 0x65, 0xca, 0x84, 0x3c, 0x71, 0xbd, 0x28, 0x4f, 0x94, 0x23, 0xf2, 0x92, - 0xfa, 0xb4, 0x91, 0xbe, 0x53, 0xe2, 0xa2, 0xfa, 0x3e, 0x62, 0x1a, 0x3a, - 0xa8, 0x3d, 0x54, 0x86, 0x5f, 0x5e, 0x5c, 0xba, 0x49, 0xc9, 0xf4, 0xd3, - 0x35, 0xea, 0xa5, 0x2b, 0xcd, 0x7d, 0xbd, 0xce, 0xcd, 0x6f, 0xd0, 0xb9, - 0xf9, 0x55, 0x9d, 0xdb, 0xa6, 0xfd, 0xa5, 0x7f, 0x8a, 0xce, 0x8d, 0xd7, - 0x9d, 0x85, 0x04, 0xe7, 0x20, 0x12, 0xca, 0xf6, 0x36, 0xcb, 0xae, 0xd9, - 0xb8, 0x8c, 0xcc, 0xec, 0x96, 0x3f, 0x9a, 0x99, 0x56, 0xf7, 0x82, 0xfe, - 0xca, 0x4d, 0x26, 0xee, 0x0f, 0x79, 0xf2, 0x61, 0xf8, 0xbb, 0x13, 0x9d, - 0x0d, 0xb2, 0xeb, 0xfd, 0xea, 0x7c, 0xcf, 0xcc, 0x86, 0x3a, 0x84, 0x91, - 0xe7, 0x9c, 0x6b, 0xbb, 0x56, 0x88, 0x77, 0xc4, 0x1a, 0x65, 0x22, 0xde, - 0x22, 0xbb, 0x81, 0x9d, 0x0a, 0x57, 0xb9, 0xea, 0x9b, 0xed, 0x8c, 0x3a, - 0x3f, 0xe9, 0xde, 0xee, 0x8f, 0x0b, 0x3e, 0xb4, 0x9a, 0xf2, 0xe7, 0xb5, - 0x6e, 0xf5, 0xfd, 0xf1, 0x0b, 0xa5, 0x3f, 0x6f, 0x5b, 0x9f, 0xe7, 0xf3, - 0x7f, 0x42, 0x9d, 0x38, 0x78, 0x55, 0x7f, 0xdf, 0x26, 0xac, 0xf8, 0x59, - 0x2c, 0x8f, 0xab, 0x7b, 0x4c, 0x17, 0xc3, 0xe4, 0x97, 0xf2, 0x9b, 0x12, - 0xd9, 0x30, 0x30, 0xce, 0x2c, 0x90, 0xb4, 0x43, 0x9f, 0x4f, 0xe3, 0x4f, - 0xe8, 0xff, 0x7d, 0xea, 0x3c, 0x75, 0x05, 0xbc, 0xf1, 0x54, 0xbc, 0x35, - 0x1f, 0x27, 0xae, 0x5f, 0xbb, 0xb3, 0x7b, 0x39, 0xbe, 0xf7, 0xbf, 0xf1, - 0xd2, 0xb1, 0x7f, 0x1d, 0x9f, 0xd1, 0x3e, 0xb8, 0x3a, 0xcb, 0xda, 0xec, - 0xff, 0x50, 0xf8, 0xdf, 0xec, 0x67, 0x4b, 0xc4, 0x76, 0xf6, 0x91, 0xb2, - 0xf4, 0x6f, 0x57, 0xb1, 0x26, 0xf2, 0xb7, 0x82, 0x75, 0x3a, 0x96, 0x08, - 0xec, 0x79, 0xa8, 0xeb, 0x6c, 0xbd, 0x1f, 0xc8, 0x3e, 0x62, 0xea, 0x0e, - 0xc4, 0xda, 0xff, 0xbd, 0x61, 0x4c, 0x25, 0x13, 0xba, 0xab, 0x34, 0x2d, - 0xe1, 0xb9, 0x31, 0x89, 0x1c, 0x63, 0xfc, 0x3a, 0x23, 0xc5, 0xb8, 0x27, - 0xf7, 0xb9, 0xeb, 0x7d, 0x93, 0x2e, 0x63, 0x23, 0xed, 0x0f, 0xcb, 0xd0, - 0xc9, 0x47, 0x25, 0x3a, 0xc7, 0x77, 0xeb, 0xce, 0x2e, 0xa0, 0x8f, 0xb6, - 0x48, 0x39, 0xce, 0x18, 0x6e, 0x54, 0x9d, 0x05, 0x9f, 0x1f, 0x5f, 0x90, - 0x22, 0xb0, 0x42, 0x5e, 0xe9, 0x16, 0xa4, 0xab, 0xbe, 0xc4, 0xf4, 0x76, - 0xee, 0x29, 0xf8, 0x98, 0xa1, 0x89, 0x72, 0x54, 0xdd, 0xc9, 0x39, 0x1f, - 0x67, 0x5d, 0xf8, 0xef, 0x73, 0xc4, 0x19, 0xd0, 0x1d, 0x63, 0x12, 0x62, - 0x3e, 0x3c, 0xb7, 0x86, 0x33, 0xa8, 0x13, 0x86, 0xdc, 0xb8, 0x44, 0x4e, - 0xf9, 0x73, 0xe7, 0x3f, 0x52, 0x32, 0x16, 0x76, 0x4b, 0xf8, 0x18, 0x9f, - 0xeb, 0xfd, 0x21, 0x62, 0x77, 0xd8, 0x86, 0xb3, 0x9f, 0x45, 0x7f, 0x7c, - 0x97, 0xd1, 0xdf, 0xc2, 0x22, 0x5f, 0xf9, 0xc7, 0xfe, 0xcf, 0x04, 0xca, - 0xfe, 0xff, 0x07, 0x3b, 0x97, 0x22, 0x9a, 0xb0, 0x4e, 0x00, 0x00, 0x00 }; + 0xcd, 0x7c, 0x0d, 0x70, 0x5b, 0xd7, 0x95, 0xde, 0xc1, 0x03, 0x40, 0x82, + 0x10, 0x45, 0x3d, 0x52, 0x30, 0x0d, 0x3b, 0x4c, 0x82, 0x47, 0x3c, 0x92, + 0xb0, 0xc9, 0x64, 0x9f, 0x64, 0x46, 0x66, 0x12, 0xac, 0x05, 0x03, 0xa4, + 0x4c, 0x27, 0xea, 0x92, 0xb6, 0x19, 0x47, 0x6d, 0x35, 0x09, 0x17, 0x92, + 0x12, 0xdb, 0x4d, 0xa7, 0x9a, 0xc6, 0xe9, 0x2a, 0x1b, 0xc7, 0x82, 0x41, + 0xca, 0x51, 0x52, 0x8a, 0x60, 0x24, 0x4a, 0xf2, 0x74, 0xb3, 0xbb, 0x0c, + 0x48, 0x4a, 0x8e, 0x03, 0x09, 0x96, 0xec, 0x75, 0xdc, 0xad, 0xb3, 0x62, + 0x68, 0xad, 0xec, 0x4d, 0xb3, 0xad, 0x9d, 0x49, 0x3a, 0x9a, 0xa9, 0xb7, + 0x55, 0x95, 0xa4, 0xf9, 0x99, 0xfe, 0xb8, 0x49, 0xa6, 0x75, 0xbb, 0xf1, + 0xbe, 0x7e, 0xdf, 0x7d, 0xf7, 0x11, 0x20, 0xc5, 0x28, 0xde, 0xec, 0x64, + 0x66, 0x39, 0x83, 0xb9, 0xef, 0xde, 0x77, 0x7f, 0xce, 0x3d, 0xf7, 0xfc, + 0x7c, 0xe7, 0xde, 0xfb, 0x78, 0x87, 0x48, 0x54, 0xf4, 0xdf, 0x46, 0xfc, + 0xfa, 0xff, 0xe9, 0x3f, 0xdb, 0xb3, 0xf5, 0xdd, 0xfd, 0xef, 0x66, 0xde, + 0x30, 0x42, 0x21, 0xa6, 0x41, 0xfc, 0x62, 0xf8, 0x6d, 0xd5, 0xcf, 0xeb, + 0xfd, 0x99, 0xf8, 0x6d, 0x0b, 0x88, 0x8c, 0xff, 0x44, 0x24, 0xb0, 0xe6, + 0x5d, 0x64, 0x9d, 0xfa, 0xae, 0xfb, 0x4b, 0x3a, 0xd2, 0x7f, 0x06, 0x7e, + 0x89, 0xeb, 0x57, 0x59, 0x19, 0xf7, 0xd7, 0xfd, 0x0b, 0xea, 0xe6, 0x1b, + 0xf5, 0x4f, 0x22, 0x46, 0x5a, 0x46, 0xb2, 0xb6, 0x44, 0x82, 0xe9, 0x9f, + 0x8f, 0xec, 0xb1, 0x45, 0x32, 0x95, 0xde, 0x44, 0x4e, 0xde, 0x74, 0x0b, + 0xb1, 0x90, 0xb0, 0xfc, 0xed, 0xe9, 0x5f, 0x1c, 0xfc, 0xfa, 0xed, 0xd6, + 0xeb, 0x73, 0x41, 0x89, 0x98, 0xe9, 0x37, 0xc4, 0xec, 0x96, 0x48, 0x07, + 0xda, 0x7c, 0xa9, 0xe7, 0x49, 0x43, 0x5a, 0xfc, 0xbe, 0xcc, 0xf1, 0x60, + 0x5a, 0x46, 0xf7, 0x4e, 0x1d, 0x74, 0x0d, 0x5b, 0x0a, 0x37, 0xa7, 0xed, + 0x44, 0x51, 0x9a, 0x07, 0x26, 0xfb, 0x6f, 0x17, 0xe4, 0x47, 0xf7, 0x56, + 0x22, 0x92, 0xad, 0x16, 0x9a, 0x0d, 0xdb, 0x46, 0x1a, 0x29, 0xbc, 0x2d, + 0x2d, 0x91, 0x86, 0xf4, 0x6c, 0xe3, 0x25, 0x9b, 0xe3, 0x0f, 0x60, 0xfc, + 0xb7, 0x49, 0xc8, 0x76, 0xdd, 0x49, 0x8c, 0xbf, 0xa3, 0xf2, 0xa6, 0xfb, + 0x58, 0xc8, 0x1b, 0xdb, 0x48, 0x1f, 0x08, 0x32, 0x0d, 0xa4, 0x33, 0x23, + 0x9d, 0x15, 0x95, 0x6f, 0xf0, 0xf2, 0x83, 0x3a, 0x1f, 0x89, 0x7a, 0xb4, + 0x4b, 0x13, 0x68, 0x8f, 0x84, 0xd2, 0xe9, 0x26, 0xf4, 0x11, 0x09, 0xa7, + 0x97, 0x7e, 0x7b, 0x51, 0xd5, 0x3b, 0xac, 0xeb, 0x3d, 0x10, 0xf6, 0xda, + 0x4d, 0x8e, 0x74, 0x57, 0x98, 0xce, 0x8e, 0x74, 0xa9, 0xf4, 0x4b, 0x23, + 0x49, 0x95, 0xce, 0xa9, 0x7a, 0x81, 0xf4, 0xc2, 0x88, 0xad, 0xd2, 0xb4, + 0x2e, 0x1f, 0x1e, 0x49, 0xa8, 0x74, 0xa7, 0x4e, 0x47, 0x75, 0x3a, 0xa6, + 0xd3, 0x5d, 0x3a, 0xdd, 0xad, 0xd3, 0x71, 0x9d, 0xee, 0xd5, 0xfd, 0x3c, + 0xa0, 0xf3, 0x9f, 0xd0, 0xe9, 0x7e, 0x9d, 0x3e, 0xac, 0xd3, 0x03, 0x3a, + 0x7d, 0x44, 0xd3, 0x55, 0xd0, 0xe9, 0x94, 0x2e, 0x9f, 0xd1, 0x74, 0x3e, + 0x01, 0x7a, 0xfe, 0x71, 0xa3, 0x96, 0x5b, 0xcc, 0x37, 0x21, 0x7b, 0xa6, + 0x22, 0x52, 0x2c, 0x05, 0x25, 0xa7, 0xd6, 0xf3, 0xe3, 0x61, 0x89, 0x46, + 0x64, 0xa2, 0x1a, 0x91, 0x2b, 0x4a, 0x5c, 0x7f, 0xe4, 0x7e, 0xbd, 0xc7, + 0x94, 0xa7, 0xab, 0x31, 0xb9, 0x50, 0x95, 0xc0, 0x68, 0x4f, 0x93, 0x18, + 0x47, 0x6f, 0x96, 0x8c, 0x19, 0x90, 0xa0, 0xe2, 0x6b, 0x42, 0xb2, 0x53, + 0xed, 0xc8, 0x5b, 0x71, 0x91, 0xc5, 0xb0, 0xb7, 0x8e, 0x11, 0x09, 0x9e, + 0xe0, 0xba, 0x3c, 0x37, 0x72, 0x69, 0x36, 0x2e, 0xa1, 0xe9, 0x04, 0xfa, + 0x6f, 0x96, 0xf0, 0x09, 0xe9, 0x08, 0x4a, 0x57, 0xfc, 0x63, 0xa8, 0x31, + 0x58, 0x09, 0xc9, 0x50, 0x25, 0x80, 0xb5, 0x8a, 0x40, 0x4e, 0x9a, 0xf1, + 0x33, 0xf1, 0x8b, 0xe1, 0x17, 0xc7, 0xef, 0xaf, 0xd0, 0x4f, 0x87, 0xe4, + 0x2a, 0xec, 0x13, 0xe3, 0x96, 0x30, 0x7e, 0xc9, 0x32, 0xc7, 0x85, 0x34, + 0xc5, 0xe5, 0xeb, 0x3d, 0x1e, 0x4d, 0x17, 0xaa, 0x91, 0x40, 0xf6, 0xa4, + 0xec, 0xcf, 0x39, 0x92, 0x30, 0xec, 0xa8, 0xe4, 0xcd, 0x40, 0x62, 0x6f, + 0xaa, 0x4d, 0x0a, 0x63, 0x78, 0x57, 0x92, 0x8c, 0x81, 0xbe, 0xf3, 0xa6, + 0x8c, 0x7b, 0xef, 0x58, 0xf6, 0x7f, 0xa1, 0xaf, 0x96, 0x49, 0xc1, 0xbd, + 0x50, 0xfa, 0xd7, 0x78, 0x66, 0x5f, 0x2f, 0x86, 0x3c, 0x9a, 0xdf, 0x40, + 0x9e, 0xe5, 0xee, 0x26, 0x2f, 0xcf, 0x67, 0xd6, 0xf5, 0xc7, 0xf4, 0xe7, + 0xca, 0xb1, 0x7b, 0x30, 0x5f, 0x8e, 0xbf, 0x32, 0x5f, 0xd0, 0xd1, 0x1c, + 0xc8, 0x9d, 0x4c, 0xc8, 0xa1, 0xd2, 0x1d, 0x92, 0x75, 0x5c, 0x77, 0x8f, + 0x23, 0x31, 0x43, 0xba, 0xcc, 0x1c, 0xde, 0x96, 0x2b, 0x12, 0xc8, 0x96, + 0x7c, 0x7e, 0xb0, 0xdf, 0x10, 0xca, 0xda, 0x51, 0xbf, 0x25, 0x30, 0x78, + 0x12, 0xb4, 0xa7, 0xc9, 0x17, 0xc8, 0xac, 0xd3, 0x15, 0xdf, 0x8b, 0xf1, + 0xe6, 0x2b, 0x5d, 0xce, 0xb2, 0x98, 0xe8, 0xb3, 0x0d, 0x75, 0xc8, 0x23, + 0xf6, 0xc5, 0x3e, 0xd9, 0x5f, 0x33, 0xda, 0xc6, 0xf0, 0x8e, 0x34, 0xb9, + 0x6e, 0xd6, 0x31, 0x99, 0x97, 0x39, 0xf0, 0x6d, 0x8e, 0x7c, 0x8b, 0x76, + 0xc8, 0xa9, 0x0a, 0xc7, 0x58, 0x8f, 0xee, 0x5b, 0xff, 0x9e, 0xd1, 0x1d, + 0x47, 0xff, 0x31, 0xa4, 0x1b, 0x02, 0xd9, 0x63, 0x2e, 0xc6, 0x8f, 0xe3, + 0x79, 0xbd, 0x39, 0x5c, 0xd1, 0x32, 0x18, 0x07, 0xed, 0x31, 0x39, 0xa7, + 0xe4, 0x70, 0x83, 0x04, 0x21, 0x87, 0x5c, 0xe3, 0xd6, 0x13, 0xef, 0x91, + 0x7c, 0xcc, 0x4a, 0xd0, 0x76, 0x76, 0x6e, 0x6d, 0xc2, 0x1c, 0xb5, 0x15, + 0x9c, 0x8e, 0x41, 0x0e, 0x97, 0x5b, 0x0d, 0x94, 0x18, 0x62, 0x99, 0xff, + 0x48, 0x0a, 0x92, 0x5b, 0xf8, 0xbd, 0x80, 0x44, 0x0d, 0xd4, 0xbb, 0x25, + 0xe0, 0xf1, 0x80, 0xfc, 0xc9, 0x80, 0x3f, 0x01, 0xd1, 0xf6, 0x41, 0x3a, + 0x2b, 0x7c, 0xdf, 0x9b, 0x30, 0xd4, 0xbb, 0x41, 0xbc, 0x0b, 0x49, 0x72, + 0xab, 0xff, 0x7e, 0x10, 0xef, 0x6f, 0x96, 0x71, 0x13, 0xb4, 0x94, 0x9e, + 0x37, 0xb2, 0xa0, 0xf1, 0xce, 0x90, 0x9a, 0x2b, 0xea, 0x8e, 0xd7, 0xf5, + 0x33, 0x8e, 0x7a, 0xff, 0x0a, 0x63, 0x81, 0xde, 0x52, 0x02, 0xb4, 0xb4, + 0x83, 0x16, 0xd2, 0x58, 0x30, 0xb2, 0xd5, 0x10, 0xf2, 0x93, 0x46, 0xee, + 0xf4, 0x61, 0x3c, 0x8b, 0x69, 0xa4, 0x9f, 0x67, 0x8a, 0xf6, 0xbb, 0xeb, + 0xda, 0xef, 0x46, 0x7b, 0x8e, 0xc1, 0xf6, 0x9e, 0xfc, 0x17, 0x94, 0x2c, + 0x26, 0xae, 0xc3, 0x8f, 0xe0, 0xaf, 0xc1, 0x8f, 0x7f, 0xa3, 0xf9, 0xf1, + 0xd7, 0xf2, 0x9b, 0xe7, 0xc7, 0x7f, 0xfa, 0x0d, 0xf1, 0x43, 0x24, 0x7f, + 0x8c, 0xcf, 0x21, 0x29, 0x28, 0xbb, 0x45, 0xbd, 0xa5, 0xbc, 0xd3, 0x66, + 0x91, 0x4f, 0x94, 0x63, 0xe8, 0x40, 0x35, 0x84, 0xf4, 0x49, 0xa4, 0x1b, + 0x02, 0xa3, 0xc7, 0xae, 0x62, 0xfd, 0x5d, 0x31, 0xb7, 0xfa, 0x7e, 0xa3, + 0x10, 0x37, 0xa5, 0x43, 0xcc, 0x77, 0xc3, 0x69, 0xb7, 0x5b, 0x66, 0x5e, + 0x7e, 0x80, 0xf7, 0x6f, 0x06, 0x7c, 0xff, 0x9e, 0x9d, 0x6a, 0x7a, 0x23, + 0xa3, 0x9e, 0xc2, 0xe4, 0x67, 0xc6, 0x48, 0x87, 0x02, 0xb9, 0x52, 0x62, + 0xdc, 0x48, 0xc7, 0x60, 0xa7, 0x98, 0x1f, 0x08, 0x78, 0x34, 0xf7, 0xa3, + 0xae, 0x6f, 0xb3, 0x7c, 0xda, 0xfb, 0x41, 0xfb, 0x5a, 0xdb, 0x95, 0x01, + 0x2d, 0xa4, 0x81, 0x74, 0x15, 0x82, 0x9a, 0xf7, 0xe8, 0xe7, 0x80, 0xea, + 0x27, 0x98, 0x1e, 0x10, 0xfa, 0xd0, 0xfc, 0x14, 0xf5, 0x80, 0xed, 0xd8, + 0x97, 0x67, 0x93, 0xf3, 0x15, 0xbf, 0x8f, 0x42, 0x7d, 0x1f, 0xa0, 0x47, + 0x36, 0x19, 0x76, 0x18, 0x6b, 0xcf, 0xae, 0x0e, 0xe3, 0xdd, 0x97, 0x24, + 0x7b, 0xfa, 0x76, 0x03, 0x73, 0x40, 0xbf, 0xe4, 0xd1, 0x28, 0x6c, 0x36, + 0xf5, 0x2c, 0x22, 0xb9, 0x18, 0xcb, 0x3e, 0xa2, 0xc7, 0x0d, 0x49, 0x46, + 0xe5, 0xbf, 0xd2, 0x52, 0xa3, 0xe3, 0x79, 0x3d, 0x9f, 0x34, 0xe6, 0x43, + 0x1a, 0xfc, 0xb9, 0xa4, 0xeb, 0xe6, 0xe2, 0xf3, 0x9a, 0xbc, 0x30, 0x61, + 0xe3, 0x23, 0xda, 0x87, 0xb0, 0xdd, 0x64, 0xdd, 0xda, 0x4d, 0xa2, 0x0d, + 0x79, 0x8f, 0x3a, 0x6b, 0xfc, 0x0a, 0x7d, 0xca, 0x20, 0xfa, 0x29, 0xce, + 0x1a, 0x92, 0x73, 0xe0, 0xab, 0x9d, 0xb7, 0x69, 0x79, 0xad, 0xc9, 0x52, + 0x78, 0x5d, 0x59, 0x3a, 0x68, 0x78, 0xf6, 0x1a, 0xbe, 0x05, 0xfe, 0x67, + 0x62, 0xd6, 0x4a, 0xf9, 0xb2, 0x54, 0x9c, 0x7a, 0x2b, 0xb2, 0xe4, 0xb7, + 0x8f, 0x40, 0x76, 0xfd, 0x31, 0xd6, 0xd2, 0xec, 0xd7, 0x01, 0x8d, 0xa5, + 0xac, 0xc6, 0x28, 0x1c, 0xc7, 0xf3, 0x0d, 0x73, 0xab, 0x7c, 0xc3, 0x61, + 0xb4, 0x95, 0x40, 0xae, 0xa7, 0x59, 0xf6, 0xcd, 0xfa, 0x7d, 0x1c, 0x56, + 0x32, 0xbb, 0x77, 0xca, 0x32, 0x87, 0x82, 0x92, 0x19, 0x9a, 0x19, 0x90, + 0xc1, 0x6a, 0x07, 0xd6, 0xf4, 0x0d, 0x17, 0xbe, 0xf3, 0xdd, 0x61, 0xb1, + 0x61, 0x17, 0x31, 0xe7, 0x7e, 0xf0, 0xb8, 0x1a, 0x16, 0x23, 0xed, 0x20, + 0xad, 0xc7, 0x58, 0xa1, 0xd0, 0xd0, 0xaa, 0x7c, 0x03, 0xea, 0xa0, 0xef, + 0xfe, 0xb5, 0xf5, 0x20, 0x9f, 0xe0, 0x6d, 0xd6, 0x79, 0xd3, 0x85, 0x1f, + 0xd6, 0x3e, 0x8b, 0xa5, 0xb4, 0x13, 0xbe, 0x8d, 0xf8, 0x10, 0xf4, 0x5b, + 0xe9, 0x42, 0xc1, 0x48, 0xef, 0x47, 0x1f, 0xa2, 0xe4, 0xb4, 0x58, 0x7d, + 0xda, 0xd7, 0x7b, 0x55, 0xbe, 0xa3, 0x9f, 0xb2, 0x37, 0x07, 0x4c, 0xc0, + 0x39, 0x2d, 0x28, 0x5d, 0xcf, 0x99, 0x31, 0x99, 0x2c, 0x29, 0x4c, 0x23, + 0xc9, 0xca, 0x1f, 0x49, 0xee, 0xb4, 0xc8, 0x37, 0xa7, 0x58, 0xef, 0x05, + 0x5d, 0xef, 0x79, 0xd4, 0x4b, 0x26, 0x06, 0x03, 0x16, 0xfc, 0x80, 0x05, + 0x35, 0xe9, 0x4d, 0x20, 0x35, 0x87, 0xf1, 0x1b, 0xa4, 0x93, 0x41, 0x3d, + 0x0f, 0x03, 0x3d, 0x0f, 0x7e, 0x88, 0xdc, 0x53, 0x6a, 0x84, 0x3d, 0xf9, + 0x2f, 0xa0, 0x35, 0x26, 0x5f, 0xc0, 0x3c, 0x2e, 0x4d, 0x11, 0x67, 0xbd, + 0x20, 0x8b, 0x53, 0xc4, 0x5d, 0xcf, 0xcb, 0xe4, 0x54, 0xd2, 0xf9, 0x26, + 0xf8, 0x7c, 0x4a, 0x38, 0x97, 0x5e, 0x07, 0x29, 0x30, 0xa0, 0x95, 0x78, + 0x1c, 0xf6, 0xac, 0x67, 0xab, 0xd7, 0x5f, 0x97, 0xee, 0xcf, 0xae, 0x58, + 0x72, 0xc5, 0xa4, 0x7d, 0xba, 0x56, 0xc7, 0xb3, 0x5a, 0xc7, 0x47, 0x9d, + 0x0e, 0x31, 0xa0, 0xd7, 0x99, 0xb1, 0x02, 0xbc, 0x1f, 0xf5, 0xfa, 0x7f, + 0x1b, 0x35, 0xfc, 0x33, 0x00, 0xac, 0x6a, 0x29, 0x7f, 0xf7, 0xb7, 0xd3, + 0xf1, 0x7a, 0xdd, 0xe6, 0xf8, 0x2d, 0x68, 0x13, 0x42, 0x7a, 0x7d, 0xbd, + 0x46, 0x1f, 0x75, 0x6d, 0x07, 0xa8, 0x17, 0x68, 0xf3, 0x07, 0xe0, 0x05, + 0xf9, 0xff, 0x56, 0xf4, 0xb9, 0x37, 0xf8, 0x96, 0xf4, 0x79, 0xec, 0x7a, + 0xfa, 0x5c, 0xaf, 0xcb, 0x67, 0xc9, 0x0b, 0x8c, 0x2d, 0x33, 0x9e, 0x6c, + 0x75, 0x81, 0xd7, 0x09, 0xc8, 0x29, 0x68, 0x28, 0xfd, 0x8d, 0x9b, 0x09, + 0x79, 0x78, 0xce, 0x93, 0x27, 0xd6, 0xf3, 0xeb, 0x78, 0xb6, 0x77, 0xb0, + 0x7a, 0x45, 0xd9, 0xd9, 0x73, 0xca, 0xce, 0x5a, 0x87, 0x0b, 0x42, 0x79, + 0xbb, 0x2d, 0x48, 0xbe, 0x3f, 0xed, 0x7c, 0x16, 0x34, 0x5a, 0x89, 0x84, + 0xd1, 0x55, 0x30, 0x8c, 0xcf, 0xca, 0xfe, 0xf9, 0x87, 0x65, 0x7f, 0x89, + 0x7d, 0xa4, 0xf1, 0xde, 0x46, 0x59, 0x13, 0x6c, 0x2d, 0x6d, 0xfa, 0x1b, + 0x01, 0x6f, 0x2c, 0x03, 0xfe, 0x6b, 0x29, 0x70, 0x4f, 0xf5, 0x62, 0x20, + 0x3b, 0x4f, 0xdd, 0x45, 0x79, 0xb5, 0xde, 0xe6, 0xfb, 0xf6, 0xbe, 0x66, + 0xff, 0x06, 0x4b, 0x93, 0xc4, 0x80, 0x46, 0xd6, 0xe1, 0x9a, 0x51, 0x37, + 0x2f, 0x98, 0xde, 0x9c, 0x3f, 0x09, 0x3e, 0x51, 0xaf, 0xc9, 0x37, 0xf8, + 0xc0, 0x10, 0x75, 0x96, 0xcf, 0xe2, 0x06, 0xd3, 0xd4, 0x3b, 0x09, 0x05, + 0x41, 0x46, 0x2e, 0xc6, 0x3a, 0x77, 0x80, 0xce, 0xb5, 0x3a, 0xcd, 0x75, + 0x14, 0x6d, 0x43, 0x58, 0x36, 0x80, 0xe7, 0x4e, 0x19, 0x9f, 0xcf, 0x60, + 0xcc, 0x3b, 0x75, 0xdf, 0xab, 0x7c, 0x0c, 0xfa, 0x48, 0xe8, 0xf5, 0xd8, + 0xe0, 0xdb, 0x41, 0x94, 0x39, 0xba, 0xac, 0xa1, 0xae, 0xcc, 0x5f, 0xb7, + 0x8f, 0x62, 0x7c, 0xfa, 0x8a, 0x61, 0x8d, 0x7f, 0x5c, 0x37, 0xc7, 0xf5, + 0xee, 0xfb, 0x87, 0x42, 0xdd, 0xb8, 0x50, 0x2a, 0x98, 0x41, 0x25, 0xa3, + 0x2f, 0xfc, 0x4e, 0x4d, 0x46, 0x81, 0x97, 0x55, 0x2f, 0xe4, 0x31, 0x69, + 0x69, 0x06, 0x4f, 0x07, 0x41, 0x2b, 0x78, 0xd7, 0x1e, 0x00, 0xff, 0x9a, + 0x25, 0x5f, 0x4d, 0xeb, 0x77, 0x2c, 0x0f, 0xc9, 0x68, 0xcc, 0xf7, 0x47, + 0xb7, 0x99, 0x1e, 0xe6, 0x45, 0x9d, 0xd2, 0x8f, 0x83, 0x9e, 0x0e, 0x98, + 0x92, 0x3f, 0x39, 0x08, 0x59, 0x23, 0x26, 0x6b, 0x80, 0xac, 0xc5, 0x94, + 0xad, 0x37, 0x6c, 0xd6, 0xc7, 0xbb, 0xd3, 0xbf, 0x17, 0xf4, 0xda, 0xb0, + 0x9e, 0xdf, 0xc6, 0x1f, 0xbb, 0x6d, 0xa5, 0xed, 0xa8, 0x63, 0x48, 0x50, + 0x8d, 0x8f, 0xb2, 0xd3, 0xab, 0xc7, 0x37, 0xda, 0xfd, 0xf1, 0x1f, 0xd1, + 0x7d, 0xb5, 0xd5, 0xf5, 0x15, 0xbb, 0xce, 0xf8, 0x78, 0x77, 0xfa, 0xa3, + 0x9b, 0xbd, 0x36, 0xb1, 0xba, 0x36, 0xed, 0x6b, 0xda, 0xb0, 0xbe, 0x3f, + 0x06, 0xde, 0x9d, 0xbe, 0xab, 0xd9, 0x6b, 0xc3, 0x7a, 0x0d, 0xf0, 0x6d, + 0x7c, 0x47, 0xd9, 0xdf, 0x5f, 0x27, 0xfb, 0xfb, 0x21, 0xfb, 0xbe, 0x4c, + 0xad, 0xc5, 0xc9, 0x7e, 0xbc, 0xc3, 0x38, 0x87, 0xd8, 0xaa, 0x16, 0xd7, + 0x84, 0x4e, 0x34, 0x03, 0xb7, 0xb4, 0x30, 0x96, 0xd1, 0xb8, 0x98, 0xb1, + 0x0d, 0x71, 0xb0, 0xd8, 0x21, 0xe9, 0x82, 0x8d, 0xea, 0x8a, 0xef, 0xa3, + 0xc2, 0x55, 0x62, 0x0a, 0x2f, 0x67, 0xf4, 0x18, 0x8c, 0x6b, 0xc8, 0x77, + 0xe6, 0x73, 0x2b, 0x71, 0x4e, 0x07, 0xe2, 0x20, 0xe2, 0x5d, 0xe2, 0x25, + 0x9f, 0x7e, 0x9f, 0x9e, 0x03, 0x46, 0x4d, 0x27, 0x32, 0xc6, 0x60, 0x75, + 0xd0, 0xf0, 0x74, 0x82, 0xef, 0x0f, 0x68, 0x9f, 0xb6, 0x96, 0xde, 0xb7, + 0xaf, 0xa1, 0x97, 0xb8, 0x2a, 0x21, 0x13, 0x90, 0x91, 0xd0, 0x09, 0xda, + 0xd8, 0xe7, 0x46, 0x16, 0x67, 0x89, 0x1f, 0xfa, 0xc0, 0x17, 0xd2, 0x4b, + 0xfe, 0x51, 0x97, 0x5b, 0x60, 0x1f, 0xba, 0x52, 0x65, 0xd4, 0x67, 0x7c, + 0x3d, 0xae, 0xe2, 0xb2, 0x66, 0xa4, 0x08, 0x9e, 0x40, 0xeb, 0x38, 0x68, + 0x1d, 0xd7, 0x31, 0xd9, 0x3e, 0xd8, 0xef, 0xd0, 0xb4, 0x4f, 0xeb, 0x8d, + 0x21, 0x7f, 0x6d, 0x56, 0xd3, 0x5e, 0xef, 0x77, 0x3c, 0xfc, 0x75, 0x4f, + 0x0f, 0x65, 0xc6, 0x2a, 0x10, 0xb3, 0x8d, 0x2b, 0xf9, 0x00, 0xf6, 0x33, + 0xc4, 0xd3, 0xa5, 0x16, 0xdf, 0xff, 0x72, 0x3e, 0xf4, 0xff, 0xd4, 0x79, + 0x7f, 0x0e, 0xcd, 0xd2, 0x79, 0x82, 0x73, 0x58, 0xa1, 0x3f, 0xc6, 0xdd, + 0x8d, 0xfd, 0xb0, 0x9b, 0x79, 0x45, 0xeb, 0x4e, 0xd9, 0x5b, 0x7a, 0xa7, + 0xa6, 0xbf, 0x19, 0xf4, 0x8f, 0x42, 0xb6, 0x6b, 0x36, 0x23, 0x5f, 0x19, + 0x43, 0xde, 0xc3, 0x62, 0xe4, 0x71, 0xbe, 0x42, 0xfb, 0xa1, 0xe7, 0x13, + 0xe5, 0x7c, 0xd6, 0xda, 0x96, 0xf5, 0xf8, 0xfa, 0x8e, 0x35, 0x7c, 0x15, + 0xcd, 0xd7, 0x88, 0x34, 0x9c, 0x50, 0x71, 0x2d, 0xfa, 0x25, 0xaf, 0xe9, + 0xbf, 0x9e, 0x1b, 0x99, 0x9c, 0x95, 0xbe, 0xb0, 0x90, 0xbe, 0x38, 0xcb, + 0xfa, 0x1b, 0xa4, 0xcb, 0xb9, 0x88, 0x79, 0xe7, 0xb1, 0xde, 0xc6, 0xb4, + 0x27, 0xdf, 0xe4, 0x6f, 0xbe, 0x12, 0x45, 0x2c, 0xcd, 0xb1, 0xc9, 0x33, + 0xd2, 0x6f, 0x2a, 0x7a, 0x56, 0xf8, 0x0d, 0xfa, 0x3e, 0x56, 0x59, 0xcb, + 0xdb, 0x7a, 0x3b, 0xe3, 0xc7, 0xec, 0xdf, 0x35, 0x3d, 0xbd, 0x58, 0x2f, + 0x66, 0x6f, 0x86, 0x7d, 0x0c, 0xd1, 0x36, 0x82, 0xf7, 0xdc, 0x5f, 0x59, + 0x0a, 0x11, 0x83, 0x5f, 0x28, 0x85, 0x95, 0xcd, 0xcb, 0x3a, 0x2d, 0x5a, + 0x3f, 0x6e, 0xd3, 0xbe, 0x23, 0xac, 0x6c, 0xb6, 0x18, 0x26, 0x71, 0x09, + 0xca, 0x90, 0x9f, 0x67, 0xde, 0xa7, 0xe3, 0xde, 0x5d, 0x61, 0xfb, 0x0f, + 0x43, 0xbe, 0x4d, 0xa8, 0xd1, 0x55, 0x1f, 0x93, 0xbb, 0xc0, 0x72, 0xef, + 0x84, 0xdc, 0xde, 0x89, 0xb8, 0x3b, 0x21, 0xf9, 0x14, 0xf5, 0x68, 0x40, + 0xc5, 0x26, 0x86, 0xbd, 0x0f, 0x65, 0x4d, 0x28, 0x83, 0x13, 0x33, 0x31, + 0x7f, 0xfb, 0x77, 0x65, 0x1c, 0x32, 0x9e, 0x4f, 0xf5, 0x82, 0x0e, 0xda, + 0x60, 0x60, 0x1c, 0x3b, 0xc5, 0xb8, 0x1d, 0x7f, 0xfd, 0x61, 0x6f, 0x5e, + 0xbb, 0x90, 0x47, 0x0c, 0x9f, 0xea, 0xd4, 0x75, 0x36, 0x08, 0xf7, 0x7f, + 0xf2, 0x66, 0x0b, 0xd2, 0xee, 0x35, 0x75, 0xdf, 0x8f, 0xfc, 0x7b, 0x75, + 0xff, 0x05, 0xbc, 0xdf, 0x86, 0xdf, 0x20, 0xca, 0x6e, 0x47, 0x99, 0x83, + 0xb2, 0xf7, 0x20, 0xff, 0x7e, 0xbd, 0x1f, 0xe0, 0xb7, 0x69, 0x41, 0xfe, + 0x31, 0xbc, 0x87, 0xad, 0x30, 0x5f, 0xc6, 0xfb, 0xf7, 0xe2, 0xf7, 0xee, + 0x35, 0x75, 0xda, 0xd6, 0xe4, 0x3f, 0xb5, 0xc2, 0x83, 0x0b, 0xa5, 0x9f, + 0x69, 0xbb, 0x46, 0x79, 0x66, 0xfe, 0x94, 0x7e, 0xf7, 0xce, 0xd0, 0xea, + 0xf2, 0x1d, 0x7e, 0xbe, 0x6e, 0x0d, 0x3b, 0xb1, 0x86, 0x3e, 0xc6, 0x7c, + 0xbb, 0xf6, 0x5d, 0x6f, 0xf7, 0xe2, 0xf4, 0x92, 0xdf, 0x8e, 0x7e, 0xed, + 0xce, 0x35, 0x63, 0x3c, 0xdf, 0x50, 0xcb, 0x37, 0x07, 0x86, 0x4e, 0xb2, + 0xec, 0x72, 0xc3, 0xea, 0x3a, 0x6f, 0xd6, 0xe5, 0x37, 0x06, 0x86, 0x94, + 0x8f, 0xbb, 0xab, 0x71, 0x75, 0x9d, 0x64, 0x63, 0x6d, 0x1e, 0x35, 0x5b, + 0x18, 0x4a, 0x2f, 0x53, 0x8e, 0xa1, 0x0b, 0xdf, 0x1a, 0xc9, 0x4e, 0xb9, + 0xee, 0x84, 0xb3, 0x14, 0x0f, 0x0a, 0x7d, 0x10, 0xb1, 0x2a, 0xcb, 0x5f, + 0x46, 0x39, 0xb0, 0x4c, 0x75, 0x54, 0x68, 0x93, 0xd6, 0xc7, 0xa4, 0x09, + 0x8d, 0x49, 0x55, 0x36, 0x94, 0x55, 0x18, 0xf2, 0xf9, 0x11, 0x60, 0x1e, + 0xfd, 0xfc, 0x02, 0x9e, 0x13, 0xf5, 0xb8, 0x17, 0xfd, 0x2e, 0x8d, 0x64, + 0x67, 0xe9, 0xf3, 0x2e, 0x8e, 0xec, 0x99, 0xa5, 0xce, 0x5f, 0x82, 0xce, + 0x07, 0x64, 0x52, 0xf9, 0x3f, 0xd2, 0xc1, 0x76, 0x4b, 0x23, 0x9d, 0x0b, + 0x4c, 0x97, 0x47, 0xec, 0x85, 0xa0, 0xec, 0x8b, 0x79, 0x6d, 0x99, 0x4f, + 0x2c, 0xf8, 0x3a, 0x10, 0x95, 0x70, 0x9a, 0x32, 0x69, 0xa5, 0x80, 0xbd, + 0x31, 0x9f, 0x27, 0x47, 0x26, 0x6d, 0xca, 0xe7, 0x87, 0x1a, 0xa4, 0x25, + 0x2a, 0x0d, 0xca, 0xde, 0x3c, 0xa5, 0xc7, 0xba, 0x84, 0xb1, 0x36, 0x29, + 0x7d, 0xca, 0xda, 0xa1, 0x38, 0xc6, 0x39, 0x68, 0xd8, 0xbd, 0x18, 0x8f, + 0x91, 0x72, 0x87, 0x4c, 0x54, 0xa9, 0x37, 0xdb, 0xc2, 0xb5, 0xf8, 0xf8, + 0x3c, 0xda, 0xf9, 0x71, 0x19, 0xc7, 0x2b, 0x03, 0x97, 0x41, 0x96, 0xd3, + 0x96, 0x99, 0x0d, 0xc2, 0xcf, 0xcf, 0xfa, 0x75, 0x48, 0xd3, 0xd9, 0x91, + 0xe4, 0x42, 0x12, 0x7d, 0x75, 0xd0, 0x86, 0xc1, 0x76, 0x05, 0xf1, 0x63, + 0xdf, 0x6c, 0x07, 0x5f, 0x34, 0x40, 0x3f, 0x72, 0x1e, 0x7e, 0xa4, 0x43, + 0x0e, 0x95, 0x54, 0x1f, 0x09, 0xf6, 0x51, 0xd4, 0x6d, 0x3b, 0x17, 0x1a, + 0x10, 0xdb, 0x24, 0xcd, 0x17, 0xa5, 0xd6, 0x76, 0x48, 0xbc, 0x76, 0x5e, + 0xdf, 0x3f, 0x77, 0x33, 0xb1, 0x7a, 0xdd, 0x8f, 0x4a, 0x10, 0x74, 0xe4, + 0xd0, 0x07, 0xc7, 0xaf, 0xf5, 0xed, 0xf7, 0x97, 0x34, 0x97, 0xaf, 0xe9, + 0x6b, 0x93, 0x8e, 0xb9, 0xac, 0x44, 0xee, 0xd7, 0x1a, 0x5b, 0xc5, 0x00, + 0x90, 0x07, 0x09, 0xe5, 0x7a, 0x60, 0x17, 0xab, 0x03, 0x5a, 0x46, 0x5e, + 0x40, 0x59, 0x7d, 0x6c, 0xe3, 0xc9, 0x57, 0x01, 0x98, 0xae, 0x08, 0x3d, + 0x0f, 0xa6, 0x33, 0xad, 0xde, 0x5e, 0xd3, 0xf5, 0xe2, 0x19, 0xc8, 0x0d, + 0xfa, 0x2c, 0xae, 0xb4, 0xe5, 0x9c, 0x5e, 0x18, 0xb9, 0x34, 0x15, 0xc7, + 0x9c, 0x3c, 0xbf, 0xe0, 0xf1, 0x9a, 0x3e, 0x27, 0x20, 0x8b, 0x76, 0x02, + 0x71, 0x33, 0x7d, 0x7c, 0x42, 0x5e, 0xb2, 0x7d, 0xff, 0x43, 0x5f, 0x84, + 0xfa, 0x55, 0xd2, 0x46, 0xda, 0xcf, 0x63, 0x6e, 0xae, 0xcc, 0x38, 0x9e, + 0x0c, 0xf6, 0xc0, 0x8f, 0x7c, 0x23, 0x64, 0x1d, 0x66, 0x7c, 0x75, 0x25, + 0x54, 0x3f, 0x1f, 0x1f, 0x2b, 0x3c, 0xaf, 0xf7, 0x7e, 0xcf, 0x6b, 0x79, + 0x59, 0x82, 0xbc, 0xf4, 0x26, 0x4c, 0xe9, 0x06, 0xed, 0xa8, 0xd3, 0xd7, + 0x85, 0x38, 0x87, 0x31, 0x74, 0x1c, 0xf4, 0x98, 0xb0, 0x1d, 0x9b, 0x34, + 0x66, 0xff, 0x77, 0x61, 0xfa, 0xb6, 0x56, 0xb5, 0xaf, 0x7c, 0x5e, 0xc9, + 0xb3, 0x27, 0xdf, 0x41, 0xfd, 0xde, 0x97, 0xa9, 0x20, 0x21, 0x8d, 0xd4, + 0xf6, 0x4f, 0x59, 0xff, 0x39, 0x5d, 0xff, 0x59, 0xd4, 0x0f, 0x60, 0x4e, + 0xae, 0xbb, 0x57, 0xd1, 0xfb, 0x1c, 0xf8, 0x1e, 0x94, 0xe2, 0x8a, 0xcc, + 0x3f, 0x07, 0x99, 0xa7, 0x7c, 0x9f, 0x87, 0xbe, 0x82, 0xf8, 0x7b, 0x29, + 0xf7, 0x65, 0x19, 0x3c, 0x9d, 0x6b, 0xe0, 0x5e, 0x67, 0xc2, 0x60, 0xec, + 0x49, 0x99, 0xec, 0x90, 0xc7, 0x4b, 0x49, 0x73, 0xa2, 0x6e, 0x2d, 0x77, + 0xac, 0x5a, 0x4b, 0xca, 0x80, 0xaa, 0x9f, 0x62, 0xfd, 0x72, 0x9d, 0x0c, + 0xcc, 0xcf, 0x5e, 0xaf, 0x1d, 0x65, 0x80, 0xed, 0xd6, 0xc3, 0xe9, 0xdc, + 0x1b, 0x74, 0xdd, 0x45, 0x87, 0xfb, 0xb8, 0x8d, 0x52, 0x50, 0x32, 0x16, + 0x90, 0xa2, 0x43, 0xbd, 0xca, 0x26, 0x42, 0x62, 0x01, 0x2b, 0x7d, 0x10, + 0x74, 0x66, 0x52, 0x61, 0xf1, 0xf6, 0x12, 0xc6, 0xb1, 0x06, 0x4b, 0xa6, + 0xeb, 0x5e, 0xb2, 0x45, 0xca, 0x88, 0x3d, 0x17, 0x91, 0x16, 0x2b, 0xd0, + 0xd9, 0x68, 0x08, 0x36, 0xc0, 0x97, 0xf1, 0x88, 0xcc, 0xa1, 0xce, 0x3c, + 0xde, 0x3d, 0x5e, 0xf1, 0x25, 0xc6, 0x75, 0x0d, 0xf0, 0x68, 0x8f, 0xfd, + 0xff, 0xdc, 0x7c, 0xac, 0xbe, 0xae, 0x8f, 0x89, 0x89, 0x65, 0x89, 0x4d, + 0x89, 0x29, 0xf9, 0x8e, 0x38, 0xf1, 0x20, 0x68, 0xa1, 0xce, 0xb6, 0x48, + 0x24, 0x6d, 0xc5, 0x87, 0xc5, 0xf7, 0xfd, 0x97, 0x21, 0x4b, 0x05, 0xb7, + 0xd1, 0xee, 0x90, 0x67, 0x20, 0x37, 0xe7, 0x57, 0x70, 0x4c, 0x02, 0x72, + 0x44, 0x3f, 0xea, 0xca, 0x39, 0xc7, 0x4e, 0x7c, 0x0e, 0xe9, 0xb7, 0x9d, + 0xdf, 0x22, 0xdf, 0x9e, 0x10, 0xe9, 0x43, 0x2c, 0x04, 0xbb, 0x3e, 0xe3, + 0x63, 0xfb, 0x16, 0xc6, 0x64, 0x5a, 0x96, 0xae, 0xa0, 0x4f, 0xcb, 0x34, + 0x00, 0x6a, 0xef, 0x42, 0x3d, 0x4f, 0x37, 0xfc, 0xb2, 0x83, 0xa8, 0x4b, + 0x1a, 0x18, 0x2f, 0x7f, 0x07, 0x3a, 0xeb, 0xba, 0xf7, 0x39, 0x8b, 0x75, + 0xb6, 0xe6, 0x39, 0xac, 0xbf, 0x92, 0xf3, 0xfe, 0x56, 0xe1, 0xfe, 0xaa, + 0xf4, 0xb5, 0xa9, 0x78, 0x8e, 0xcf, 0x90, 0xf7, 0x7e, 0x62, 0xa1, 0x84, + 0xc2, 0x9a, 0xc4, 0x0d, 0xe7, 0xc1, 0xfb, 0x4f, 0x2a, 0x4c, 0x43, 0xfc, + 0x06, 0xfa, 0x4b, 0xc4, 0x14, 0x1e, 0x96, 0xf6, 0x70, 0x1d, 0xb1, 0x45, + 0x0a, 0x6b, 0xe3, 0xe3, 0x0b, 0xb6, 0x65, 0x3d, 0xb6, 0xad, 0x5f, 0x3f, + 0xd6, 0xd9, 0x14, 0xc8, 0x1d, 0xa3, 0x3c, 0xd3, 0x3f, 0xb6, 0xca, 0xbe, + 0x54, 0x23, 0xf8, 0xde, 0xa6, 0xfd, 0xf8, 0xfb, 0x80, 0xd9, 0x80, 0xbd, + 0x4d, 0xcb, 0xa9, 0xd9, 0x9e, 0xf7, 0xa0, 0xec, 0x17, 0xe0, 0x3f, 0xcb, + 0xf6, 0x37, 0x78, 0x7e, 0xf2, 0x61, 0xe8, 0xf2, 0xdc, 0x26, 0x6f, 0xef, + 0x8a, 0xeb, 0xe0, 0xe3, 0x04, 0x1f, 0xf7, 0x99, 0x1a, 0xef, 0x73, 0x6d, + 0xbc, 0x7d, 0x2e, 0x43, 0xd5, 0x65, 0xac, 0x55, 0x1f, 0x5b, 0x52, 0x87, + 0x5d, 0xf7, 0x9c, 0xe3, 0xe3, 0xc8, 0xed, 0xf0, 0xa1, 0x21, 0xcd, 0xeb, + 0x66, 0xf0, 0x9a, 0x18, 0x25, 0x22, 0x89, 0x36, 0x62, 0x8a, 0x07, 0x1b, + 0x6a, 0x58, 0xe6, 0x6f, 0xdc, 0xa0, 0xcd, 0x78, 0x8f, 0x38, 0x86, 0xb4, + 0x6f, 0xd7, 0x78, 0x86, 0xd8, 0xe6, 0x31, 0x8c, 0x11, 0x94, 0x44, 0x3b, + 0xf3, 0x7f, 0xa9, 0xdb, 0xf0, 0xd9, 0x95, 0xee, 0xad, 0xf5, 0xf2, 0x3c, + 0x00, 0x3a, 0x39, 0x1f, 0x7f, 0xef, 0xb5, 0x43, 0xd9, 0x93, 0x9a, 0x5c, + 0xf8, 0x34, 0xf9, 0xe3, 0x92, 0xb6, 0xb8, 0xb4, 0x81, 0xb6, 0x7b, 0xe0, + 0x53, 0xb6, 0xb6, 0xb1, 0x4f, 0x7f, 0xec, 0x7a, 0x9a, 0xea, 0xf1, 0x55, + 0x02, 0x63, 0x34, 0xca, 0xd6, 0x76, 0xf2, 0xae, 0x43, 0xf9, 0x96, 0xda, + 0x7a, 0xd0, 0xf7, 0x73, 0xec, 0xb5, 0xe5, 0xef, 0xad, 0xa3, 0x6b, 0x2d, + 0xe6, 0xdb, 0x86, 0x77, 0xa4, 0xc9, 0x84, 0x5d, 0x72, 0x65, 0x87, 0xe3, + 0xe3, 0xbb, 0x7a, 0x3a, 0x88, 0xf1, 0x48, 0x33, 0x69, 0xf0, 0x31, 0x39, + 0x7f, 0x5c, 0x1b, 0xd2, 0x93, 0xd6, 0xe7, 0x44, 0xfb, 0xf5, 0xbc, 0x6e, + 0xd3, 0x75, 0x92, 0x68, 0xfb, 0xc7, 0x98, 0x03, 0x9f, 0x39, 0x0f, 0x1f, + 0x1b, 0x26, 0xbd, 0x7e, 0xa2, 0xeb, 0xc5, 0x00, 0xd4, 0x19, 0x9f, 0x4f, + 0x6d, 0x7a, 0x8d, 0xb6, 0xaf, 0x19, 0xd7, 0x72, 0x56, 0xdb, 0x91, 0xf7, + 0xd4, 0xcd, 0xaf, 0x4f, 0x0a, 0xf3, 0x94, 0x8b, 0x77, 0x21, 0xf5, 0x63, + 0xa3, 0x7e, 0xf8, 0x91, 0x0c, 0x62, 0x21, 0xc6, 0x48, 0xd7, 0xc4, 0x47, + 0x3c, 0x47, 0x1c, 0xcb, 0x23, 0x5e, 0x56, 0x7e, 0xc4, 0xf3, 0x91, 0xc8, + 0xc3, 0x9e, 0x54, 0xef, 0xa5, 0x8c, 0x8d, 0x8d, 0x57, 0x9c, 0xb1, 0xbd, + 0x95, 0xfe, 0x31, 0xc6, 0x11, 0x9e, 0xcc, 0xa1, 0x7e, 0x45, 0xc6, 0x0d, + 0xb4, 0xcb, 0xaa, 0x76, 0x6a, 0x1f, 0x68, 0x9d, 0x7e, 0x84, 0xfa, 0x38, + 0xee, 0x8d, 0x15, 0x19, 0xcb, 0xc1, 0x06, 0xcd, 0xcf, 0xc0, 0xc7, 0xd9, + 0x56, 0x86, 0x72, 0xb9, 0xc7, 0xb1, 0x86, 0x95, 0xec, 0xc5, 0xac, 0x51, + 0xae, 0x65, 0x79, 0xe6, 0x1d, 0xb0, 0xa1, 0xae, 0xdc, 0x0d, 0x5b, 0xf8, + 0x10, 0x64, 0x55, 0xce, 0xc0, 0x10, 0x9e, 0x81, 0xf1, 0x3a, 0x13, 0x13, + 0xe3, 0x78, 0x87, 0x84, 0x8f, 0xc4, 0x25, 0x74, 0x84, 0xb1, 0x58, 0xd2, + 0xbc, 0x5b, 0x04, 0x3e, 0xf1, 0xc5, 0xdb, 0x0d, 0xb1, 0x06, 0x32, 0x92, + 0x44, 0x3c, 0xd9, 0x6b, 0x96, 0x91, 0x16, 0x25, 0x99, 0x3a, 0x8d, 0xbe, + 0xc2, 0x67, 0x50, 0x17, 0xed, 0x9a, 0x16, 0x13, 0xf8, 0xb5, 0x4b, 0x74, + 0xd1, 0xd3, 0x95, 0xe8, 0xe2, 0xea, 0x3d, 0x94, 0xc1, 0x95, 0x3d, 0x14, + 0xbe, 0x7f, 0x43, 0xef, 0xfd, 0x3c, 0xab, 0xe3, 0x1a, 0xca, 0x08, 0x7d, + 0x9b, 0x8a, 0xcd, 0x60, 0xc7, 0x9f, 0x45, 0x2c, 0x6c, 0x4b, 0xae, 0x04, + 0xcc, 0x9e, 0x76, 0xe5, 0x29, 0xa7, 0xe0, 0x66, 0xfb, 0x5d, 0xb9, 0xec, + 0xd8, 0x85, 0xbc, 0x58, 0x6f, 0xd0, 0xde, 0xfd, 0x4f, 0xe7, 0xfd, 0xb2, + 0xab, 0xd5, 0xda, 0x95, 0x09, 0x14, 0xdc, 0x66, 0x3b, 0x2a, 0x37, 0xa5, + 0x0f, 0xca, 0x9e, 0x2d, 0x4b, 0x66, 0x50, 0x32, 0x37, 0x01, 0x17, 0xc6, + 0xf3, 0xca, 0x56, 0xbd, 0xa6, 0xe2, 0xeb, 0x07, 0xba, 0x0e, 0xca, 0xc6, + 0x2d, 0x96, 0x79, 0x35, 0x48, 0xcc, 0x76, 0x10, 0xb1, 0x80, 0x15, 0xcf, + 0x05, 0x6d, 0x73, 0xa7, 0x58, 0xc3, 0x9f, 0x16, 0x9e, 0xdb, 0xda, 0xd2, + 0x79, 0xc4, 0x8e, 0x7f, 0x22, 0xd0, 0xbd, 0xff, 0x13, 0x8c, 0xef, 0xce, + 0x30, 0xef, 0x4a, 0x64, 0x8b, 0x89, 0xe7, 0x98, 0x74, 0x1e, 0x4f, 0x48, + 0x12, 0x7c, 0xe9, 0x51, 0x3c, 0xe1, 0xf9, 0x51, 0x5c, 0xba, 0x8f, 0x10, + 0x43, 0x29, 0xde, 0xf4, 0x80, 0x37, 0x29, 0xf0, 0x06, 0x31, 0x55, 0xaf, + 0x79, 0x15, 0xe9, 0xb2, 0x24, 0x07, 0x7e, 0x00, 0xde, 0xf4, 0x80, 0x37, + 0xdd, 0x67, 0x12, 0x68, 0x8f, 0x3e, 0x16, 0x3b, 0x91, 0x46, 0xe5, 0x83, + 0x37, 0xb4, 0xe3, 0xd9, 0x96, 0xe4, 0x91, 0x08, 0xc6, 0x08, 0xc8, 0x8e, + 0xae, 0x82, 0x0c, 0x6d, 0x41, 0x6c, 0x16, 0x3b, 0x28, 0x17, 0xe1, 0x87, + 0x4a, 0x88, 0x11, 0x9e, 0x1a, 0xb0, 0x46, 0x97, 0x60, 0x4b, 0xab, 0xf7, + 0xb8, 0xf2, 0xf2, 0x96, 0xbf, 0x70, 0xe3, 0x37, 0x58, 0xbb, 0x24, 0xd0, + 0x2f, 0x93, 0x25, 0xe5, 0x1f, 0xe2, 0xd9, 0xa0, 0xc2, 0x65, 0x98, 0x63, + 0x01, 0x3e, 0x86, 0xe7, 0xd1, 0x36, 0x6c, 0xfd, 0xa7, 0xe5, 0xa1, 0xb9, + 0x09, 0xfc, 0x10, 0x6f, 0x4e, 0xb1, 0xee, 0x7e, 0xc4, 0x73, 0x0f, 0xcb, + 0xbe, 0x29, 0x60, 0xc7, 0x34, 0xe8, 0xee, 0xb7, 0x11, 0xcf, 0xcd, 0x37, + 0x4a, 0x0b, 0xca, 0xc0, 0xdb, 0xd1, 0xea, 0xda, 0x38, 0x6e, 0x09, 0xeb, + 0x30, 0x20, 0x7f, 0x56, 0xed, 0x97, 0xaf, 0x55, 0xfb, 0xe4, 0x4f, 0xe0, + 0x5b, 0xce, 0x57, 0x3b, 0xa0, 0x2b, 0x71, 0xac, 0x49, 0x1a, 0xeb, 0xe3, + 0xc8, 0x73, 0xd5, 0x94, 0x3c, 0x0b, 0x5e, 0x3d, 0x83, 0xdf, 0x50, 0x29, + 0x25, 0x3b, 0x4a, 0x7d, 0x7a, 0x8d, 0xb8, 0x3e, 0x36, 0xe8, 0xb1, 0x31, + 0x77, 0xeb, 0xc9, 0x02, 0xf4, 0x6f, 0xbe, 0x6a, 0xbf, 0x5e, 0x96, 0x8f, + 0x37, 0x72, 0x8f, 0xf7, 0xd4, 0x8a, 0x7f, 0x29, 0xb8, 0xa6, 0x6d, 0x1d, + 0x1e, 0xc7, 0x3a, 0x94, 0xa1, 0xa7, 0xa3, 0x8a, 0xf7, 0x35, 0xdf, 0x53, + 0xf6, 0x7c, 0x8f, 0x3f, 0xbf, 0x99, 0xbc, 0x7c, 0x5b, 0xb2, 0x47, 0x27, + 0x65, 0xcf, 0x31, 0x57, 0x3e, 0xec, 0xb8, 0x90, 0x63, 0xda, 0xe2, 0x7e, + 0xda, 0xf8, 0xc4, 0x78, 0xd0, 0x50, 0xb1, 0x94, 0x87, 0x5b, 0x7a, 0x37, + 0x43, 0x67, 0x53, 0x19, 0x63, 0x42, 0x92, 0x47, 0x27, 0xa4, 0xf3, 0x28, + 0x64, 0xc1, 0x61, 0x5f, 0x4b, 0xa6, 0x71, 0x8d, 0x3c, 0x70, 0x1c, 0x6b, + 0x20, 0x27, 0xb6, 0xf9, 0xba, 0xa4, 0x30, 0xfe, 0x01, 0xe9, 0x42, 0x1b, + 0x1b, 0x6d, 0xae, 0xaa, 0xb1, 0x9b, 0x31, 0x76, 0xa3, 0x1c, 0x8a, 0x59, + 0x90, 0x35, 0xfa, 0xf0, 0xff, 0x25, 0xd9, 0x32, 0xd3, 0x9f, 0x4a, 0xf6, + 0xd4, 0x47, 0x23, 0x12, 0xe5, 0x33, 0x4c, 0xc3, 0x09, 0x96, 0x77, 0x22, + 0x65, 0xb9, 0x8d, 0x38, 0xfa, 0xe7, 0x92, 0x3d, 0xcb, 0xb1, 0x5f, 0x47, + 0xf9, 0xcb, 0x92, 0x9d, 0xfe, 0x05, 0xf2, 0x17, 0x91, 0xbe, 0x81, 0x74, + 0x54, 0x3a, 0xa7, 0x25, 0x90, 0x3d, 0xfb, 0x2d, 0xe4, 0x43, 0x48, 0x0f, + 0xa1, 0xde, 0x76, 0xd0, 0xf7, 0xa7, 0xe8, 0x2f, 0x03, 0x9b, 0xf7, 0x3b, + 0x9a, 0x7e, 0x96, 0xb3, 0x8c, 0xef, 0x0e, 0xc1, 0xa6, 0xfd, 0x67, 0xd8, + 0x34, 0xfd, 0x3c, 0xcf, 0x3c, 0x6d, 0x1b, 0x9f, 0x27, 0xc0, 0x93, 0x03, + 0xc8, 0xbb, 0xf2, 0xb0, 0x43, 0x7f, 0xb3, 0x4d, 0xc6, 0xcc, 0x82, 0x1b, + 0x05, 0xae, 0x68, 0x86, 0x1e, 0x4c, 0x6c, 0x5d, 0x5f, 0x0f, 0x0e, 0x77, + 0x1f, 0x94, 0xa6, 0x2d, 0xfe, 0xfc, 0xfd, 0xf9, 0xda, 0xe6, 0x4f, 0x14, + 0x1f, 0xac, 0xc2, 0x27, 0x84, 0xf3, 0xb0, 0xe3, 0x5f, 0x30, 0xba, 0x77, + 0x3d, 0x04, 0x3d, 0x30, 0xce, 0x32, 0xef, 0xe9, 0x81, 0x71, 0x16, 0xb6, + 0xe1, 0x04, 0x62, 0xc4, 0x13, 0x1d, 0xd2, 0x38, 0x5d, 0xd3, 0x83, 0x86, + 0xe9, 0x5f, 0xad, 0x07, 0x8d, 0x67, 0x51, 0xef, 0x2c, 0x79, 0x86, 0x3e, + 0x4e, 0x91, 0x67, 0xed, 0x48, 0x3f, 0x8d, 0xb9, 0x92, 0xf6, 0x46, 0xd0, + 0xee, 0xe1, 0xa2, 0xdb, 0x21, 0xef, 0x0f, 0x6c, 0x39, 0xa0, 0xcb, 0xff, + 0xd2, 0x1d, 0x8e, 0x59, 0x73, 0x12, 0x20, 0x4f, 0x51, 0xb7, 0x4c, 0x1e, + 0xde, 0xdc, 0x24, 0xd1, 0xfd, 0xd2, 0x49, 0xfe, 0x95, 0x77, 0x22, 0x5f, + 0x70, 0xc3, 0x76, 0xb3, 0xe6, 0x27, 0x70, 0x52, 0x3f, 0xcb, 0x5f, 0x85, + 0xcc, 0x10, 0xaf, 0xbe, 0x26, 0x7b, 0xa6, 0x5c, 0x19, 0x73, 0x38, 0xff, + 0xef, 0x63, 0xfe, 0x99, 0x2d, 0x31, 0x59, 0x4a, 0xc4, 0xc0, 0x93, 0x79, + 0xd8, 0xf6, 0x8b, 0xe2, 0xf1, 0x81, 0xe7, 0x02, 0x3b, 0xc4, 0x8e, 0x0f, + 0x89, 0x9d, 0xfa, 0x01, 0xf8, 0x30, 0x04, 0xd9, 0xcf, 0x55, 0x29, 0x3b, + 0xaf, 0xc8, 0x20, 0x64, 0xe2, 0x7b, 0x8e, 0x95, 0x02, 0x16, 0x82, 0xbd, + 0xa0, 0x5c, 0x50, 0x26, 0x5a, 0x94, 0x4d, 0x3a, 0xe1, 0x58, 0x4f, 0x94, + 0xe5, 0x56, 0x39, 0xd1, 0x46, 0xda, 0xf1, 0x6e, 0x5a, 0xf9, 0x8b, 0xd4, + 0xb8, 0xd1, 0x05, 0x1b, 0x9d, 0x12, 0xb3, 0xbb, 0xd8, 0xe8, 0xdf, 0x21, + 0xc9, 0x1f, 0x0d, 0xc8, 0x44, 0x37, 0xd7, 0x8a, 0xfd, 0x22, 0x5f, 0x2e, + 0xb8, 0x21, 0xfb, 0x75, 0xf7, 0x64, 0x7b, 0x42, 0x3e, 0xd9, 0xbd, 0x22, + 0x97, 0x73, 0x22, 0x9e, 0x5e, 0x0c, 0xaa, 0xf5, 0xf0, 0xe9, 0xf6, 0xe7, + 0xe2, 0xbf, 0xeb, 0xab, 0x7b, 0xc7, 0xb9, 0x50, 0xd6, 0x57, 0x74, 0x27, + 0x71, 0x2d, 0xad, 0xaf, 0x41, 0x9e, 0xac, 0x27, 0x8a, 0x72, 0x19, 0xb2, + 0x07, 0x1e, 0x9e, 0x65, 0x4a, 0x1e, 0x4e, 0x40, 0xee, 0x5f, 0x95, 0x1d, + 0x47, 0xa9, 0x33, 0xaf, 0x62, 0xae, 0xca, 0x96, 0xc0, 0x46, 0xb0, 0x3f, + 0x57, 0x26, 0x9d, 0xae, 0xd4, 0x29, 0xb9, 0x35, 0xbe, 0x17, 0x31, 0xe7, + 0xb8, 0xe9, 0xca, 0xa2, 0x53, 0x90, 0xc5, 0x01, 0xb4, 0x29, 0x7f, 0x1a, + 0xbf, 0x4f, 0xe9, 0xb9, 0x3d, 0x0a, 0xbe, 0x5b, 0x89, 0x39, 0xe3, 0xf7, + 0xc1, 0xf7, 0x87, 0x25, 0x39, 0xbd, 0x62, 0x6b, 0x20, 0x77, 0x9e, 0xad, + 0x49, 0x9e, 0x35, 0xa5, 0x5c, 0xb2, 0xe5, 0x23, 0xb4, 0x21, 0x25, 0xce, + 0x0b, 0x36, 0x86, 0x67, 0xec, 0x25, 0xd8, 0x99, 0x12, 0x6c, 0x0a, 0x6c, + 0xc8, 0x9f, 0xa0, 0xfc, 0x59, 0xd4, 0x79, 0x06, 0xf1, 0xd3, 0x79, 0x60, + 0xbf, 0x73, 0xc0, 0x14, 0x4f, 0x97, 0x32, 0x3a, 0x96, 0x55, 0xf3, 0x85, + 0xcf, 0x52, 0xb1, 0x8f, 0x94, 0xe7, 0xd4, 0x7d, 0x1e, 0xb5, 0xb6, 0x59, + 0x67, 0x13, 0x71, 0x16, 0x28, 0x13, 0x99, 0x9b, 0xf3, 0x79, 0x42, 0xdb, + 0xc7, 0xf3, 0x19, 0xdf, 0x56, 0x36, 0xaf, 0xb1, 0x95, 0x22, 0x2f, 0x56, + 0x3c, 0x3c, 0x49, 0x7c, 0x5c, 0x9c, 0x4a, 0xac, 0x9c, 0x63, 0x16, 0xe1, + 0x37, 0x97, 0x11, 0x67, 0x44, 0xd2, 0xdf, 0x94, 0xc8, 0x71, 0xd7, 0xfd, + 0x21, 0xfc, 0x66, 0x01, 0x6b, 0x62, 0x04, 0x50, 0xbe, 0xc0, 0x77, 0x94, + 0x7b, 0xca, 0x76, 0x80, 0xe7, 0x19, 0xf2, 0x12, 0xca, 0xca, 0x2a, 0xfe, + 0xfa, 0x16, 0xe8, 0xd1, 0xf4, 0xa9, 0x32, 0xd6, 0x6b, 0x94, 0xdc, 0x58, + 0x0a, 0x31, 0x4e, 0xaf, 0xd9, 0x88, 0xf6, 0x73, 0x0b, 0x6c, 0x63, 0x0d, + 0xf0, 0x3a, 0xd5, 0x4b, 0x0b, 0x2c, 0xef, 0x90, 0x8b, 0x88, 0x45, 0x49, + 0x43, 0x79, 0x36, 0x2d, 0xde, 0xde, 0x31, 0xed, 0x15, 0x69, 0x45, 0x1e, + 0xfc, 0xca, 0x96, 0xe8, 0x67, 0x43, 0x52, 0x88, 0x93, 0xd7, 0x71, 0x59, + 0x9e, 0xfa, 0x4c, 0x13, 0xf7, 0x66, 0xb3, 0x36, 0x9f, 0xfd, 0xbd, 0x0e, + 0xf3, 0x2d, 0xec, 0x75, 0x70, 0x7f, 0x23, 0x04, 0x5f, 0xa6, 0xf6, 0x3c, + 0x90, 0x26, 0xea, 0xe2, 0x5f, 0xbe, 0xf7, 0xb0, 0x51, 0x0d, 0x3f, 0x12, + 0x4f, 0x72, 0xbe, 0x56, 0x61, 0x09, 0xf6, 0xa3, 0x2d, 0x7d, 0x49, 0xee, + 0x3d, 0xe1, 0xcd, 0xcf, 0x38, 0x25, 0xbc, 0x4b, 0x23, 0x57, 0x67, 0x2d, + 0xe7, 0x0a, 0x30, 0x45, 0x2e, 0xe6, 0x60, 0xbd, 0x46, 0x9b, 0x60, 0xbf, + 0x06, 0x32, 0xc6, 0x99, 0x26, 0x0f, 0x9f, 0x85, 0x64, 0x62, 0x8a, 0xe7, + 0x9e, 0xb0, 0x6d, 0xc0, 0x90, 0xbf, 0x1b, 0xc2, 0x73, 0x85, 0x79, 0xc4, + 0xa4, 0x5e, 0x3c, 0x8b, 0x67, 0xaf, 0x3f, 0xf2, 0xdc, 0x38, 0xc1, 0xb9, + 0x07, 0xe4, 0x5e, 0xa0, 0x13, 0x41, 0xff, 0x9d, 0x7a, 0xac, 0xce, 0x53, + 0x29, 0xee, 0x65, 0x4b, 0x12, 0xf6, 0x22, 0x8b, 0x58, 0x32, 0x17, 0xeb, + 0xd0, 0xd8, 0x9c, 0xef, 0xd6, 0x62, 0x4f, 0x3f, 0xc6, 0x4b, 0xc9, 0xe7, + 0x4b, 0x3e, 0xd6, 0x4b, 0xc1, 0xc7, 0x4a, 0x68, 0xb8, 0xc7, 0x95, 0x1f, + 0x3a, 0xe4, 0x57, 0x1f, 0xf2, 0x8e, 0x1c, 0xae, 0xfe, 0xb2, 0xf3, 0xcd, + 0xfa, 0xbf, 0x66, 0xd0, 0xc8, 0x1f, 0xe8, 0x03, 0x3e, 0x22, 0xed, 0x06, + 0xfc, 0x79, 0x11, 0xb8, 0xcb, 0x38, 0xd3, 0xa1, 0xde, 0x19, 0xc0, 0x06, + 0xe5, 0x29, 0xd8, 0xc6, 0x33, 0x3c, 0xf3, 0x85, 0x6d, 0x3b, 0x13, 0x96, + 0xe2, 0x0c, 0xe5, 0x52, 0xda, 0x0c, 0xac, 0x17, 0xeb, 0x97, 0xa7, 0x3a, + 0x90, 0x36, 0x23, 0x4d, 0xa8, 0x7e, 0xca, 0x53, 0xb6, 0x6a, 0x5f, 0x9e, + 0x4a, 0xa9, 0x76, 0xe5, 0xa9, 0x3e, 0xa4, 0x8e, 0x34, 0x9c, 0x41, 0xe0, + 0x74, 0xa6, 0x5b, 0x26, 0x4e, 0xc2, 0xbf, 0xf4, 0x1b, 0xea, 0xbe, 0xc4, + 0x38, 0xfc, 0x4f, 0x08, 0x51, 0xd6, 0x15, 0x73, 0x00, 0x18, 0x6b, 0x1b, + 0x30, 0xc8, 0x36, 0xb1, 0x8f, 0x73, 0xfe, 0xb4, 0xbd, 0xcb, 0xdc, 0xff, + 0x8a, 0x3f, 0x28, 0x19, 0xd9, 0x37, 0xd3, 0x08, 0x7d, 0x0d, 0x99, 0x45, + 0xe9, 0x32, 0x87, 0x90, 0xcf, 0xcf, 0x91, 0x6f, 0xf7, 0xab, 0xd8, 0x2d, + 0xeb, 0xc4, 0xa2, 0x12, 0x4d, 0x63, 0x8c, 0xb7, 0xd2, 0xbe, 0x07, 0xf2, + 0x67, 0xeb, 0x3e, 0xd2, 0xa0, 0xa7, 0x9e, 0x1f, 0x3c, 0xeb, 0xcd, 0xfc, + 0x8a, 0xb3, 0x5e, 0xca, 0x35, 0xf9, 0x7b, 0xbf, 0x2c, 0xdb, 0x69, 0x79, + 0xc9, 0x4e, 0xc9, 0x45, 0x7b, 0xab, 0xfc, 0x39, 0xfc, 0xf4, 0x25, 0x7b, + 0xba, 0x89, 0x58, 0xa0, 0xac, 0xce, 0xcf, 0xfc, 0xb5, 0xb2, 0xf5, 0x3e, + 0xfa, 0x8f, 0x64, 0x71, 0x8a, 0xd8, 0xd9, 0xdd, 0xbe, 0xc7, 0x29, 0xd0, + 0x6f, 0x81, 0x06, 0x62, 0xb5, 0x02, 0xfc, 0xdf, 0x41, 0x19, 0x72, 0xe8, + 0xf7, 0x94, 0x8f, 0x8a, 0x0f, 0x79, 0xfa, 0xec, 0xe4, 0x61, 0x57, 0x97, + 0x67, 0xa0, 0x4f, 0x42, 0xf9, 0xc7, 0xf3, 0x1c, 0xd7, 0xdd, 0x96, 0x2f, + 0x94, 0x38, 0xcf, 0xe2, 0xe6, 0xa8, 0x04, 0x65, 0x58, 0xe1, 0x85, 0x16, + 0x79, 0x71, 0x61, 0x83, 0x18, 0xf0, 0x50, 0xc6, 0x2d, 0x61, 0x75, 0xd3, + 0x84, 0xf1, 0xb7, 0xb4, 0xf2, 0xbe, 0xd8, 0x87, 0xc1, 0x1b, 0xee, 0x05, + 0x60, 0x6e, 0xad, 0x9c, 0x89, 0x9f, 0xef, 0x83, 0x7e, 0xf1, 0x39, 0x20, + 0x39, 0x3b, 0x86, 0x67, 0xa6, 0xd4, 0x39, 0xee, 0x93, 0x05, 0xc5, 0xc3, + 0xdc, 0xe3, 0xea, 0x7d, 0xa3, 0x7d, 0x07, 0x70, 0x1d, 0xe5, 0x15, 0xe9, + 0xa2, 0x37, 0x6e, 0x0e, 0x38, 0x2e, 0xdf, 0xd7, 0xa4, 0xce, 0xff, 0x0a, + 0xd0, 0x85, 0x71, 0x55, 0xbf, 0x5f, 0x2e, 0x4d, 0xed, 0x8f, 0x7a, 0xfa, + 0x31, 0xa0, 0x9f, 0xf9, 0x9e, 0xf1, 0x15, 0xf7, 0x4b, 0x5e, 0x19, 0x99, + 0xb4, 0xbf, 0xa1, 0xf5, 0x47, 0x02, 0x77, 0xf7, 0x00, 0x87, 0x1e, 0x69, + 0xc0, 0x5c, 0xac, 0x44, 0x22, 0x60, 0xb4, 0x1b, 0xc0, 0xf1, 0x43, 0xca, + 0xe7, 0xf6, 0xa8, 0xfd, 0xe8, 0x53, 0xa9, 0x16, 0x29, 0x9b, 0xb6, 0xba, + 0x17, 0xb7, 0x64, 0x6e, 0x21, 0xd6, 0xc7, 0xaf, 0x09, 0x65, 0x5d, 0x48, + 0x1b, 0x91, 0xbe, 0x4b, 0x8a, 0xc7, 0xa6, 0xf5, 0x78, 0xe1, 0x35, 0xf9, + 0x3e, 0x9d, 0x7e, 0x44, 0xc7, 0x53, 0x1c, 0x27, 0x2c, 0xf6, 0x17, 0x9b, + 0xa5, 0xeb, 0x88, 0x09, 0x6c, 0x1b, 0x07, 0xd6, 0xed, 0x90, 0xd4, 0x91, + 0x84, 0xdc, 0x72, 0xc4, 0xdf, 0x73, 0xfa, 0x0f, 0x23, 0x49, 0xb5, 0xc7, + 0xf9, 0xdd, 0x11, 0x7b, 0x8e, 0xe9, 0x6b, 0xfa, 0xfe, 0xde, 0x15, 0x7d, + 0xaf, 0xef, 0x47, 0x23, 0x3d, 0x2a, 0xfd, 0x6f, 0x23, 0x29, 0x95, 0xbe, + 0x3e, 0x72, 0x4b, 0xc5, 0x8b, 0x8f, 0x8a, 0xf3, 0x29, 0xf9, 0x5c, 0x89, + 0xf8, 0xb2, 0x1f, 0xd8, 0xd1, 0x81, 0x9d, 0xe9, 0x83, 0x9d, 0x49, 0xc1, + 0xce, 0x0c, 0xd0, 0xce, 0xc0, 0x6e, 0xbf, 0x02, 0xbb, 0xed, 0xc8, 0xf7, + 0x20, 0xaf, 0x4f, 0x3b, 0x8d, 0xc0, 0x85, 0xae, 0xeb, 0xcd, 0xd5, 0x7a, + 0x62, 0x09, 0xeb, 0x5b, 0x3e, 0x2d, 0x91, 0x56, 0xd8, 0xa0, 0x2d, 0x27, + 0x1a, 0x64, 0x3e, 0xe6, 0xba, 0x47, 0x1d, 0x5b, 0xae, 0xa2, 0x7e, 0xd6, + 0xa6, 0x1e, 0xbf, 0x14, 0x65, 0x3c, 0x76, 0x75, 0x6a, 0x2b, 0x6c, 0x12, + 0xe5, 0x3d, 0x22, 0xe5, 0xb1, 0xb8, 0x2c, 0x20, 0x3e, 0xab, 0xd5, 0x49, + 0xe1, 0x99, 0xfa, 0xff, 0x5d, 0xd4, 0x4d, 0xc1, 0x3f, 0x98, 0xb2, 0xd8, + 0x93, 0x90, 0x53, 0x3d, 0xd6, 0x40, 0xc2, 0xa0, 0xed, 0x4a, 0xc8, 0x1c, + 0x62, 0xfd, 0x72, 0x89, 0xf5, 0x59, 0x0f, 0xfa, 0x59, 0xf2, 0xda, 0x4d, + 0x96, 0x7c, 0x3b, 0xd1, 0xcf, 0x7d, 0xc8, 0x50, 0xae, 0xc7, 0xf3, 0x01, + 0x86, 0xd1, 0x08, 0x39, 0x70, 0xc0, 0xff, 0x31, 0x94, 0xf7, 0xf3, 0xbe, + 0x07, 0xca, 0x88, 0x85, 0x7e, 0x1c, 0x25, 0x46, 0xcc, 0x39, 0x63, 0x28, + 0x63, 0x1b, 0x2b, 0x9e, 0x44, 0xf9, 0xa8, 0x24, 0xe3, 0x79, 0x75, 0xf7, + 0xac, 0x1d, 0x65, 0xec, 0x23, 0xa8, 0xf7, 0x63, 0xfe, 0x8f, 0x92, 0xa3, + 0xa0, 0xed, 0x97, 0xf7, 0xaa, 0xbd, 0x81, 0x8c, 0xe9, 0x40, 0x1f, 0x58, + 0x96, 0x34, 0xd9, 0x2e, 0xe7, 0x38, 0xca, 0x16, 0xde, 0x57, 0xe1, 0x19, + 0x5e, 0x44, 0xee, 0xad, 0x34, 0x4b, 0xae, 0xd2, 0x70, 0x1d, 0xfb, 0xef, + 0xeb, 0xe4, 0x72, 0xdc, 0x14, 0xde, 0x83, 0xf0, 0xf4, 0x3c, 0xb4, 0x95, + 0x3a, 0x31, 0xc0, 0x73, 0x03, 0xf8, 0x5b, 0xac, 0x05, 0xfc, 0xef, 0x39, + 0xf8, 0xdf, 0xa7, 0x4b, 0x35, 0xfb, 0xe1, 0xf9, 0x5d, 0xda, 0x80, 0x27, + 0xb1, 0x66, 0xa3, 0xc0, 0xfd, 0x3b, 0x11, 0x0f, 0x0c, 0x03, 0xfb, 0x0f, + 0x62, 0xfd, 0xd2, 0x58, 0xbb, 0x31, 0xde, 0x17, 0xc2, 0x3a, 0x0e, 0xa8, + 0x73, 0xe6, 0x19, 0x75, 0xe7, 0xe2, 0x47, 0xca, 0xf7, 0x3e, 0x5e, 0x32, + 0xe0, 0x1f, 0x0a, 0xee, 0x66, 0xdb, 0x02, 0xfe, 0x5b, 0xd1, 0xe7, 0x81, + 0x17, 0x61, 0x57, 0x7e, 0x06, 0xba, 0xce, 0xcf, 0xd0, 0x9f, 0xa3, 0x8e, + 0x87, 0xb7, 0x1d, 0xee, 0x75, 0x41, 0x9f, 0x0f, 0x2f, 0xcb, 0x12, 0x70, + 0x47, 0x86, 0x72, 0x8c, 0xf8, 0xc1, 0x7a, 0x7a, 0x4e, 0xba, 0x69, 0x03, + 0xe7, 0xa8, 0x2b, 0xfd, 0xd3, 0x71, 0x60, 0x3d, 0x20, 0x79, 0x75, 0xae, + 0x8a, 0xe7, 0xb3, 0x1b, 0xc5, 0x20, 0xde, 0x73, 0x6e, 0x40, 0x19, 0xed, + 0x86, 0x8f, 0x91, 0x96, 0x06, 0xda, 0x24, 0xb3, 0xa5, 0x4d, 0xd9, 0x0e, + 0xcb, 0x79, 0x09, 0xe3, 0xee, 0x90, 0x46, 0x60, 0xb8, 0x02, 0xc6, 0x38, + 0x20, 0xff, 0xd5, 0xe1, 0x1e, 0x95, 0x17, 0xfb, 0x81, 0x96, 0x08, 0x78, + 0xd6, 0xb4, 0xc7, 0x36, 0x23, 0x3b, 0xaa, 0xec, 0x3f, 0xa2, 0x30, 0x56, + 0x4e, 0xd8, 0x3f, 0xfc, 0x04, 0xc6, 0x4c, 0x4e, 0x53, 0xf6, 0x7b, 0xb1, + 0x6e, 0xbf, 0x0d, 0x0c, 0x44, 0xae, 0x7e, 0x75, 0x83, 0xa7, 0x2f, 0xa4, + 0x7f, 0x89, 0x78, 0x82, 0x67, 0x00, 0x5e, 0x5c, 0xbe, 0x42, 0x5b, 0x3f, + 0xe8, 0x9d, 0xdd, 0xe0, 0x9f, 0x25, 0x77, 0x4e, 0x7b, 0xfe, 0xba, 0xf3, + 0x2c, 0x5a, 0x1d, 0x95, 0x76, 0x9e, 0x4a, 0x1b, 0x72, 0x8b, 0xdc, 0x19, + 0xf2, 0xfa, 0x31, 0x4e, 0x98, 0x90, 0x55, 0xda, 0x81, 0x76, 0xc8, 0x39, + 0xf3, 0xb4, 0x29, 0xb4, 0x09, 0x94, 0x05, 0x5b, 0x8a, 0x55, 0xd8, 0x84, + 0x96, 0x0e, 0x99, 0x23, 0xcf, 0x4e, 0xd0, 0x4e, 0xfc, 0x48, 0x26, 0xd7, + 0xd8, 0xca, 0x41, 0xf1, 0xe3, 0xda, 0x66, 0x09, 0xa7, 0x6d, 0xf3, 0x3e, + 0x35, 0x47, 0xcf, 0x5e, 0xee, 0x23, 0xfe, 0x9c, 0xc9, 0x58, 0x6d, 0xa2, + 0xb1, 0xa7, 0xc2, 0x4f, 0xdf, 0xc7, 0x5c, 0xd9, 0x87, 0xe2, 0xd3, 0xc0, + 0xa0, 0x17, 0x0b, 0xa8, 0x3d, 0x3f, 0xe0, 0xe0, 0xf8, 0xcf, 0x60, 0x6b, + 0x73, 0xc4, 0x25, 0xe0, 0x73, 0xe7, 0x51, 0xca, 0xd1, 0x66, 0xda, 0x32, + 0xe0, 0xbc, 0x14, 0xed, 0xb5, 0x2c, 0x4c, 0x03, 0x73, 0x19, 0x77, 0x48, + 0x9e, 0xf2, 0xca, 0xbb, 0x0a, 0x0b, 0x86, 0x4c, 0xce, 0xb6, 0x48, 0xd7, + 0x09, 0xee, 0xaf, 0x9e, 0x8a, 0x4a, 0x0b, 0xf7, 0x58, 0xe9, 0x83, 0xfa, + 0x25, 0x87, 0xf2, 0xce, 0x13, 0x41, 0xb5, 0x1f, 0x36, 0x67, 0x90, 0x47, + 0x7d, 0xb0, 0x07, 0x56, 0x6a, 0xc9, 0xd8, 0xd6, 0xe4, 0x61, 0x48, 0xc8, + 0x52, 0x09, 0x32, 0x56, 0x82, 0x8c, 0x95, 0x20, 0x63, 0x25, 0xc8, 0x18, + 0xb0, 0xdf, 0x79, 0xe8, 0xdf, 0xb9, 0xd2, 0x80, 0xf6, 0xeb, 0xbb, 0x94, + 0x5f, 0x3f, 0x54, 0x7a, 0xc5, 0x65, 0xfa, 0xac, 0x8a, 0x4d, 0xfb, 0x20, + 0x83, 0x8c, 0x45, 0xfd, 0x18, 0xf5, 0x15, 0x79, 0x72, 0xe6, 0x55, 0x39, + 0x35, 0x53, 0xc3, 0x81, 0x13, 0x25, 0x57, 0x5e, 0x72, 0x10, 0x7f, 0xce, + 0x13, 0x53, 0x65, 0x5a, 0x1b, 0x15, 0xb6, 0x3a, 0x28, 0x79, 0x85, 0x93, + 0x95, 0x1f, 0x01, 0xbe, 0x52, 0xb8, 0x90, 0xba, 0x29, 0x6d, 0x5b, 0x2e, + 0xcb, 0x39, 0xf8, 0xf1, 0x85, 0xea, 0x6b, 0xf2, 0x8c, 0xc2, 0xe3, 0xe4, + 0xc3, 0x3b, 0xe5, 0xa7, 0xa6, 0x77, 0x9e, 0x7f, 0x0a, 0x58, 0x63, 0xa1, + 0x87, 0xb6, 0x23, 0x04, 0x5f, 0x60, 0x15, 0x3a, 0xa1, 0xd7, 0xfb, 0x8d, + 0x1b, 0x81, 0x69, 0xf8, 0x7e, 0xa3, 0xbc, 0x38, 0x53, 0xa8, 0x93, 0x09, + 0xda, 0x07, 0xeb, 0xb0, 0x18, 0xf4, 0x53, 0xf4, 0x9b, 0x9c, 0x2f, 0xfd, + 0xd4, 0x4f, 0x37, 0xf0, 0x0e, 0x57, 0xf9, 0x58, 0x6c, 0x03, 0xf7, 0x1b, + 0x63, 0x36, 0x79, 0x7a, 0x59, 0xf6, 0x57, 0x58, 0xf6, 0x2a, 0xd6, 0x87, + 0xe9, 0x0f, 0xdc, 0x7b, 0x63, 0x1c, 0x8f, 0xfd, 0x02, 0x37, 0xb5, 0x63, + 0xae, 0xa5, 0x8f, 0x68, 0xcc, 0xdd, 0xa7, 0x70, 0xf4, 0xb5, 0x78, 0x99, + 0x7c, 0x72, 0xc0, 0xa7, 0xcb, 0x6a, 0x3f, 0x70, 0x9d, 0x7d, 0xe2, 0x27, + 0xa0, 0x57, 0x85, 0x2b, 0xc2, 0x3d, 0x4b, 0xee, 0xe7, 0x72, 0xaf, 0xb8, + 0xde, 0x62, 0xa8, 0x7b, 0x03, 0x72, 0x0f, 0xec, 0xcb, 0xbd, 0xb0, 0x2f, + 0xf7, 0x5d, 0x73, 0x07, 0xda, 0x3f, 0x03, 0xe8, 0x2a, 0x04, 0x8d, 0x0e, + 0x19, 0xad, 0xd4, 0xb7, 0xe5, 0x3e, 0xee, 0x7a, 0xfb, 0xb6, 0xdc, 0xd3, + 0x4d, 0xad, 0xd9, 0x0b, 0xa4, 0x6c, 0xb8, 0x72, 0xc9, 0xe1, 0xbe, 0x9b, + 0x7f, 0x6f, 0x7e, 0x3d, 0xfc, 0x15, 0x68, 0xf6, 0xf7, 0x9c, 0x43, 0xe9, + 0x2b, 0xc2, 0xfb, 0xf3, 0xc5, 0x29, 0xe2, 0x81, 0x98, 0xba, 0x17, 0x63, + 0xa8, 0x7d, 0x3e, 0xaf, 0x6d, 0x71, 0x4a, 0x9d, 0x31, 0x15, 0xb8, 0x77, + 0x6d, 0x6e, 0xb5, 0xcc, 0xd1, 0xa0, 0x77, 0x1f, 0x93, 0xba, 0xec, 0xd9, + 0x32, 0xc8, 0x62, 0xb5, 0x76, 0xcf, 0x71, 0x50, 0xd9, 0x8b, 0x2b, 0xd0, + 0x01, 0xae, 0x17, 0xe2, 0x05, 0xe8, 0xc9, 0x04, 0xec, 0x53, 0x5e, 0xf5, + 0x17, 0xa1, 0x5c, 0x64, 0xb2, 0x41, 0x43, 0xc2, 0xc7, 0x19, 0x0b, 0x79, + 0x7b, 0x2d, 0xb9, 0xa0, 0xa5, 0xec, 0x37, 0x68, 0x07, 0x3e, 0xa3, 0x7e, + 0x26, 0xc6, 0x1b, 0xd3, 0x0d, 0xf0, 0xab, 0x58, 0xbf, 0x2a, 0xf7, 0x04, + 0xa0, 0xbb, 0x8b, 0xdf, 0x91, 0x7d, 0xb3, 0xdd, 0xcd, 0x9e, 0xfc, 0x73, + 0x1f, 0x99, 0xf3, 0xf3, 0x69, 0x58, 0xdd, 0xb7, 0x71, 0x5c, 0x22, 0x51, + 0xf8, 0xb4, 0x0f, 0x20, 0xce, 0xd8, 0x01, 0x59, 0x59, 0x8a, 0xb1, 0x5f, + 0x4f, 0x67, 0x26, 0x4b, 0xec, 0xfb, 0x3b, 0x32, 0x34, 0x5b, 0x6a, 0xa6, + 0x2f, 0x59, 0x84, 0x1d, 0x58, 0x36, 0xe9, 0x43, 0xc7, 0xe0, 0xe3, 0xda, + 0xe5, 0xfb, 0xb3, 0xf4, 0x8f, 0x49, 0xf3, 0x94, 0xf4, 0xc6, 0x4f, 0x81, + 0xa6, 0xcf, 0x3b, 0x21, 0xc6, 0x68, 0xee, 0x20, 0xca, 0xfe, 0x5c, 0x92, + 0x66, 0x67, 0x80, 0xcf, 0xbd, 0xe6, 0x17, 0x80, 0x61, 0x33, 0x66, 0xd2, + 0xbc, 0x35, 0x40, 0x39, 0x42, 0xcc, 0xbd, 0x58, 0xa3, 0xf3, 0x07, 0xb3, + 0x2a, 0x4e, 0x52, 0x76, 0x66, 0xd1, 0xe1, 0x78, 0xa0, 0x5b, 0xd9, 0xac, + 0x5b, 0x61, 0x4f, 0x22, 0xfa, 0xfc, 0x0d, 0x6d, 0x88, 0x6d, 0x9c, 0x90, + 0xce, 0x3f, 0x2a, 0xd9, 0x93, 0x31, 0xd8, 0x33, 0xf6, 0xe5, 0xc7, 0x0e, + 0xf4, 0x91, 0x3e, 0xde, 0xa6, 0xbf, 0xbb, 0x03, 0x7e, 0xef, 0x66, 0x45, + 0xcf, 0xb0, 0xd3, 0x27, 0x13, 0xc7, 0x38, 0x76, 0x0f, 0x6c, 0x79, 0x5c, + 0xc9, 0x6d, 0xb1, 0xb4, 0x1c, 0x8f, 0xc0, 0x26, 0x47, 0xb6, 0x90, 0x9f, + 0xef, 0x93, 0xbb, 0xec, 0x31, 0xb9, 0x1b, 0xb2, 0x33, 0x68, 0x3b, 0x32, + 0x84, 0xb5, 0xd8, 0x61, 0xc3, 0xef, 0x28, 0x0c, 0xdd, 0x88, 0xb8, 0x8b, + 0x63, 0xb7, 0xeb, 0xfb, 0x17, 0x1e, 0x7e, 0xfc, 0x4a, 0xd5, 0xe3, 0x51, + 0x76, 0xf6, 0x49, 0xc5, 0x9b, 0x61, 0x67, 0x9b, 0xf6, 0xb3, 0x2d, 0x92, + 0x53, 0xf5, 0xb6, 0x29, 0x7f, 0x5c, 0x5c, 0xb8, 0x1f, 0x29, 0x7c, 0xf3, + 0x02, 0xec, 0x0d, 0x30, 0x77, 0xb1, 0xb2, 0x15, 0x79, 0xf8, 0xd0, 0x85, + 0x34, 0xd2, 0xf7, 0x21, 0x65, 0xdd, 0x07, 0x9a, 0xbd, 0xbd, 0xdc, 0xb5, + 0xf7, 0xb8, 0x24, 0xf0, 0x01, 0x85, 0x4b, 0xaf, 0xa8, 0x3b, 0x80, 0x88, + 0xa1, 0x47, 0xb2, 0xb0, 0x2b, 0xcd, 0xc0, 0x40, 0x53, 0xc7, 0xad, 0xd4, + 0x50, 0x60, 0xbb, 0x7c, 0x10, 0xb1, 0x7c, 0xd9, 0xe1, 0x5a, 0x6e, 0x95, + 0x07, 0xdf, 0x4b, 0x19, 0xd9, 0x2e, 0x7b, 0xde, 0x1b, 0x90, 0x3d, 0x7d, + 0x56, 0x86, 0x74, 0xdf, 0xf2, 0x2e, 0x3f, 0x9e, 0xee, 0x1a, 0x4e, 0x06, + 0xfa, 0xe5, 0x0b, 0x90, 0xb1, 0x02, 0xe4, 0x6b, 0xa8, 0x4a, 0x9e, 0xd3, + 0xde, 0xd3, 0xce, 0xa7, 0x80, 0x95, 0x7d, 0xec, 0x67, 0xcb, 0x54, 0xb5, + 0x41, 0x12, 0x37, 0x70, 0x3f, 0x39, 0xe1, 0x9d, 0x71, 0xdc, 0x40, 0x99, + 0x40, 0x0c, 0x72, 0x83, 0xa7, 0x9f, 0xea, 0xee, 0xdd, 0x0d, 0x9e, 0x5f, + 0x41, 0xfc, 0xeb, 0x12, 0xe7, 0x79, 0x77, 0x0d, 0xbe, 0xa1, 0x6d, 0x69, + 0x68, 0xe3, 0x0a, 0xbe, 0x6b, 0x61, 0xfc, 0xf0, 0x87, 0xcd, 0xb5, 0x6f, + 0x07, 0xd6, 0xca, 0xa2, 0xbf, 0xef, 0x36, 0x87, 0x39, 0xd3, 0xa7, 0x5b, + 0x26, 0x6d, 0x61, 0xab, 0xbd, 0x4b, 0xfe, 0x0c, 0xfe, 0xfd, 0x6b, 0x2b, + 0xfe, 0x7d, 0x37, 0xf8, 0xb1, 0x16, 0x03, 0xd8, 0xe6, 0x3d, 0x98, 0xcb, + 0x30, 0xd6, 0xf3, 0x6e, 0xfc, 0xee, 0x2a, 0xad, 0xda, 0xc7, 0x9b, 0x29, + 0x00, 0x4f, 0x36, 0xd8, 0xec, 0x6f, 0xd5, 0x7e, 0x5e, 0x21, 0x2f, 0x2b, + 0x7b, 0x85, 0x03, 0x57, 0x85, 0x7e, 0xef, 0x75, 0x09, 0x77, 0xdb, 0xaf, + 0x77, 0x06, 0xec, 0xe7, 0x8d, 0x00, 0xcf, 0xc1, 0x1d, 0x39, 0x5d, 0x25, + 0x0e, 0xbb, 0x28, 0xc6, 0x59, 0x62, 0xb0, 0x97, 0xd5, 0x1e, 0x54, 0xb9, + 0xf4, 0x2d, 0xa4, 0xa8, 0x0f, 0xfb, 0x18, 0xf4, 0xf6, 0x29, 0x14, 0x56, + 0xa1, 0x9d, 0xbd, 0x1b, 0xeb, 0x30, 0x81, 0x5f, 0xe7, 0x96, 0x5b, 0xa1, + 0xbf, 0x94, 0x53, 0xee, 0x7d, 0x75, 0x9b, 0x5b, 0x02, 0x7c, 0xb7, 0xde, + 0x3e, 0xd8, 0xb7, 0x25, 0x74, 0x14, 0xbe, 0xce, 0xa0, 0x7d, 0xe0, 0x3c, + 0xe8, 0x27, 0x4d, 0x99, 0x3f, 0x46, 0x5d, 0x5f, 0xaf, 0xbe, 0x5f, 0xd7, + 0x9f, 0x8b, 0xf2, 0x1b, 0x99, 0x3c, 0xf7, 0x38, 0x4b, 0x5c, 0x03, 0x07, + 0x6b, 0xe0, 0xca, 0x71, 0xa7, 0x95, 0x36, 0x5d, 0x82, 0xc7, 0x5d, 0x19, + 0x54, 0xd8, 0xb5, 0x17, 0x98, 0x6b, 0xa3, 0xc6, 0x0d, 0x31, 0x09, 0x1d, + 0xef, 0x90, 0x46, 0xe0, 0xea, 0x86, 0x23, 0xf4, 0x91, 0xc9, 0xc4, 0x20, + 0x84, 0x20, 0xa4, 0xee, 0x93, 0x5a, 0x03, 0xdf, 0x97, 0xde, 0xc4, 0xf7, + 0x85, 0x78, 0xe9, 0x51, 0xac, 0x9f, 0xe5, 0x5c, 0x5c, 0xa7, 0x7e, 0xb1, + 0x56, 0x1f, 0x72, 0xc4, 0xbd, 0x35, 0xb6, 0xe1, 0x5e, 0x5b, 0x72, 0xe0, + 0x7b, 0xdc, 0x63, 0x43, 0xac, 0xd9, 0x70, 0xc6, 0xa3, 0xc1, 0x58, 0x6c, + 0x93, 0xf2, 0x49, 0xea, 0x28, 0xf7, 0x59, 0x4c, 0x2f, 0x4e, 0x2d, 0x31, + 0x5e, 0xe5, 0xfb, 0x84, 0x7e, 0xdf, 0xa9, 0xdf, 0x33, 0x1e, 0x2d, 0xb8, + 0x0d, 0xe0, 0xe9, 0x0e, 0xd8, 0xcf, 0xfb, 0xb7, 0xda, 0x0a, 0x37, 0xdc, + 0xbf, 0xb2, 0x66, 0x3b, 0xd5, 0xdd, 0xa2, 0x72, 0xe9, 0xa0, 0xd8, 0x5b, + 0x96, 0x52, 0x21, 0x19, 0xc5, 0x5a, 0x30, 0x9f, 0x21, 0x3d, 0xa9, 0x43, + 0xb2, 0x5f, 0xad, 0x4d, 0xf9, 0x98, 0x75, 0x38, 0x11, 0x98, 0x10, 0xa3, + 0xcc, 0xe7, 0x4f, 0x23, 0x3d, 0x04, 0xbc, 0xe3, 0xed, 0x5d, 0x1a, 0xe5, + 0xd5, 0xbc, 0x04, 0xc6, 0x30, 0x77, 0xac, 0xda, 0xc7, 0xaa, 0xed, 0x71, + 0xf1, 0xfd, 0xa0, 0x7a, 0x9f, 0x5a, 0xb5, 0xcf, 0x95, 0x33, 0x88, 0x65, + 0xfc, 0xf7, 0x5c, 0x0b, 0xae, 0x17, 0x7c, 0xf1, 0x31, 0x7f, 0xcf, 0xab, + 0x45, 0xaf, 0x0b, 0xd7, 0x67, 0x4a, 0xce, 0x99, 0xd6, 0x30, 0xe5, 0xef, + 0xb6, 0xad, 0x37, 0xc9, 0x78, 0x3b, 0xf7, 0xdb, 0xea, 0x69, 0x58, 0xbb, + 0x8f, 0x56, 0x3f, 0xfe, 0xda, 0xfd, 0x37, 0x8e, 0xed, 0xed, 0xb1, 0x65, + 0x57, 0xed, 0xb1, 0xd5, 0x8f, 0xc7, 0xb1, 0x36, 0x22, 0x7e, 0x2a, 0xb8, + 0x31, 0x9b, 0x6b, 0xd4, 0x95, 0x98, 0x65, 0xfe, 0xcb, 0x06, 0xd6, 0x31, + 0x06, 0x3f, 0xc2, 0xb5, 0xf4, 0xcf, 0x9e, 0xb9, 0xa6, 0xc9, 0xc4, 0x21, + 0x6f, 0x3d, 0x07, 0xbc, 0x75, 0xf7, 0xd6, 0xff, 0xe2, 0xca, 0x3a, 0xd2, + 0x3f, 0x70, 0x1d, 0xdb, 0x45, 0x60, 0x67, 0x8d, 0x23, 0x5c, 0x43, 0xa6, + 0x5c, 0x43, 0xbe, 0xe3, 0x1a, 0x76, 0xea, 0x77, 0x5c, 0x3f, 0xe0, 0xb4, + 0x2f, 0x02, 0x63, 0x38, 0x59, 0xf5, 0x1d, 0x54, 0x67, 0xb7, 0xaf, 0x8b, + 0x29, 0x79, 0x66, 0x3e, 0x2a, 0x66, 0xda, 0x9b, 0xd7, 0xd8, 0xaa, 0xfd, + 0x76, 0x9e, 0x5f, 0xf5, 0x11, 0x7b, 0xfa, 0xf3, 0x8a, 0x73, 0x5e, 0xfb, + 0xe5, 0xb2, 0xe4, 0xa7, 0x42, 0x88, 0x01, 0x53, 0xc0, 0x39, 0x7d, 0xb0, + 0xb7, 0xdc, 0x1f, 0x45, 0x59, 0x85, 0x78, 0x85, 0xbe, 0x2e, 0x05, 0x5d, + 0xa1, 0x0d, 0x26, 0x1e, 0x79, 0x55, 0x72, 0x73, 0xbe, 0x8d, 0x41, 0xff, + 0x86, 0xdf, 0x3f, 0xf9, 0x9c, 0xb9, 0x65, 0xb3, 0x2c, 0x25, 0x36, 0x8b, + 0x95, 0x58, 0x90, 0xda, 0xba, 0x8e, 0xad, 0xcf, 0x77, 0xe7, 0xfe, 0x60, + 0x4d, 0x36, 0xc6, 0xd6, 0x59, 0xfb, 0xbd, 0xe2, 0xbf, 0xf7, 0xd7, 0x7e, + 0xdd, 0x75, 0x28, 0xbc, 0x22, 0x5c, 0x0b, 0xf2, 0x80, 0x78, 0x38, 0x2c, + 0x9f, 0x8a, 0x51, 0x1f, 0x0b, 0xea, 0x7c, 0x33, 0x69, 0x74, 0x2b, 0x9b, + 0x31, 0xe8, 0x78, 0xf2, 0x5a, 0xc0, 0x38, 0x91, 0xae, 0x7f, 0xe1, 0x0e, + 0xc6, 0x10, 0xe7, 0x76, 0xd1, 0xbe, 0xf8, 0x3a, 0x1d, 0x55, 0x3a, 0xfd, + 0x79, 0x27, 0x20, 0x45, 0x3b, 0x20, 0x13, 0xf6, 0x41, 0x85, 0xf1, 0x3f, + 0x84, 0xbe, 0x1e, 0xd4, 0x7d, 0x4d, 0x48, 0xb7, 0xb6, 0x3f, 0x07, 0x20, + 0xe7, 0xae, 0xdc, 0xe7, 0x6c, 0x95, 0xdb, 0x5a, 0xa9, 0x03, 0xfe, 0xfc, + 0x0f, 0x4a, 0xd7, 0xd6, 0xa5, 0x04, 0x22, 0x83, 0x5b, 0xc2, 0x2b, 0x3c, + 0xa0, 0x9e, 0xf9, 0xf2, 0xed, 0xf1, 0xc1, 0x9b, 0xff, 0xaa, 0xb9, 0xea, + 0x79, 0x72, 0xce, 0xac, 0xc7, 0xb9, 0x7a, 0x58, 0xbe, 0x36, 0x57, 0xbf, + 0x7e, 0x33, 0x64, 0xc9, 0x4a, 0x48, 0xa0, 0x9e, 0x37, 0x2b, 0x36, 0x6a, + 0x98, 0x7b, 0x24, 0x4b, 0xa6, 0x95, 0x4a, 0x04, 0xfc, 0xbd, 0x68, 0x0f, + 0xeb, 0x76, 0x02, 0x87, 0xdb, 0xdd, 0xdd, 0xa9, 0xbc, 0xda, 0x23, 0x35, + 0xd4, 0xbc, 0x26, 0x80, 0xc9, 0xe6, 0x9d, 0x57, 0xdc, 0x4f, 0x02, 0xb3, + 0x8e, 0xcb, 0xc3, 0x12, 0x5c, 0xb5, 0x97, 0x8b, 0xfc, 0x59, 0xee, 0xe7, + 0x5a, 0x89, 0x0c, 0xd6, 0xf8, 0xc3, 0x88, 0xe1, 0xcb, 0xb0, 0xfb, 0x1f, + 0xa1, 0x6f, 0x28, 0xc1, 0x5f, 0x00, 0x97, 0x7c, 0xed, 0xba, 0x18, 0x7e, + 0xbc, 0x6e, 0x2f, 0xd7, 0xc3, 0xa7, 0xe7, 0x14, 0x26, 0x25, 0x6e, 0x3f, + 0x1c, 0xb8, 0xa7, 0x27, 0x88, 0x38, 0xa3, 0xe0, 0x46, 0x6c, 0xe2, 0xb8, + 0x83, 0x72, 0x17, 0xd6, 0xe7, 0xf4, 0x7c, 0x21, 0xb0, 0xa3, 0xe4, 0xcb, + 0x2a, 0xe2, 0xca, 0xaa, 0x95, 0x5a, 0x06, 0x3f, 0x9e, 0xd4, 0x98, 0x8f, + 0xe7, 0x35, 0x65, 0x1d, 0xb3, 0x70, 0x6f, 0xa8, 0x58, 0x3d, 0x28, 0x93, + 0x0e, 0xf7, 0x76, 0xba, 0xa4, 0x18, 0xcb, 0xdc, 0xd4, 0xb8, 0xc2, 0x23, + 0xcb, 0x44, 0xcc, 0x97, 0xa2, 0xfd, 0x2e, 0xeb, 0xf3, 0x8e, 0x27, 0x95, + 0x7c, 0xf9, 0xfb, 0xc2, 0x8c, 0x8f, 0x78, 0x5e, 0xd5, 0x65, 0x0e, 0xf3, + 0x79, 0x8e, 0x32, 0xa0, 0x62, 0x26, 0xf0, 0xf2, 0x21, 0xc9, 0x8c, 0x26, + 0x14, 0x6e, 0x79, 0xbc, 0x44, 0x7d, 0x21, 0xfe, 0xbf, 0x0c, 0xec, 0x1f, + 0xc2, 0x9a, 0x31, 0x0e, 0xe0, 0xd8, 0xd4, 0x0b, 0x94, 0x55, 0xcc, 0x5f, + 0xa2, 0x17, 0xdb, 0x37, 0x11, 0x63, 0x5c, 0x28, 0x7d, 0x5c, 0xf1, 0x6f, + 0x49, 0xfc, 0xbd, 0x73, 0x85, 0x05, 0x0b, 0xd9, 0x60, 0x40, 0x92, 0x47, + 0x3f, 0x03, 0x19, 0x1a, 0x41, 0x8c, 0xc4, 0x7a, 0xa2, 0xce, 0xaf, 0x06, + 0x81, 0xb9, 0x0c, 0xfb, 0x46, 0x29, 0x9a, 0x61, 0x29, 0xaa, 0x7b, 0x80, + 0x3c, 0xcf, 0x0d, 0xaa, 0xbd, 0x9d, 0xa2, 0x49, 0xcc, 0x9f, 0xd9, 0xe4, + 0xdf, 0x03, 0x2c, 0x9a, 0x6c, 0xc7, 0x3c, 0xcb, 0x27, 0x24, 0x7c, 0xf4, + 0x80, 0x34, 0x1c, 0x7d, 0x58, 0x1a, 0xa7, 0x89, 0xf1, 0xb8, 0x77, 0x6f, + 0xdc, 0xd1, 0x28, 0xc4, 0xdc, 0x5f, 0xc5, 0xd8, 0x07, 0xe5, 0x87, 0x8e, + 0x4f, 0xd3, 0x86, 0x8d, 0xd2, 0xc2, 0x3a, 0x7e, 0xde, 0xc7, 0xe3, 0x77, + 0x80, 0x1e, 0xce, 0x3f, 0xa1, 0x71, 0xdf, 0x1d, 0x75, 0xb1, 0x6b, 0x83, + 0x8e, 0x5d, 0xd9, 0xee, 0x32, 0x7c, 0xf6, 0x31, 0x09, 0xdb, 0x7e, 0xfb, + 0xed, 0xa8, 0x17, 0xaf, 0xbb, 0x03, 0xc1, 0x3a, 0xfa, 0x4e, 0x40, 0x0b, + 0x71, 0x0f, 0xcf, 0xdb, 0x59, 0xe6, 0x9d, 0xf9, 0x1b, 0xe5, 0x74, 0x70, + 0xf5, 0xf8, 0xdb, 0xea, 0xea, 0xfa, 0x65, 0x7e, 0x9b, 0xb0, 0x17, 0xf3, + 0xf7, 0x87, 0xeb, 0xda, 0x7d, 0xd7, 0xf4, 0x52, 0x2f, 0xf6, 0xf0, 0xe2, + 0x20, 0xce, 0x21, 0x55, 0x87, 0x73, 0x56, 0x7f, 0x2f, 0x9a, 0x43, 0x79, + 0x7e, 0xd6, 0xbf, 0x3b, 0x64, 0x60, 0x2e, 0x56, 0x81, 0xf1, 0x8b, 0xc9, + 0x6f, 0x33, 0x67, 0x0b, 0xa0, 0xfb, 0x66, 0x75, 0xef, 0x88, 0x77, 0x37, + 0x50, 0x2f, 0xe1, 0xe1, 0x4f, 0xe6, 0xe3, 0x58, 0xf3, 0x77, 0x75, 0x18, + 0xe9, 0xff, 0x7e, 0x53, 0xb6, 0x9f, 0xf8, 0x66, 0x13, 0xcf, 0x21, 0x81, + 0x9b, 0x29, 0x67, 0xdf, 0x81, 0x9c, 0x35, 0xaa, 0x73, 0x9f, 0x62, 0x89, + 0xf1, 0x5c, 0x1e, 0xf2, 0xc3, 0xfb, 0x7b, 0x8c, 0xfb, 0xf2, 0x7a, 0x3f, + 0x96, 0x74, 0x12, 0xd3, 0xfb, 0xf1, 0x01, 0xfb, 0x5c, 0xef, 0x9e, 0xb2, + 0x1f, 0xb3, 0x51, 0xde, 0xe2, 0x8a, 0xe6, 0xa1, 0x35, 0xf1, 0xca, 0x21, + 0xd8, 0x82, 0x79, 0xc8, 0xf3, 0x5e, 0xd8, 0xc0, 0xc1, 0x20, 0xf5, 0x33, + 0xaa, 0x63, 0x59, 0x9b, 0x71, 0x7b, 0x60, 0x14, 0x7d, 0x18, 0xd3, 0xaf, + 0xc9, 0x04, 0xec, 0xff, 0x64, 0x35, 0xa9, 0xbe, 0xe9, 0xc9, 0xc4, 0x79, + 0x9f, 0x8c, 0xe5, 0x5f, 0x83, 0xbc, 0xbe, 0x06, 0x3c, 0xbc, 0x01, 0xfc, + 0x34, 0xf4, 0x5a, 0xfd, 0x96, 0xde, 0x8b, 0x8a, 0x70, 0x2f, 0x1e, 0x76, + 0xb3, 0xe8, 0x61, 0xcd, 0xd8, 0x24, 0xd2, 0x7f, 0x1e, 0xf5, 0xe4, 0xf5, + 0xdf, 0x6a, 0x79, 0x6b, 0x42, 0xf9, 0x63, 0x6a, 0x0f, 0xd2, 0x9b, 0x93, + 0xa5, 0x63, 0x95, 0x30, 0x64, 0x8e, 0xf3, 0xfa, 0x53, 0xd4, 0xa3, 0xac, + 0xf5, 0xe8, 0xb3, 0xd9, 0xa8, 0xb2, 0x8f, 0x39, 0xc8, 0x52, 0x5e, 0xc5, + 0x11, 0xc0, 0xf7, 0x0e, 0xdb, 0x3d, 0xb7, 0x89, 0x67, 0x9f, 0x0d, 0xb6, + 0x8a, 0x2d, 0xda, 0x83, 0xe2, 0x97, 0xdd, 0x89, 0x32, 0xca, 0xd9, 0x8d, + 0x58, 0x1b, 0x96, 0x65, 0x91, 0xe7, 0x58, 0x37, 0xe9, 0x71, 0x38, 0x46, + 0x77, 0xf3, 0x6a, 0x9a, 0x38, 0x97, 0xf6, 0x35, 0xdf, 0x35, 0xb0, 0xec, + 0x46, 0x5d, 0x16, 0xd2, 0xf3, 0x1b, 0xd2, 0xdf, 0xd2, 0x5a, 0x87, 0x33, + 0x2b, 0xd8, 0x98, 0xf4, 0x45, 0x54, 0xbb, 0x8c, 0xe9, 0xc9, 0xce, 0x21, + 0xac, 0x47, 0x28, 0x1d, 0xe4, 0x99, 0x2c, 0xf8, 0xeb, 0xeb, 0x44, 0x5c, + 0xc5, 0x9d, 0x09, 0xc3, 0xbb, 0xbb, 0x74, 0xee, 0x9a, 0xfb, 0xd9, 0xde, + 0x5d, 0xf7, 0xa1, 0x9e, 0x26, 0x99, 0x9f, 0x89, 0xe8, 0x7b, 0x93, 0x71, + 0xa5, 0xb3, 0xf9, 0x31, 0xe6, 0xff, 0xc7, 0x26, 0x7e, 0xc7, 0x6c, 0xd8, + 0x2c, 0x6f, 0xd7, 0xfc, 0xbd, 0x51, 0xdd, 0x33, 0xa2, 0x2e, 0x14, 0xe7, + 0xde, 0x50, 0xef, 0x4f, 0xcf, 0x36, 0xa8, 0xfa, 0xa7, 0x67, 0xd7, 0xde, + 0x15, 0x62, 0xd9, 0xdb, 0xb8, 0xbf, 0x21, 0x0b, 0x53, 0x0d, 0xb2, 0x38, + 0x1b, 0x60, 0xbc, 0x96, 0x6e, 0xac, 0x7d, 0x0b, 0xa3, 0xbf, 0x5b, 0x73, + 0x65, 0x08, 0xeb, 0x37, 0x3f, 0x30, 0x29, 0xe5, 0x01, 0xc6, 0x23, 0xea, + 0x3e, 0x20, 0x64, 0xa4, 0x01, 0x58, 0xb4, 0xe0, 0x96, 0x6d, 0xee, 0x03, + 0xb7, 0x68, 0xbd, 0x7e, 0x45, 0xc7, 0x7c, 0xe4, 0x91, 0x21, 0xb9, 0xbe, + 0x09, 0x45, 0x57, 0x59, 0xf1, 0xca, 0xff, 0xd6, 0x88, 0xfd, 0xf3, 0x7b, + 0xa3, 0xa0, 0xc6, 0xb2, 0xfb, 0x35, 0xcf, 0xff, 0x4a, 0xa7, 0x8f, 0xca, + 0x9e, 0x63, 0xbf, 0x0f, 0x5a, 0x9b, 0xbc, 0x3b, 0x4f, 0x52, 0xff, 0x3d, + 0x49, 0x48, 0x7d, 0xcf, 0x12, 0xb2, 0x1f, 0x45, 0x19, 0xf7, 0xc1, 0x1e, + 0x55, 0xf3, 0xe0, 0xbd, 0xba, 0x82, 0xfc, 0xaa, 0xfb, 0x21, 0x7e, 0x2c, + 0xc6, 0xbb, 0x4b, 0x51, 0xdd, 0xdf, 0x0e, 0xbd, 0x8e, 0x63, 0xb2, 0x07, + 0xbe, 0x26, 0x0f, 0x4c, 0xca, 0xfb, 0x5e, 0xe3, 0xc1, 0xfa, 0x31, 0x7d, + 0x59, 0xf6, 0xe2, 0x7c, 0xff, 0xde, 0x41, 0x50, 0xc5, 0x23, 0x2b, 0x7b, + 0x06, 0xba, 0x7c, 0x4c, 0xf6, 0x95, 0xd4, 0xde, 0x81, 0x3a, 0x2f, 0x9c, + 0x84, 0x4e, 0x0e, 0x2a, 0x7f, 0x12, 0x09, 0x0c, 0x55, 0xd2, 0x92, 0x3f, + 0xb9, 0x13, 0xe3, 0x70, 0x1f, 0x2e, 0xa3, 0xcf, 0xe5, 0x76, 0xcb, 0x9e, + 0xaa, 0x37, 0xf6, 0xde, 0x12, 0xdf, 0x27, 0xe1, 0xa3, 0xf9, 0x3e, 0x17, + 0x0f, 0xaa, 0x93, 0x85, 0x5b, 0xd1, 0xb6, 0x41, 0xf3, 0x96, 0xf7, 0xfc, + 0xd9, 0x9e, 0xfa, 0xf7, 0x4f, 0x4c, 0x89, 0xe6, 0xf0, 0x9e, 0x6d, 0xfc, + 0xfe, 0xf6, 0xc2, 0x67, 0x30, 0x36, 0x7e, 0x44, 0x96, 0xe6, 0x26, 0x65, + 0x79, 0xce, 0x97, 0x33, 0xde, 0xb9, 0x26, 0xed, 0x77, 0xeb, 0x3b, 0xd7, + 0x19, 0xac, 0xc3, 0x6a, 0x5e, 0xe5, 0x56, 0x7d, 0x8f, 0xf4, 0x75, 0xd3, + 0xfb, 0x26, 0x70, 0xbb, 0xba, 0x3f, 0xb5, 0x5a, 0xde, 0xd9, 0xcf, 0x57, + 0x4c, 0x9e, 0x33, 0x78, 0x77, 0xc0, 0xda, 0xeb, 0xde, 0xc7, 0xf4, 0xbd, + 0xab, 0xaf, 0xe9, 0xbb, 0xfa, 0xe4, 0xe7, 0xa8, 0xa6, 0xf7, 0x56, 0xe8, + 0x1e, 0xfb, 0x7c, 0x4c, 0xaf, 0x1b, 0xd2, 0x79, 0x3e, 0xab, 0xbb, 0xa6, + 0xfa, 0xec, 0xd5, 0xd4, 0x63, 0xd4, 0xdf, 0x7b, 0x6b, 0xa8, 0x1b, 0x97, + 0xed, 0xe9, 0x1b, 0xfc, 0x3b, 0xe0, 0x2c, 0x3b, 0xa6, 0xef, 0xd7, 0xf9, + 0x77, 0xbe, 0x59, 0xe6, 0xdf, 0x03, 0x23, 0xbf, 0xb8, 0x9f, 0x88, 0xb4, + 0x3a, 0xaa, 0x9f, 0x47, 0xeb, 0xbe, 0x1d, 0xf2, 0xfb, 0x0c, 0xa1, 0x8f, + 0x3b, 0x83, 0xd7, 0xde, 0x11, 0xe7, 0xb7, 0x54, 0x94, 0x45, 0x83, 0xdf, + 0x78, 0x33, 0x06, 0x03, 0x6e, 0xda, 0x28, 0x7b, 0x15, 0x3d, 0x05, 0x75, + 0x57, 0x22, 0xeb, 0x34, 0xc9, 0xa0, 0xe9, 0xe5, 0xf7, 0xce, 0xaf, 0x95, + 0x53, 0x96, 0x6f, 0x8a, 0x48, 0x94, 0xdf, 0x70, 0xf1, 0xfd, 0x7a, 0xdf, + 0x2e, 0x84, 0xf5, 0xf7, 0x53, 0x0e, 0xda, 0x7c, 0x9e, 0xf2, 0x5e, 0x28, + 0xac, 0xdc, 0xd1, 0x2c, 0xa8, 0x3d, 0x52, 0x00, 0x73, 0x7d, 0x57, 0x92, + 0xdf, 0xb0, 0x8b, 0x3c, 0x5d, 0xe1, 0xb7, 0x5c, 0xdb, 0xd5, 0x1d, 0x16, + 0xef, 0x5c, 0x90, 0x74, 0x75, 0x29, 0x9b, 0x5c, 0xae, 0x14, 0xc9, 0x53, + 0xed, 0x57, 0xc3, 0xda, 0xaf, 0x92, 0xc7, 0xc3, 0xe0, 0xf1, 0x5f, 0xeb, + 0x75, 0x61, 0xfb, 0x8c, 0xba, 0x0b, 0x9e, 0x89, 0xf1, 0x6c, 0xea, 0x31, + 0x35, 0x17, 0xda, 0x68, 0xb4, 0x7d, 0x47, 0x50, 0xe9, 0xae, 0xfa, 0x46, + 0x1e, 0xf2, 0xc9, 0x6f, 0xde, 0x61, 0x5f, 0x4b, 0xfc, 0xb6, 0x7d, 0x58, + 0x7d, 0x67, 0x52, 0xae, 0x70, 0x5d, 0xf9, 0x4d, 0xfb, 0x68, 0x9d, 0x3c, + 0x06, 0xf5, 0x58, 0x9b, 0x5a, 0x25, 0xea, 0xad, 0x3b, 0xbf, 0x51, 0x29, + 0x57, 0xfc, 0xfb, 0x9d, 0x1b, 0x96, 0xa8, 0x13, 0xa2, 0x62, 0x6c, 0xef, + 0x3b, 0x9b, 0xb2, 0xfa, 0x6e, 0x25, 0xc1, 0xef, 0x2e, 0xe1, 0x3b, 0x76, + 0xe1, 0x99, 0x67, 0xba, 0xbb, 0x91, 0xc2, 0xe6, 0x54, 0xc6, 0x91, 0x3e, + 0x2c, 0x39, 0xb5, 0xe7, 0xd6, 0x8c, 0xfc, 0x5e, 0x35, 0x76, 0xb1, 0xf2, + 0x80, 0xec, 0x39, 0xf9, 0x10, 0xbf, 0xed, 0x51, 0xdf, 0xe5, 0x67, 0x1d, + 0xd2, 0x18, 0x93, 0x09, 0x35, 0xef, 0x42, 0xed, 0x9b, 0x11, 0xc5, 0xfb, + 0x5c, 0x2b, 0xd7, 0xb4, 0x50, 0x69, 0x06, 0x8d, 0x01, 0x7d, 0xc7, 0x93, + 0x58, 0xdc, 0x9f, 0x7f, 0x94, 0xf7, 0x06, 0x5d, 0x9e, 0xdd, 0xed, 0x29, + 0xf1, 0x0e, 0x67, 0x52, 0xc7, 0xe8, 0xdc, 0xb7, 0xe3, 0xd9, 0x00, 0x65, + 0xdc, 0x4a, 0x8d, 0xc3, 0xfa, 0x87, 0x25, 0xce, 0x73, 0x65, 0x3d, 0x97, + 0xe6, 0xba, 0xb9, 0xf0, 0xde, 0xaa, 0x37, 0x1f, 0x7e, 0x0b, 0x93, 0x2f, + 0xd5, 0x7f, 0xc7, 0xa3, 0xbe, 0x11, 0x57, 0xdf, 0xcd, 0x8c, 0x57, 0x3e, + 0x21, 0x1f, 0x2b, 0x6d, 0xd4, 0xdf, 0xf0, 0x44, 0xe4, 0x63, 0x95, 0xd7, + 0x14, 0x4f, 0xf3, 0xea, 0xfb, 0xa3, 0xb0, 0x5e, 0xb3, 0x98, 0xea, 0xa3, + 0xf6, 0x1d, 0x92, 0x55, 0xf7, 0x4d, 0x4a, 0x58, 0xc6, 0xe7, 0x7f, 0xd9, + 0xb7, 0x48, 0x8f, 0x08, 0xbf, 0x47, 0xb9, 0xe4, 0x4c, 0xca, 0xe3, 0x73, + 0xae, 0x7b, 0x97, 0x43, 0x5c, 0xb7, 0x41, 0x96, 0x63, 0xa3, 0x3b, 0xbe, + 0x67, 0xb7, 0x05, 0xca, 0x33, 0x8d, 0xb0, 0xd7, 0xc4, 0x12, 0x12, 0x65, + 0x7e, 0x7e, 0x86, 0x7a, 0x1a, 0xc2, 0x1c, 0x2d, 0xf3, 0xaa, 0x7c, 0xa6, + 0x95, 0x7b, 0x5e, 0x77, 0x21, 0x8e, 0xfc, 0xb8, 0xe3, 0xd9, 0xe5, 0xcf, + 0x2d, 0xec, 0x94, 0xcf, 0x55, 0x22, 0x81, 0xf2, 0x14, 0xef, 0xfa, 0x59, + 0xc3, 0x73, 0x92, 0x44, 0x3d, 0xf6, 0x0f, 0x79, 0x89, 0x6f, 0x96, 0xa7, + 0x8e, 0xfd, 0xc2, 0xbd, 0x6a, 0xe3, 0x3d, 0x6c, 0xcd, 0xb2, 0xe3, 0xef, + 0xeb, 0x21, 0x86, 0x3f, 0xc2, 0x7a, 0x9b, 0x21, 0x07, 0xf0, 0xdb, 0xd0, + 0x39, 0xc6, 0x98, 0x57, 0xb5, 0xdd, 0x32, 0x8e, 0xdc, 0x2c, 0x57, 0x57, + 0xee, 0x0a, 0x5f, 0x86, 0x6c, 0x27, 0x3c, 0xfe, 0xab, 0x7d, 0xf0, 0x03, + 0x12, 0xfc, 0x22, 0xfc, 0xc4, 0x17, 0x1b, 0x94, 0x6d, 0xa7, 0x3f, 0x43, + 0xfc, 0x81, 0x18, 0x23, 0x84, 0x7e, 0x1e, 0x6c, 0xf5, 0x64, 0x76, 0x52, + 0xe4, 0xcb, 0x4d, 0x92, 0x69, 0x65, 0x0c, 0x2b, 0xbf, 0xc2, 0x7e, 0xd5, + 0xeb, 0x59, 0x4a, 0xbe, 0x42, 0x1d, 0xaf, 0x72, 0x2e, 0xc9, 0xf8, 0x8f, + 0xe5, 0x93, 0x32, 0x1e, 0xe7, 0x5c, 0x1e, 0x91, 0xc2, 0xdc, 0x63, 0xf8, + 0x71, 0x9e, 0xa4, 0xfb, 0x1f, 0xe8, 0x7b, 0x04, 0xa3, 0x52, 0x9c, 0x4a, + 0xcb, 0xc4, 0xec, 0x5e, 0x7e, 0xa3, 0x3b, 0x7c, 0x97, 0x3a, 0x5f, 0xb3, + 0xe2, 0xc9, 0x40, 0x6f, 0x62, 0x82, 0xf7, 0x26, 0xd4, 0x7c, 0xf6, 0x62, + 0x3e, 0xdf, 0x6a, 0xe5, 0xdd, 0xf3, 0xab, 0xb0, 0xbf, 0xc6, 0x71, 0xca, + 0xa1, 0x65, 0x76, 0x06, 0x98, 0xdf, 0x8d, 0xd8, 0x99, 0x65, 0xbb, 0x25, + 0x78, 0x64, 0xc5, 0xce, 0xa3, 0x5c, 0x9f, 0xf3, 0xaa, 0xf6, 0xff, 0x11, + 0x6d, 0x51, 0xef, 0x88, 0xdf, 0xd6, 0xaf, 0xc3, 0xb6, 0x9c, 0xe7, 0x4e, + 0xc4, 0xec, 0x3e, 0x5d, 0x90, 0xc3, 0x78, 0x3d, 0xbf, 0xa3, 0x6b, 0xf8, + 0x1d, 0x22, 0xde, 0x04, 0xbf, 0xc8, 0xe3, 0xa0, 0xe6, 0xf1, 0x9b, 0xe8, + 0xdf, 0x5f, 0x83, 0xbb, 0x50, 0x66, 0xea, 0x6f, 0x03, 0xdf, 0x0a, 0xdf, + 0xc9, 0x73, 0xd6, 0x7f, 0xb0, 0xd5, 0x93, 0x35, 0xd2, 0xb3, 0x1e, 0xcf, + 0x3b, 0xdb, 0xbc, 0x75, 0xd9, 0x0d, 0x7e, 0xf1, 0x4e, 0x67, 0xaf, 0xfa, + 0x4e, 0x20, 0x33, 0xb6, 0x1b, 0xb2, 0xe3, 0xcf, 0xab, 0x17, 0x32, 0xc6, + 0x33, 0x0b, 0xd6, 0xaf, 0xe7, 0x89, 0xe7, 0xf7, 0x82, 0xdc, 0x77, 0xb0, + 0x39, 0x57, 0x60, 0xc2, 0x2f, 0xab, 0xef, 0x82, 0x60, 0x27, 0xdf, 0xb6, + 0xf2, 0x5d, 0xd0, 0xf5, 0xd7, 0x78, 0xa0, 0xcd, 0xf3, 0x51, 0x26, 0x78, + 0xd2, 0xa2, 0xdb, 0xec, 0x06, 0x3e, 0xe5, 0x5e, 0x6c, 0x32, 0xfe, 0xa0, + 0xf8, 0xe3, 0xb8, 0xdb, 0x19, 0x73, 0x0e, 0xf6, 0xf7, 0x22, 0xbe, 0x56, + 0xf7, 0x65, 0xe2, 0xbc, 0x7f, 0x93, 0x0c, 0xec, 0x56, 0x77, 0x27, 0x2e, + 0xac, 0xfa, 0xb6, 0x2b, 0x25, 0x4f, 0xd5, 0x64, 0x65, 0xf8, 0x27, 0x62, + 0x49, 0xe2, 0x26, 0xca, 0x0a, 0xfb, 0xdd, 0xcb, 0x79, 0xc6, 0x1f, 0x52, + 0xf3, 0x34, 0x11, 0xc3, 0xf1, 0x9e, 0x83, 0x19, 0x28, 0xcf, 0x72, 0xdd, + 0x91, 0x2e, 0xf0, 0xd9, 0x3f, 0x6b, 0x55, 0x76, 0x05, 0xe3, 0xb2, 0x8c, + 0xb6, 0x91, 0xef, 0xd3, 0xfa, 0x2c, 0xf6, 0xc3, 0x6d, 0xbc, 0x0f, 0x90, + 0x47, 0xd9, 0xdc, 0xc2, 0xfa, 0xb4, 0x7d, 0x5c, 0xc9, 0xc1, 0x23, 0xe0, + 0xfb, 0x1f, 0xa3, 0xee, 0x63, 0x48, 0x39, 0xc7, 0xf4, 0xca, 0xba, 0x93, + 0xdf, 0x1f, 0x90, 0x01, 0xc8, 0x05, 0xf3, 0x8f, 0x48, 0x51, 0xdd, 0x63, + 0x42, 0x3a, 0xc7, 0x67, 0xda, 0x7a, 0x5b, 0xfb, 0x53, 0xd2, 0xb2, 0x5b, + 0x7f, 0x4f, 0xe6, 0xcb, 0xd3, 0x2e, 0xdd, 0x6e, 0x6c, 0x85, 0x57, 0x0f, + 0x5d, 0x83, 0x37, 0xc2, 0x2b, 0x78, 0xc3, 0x1b, 0xeb, 0xf1, 0x36, 0x1f, + 0x6b, 0x78, 0x73, 0xf0, 0xb0, 0x86, 0x27, 0xe7, 0x7b, 0x25, 0x04, 0x39, + 0x0e, 0xd6, 0xe4, 0x18, 0xb8, 0xc7, 0xd3, 0x99, 0x09, 0x9e, 0x21, 0x2a, + 0x3e, 0x53, 0x0e, 0x29, 0xbf, 0x5c, 0xc7, 0xfa, 0xb5, 0x7e, 0xcf, 0x2f, + 0x59, 0xeb, 0x97, 0xdb, 0x7c, 0xfc, 0xf0, 0x77, 0xd3, 0x83, 0x0b, 0x6d, + 0x35, 0x3d, 0xb8, 0xf9, 0x37, 0xa4, 0x07, 0x6b, 0xe5, 0xb2, 0x5e, 0xa6, + 0x4c, 0xc8, 0x13, 0xd7, 0x8b, 0xf2, 0x44, 0x39, 0x22, 0x2f, 0x69, 0x4f, + 0x1b, 0x19, 0x3b, 0xc5, 0xaf, 0xa8, 0xef, 0x36, 0x26, 0x61, 0x83, 0xda, + 0x02, 0x73, 0x73, 0x31, 0x29, 0x2e, 0xbc, 0x4f, 0xc9, 0xf4, 0x53, 0x55, + 0xda, 0xa5, 0xeb, 0xcd, 0x7d, 0xb5, 0xcd, 0xcd, 0xaf, 0xb1, 0xb9, 0xf9, + 0x15, 0x9b, 0xdb, 0xaa, 0xe3, 0xa5, 0xbf, 0x8b, 0xcd, 0x8d, 0xd5, 0x9d, + 0xcb, 0xf8, 0x67, 0x32, 0x12, 0xc8, 0xf6, 0x44, 0x65, 0x07, 0xfc, 0xc8, + 0xf0, 0xd4, 0x4e, 0xf9, 0x97, 0x53, 0x93, 0xea, 0x8e, 0xd2, 0x5f, 0x38, + 0xc9, 0xf8, 0x03, 0x01, 0x57, 0x3e, 0x80, 0x78, 0x77, 0xbc, 0xa3, 0x41, + 0x76, 0xbc, 0x4b, 0x9d, 0x35, 0x9a, 0xd9, 0x40, 0xbb, 0x70, 0x17, 0x3c, + 0xe7, 0x58, 0x4e, 0x22, 0xc0, 0xfb, 0x6a, 0x8d, 0x32, 0x1e, 0x6b, 0x96, + 0x9d, 0xc0, 0x4e, 0x85, 0x1b, 0x1c, 0xf5, 0x2d, 0x79, 0x46, 0x9d, 0xe5, + 0xdc, 0xb2, 0xd9, 0x1b, 0x17, 0x7c, 0x68, 0x31, 0xe5, 0xab, 0xd5, 0x5b, + 0xd4, 0x77, 0xd1, 0x17, 0x4a, 0xd5, 0xd6, 0xd5, 0x79, 0x3e, 0xff, 0x7b, + 0xd4, 0x89, 0x81, 0x57, 0xf5, 0x77, 0x7f, 0x82, 0x8a, 0x9f, 0xc5, 0xb9, + 0x31, 0x75, 0xa7, 0xea, 0x4a, 0x90, 0xfc, 0x52, 0x71, 0x53, 0x3c, 0x1b, + 0x04, 0xc6, 0x99, 0x01, 0x92, 0xb6, 0x19, 0xf3, 0x69, 0xfc, 0x09, 0xfb, + 0xbf, 0x47, 0x9d, 0xed, 0x2e, 0x81, 0x37, 0xae, 0xda, 0xfb, 0xcd, 0xc7, + 0x88, 0xeb, 0x6b, 0xf7, 0x87, 0xaf, 0xc5, 0xf7, 0xde, 0xb7, 0x67, 0xfa, + 0x1c, 0x42, 0xef, 0x15, 0xe9, 0x18, 0x5c, 0x9d, 0xab, 0xad, 0xf7, 0x7f, + 0x29, 0x88, 0xf5, 0xf8, 0x7f, 0x0f, 0x88, 0xed, 0xac, 0xc3, 0x73, 0xe2, + 0xa8, 0x38, 0x30, 0x43, 0xfe, 0x96, 0xb1, 0x4e, 0xd3, 0x71, 0xdf, 0x9f, + 0x07, 0x3a, 0xcf, 0xd6, 0xc7, 0x81, 0xec, 0x23, 0xa2, 0xee, 0x63, 0xd4, + 0xfe, 0x0f, 0x0e, 0xf7, 0x77, 0x32, 0x81, 0x7b, 0x4a, 0x93, 0x12, 0x3c, + 0x3a, 0x2a, 0xa1, 0x69, 0xee, 0xa5, 0x67, 0xa4, 0x18, 0x73, 0xe5, 0x63, + 0xce, 0xea, 0xd8, 0xa4, 0xd3, 0x58, 0x4b, 0xfb, 0x23, 0x32, 0x78, 0xf2, + 0x31, 0x09, 0x1f, 0xe5, 0xbb, 0x55, 0xe7, 0x28, 0xb0, 0x47, 0x1b, 0x64, + 0x2e, 0xc6, 0xfd, 0xe4, 0xb0, 0x3a, 0x97, 0x5e, 0x1e, 0x7b, 0x2d, 0x5c, + 0x04, 0x56, 0xc8, 0x2b, 0xdb, 0x82, 0x74, 0x25, 0x96, 0x38, 0xbc, 0x99, + 0x3a, 0x85, 0x18, 0x33, 0x30, 0x3e, 0x17, 0x56, 0xf7, 0x83, 0x96, 0x63, + 0xac, 0x8b, 0xf8, 0xfd, 0x28, 0x71, 0x06, 0x6c, 0xc7, 0xa8, 0x44, 0x99, + 0x0f, 0x1e, 0xad, 0xe1, 0x0c, 0xda, 0x84, 0x41, 0x27, 0x26, 0xa1, 0x53, + 0xde, 0xdc, 0xf9, 0x8f, 0x95, 0x8c, 0x13, 0x3b, 0x25, 0x38, 0xcd, 0xe7, + 0xfa, 0x78, 0x88, 0xd8, 0x1d, 0xbe, 0xe1, 0xec, 0x67, 0xd1, 0x1f, 0xdf, + 0x65, 0xf4, 0x37, 0xba, 0xc8, 0x97, 0xff, 0xb6, 0xff, 0x43, 0x81, 0xb2, + 0xff, 0xff, 0x01, 0xe6, 0x8e, 0x9a, 0x21, 0xc0, 0x4e, 0x00, 0x00, 0x00 }; static const u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 }; static const u32 bnx2_COM_b06FwRodata[(0x14/4) + 1] = { - 0x08000f04, 0x08000f4c, 0x08000f80, 0x08000fcc, 0x08001000, 0x00000000 + 0x08000e7c, 0x08000ec4, 0x08000ef8, 0x08000f44, 0x08000f78, 0x00000000 }; static struct fw_info bnx2_com_fw_06 = { - /* Firmware version: 4.0.5 */ + /* Firmware version: 4.4.2 */ .ver_major = 0x4, - .ver_minor = 0x0, - .ver_fix = 0x5, + .ver_minor = 0x4, + .ver_fix = 0x2, .start_addr = 0x080000f8, .text_addr = 0x08000000, - .text_len = 0x4eac, + .text_len = 0x4ebc, .text_index = 0x0, .gz_text = bnx2_COM_b06FwText, .gz_text_len = sizeof(bnx2_COM_b06FwText), @@ -872,15 +872,15 @@ static struct fw_info bnx2_com_fw_06 = { .data_index = 0x0, .data = bnx2_COM_b06FwData, - .sbss_addr = 0x08004ee0, + .sbss_addr = 0x08004f00, .sbss_len = 0x38, .sbss_index = 0x0, - .bss_addr = 0x08004f18, + .bss_addr = 0x08004f38, .bss_len = 0xbc, .bss_index = 0x0, - .rodata_addr = 0x08004eac, + .rodata_addr = 0x08004ebc, .rodata_len = 0x14, .rodata_index = 0x0, .rodata = bnx2_COM_b06FwRodata, @@ -902,1231 +902,1232 @@ static const struct cpu_reg cpu_reg_com = { .mips_view_base = 0x8000000, }; - static u8 bnx2_CP_b06FwText[] = { - 0x9d, 0xbc, 0x0d, 0x78, 0x13, 0xe7, 0x99, 0x2e, 0x7c, 0xcf, 0x48, 0xb2, - 0x65, 0x5b, 0xb6, 0xc7, 0xb6, 0x0c, 0x22, 0x65, 0x41, 0x83, 0x47, 0x20, - 0x62, 0x27, 0x1d, 0x81, 0x49, 0x94, 0xac, 0x36, 0xa8, 0xc6, 0x01, 0x93, - 0x90, 0xc6, 0x34, 0xb4, 0x75, 0x7a, 0xd2, 0x8d, 0x62, 0x0c, 0x21, 0x84, - 0x10, 0x67, 0x9b, 0x9e, 0xe3, 0x7c, 0x5f, 0xce, 0x5a, 0x35, 0x06, 0x0c, - 0xc8, 0x96, 0x31, 0x0e, 0x90, 0xfd, 0x7a, 0x9d, 0x18, 0x6c, 0x30, 0x49, - 0x65, 0x8b, 0x34, 0x74, 0x97, 0xf4, 0xa3, 0x45, 0x07, 0xf2, 0xe3, 0xfc, - 0x35, 0xa4, 0xed, 0x76, 0xdb, 0x3d, 0x39, 0x89, 0x0f, 0x25, 0x84, 0xb4, - 0xdd, 0xfc, 0xb4, 0xdd, 0x2d, 0x69, 0x9b, 0xcc, 0x77, 0x3f, 0x23, 0x09, - 0x0c, 0x4d, 0x7f, 0xf6, 0xf3, 0x75, 0xcd, 0x65, 0xcd, 0xcc, 0xfb, 0xf3, - 0xbc, 0xcf, 0xfb, 0x3c, 0xf7, 0x73, 0x3f, 0xef, 0xbc, 0x33, 0xb3, 0x80, - 0x62, 0xe4, 0xfe, 0x4a, 0x79, 0x5c, 0x5d, 0xdf, 0xbe, 0x1a, 0x8b, 0xae, - 0x36, 0xe5, 0xdc, 0xe9, 0x82, 0x13, 0x7f, 0xe1, 0x9f, 0xff, 0x2f, 0x2d, - 0x38, 0xe5, 0xcf, 0x01, 0x68, 0xf9, 0x7e, 0xe5, 0x80, 0x5b, 0x8d, 0x3c, - 0xf3, 0x5f, 0x1a, 0x0c, 0xb8, 0x1d, 0x91, 0x9e, 0xd6, 0xd5, 0x06, 0x10, - 0x4d, 0xd5, 0xfa, 0x97, 0xe0, 0x23, 0x2b, 0xee, 0x75, 0x42, 0xae, 0xff, - 0x55, 0xe4, 0xf7, 0x9d, 0xdf, 0xb9, 0x56, 0x7f, 0x7f, 0xc8, 0x01, 0xb7, - 0x16, 0xe9, 0x80, 0x36, 0x17, 0xee, 0x99, 0xac, 0xf3, 0xf5, 0x79, 0xdb, - 0x15, 0x94, 0xe5, 0xdb, 0x3a, 0x67, 0x7d, 0x67, 0x9e, 0x2f, 0x56, 0x14, - 0xd1, 0x70, 0x3c, 0x8d, 0xe6, 0xba, 0xde, 0x4e, 0xab, 0xd4, 0x08, 0xc1, - 0x6d, 0x18, 0x2d, 0xbd, 0x8a, 0x27, 0xbc, 0x7e, 0x11, 0x3c, 0x85, 0x06, - 0xe2, 0x57, 0x44, 0xd0, 0x7c, 0xe5, 0x58, 0x71, 0xdc, 0x19, 0x71, 0xa3, - 0x29, 0xed, 0x8e, 0x7f, 0x2a, 0x62, 0x60, 0x59, 0xfa, 0xfa, 0x62, 0x94, - 0xb9, 0xd1, 0x9d, 0xfe, 0xa8, 0x28, 0xdb, 0x5e, 0x73, 0xee, 0xff, 0xec, - 0xaa, 0xec, 0xff, 0x69, 0x31, 0x67, 0x04, 0xd8, 0x9c, 0xb0, 0xac, 0x82, - 0xc8, 0x6d, 0xb7, 0xa9, 0x11, 0xc3, 0x77, 0x10, 0x8b, 0xd1, 0xaa, 0xe1, - 0xe1, 0x2d, 0xf5, 0xbf, 0x54, 0x4e, 0x0c, 0xb2, 0xe1, 0x51, 0x07, 0xa2, - 0xda, 0x33, 0xfc, 0x3f, 0x6b, 0x56, 0x4b, 0xd8, 0xc0, 0xde, 0xd1, 0xf3, - 0xbc, 0xee, 0xb4, 0xaf, 0x6d, 0xda, 0x33, 0x6b, 0xd6, 0xed, 0xe1, 0x67, - 0xf0, 0xe8, 0xa8, 0xfc, 0xbe, 0x1b, 0x9d, 0x75, 0x0a, 0x26, 0x6f, 0x5b, - 0x0b, 0x87, 0x61, 0xa0, 0x7b, 0x8f, 0xe2, 0xec, 0xaa, 0x53, 0x11, 0xf5, - 0xea, 0xc1, 0x18, 0x95, 0xef, 0x34, 0x10, 0x2b, 0x8c, 0x84, 0x9d, 0xef, - 0x24, 0x22, 0x9a, 0xc3, 0xb0, 0xac, 0x60, 0x68, 0x3a, 0x1c, 0x15, 0x96, - 0xf5, 0xb4, 0xe9, 0x81, 0xff, 0x8b, 0xcf, 0x21, 0x3e, 0xdc, 0x0c, 0xd5, - 0x78, 0x0e, 0x5d, 0xc3, 0xcf, 0xe1, 0xb1, 0x5d, 0xc5, 0x98, 0xac, 0xe2, - 0x78, 0x93, 0x3e, 0x7c, 0x67, 0x9e, 0xf4, 0x2d, 0x72, 0xd4, 0xf1, 0x70, - 0x63, 0xd2, 0xf1, 0x06, 0xff, 0x4b, 0x99, 0xf3, 0xd6, 0xe4, 0xf4, 0x8b, - 0x65, 0x36, 0xb3, 0x4c, 0xf7, 0x65, 0x65, 0xe2, 0xc3, 0x11, 0xbc, 0x94, - 0x50, 0xb0, 0x3e, 0x54, 0x86, 0x68, 0x85, 0x8c, 0xd7, 0xb2, 0x46, 0xcd, - 0xb3, 0xd6, 0xa4, 0x26, 0x7d, 0x4d, 0xe0, 0x65, 0xde, 0xdb, 0x12, 0x3a, - 0x63, 0x65, 0xbc, 0xd2, 0x5e, 0x3b, 0x6d, 0x67, 0x25, 0xaf, 0x3b, 0x91, - 0x4c, 0x20, 0x56, 0x16, 0xb9, 0x8d, 0xe7, 0xba, 0xf9, 0xae, 0xe2, 0x76, - 0xbf, 0x97, 0x70, 0x7f, 0xb1, 0xd4, 0x50, 0x1f, 0x2c, 0xa7, 0x01, 0xbd, - 0x42, 0x99, 0x8f, 0x9a, 0x6b, 0xe1, 0x32, 0x1e, 0x10, 0x5b, 0xe3, 0xb8, - 0x7e, 0x68, 0x61, 0x7a, 0xbe, 0xbe, 0xb4, 0xeb, 0xc6, 0x96, 0xa4, 0x65, - 0x6d, 0x33, 0xa3, 0xd7, 0x15, 0xd1, 0x20, 0x4e, 0x26, 0x9a, 0xe1, 0x8e, - 0x04, 0xfc, 0xe7, 0x10, 0xc6, 0x92, 0xb4, 0x17, 0xcf, 0x26, 0xe0, 0x6c, - 0x98, 0xe7, 0x45, 0x57, 0x3a, 0x82, 0x1b, 0xd3, 0x26, 0x1a, 0xd3, 0x7f, - 0xde, 0xb2, 0x6e, 0x4e, 0xfa, 0x39, 0x86, 0x8f, 0xac, 0xec, 0x18, 0x64, - 0x7c, 0xd9, 0xff, 0xdd, 0xc9, 0x2b, 0xb0, 0x9d, 0x73, 0xb4, 0x95, 0xf3, - 0xb7, 0x3c, 0x94, 0x89, 0x16, 0x41, 0x37, 0xcf, 0x21, 0x82, 0xa5, 0x69, - 0x83, 0x73, 0x1a, 0xc1, 0x92, 0x64, 0x8d, 0x36, 0x8c, 0xf9, 0x88, 0xfa, - 0xb2, 0x36, 0xbd, 0x83, 0xe3, 0x6d, 0x0d, 0x34, 0xa3, 0x94, 0x36, 0x92, - 0x5a, 0x14, 0x46, 0x03, 0xfb, 0x5f, 0xf1, 0x17, 0xf4, 0x7f, 0x2b, 0xfb, - 0x7f, 0x97, 0xfd, 0x67, 0xec, 0xfe, 0xe1, 0xbc, 0x89, 0xe7, 0x6e, 0xda, - 0xe3, 0xf6, 0x94, 0xd3, 0xb9, 0x3c, 0xe9, 0xc5, 0xb6, 0x94, 0x49, 0x9b, - 0x93, 0x5b, 0x3e, 0x6c, 0x19, 0x9c, 0x89, 0xad, 0x83, 0xba, 0xef, 0x79, - 0xfe, 0xde, 0x34, 0x72, 0x05, 0x36, 0x0f, 0x2a, 0xd8, 0x6f, 0x5c, 0x81, - 0x2e, 0xfe, 0xde, 0x3b, 0x38, 0x0b, 0x8f, 0x0e, 0x3a, 0x10, 0xae, 0xba, - 0x74, 0x1c, 0x93, 0x8e, 0x2b, 0x10, 0x1f, 0xf1, 0xa3, 0x2b, 0xf1, 0xa2, - 0xad, 0xc3, 0xd2, 0xc8, 0xff, 0x9b, 0xf7, 0x63, 0xfa, 0x8e, 0x1f, 0xab, - 0x13, 0x1a, 0xba, 0x92, 0x0e, 0xb1, 0x4b, 0xfe, 0xfd, 0x92, 0xf7, 0x34, - 0x6c, 0x4a, 0xe7, 0xeb, 0x8b, 0x9f, 0xf9, 0xd1, 0x90, 0x98, 0xa0, 0x9f, - 0xd4, 0xd3, 0x47, 0x4c, 0x7c, 0x37, 0x5d, 0x87, 0x7f, 0x4a, 0x07, 0xf1, - 0x8f, 0xd4, 0xc3, 0xb7, 0xd2, 0x7e, 0x1c, 0x49, 0xcf, 0xc4, 0x53, 0x69, - 0x1f, 0xbe, 0x49, 0xfd, 0x3f, 0x99, 0x6e, 0xa6, 0xed, 0x6a, 0x38, 0x9c, - 0x16, 0xfd, 0x15, 0x50, 0xde, 0x62, 0x6c, 0x1a, 0xac, 0x09, 0x9e, 0xa4, - 0x6d, 0xfc, 0xa3, 0x79, 0x13, 0x32, 0x95, 0xf5, 0xb6, 0x4d, 0x6d, 0xe3, - 0xf5, 0xed, 0x83, 0x35, 0xd1, 0x2b, 0x15, 0xcb, 0x52, 0x43, 0xb5, 0xe1, - 0x13, 0xaa, 0x8a, 0x49, 0xaf, 0xee, 0xcf, 0xa8, 0xba, 0x3f, 0x0a, 0x17, - 0x12, 0xb4, 0xed, 0x78, 0xb5, 0x3e, 0x14, 0xa7, 0x4d, 0x78, 0x8d, 0x7d, - 0x40, 0x99, 0xee, 0x8f, 0xab, 0x6e, 0x6c, 0x4d, 0xea, 0x7b, 0xe3, 0xaa, - 0x07, 0xf1, 0x74, 0x31, 0xfe, 0x6d, 0x50, 0xef, 0x89, 0xab, 0x9f, 0x45, - 0xbc, 0xd2, 0xb2, 0xbe, 0x19, 0x42, 0xfb, 0xf4, 0x08, 0xa2, 0xd5, 0x11, - 0xc4, 0x66, 0x45, 0xbc, 0x48, 0x26, 0x81, 0x77, 0x7b, 0x0d, 0xdf, 0xbf, - 0x28, 0xcd, 0xf8, 0x6a, 0xb3, 0xee, 0xf7, 0xab, 0xb5, 0xf1, 0x61, 0x75, - 0x11, 0x5d, 0x12, 0x7e, 0x5f, 0x64, 0x19, 0x3a, 0xec, 0x6b, 0x0a, 0x34, - 0xc3, 0x83, 0x4d, 0xc9, 0xeb, 0x10, 0xf3, 0xd6, 0xb4, 0xec, 0x54, 0x6b, - 0xce, 0x9b, 0xaa, 0x3e, 0xd1, 0xac, 0x5a, 0xd6, 0x07, 0x0b, 0xdf, 0xb5, - 0xfc, 0xd3, 0x2c, 0x6b, 0xc1, 0x42, 0xe9, 0xd3, 0x8f, 0x8a, 0x88, 0x89, - 0x95, 0xf6, 0x1c, 0x14, 0xe3, 0xec, 0x60, 0x25, 0xfb, 0xd0, 0xf0, 0xcf, - 0xd7, 0xea, 0xc1, 0xb5, 0x6a, 0x31, 0xde, 0x1a, 0x29, 0xc6, 0x69, 0x8e, - 0xe7, 0x97, 0x83, 0x3e, 0xfc, 0x7a, 0xd0, 0xb2, 0xbe, 0x68, 0xfe, 0x35, - 0x06, 0x2a, 0xfb, 0xf1, 0x4f, 0xe3, 0x5e, 0xfc, 0x1b, 0x75, 0x7b, 0x26, - 0x11, 0x7d, 0xa0, 0x0a, 0x7a, 0x74, 0x5c, 0x39, 0x79, 0x67, 0x19, 0x6a, - 0x9b, 0xcb, 0x14, 0xbd, 0x69, 0x07, 0x74, 0xdf, 0x95, 0x8a, 0x17, 0xe7, - 0x52, 0x1a, 0x7e, 0x9a, 0xaa, 0x09, 0xff, 0x80, 0x7d, 0xfe, 0x87, 0xf9, - 0xb4, 0x95, 0x99, 0x26, 0x7a, 0x13, 0x1d, 0x51, 0xcf, 0x49, 0xea, 0x39, - 0x49, 0x3d, 0x27, 0xa9, 0x67, 0xca, 0x70, 0x24, 0x49, 0x3d, 0x53, 0x77, - 0xdf, 0xa4, 0x4d, 0x3c, 0x99, 0xa4, 0x8e, 0x93, 0x32, 0x47, 0x61, 0xfa, - 0xe7, 0xa7, 0xf0, 0xf7, 0xf6, 0xdc, 0xbd, 0x6c, 0xfd, 0x37, 0xaf, 0x8c, - 0xe9, 0xfe, 0x69, 0x59, 0xfc, 0x91, 0xb1, 0xbd, 0x64, 0xc5, 0x34, 0x19, - 0x97, 0x8c, 0xcf, 0xd6, 0x9f, 0xbf, 0x5d, 0xf9, 0xaa, 0x82, 0x62, 0xcb, - 0xda, 0x65, 0xe6, 0xee, 0x7b, 0xf3, 0xe3, 0xfb, 0x8c, 0x92, 0xb5, 0x8b, - 0x7f, 0x72, 0x53, 0xdf, 0xc1, 0xa8, 0xba, 0x88, 0xe7, 0x7a, 0x3c, 0x8a, - 0x9b, 0x0a, 0x2f, 0x3d, 0xbf, 0xb6, 0x5a, 0xe6, 0xc3, 0x7f, 0xe1, 0x9c, - 0xf6, 0x64, 0xf7, 0xf7, 0x45, 0x9e, 0xcb, 0x58, 0x04, 0x53, 0xc5, 0x06, - 0xbc, 0xb4, 0x97, 0x45, 0xb9, 0x7b, 0x88, 0xab, 0x91, 0x76, 0x34, 0xd7, - 0xef, 0xb5, 0xfb, 0x28, 0xe8, 0x13, 0xbb, 0x57, 0xf0, 0xee, 0x75, 0x0a, - 0x4e, 0x84, 0x0c, 0xda, 0xcc, 0x10, 0xfd, 0x1a, 0x28, 0xec, 0x83, 0xdb, - 0x13, 0x89, 0x20, 0xd1, 0x0b, 0x77, 0x51, 0x24, 0x8c, 0xf9, 0xbd, 0x35, - 0xeb, 0xce, 0x42, 0x0f, 0xf6, 0x2a, 0x7a, 0x33, 0x50, 0x6b, 0x8e, 0x51, - 0x8f, 0x57, 0x2a, 0xba, 0xbf, 0x40, 0x81, 0x5b, 0x61, 0xb9, 0x40, 0x6a, - 0x08, 0x5b, 0xd3, 0xf2, 0x3b, 0x0c, 0x23, 0xf5, 0xeb, 0x7c, 0x5f, 0xb4, - 0xeb, 0x76, 0xda, 0xf5, 0x59, 0x8e, 0x5d, 0xf7, 0x13, 0x1f, 0xdd, 0xae, - 0xc8, 0x3a, 0x1c, 0x48, 0xc0, 0x5d, 0x10, 0xd9, 0x80, 0xe7, 0x12, 0x1f, - 0x57, 0xe7, 0xcb, 0x29, 0x2c, 0xe7, 0x4f, 0x4d, 0x95, 0xe5, 0x0d, 0x2b, - 0xea, 0xcd, 0xca, 0x52, 0xdc, 0x37, 0x84, 0x1d, 0x49, 0xa9, 0x1b, 0xb1, - 0xeb, 0x3a, 0xd9, 0x47, 0x77, 0xa2, 0xa6, 0xe9, 0x66, 0x45, 0x0f, 0x3f, - 0x8e, 0xda, 0xe8, 0x3b, 0x9c, 0xc3, 0x2e, 0xe8, 0xe7, 0xd7, 0x21, 0x2b, - 0xcb, 0xbc, 0x54, 0x56, 0x8e, 0xc5, 0x29, 0x28, 0xb7, 0x27, 0xe1, 0xf1, - 0x19, 0x55, 0x39, 0x5f, 0x84, 0x72, 0x0b, 0xe7, 0x4f, 0x35, 0xfc, 0xb8, - 0x85, 0x36, 0xb4, 0x61, 0x97, 0x85, 0x4d, 0xa1, 0x4a, 0xfa, 0x5b, 0x33, - 0xca, 0x88, 0x87, 0x1b, 0x35, 0x44, 0xcb, 0x23, 0x61, 0xe5, 0xd6, 0xf4, - 0xce, 0x9c, 0xfe, 0x9f, 0xae, 0xa4, 0x7c, 0x4a, 0x63, 0xf2, 0xf2, 0xeb, - 0x1f, 0xe5, 0xc7, 0x77, 0xd9, 0xf5, 0xb9, 0x05, 0x9f, 0x5c, 0xbe, 0x56, - 0x1b, 0x81, 0xc2, 0x78, 0x51, 0x44, 0xfd, 0xea, 0x8c, 0xd2, 0xd1, 0xa0, - 0xcb, 0xbe, 0xe6, 0xc0, 0x90, 0x33, 0xea, 0x73, 0xe0, 0xf7, 0x56, 0x74, - 0x95, 0x5c, 0x2b, 0x46, 0xac, 0xb9, 0xd6, 0xe7, 0x44, 0x6d, 0x78, 0x33, - 0xfd, 0x6d, 0x72, 0x55, 0x03, 0xef, 0x05, 0xcc, 0x93, 0xa8, 0xf1, 0x6f, - 0x86, 0xfc, 0xfe, 0x90, 0x36, 0xd2, 0x20, 0x75, 0x59, 0x46, 0x6c, 0x4e, - 0xd7, 0x4e, 0xc2, 0x8b, 0xcd, 0xb4, 0xbf, 0xc2, 0x88, 0x6e, 0x2e, 0x73, - 0x38, 0x71, 0x88, 0x38, 0xec, 0x30, 0x7a, 0x50, 0xc8, 0x31, 0x32, 0x3e, - 0xe2, 0xf1, 0x04, 0xf0, 0x62, 0xbf, 0x85, 0x86, 0x90, 0x07, 0x4b, 0x6c, - 0xdb, 0x3c, 0xaa, 0xdc, 0x98, 0xfc, 0xd8, 0x1a, 0x72, 0x16, 0x45, 0xd5, - 0x48, 0xc0, 0x77, 0x9a, 0xd1, 0xbc, 0x20, 0x52, 0xab, 0x39, 0x11, 0x57, - 0x9a, 0xd2, 0xdd, 0xca, 0xf2, 0x74, 0x8f, 0xb2, 0xc4, 0xc6, 0x9c, 0xa3, - 0xca, 0xd2, 0xb4, 0x07, 0xa9, 0x7e, 0x05, 0x3b, 0x42, 0x94, 0xab, 0x3a, - 0x6b, 0xc7, 0xe9, 0x7e, 0x95, 0x18, 0xf9, 0x2e, 0x31, 0x52, 0x0f, 0x83, - 0x7d, 0x3f, 0x9d, 0xa8, 0xc4, 0x51, 0x62, 0xe1, 0x4f, 0x52, 0xe5, 0x2a, - 0x8a, 0xaf, 0xc0, 0x8f, 0x47, 0xca, 0x30, 0x36, 0x38, 0x8b, 0xbf, 0xeb, - 0xf0, 0xca, 0x88, 0x65, 0x75, 0x9b, 0x96, 0x75, 0xc0, 0x3c, 0xaa, 0x34, - 0xb0, 0xcf, 0xa8, 0x33, 0x1e, 0x2d, 0x8c, 0x04, 0xcc, 0xad, 0xec, 0xd3, - 0x11, 0x89, 0x2b, 0x51, 0xf6, 0x77, 0x23, 0xfb, 0x5b, 0x9a, 0xeb, 0x2f, - 0xdb, 0xaf, 0xc8, 0x22, 0xf5, 0xf2, 0x75, 0xc2, 0xac, 0x03, 0x1c, 0x4c, - 0x04, 0x82, 0xf9, 0x7a, 0x4b, 0x59, 0xe7, 0xc6, 0x0b, 0x75, 0x80, 0xe1, - 0x44, 0x90, 0x73, 0x2a, 0xb6, 0xee, 0x67, 0xec, 0xf9, 0x1a, 0x9c, 0x46, - 0x3d, 0x5a, 0x87, 0x85, 0x47, 0x84, 0xd5, 0xec, 0x3c, 0x49, 0xfc, 0x74, - 0xdb, 0x31, 0x6b, 0xd2, 0x21, 0x71, 0x34, 0x88, 0x5e, 0xfa, 0x75, 0x57, - 0x52, 0x6c, 0xbc, 0xfe, 0xcb, 0x89, 0x80, 0x82, 0x6f, 0x04, 0x32, 0xcd, - 0xa5, 0x28, 0xc7, 0xba, 0x90, 0xd8, 0xa6, 0xf9, 0xe5, 0xe7, 0x0c, 0x3d, - 0xbc, 0x42, 0xe1, 0x9c, 0x05, 0xf4, 0xa6, 0xa5, 0x0a, 0x10, 0x18, 0x03, - 0xce, 0xa4, 0xca, 0xb1, 0xda, 0x74, 0x40, 0xad, 0x08, 0xa2, 0x27, 0x3d, - 0x15, 0xd7, 0x4d, 0xe2, 0xb4, 0xb4, 0x17, 0xa4, 0x5f, 0x97, 0x60, 0x99, - 0x96, 0xb5, 0x69, 0x37, 0xdb, 0x76, 0x07, 0x32, 0x41, 0x95, 0xf1, 0xea, - 0x10, 0x2f, 0x9c, 0x64, 0x5c, 0x6a, 0x30, 0x5c, 0x68, 0xd3, 0xca, 0xd1, - 0x60, 0xfe, 0xd6, 0x5a, 0xb6, 0x4a, 0xee, 0x5d, 0xc4, 0xf7, 0x42, 0xf6, - 0xfb, 0xb6, 0xa1, 0xfb, 0x47, 0x79, 0x92, 0x49, 0x65, 0xaf, 0xc7, 0x19, - 0x73, 0x36, 0xb1, 0xdd, 0x2d, 0x6c, 0x77, 0xad, 0xa6, 0x47, 0xe3, 0x17, - 0xca, 0x65, 0x82, 0x0e, 0xe8, 0x9a, 0x94, 0x6d, 0x64, 0xbb, 0xab, 0xd9, - 0x6e, 0x8f, 0x26, 0xf2, 0xfd, 0xd6, 0x5a, 0xbb, 0x4a, 0xee, 0x65, 0xed, - 0x23, 0xdb, 0x6e, 0xbd, 0xb4, 0x6b, 0x8e, 0xe6, 0xfa, 0x3a, 0x91, 0x40, - 0xbf, 0x23, 0xc2, 0x18, 0x59, 0x1f, 0xf0, 0x77, 0x31, 0x5e, 0x36, 0x32, - 0x76, 0x64, 0x6d, 0x62, 0x6a, 0xbc, 0x42, 0xfc, 0x62, 0x19, 0xb9, 0x26, - 0xe5, 0xc4, 0xd6, 0x26, 0xa9, 0x67, 0x89, 0x2f, 0x3e, 0xea, 0x57, 0xb0, - 0xc5, 0x89, 0xc3, 0x09, 0xe2, 0x3f, 0xbe, 0x46, 0xbb, 0xf3, 0xa3, 0x39, - 0x5d, 0x83, 0xb6, 0x5d, 0x8c, 0x63, 0x66, 0x05, 0x6d, 0x3d, 0x6b, 0x6f, - 0xcb, 0xd8, 0xf6, 0xa4, 0xdd, 0x76, 0x5c, 0x69, 0x4e, 0xd7, 0x6a, 0x15, - 0x8c, 0x99, 0xc7, 0x2f, 0x60, 0xe7, 0xec, 0x68, 0x71, 0x24, 0xd0, 0xb4, - 0x9e, 0x93, 0xe4, 0x66, 0x7c, 0xfb, 0xce, 0xbc, 0x6e, 0xda, 0x45, 0x0f, - 0xed, 0x30, 0x3b, 0xbf, 0x4d, 0x62, 0x70, 0xc4, 0x38, 0xa8, 0x35, 0x58, - 0xbb, 0x4b, 0xfe, 0x93, 0x6b, 0xd4, 0x3f, 0xca, 0x6b, 0x35, 0x58, 0x3d, - 0xfc, 0x0d, 0xda, 0x99, 0xee, 0x13, 0x3b, 0xec, 0xba, 0x20, 0x97, 0xc8, - 0x24, 0xb2, 0x89, 0x4c, 0xff, 0x37, 0xcb, 0xcd, 0xa4, 0x7e, 0x04, 0x1b, - 0x2b, 0x29, 0xcf, 0x36, 0xf2, 0x99, 0xa3, 0xca, 0x67, 0x29, 0x4f, 0xc6, - 0xe5, 0xc5, 0x63, 0x49, 0x91, 0x47, 0x89, 0xce, 0x88, 0xcc, 0xc4, 0xf9, - 0x64, 0x20, 0xfe, 0x34, 0x44, 0xb6, 0x6e, 0xa5, 0x45, 0xea, 0x27, 0x7b, - 0x78, 0x2f, 0x2f, 0x23, 0xb4, 0x72, 0x5b, 0xb6, 0xac, 0x4c, 0xb7, 0x72, - 0xae, 0x5d, 0xc6, 0xfd, 0xa5, 0x28, 0x73, 0xd2, 0xd6, 0xa4, 0xed, 0x9f, - 0x59, 0x51, 0x6d, 0x13, 0xaf, 0x79, 0x39, 0x4f, 0x6e, 0xc6, 0x75, 0x3d, - 0x78, 0x8b, 0x43, 0x69, 0xf6, 0x48, 0xbc, 0xa6, 0x7d, 0xa6, 0x52, 0x4e, - 0x3c, 0x93, 0x58, 0xba, 0xb4, 0xc4, 0xb8, 0x1a, 0xdf, 0x18, 0xf1, 0x61, - 0x84, 0x73, 0xfb, 0x62, 0x42, 0xe2, 0xeb, 0x4c, 0x3c, 0x91, 0xf2, 0xe0, - 0x85, 0x84, 0x1f, 0x8f, 0x33, 0xfe, 0x4c, 0x24, 0x0c, 0x1c, 0x4a, 0x79, - 0xf1, 0x3c, 0xed, 0x79, 0x34, 0xe5, 0xa3, 0xbd, 0xd4, 0x61, 0x38, 0xd5, - 0x6c, 0x8f, 0xe1, 0xd9, 0xc4, 0xab, 0x32, 0xd6, 0xa0, 0x8c, 0x75, 0x8b, - 0x3d, 0xd6, 0x7c, 0x9c, 0x9f, 0x79, 0x61, 0x1e, 0x4e, 0x25, 0x6c, 0x1c, - 0xe8, 0x59, 0xe6, 0x90, 0x79, 0xa0, 0xcd, 0x0e, 0x08, 0x16, 0xe8, 0xfd, - 0x71, 0x58, 0xd8, 0x6f, 0xce, 0xa0, 0xff, 0xf7, 0x50, 0x5e, 0xea, 0x94, - 0xe3, 0x87, 0xab, 0x2c, 0x5a, 0x1a, 0x09, 0xc4, 0x7a, 0xa9, 0x77, 0x67, - 0x44, 0xf4, 0x90, 0xd5, 0xfb, 0x8a, 0xf4, 0x51, 0x45, 0xb8, 0xda, 0x95, - 0x03, 0x71, 0xab, 0xc4, 0x10, 0x7d, 0x07, 0x88, 0xb3, 0xc0, 0xfc, 0xfd, - 0x4e, 0x8e, 0x6f, 0x25, 0xc7, 0x6c, 0xa2, 0xc0, 0xa8, 0xd5, 0x2a, 0x29, - 0xfb, 0xf1, 0x3f, 0x88, 0x81, 0xa2, 0xa3, 0x35, 0xb9, 0xf9, 0x2a, 0x77, - 0x50, 0x5e, 0x3f, 0x90, 0x9f, 0x17, 0xcb, 0xda, 0x69, 0xe6, 0xe7, 0xa6, - 0x1a, 0xfe, 0x4a, 0x3d, 0x3e, 0x44, 0x8b, 0x18, 0x49, 0x54, 0x21, 0xae, - 0xa9, 0xb9, 0xb6, 0xa3, 0x4a, 0x01, 0xf3, 0x07, 0x8c, 0x8b, 0xef, 0x97, - 0x22, 0xea, 0x94, 0xfa, 0x88, 0x16, 0x44, 0x02, 0xc1, 0xb9, 0xea, 0x54, - 0x9b, 0x11, 0x1c, 0x90, 0xbe, 0xe2, 0x94, 0xf5, 0x52, 0x2c, 0x18, 0x49, - 0xe4, 0x71, 0xe3, 0x3f, 0x53, 0xcf, 0x4b, 0x1f, 0x9b, 0xaa, 0x53, 0x91, - 0x53, 0xf4, 0xaa, 0xa2, 0x75, 0x50, 0xf4, 0xe7, 0xc4, 0x4a, 0x73, 0x51, - 0x4e, 0xe6, 0x99, 0x68, 0x4b, 0xa8, 0xd8, 0x30, 0xc8, 0xbe, 0x52, 0x0a, - 0x36, 0x87, 0x96, 0x60, 0xc8, 0x6b, 0xd3, 0x45, 0xb4, 0x26, 0x1a, 0x69, - 0x63, 0xc4, 0x99, 0x71, 0x3b, 0x7e, 0xda, 0xfe, 0x33, 0x9b, 0x3e, 0xb1, - 0x2c, 0xfd, 0x20, 0xd6, 0x26, 0x03, 0xfe, 0x93, 0x78, 0x10, 0x6d, 0x69, - 0x17, 0x62, 0xc3, 0x1e, 0x74, 0xb2, 0x6f, 0xb5, 0x4f, 0xfc, 0x49, 0x43, - 0xe7, 0xe8, 0x89, 0x17, 0x54, 0xda, 0x67, 0xe7, 0xa8, 0x97, 0xc7, 0x34, - 0x1e, 0x6e, 0x3c, 0xc4, 0xe3, 0x28, 0xe7, 0xbf, 0x83, 0x18, 0x9c, 0x4e, - 0x98, 0xb8, 0x9f, 0x32, 0x8d, 0x27, 0xea, 0xb1, 0x91, 0xf2, 0x8d, 0x25, - 0x1c, 0xf0, 0x4f, 0x0b, 0xe3, 0x3e, 0xea, 0xf2, 0xc9, 0x44, 0x58, 0x79, - 0x80, 0xff, 0x0f, 0x51, 0x26, 0xc9, 0x47, 0xd6, 0xd1, 0x0e, 0xa2, 0xd3, - 0x68, 0x27, 0x6a, 0xad, 0xc3, 0x9e, 0x07, 0x88, 0x7f, 0x5c, 0x3e, 0x57, - 0xba, 0x16, 0x43, 0x7e, 0xbe, 0x80, 0xa1, 0x14, 0x62, 0xee, 0x48, 0x5d, - 0x63, 0x41, 0x6f, 0xeb, 0x86, 0xc2, 0x48, 0xfb, 0x43, 0x3f, 0xad, 0x9f, - 0x85, 0x93, 0x9c, 0x13, 0xa7, 0x6d, 0xe3, 0x51, 0xc5, 0x65, 0x18, 0xb6, - 0x2f, 0xab, 0xe3, 0xed, 0xb9, 0xbc, 0x4a, 0x97, 0x38, 0xc6, 0x3e, 0x44, - 0x6f, 0xa2, 0x0b, 0xd1, 0xc3, 0x71, 0x6b, 0xc8, 0xf6, 0x77, 0xf1, 0x39, - 0x27, 0x75, 0xf4, 0x5d, 0xc6, 0x6f, 0xd1, 0x85, 0x94, 0xdb, 0xca, 0xb6, - 0x44, 0x1e, 0x3b, 0x16, 0xfa, 0xfe, 0xd0, 0x76, 0xa6, 0xca, 0x53, 0x87, - 0xed, 0x7b, 0x0c, 0xec, 0xd8, 0x53, 0x4b, 0xbb, 0xfb, 0xa5, 0xe5, 0xaf, - 0x18, 0x60, 0xdd, 0xa9, 0xb2, 0x08, 0x2f, 0x40, 0xae, 0x5d, 0x69, 0x73, - 0x13, 0xef, 0x1d, 0xa6, 0xad, 0x49, 0xbb, 0x96, 0xb5, 0xe5, 0x42, 0xdc, - 0x28, 0x88, 0x16, 0x31, 0x6e, 0x1c, 0x4a, 0x04, 0xc2, 0x2f, 0xd8, 0xb1, - 0xcd, 0x49, 0xdb, 0x90, 0xf9, 0xef, 0xb6, 0xe7, 0x7e, 0xd9, 0x85, 0xb9, - 0x9f, 0xbc, 0xc0, 0x91, 0xfa, 0x93, 0x53, 0x7d, 0x2a, 0x3b, 0xef, 0xce, - 0x3e, 0xbd, 0xc7, 0xb6, 0xd3, 0x94, 0xe0, 0x9f, 0x03, 0x8e, 0x01, 0xce, - 0xb3, 0x79, 0x15, 0xc7, 0x5f, 0xc9, 0x78, 0x52, 0xc0, 0x83, 0x79, 0xe4, - 0xf0, 0xa7, 0x50, 0x3c, 0x90, 0xb1, 0x8a, 0xf8, 0xbb, 0x29, 0x14, 0x08, - 0x17, 0x29, 0x37, 0xe0, 0xee, 0x61, 0x07, 0x0a, 0x06, 0x14, 0x3c, 0x6b, - 0xd6, 0xe5, 0xec, 0x43, 0xe6, 0xfb, 0x2a, 0xdb, 0x3e, 0xe6, 0x8c, 0xcb, - 0x7c, 0xcb, 0x1c, 0x7b, 0xe0, 0xeb, 0x53, 0xe0, 0x21, 0x6e, 0x94, 0x18, - 0x32, 0xd7, 0x1a, 0xca, 0xfb, 0x64, 0xae, 0x49, 0x1b, 0x77, 0x87, 0xb1, - 0x91, 0xf6, 0x50, 0xba, 0xfb, 0x7a, 0xdc, 0xc7, 0x72, 0x1b, 0x78, 0x6f, - 0xc3, 0x68, 0x25, 0x0f, 0x2f, 0x8f, 0x69, 0x3c, 0xea, 0x71, 0xef, 0x70, - 0x0d, 0xa2, 0x95, 0x7a, 0xd0, 0xaf, 0x3a, 0x50, 0x39, 0x20, 0x3a, 0x55, - 0xb1, 0x72, 0x81, 0x02, 0xf3, 0xea, 0x42, 0xa8, 0x73, 0x3f, 0xc9, 0x37, - 0xff, 0x9c, 0xac, 0x3f, 0x9a, 0x32, 0x87, 0x6e, 0x8e, 0xfd, 0x9f, 0xed, - 0x39, 0x9c, 0x33, 0x2e, 0x7d, 0x48, 0x2c, 0xb5, 0xe7, 0xf1, 0x4f, 0xf8, - 0xfe, 0x73, 0x9c, 0x8f, 0x2e, 0x96, 0xf9, 0xc3, 0xf9, 0xc5, 0x85, 0xf9, - 0x9d, 0xca, 0x49, 0x25, 0xae, 0xeb, 0xe1, 0x21, 0x9b, 0xc3, 0xf8, 0x99, - 0xcf, 0xe9, 0x71, 0xd1, 0x39, 0x39, 0x8b, 0x5b, 0x35, 0xe0, 0x2f, 0x30, - 0xee, 0xc0, 0x3d, 0x9c, 0xa7, 0x03, 0x09, 0x75, 0xa9, 0x0b, 0xea, 0x4c, - 0x17, 0x13, 0xdb, 0x11, 0x53, 0xc7, 0xba, 0x61, 0xe6, 0x4a, 0xc3, 0xa5, - 0xe8, 0xd2, 0x14, 0xf7, 0xf6, 0xba, 0x45, 0x92, 0xf3, 0xfa, 0xcb, 0x0d, - 0xa8, 0x25, 0x8c, 0xef, 0x3b, 0x34, 0x38, 0x0b, 0x0c, 0x45, 0x4d, 0xd4, - 0x35, 0x22, 0x5e, 0x01, 0x67, 0x99, 0x01, 0x85, 0x39, 0x2d, 0x7a, 0x35, - 0x08, 0xb6, 0x44, 0x0b, 0x8c, 0x07, 0x71, 0x4f, 0x12, 0x56, 0x71, 0x84, - 0xf9, 0x4e, 0xc4, 0x20, 0x87, 0x0d, 0xf8, 0x0a, 0x94, 0x07, 0xb1, 0x9a, - 0xbc, 0x61, 0xcd, 0xb0, 0xc8, 0xe1, 0x21, 0x9f, 0x30, 0xfc, 0xad, 0x60, - 0x8e, 0xdd, 0xac, 0x07, 0x27, 0x99, 0x67, 0xae, 0xa6, 0xee, 0x47, 0x12, - 0x0f, 0xa2, 0x21, 0x79, 0xdc, 0xf2, 0x90, 0x27, 0x16, 0x18, 0x35, 0xe7, - 0xbb, 0x10, 0xa3, 0x0f, 0x0b, 0xff, 0x69, 0xc3, 0x43, 0xf4, 0xbf, 0x74, - 0x42, 0x7d, 0x86, 0xec, 0x01, 0x1d, 0xa3, 0xeb, 0x71, 0xff, 0xe8, 0x4c, - 0xfa, 0xea, 0x06, 0xfa, 0x2a, 0xb9, 0x50, 0xff, 0x0d, 0xb8, 0x6f, 0xf8, - 0x06, 0xdc, 0xbb, 0xcb, 0x08, 0x6e, 0xa0, 0xae, 0xd7, 0x0c, 0x33, 0x10, - 0x4e, 0x93, 0x76, 0xf3, 0xba, 0x12, 0x3e, 0x48, 0x5d, 0xe4, 0xf4, 0x94, - 0x41, 0x9e, 0xa3, 0xfc, 0xb3, 0xc5, 0x4b, 0xf1, 0x82, 0x7a, 0xc5, 0xbf, - 0xb7, 0xee, 0xfb, 0xcc, 0xbd, 0x45, 0x76, 0x44, 0x67, 0x18, 0xaf, 0x5a, - 0x8f, 0x6a, 0x0a, 0x0a, 0x22, 0x88, 0xcf, 0xae, 0x7f, 0xd9, 0x7a, 0x6c, - 0x95, 0x5c, 0xbf, 0xd5, 0x89, 0x62, 0x95, 0xd7, 0xa4, 0xcd, 0x1d, 0x32, - 0x47, 0x44, 0xda, 0x4f, 0x6a, 0x33, 0x63, 0xf5, 0x5d, 0x28, 0x4f, 0xde, - 0x47, 0xac, 0x7d, 0x3a, 0xe1, 0x45, 0x4f, 0x32, 0xcb, 0x9d, 0x6e, 0x4f, - 0x0b, 0x67, 0x72, 0xa3, 0xb8, 0x57, 0xe2, 0x46, 0x14, 0xeb, 0xf9, 0xbb, - 0xa8, 0x57, 0x6f, 0x8e, 0x83, 0xc9, 0xbc, 0xd1, 0xc8, 0xb9, 0xa0, 0xbd, - 0xf6, 0x3a, 0x50, 0x64, 0x34, 0x65, 0x6d, 0xb5, 0x77, 0x85, 0x8d, 0x4b, - 0x65, 0xbd, 0xdd, 0x36, 0x2e, 0x95, 0xb2, 0x9e, 0x60, 0x92, 0xa7, 0x77, - 0x15, 0xed, 0x75, 0x26, 0x4a, 0x7a, 0x5b, 0x70, 0x2f, 0xe7, 0x78, 0x2d, - 0x79, 0xf6, 0x09, 0xb3, 0x3c, 0xc7, 0x3f, 0x9b, 0x70, 0x77, 0x32, 0x8a, - 0xd6, 0x64, 0x4d, 0xf4, 0xb4, 0xac, 0x25, 0xb9, 0xb2, 0xd8, 0x19, 0xad, - 0x16, 0x5d, 0x3c, 0x97, 0xc3, 0x08, 0xbd, 0x29, 0xcb, 0xd9, 0x74, 0xcd, - 0xaf, 0xe4, 0x65, 0xef, 0x46, 0x8c, 0xf9, 0xc5, 0xec, 0x48, 0x33, 0xac, - 0xa4, 0xc8, 0x1d, 0xb7, 0x7c, 0xcc, 0x19, 0x3d, 0x11, 0xbd, 0x7d, 0xb1, - 0xc3, 0xe8, 0xf8, 0xb1, 0x12, 0xc4, 0xad, 0x94, 0xa1, 0xa4, 0xb7, 0x13, - 0xaf, 0x84, 0x74, 0xdf, 0xb7, 0x15, 0xfd, 0xfc, 0x06, 0xfc, 0x18, 0x3f, - 0xe7, 0xb5, 0x82, 0xde, 0x09, 0x3c, 0x96, 0x7e, 0x1d, 0x67, 0x29, 0xab, - 0xda, 0xfb, 0xb1, 0xb5, 0xcc, 0x20, 0x18, 0x14, 0xbb, 0x95, 0xb7, 0xd3, - 0x53, 0x6d, 0xf1, 0x06, 0xac, 0xde, 0x25, 0xf6, 0xa7, 0x07, 0xe3, 0xa0, - 0x7c, 0x66, 0x99, 0x60, 0x9c, 0xc4, 0x1f, 0xca, 0xdf, 0x4c, 0xd9, 0x2c, - 0xfa, 0x07, 0xed, 0xc0, 0x1e, 0xc3, 0x43, 0x36, 0x0e, 0x3a, 0xfb, 0xe4, - 0xc8, 0xeb, 0x39, 0xa2, 0xb4, 0x8e, 0x5e, 0x53, 0x8c, 0x62, 0x5f, 0xce, - 0x0f, 0xb2, 0x6b, 0x0a, 0x17, 0xeb, 0xfe, 0xd2, 0x1a, 0xf1, 0x5e, 0x5a, - 0xb7, 0x8c, 0x39, 0x56, 0x39, 0xc7, 0xf3, 0x5e, 0x6f, 0xdc, 0x2a, 0xce, - 0x8e, 0xa5, 0xe9, 0x55, 0x45, 0x6c, 0x32, 0x48, 0xee, 0xde, 0x89, 0xab, - 0x42, 0x7a, 0xcb, 0xb7, 0x15, 0x29, 0xab, 0x87, 0x37, 0x28, 0xf9, 0x7e, - 0x7e, 0x84, 0xd3, 0x23, 0xd2, 0x87, 0xf4, 0x35, 0xc1, 0x9c, 0xeb, 0x52, - 0x7f, 0x4a, 0xd9, 0xf3, 0xa9, 0x9b, 0x43, 0xe4, 0x75, 0x2b, 0x38, 0xcc, - 0x92, 0x5e, 0x19, 0x93, 0xa9, 0xdc, 0x3b, 0x2a, 0xf3, 0xba, 0x40, 0x59, - 0x4f, 0x2c, 0x29, 0xea, 0xad, 0x57, 0xee, 0x21, 0x96, 0x14, 0xee, 0xac, - 0x51, 0xee, 0xb6, 0x6d, 0xbe, 0x0a, 0x23, 0xfd, 0xd7, 0x28, 0x6d, 0xc3, - 0xa2, 0x03, 0x37, 0xc7, 0x3e, 0x8d, 0x63, 0xf7, 0xa2, 0x8f, 0xfe, 0xfb, - 0x4a, 0x6f, 0x9d, 0x72, 0x1f, 0x7d, 0xa3, 0x73, 0x97, 0x8a, 0xc9, 0x2a, - 0x85, 0x78, 0x47, 0xfe, 0x6b, 0xf8, 0x94, 0xd6, 0xe1, 0xef, 0x3b, 0x25, - 0xbe, 0x64, 0x70, 0x03, 0x5a, 0x79, 0x6f, 0xa9, 0xe9, 0x42, 0x46, 0xab, - 0xd5, 0x34, 0xac, 0xc0, 0xea, 0xe4, 0x2a, 0xb4, 0x25, 0x8b, 0xc9, 0x73, - 0x65, 0xbc, 0x79, 0xb9, 0xf3, 0xf3, 0xf8, 0x20, 0x5a, 0x92, 0x88, 0xcf, - 0x88, 0x04, 0x3a, 0x66, 0x38, 0xe8, 0xd2, 0xc5, 0x75, 0xca, 0xfd, 0xe9, - 0x1a, 0x65, 0xcd, 0xae, 0x72, 0x64, 0xb1, 0xe7, 0x61, 0x34, 0xed, 0xa9, - 0x57, 0xee, 0xde, 0x53, 0x85, 0x49, 0xcd, 0xb2, 0x9c, 0xa1, 0x7a, 0xa5, - 0x75, 0x8f, 0x65, 0xdd, 0x64, 0x46, 0x9b, 0x8a, 0xc9, 0x77, 0xb7, 0xb1, - 0xbd, 0xd6, 0x51, 0xe9, 0xe7, 0xf2, 0x76, 0x4d, 0x65, 0xe3, 0x9e, 0x87, - 0xb1, 0x82, 0x65, 0x5f, 0x09, 0x45, 0x5b, 0x4a, 0x59, 0x56, 0x74, 0xd6, - 0x3a, 0xfa, 0x19, 0xf6, 0x21, 0xe5, 0x17, 0x4c, 0x69, 0x67, 0x31, 0xaf, - 0x49, 0x5b, 0x59, 0xdd, 0x89, 0xde, 0x1e, 0xcf, 0xea, 0x2d, 0x2c, 0x7a, - 0x5b, 0x4e, 0x5d, 0xba, 0x7a, 0x7d, 0x3c, 0x5c, 0xf4, 0x75, 0x1f, 0xd6, - 0xa4, 0x65, 0x4c, 0x33, 0x89, 0x03, 0xcd, 0xb4, 0xdb, 0x76, 0xb4, 0x52, - 0xaf, 0x71, 0x2d, 0x6b, 0x9f, 0x17, 0x7d, 0x4b, 0xf7, 0x4f, 0x72, 0xec, - 0xad, 0x49, 0xd1, 0x4b, 0x33, 0xcb, 0xdb, 0xf7, 0xe9, 0xdb, 0x53, 0xcb, - 0x5c, 0x3a, 0x57, 0xfb, 0x13, 0xc2, 0x27, 0x0a, 0xc8, 0x7d, 0x0a, 0xd8, - 0x5e, 0x96, 0x2b, 0x8a, 0xbd, 0x38, 0x68, 0x2f, 0xcf, 0x98, 0xc5, 0xd8, - 0xe4, 0x95, 0x31, 0x66, 0xf5, 0x0c, 0x15, 0x58, 0xc7, 0x7b, 0x2e, 0xde, - 0x2b, 0x0c, 0x15, 0xe2, 0x2d, 0x5b, 0x57, 0x59, 0x3e, 0x98, 0xf7, 0xf3, - 0xa1, 0x0b, 0xfd, 0x1c, 0xab, 0xce, 0xda, 0xd8, 0x26, 0x57, 0x96, 0x33, - 0xe6, 0xb9, 0x8d, 0x65, 0x0d, 0x98, 0x79, 0x6e, 0x23, 0x71, 0xee, 0x53, - 0xc2, 0x15, 0x6c, 0x1e, 0xd6, 0x96, 0xeb, 0xb7, 0xcb, 0x0c, 0xd0, 0x4f, - 0x85, 0xfb, 0x45, 0x94, 0xb6, 0x3d, 0xa7, 0x68, 0xab, 0x92, 0x8b, 0x01, - 0x1b, 0x79, 0xbf, 0x94, 0xf7, 0x5f, 0x0b, 0xb9, 0x70, 0xd5, 0x34, 0xe9, - 0xfb, 0x06, 0x74, 0xec, 0x8a, 0xa2, 0x7c, 0x61, 0x00, 0x93, 0xf6, 0x7a, - 0x59, 0x9e, 0xa7, 0xbb, 0x70, 0xdf, 0xae, 0x8f, 0xad, 0x32, 0x9b, 0x3b, - 0x1a, 0xb1, 0x71, 0x45, 0xc5, 0x8e, 0x45, 0xc2, 0xd7, 0x5d, 0x8c, 0x57, - 0xe4, 0xce, 0x92, 0x0b, 0xb8, 0x4a, 0xc8, 0xb9, 0x85, 0x73, 0x06, 0x32, - 0xb7, 0xab, 0xd0, 0xb4, 0x88, 0x70, 0xcf, 0x99, 0x36, 0xe7, 0x16, 0xee, - 0xfd, 0xcd, 0xe4, 0xd1, 0x29, 0xdc, 0xfb, 0x02, 0x4f, 0x61, 0xae, 0xd6, - 0x8c, 0x44, 0xaf, 0x07, 0xee, 0x88, 0xde, 0xbc, 0x59, 0xe9, 0xc4, 0xf2, - 0x90, 0x61, 0xca, 0x1a, 0xc0, 0xf5, 0x8a, 0x1e, 0x3c, 0x87, 0x20, 0xe3, - 0xc7, 0x8f, 0x30, 0x32, 0xf8, 0x0f, 0x2e, 0xf1, 0x8b, 0xcd, 0xe9, 0x8b, - 0xf2, 0xdc, 0x4d, 0x79, 0xdc, 0x59, 0x79, 0xcc, 0x73, 0x54, 0xe4, 0xb3, - 0xf5, 0x2e, 0xe2, 0xf0, 0x7f, 0xb7, 0xed, 0x76, 0x89, 0x9d, 0x4b, 0xfc, - 0x77, 0xc6, 0x93, 0x70, 0x71, 0x5e, 0xcf, 0x9d, 0xc4, 0xab, 0x0f, 0x17, - 0x16, 0x21, 0x44, 0x7b, 0xaf, 0x30, 0x3a, 0x98, 0xcf, 0x7f, 0x6c, 0xc5, - 0x9d, 0xa4, 0xdf, 0x06, 0xb4, 0xa2, 0x48, 0x94, 0xb2, 0x35, 0x2a, 0x37, - 0x0d, 0x8f, 0xb3, 0x9f, 0x0e, 0xe6, 0x29, 0x1e, 0x3c, 0x40, 0x5c, 0x79, - 0x80, 0xfe, 0xf4, 0x00, 0x63, 0xf3, 0x03, 0xa3, 0xff, 0x8b, 0xd7, 0xa7, - 0xd9, 0xbf, 0x37, 0x27, 0xf3, 0xf6, 0xe5, 0x64, 0x9c, 0x13, 0xfd, 0x6e, - 0x21, 0x16, 0x48, 0x9c, 0x03, 0x65, 0xb2, 0x70, 0xda, 0x2c, 0xa4, 0xae, - 0xf5, 0x60, 0x06, 0x09, 0xd7, 0xc5, 0x3c, 0x35, 0x1f, 0x2b, 0x65, 0x1e, - 0x5d, 0xb8, 0x87, 0x32, 0x06, 0x43, 0xbf, 0xb1, 0x50, 0x21, 0x58, 0x74, - 0xf9, 0xfd, 0xec, 0xbc, 0x1e, 0xbf, 0xc0, 0x59, 0x15, 0xc9, 0x91, 0xe8, - 0xef, 0xfd, 0x36, 0x07, 0x7b, 0x8d, 0x3e, 0xd9, 0xb6, 0xeb, 0xc4, 0x7c, - 0x31, 0x95, 0x35, 0xa3, 0x51, 0x6c, 0xe2, 0xb8, 0x57, 0x0f, 0x3f, 0x9a, - 0xd3, 0x4b, 0x7e, 0xbc, 0xe2, 0xd3, 0x1e, 0xda, 0x74, 0x36, 0xb7, 0x6a, - 0x1d, 0x15, 0x2e, 0x5e, 0xc9, 0xff, 0xc2, 0xc5, 0xc5, 0x7f, 0x84, 0x97, - 0x4f, 0xe3, 0x7f, 0x27, 0x39, 0xa7, 0x70, 0xe9, 0x3a, 0xf4, 0xd0, 0x8f, - 0x0a, 0x03, 0x75, 0xd8, 0x3a, 0x7a, 0xf9, 0x1c, 0x5d, 0x2e, 0x8f, 0x3d, - 0x07, 0xcc, 0xc3, 0x5c, 0x82, 0xad, 0x7e, 0xbf, 0x2a, 0x7d, 0x5b, 0x68, - 0x37, 0x6f, 0xc8, 0x72, 0xa7, 0x4a, 0xb9, 0x36, 0x95, 0x9f, 0xe7, 0xdb, - 0x99, 0x7a, 0x4d, 0x2d, 0x40, 0x71, 0x9e, 0x37, 0x78, 0x73, 0xb9, 0x0e, - 0xf3, 0x9b, 0xa4, 0xe8, 0x4b, 0xc6, 0x90, 0xcd, 0x5f, 0xc5, 0x5e, 0x2e, - 0xc5, 0x83, 0xf8, 0xb4, 0x22, 0x43, 0x6c, 0x25, 0x48, 0x7f, 0xd6, 0xc3, - 0x4d, 0x0c, 0x35, 0x67, 0x13, 0x88, 0x39, 0x22, 0x4d, 0x8d, 0x6b, 0x12, - 0x73, 0xb5, 0x67, 0x72, 0xf9, 0xf1, 0x7e, 0xc6, 0x1e, 0xd5, 0x90, 0xb5, - 0x19, 0xda, 0xc3, 0xb0, 0xe8, 0xa7, 0x43, 0xb9, 0x98, 0x0b, 0x47, 0xc9, - 0x15, 0x19, 0x57, 0x0d, 0xc9, 0x91, 0x1a, 0x95, 0xa5, 0xc3, 0x52, 0x87, - 0xf6, 0x70, 0x19, 0x67, 0xcc, 0x8e, 0xb7, 0x0c, 0x9e, 0x01, 0xe1, 0x8a, - 0x3a, 0x36, 0x90, 0x9b, 0x94, 0x0c, 0xf8, 0x69, 0xef, 0x95, 0x28, 0xde, - 0x1d, 0xc1, 0xfa, 0x51, 0x0d, 0x45, 0xbb, 0x2d, 0x6b, 0x6e, 0xa8, 0x1b, - 0x6b, 0xd3, 0xcb, 0x0b, 0x24, 0x9f, 0x73, 0xf6, 0x11, 0x2b, 0x88, 0x2b, - 0xeb, 0x92, 0x0a, 0x6e, 0x24, 0x07, 0x88, 0xa2, 0x99, 0xdc, 0x5d, 0xf0, - 0xc5, 0xea, 0x9c, 0x1d, 0x71, 0xd1, 0x4e, 0x56, 0xf1, 0x7e, 0x0b, 0xb1, - 0xa7, 0x85, 0x58, 0x62, 0x59, 0x1f, 0x5e, 0x8b, 0xce, 0x92, 0xc8, 0x1d, - 0xc4, 0xa0, 0x1a, 0xe6, 0x0f, 0xc2, 0x39, 0xae, 0x45, 0x1b, 0xb1, 0xbb, - 0xb0, 0xcf, 0xce, 0xf1, 0xa8, 0x47, 0xc6, 0xd5, 0x34, 0xe3, 0x32, 0x65, - 0x7f, 0x9e, 0x7c, 0xbd, 0x83, 0x7e, 0x54, 0xde, 0xb7, 0x81, 0xf1, 0xd9, - 0x83, 0xb2, 0x81, 0x6b, 0xb0, 0x91, 0xd8, 0x7e, 0xdf, 0x2e, 0x3f, 0x52, - 0x8b, 0x6e, 0xa0, 0x7c, 0x0f, 0x62, 0x7d, 0xd2, 0x90, 0xbc, 0x2e, 0x1a, - 0x5c, 0xf4, 0x20, 0xfb, 0xa5, 0x7d, 0xec, 0x92, 0x1c, 0xb1, 0x04, 0x4b, - 0x9a, 0x81, 0x60, 0x9f, 0x60, 0x8e, 0x8c, 0xff, 0x36, 0x59, 0xcf, 0x82, - 0xd1, 0x37, 0x75, 0x3e, 0xa6, 0x72, 0x39, 0x59, 0x1b, 0x6c, 0xc6, 0x7c, - 0xc6, 0x2f, 0xb1, 0x21, 0x8d, 0x79, 0x6f, 0x91, 0x62, 0xf8, 0xf6, 0xd3, - 0x17, 0x25, 0x17, 0xbb, 0xae, 0x2f, 0x1f, 0xaf, 0xf5, 0xcc, 0x62, 0x47, - 0x27, 0xb1, 0x42, 0x6f, 0xff, 0xad, 0xa2, 0xaf, 0x3b, 0xa5, 0xfc, 0x18, - 0x07, 0xc7, 0x5e, 0xc7, 0xd0, 0x98, 0x5b, 0x19, 0x1d, 0x93, 0xbe, 0x26, - 0xd0, 0x9b, 0xfe, 0x73, 0x7d, 0x4d, 0x5d, 0x13, 0x5a, 0x74, 0xc9, 0x3a, - 0xd2, 0x8d, 0xb9, 0xdc, 0x75, 0xe9, 0x25, 0x9c, 0x5e, 0xe6, 0x44, 0x6c, - 0xcf, 0x8b, 0xee, 0xe4, 0xc5, 0xb5, 0x8a, 0xfe, 0xc4, 0x76, 0xdb, 0x07, - 0x9b, 0xd3, 0x62, 0x93, 0xcc, 0xef, 0xcc, 0x39, 0xf6, 0xb3, 0x1b, 0x59, - 0x5f, 0x58, 0xb3, 0xab, 0xd7, 0xbe, 0x77, 0xd0, 0xfc, 0x2b, 0x64, 0xec, - 0x6b, 0x8b, 0xe9, 0x7f, 0x8c, 0x93, 0xc4, 0xbd, 0x60, 0xc8, 0x87, 0xc2, - 0x0a, 0x59, 0x5b, 0xba, 0xb8, 0x1e, 0xb1, 0x61, 0x17, 0x69, 0x84, 0x8d, - 0x2b, 0x0d, 0xc4, 0xb8, 0x1a, 0xce, 0x77, 0x16, 0x4b, 0xd6, 0xd3, 0x86, - 0x6e, 0x11, 0x1b, 0x72, 0x65, 0x6d, 0xe8, 0x0f, 0xd7, 0x3c, 0x54, 0x90, - 0xaf, 0x6a, 0x65, 0x76, 0x2e, 0xda, 0xa8, 0xdc, 0x9a, 0xb3, 0xab, 0xcf, - 0xa6, 0xbf, 0x53, 0x90, 0xcb, 0x91, 0x2e, 0x2b, 0xff, 0x49, 0x3a, 0xb8, - 0xe6, 0x2f, 0xd0, 0x81, 0x60, 0xbe, 0xe4, 0x31, 0xa2, 0x83, 0x99, 0x53, - 0xfc, 0xf2, 0x93, 0xf4, 0x50, 0x9b, 0xd3, 0xc3, 0x62, 0x62, 0x48, 0x25, - 0x71, 0x4f, 0x38, 0x4b, 0x00, 0x4f, 0x6a, 0x79, 0x3d, 0x38, 0x73, 0x7a, - 0xd0, 0xff, 0x40, 0x0f, 0xf7, 0x13, 0x5f, 0x4b, 0xd9, 0x56, 0x31, 0x8f, - 0x77, 0xa9, 0x87, 0x8d, 0xc3, 0x8b, 0xf1, 0x00, 0x7d, 0x69, 0x83, 0xbd, - 0x5e, 0x23, 0xcf, 0xef, 0x5c, 0x97, 0xe8, 0x66, 0x25, 0xe5, 0xf7, 0x17, - 0xa8, 0x98, 0x41, 0x1d, 0xf8, 0x6c, 0x3c, 0x95, 0x3e, 0x1a, 0x95, 0xdb, - 0x87, 0x05, 0xe3, 0x3e, 0xa6, 0x0e, 0x3a, 0x18, 0x07, 0xfe, 0x54, 0x9e, - 0x21, 0xfd, 0x7f, 0x7c, 0x41, 0x57, 0x7f, 0xbc, 0xdc, 0x8f, 0xa9, 0x03, - 0x79, 0x26, 0x22, 0x6b, 0xec, 0xf2, 0x7c, 0x44, 0xf4, 0x61, 0x4c, 0xd1, - 0x83, 0x65, 0x1d, 0x31, 0xe7, 0x21, 0x56, 0xa9, 0xf7, 0x4b, 0x1c, 0xed, - 0x27, 0xa6, 0x38, 0x98, 0xb7, 0x17, 0x44, 0xa2, 0x14, 0x5b, 0xbd, 0x81, - 0x4c, 0xa7, 0xce, 0x81, 0x4e, 0x9c, 0x31, 0x8d, 0x9e, 0xb5, 0xf8, 0x2b, - 0x74, 0x79, 0x2d, 0x1c, 0x60, 0x3b, 0x9b, 0x92, 0x45, 0x58, 0x57, 0x47, - 0xd3, 0x5c, 0xe9, 0xc1, 0xce, 0x64, 0xbc, 0x85, 0xd0, 0xc2, 0xd8, 0x74, - 0xe6, 0xf6, 0x44, 0x40, 0x6f, 0xde, 0x40, 0xbe, 0xb6, 0xbc, 0xd7, 0x0d, - 0xbf, 0x92, 0x8d, 0xcf, 0x03, 0xaa, 0xac, 0x7f, 0x5e, 0xc9, 0xb1, 0x77, - 0xdb, 0x79, 0xac, 0x7f, 0x9a, 0xf4, 0xe3, 0x47, 0x3c, 0x2d, 0x75, 0xa9, - 0xb3, 0xb9, 0x0a, 0x96, 0xcf, 0xd5, 0xe3, 0x51, 0xc5, 0xb2, 0x16, 0x84, - 0x9c, 0xf6, 0xfd, 0xed, 0xe9, 0xda, 0x96, 0xdb, 0xd4, 0xd7, 0xad, 0xec, - 0x9a, 0xab, 0xae, 0x45, 0x99, 0x0c, 0x1d, 0xff, 0xa3, 0xcf, 0x1d, 0x82, - 0x90, 0xe7, 0x41, 0x6e, 0x63, 0x25, 0x0e, 0xe5, 0xd6, 0x1d, 0x5d, 0x91, - 0xc3, 0x5f, 0x3e, 0x60, 0x48, 0xbe, 0x26, 0x7a, 0x92, 0xfe, 0xc4, 0x9e, - 0x1e, 0x28, 0x14, 0x1c, 0xed, 0x4a, 0x2f, 0xe4, 0x3c, 0xfe, 0x87, 0x35, - 0xea, 0x9d, 0x5a, 0x76, 0x89, 0x9a, 0x7d, 0x8e, 0x20, 0x65, 0xf3, 0xe5, - 0xe6, 0x10, 0x57, 0x1a, 0x30, 0x7c, 0x49, 0x9b, 0x92, 0x6f, 0xe7, 0xdb, - 0xec, 0x2d, 0x14, 0x5e, 0x55, 0x81, 0x42, 0xe2, 0xe3, 0x6f, 0xac, 0x83, - 0x97, 0xb4, 0xb7, 0xd1, 0x95, 0x6d, 0x6f, 0x0f, 0xcb, 0x48, 0xd9, 0x02, - 0xd6, 0x79, 0x37, 0xc7, 0x7f, 0xf3, 0x65, 0x3e, 0x77, 0x59, 0x19, 0x66, - 0x78, 0xc6, 0x5b, 0xd6, 0xfe, 0x4b, 0xca, 0x7c, 0xda, 0x79, 0x69, 0x19, - 0x27, 0x66, 0x1b, 0xaf, 0x5b, 0xc7, 0x2f, 0x29, 0x33, 0x70, 0x59, 0x99, - 0x6b, 0x31, 0x56, 0xf7, 0xb8, 0x35, 0x94, 0x9d, 0x9b, 0x0c, 0x5d, 0xd0, - 0x3d, 0x23, 0xe2, 0xfe, 0xd2, 0x75, 0xf3, 0x74, 0xf2, 0x4d, 0x79, 0x16, - 0xe5, 0x46, 0x26, 0x3b, 0x37, 0x71, 0x99, 0x1b, 0xd7, 0x82, 0xfc, 0xdc, - 0x3c, 0x90, 0xab, 0x9f, 0x6f, 0x37, 0x56, 0x70, 0x69, 0xbb, 0xf9, 0xeb, - 0x8e, 0xcb, 0xe4, 0x9e, 0xb8, 0xac, 0x5c, 0x51, 0xe1, 0x27, 0xd7, 0xfb, - 0x81, 0xe3, 0xd2, 0xeb, 0xff, 0x43, 0xbd, 0xf4, 0xfc, 0x9a, 0xdc, 0x79, - 0x5e, 0xff, 0xd6, 0x65, 0xf7, 0x1d, 0x97, 0x9d, 0x3f, 0xa3, 0x7e, 0x72, - 0x3f, 0xab, 0x2e, 0xeb, 0xc7, 0x5e, 0x83, 0xc7, 0x73, 0x17, 0x70, 0x03, - 0x8d, 0x05, 0x08, 0x98, 0x4e, 0x05, 0x7e, 0xe2, 0x87, 0xff, 0xf9, 0xcb, - 0xd6, 0xe2, 0x1b, 0x2f, 0xe0, 0xc7, 0x25, 0x5c, 0x35, 0x56, 0x18, 0x91, - 0x38, 0x28, 0x3c, 0x55, 0xf8, 0xe2, 0x27, 0xf1, 0xef, 0xb2, 0x58, 0x51, - 0xa4, 0x1e, 0xfe, 0xb1, 0x99, 0xfe, 0xb7, 0x12, 0xb2, 0x1e, 0xfb, 0x7b, - 0x72, 0x2e, 0xc3, 0x77, 0x08, 0x33, 0xfd, 0x3f, 0x4d, 0x95, 0xb8, 0x51, - 0xe6, 0xc1, 0x8d, 0x89, 0x4f, 0xae, 0xa7, 0x46, 0xa0, 0x2c, 0xab, 0xf7, - 0x31, 0xaf, 0x84, 0xf3, 0xa6, 0x79, 0x98, 0xf2, 0xd7, 0x2c, 0x79, 0xae, - 0x7a, 0xb2, 0x3e, 0xcc, 0x18, 0x9f, 0x7d, 0x8e, 0xbc, 0x24, 0xad, 0xfb, - 0xa2, 0x4a, 0xf6, 0x59, 0xf1, 0xba, 0xd0, 0x47, 0xe4, 0x45, 0x9d, 0x94, - 0xcb, 0x62, 0x5f, 0xc0, 0x86, 0x84, 0x65, 0x3d, 0xc7, 0xfc, 0x5c, 0xf6, - 0x20, 0xfc, 0x22, 0xf5, 0x3b, 0x6b, 0xc2, 0xeb, 0xc4, 0xdb, 0xc6, 0xd4, - 0xf6, 0xfc, 0x28, 0x8f, 0x98, 0xcc, 0x13, 0xed, 0x13, 0x75, 0xcc, 0xa8, - 0x6d, 0x3f, 0x40, 0xbf, 0x9b, 0x1f, 0xd0, 0xfd, 0x7d, 0xf8, 0x3f, 0x96, - 0xbf, 0x5a, 0x0f, 0x0e, 0x29, 0xf9, 0xf5, 0xef, 0xcb, 0xd7, 0xb9, 0xcb, - 0x62, 0x2e, 0x8e, 0x6f, 0xbf, 0xbd, 0xd6, 0x5d, 0x40, 0xac, 0x44, 0xcc, - 0x19, 0x99, 0xe9, 0xdf, 0x9a, 0xb0, 0xc7, 0x49, 0x5e, 0xa9, 0xe0, 0x64, - 0xfd, 0x4c, 0xff, 0xa6, 0x94, 0x17, 0x3b, 0x18, 0xd3, 0x8b, 0x8c, 0x7a, - 0x3c, 0x9e, 0x52, 0x71, 0xcf, 0x23, 0x5e, 0xac, 0x21, 0x67, 0x6d, 0xef, - 0xfd, 0x1a, 0x8c, 0xab, 0x9c, 0xb8, 0x9b, 0xf6, 0xb7, 0x96, 0xae, 0x23, - 0xf9, 0xc3, 0xfa, 0x5e, 0x27, 0xea, 0xae, 0x2a, 0x43, 0xbc, 0xba, 0x10, - 0xdf, 0x33, 0x1d, 0xcc, 0xf7, 0x4a, 0x30, 0x64, 0x73, 0x69, 0xc9, 0xe1, - 0x05, 0x13, 0x45, 0x6f, 0x0e, 0x7b, 0xbd, 0xf5, 0x93, 0xe3, 0xc1, 0x7f, - 0x58, 0x99, 0xea, 0x1d, 0x36, 0x8e, 0x3b, 0x22, 0xa6, 0x1d, 0x73, 0x81, - 0x2c, 0x9f, 0xeb, 0xba, 0xe4, 0x79, 0x77, 0xb3, 0x32, 0x3b, 0x12, 0x98, - 0x58, 0xac, 0x38, 0x10, 0x0e, 0x94, 0xc5, 0xca, 0x23, 0x61, 0x2c, 0x4b, - 0x77, 0xf9, 0x7c, 0xf6, 0x33, 0xf4, 0x08, 0xce, 0x2d, 0x32, 0x99, 0xfb, - 0xc3, 0xb9, 0x8c, 0xba, 0x6f, 0xa4, 0x5e, 0xb7, 0x98, 0x1f, 0x59, 0x19, - 0xdb, 0xef, 0xdd, 0x88, 0x31, 0x07, 0x5b, 0x4b, 0xfd, 0x3a, 0xa8, 0xc7, - 0x9f, 0xe7, 0xf4, 0x2b, 0x3a, 0x2d, 0x19, 0xfb, 0x9d, 0x75, 0x92, 0xfa, - 0x75, 0xb3, 0x3d, 0x37, 0xdb, 0x2b, 0x1a, 0xbb, 0x54, 0xcf, 0x85, 0x94, - 0x67, 0x99, 0x2d, 0xc3, 0x42, 0x79, 0x86, 0xe9, 0x8f, 0x2a, 0x32, 0x1e, - 0xc1, 0xf7, 0x3f, 0x37, 0xa6, 0x1f, 0x4f, 0xc9, 0x55, 0x44, 0xff, 0x7e, - 0xea, 0x5f, 0x30, 0x5c, 0xe6, 0xa0, 0x4e, 0xd6, 0xbb, 0x7a, 0x80, 0x97, - 0x98, 0xcc, 0x2a, 0xa8, 0x32, 0x22, 0x78, 0xaa, 0xd9, 0x83, 0xb7, 0x12, - 0xa5, 0xf6, 0xb8, 0xaf, 0x9a, 0x6b, 0x59, 0x4f, 0x86, 0xfc, 0xf8, 0x85, - 0x51, 0x1b, 0x5e, 0xa0, 0xea, 0xcc, 0x1f, 0xbd, 0x48, 0x10, 0x67, 0xbb, - 0x92, 0xb3, 0x38, 0x5f, 0x5e, 0x6c, 0x4d, 0xa2, 0x9d, 0xf6, 0xe4, 0x77, - 0x44, 0x80, 0x33, 0x09, 0x23, 0xb8, 0x85, 0xfd, 0x0f, 0x7b, 0xeb, 0xc9, - 0xd3, 0xd5, 0x46, 0xd2, 0xbd, 0x78, 0x51, 0xc4, 0x88, 0x6f, 0xc3, 0xcf, - 0xac, 0x21, 0xe2, 0x7c, 0x41, 0x48, 0xd6, 0x1c, 0x67, 0xe3, 0x19, 0xcd, - 0x81, 0x17, 0x83, 0xcc, 0x87, 0x2b, 0x1c, 0x28, 0x31, 0xde, 0xb6, 0x7e, - 0xe0, 0x95, 0x7e, 0x64, 0x2c, 0x33, 0x38, 0x0e, 0xc5, 0xc6, 0xc2, 0xad, - 0xc9, 0x7a, 0xea, 0xfb, 0xf2, 0xfe, 0xff, 0x8f, 0x35, 0xe9, 0x95, 0xfe, - 0x75, 0xcd, 0xaf, 0x72, 0x0c, 0x7f, 0x14, 0xbb, 0xbf, 0x6f, 0xbd, 0x64, - 0xb7, 0x79, 0xbb, 0x3b, 0x1b, 0x4f, 0xa5, 0xbd, 0xb7, 0x38, 0x3e, 0x69, - 0x33, 0xdf, 0x8f, 0xe8, 0xed, 0x8c, 0x5b, 0xfc, 0x79, 0x6b, 0x52, 0xf4, - 0x27, 0x78, 0x75, 0xd2, 0xc2, 0x34, 0x39, 0x7f, 0xd6, 0x2e, 0x1b, 0xa7, - 0xbe, 0xba, 0x68, 0x43, 0x8c, 0xe1, 0x3e, 0xd8, 0xbb, 0x3b, 0x34, 0x3b, - 0x9f, 0xdb, 0xcc, 0x1c, 0x60, 0xc8, 0x5b, 0x8e, 0xad, 0x26, 0xed, 0xce, - 0x50, 0xe7, 0x38, 0x61, 0xe1, 0xa4, 0x29, 0xe7, 0x2e, 0x4c, 0x7a, 0x1d, - 0xd8, 0x66, 0x3a, 0xb1, 0xce, 0x50, 0x75, 0xb9, 0xee, 0x08, 0xc9, 0xb9, - 0x0b, 0xfe, 0x6a, 0x05, 0x3b, 0x18, 0x3e, 0xd6, 0x1b, 0x5d, 0x7e, 0xb9, - 0xbe, 0x24, 0x24, 0xe7, 0x0a, 0xda, 0xa8, 0x93, 0xb8, 0xa6, 0x60, 0x83, - 0x21, 0xcf, 0x4d, 0xb3, 0xfc, 0x39, 0x06, 0xcb, 0xda, 0x61, 0x36, 0x5c, - 0x57, 0xc2, 0x72, 0x67, 0x4d, 0xe1, 0x83, 0x87, 0xef, 0x98, 0x1f, 0x88, - 0x47, 0x0b, 0xa0, 0xc7, 0x8a, 0xe8, 0xa7, 0x5b, 0x7b, 0x67, 0xb3, 0x9e, - 0x42, 0x6e, 0xe0, 0xf4, 0x6d, 0x87, 0xc4, 0xcf, 0x80, 0xff, 0xa7, 0x4c, - 0xb2, 0x86, 0xbc, 0xf3, 0xa8, 0x59, 0xc3, 0x7f, 0x9a, 0xf3, 0x56, 0x6e, - 0x38, 0xdb, 0x5f, 0x85, 0xbe, 0xae, 0x48, 0x99, 0x17, 0x2c, 0x63, 0xae, - 0x10, 0x27, 0xbe, 0x8f, 0x8c, 0x39, 0xb1, 0x25, 0x69, 0x68, 0x07, 0x6d, - 0xfe, 0xe7, 0xa4, 0x2e, 0x9c, 0xcc, 0xcf, 0x03, 0xda, 0x84, 0x92, 0x3f, - 0x9f, 0x2d, 0xd8, 0x40, 0x3e, 0x2f, 0xf8, 0x16, 0xb7, 0x9e, 0xad, 0x17, - 0xaa, 0xe1, 0xf6, 0xc7, 0x52, 0x1e, 0x1e, 0x1a, 0x0f, 0xaf, 0x7f, 0x4d, - 0xca, 0xe7, 0x6f, 0x4b, 0xc1, 0xdf, 0x9a, 0xca, 0xdb, 0x65, 0xde, 0xb7, - 0x05, 0xdb, 0x2c, 0x72, 0xd6, 0x6c, 0x6e, 0xd6, 0x25, 0xb9, 0x0f, 0xe4, - 0xb9, 0xdf, 0xe1, 0x3b, 0x9e, 0xa3, 0xad, 0xbb, 0x98, 0x0f, 0x6c, 0x33, - 0xe2, 0x51, 0x79, 0x0e, 0x69, 0x84, 0x74, 0x5f, 0x81, 0xe2, 0xc7, 0xd6, - 0xba, 0xdf, 0x72, 0x3e, 0xc9, 0x93, 0x53, 0x9f, 0x29, 0xca, 0xce, 0x87, - 0xf8, 0x99, 0x60, 0x80, 0x9f, 0xf9, 0x92, 0xcf, 0xdf, 0xc5, 0x7e, 0x36, - 0xa7, 0xa6, 0xfa, 0x80, 0x82, 0x9b, 0xd8, 0x56, 0x43, 0x08, 0xce, 0xa5, - 0x75, 0xbf, 0xb1, 0x32, 0xde, 0xec, 0x33, 0xc8, 0x2c, 0xe6, 0x81, 0x36, - 0x67, 0xf7, 0xe9, 0xdc, 0x5f, 0x27, 0xfb, 0x8e, 0x14, 0x0c, 0xd3, 0xa7, - 0x36, 0xa5, 0xc5, 0x9e, 0xb2, 0x7a, 0x8d, 0xff, 0x01, 0xfe, 0x98, 0xb8, - 0x37, 0x89, 0x58, 0x41, 0x44, 0xf0, 0xc7, 0xed, 0x7f, 0x29, 0x55, 0x47, - 0x0e, 0x2f, 0xcf, 0xf2, 0xdd, 0x9c, 0x67, 0x8f, 0xff, 0xc5, 0xd4, 0xf5, - 0xb8, 0x67, 0x4f, 0x18, 0xeb, 0xf6, 0xa0, 0xae, 0x88, 0x72, 0x17, 0x86, - 0x02, 0xfe, 0x51, 0x68, 0xfe, 0x67, 0xa8, 0x87, 0x13, 0x94, 0xed, 0xe4, - 0x25, 0xb2, 0x89, 0xde, 0xe0, 0xbf, 0x2f, 0xe1, 0x46, 0x2a, 0xf4, 0xa1, - 0x15, 0xb7, 0x79, 0x86, 0xd7, 0xbf, 0x31, 0xe1, 0x47, 0xc6, 0xe6, 0xac, - 0xae, 0x22, 0xc9, 0x1f, 0xbb, 0x93, 0xf1, 0x28, 0xd3, 0xe1, 0xdc, 0x9c, - 0xea, 0x61, 0x99, 0xcf, 0x33, 0x09, 0xb9, 0x17, 0xfd, 0x9a, 0x0a, 0xdd, - 0xaf, 0x32, 0x7e, 0xf6, 0x9b, 0x62, 0xb3, 0x35, 0xa2, 0x93, 0x20, 0x2b, - 0xc6, 0x3d, 0x91, 0x40, 0x4b, 0x1d, 0xaf, 0x6b, 0x0b, 0x10, 0xab, 0x88, - 0x08, 0x27, 0xf4, 0xfa, 0x6b, 0xc7, 0x7d, 0x7e, 0x73, 0x1c, 0xfe, 0x2b, - 0xc7, 0xa7, 0x8a, 0x40, 0x6e, 0xff, 0x89, 0xb9, 0x9f, 0xd7, 0xbf, 0x36, - 0x31, 0x1b, 0x6a, 0x24, 0x6e, 0x2d, 0xa9, 0x3f, 0x67, 0xcd, 0x8e, 0x18, - 0x99, 0x93, 0x94, 0xe1, 0xc3, 0x6b, 0xf5, 0xf8, 0x0c, 0xc7, 0x89, 0x87, - 0xb4, 0x29, 0x7d, 0xbc, 0x1f, 0xfa, 0xff, 0xdb, 0x47, 0x3e, 0xb6, 0x89, - 0xfc, 0x12, 0xdf, 0x72, 0x73, 0xaa, 0xe6, 0xc7, 0xa2, 0x70, 0x4e, 0x39, - 0x1f, 0xc9, 0x7c, 0xac, 0xb2, 0xac, 0x56, 0xc3, 0x97, 0x7b, 0xfe, 0x07, - 0xda, 0xcb, 0x89, 0xeb, 0x9c, 0x58, 0x4c, 0x7b, 0x6f, 0xf8, 0x6b, 0x27, - 0xa2, 0xbe, 0x42, 0xc6, 0x50, 0xd9, 0x53, 0xf0, 0x4c, 0xdd, 0xa4, 0x35, - 0x61, 0xd4, 0xa1, 0x21, 0x2d, 0xcf, 0x63, 0x1d, 0xb4, 0x63, 0x0b, 0x8f, - 0x9b, 0x72, 0x5f, 0xf0, 0x24, 0x1e, 0x73, 0xd0, 0x26, 0xdc, 0x86, 0xde, - 0xf2, 0x0f, 0x4a, 0x19, 0x8a, 0x23, 0xce, 0xe0, 0x04, 0xf4, 0xf0, 0x7a, - 0x72, 0x63, 0x7f, 0xc5, 0x3c, 0x53, 0xd4, 0xfe, 0x4e, 0x22, 0x60, 0x06, - 0x72, 0xf1, 0xe7, 0x2c, 0xe7, 0xeb, 0xdd, 0x84, 0xb1, 0xee, 0xb9, 0xdc, - 0xf9, 0xbf, 0xa5, 0xa6, 0xe6, 0xbf, 0x62, 0x77, 0x6e, 0xf7, 0xe6, 0x04, - 0xde, 0x77, 0xd4, 0xe3, 0xfd, 0xfd, 0x66, 0x01, 0xf3, 0x36, 0xb1, 0x47, - 0xb7, 0x7b, 0x6b, 0x02, 0x93, 0x4e, 0x5e, 0x3b, 0x6b, 0xce, 0x22, 0x76, - 0xa9, 0xbc, 0x16, 0x96, 0x58, 0x10, 0xd3, 0x18, 0x47, 0x8b, 0x23, 0x5e, - 0x77, 0xf1, 0x38, 0xb4, 0x22, 0xa3, 0x8c, 0x79, 0x31, 0x1a, 0x1d, 0x7d, - 0xba, 0xbf, 0xc9, 0x51, 0xc7, 0xfc, 0xd8, 0xaf, 0xb8, 0x8c, 0x6f, 0x31, - 0xcf, 0x97, 0xf5, 0xaa, 0x30, 0xc7, 0xed, 0x64, 0x85, 0x9d, 0xd3, 0xd4, - 0x88, 0x42, 0xcc, 0x2b, 0xc3, 0xbd, 0xda, 0x86, 0xc5, 0x6a, 0xa4, 0x1f, - 0xb7, 0xd6, 0xbb, 0x1b, 0xcb, 0xc7, 0xf3, 0x3a, 0x41, 0xcc, 0x13, 0x61, - 0x0e, 0x63, 0x40, 0x2d, 0x8d, 0x88, 0x6e, 0xfc, 0x8d, 0x7d, 0x63, 0x22, - 0xab, 0xe6, 0xee, 0x1d, 0xf3, 0x14, 0xa3, 0x38, 0x4c, 0x4c, 0xfa, 0x57, - 0xdf, 0x7f, 0xae, 0xde, 0x64, 0x91, 0xe0, 0xba, 0xcb, 0x90, 0xff, 0xb6, - 0x3d, 0xb9, 0xdd, 0x91, 0x63, 0x31, 0x77, 0xc0, 0xb2, 0x18, 0x0f, 0x7d, - 0x50, 0x66, 0x71, 0x3c, 0xf4, 0x29, 0xce, 0x4d, 0x5b, 0xea, 0x23, 0xeb, - 0x33, 0x4e, 0x3b, 0xd6, 0xbb, 0x0b, 0x23, 0xe1, 0xbb, 0xde, 0x36, 0x7e, - 0x6f, 0xbd, 0x95, 0x60, 0x5e, 0x4d, 0xdf, 0x2d, 0x20, 0x6e, 0x6f, 0x37, - 0x9d, 0x4d, 0x4b, 0x15, 0x05, 0xdd, 0xc6, 0x3c, 0xad, 0x88, 0xf1, 0x68, - 0x13, 0xfd, 0x37, 0xe6, 0x35, 0x82, 0xfb, 0xc1, 0x72, 0xa9, 0xb5, 0x6b, - 0x5d, 0x91, 0x8d, 0x77, 0x8d, 0xd4, 0x8b, 0xcf, 0x9f, 0xbf, 0xeb, 0x39, - 0xa3, 0x19, 0xdd, 0xe9, 0x41, 0xf4, 0xa4, 0xb3, 0xfd, 0x64, 0x30, 0xfb, - 0x13, 0xfa, 0x59, 0xbb, 0xb6, 0x30, 0x22, 0x1c, 0xeb, 0xe8, 0x5d, 0x07, - 0x8c, 0x28, 0xb6, 0xa4, 0x37, 0xde, 0x75, 0xb6, 0xbe, 0x9f, 0xff, 0xb3, - 0x75, 0x86, 0x50, 0xfe, 0x89, 0x75, 0x4a, 0x22, 0xd2, 0x47, 0x98, 0x7d, - 0x6c, 0xbc, 0x6b, 0xdd, 0xa2, 0xaf, 0x63, 0x73, 0x7a, 0xdd, 0x9f, 0xed, - 0xa7, 0x94, 0x75, 0x8a, 0x23, 0x1d, 0xad, 0x37, 0x05, 0x36, 0xde, 0x95, - 0x5a, 0xd4, 0xc3, 0x3e, 0x56, 0x31, 0x8e, 0x64, 0xeb, 0x44, 0x15, 0xc7, - 0x27, 0xea, 0xa0, 0x28, 0xd2, 0xd3, 0x3a, 0x3f, 0xf0, 0x7b, 0x6b, 0x5e, - 0x6f, 0x81, 0xad, 0x03, 0x17, 0x75, 0xf0, 0xa8, 0xe9, 0xcc, 0x04, 0x1c, - 0xb6, 0x0e, 0x3a, 0x7c, 0xd4, 0x41, 0x1f, 0x75, 0x90, 0xa9, 0x36, 0xc2, - 0xef, 0x51, 0x07, 0xf3, 0xc6, 0xd6, 0xae, 0x2d, 0x8a, 0xc0, 0xe9, 0x30, - 0x5e, 0x77, 0x38, 0x39, 0x17, 0x2e, 0x63, 0x2d, 0xf5, 0xb6, 0xf1, 0xae, - 0x39, 0x8b, 0x6c, 0x9d, 0x7f, 0xd9, 0x1d, 0xd8, 0x60, 0xef, 0xdd, 0xdb, - 0x94, 0x6e, 0xe3, 0xd1, 0xc4, 0xe3, 0x61, 0x1e, 0xdd, 0xcc, 0x4d, 0xee, - 0xa0, 0xae, 0x1a, 0x39, 0x8e, 0x15, 0x94, 0xab, 0x9d, 0xbf, 0x5b, 0xf8, - 0xbb, 0x83, 0xbf, 0x65, 0x7e, 0xd4, 0x0b, 0xb2, 0xc5, 0x2e, 0xc8, 0xe6, - 0xa0, 0x3c, 0x1e, 0x62, 0x94, 0x8c, 0x69, 0xe2, 0xcb, 0x37, 0x05, 0x62, - 0x6c, 0xe3, 0xa9, 0x62, 0xd9, 0xf7, 0xe4, 0x32, 0xe2, 0x3e, 0x27, 0x44, - 0x3e, 0xbd, 0x65, 0x1d, 0x32, 0xc4, 0xd8, 0xdf, 0x65, 0x31, 0x96, 0xb2, - 0x95, 0x71, 0x7e, 0x5e, 0x59, 0x34, 0x34, 0xdd, 0x63, 0xc0, 0xe7, 0x36, - 0xe2, 0xe8, 0x4d, 0x27, 0xa8, 0x03, 0xb1, 0x93, 0x07, 0xa9, 0xbf, 0x4e, - 0x74, 0x19, 0x27, 0xf4, 0xec, 0xde, 0x89, 0xbd, 0x94, 0x21, 0x48, 0x7e, - 0xe8, 0x81, 0x33, 0xa2, 0xfb, 0x1b, 0x1d, 0x5d, 0x41, 0x17, 0x68, 0xcb, - 0xc5, 0x62, 0xcb, 0x71, 0xc6, 0x35, 0xc1, 0x3a, 0xb7, 0xd6, 0x66, 0xe3, - 0x5f, 0x7c, 0xbe, 0x0b, 0x1e, 0x6d, 0x4d, 0x2a, 0x1f, 0x0b, 0x3c, 0x5a, - 0x6b, 0x42, 0xfc, 0x4a, 0xd6, 0xfc, 0xc3, 0x76, 0x2c, 0x3f, 0x9e, 0x7e, - 0xb1, 0x18, 0x65, 0xb6, 0x8f, 0x95, 0x39, 0x8d, 0x6c, 0xbb, 0x1a, 0xdb, - 0x6d, 0x76, 0x68, 0xb8, 0xe8, 0x23, 0xba, 0xd6, 0xec, 0x90, 0x7d, 0xae, - 0xf4, 0xfe, 0x54, 0xae, 0x5e, 0x16, 0x27, 0x16, 0xbb, 0x6c, 0x9c, 0x60, - 0x1b, 0xc5, 0xc0, 0x92, 0xc4, 0xe5, 0xfd, 0x4b, 0x7f, 0xd2, 0x6f, 0x57, - 0x85, 0x8a, 0x09, 0xfb, 0x99, 0xcb, 0x91, 0x74, 0x0c, 0x83, 0xc9, 0xa9, - 0x7b, 0xf9, 0xf4, 0xa3, 0x6c, 0xff, 0x70, 0x9c, 0xfa, 0x98, 0x65, 0xc8, - 0x3e, 0x3f, 0xd9, 0xdb, 0x37, 0x75, 0x5f, 0x9f, 0xc8, 0x56, 0x58, 0x42, - 0x00, 0xc1, 0x01, 0xe2, 0x4c, 0xb4, 0x59, 0xea, 0x5b, 0xd6, 0x1b, 0xf3, - 0x82, 0xc8, 0x54, 0x39, 0x31, 0x38, 0x17, 0x18, 0xe8, 0x93, 0x7d, 0x57, - 0x47, 0x63, 0xab, 0x99, 0x97, 0x45, 0x2b, 0x6b, 0xb5, 0x4d, 0xaa, 0xec, - 0x99, 0x3a, 0xf6, 0xe5, 0x6e, 0xa3, 0x46, 0xeb, 0x56, 0x33, 0x87, 0x88, - 0xdd, 0x7b, 0x81, 0x69, 0x25, 0xe2, 0x6b, 0x15, 0x46, 0xb4, 0xa7, 0x02, - 0x73, 0xe1, 0xaf, 0xb4, 0xf1, 0x32, 0xfe, 0x94, 0x6a, 0x04, 0x57, 0xda, - 0x38, 0xf8, 0xa1, 0x35, 0xc4, 0xb8, 0xf4, 0x95, 0xb9, 0x3f, 0x28, 0xce, - 0xe6, 0xd9, 0xd1, 0x75, 0xd3, 0x38, 0x57, 0xbf, 0x58, 0xa0, 0xfb, 0x53, - 0x8a, 0xe8, 0x48, 0xb8, 0x49, 0x02, 0xdb, 0xc8, 0x75, 0x7f, 0x33, 0x37, - 0x82, 0x83, 0xfc, 0xff, 0xf3, 0xeb, 0x65, 0x0f, 0xaa, 0x65, 0x05, 0x03, - 0xf3, 0xc2, 0x15, 0x1c, 0xc3, 0x8b, 0xbc, 0xdf, 0x93, 0x7e, 0xdb, 0x3a, - 0x3b, 0xcd, 0xe8, 0x5f, 0xc6, 0x40, 0x32, 0x30, 0xae, 0x6b, 0x93, 0xea, - 0x7f, 0x76, 0x4f, 0x1d, 0xdc, 0x65, 0x1c, 0xcb, 0xf7, 0x02, 0xb5, 0x5a, - 0x9f, 0xaa, 0x96, 0x88, 0x5e, 0x07, 0xc6, 0x7f, 0x3c, 0x65, 0xaf, 0x47, - 0x9e, 0x1f, 0xda, 0x6b, 0x1d, 0x3d, 0x43, 0xf4, 0xa9, 0x21, 0x2d, 0x1a, - 0xa7, 0xde, 0xdd, 0x55, 0x1c, 0xf3, 0x57, 0xe6, 0xde, 0x6a, 0x8f, 0xb3, - 0xd2, 0x98, 0xc1, 0x31, 0x2a, 0xd0, 0xe6, 0xfe, 0x2c, 0xb7, 0xee, 0xd9, - 0x40, 0x36, 0x33, 0x64, 0x35, 0xd2, 0x06, 0x0b, 0x58, 0xe7, 0x46, 0x73, - 0xdf, 0xf4, 0xae, 0x3a, 0xdd, 0xf7, 0x15, 0xc6, 0xce, 0xd0, 0xdc, 0x5f, - 0x5b, 0x51, 0xcd, 0x69, 0x7e, 0x93, 0xa3, 0xbe, 0x27, 0x21, 0x65, 0x65, - 0x5e, 0x8d, 0xe8, 0x5c, 0xe5, 0x5d, 0x0b, 0xd5, 0x81, 0xf0, 0x5c, 0x7b, - 0xfc, 0xc0, 0xdd, 0xa9, 0x04, 0xb6, 0x27, 0xa5, 0x4d, 0x05, 0xcb, 0x02, - 0xef, 0x58, 0xfe, 0x69, 0x09, 0x6c, 0x4d, 0xff, 0x29, 0xae, 0x37, 0x28, - 0x71, 0xbf, 0x25, 0x0e, 0x3d, 0x9a, 0x7d, 0xc6, 0x35, 0x5b, 0xd6, 0x94, - 0x65, 0x0f, 0xd2, 0x5d, 0x89, 0x00, 0xdc, 0xa5, 0xc4, 0xba, 0xb1, 0x80, - 0x3c, 0x13, 0xf5, 0x22, 0xd3, 0x2c, 0x65, 0x6a, 0xb4, 0x31, 0x64, 0xc8, - 0xc4, 0x64, 0x7d, 0xb2, 0xa7, 0x24, 0xbb, 0x9f, 0x82, 0x86, 0x57, 0xad, - 0x6b, 0x67, 0xc8, 0x9d, 0x9a, 0x0c, 0x69, 0x43, 0xc1, 0xfc, 0x40, 0x15, - 0x6a, 0x57, 0xbe, 0xfe, 0x66, 0x41, 0xa0, 0x80, 0xb8, 0x2d, 0xfe, 0x64, - 0xb4, 0x9f, 0xc4, 0xbf, 0xd3, 0xd7, 0x65, 0x6f, 0xd9, 0x16, 0xa9, 0xc7, - 0xb6, 0xe6, 0x22, 0xa5, 0x39, 0xc9, 0x33, 0x64, 0x9f, 0xb2, 0x65, 0xdd, - 0x14, 0x78, 0xcb, 0x8a, 0x56, 0x53, 0x1e, 0xf2, 0x9f, 0x6c, 0x5d, 0x29, - 0x93, 0xdb, 0x33, 0xa4, 0x34, 0xdc, 0x25, 0x3a, 0x79, 0xd6, 0x8c, 0x93, - 0x5d, 0x0b, 0xbe, 0x1e, 0x8b, 0xbd, 0x6d, 0x28, 0xf6, 0xb3, 0xca, 0x65, - 0x4a, 0x39, 0xe3, 0x95, 0xd3, 0x3f, 0x62, 0xe7, 0xdf, 0x61, 0x62, 0xa1, - 0xf0, 0x35, 0xc9, 0xa1, 0x9c, 0x78, 0xce, 0xa8, 0xc0, 0xb3, 0x5a, 0x96, - 0xfb, 0x10, 0x53, 0xf0, 0x6a, 0x62, 0x5e, 0x86, 0x1e, 0x42, 0x0e, 0x69, - 0xac, 0x3b, 0xaf, 0xfc, 0x3b, 0xf3, 0x2b, 0xe0, 0x95, 0x54, 0x3b, 0x1e, - 0x95, 0x75, 0x3d, 0xa5, 0xa6, 0xa9, 0xd6, 0x21, 0xfd, 0xb5, 0x63, 0x5b, - 0x5a, 0xda, 0x3a, 0x16, 0x3b, 0x60, 0xf4, 0xe7, 0x64, 0x15, 0xcc, 0x3c, - 0x16, 0x7b, 0xce, 0x78, 0xdc, 0x9e, 0x3b, 0x79, 0x7e, 0xd6, 0x63, 0x0a, - 0xb6, 0x14, 0x43, 0x25, 0x0f, 0x77, 0x18, 0x77, 0xc0, 0x51, 0xf1, 0x75, - 0xda, 0x9e, 0xec, 0xbf, 0xb9, 0x13, 0xce, 0x0a, 0x17, 0x7d, 0xf3, 0x6e, - 0xb8, 0x2a, 0x84, 0xfb, 0xe6, 0x79, 0x69, 0x94, 0xf7, 0x45, 0xb7, 0xe7, - 0x6d, 0xdd, 0x3a, 0x89, 0xa7, 0xdd, 0x92, 0x27, 0x19, 0xe5, 0xd4, 0x91, - 0xde, 0x42, 0x8e, 0x8c, 0x52, 0x62, 0x13, 0xe3, 0x90, 0xbb, 0x9c, 0x65, - 0xde, 0xa3, 0xde, 0xe7, 0xf5, 0x96, 0x90, 0x13, 0x5b, 0xd6, 0x87, 0xe4, - 0xc4, 0xf3, 0x03, 0xb5, 0x19, 0x83, 0xf1, 0x03, 0xb7, 0xe9, 0x4d, 0x71, - 0xe6, 0x88, 0xab, 0x8d, 0xf3, 0x56, 0x6c, 0x95, 0x94, 0xd1, 0x7d, 0x31, - 0x25, 0xdf, 0xc7, 0x02, 0xf8, 0xab, 0x2c, 0xb8, 0x22, 0xb2, 0x96, 0x2f, - 0x6b, 0xb8, 0x0d, 0xf2, 0xcc, 0xb0, 0x59, 0xc6, 0xef, 0x92, 0x75, 0x41, - 0x44, 0x27, 0x5c, 0x30, 0x32, 0x07, 0x65, 0xce, 0xa6, 0x5b, 0x08, 0x2c, - 0xfc, 0x1d, 0x73, 0x0b, 0x99, 0x9f, 0x9a, 0x4c, 0x9d, 0x92, 0x09, 0xfa, - 0xc8, 0x91, 0x9f, 0x80, 0xde, 0x9c, 0xa0, 0xae, 0x1b, 0x43, 0xb2, 0x0f, - 0xc0, 0xe9, 0x4b, 0xc0, 0xe6, 0xc5, 0xe6, 0x69, 0x7c, 0x06, 0xa5, 0xcc, - 0x05, 0xe7, 0x8e, 0xad, 0x40, 0x59, 0x45, 0xd4, 0x57, 0x8c, 0x6b, 0x78, - 0xde, 0x46, 0xbe, 0xff, 0x05, 0x94, 0xad, 0x6c, 0x41, 0x82, 0x63, 0x2f, - 0x35, 0xbe, 0xc4, 0x6b, 0x0f, 0xa3, 0x2f, 0xe9, 0xe2, 0x38, 0xfe, 0xd5, - 0x2a, 0xab, 0x16, 0xd9, 0x4c, 0x6f, 0x09, 0xf3, 0xf4, 0xa8, 0xad, 0x0b, - 0x62, 0x63, 0x52, 0xb8, 0x48, 0x6d, 0x74, 0x3d, 0x98, 0x2b, 0x57, 0xeb, - 0x2d, 0x6d, 0x4a, 0x07, 0x6d, 0xb6, 0x9b, 0x3a, 0x97, 0xb2, 0x96, 0xb5, - 0x3c, 0x30, 0x49, 0x1d, 0x77, 0xf0, 0xdc, 0xf0, 0xbf, 0x05, 0xf5, 0x9a, - 0x42, 0x9c, 0xb2, 0xe2, 0x9a, 0x8f, 0x76, 0xa9, 0xae, 0x12, 0xde, 0xb2, - 0x34, 0x74, 0xae, 0x44, 0xf6, 0x21, 0x67, 0xed, 0xf4, 0x68, 0x4e, 0x97, - 0xe7, 0xef, 0xea, 0x36, 0x5e, 0xb5, 0xaf, 0x3b, 0xec, 0xeb, 0xe1, 0xdc, - 0xf5, 0xa3, 0xbc, 0xfe, 0x3d, 0x5e, 0xef, 0xa1, 0xee, 0xd5, 0x2b, 0xa4, - 0xfe, 0x5a, 0x53, 0xea, 0x33, 0x45, 0x31, 0xba, 0x73, 0xf3, 0xd1, 0xd1, - 0x9a, 0x2d, 0xdb, 0xd3, 0x9a, 0x6d, 0xc3, 0xc9, 0x36, 0xe2, 0xd1, 0x62, - 0x98, 0x28, 0x61, 0x9c, 0x3f, 0x6b, 0x88, 0x5c, 0x9c, 0xbb, 0xb4, 0xc8, - 0xd5, 0xc6, 0xb8, 0xd2, 0xf5, 0x42, 0x31, 0xe2, 0x1d, 0x33, 0x6c, 0x3b, - 0x3c, 0x7a, 0x97, 0xec, 0x8f, 0x7b, 0x5b, 0x69, 0xf0, 0xc9, 0xb6, 0xca, - 0x24, 0x79, 0xe2, 0x43, 0xa6, 0x33, 0x5c, 0xe7, 0x98, 0x97, 0x29, 0x84, - 0x11, 0x3b, 0xaf, 0x7c, 0x64, 0xe3, 0x43, 0x22, 0xd5, 0xc0, 0x4c, 0x26, - 0x1e, 0x64, 0x0e, 0x12, 0x4c, 0x53, 0xb7, 0xad, 0x44, 0xec, 0xa3, 0xf6, - 0x1e, 0x39, 0xe7, 0xc4, 0x0a, 0x34, 0xe8, 0x0e, 0xcc, 0x0b, 0xcf, 0x60, - 0x26, 0x43, 0xbb, 0x34, 0x0b, 0x1d, 0xba, 0xff, 0x56, 0x7c, 0xc6, 0x23, - 0xf5, 0x0e, 0xa6, 0x32, 0xeb, 0x8a, 0x39, 0xa7, 0xdf, 0xa0, 0x1c, 0xdb, - 0x03, 0x22, 0xc7, 0xd7, 0x73, 0x72, 0xb4, 0x30, 0x66, 0x99, 0xda, 0xcd, - 0x81, 0x9e, 0x0b, 0x7a, 0x7b, 0xc1, 0xd6, 0xdb, 0xc3, 0x3c, 0x2f, 0x64, - 0xbe, 0x5c, 0x80, 0x13, 0x75, 0xde, 0xdc, 0x7e, 0x37, 0xc9, 0x7d, 0x04, - 0x7f, 0xcf, 0x7c, 0x69, 0xb5, 0xa1, 0x87, 0x1d, 0x36, 0x67, 0x76, 0x23, - 0x6e, 0xf3, 0x51, 0x79, 0x76, 0x5e, 0x86, 0xc7, 0xed, 0x72, 0x2e, 0xea, - 0xa4, 0x04, 0x4f, 0xe4, 0xfc, 0x45, 0xf6, 0x2e, 0x7c, 0xc3, 0xfe, 0xbd, - 0x97, 0x73, 0xeb, 0xa2, 0xaf, 0xe6, 0x63, 0x94, 0xac, 0x81, 0x6f, 0xb4, - 0x7d, 0x7f, 0x08, 0xc7, 0xec, 0xff, 0x99, 0x6c, 0xfe, 0x82, 0x6e, 0x53, - 0xf6, 0xfc, 0x94, 0x60, 0x93, 0x3c, 0x8b, 0x4c, 0x4b, 0x4e, 0x7d, 0x3d, - 0xb6, 0x70, 0x54, 0x6e, 0x83, 0x1c, 0x43, 0x13, 0x9b, 0xe8, 0x44, 0x9f, - 0x66, 0x7a, 0xd3, 0x75, 0x53, 0x73, 0x0f, 0x13, 0xfb, 0xeb, 0x7e, 0x6f, - 0x45, 0xed, 0x7c, 0xe4, 0x94, 0x75, 0xc0, 0x38, 0x11, 0xa2, 0x07, 0xaf, - 0x2b, 0xb0, 0xf5, 0x7b, 0xfe, 0x2e, 0x7b, 0x9f, 0x20, 0x65, 0x7e, 0x21, - 0x21, 0x71, 0x74, 0x36, 0x52, 0xa6, 0xc8, 0xe6, 0x6c, 0xde, 0xc1, 0x39, - 0xe9, 0x4e, 0x06, 0xa2, 0x57, 0xf2, 0xde, 0x04, 0x63, 0xd9, 0x26, 0xea, - 0x33, 0xd6, 0x2c, 0x3c, 0xa8, 0x0d, 0x7b, 0x69, 0x63, 0xe3, 0xa6, 0x65, - 0x1d, 0x24, 0x46, 0x94, 0xcf, 0x53, 0x91, 0xa9, 0x6e, 0x43, 0x92, 0xb1, - 0xe9, 0xa0, 0xd1, 0xf0, 0x99, 0x02, 0xc4, 0xfd, 0x6e, 0xe8, 0xbe, 0xad, - 0x1c, 0xcd, 0x43, 0x9c, 0xaf, 0x13, 0xa6, 0xf0, 0x33, 0xe7, 0xf9, 0xa5, - 0x30, 0xc2, 0x8b, 0x1d, 0xff, 0x6a, 0x4d, 0xda, 0xcf, 0x51, 0xbb, 0xfe, - 0x27, 0x65, 0x68, 0x17, 0xe7, 0x2d, 0xe7, 0x1c, 0xbf, 0x17, 0x90, 0xe7, - 0xe0, 0x40, 0x6d, 0x6f, 0xc3, 0x3a, 0x91, 0xe1, 0x40, 0xc8, 0x19, 0x3b, - 0x88, 0x40, 0xf3, 0x06, 0xe5, 0x22, 0x07, 0xbf, 0x72, 0xcc, 0xc4, 0x68, - 0xdd, 0x8b, 0xe4, 0x0b, 0x52, 0xbf, 0x10, 0x4f, 0x9b, 0xcf, 0x5b, 0x35, - 0xd3, 0xbf, 0x67, 0x1d, 0x32, 0xd4, 0xf5, 0xd4, 0x76, 0xac, 0x94, 0x6d, - 0x95, 0xb0, 0xad, 0x7b, 0x03, 0xba, 0xb9, 0x83, 0x6d, 0x3d, 0x93, 0x38, - 0x11, 0x74, 0xb3, 0xad, 0x27, 0x4c, 0xe1, 0xe0, 0xce, 0xa6, 0x26, 0xce, - 0x6d, 0x57, 0x32, 0xe0, 0xdb, 0x46, 0xb9, 0x24, 0x37, 0xba, 0x33, 0x21, - 0xef, 0x74, 0x7c, 0x9d, 0xe3, 0x89, 0xb6, 0xbb, 0xd0, 0xf0, 0x50, 0x19, - 0xed, 0xa7, 0x1c, 0x79, 0x5b, 0xd7, 0x7d, 0xc4, 0x3b, 0xdc, 0xcb, 0x32, - 0x6f, 0x06, 0x66, 0xe3, 0x95, 0x50, 0xc3, 0xca, 0xd9, 0x70, 0xc6, 0x0e, - 0x29, 0x81, 0xa6, 0x0d, 0x4a, 0x5c, 0x13, 0x5b, 0xbc, 0x27, 0xa5, 0x07, - 0x1b, 0x21, 0xd8, 0xdd, 0x42, 0x7d, 0xcc, 0xc6, 0x87, 0x0b, 0x45, 0x2e, - 0x67, 0x38, 0xe8, 0x08, 0x74, 0x3c, 0xcf, 0xf9, 0x2d, 0x9b, 0x97, 0xcd, - 0xfb, 0xd2, 0xf6, 0xbe, 0xce, 0x16, 0xf4, 0xa5, 0x4f, 0xbd, 0x77, 0xc0, - 0x80, 0xf3, 0x68, 0xdd, 0xa3, 0x16, 0xec, 0x77, 0x40, 0x1a, 0x64, 0x1e, - 0x5a, 0x64, 0x1e, 0x8a, 0xe9, 0x4f, 0x37, 0x51, 0xee, 0xf5, 0xb6, 0xdc, - 0xb3, 0x31, 0x6c, 0xca, 0x7a, 0x92, 0x53, 0xbb, 0x07, 0x3d, 0xc4, 0xce, - 0xc0, 0xf9, 0x2e, 0xf6, 0xf3, 0x26, 0x65, 0x9e, 0x47, 0xbd, 0x4f, 0x36, - 0x0b, 0x3f, 0x7c, 0x18, 0xbd, 0xc9, 0xfc, 0x3b, 0x22, 0x0a, 0x52, 0x01, - 0xe9, 0xe3, 0x61, 0xf2, 0xa5, 0x2e, 0x6b, 0xb2, 0x5a, 0xae, 0xef, 0x65, - 0x2e, 0x1d, 0xd5, 0xe8, 0x0f, 0xd4, 0x3b, 0xf4, 0xd9, 0xd0, 0x27, 0xce, - 0x38, 0xa2, 0xf4, 0x01, 0xd3, 0x7b, 0x9e, 0xd8, 0x70, 0x14, 0x1d, 0x16, - 0x2a, 0x6c, 0x7b, 0xf8, 0xf9, 0x88, 0xf1, 0x0b, 0x45, 0x62, 0x7b, 0x86, - 0x3a, 0x60, 0xb6, 0xdf, 0x2e, 0x3a, 0x28, 0xa5, 0xcf, 0x8e, 0x05, 0x74, - 0xff, 0x2b, 0x94, 0x67, 0x07, 0xe5, 0x59, 0x91, 0x9d, 0x43, 0xdf, 0x16, - 0x45, 0x7c, 0x3a, 0xd0, 0xbc, 0x9a, 0xd7, 0xb7, 0x53, 0x9e, 0x40, 0xaf, - 0x82, 0xa1, 0xe6, 0x6e, 0xf2, 0xb1, 0x0e, 0xea, 0xe0, 0xa2, 0x3c, 0x6e, - 0x7b, 0xce, 0x3a, 0xc8, 0x05, 0x0a, 0x99, 0xff, 0x0b, 0x7e, 0x6b, 0x18, - 0xa6, 0x9d, 0xee, 0xe7, 0x8c, 0x44, 0xbd, 0x2a, 0x0a, 0x0d, 0xc1, 0x80, - 0x6a, 0x5e, 0x73, 0x71, 0x6e, 0xca, 0x71, 0x48, 0xdb, 0x6b, 0xef, 0x69, - 0xce, 0xe6, 0xea, 0x1f, 0x59, 0xa3, 0x5e, 0xe1, 0x67, 0xb2, 0xde, 0x24, - 0x6b, 0x32, 0x71, 0x4f, 0x76, 0x4f, 0xb5, 0x8b, 0x3a, 0xc9, 0x5e, 0x7f, - 0x41, 0x73, 0xe4, 0xf2, 0x66, 0xb9, 0xfe, 0x81, 0xf5, 0xac, 0x5d, 0x5e, - 0xca, 0xb9, 0x6c, 0x2e, 0x5c, 0x6c, 0x97, 0xfb, 0xc0, 0x7a, 0x51, 0x73, - 0x4e, 0x29, 0x97, 0x7f, 0x86, 0x77, 0xe2, 0x6b, 0x4e, 0x62, 0x5e, 0xe1, - 0xdc, 0xc5, 0x38, 0x69, 0x9c, 0xaa, 0x39, 0x5d, 0xd7, 0xc9, 0x38, 0x36, - 0x75, 0x1f, 0x98, 0x85, 0x27, 0xed, 0x1c, 0xb7, 0x6b, 0xbe, 0x03, 0x27, - 0x76, 0x16, 0xd0, 0x27, 0xa3, 0x9a, 0xac, 0x87, 0x45, 0x4b, 0x72, 0x7b, - 0x55, 0x24, 0x6f, 0x0c, 0xfa, 0xd5, 0xab, 0x6d, 0x6e, 0x18, 0x55, 0xff, - 0xdc, 0x7e, 0x3b, 0xe1, 0x2e, 0x9d, 0xd8, 0x6f, 0xe4, 0x39, 0xcb, 0x89, - 0x47, 0x55, 0xe2, 0xe4, 0x80, 0xb9, 0x58, 0x62, 0xb3, 0x9f, 0xf5, 0x83, - 0x31, 0x75, 0x2a, 0xb7, 0x59, 0xed, 0x41, 0x59, 0xd7, 0x36, 0x07, 0x64, - 0x9f, 0xa9, 0xec, 0x19, 0x95, 0xbe, 0x8a, 0x72, 0xeb, 0x3c, 0x9f, 0xc4, - 0x35, 0xf2, 0x7d, 0x09, 0xdf, 0xf8, 0x20, 0xc7, 0xdd, 0xf4, 0x60, 0xd4, - 0x96, 0xf3, 0x57, 0xd6, 0x4a, 0x2d, 0x33, 0x43, 0xc3, 0xa5, 0xb2, 0x47, - 0x73, 0xb2, 0xc7, 0x3e, 0x71, 0x9d, 0x4a, 0xfa, 0x99, 0xda, 0x66, 0x7e, - 0x4f, 0xb7, 0xac, 0x61, 0xca, 0x3d, 0x05, 0x5d, 0xc4, 0xa1, 0xa8, 0xd6, - 0xc0, 0x38, 0xaf, 0xfb, 0xd6, 0x70, 0x3e, 0xe2, 0x5e, 0xd9, 0xcb, 0x9e, - 0x8f, 0x91, 0x85, 0xc8, 0xae, 0x25, 0xca, 0x7e, 0x87, 0xec, 0xfa, 0x21, - 0xed, 0x1e, 0x5d, 0xa9, 0xdf, 0x59, 0x19, 0xaf, 0x93, 0xb1, 0xf0, 0xe2, - 0x3e, 0xea, 0x21, 0xea, 0x55, 0xd6, 0x41, 0xb6, 0x5c, 0x58, 0xab, 0x90, - 0x35, 0x1a, 0x89, 0xbd, 0xbf, 0xb5, 0x5a, 0x2f, 0x29, 0x3b, 0x75, 0x4f, - 0x79, 0x75, 0x4c, 0x9e, 0x83, 0x8d, 0xe6, 0xd6, 0xb1, 0x1b, 0xff, 0xe0, - 0x39, 0xd8, 0x04, 0x6d, 0x09, 0xd1, 0x2d, 0xe4, 0x76, 0x71, 0x74, 0x63, - 0x34, 0x51, 0xab, 0x6d, 0x85, 0x26, 0xeb, 0xb7, 0xfc, 0xeb, 0xc6, 0xa1, - 0x04, 0xa2, 0x05, 0x57, 0x95, 0x93, 0x6f, 0x21, 0xea, 0x60, 0x8c, 0x7a, - 0x22, 0x51, 0xdb, 0xb4, 0x9d, 0x63, 0xf2, 0xaf, 0xec, 0xc6, 0x70, 0xa2, - 0xe1, 0x4b, 0x8c, 0x23, 0xfe, 0x12, 0x9b, 0xeb, 0x44, 0xff, 0xcb, 0x01, - 0xe2, 0xc0, 0xe6, 0xdc, 0x1a, 0x52, 0x6b, 0xe2, 0xd7, 0x94, 0xdf, 0x16, - 0x92, 0xf5, 0xfe, 0x54, 0xb9, 0x09, 0xe6, 0xd3, 0xa7, 0xb0, 0xb6, 0x5f, - 0xc1, 0xb3, 0xc6, 0x29, 0xac, 0x19, 0x12, 0x79, 0x4e, 0xa1, 0xad, 0xff, - 0xfb, 0xd8, 0xdf, 0x3f, 0x1d, 0x8d, 0xb6, 0x6e, 0x3a, 0xb0, 0x61, 0xd7, - 0x11, 0xec, 0x48, 0x5a, 0xd8, 0x1e, 0xf2, 0x60, 0xfd, 0x3e, 0x05, 0xcb, - 0x03, 0xc7, 0xb0, 0x75, 0x97, 0x85, 0x39, 0xa1, 0x4e, 0x34, 0x99, 0x25, - 0x28, 0xac, 0x98, 0xb7, 0x4e, 0x65, 0xb9, 0xd6, 0xe1, 0x8e, 0xdc, 0xfe, - 0xe5, 0x43, 0xc4, 0x02, 0x15, 0x3e, 0x43, 0xf6, 0x26, 0x47, 0x95, 0xdb, - 0xd3, 0x8d, 0x4a, 0x4b, 0xee, 0x39, 0xe2, 0xad, 0xe9, 0x8f, 0x99, 0xff, - 0xc4, 0xb1, 0x3f, 0x74, 0x0a, 0x43, 0x43, 0xbf, 0x2e, 0xcd, 0xfa, 0xcb, - 0x04, 0xb9, 0x83, 0xe4, 0x1c, 0x26, 0x6d, 0xea, 0x4f, 0xbd, 0x37, 0x24, - 0x76, 0x37, 0x89, 0x9f, 0x0e, 0x9e, 0xc6, 0xe9, 0xc1, 0x7f, 0xc1, 0x12, - 0x4d, 0xf2, 0x34, 0xab, 0xd3, 0x19, 0xb1, 0xac, 0x3d, 0xf5, 0x71, 0xab, - 0xda, 0x78, 0xab, 0x0c, 0xc5, 0x65, 0x98, 0x16, 0x79, 0x0d, 0xdb, 0x35, - 0xb6, 0x95, 0x3c, 0x84, 0x9d, 0x8c, 0xeb, 0xbe, 0xc8, 0x1d, 0xf0, 0x25, - 0x33, 0x66, 0x25, 0xa2, 0x3b, 0x2b, 0xa1, 0xb7, 0x57, 0x38, 0x8c, 0x8e, - 0x7f, 0x56, 0xea, 0x70, 0x6b, 0xfa, 0x34, 0x7e, 0x31, 0x68, 0xef, 0xc9, - 0x6a, 0xf9, 0xb6, 0x62, 0x75, 0x6e, 0x0f, 0xe9, 0x4d, 0xff, 0x55, 0x89, - 0xc6, 0x65, 0x2f, 0x4f, 0x11, 0x73, 0x82, 0xdb, 0x06, 0x25, 0xdf, 0x6c, - 0x81, 0xbb, 0x57, 0xcf, 0x2c, 0x25, 0xcf, 0xfe, 0xca, 0x82, 0xf8, 0x8c, - 0x2a, 0xda, 0xa5, 0x43, 0xd1, 0x83, 0x86, 0xda, 0x89, 0xe3, 0xa6, 0x3e, - 0xf1, 0x5b, 0x87, 0x31, 0xf4, 0x2d, 0xd4, 0x61, 0x55, 0x5a, 0x1f, 0xba, - 0x86, 0x79, 0xd8, 0xd6, 0x3e, 0x13, 0xc9, 0x3e, 0xbd, 0xa5, 0xc3, 0xd1, - 0x83, 0xfb, 0x02, 0x35, 0xed, 0xef, 0x91, 0xcb, 0x79, 0x88, 0x29, 0x7d, - 0xe3, 0x23, 0xcc, 0x13, 0x7b, 0xb0, 0x61, 0x5f, 0x04, 0xeb, 0xf7, 0x98, - 0xe8, 0xee, 0x1b, 0xa1, 0x6c, 0x2f, 0x95, 0xca, 0x1e, 0x96, 0xe6, 0x50, - 0xfc, 0x66, 0x15, 0x81, 0x28, 0xfb, 0x6c, 0x50, 0x23, 0x01, 0xbf, 0xaa, - 0x30, 0xfa, 0x8f, 0x3b, 0xb1, 0x89, 0x65, 0x7a, 0x93, 0xb4, 0xb9, 0x3e, - 0x37, 0xe3, 0xe5, 0x4c, 0x0c, 0x8f, 0xf9, 0x70, 0x70, 0xcc, 0x83, 0xa1, - 0x31, 0x8d, 0x47, 0x31, 0x1e, 0x1b, 0x90, 0xbd, 0x20, 0x5e, 0x3c, 0x7d, - 0xc0, 0x8d, 0xcd, 0xbb, 0x3d, 0x98, 0x1d, 0x99, 0x86, 0x03, 0x07, 0x8a, - 0xb1, 0x97, 0xd7, 0x2b, 0x16, 0xfa, 0xf1, 0x24, 0xaf, 0xf7, 0xef, 0x76, - 0x71, 0x1e, 0xe6, 0xe0, 0x30, 0x0d, 0x7b, 0x68, 0xac, 0x04, 0xc9, 0x01, - 0x9a, 0x3c, 0x39, 0xeb, 0xdb, 0xcc, 0x30, 0x46, 0x0f, 0x30, 0x36, 0xee, - 0x33, 0x91, 0x60, 0x3f, 0x3b, 0xa8, 0xab, 0x6e, 0xe2, 0xda, 0x86, 0x31, - 0xc1, 0xf8, 0x55, 0xb8, 0xa9, 0x57, 0x6f, 0x6a, 0x54, 0x8c, 0xe8, 0x22, - 0x7b, 0xbf, 0x97, 0xbc, 0xdf, 0xb5, 0x0a, 0x0d, 0x09, 0xdd, 0x6c, 0x44, - 0x27, 0x4e, 0x72, 0xdc, 0xff, 0x17, 0xfd, 0x76, 0xb1, 0x43, 0xef, 0xb9, - 0x51, 0x3d, 0x82, 0x9d, 0xe9, 0xa3, 0xe4, 0xea, 0x40, 0x78, 0xff, 0x11, - 0xf2, 0xb7, 0xe3, 0xc4, 0x9f, 0x37, 0x2d, 0x9f, 0xa1, 0xe2, 0xd6, 0x47, - 0x8c, 0xf0, 0xfb, 0x4a, 0xa0, 0xfd, 0x57, 0xd4, 0xc1, 0x67, 0x0f, 0xa8, - 0xb8, 0x65, 0xe7, 0x62, 0xa4, 0x42, 0x51, 0xec, 0x58, 0xa4, 0xe2, 0xe6, - 0x7d, 0x47, 0x88, 0xfb, 0x13, 0x36, 0x4f, 0xce, 0xa4, 0x1e, 0x46, 0xb0, - 0x57, 0xd6, 0xb8, 0xdd, 0x8c, 0xdf, 0xa5, 0x78, 0xa6, 0x9f, 0x39, 0xb4, - 0x59, 0x8a, 0x13, 0x43, 0x47, 0x68, 0x8f, 0xa5, 0x38, 0xde, 0x6f, 0x4c, - 0xfc, 0xd4, 0x51, 0x8a, 0xa7, 0x79, 0xbe, 0x93, 0xe7, 0x0b, 0x07, 0x8c, - 0xfe, 0x0e, 0xb5, 0x14, 0x0b, 0xf6, 0xd7, 0xa3, 0xbf, 0x4f, 0x6c, 0x53, - 0x43, 0xfb, 0x58, 0x5d, 0x4e, 0xf7, 0xa2, 0x73, 0x2f, 0x36, 0x52, 0x57, - 0xf7, 0xed, 0xec, 0x64, 0x7f, 0x3e, 0xea, 0xfc, 0x08, 0x1e, 0x63, 0x5e, - 0xb7, 0xbd, 0xcf, 0x87, 0x73, 0x49, 0xc3, 0xff, 0x45, 0xc5, 0x30, 0x8b, - 0x94, 0x80, 0xf6, 0x0c, 0x7c, 0x38, 0x9d, 0x2e, 0xc6, 0xa6, 0x81, 0x99, - 0xf8, 0x29, 0xed, 0xf3, 0xd1, 0xdd, 0xd2, 0xdf, 0x04, 0xe3, 0xc3, 0x2c, - 0x3c, 0x3d, 0x62, 0xb2, 0x6d, 0x99, 0x27, 0x89, 0x39, 0xdd, 0x70, 0x25, - 0xc5, 0x37, 0xa2, 0x3b, 0x69, 0x16, 0xc4, 0xc4, 0x63, 0x48, 0xf7, 0xeb, - 0x3d, 0xb7, 0xa9, 0xc2, 0xab, 0x55, 0xea, 0xd2, 0x81, 0x49, 0x4d, 0x8f, - 0x57, 0xa8, 0xf1, 0x7e, 0xe6, 0xaf, 0xf1, 0x4a, 0xf5, 0x18, 0x9e, 0xee, - 0x77, 0x62, 0xde, 0x42, 0x95, 0xd7, 0xe3, 0xe7, 0x19, 0xdb, 0xe2, 0xb3, - 0x55, 0x13, 0x7b, 0x6d, 0x59, 0x11, 0x2f, 0x20, 0xb7, 0x2f, 0x5f, 0x58, - 0xc3, 0xf8, 0xe5, 0x10, 0xdb, 0x8b, 0x95, 0xaa, 0x4e, 0xea, 0xfd, 0x34, - 0x46, 0x68, 0xd7, 0x4f, 0xf0, 0x38, 0x3c, 0x68, 0x75, 0x2e, 0x27, 0xe7, - 0x9e, 0x13, 0xb0, 0x3a, 0x6f, 0x33, 0x0d, 0x5f, 0x81, 0x1a, 0x88, 0x7e, - 0x05, 0xa7, 0x71, 0x68, 0x44, 0xca, 0xc0, 0xed, 0x8d, 0x30, 0xaf, 0xee, - 0xb3, 0x3a, 0x77, 0x9a, 0x73, 0x50, 0x6f, 0xe7, 0xc6, 0x3f, 0x2f, 0xcd, - 0x62, 0xa6, 0xf8, 0x91, 0xbd, 0xa7, 0x0a, 0xbf, 0x62, 0x3b, 0xef, 0x0f, - 0x96, 0xa3, 0xaa, 0x52, 0xfc, 0xe0, 0x14, 0xde, 0xe9, 0x7f, 0x0d, 0xe7, - 0xfa, 0x2d, 0x2c, 0x08, 0x59, 0x70, 0x86, 0x6a, 0xcd, 0x46, 0xf5, 0x1a, - 0x62, 0x84, 0x82, 0x9b, 0xe6, 0x7e, 0x1f, 0xef, 0xd2, 0xff, 0x6f, 0x9e, - 0x6b, 0xd9, 0xb2, 0xf4, 0x62, 0xa1, 0xb5, 0xa3, 0x5a, 0xfc, 0xc6, 0xb4, - 0xf7, 0xd3, 0xfc, 0xe9, 0x3c, 0x38, 0xbf, 0xaf, 0x4b, 0x72, 0xe1, 0xd3, - 0x18, 0x1e, 0x34, 0xa2, 0x6b, 0xf3, 0x72, 0xf6, 0x9f, 0xa6, 0x0e, 0x2c, - 0xec, 0x34, 0x4f, 0xec, 0xab, 0xc0, 0xbc, 0xf3, 0xcc, 0x1a, 0xaf, 0x9b, - 0x4d, 0xdb, 0x59, 0xb0, 0x30, 0x60, 0x2e, 0x53, 0xff, 0x37, 0xfd, 0xf4, - 0x34, 0x0e, 0x0e, 0xe5, 0xf1, 0xda, 0x87, 0x46, 0xfa, 0x79, 0x76, 0xcf, - 0xbb, 0x17, 0x0d, 0xc9, 0xa3, 0xf6, 0xfa, 0xc3, 0x61, 0xe2, 0x63, 0xf6, - 0x19, 0xa1, 0x86, 0x91, 0x74, 0x23, 0xb1, 0x21, 0x8a, 0xef, 0xa6, 0x23, - 0xc4, 0x87, 0x30, 0xf1, 0xa1, 0x9e, 0xf8, 0x60, 0x12, 0x1f, 0xea, 0x88, - 0x0f, 0x41, 0xfb, 0xd9, 0xb9, 0xac, 0x47, 0x0f, 0x8d, 0xbe, 0x86, 0x82, - 0x81, 0x53, 0x70, 0x0d, 0xc8, 0x3e, 0x35, 0x8b, 0xfc, 0xa4, 0x56, 0x6b, - 0xc3, 0x1c, 0x45, 0xf6, 0x0c, 0x0e, 0xa5, 0x4f, 0xa1, 0x68, 0x40, 0xe3, - 0x58, 0x64, 0xaf, 0x40, 0x4d, 0xb8, 0x87, 0x58, 0xfd, 0x6b, 0xa3, 0xb6, - 0xc7, 0x8b, 0xda, 0xbd, 0xd5, 0x30, 0xfa, 0x17, 0xaa, 0x73, 0x95, 0xe8, - 0xe7, 0xbc, 0x1c, 0x67, 0x25, 0x66, 0xed, 0xd6, 0x30, 0x9b, 0xc7, 0x3f, - 0x25, 0x6b, 0x26, 0xde, 0x74, 0xc0, 0x3b, 0x9d, 0x74, 0x67, 0x06, 0x99, - 0x00, 0x59, 0xad, 0xd7, 0x87, 0x2b, 0x0f, 0x9f, 0x56, 0x15, 0x64, 0x3e, - 0x27, 0x31, 0xaf, 0x36, 0xd8, 0xad, 0x32, 0x5b, 0xd7, 0x04, 0xc3, 0x79, - 0xa8, 0x88, 0x90, 0x45, 0xcc, 0x64, 0x7e, 0x61, 0xb5, 0x99, 0x45, 0xd8, - 0x52, 0xa7, 0xca, 0x7e, 0x8d, 0xa3, 0x12, 0xa3, 0xa6, 0x33, 0x46, 0x14, - 0xf7, 0xc5, 0xef, 0x99, 0x0e, 0x0f, 0x8a, 0xfa, 0x2c, 0xeb, 0x1b, 0x21, - 0x0d, 0x9e, 0x48, 0x20, 0xba, 0x81, 0x69, 0xe4, 0xe7, 0xe6, 0x85, 0x71, - 0x53, 0xfa, 0x30, 0x06, 0x38, 0xbe, 0xe5, 0xe9, 0xfc, 0xbb, 0x9c, 0x7f, - 0xfa, 0xef, 0xe2, 0x3b, 0xa1, 0x57, 0xee, 0x9d, 0x0e, 0x43, 0x7b, 0x40, - 0xed, 0x28, 0x27, 0x07, 0x3f, 0xcc, 0xb8, 0xa7, 0x4c, 0x7e, 0x5e, 0x41, - 0xcb, 0x40, 0x1c, 0x55, 0xa1, 0x53, 0x4a, 0x4c, 0xf6, 0x32, 0x29, 0x95, - 0xf8, 0xfc, 0x6e, 0xea, 0x7a, 0x41, 0x86, 0xb6, 0xe2, 0xc3, 0xb7, 0x46, - 0x45, 0xb7, 0x35, 0x43, 0x3b, 0x39, 0x8e, 0x37, 0xe6, 0x1e, 0x16, 0x9c, - 0x3c, 0x32, 0x0b, 0x8e, 0x23, 0xd3, 0x98, 0x9b, 0xd6, 0xcc, 0xbd, 0xf2, - 0xfc, 0xbf, 0xa8, 0xa2, 0x17, 0x85, 0xd8, 0xa1, 0xf7, 0xc7, 0xd8, 0xf6, - 0x07, 0x8e, 0xc3, 0xd8, 0x44, 0x0c, 0x3e, 0x9a, 0xfe, 0x0e, 0x75, 0x79, - 0x28, 0x97, 0x2f, 0xad, 0x42, 0xa2, 0x57, 0xf6, 0xe3, 0x9d, 0xc2, 0xac, - 0x01, 0xbd, 0x79, 0x9b, 0x62, 0x04, 0x6f, 0x56, 0x4e, 0x61, 0xc6, 0x40, - 0x90, 0x73, 0xa9, 0x61, 0x59, 0x5f, 0x1e, 0x3f, 0x05, 0x83, 0x57, 0x11, - 0x83, 0xad, 0xc5, 0x3f, 0x35, 0xe3, 0xcc, 0x71, 0x74, 0xd3, 0xa9, 0xe8, - 0x2d, 0x73, 0x15, 0xd9, 0x9b, 0x63, 0x9c, 0x6f, 0x65, 0x1d, 0xcf, 0x40, - 0x1d, 0xee, 0xe4, 0x98, 0x9b, 0x38, 0x6f, 0xaf, 0x2d, 0xb4, 0xb0, 0x68, - 0xa1, 0xbe, 0xb7, 0xc8, 0x11, 0x7d, 0xa0, 0x02, 0x99, 0x8e, 0x6a, 0xda, - 0xcd, 0x7d, 0x0b, 0xf4, 0xf0, 0xab, 0xc4, 0x5d, 0xe2, 0x34, 0x36, 0x31, - 0xee, 0xb4, 0x31, 0x16, 0x15, 0x47, 0xf4, 0x1e, 0xe6, 0xa8, 0xef, 0xdf, - 0xed, 0x88, 0x86, 0xe4, 0x7d, 0xa3, 0x7f, 0xc0, 0x62, 0xb8, 0x43, 0x65, - 0xc4, 0x41, 0x3d, 0xf3, 0x1a, 0xf4, 0xbd, 0x77, 0x92, 0x93, 0xfe, 0x84, - 0xfc, 0xae, 0xfa, 0xaa, 0xa3, 0xc4, 0xa8, 0x11, 0x3c, 0x9a, 0x3e, 0x82, - 0xbd, 0xe9, 0x14, 0x76, 0xa5, 0x77, 0x28, 0x43, 0xf6, 0xb3, 0x3a, 0x45, - 0xde, 0xad, 0x8b, 0x96, 0x29, 0x5f, 0x46, 0x69, 0xe8, 0x9b, 0xd6, 0x50, - 0x85, 0x8a, 0xf2, 0x50, 0x10, 0x37, 0xf5, 0xc5, 0xe1, 0x88, 0xbc, 0x67, - 0xc9, 0x7b, 0xd9, 0xeb, 0xc7, 0x0d, 0xdc, 0xd8, 0x57, 0x8c, 0xd8, 0x7e, - 0xcb, 0xea, 0xa9, 0x77, 0x62, 0xcd, 0x78, 0x1d, 0x96, 0x0d, 0x3c, 0x66, - 0xcd, 0x66, 0xcc, 0xf9, 0xf8, 0x5a, 0x0f, 0xee, 0xde, 0xef, 0x41, 0x6b, - 0x5f, 0x14, 0xbe, 0x48, 0x09, 0x7f, 0x07, 0xcc, 0x25, 0x30, 0x26, 0x26, - 0x60, 0xf4, 0xdc, 0xe0, 0x08, 0x1c, 0x0a, 0xab, 0x1e, 0x7c, 0x95, 0x38, - 0xbe, 0x9c, 0xb8, 0x13, 0x1b, 0xb7, 0x50, 0x1e, 0xf1, 0xe2, 0x1e, 0xd6, - 0xbf, 0x85, 0x73, 0xff, 0xee, 0xa2, 0x43, 0xc4, 0x02, 0xd9, 0x83, 0xa8, - 0x61, 0xc3, 0xb8, 0x9b, 0xba, 0x72, 0x23, 0x76, 0xb0, 0x12, 0x37, 0xee, - 0xf6, 0xe3, 0xee, 0x71, 0x0f, 0x1a, 0xfa, 0xac, 0xc5, 0x87, 0xcd, 0xf8, - 0x4a, 0x0d, 0x06, 0x5a, 0xc7, 0xbd, 0xf8, 0xdb, 0x3e, 0xdd, 0x77, 0x33, - 0x73, 0xfe, 0x11, 0x33, 0x88, 0xbf, 0x1f, 0xf7, 0xe1, 0xf6, 0xbe, 0x13, - 0x92, 0x47, 0x2e, 0x71, 0x32, 0xf6, 0x3c, 0x34, 0x3e, 0x13, 0x2b, 0xfb, - 0xf4, 0xf3, 0x13, 0xe4, 0x76, 0x9d, 0x07, 0x4d, 0x3c, 0x30, 0xae, 0xa2, - 0x85, 0xed, 0x7c, 0xbe, 0x6f, 0x16, 0x3a, 0x0e, 0xd6, 0x53, 0x86, 0x85, - 0x58, 0x3e, 0xe0, 0x84, 0x49, 0x16, 0x8f, 0x2f, 0x00, 0xcd, 0x03, 0x13, - 0xcc, 0xe3, 0x1e, 0xc6, 0x8e, 0x5e, 0x13, 0xf7, 0x8e, 0xcb, 0xf9, 0x11, - 0xfb, 0x5d, 0xd8, 0xf7, 0xf7, 0x2d, 0xc4, 0x67, 0x07, 0x54, 0xe2, 0x40, - 0x21, 0x86, 0x56, 0x2a, 0xf8, 0x5b, 0x5e, 0xdf, 0x96, 0x94, 0xbd, 0xcc, - 0x40, 0x68, 0x67, 0xe0, 0x50, 0x05, 0x39, 0xc3, 0xa2, 0x7d, 0xd9, 0xeb, - 0x8f, 0x12, 0xe7, 0x8b, 0x88, 0xf3, 0x25, 0xe4, 0xb0, 0x37, 0x0c, 0x1f, - 0xc1, 0x23, 0xc4, 0xe5, 0xa3, 0x03, 0x9d, 0x8c, 0x3b, 0xa5, 0x78, 0x92, - 0x71, 0xa0, 0x8f, 0xe7, 0xa7, 0x76, 0x1a, 0x1d, 0x45, 0xc4, 0xe9, 0x57, - 0x89, 0xbf, 0x3d, 0xc4, 0x8c, 0xfb, 0xfa, 0x18, 0xee, 0x77, 0x32, 0x07, - 0xb8, 0x2a, 0x3a, 0xdf, 0xc3, 0x1c, 0xeb, 0x66, 0x25, 0xe0, 0x7b, 0x0b, - 0xa5, 0x70, 0xec, 0xab, 0x44, 0xc3, 0x6e, 0x29, 0x23, 0xf8, 0xa5, 0x42, - 0x3d, 0xe0, 0xa4, 0xce, 0x8f, 0xc1, 0xea, 0x77, 0x70, 0xbc, 0x35, 0x26, - 0x19, 0x38, 0xde, 0x30, 0x75, 0xed, 0xbb, 0xc4, 0xda, 0x0f, 0x89, 0xa9, - 0xfe, 0xe9, 0xf5, 0x68, 0x34, 0x4c, 0x1e, 0xc7, 0x70, 0xba, 0xdf, 0x30, - 0x65, 0x9f, 0xdc, 0x9b, 0xe4, 0x79, 0x93, 0xd3, 0x19, 0x33, 0x0d, 0xf1, - 0xc3, 0x11, 0x8e, 0x47, 0x95, 0xbc, 0x04, 0x8e, 0x31, 0xe0, 0x9d, 0x7d, - 0x8b, 0x39, 0x2e, 0x89, 0xa5, 0x12, 0xef, 0x46, 0x28, 0xeb, 0x62, 0xac, - 0xa0, 0x3e, 0x1a, 0xfb, 0x54, 0xa4, 0x0e, 0x46, 0x70, 0xef, 0x9e, 0x6c, - 0x1c, 0x6e, 0x0f, 0xc5, 0x6f, 0x63, 0x1c, 0x0e, 0x17, 0x33, 0x0e, 0xbb, - 0x22, 0x22, 0x9b, 0x13, 0xc3, 0x8c, 0xdb, 0x5b, 0x92, 0x61, 0x34, 0x71, - 0x0e, 0x27, 0x52, 0xec, 0xb7, 0x6f, 0x26, 0x9e, 0x49, 0x79, 0x18, 0xb3, - 0x34, 0x1e, 0x44, 0xb5, 0x91, 0x69, 0x3c, 0xfc, 0x3c, 0xe6, 0xf0, 0x30, - 0xec, 0x6b, 0x6d, 0x7d, 0x0a, 0xe2, 0xcd, 0xd9, 0xe7, 0x65, 0xcf, 0xa4, - 0x04, 0x9b, 0x65, 0x2d, 0xf3, 0xde, 0x72, 0xd9, 0xfb, 0xd9, 0x9f, 0xfc, - 0x3e, 0xca, 0x89, 0x4f, 0x65, 0x39, 0x1c, 0xfa, 0x79, 0x48, 0x70, 0xb7, - 0x86, 0xb8, 0x2b, 0xfb, 0x73, 0x2c, 0x6b, 0x55, 0x60, 0x2a, 0x1e, 0xfd, - 0xef, 0x8f, 0xa3, 0xf6, 0x7e, 0x56, 0xc1, 0x24, 0xe2, 0x5f, 0x92, 0xf8, - 0xc7, 0x31, 0x74, 0x5d, 0x4f, 0x0c, 0xa4, 0x4c, 0xff, 0x98, 0x24, 0x06, - 0x12, 0xa7, 0x8f, 0x10, 0xa7, 0x9f, 0x22, 0x4e, 0x7f, 0x93, 0x38, 0xfd, - 0x24, 0x31, 0x21, 0xbb, 0xa6, 0xd7, 0x24, 0xcf, 0x2f, 0x38, 0x1f, 0xef, - 0xd9, 0x6b, 0x8b, 0xd5, 0xd4, 0xd5, 0xac, 0x01, 0x79, 0xe7, 0x47, 0x3f, - 0x24, 0x76, 0xff, 0x13, 0xce, 0x93, 0xbf, 0x2a, 0xbb, 0xef, 0xaa, 0xb1, - 0xaf, 0x1b, 0xee, 0xbe, 0x5a, 0xad, 0x07, 0xf6, 0xb7, 0x02, 0x4c, 0xe1, - 0xa2, 0x05, 0x7d, 0x6d, 0x70, 0xf4, 0xd5, 0x1e, 0x3a, 0x29, 0xcf, 0x43, - 0xa7, 0x49, 0x5e, 0xdf, 0x26, 0x7b, 0xbd, 0x0f, 0xc9, 0x7e, 0xad, 0x65, - 0xbc, 0xe7, 0xea, 0xab, 0x35, 0xdf, 0x82, 0x8d, 0x6d, 0xfe, 0x49, 0xfb, - 0x5e, 0xcd, 0xfb, 0x8f, 0x50, 0x5f, 0x19, 0xb6, 0x99, 0x4a, 0xca, 0x7e, - 0xd4, 0x99, 0x78, 0x22, 0x2d, 0xbf, 0x6b, 0x5b, 0x12, 0xea, 0xe3, 0x88, - 0x55, 0x0b, 0x1f, 0x0f, 0xe3, 0xd6, 0x3e, 0x0f, 0xed, 0x20, 0x8e, 0x32, - 0xfa, 0xd6, 0xfd, 0xe3, 0xf5, 0xf4, 0xb5, 0xc7, 0x2c, 0x2d, 0x12, 0x68, - 0x19, 0x27, 0xe7, 0x59, 0x3f, 0xbe, 0x18, 0x4b, 0x07, 0x2c, 0xcb, 0x73, - 0x8d, 0x11, 0xde, 0xa0, 0xf8, 0xe1, 0xa2, 0x0f, 0x3a, 0xe8, 0x57, 0x6b, - 0xf7, 0x07, 0xb4, 0xb7, 0x88, 0xa7, 0xeb, 0xea, 0x0f, 0xd3, 0x3e, 0x8c, - 0xf3, 0x4d, 0xc4, 0x52, 0x67, 0x24, 0xc0, 0x3c, 0xd1, 0x43, 0xdb, 0xf7, - 0xe2, 0x7c, 0x42, 0xfc, 0x4b, 0xef, 0xf8, 0x2e, 0x73, 0x93, 0x0e, 0xfa, - 0xc6, 0x07, 0x89, 0xeb, 0xe9, 0x4b, 0x61, 0x1e, 0x33, 0xe9, 0x0b, 0x6e, - 0xbc, 0x93, 0x30, 0xe8, 0x77, 0x1e, 0xbc, 0x9b, 0xa8, 0x63, 0x9f, 0x41, - 0x96, 0xf5, 0x63, 0xa3, 0xfd, 0xde, 0x75, 0x4d, 0xfc, 0x5b, 0x4a, 0x4d, - 0xff, 0x2c, 0xb5, 0x02, 0xd1, 0x4a, 0x0d, 0x7f, 0x37, 0xfe, 0x37, 0xf8, - 0x19, 0xe3, 0xf6, 0x9a, 0x3e, 0x70, 0x0e, 0x11, 0x22, 0x0f, 0x9c, 0x38, - 0x28, 0xcf, 0xe9, 0x50, 0x1b, 0x9d, 0xeb, 0xd0, 0x99, 0xdb, 0xea, 0x99, - 0x73, 0x0e, 0x27, 0xfb, 0x24, 0x2b, 0x66, 0xd9, 0x0f, 0xfa, 0x8b, 0xf1, - 0xc0, 0xfe, 0xc3, 0xf4, 0x91, 0x02, 0x2c, 0x78, 0xc4, 0x8d, 0xbf, 0x3b, - 0x38, 0x22, 0x6b, 0x4b, 0x82, 0x99, 0xfe, 0x21, 0x12, 0x85, 0x30, 0xb9, - 0xde, 0xfd, 0x7b, 0x46, 0x30, 0x90, 0xe3, 0x79, 0x1f, 0x84, 0xe2, 0x5f, - 0x51, 0x71, 0x98, 0x3c, 0x22, 0x10, 0xbf, 0x9a, 0x36, 0x26, 0xef, 0xb8, - 0x49, 0xec, 0x5f, 0x41, 0x1b, 0xeb, 0xe6, 0x7c, 0x7e, 0x83, 0xe3, 0xd8, - 0x41, 0x1b, 0x1b, 0x4d, 0xcc, 0xc4, 0x56, 0xda, 0x58, 0x9c, 0x36, 0x16, - 0xa7, 0x3d, 0xc5, 0x69, 0x63, 0xf2, 0x6e, 0x7e, 0x9c, 0x36, 0x16, 0xa7, - 0x8d, 0xc5, 0x53, 0x8b, 0xf1, 0x14, 0x99, 0xc6, 0xae, 0x91, 0x45, 0xc4, - 0x31, 0x79, 0xb6, 0xc6, 0x79, 0xb8, 0xed, 0x6f, 0xc8, 0xd9, 0x6f, 0xe0, - 0xa1, 0xe0, 0x4e, 0xfa, 0xe4, 0x63, 0x43, 0xc4, 0x3b, 0xda, 0xc1, 0xa2, - 0xb4, 0x70, 0xfc, 0x7a, 0xe6, 0xb1, 0xc7, 0xc8, 0xf3, 0x55, 0x3c, 0x6b, - 0x4a, 0x1e, 0x6c, 0xf2, 0x9c, 0xb1, 0x26, 0x29, 0x1c, 0xec, 0x18, 0x36, - 0xf4, 0x03, 0x37, 0x91, 0x17, 0x56, 0x92, 0x97, 0x8c, 0x2c, 0x00, 0x5e, - 0x1c, 0x12, 0x19, 0xc5, 0xc7, 0xb3, 0xfb, 0x4f, 0x8f, 0xf7, 0xd7, 0x44, - 0x1b, 0x65, 0x7d, 0x88, 0x9c, 0x64, 0xf1, 0xb0, 0x70, 0xbc, 0xc3, 0xe4, - 0x48, 0x7a, 0xf8, 0xdf, 0x21, 0x1c, 0xaf, 0x12, 0x65, 0x7b, 0xf4, 0xf0, - 0x3b, 0x30, 0xd6, 0xfd, 0x52, 0xb1, 0x16, 0xbf, 0x16, 0x0a, 0xc4, 0x9f, - 0x54, 0x54, 0x34, 0x93, 0xef, 0xdd, 0xbc, 0xd3, 0x89, 0x9e, 0xd0, 0x62, - 0x7c, 0x85, 0x9c, 0x6f, 0xf5, 0x35, 0x2a, 0x96, 0xec, 0xa3, 0x2d, 0x55, - 0x0a, 0xc7, 0xd2, 0xc3, 0xe7, 0x30, 0x61, 0xaf, 0x13, 0x8e, 0xa6, 0x8e, - 0x5b, 0x55, 0x86, 0x60, 0x11, 0xb1, 0xed, 0xea, 0x37, 0x2d, 0xb7, 0xac, - 0x35, 0x91, 0x03, 0x0e, 0xf7, 0x47, 0x5f, 0x70, 0x12, 0xf7, 0xd7, 0x93, - 0x07, 0x3e, 0x91, 0xe3, 0x81, 0x07, 0xfb, 0x0d, 0xed, 0x07, 0xc4, 0x8b, - 0xfd, 0x3c, 0xdf, 0xca, 0x73, 0xab, 0xdf, 0xe0, 0x7c, 0x04, 0x9a, 0x66, - 0x90, 0x1b, 0xbe, 0x43, 0x99, 0x7b, 0x29, 0x73, 0x82, 0xf6, 0x9f, 0xee, - 0xd5, 0x90, 0x1c, 0x33, 0x30, 0xde, 0xeb, 0x45, 0xdf, 0x58, 0x10, 0x4f, - 0xf6, 0xfa, 0xb0, 0x93, 0xfc, 0xf0, 0x70, 0xaf, 0xf8, 0xe2, 0x4c, 0xf4, - 0x8f, 0xcd, 0xc4, 0x37, 0x92, 0xb2, 0x3e, 0xf5, 0x2e, 0x56, 0x57, 0x88, - 0x7e, 0xc4, 0x2f, 0xc9, 0xaf, 0x93, 0x7a, 0x4f, 0x8c, 0x63, 0x8a, 0x79, - 0xf5, 0x43, 0x31, 0xe8, 0x43, 0x9c, 0xc1, 0x8f, 0x87, 0xbe, 0x20, 0x31, - 0x52, 0x7c, 0x52, 0xc3, 0x13, 0xe4, 0x3c, 0xa5, 0xc4, 0xd5, 0x92, 0x48, - 0x4d, 0xf4, 0x0b, 0x8a, 0x1e, 0x7b, 0x45, 0xb5, 0xac, 0x4a, 0x89, 0xe1, - 0x07, 0x35, 0xf2, 0x0f, 0x13, 0x37, 0xdb, 0x31, 0x5b, 0xc3, 0xf4, 0xdd, - 0x95, 0xa8, 0xda, 0xdd, 0x87, 0xff, 0x56, 0x19, 0xff, 0x60, 0x1a, 0x63, - 0xfd, 0x34, 0x62, 0xfb, 0xec, 0xbe, 0x93, 0xd3, 0x67, 0x91, 0x33, 0xbf, - 0xa1, 0xd6, 0x66, 0xbe, 0x0b, 0xfd, 0xd0, 0x69, 0x87, 0x3e, 0x71, 0x94, - 0xf1, 0xc1, 0x45, 0xfb, 0x9c, 0x31, 0xae, 0xd1, 0x7f, 0x6b, 0x8f, 0x56, - 0xc1, 0x88, 0x5f, 0xab, 0x3a, 0x2d, 0x54, 0x8a, 0x3c, 0xa1, 0xf2, 0x6c, - 0x6e, 0x14, 0x26, 0xf6, 0x4b, 0x6c, 0x70, 0x40, 0x23, 0x0e, 0xff, 0x3d, - 0x7d, 0xe6, 0x4e, 0x3b, 0x1e, 0x1d, 0xb6, 0x9f, 0x85, 0x76, 0x8e, 0xc7, - 0xe9, 0x27, 0x8b, 0xd1, 0xd1, 0xef, 0x41, 0xbb, 0x1d, 0x8b, 0x1e, 0xb3, - 0x2a, 0xe8, 0x33, 0x1d, 0xfb, 0x03, 0x4d, 0x37, 0xd2, 0x67, 0xae, 0xbb, - 0x46, 0xe2, 0xd8, 0x61, 0xf2, 0x5f, 0xc3, 0xbc, 0x8e, 0xf8, 0xb2, 0xb5, - 0xde, 0xe8, 0x78, 0x9e, 0x32, 0xdd, 0x4f, 0xfb, 0x7f, 0x97, 0x3c, 0xe7, - 0xdc, 0x9e, 0x43, 0xd4, 0x99, 0x66, 0xfb, 0xc3, 0xcf, 0x92, 0x3e, 0xdb, - 0x37, 0x62, 0xfc, 0x2d, 0x71, 0x2f, 0x46, 0x5f, 0xfa, 0x37, 0xc6, 0xec, - 0xe2, 0x50, 0xfc, 0xf6, 0x62, 0x04, 0x71, 0x1f, 0x65, 0xfd, 0x38, 0xa9, - 0xf7, 0x6f, 0x90, 0x77, 0x8f, 0x43, 0x26, 0x65, 0xf1, 0xe0, 0x83, 0xa4, - 0xd8, 0xd9, 0x89, 0xff, 0x59, 0x89, 0xf8, 0x26, 0xc6, 0xe0, 0xa0, 0xe6, - 0x90, 0xb5, 0xf0, 0x99, 0x58, 0x73, 0xf0, 0x1a, 0xca, 0x5c, 0x47, 0xff, - 0x03, 0xe6, 0x0c, 0x47, 0x70, 0xcf, 0x1e, 0xc9, 0x31, 0xd0, 0x20, 0xb9, - 0xda, 0xbc, 0x50, 0xc0, 0x3c, 0x43, 0xac, 0x58, 0x3b, 0x76, 0x98, 0x71, - 0x42, 0xd6, 0x96, 0x91, 0xf1, 0x19, 0x61, 0xbc, 0xda, 0x5b, 0x6f, 0xbf, - 0xd3, 0x70, 0xff, 0x58, 0x3d, 0x5e, 0xe9, 0x9d, 0x89, 0xfb, 0x98, 0xeb, - 0xc4, 0x98, 0xeb, 0xc4, 0xc6, 0xbc, 0x88, 0x1d, 0x98, 0xc6, 0x83, 0xb2, - 0x1d, 0x98, 0xc3, 0x83, 0xb2, 0x8d, 0xa9, 0xf8, 0x2a, 0xf3, 0x97, 0x0d, - 0xc4, 0xf3, 0x1e, 0xda, 0xe3, 0xff, 0xe0, 0xdc, 0x0f, 0xd0, 0xde, 0xab, - 0x89, 0xf7, 0x6f, 0xee, 0x02, 0xee, 0xb4, 0xf5, 0x73, 0x84, 0x7a, 0x54, - 0xf0, 0x15, 0xfa, 0x44, 0x15, 0x63, 0x52, 0x37, 0xe7, 0x7c, 0xe7, 0xa0, - 0x11, 0x0c, 0xab, 0x01, 0xed, 0x09, 0xce, 0x73, 0xd7, 0x88, 0x8a, 0x47, - 0xfb, 0x17, 0x63, 0x3e, 0x63, 0xca, 0xb6, 0xa1, 0x09, 0xbb, 0x7c, 0x37, - 0xfd, 0xe1, 0x6e, 0xfa, 0xc9, 0x7b, 0xf4, 0x93, 0xc9, 0x95, 0xf2, 0x3e, - 0xa9, 0x93, 0x39, 0xff, 0xc3, 0x58, 0x93, 0x90, 0x78, 0xa7, 0xf7, 0x0c, - 0xa9, 0xcc, 0xb5, 0x68, 0x9f, 0x5d, 0xcc, 0x51, 0x6e, 0xa7, 0x6d, 0x3e, - 0x3a, 0x24, 0x3e, 0x24, 0x39, 0x8b, 0x11, 0xde, 0x46, 0xdb, 0x7c, 0x7e, - 0x48, 0xfc, 0xa3, 0x14, 0xb7, 0xee, 0x94, 0xfd, 0xa6, 0xa5, 0xf8, 0xec, - 0xbe, 0xc3, 0x94, 0xef, 0x08, 0x76, 0xd1, 0x2e, 0x4b, 0x69, 0x97, 0xf7, - 0x51, 0xaf, 0x1e, 0xda, 0xe5, 0x06, 0xe2, 0x50, 0x09, 0xed, 0xf2, 0x5e, - 0xf2, 0x81, 0xca, 0x9c, 0x5d, 0xfe, 0xdd, 0xf8, 0xc2, 0x8a, 0x6c, 0x8c, - 0xf0, 0x42, 0xdd, 0x2d, 0xef, 0xf7, 0x59, 0xd6, 0xed, 0x66, 0xa6, 0x69, - 0x06, 0x74, 0xb6, 0x1d, 0xc1, 0xb2, 0xb4, 0x13, 0xe5, 0x7d, 0x11, 0x2c, - 0x4d, 0xd6, 0xb4, 0x9f, 0x55, 0x22, 0xc8, 0xcc, 0xc8, 0xf2, 0x40, 0x57, - 0x9f, 0x7c, 0xdf, 0x43, 0x23, 0x07, 0xe1, 0xf8, 0xaf, 0xcd, 0x7e, 0x53, - 0xe4, 0xf3, 0x7f, 0x01, 0x7f, 0x5c, 0x42, 0x99, 0x3a, 0xcd, 0x8f, 0xac, - 0xc9, 0xec, 0xf7, 0x07, 0x9c, 0xb7, 0xf1, 0x7c, 0x16, 0xdb, 0xa8, 0x1a, - 0x77, 0x3a, 0xbf, 0x98, 0xf4, 0x60, 0xfa, 0xb8, 0x89, 0xbf, 0xcd, 0xb6, - 0xe3, 0x2e, 0x88, 0x34, 0xe2, 0xb9, 0x84, 0x82, 0x69, 0xc6, 0xd3, 0xf8, - 0x91, 0xbd, 0x2e, 0x50, 0x89, 0xf2, 0xdd, 0xf6, 0x9a, 0x02, 0x0e, 0x24, - 0xf4, 0xf6, 0x34, 0xcf, 0xcb, 0x0e, 0x7a, 0x51, 0xbc, 0x5b, 0xc1, 0x2d, - 0x01, 0x2f, 0x4a, 0xf9, 0xdb, 0x43, 0xbe, 0xd9, 0x1d, 0x5a, 0x6e, 0x6d, - 0x59, 0x25, 0xf6, 0xed, 0x05, 0x0e, 0x96, 0x94, 0x0b, 0x0e, 0x1e, 0x30, - 0x65, 0xed, 0xd2, 0x40, 0x77, 0xa2, 0x12, 0x85, 0xbb, 0x6b, 0x9a, 0x1a, - 0x51, 0x63, 0xbe, 0xc3, 0xfa, 0x05, 0x07, 0x3f, 0x5b, 0x21, 0xeb, 0xf6, - 0x4f, 0x49, 0x8c, 0x1b, 0x92, 0x79, 0xcd, 0xc6, 0x50, 0xe7, 0xd8, 0x5b, - 0x9a, 0xe8, 0x65, 0x13, 0x39, 0x8a, 0xda, 0xf7, 0xa6, 0x5d, 0xc6, 0x17, - 0x39, 0x4a, 0x0c, 0x90, 0xf8, 0x72, 0x0a, 0xed, 0xfd, 0xa7, 0x68, 0xff, - 0xb2, 0x8e, 0xc1, 0xbc, 0x77, 0x81, 0x85, 0xe2, 0x85, 0x99, 0x60, 0x31, - 0xa2, 0x15, 0x15, 0xc4, 0x6f, 0xfa, 0x00, 0x5e, 0x30, 0xf5, 0x96, 0x87, - 0x1c, 0xd1, 0x87, 0x8a, 0xa0, 0xaf, 0x7b, 0x5b, 0xe9, 0xc1, 0xc6, 0xc0, - 0x08, 0xfa, 0xc8, 0x05, 0xf3, 0xf9, 0xf8, 0xba, 0x3d, 0x8c, 0x6f, 0x8e, - 0x8b, 0xf9, 0xb8, 0x16, 0x8a, 0xff, 0x8e, 0x3c, 0xc0, 0x3f, 0x9b, 0x18, - 0xed, 0xb0, 0x7d, 0x27, 0x90, 0xd9, 0x44, 0x7b, 0x0d, 0x8f, 0x87, 0xe9, - 0x23, 0x23, 0x82, 0x7d, 0xf2, 0x35, 0xa3, 0x17, 0x0a, 0x98, 0x3f, 0x16, - 0x33, 0x0f, 0x39, 0x9d, 0xb4, 0x3a, 0xdd, 0xb4, 0x6b, 0xe7, 0xa2, 0x99, - 0x50, 0xd3, 0x37, 0xe0, 0x9d, 0x5d, 0x33, 0x51, 0x48, 0x5f, 0xaa, 0x48, - 0xca, 0x0b, 0x55, 0xea, 0xa7, 0xd9, 0x6f, 0xec, 0x3d, 0x04, 0xda, 0x03, - 0x8e, 0xda, 0x75, 0x49, 0x45, 0x27, 0xf6, 0xeb, 0x2d, 0xa5, 0xea, 0x4c, - 0x78, 0x98, 0xaf, 0x94, 0xa4, 0x3d, 0x00, 0xb9, 0x32, 0x58, 0xef, 0xa7, - 0xbb, 0x5c, 0x28, 0x37, 0x8c, 0xe8, 0x33, 0xcc, 0x81, 0x1c, 0xa3, 0x4e, - 0xfc, 0xcc, 0x96, 0x6b, 0x1a, 0x8a, 0x47, 0x6f, 0xc0, 0xe9, 0x5d, 0x7e, - 0xa8, 0xbc, 0x76, 0x76, 0xcf, 0x1c, 0x14, 0x8c, 0x12, 0x08, 0xd2, 0x8b, - 0xf1, 0xd6, 0x2e, 0x15, 0xae, 0xd1, 0xbf, 0xc1, 0x87, 0xbb, 0x14, 0xcc, - 0x9f, 0xa7, 0xa0, 0x68, 0x78, 0x84, 0x3a, 0x11, 0xee, 0x45, 0x3f, 0x4d, - 0xc1, 0xe6, 0x5d, 0x5b, 0x92, 0xc2, 0xed, 0xc9, 0xe9, 0x06, 0x2b, 0x61, - 0xee, 0x7e, 0xd3, 0xaa, 0x30, 0x8c, 0xd8, 0x2d, 0xaa, 0xb5, 0xb8, 0x72, - 0x41, 0xa0, 0x65, 0x80, 0x38, 0xfd, 0x12, 0x7d, 0xe0, 0x64, 0x7f, 0xdc, - 0xf2, 0x18, 0x8b, 0x89, 0xb5, 0x51, 0x34, 0x30, 0x37, 0x97, 0xbc, 0x7b, - 0x9b, 0x9d, 0xef, 0xca, 0x7e, 0x63, 0x27, 0xfc, 0x63, 0x0f, 0xe3, 0x78, - 0xc2, 0x8d, 0xc5, 0x63, 0xa5, 0xb8, 0x8e, 0x39, 0x75, 0x98, 0xdc, 0x21, - 0xbc, 0x2f, 0xcb, 0xf1, 0x9e, 0x27, 0xc7, 0xfb, 0x15, 0xb2, 0x1c, 0x6f, - 0x80, 0xb9, 0x5a, 0x95, 0x51, 0x8a, 0x5b, 0x06, 0x0c, 0xc6, 0x80, 0x52, - 0x34, 0xdb, 0xeb, 0x01, 0x1a, 0x6e, 0xa3, 0xff, 0x7e, 0x9e, 0xf9, 0xf8, - 0xcd, 0x3b, 0x03, 0xbe, 0x1d, 0x8a, 0x8f, 0x71, 0x40, 0xda, 0x3f, 0x4c, - 0xdc, 0xf0, 0x61, 0x4e, 0xaf, 0x11, 0x5c, 0x8a, 0xc0, 0xf9, 0x43, 0xd4, - 0xe5, 0xe2, 0xb1, 0x1b, 0x10, 0xa6, 0xee, 0xc2, 0xfb, 0x0e, 0xe7, 0xc6, - 0x31, 0x41, 0xd9, 0x9d, 0x78, 0x6f, 0x70, 0x16, 0x5e, 0x3d, 0x90, 0xcd, - 0xc3, 0x03, 0x7d, 0x13, 0xb2, 0x5e, 0xfc, 0x35, 0x86, 0xd7, 0x7b, 0x24, - 0x0f, 0xff, 0x41, 0xbf, 0xde, 0x5f, 0x2a, 0xeb, 0x84, 0xf4, 0xe7, 0xaf, - 0x2e, 0x70, 0x30, 0xbe, 0xe8, 0xfe, 0xef, 0x3b, 0xe2, 0xf2, 0x1c, 0xd9, - 0xff, 0x08, 0xef, 0x7f, 0x9f, 0xf1, 0xfc, 0x36, 0x5e, 0x8f, 0x55, 0x32, - 0xd7, 0x5e, 0x18, 0x3f, 0xef, 0xe2, 0xf5, 0xc7, 0x38, 0x97, 0x65, 0x46, - 0x4d, 0xec, 0x15, 0xe5, 0x08, 0x71, 0xc3, 0x81, 0x1d, 0x21, 0x3d, 0xba, - 0xc3, 0xce, 0xa1, 0x9d, 0x98, 0x48, 0x5f, 0x9d, 0xf3, 0xc1, 0x4a, 0x94, - 0xec, 0x96, 0xfc, 0xc5, 0x90, 0xf5, 0x9f, 0xfe, 0x12, 0xe6, 0x4f, 0x95, - 0x17, 0xec, 0x33, 0xbf, 0xff, 0x09, 0xee, 0x8a, 0x48, 0x33, 0x42, 0x7d, - 0xf9, 0x7d, 0x50, 0x87, 0xd0, 0x9d, 0x7e, 0x10, 0xed, 0xbb, 0xf4, 0x76, - 0x59, 0x1f, 0x7a, 0x25, 0x14, 0xb7, 0xca, 0x8d, 0x4e, 0xb8, 0x16, 0x18, - 0xcd, 0xcc, 0x5d, 0x62, 0xdf, 0x56, 0x8a, 0x19, 0x3b, 0x8e, 0x61, 0xf3, - 0xb0, 0x1e, 0xdc, 0xa1, 0x18, 0xcc, 0xf7, 0x34, 0x1c, 0x1a, 0x2c, 0xc0, - 0xdd, 0x7b, 0x5a, 0x19, 0xdb, 0x4c, 0xe2, 0x66, 0x8d, 0xff, 0x1c, 0xde, - 0xc7, 0x49, 0x53, 0xde, 0x11, 0x2a, 0x42, 0xab, 0x26, 0x7b, 0x80, 0x98, - 0x79, 0x4e, 0xbb, 0xe4, 0x3d, 0x71, 0x4f, 0x91, 0x91, 0x7f, 0xdf, 0xdf, - 0x60, 0xae, 0x38, 0x89, 0xfd, 0x83, 0xb2, 0x2e, 0x50, 0xa5, 0x1c, 0xef, - 0x9f, 0xeb, 0xeb, 0x22, 0xe6, 0x3f, 0x64, 0x66, 0x70, 0x7e, 0x61, 0x25, - 0x30, 0x5d, 0x41, 0xe8, 0xd3, 0x01, 0xf9, 0x9e, 0x0d, 0xff, 0xde, 0xb3, - 0xfc, 0x5f, 0x90, 0x76, 0x4a, 0xcb, 0xb2, 0x6b, 0x05, 0x3f, 0xaa, 0x94, - 0xf7, 0x01, 0x8f, 0x27, 0x2b, 0xca, 0xb3, 0xcf, 0x9c, 0xff, 0x54, 0x1f, - 0x6f, 0x58, 0x7e, 0xbb, 0x8d, 0x7c, 0xdd, 0xd7, 0xad, 0xa8, 0x57, 0xca, - 0x17, 0xb0, 0x6d, 0xf1, 0xcb, 0x2a, 0x65, 0x1d, 0x71, 0x54, 0x0d, 0x55, - 0x29, 0xad, 0x43, 0x97, 0xb7, 0xfb, 0x9a, 0x15, 0x6d, 0x96, 0xf3, 0x7c, - 0x39, 0x8b, 0xf7, 0xa5, 0x6c, 0xfe, 0xfe, 0x0b, 0xb9, 0xb6, 0x0a, 0xc9, - 0x53, 0xb3, 0x65, 0xee, 0xee, 0x97, 0xfd, 0x4b, 0x51, 0x9c, 0xa8, 0x9f, - 0xda, 0x5e, 0xbe, 0xef, 0xef, 0x5c, 0xd2, 0x5e, 0xb6, 0x6c, 0x55, 0x15, - 0x8a, 0xa5, 0x7c, 0x06, 0xff, 0x8f, 0xbd, 0x86, 0x70, 0xc6, 0xde, 0x73, - 0xb8, 0xcd, 0x6c, 0x88, 0x16, 0xe1, 0x33, 0x50, 0xaf, 0x8a, 0xcf, 0x2f, - 0xb2, 0xb9, 0x6d, 0xb4, 0xb9, 0x88, 0xf9, 0xad, 0xdb, 0x88, 0x3e, 0xe4, - 0x46, 0x26, 0xe3, 0x86, 0xde, 0x72, 0x5e, 0x39, 0xa4, 0xdc, 0x1d, 0xd0, - 0xdb, 0xdf, 0x23, 0xd7, 0x78, 0x39, 0x10, 0xb7, 0x4a, 0x0d, 0xc3, 0xd7, - 0xab, 0xe8, 0xe6, 0x1a, 0xc6, 0xb2, 0x17, 0x99, 0x3f, 0xb6, 0x05, 0x7a, - 0xec, 0xe7, 0x8b, 0x4a, 0x64, 0x05, 0xae, 0xb4, 0xbf, 0xdd, 0xd2, 0x0c, - 0x23, 0xf5, 0xb2, 0xac, 0x77, 0xf1, 0x77, 0x0c, 0xf3, 0xed, 0x6b, 0x6d, - 0x08, 0xda, 0xff, 0x57, 0xe5, 0xbe, 0xef, 0xd2, 0x82, 0x1a, 0xfb, 0xff, - 0x1d, 0x98, 0x9b, 0xba, 0xb0, 0x2e, 0x8c, 0x4d, 0xa6, 0x65, 0x3d, 0x67, - 0x5a, 0x38, 0x73, 0x71, 0xbf, 0xf3, 0x0a, 0x07, 0xf3, 0x0d, 0x52, 0xac, - 0x58, 0xf6, 0xfb, 0x54, 0x17, 0xdf, 0x97, 0x58, 0x7a, 0xc9, 0x7e, 0x67, - 0xf9, 0xae, 0x42, 0xa5, 0xfd, 0xfd, 0xb1, 0x79, 0x8b, 0x9c, 0x78, 0x29, - 0x51, 0x16, 0xf3, 0xf0, 0xf7, 0xe6, 0x45, 0x05, 0x58, 0x4f, 0x4e, 0xd6, - 0x74, 0xd5, 0x33, 0x38, 0x67, 0x7f, 0xc7, 0x21, 0x1e, 0x92, 0xef, 0x37, - 0x9c, 0x48, 0xd0, 0xa7, 0x07, 0xbb, 0x43, 0xfb, 0xed, 0xbe, 0x5f, 0xc7, - 0xa6, 0x51, 0x79, 0xe6, 0xd7, 0x8c, 0xd5, 0x89, 0x49, 0xc6, 0x37, 0x69, - 0x4b, 0xf2, 0x6e, 0x3d, 0xd3, 0xc6, 0x5c, 0x55, 0x75, 0x04, 0x71, 0x3b, - 0xe3, 0xca, 0x2b, 0x09, 0xda, 0xe9, 0x42, 0xbd, 0xe3, 0xdb, 0xe4, 0x06, - 0x65, 0x11, 0x3d, 0xf8, 0xae, 0xd2, 0x82, 0x31, 0xd6, 0x9f, 0x48, 0x88, - 0x2d, 0x56, 0xc6, 0x0a, 0x39, 0x96, 0x43, 0xe4, 0xa3, 0x2f, 0x27, 0x34, - 0x9c, 0xab, 0xf7, 0x20, 0x45, 0x7e, 0xfa, 0x52, 0x42, 0xb8, 0x9a, 0x17, - 0x4f, 0x0c, 0xca, 0xfa, 0x60, 0x23, 0x1a, 0x12, 0xb2, 0x36, 0xec, 0xc5, - 0xe3, 0x23, 0x5e, 0xda, 0xa3, 0x65, 0x6d, 0xa2, 0xed, 0xb6, 0x6a, 0x13, - 0xec, 0x53, 0xd6, 0x14, 0xa3, 0xb8, 0xa9, 0xb7, 0x12, 0x4f, 0x8c, 0xf8, - 0xf0, 0x3d, 0xf2, 0xf1, 0x3e, 0xd6, 0x7b, 0x25, 0xe1, 0x47, 0x6f, 0xca, - 0x87, 0xe7, 0xc9, 0xcb, 0xb7, 0xf2, 0x5c, 0xbe, 0x05, 0x56, 0x60, 0x04, - 0x91, 0x48, 0x1d, 0x63, 0x6c, 0xbc, 0x02, 0x6b, 0x57, 0x1e, 0x81, 0xda, - 0x7b, 0x94, 0xc7, 0xf5, 0x8c, 0xd5, 0xd7, 0x23, 0x39, 0x18, 0x41, 0x72, - 0xe4, 0x87, 0xe8, 0x19, 0x94, 0x71, 0xc9, 0x37, 0xa1, 0x64, 0x6f, 0x91, - 0x81, 0xf9, 0x8c, 0xa7, 0x43, 0x23, 0xd2, 0x4f, 0x25, 0xfb, 0xfe, 0x4b, - 0xdb, 0xff, 0x99, 0xb5, 0xf6, 0xf3, 0xd2, 0xf6, 0x91, 0x3f, 0xd1, 0xbe, - 0xe8, 0x2a, 0xff, 0x6e, 0x9f, 0xac, 0x73, 0xb8, 0xd9, 0xa6, 0x07, 0x8e, - 0x48, 0x66, 0x65, 0x29, 0xf4, 0xe8, 0x76, 0xc5, 0x68, 0x2a, 0x51, 0x26, - 0xb1, 0x3d, 0x2d, 0xef, 0x71, 0x15, 0xe2, 0x79, 0x72, 0x02, 0x57, 0x48, - 0xd7, 0xbe, 0x4d, 0xdb, 0x59, 0x42, 0x8c, 0x39, 0x63, 0x7e, 0x1a, 0x71, - 0x4d, 0xf4, 0x57, 0x88, 0x57, 0xfb, 0xdd, 0x78, 0x37, 0xc4, 0x98, 0x6d, - 0xef, 0xa1, 0xf6, 0xe0, 0x27, 0x09, 0x2f, 0xe7, 0xab, 0x36, 0x63, 0x38, - 0xe6, 0x02, 0x55, 0xd9, 0x6b, 0x27, 0x12, 0x6d, 0xd8, 0x4f, 0x79, 0x5f, - 0x49, 0x9c, 0xe7, 0xfc, 0xac, 0xa3, 0xfe, 0x45, 0xdf, 0xf1, 0x9c, 0xae, - 0xbb, 0xa9, 0xeb, 0x99, 0x78, 0x31, 0xf1, 0x30, 0x9e, 0xa0, 0xfc, 0x8f, - 0xf7, 0x1b, 0xd1, 0x39, 0xca, 0x31, 0x1c, 0x1a, 0x2a, 0x24, 0x7e, 0xbb, - 0x71, 0x37, 0xb3, 0xe4, 0x49, 0xe9, 0x2b, 0x29, 0x6b, 0x93, 0x0a, 0xb9, - 0xc7, 0x31, 0x8c, 0xf3, 0xde, 0x4f, 0xf8, 0x3b, 0xbc, 0xb0, 0x9c, 0x7d, - 0x88, 0x7e, 0xfc, 0x76, 0x1e, 0xd0, 0x45, 0x7e, 0xb3, 0xbc, 0xfe, 0x98, - 0xcd, 0x79, 0xba, 0x93, 0xad, 0xe8, 0xe9, 0x7f, 0x9f, 0x7c, 0x8e, 0x38, - 0xe4, 0xad, 0xa7, 0xad, 0x67, 0xb0, 0x3d, 0xf5, 0xef, 0x55, 0x59, 0xee, - 0xf9, 0x6a, 0x95, 0xec, 0xeb, 0x3d, 0x91, 0x28, 0xc4, 0x4b, 0xac, 0xb3, - 0x36, 0xe4, 0xca, 0x3d, 0x2f, 0x39, 0x86, 0x5e, 0xe2, 0x6a, 0x8a, 0x7d, - 0x24, 0xec, 0x36, 0xaa, 0x94, 0xbd, 0xf4, 0xc3, 0xf2, 0x85, 0x55, 0x4a, - 0x92, 0xe7, 0x7d, 0xc9, 0x1f, 0xe2, 0xd9, 0x47, 0xb2, 0x3a, 0xdc, 0x6f, - 0xb6, 0x61, 0x28, 0x75, 0x2a, 0xd7, 0xde, 0x8f, 0xa7, 0xbc, 0x9b, 0x26, - 0xef, 0xba, 0xe4, 0xdf, 0x7b, 0xc9, 0x3e, 0xcf, 0x7a, 0x2a, 0x5d, 0x46, - 0xde, 0x5c, 0x4c, 0x5b, 0x2b, 0x88, 0x79, 0x19, 0x4f, 0xdb, 0x16, 0x68, - 0xd8, 0x75, 0xcd, 0x9c, 0x2a, 0x94, 0x69, 0xee, 0x5f, 0xd7, 0xbf, 0xcc, - 0x7e, 0xca, 0x62, 0x15, 0x91, 0x8c, 0xbd, 0x07, 0x2a, 0x74, 0x4d, 0x35, - 0x73, 0x68, 0x79, 0x2e, 0x1c, 0xc3, 0xdb, 0x89, 0xca, 0x58, 0x65, 0xa4, - 0x9c, 0x78, 0x7b, 0x0e, 0xbd, 0xc3, 0xc4, 0x76, 0xf2, 0xe5, 0xd2, 0xbe, - 0x4a, 0xb8, 0xed, 0x35, 0xbc, 0x2b, 0x30, 0x63, 0xf7, 0x2c, 0xf8, 0x76, - 0xcf, 0x24, 0x5f, 0x61, 0x6e, 0x19, 0xb2, 0xac, 0x9f, 0x2f, 0xb4, 0xac, - 0x2b, 0x79, 0x14, 0xf1, 0x38, 0x1b, 0x12, 0x3f, 0x8d, 0xa2, 0xd6, 0xf6, - 0x57, 0x03, 0x75, 0xf6, 0xff, 0x46, 0xfa, 0x7a, 0x47, 0x68, 0xfe, 0xf8, - 0xc3, 0xa1, 0xb9, 0xe3, 0xd5, 0x50, 0x07, 0xa6, 0xc1, 0xc1, 0xb6, 0x3e, - 0x77, 0x8d, 0x85, 0x46, 0xfa, 0xf0, 0x1a, 0x53, 0xf8, 0x50, 0x1b, 0xf9, - 0x50, 0x4f, 0xc8, 0x18, 0x3f, 0x82, 0x1b, 0xc9, 0x97, 0xdd, 0x03, 0x3e, - 0xf6, 0x23, 0xf9, 0xb5, 0x33, 0x33, 0x9b, 0x3c, 0xfb, 0xd3, 0x0b, 0x85, - 0x1b, 0xb5, 0x90, 0x1b, 0x1d, 0x45, 0xcb, 0xf8, 0x31, 0xdc, 0xca, 0x32, - 0x1e, 0xe6, 0xfd, 0x7d, 0xe9, 0x1f, 0x92, 0x77, 0x58, 0x8c, 0x39, 0x19, - 0xdc, 0xcc, 0xb6, 0x8b, 0x07, 0x9a, 0x70, 0xf7, 0xf8, 0x0a, 0xac, 0x1d, - 0xb7, 0xb0, 0x3c, 0x34, 0x81, 0xe5, 0xe3, 0xe4, 0x9a, 0xe3, 0x79, 0x7f, - 0x15, 0x9e, 0xb4, 0x82, 0x3c, 0x49, 0xe2, 0xd0, 0x2a, 0x7b, 0x1d, 0x4d, - 0xa5, 0x1f, 0x36, 0x24, 0xe4, 0x9d, 0x9b, 0x38, 0x56, 0x8f, 0x0b, 0x56, - 0x3f, 0x88, 0x4d, 0xe3, 0xb2, 0x2e, 0xfb, 0xf5, 0xd0, 0x9c, 0xf1, 0xd7, - 0xd1, 0x30, 0x3e, 0x14, 0x9a, 0x37, 0x3e, 0x42, 0xb9, 0x13, 0x94, 0xad, - 0x3f, 0x54, 0x33, 0x3e, 0x18, 0x0a, 0x8e, 0xef, 0x0d, 0x05, 0xc6, 0x9b, - 0xb1, 0x75, 0x7c, 0x15, 0xb6, 0x8c, 0xb7, 0x63, 0xf3, 0xb8, 0xe0, 0xfc, - 0x24, 0x96, 0x8d, 0x9f, 0xc1, 0xd2, 0xf1, 0x97, 0xd1, 0x38, 0x7e, 0x0a, - 0x4b, 0xc6, 0x7f, 0x88, 0xa6, 0xf1, 0x1f, 0x73, 0x2c, 0xb2, 0xce, 0x2b, - 0x6b, 0xbc, 0xf9, 0x67, 0x6a, 0xf9, 0xf7, 0x44, 0xf3, 0xdf, 0xd7, 0x70, - 0x21, 0xaa, 0xbd, 0x81, 0xee, 0x3d, 0xf2, 0xbd, 0xc1, 0x5a, 0x6d, 0x93, - 0xfd, 0xbe, 0xc1, 0xcb, 0xb2, 0x4f, 0x1d, 0x45, 0xc6, 0xe5, 0xef, 0xc5, - 0xcb, 0x77, 0x31, 0xe4, 0x39, 0xe7, 0x24, 0xba, 0xd2, 0xe7, 0xad, 0xa8, - 0x26, 0x65, 0xde, 0xc0, 0xe6, 0x3d, 0xf2, 0x3e, 0x71, 0x06, 0x5d, 0x49, - 0x79, 0x0e, 0x2f, 0xef, 0xa0, 0xbf, 0x81, 0x2d, 0xa3, 0xb6, 0xaf, 0xa1, - 0x71, 0x48, 0xde, 0x89, 0x69, 0xc3, 0x75, 0xc9, 0x8c, 0xbd, 0x56, 0x5e, - 0x66, 0xe0, 0xef, 0x67, 0xe0, 0x41, 0xe6, 0x04, 0x05, 0xe4, 0xfd, 0xc5, - 0xe8, 0x7c, 0x24, 0x6e, 0x15, 0x1a, 0x1e, 0xcc, 0x88, 0x18, 0x99, 0x77, - 0x1d, 0xc5, 0xe8, 0xe0, 0xb5, 0xfb, 0x76, 0xc2, 0xef, 0x33, 0x44, 0xf7, - 0x81, 0xd8, 0x28, 0x63, 0xec, 0x86, 0x7d, 0x19, 0xf2, 0x8b, 0x0e, 0xf8, - 0xf9, 0x7f, 0x7b, 0x52, 0xf6, 0x21, 0x6d, 0x42, 0x74, 0x9f, 0xe8, 0xb0, - 0x99, 0x3a, 0x9c, 0x64, 0xdc, 0x90, 0x67, 0x38, 0x46, 0x70, 0x2b, 0x64, - 0x9d, 0x52, 0xc5, 0xf7, 0x06, 0xe5, 0x79, 0x83, 0xde, 0xf1, 0x25, 0xfa, - 0xf4, 0x87, 0xca, 0x0f, 0x51, 0x76, 0x40, 0xf8, 0xd2, 0x04, 0x7a, 0x84, - 0x6f, 0x47, 0x14, 0x23, 0x15, 0x38, 0x0b, 0xcf, 0x01, 0xc1, 0x5d, 0x27, - 0x4a, 0xc6, 0xe4, 0xfb, 0x38, 0x40, 0x31, 0xf3, 0x12, 0x1c, 0x20, 0xa7, - 0x3d, 0x70, 0x0a, 0xd8, 0x27, 0xeb, 0x56, 0xaf, 0x61, 0x72, 0x48, 0xe6, - 0xad, 0x8d, 0xf3, 0x26, 0x7e, 0xf8, 0x7d, 0x0c, 0x0f, 0x79, 0xe8, 0xe3, - 0x13, 0x1c, 0xc7, 0xeb, 0x78, 0x74, 0x8f, 0x3c, 0x17, 0x99, 0x89, 0x36, - 0xd6, 0x3b, 0xc1, 0x3c, 0xbf, 0x75, 0xcc, 0xe4, 0x78, 0x56, 0xa1, 0xf3, - 0xc0, 0x17, 0x78, 0x4c, 0xc3, 0x43, 0x07, 0xd6, 0x71, 0x8c, 0x71, 0x74, - 0x8c, 0x75, 0xf3, 0x68, 0xc5, 0xc6, 0x9d, 0x26, 0xb9, 0xa0, 0xd8, 0xb4, - 0x46, 0x3f, 0x6b, 0xe5, 0x98, 0xa4, 0x8f, 0xd5, 0xf8, 0x19, 0x31, 0xa6, - 0x29, 0xb4, 0x1a, 0xe7, 0x6c, 0xbf, 0x5b, 0x8d, 0x2d, 0xfd, 0x46, 0xf0, - 0x24, 0x56, 0x63, 0x33, 0xcf, 0x1f, 0xa5, 0xef, 0xcf, 0x21, 0x17, 0xbc, - 0x93, 0xbe, 0xbd, 0x78, 0x78, 0x42, 0xbe, 0x9d, 0x80, 0xbe, 0x5d, 0x32, - 0x1f, 0x6d, 0xf0, 0x8d, 0x65, 0x50, 0x3e, 0xc6, 0xec, 0x79, 0x27, 0xee, - 0x2a, 0x43, 0x39, 0xbe, 0x11, 0x92, 0x3d, 0x0b, 0x3f, 0x40, 0xf1, 0x3e, - 0x91, 0xf5, 0x87, 0x6c, 0xfb, 0x1c, 0x73, 0xf1, 0x53, 0x9c, 0x83, 0xfc, - 0xb3, 0xf1, 0x5f, 0xe0, 0x60, 0x6a, 0x92, 0xb8, 0x7a, 0x9a, 0xc7, 0xe5, - 0xcf, 0xa5, 0xbd, 0x76, 0x8e, 0x92, 0xdd, 0xff, 0xed, 0xc4, 0x8c, 0x3e, - 0x59, 0xdf, 0x6d, 0x86, 0x2f, 0x29, 0x7c, 0x27, 0xb3, 0x8d, 0xf9, 0x4a, - 0x7b, 0xd8, 0xe6, 0x3f, 0x46, 0x8c, 0xbc, 0xa7, 0xf9, 0xdb, 0x8a, 0x87, - 0xbc, 0x27, 0x88, 0x15, 0x69, 0x3d, 0x7a, 0x33, 0xf5, 0x5b, 0xf4, 0xc8, - 0x8f, 0xe0, 0x7c, 0xc4, 0x89, 0x42, 0xe6, 0x37, 0xa1, 0x90, 0xe8, 0x59, - 0xde, 0x95, 0xcd, 0xe8, 0x85, 0xc4, 0xcc, 0x82, 0xbe, 0x0c, 0xe7, 0x27, - 0x33, 0xbf, 0x00, 0x7e, 0xce, 0xcd, 0x0d, 0x68, 0xeb, 0x8f, 0x72, 0x6e, - 0x3e, 0x45, 0x1b, 0x9b, 0xa0, 0xbd, 0x48, 0x4e, 0xf4, 0x32, 0x65, 0x74, - 0xe5, 0xbe, 0xc9, 0x93, 0xd1, 0x9d, 0xd0, 0x4d, 0xbf, 0x5a, 0x95, 0x7d, - 0x27, 0x05, 0xf6, 0xb3, 0xe7, 0x30, 0xf0, 0x06, 0x6d, 0x33, 0xcf, 0x67, - 0x2c, 0xab, 0x9d, 0xf6, 0xd5, 0x3f, 0x2a, 0xbe, 0xb2, 0xb4, 0x2a, 0xfb, - 0xbe, 0xee, 0x54, 0xae, 0x93, 0xaf, 0xeb, 0x20, 0x36, 0xe6, 0xef, 0xff, - 0x08, 0x77, 0x32, 0x7e, 0x9d, 0x59, 0x78, 0x2a, 0x67, 0xf3, 0xd3, 0xab, - 0xb3, 0xf8, 0xf5, 0x49, 0xdf, 0x0b, 0xfa, 0x2b, 0xfb, 0xdb, 0x3b, 0xd9, - 0x6f, 0x1f, 0x01, 0xcf, 0x26, 0x0a, 0xe4, 0x29, 0xc1, 0x62, 0x17, 0x54, - 0xaf, 0x0b, 0x85, 0x8c, 0x01, 0xd5, 0xd8, 0xe4, 0xb5, 0x70, 0xa3, 0x59, - 0x80, 0x43, 0x75, 0xb7, 0x00, 0x15, 0xf1, 0x16, 0x97, 0xfd, 0x4e, 0xde, - 0xef, 0xbf, 0xf4, 0x87, 0xef, 0xe4, 0x9d, 0xb1, 0xf3, 0xe1, 0x52, 0xe3, - 0x76, 0xbc, 0x62, 0xc7, 0x09, 0x05, 0x25, 0x73, 0x65, 0x5d, 0xd2, 0x8f, - 0x17, 0x8d, 0x5a, 0x7f, 0x85, 0x3c, 0x6f, 0x52, 0xce, 0x5a, 0x71, 0xaf, - 0xbc, 0x87, 0xf7, 0xc7, 0xf6, 0x8f, 0x3f, 0x87, 0xad, 0xbb, 0xc2, 0x90, - 0xf7, 0x3b, 0x9c, 0x46, 0xa1, 0x37, 0x2b, 0xbf, 0xc8, 0x26, 0xeb, 0x44, - 0xb7, 0x71, 0x1c, 0x67, 0xe8, 0x8b, 0x67, 0xec, 0x75, 0x2a, 0xb7, 0xf1, - 0xd7, 0x08, 0x56, 0xe4, 0xc7, 0x2f, 0x39, 0x8d, 0x92, 0xd5, 0x41, 0xf6, - 0xfd, 0xda, 0x6a, 0xc1, 0xfe, 0x2d, 0xc9, 0x33, 0xf6, 0x9a, 0xac, 0xcb, - 0xf8, 0x0f, 0xeb, 0x2d, 0x6f, 0x25, 0xcb, 0x3e, 0x95, 0xbb, 0x3f, 0x29, - 0xeb, 0x38, 0xa6, 0x7c, 0xbb, 0xca, 0x69, 0xd7, 0x11, 0xbd, 0x5f, 0xac, - 0xb3, 0x89, 0xbc, 0x7a, 0xb6, 0x71, 0xca, 0xea, 0xf4, 0xca, 0x18, 0xd6, - 0x5c, 0x56, 0x47, 0xd6, 0x08, 0x34, 0xe9, 0x37, 0x2c, 0x63, 0xee, 0x4a, - 0xff, 0x61, 0x9f, 0xb2, 0x7e, 0x5b, 0x60, 0x94, 0xe0, 0x6c, 0x45, 0x76, - 0x4d, 0xe5, 0xa2, 0x8c, 0xed, 0xd5, 0xb2, 0xef, 0xae, 0xd0, 0x3e, 0xb7, - 0xfb, 0x35, 0x2f, 0xd6, 0x7b, 0x30, 0x37, 0xde, 0x4a, 0xfb, 0x9d, 0x9a, - 0x47, 0x6d, 0xae, 0xe3, 0x98, 0x32, 0xee, 0xdf, 0x78, 0x2f, 0xed, 0xe7, - 0xf3, 0xb9, 0x7e, 0x45, 0x1e, 0xef, 0x94, 0x3e, 0x44, 0xae, 0xde, 0x5c, - 0x1d, 0x3d, 0x1c, 0xb5, 0xfb, 0x57, 0x11, 0xde, 0x93, 0xef, 0xd3, 0xb2, - 0x0a, 0x16, 0xe6, 0xdb, 0xc8, 0xd0, 0x0f, 0xad, 0xce, 0x42, 0xc6, 0xab, - 0xb3, 0xf5, 0x0f, 0x62, 0x73, 0x42, 0xf4, 0x2c, 0xdf, 0x70, 0x25, 0x2e, - 0xdb, 0xfc, 0xcb, 0xc5, 0x5c, 0xf6, 0x1a, 0x0c, 0x69, 0x71, 0xec, 0xaf, - 0x93, 0x77, 0xc8, 0x5c, 0xf4, 0x85, 0x38, 0x71, 0xb0, 0x90, 0x38, 0x1a, - 0xb7, 0xf7, 0x94, 0x1c, 0x34, 0xf5, 0xe8, 0xb3, 0xf2, 0x8d, 0xb2, 0xab, - 0xec, 0xb5, 0xa7, 0xa6, 0x21, 0xc8, 0xf5, 0xfc, 0x7a, 0x52, 0xfe, 0xaf, - 0x88, 0xb6, 0x23, 0x72, 0x89, 0x0d, 0x50, 0xba, 0x84, 0xbc, 0xeb, 0x54, - 0x1b, 0x23, 0x67, 0xc4, 0x2b, 0x29, 0xd9, 0x7f, 0xf0, 0x5b, 0x2b, 0x5e, - 0x2d, 0xfb, 0x1c, 0xa7, 0xd6, 0x29, 0x20, 0x97, 0x0b, 0x84, 0xcb, 0x94, - 0xfc, 0xfb, 0x4e, 0x17, 0xff, 0x6e, 0xa5, 0xcd, 0x9c, 0xb3, 0xdf, 0x51, - 0x93, 0xb3, 0x08, 0x1a, 0x92, 0xf2, 0xad, 0x52, 0x7d, 0x62, 0x39, 0x6a, - 0x33, 0x35, 0x0e, 0x67, 0x8e, 0x93, 0x84, 0xb1, 0x82, 0x76, 0xb3, 0x25, - 0x10, 0xb6, 0xdf, 0xc5, 0x5a, 0x96, 0xac, 0x09, 0x3e, 0xce, 0x1c, 0xfa, - 0x1d, 0x96, 0xbf, 0x25, 0xfd, 0x3d, 0x6b, 0xc8, 0x2b, 0x63, 0xca, 0x63, - 0xc3, 0x29, 0xfa, 0x06, 0xf5, 0x18, 0x11, 0xff, 0xf0, 0xa0, 0x22, 0x12, - 0xa6, 0xff, 0x4a, 0x4c, 0x97, 0xf7, 0xb8, 0xf4, 0xbd, 0x71, 0x98, 0xc4, - 0xfc, 0x1e, 0xda, 0x91, 0xec, 0x5b, 0xd6, 0xfd, 0x2b, 0x19, 0x5b, 0x8e, - 0x5f, 0x78, 0xc6, 0x2f, 0x1c, 0xe0, 0xd9, 0xea, 0xdc, 0xde, 0x66, 0xf7, - 0x6c, 0xc6, 0x3c, 0xcb, 0x7e, 0x6e, 0xdf, 0x66, 0x63, 0x8a, 0x66, 0xe8, - 0x87, 0x7e, 0xe5, 0xe8, 0xc4, 0xd3, 0x0b, 0x8c, 0x8e, 0xc3, 0x6a, 0x66, - 0xc8, 0x47, 0x7c, 0xb9, 0xde, 0x11, 0xdd, 0xc9, 0xff, 0xfe, 0xd7, 0xec, - 0x6f, 0xab, 0x48, 0x5d, 0x3d, 0xb8, 0x4a, 0x95, 0xfd, 0x40, 0xcd, 0x18, - 0xeb, 0x95, 0x77, 0x06, 0xf4, 0x96, 0xa7, 0x94, 0x4e, 0x6c, 0x08, 0x19, - 0xcd, 0xed, 0x8a, 0xde, 0xf4, 0x0f, 0x8a, 0xee, 0x0f, 0x29, 0x52, 0x2e, - 0xc8, 0xbc, 0xeb, 0x62, 0x3c, 0x75, 0xb1, 0x8f, 0x03, 0x09, 0x3d, 0x5c, - 0xc5, 0xb2, 0x67, 0x4d, 0xc3, 0xf7, 0x3e, 0xdb, 0xfc, 0x57, 0x1e, 0x3b, - 0xed, 0xf7, 0xc4, 0xa5, 0x7c, 0x74, 0xbe, 0xcb, 0xfe, 0xbe, 0x69, 0x0b, - 0xe3, 0xae, 0x7c, 0x23, 0x38, 0x06, 0xad, 0x6f, 0x26, 0x4d, 0x4c, 0xef, - 0xb9, 0x0d, 0xb2, 0xe7, 0xa0, 0x89, 0x09, 0xba, 0x07, 0xde, 0x48, 0x27, + 0x9d, 0xbc, 0x0d, 0x78, 0x1b, 0xe5, 0x95, 0x36, 0x7c, 0xcf, 0x48, 0xb2, + 0x65, 0x5b, 0xb6, 0xc7, 0x8e, 0x9c, 0x28, 0x6c, 0x9a, 0x68, 0xf0, 0x28, + 0x51, 0xb0, 0x69, 0x47, 0x89, 0x03, 0x82, 0x55, 0x89, 0xea, 0x98, 0xc4, + 0x81, 0x50, 0x9c, 0x12, 0x5a, 0xb3, 0x4b, 0x5b, 0xe1, 0xfc, 0x60, 0x42, + 0xa0, 0xa1, 0xb0, 0xef, 0x9a, 0xef, 0x65, 0x5f, 0xab, 0xb6, 0x93, 0x38, + 0x89, 0x2c, 0x39, 0x8e, 0x21, 0x61, 0xbf, 0x5e, 0x8b, 0x89, 0x9d, 0x38, + 0x80, 0x6c, 0x85, 0x36, 0xdd, 0x0d, 0x7d, 0xd3, 0x8d, 0x36, 0x09, 0x60, + 0xfe, 0xda, 0x40, 0xbb, 0x2c, 0xed, 0xcb, 0x07, 0xde, 0x14, 0x42, 0xd8, + 0xb6, 0x40, 0xb7, 0x3f, 0x1b, 0x5a, 0xca, 0xbc, 0xf7, 0x19, 0x49, 0x89, + 0x13, 0x28, 0xed, 0x7e, 0xbe, 0xae, 0xb9, 0xac, 0x99, 0x79, 0x7e, 0xce, + 0x73, 0x9e, 0x73, 0xee, 0x73, 0x9f, 0x67, 0x9e, 0x19, 0x3f, 0x50, 0x8a, + 0xfc, 0x5f, 0x39, 0x8f, 0x4f, 0x37, 0x6c, 0x5c, 0xbd, 0x60, 0xc1, 0xa7, + 0x1b, 0xe4, 0xdc, 0x39, 0xdd, 0xe9, 0xc4, 0x9f, 0xf9, 0xe7, 0xff, 0x73, + 0x0b, 0x7e, 0xcc, 0x9f, 0x03, 0xd0, 0x0a, 0xfd, 0xcb, 0x01, 0xb7, 0x1a, + 0x71, 0xde, 0xdc, 0x68, 0xc0, 0xed, 0x88, 0x4c, 0xb4, 0xad, 0x36, 0x80, + 0x68, 0xba, 0xce, 0xbf, 0x04, 0x7f, 0xb0, 0xe2, 0x5e, 0x27, 0xe4, 0xfa, + 0xa7, 0x22, 0x1f, 0x74, 0x7e, 0xef, 0x72, 0xfd, 0xbd, 0x21, 0x07, 0xdc, + 0x5a, 0x24, 0x0e, 0x6d, 0x2e, 0xdc, 0xb3, 0x58, 0xe7, 0x9b, 0xf3, 0xbe, + 0xa9, 0xa0, 0xa2, 0xd0, 0xd6, 0x69, 0xeb, 0x7b, 0xf3, 0x7c, 0xb1, 0x92, + 0x88, 0x86, 0x23, 0x19, 0xb4, 0xd4, 0xf7, 0x75, 0x5a, 0xe5, 0x46, 0x08, + 0x6e, 0xc3, 0x68, 0xed, 0x53, 0x3c, 0xe1, 0xf5, 0x8b, 0xe0, 0x29, 0x36, + 0x10, 0xbf, 0x28, 0x82, 0x96, 0x4b, 0xc6, 0x4a, 0xe3, 0xce, 0x88, 0x1b, + 0xcd, 0x19, 0x77, 0xfc, 0x2f, 0x22, 0x06, 0x96, 0x65, 0x66, 0x95, 0xa2, + 0xc2, 0x8d, 0x9e, 0xcc, 0xeb, 0x25, 0xb9, 0xf6, 0xea, 0xf3, 0xff, 0x83, + 0xd3, 0x72, 0xff, 0xa7, 0xc7, 0x9c, 0x11, 0x60, 0x53, 0xc2, 0xb2, 0x8a, + 0x22, 0x37, 0xdc, 0xa0, 0x46, 0x0c, 0xdf, 0x3e, 0x2c, 0x46, 0x9b, 0x86, + 0xfb, 0x36, 0x37, 0xfc, 0xa7, 0x72, 0x74, 0x90, 0x0d, 0x8f, 0x3a, 0x10, + 0xd5, 0x8e, 0xf3, 0xff, 0xec, 0xd9, 0xad, 0x61, 0x03, 0xbb, 0x47, 0xcf, + 0xf0, 0xba, 0xd3, 0xbe, 0xd6, 0xbd, 0x6b, 0xf6, 0xec, 0x9b, 0xc2, 0xc7, + 0xf1, 0xe0, 0xa8, 0xfc, 0xbe, 0x15, 0x9d, 0xf5, 0x0a, 0x26, 0x6f, 0x58, + 0x07, 0x87, 0x61, 0xa0, 0x67, 0x97, 0xe2, 0xec, 0xaa, 0x57, 0x11, 0xf5, + 0xea, 0xc1, 0x18, 0x27, 0xc1, 0x69, 0x20, 0x56, 0x1c, 0x09, 0x3b, 0xdf, + 0x4e, 0x44, 0x34, 0x87, 0x61, 0x59, 0xc1, 0xd0, 0x0c, 0x38, 0xaa, 0x2c, + 0xeb, 0x09, 0xd3, 0x03, 0xff, 0x97, 0x9e, 0x42, 0x7c, 0xb8, 0x05, 0xaa, + 0xf1, 0x14, 0xba, 0x86, 0x9f, 0xc2, 0x43, 0x3b, 0x4b, 0x31, 0x39, 0x8d, + 0xe3, 0x4d, 0xf9, 0xf0, 0xbd, 0x79, 0xd2, 0xb7, 0xc8, 0x51, 0xcf, 0xc3, + 0x8d, 0x49, 0xc7, 0x6b, 0xfc, 0x2f, 0x65, 0xce, 0x58, 0x93, 0x33, 0xce, + 0x95, 0xd9, 0xc4, 0x32, 0x3d, 0x17, 0x94, 0x89, 0x0f, 0x47, 0xf0, 0x5c, + 0x42, 0xc1, 0xfa, 0x50, 0x05, 0xa2, 0x55, 0x32, 0x5e, 0xcb, 0x1a, 0x35, + 0x4f, 0x59, 0x93, 0x9a, 0xf4, 0x35, 0x81, 0xe7, 0x79, 0x6f, 0x73, 0xe8, + 0x0d, 0x2b, 0xeb, 0x95, 0xf6, 0xbe, 0x4e, 0x1b, 0x5a, 0xc9, 0xeb, 0x4e, + 0xa4, 0x12, 0x88, 0x55, 0x44, 0x6e, 0xe4, 0xb9, 0x6e, 0xbe, 0xa3, 0xb8, + 0xdd, 0xef, 0x26, 0xdc, 0x5f, 0x2a, 0x37, 0xd4, 0x7b, 0x2a, 0xe1, 0xc4, + 0x0b, 0x94, 0xf9, 0x90, 0xb9, 0x0e, 0x2e, 0xe3, 0x6e, 0xb1, 0x39, 0x8e, + 0xeb, 0x47, 0x16, 0x66, 0x14, 0xea, 0x4b, 0xbb, 0x6e, 0x6c, 0x4e, 0x59, + 0xd6, 0x56, 0x33, 0x7a, 0x45, 0x09, 0x0d, 0xe2, 0x58, 0xa2, 0x05, 0xee, + 0x48, 0xc0, 0x7f, 0x1a, 0x61, 0x2c, 0xc9, 0x78, 0xf1, 0x64, 0x02, 0xce, + 0xc6, 0x79, 0x5e, 0x74, 0x65, 0x22, 0xb8, 0x3a, 0x63, 0xa2, 0x29, 0xf3, + 0xa7, 0x2d, 0xeb, 0xda, 0x94, 0x9f, 0x63, 0xf8, 0x83, 0x95, 0x1b, 0x83, + 0x8c, 0x2f, 0xf7, 0xbf, 0x27, 0x75, 0x11, 0xb6, 0x71, 0x8e, 0xb6, 0x70, + 0xfe, 0x96, 0x87, 0xb2, 0xd1, 0x12, 0xe8, 0xe6, 0x69, 0x44, 0xb0, 0x34, + 0x63, 0x70, 0x4e, 0x23, 0x58, 0x92, 0xaa, 0xd5, 0x86, 0x31, 0x1f, 0x51, + 0x5f, 0xce, 0xb6, 0xb7, 0x73, 0xbc, 0x6d, 0x81, 0x16, 0x94, 0xd3, 0x46, + 0xd2, 0x8b, 0xc2, 0x68, 0x64, 0xff, 0x2b, 0xfe, 0x8c, 0xfe, 0xaf, 0x67, + 0xff, 0xef, 0xb0, 0xff, 0xac, 0xdd, 0x3f, 0x9c, 0xd7, 0xf0, 0xdc, 0x4d, + 0x7b, 0xdc, 0x96, 0x76, 0x3a, 0x97, 0xa7, 0xbc, 0xd8, 0x9a, 0x36, 0x69, + 0x73, 0x72, 0xcb, 0x87, 0xcd, 0x83, 0xb3, 0xb0, 0x65, 0x50, 0xf7, 0x3d, + 0xcd, 0xdf, 0xdd, 0x23, 0x17, 0x61, 0xd3, 0xa0, 0x82, 0x3d, 0xc6, 0x45, + 0xe8, 0xe2, 0xef, 0xdd, 0x83, 0xb3, 0xf1, 0xe0, 0xa0, 0x03, 0xe1, 0x69, + 0xe7, 0x8f, 0x63, 0xd2, 0x71, 0x11, 0xe2, 0x23, 0x7e, 0x74, 0x25, 0x9e, + 0xb7, 0x75, 0x58, 0x1e, 0xf9, 0x5e, 0xc1, 0x9f, 0xe9, 0x3b, 0x7e, 0xac, + 0x4e, 0x68, 0xe8, 0x4a, 0x89, 0x1f, 0xb8, 0x69, 0x9b, 0xe2, 0x07, 0xbf, + 0x06, 0x2a, 0x34, 0x74, 0x67, 0x0a, 0xf7, 0x15, 0x38, 0x39, 0x6f, 0x6b, + 0x34, 0x37, 0xb6, 0xa6, 0xc4, 0x26, 0xa4, 0x4d, 0xb1, 0x0b, 0xf9, 0x5d, + 0x4d, 0xbb, 0x2b, 0x85, 0x7f, 0x6f, 0x29, 0x82, 0xf7, 0x6b, 0x78, 0xb3, + 0x41, 0xae, 0xd3, 0xde, 0x43, 0x52, 0xa6, 0x1f, 0xfb, 0xd2, 0xe2, 0xa7, + 0x7e, 0x34, 0x26, 0x26, 0xd8, 0x7e, 0x03, 0xdb, 0x36, 0xf1, 0xcf, 0x99, + 0x7a, 0xfc, 0x53, 0x26, 0x88, 0x7f, 0xa4, 0x1e, 0xbf, 0x93, 0xf1, 0xe3, + 0x60, 0x66, 0x16, 0xbe, 0x9d, 0xf1, 0xe1, 0x5b, 0x9c, 0xbf, 0xc7, 0x33, + 0x2d, 0xb4, 0x7d, 0x0d, 0x07, 0x32, 0xa2, 0xff, 0x22, 0x8e, 0xb7, 0x14, + 0xdd, 0x83, 0xb5, 0xc1, 0x63, 0xb4, 0xad, 0x7f, 0x34, 0xaf, 0x41, 0xb6, + 0xba, 0xc1, 0xb6, 0xc9, 0xad, 0xbc, 0xbe, 0x6d, 0xb0, 0x36, 0x7a, 0x89, + 0x62, 0x59, 0x6a, 0xa8, 0x2e, 0x7c, 0x54, 0x55, 0x31, 0xe9, 0xd5, 0xfd, + 0x59, 0x55, 0xf7, 0x47, 0xe1, 0x42, 0x82, 0xbe, 0x11, 0xaf, 0xd1, 0x87, + 0xe2, 0xb4, 0x29, 0xaf, 0x31, 0xcc, 0xf1, 0xe8, 0xfe, 0xb8, 0xea, 0xc6, + 0x96, 0x94, 0xbe, 0x3b, 0xae, 0x7a, 0x10, 0xcf, 0x94, 0xe2, 0x17, 0x83, + 0x7a, 0x6f, 0x5c, 0xfd, 0x3c, 0xe2, 0xd5, 0x96, 0xf5, 0xad, 0x10, 0x36, + 0xce, 0x88, 0x20, 0x5a, 0x13, 0x41, 0x6c, 0x76, 0xc4, 0x8b, 0x54, 0x0a, + 0x78, 0xa7, 0xcf, 0xf0, 0xfd, 0x9b, 0xd2, 0x82, 0xbf, 0x69, 0xd1, 0xfd, + 0x7e, 0xb5, 0x2e, 0x3e, 0xac, 0x2e, 0xa2, 0x4b, 0xc3, 0xef, 0x8b, 0x2c, + 0x43, 0x87, 0x7d, 0x4d, 0x81, 0x66, 0x78, 0xd0, 0x9d, 0xba, 0x02, 0x31, + 0x6f, 0x6d, 0xeb, 0x0e, 0xb5, 0xf6, 0x8c, 0xa9, 0xea, 0x13, 0x2d, 0xaa, + 0x65, 0xfd, 0x72, 0xe1, 0x3b, 0x96, 0x7f, 0xba, 0x65, 0x2d, 0x58, 0x28, + 0x7d, 0xfa, 0x51, 0x15, 0x31, 0xb1, 0xd2, 0x9e, 0xc3, 0x52, 0x9c, 0x1a, + 0xac, 0x66, 0x1f, 0x1a, 0xfe, 0xf5, 0x72, 0x3d, 0xb8, 0x4e, 0x2d, 0xc5, + 0x9b, 0x23, 0xa5, 0x38, 0xc9, 0xf1, 0xfc, 0xe7, 0xa0, 0x0f, 0xbf, 0x1e, + 0xb4, 0xac, 0x2f, 0x99, 0x7f, 0x89, 0x81, 0xea, 0x7e, 0xfc, 0xd3, 0xb8, + 0x17, 0xbf, 0xe0, 0xdc, 0xbc, 0x91, 0x88, 0xde, 0x35, 0x0d, 0x7a, 0x74, + 0x5c, 0x39, 0xf6, 0xd5, 0x0a, 0xd4, 0xb5, 0x54, 0x28, 0x7a, 0xf3, 0x76, + 0xe8, 0xbe, 0x4b, 0x14, 0x2f, 0x4e, 0xa7, 0x35, 0xfc, 0x34, 0x5d, 0x1b, + 0xfe, 0x21, 0xfb, 0xfc, 0xad, 0xf9, 0x84, 0x95, 0x9d, 0x2e, 0x7a, 0x13, + 0x1d, 0x51, 0xcf, 0x29, 0xea, 0x39, 0x45, 0x3d, 0xa7, 0xa8, 0x67, 0xca, + 0x70, 0x30, 0x45, 0x3d, 0x53, 0x77, 0xdf, 0xa2, 0x4d, 0x3d, 0xce, 0x79, + 0x3c, 0x60, 0xcf, 0x63, 0x98, 0xf3, 0xf5, 0x17, 0xf8, 0x5f, 0x36, 0xb6, + 0x3e, 0x6f, 0xfd, 0xad, 0x57, 0xc6, 0xd4, 0x3d, 0x3d, 0x87, 0x5f, 0x32, + 0xb6, 0xe7, 0xac, 0x98, 0x26, 0xe3, 0x92, 0xf1, 0xd9, 0xfa, 0xf3, 0x6f, + 0x54, 0xb6, 0x28, 0x28, 0xb5, 0xac, 0x9d, 0x66, 0xfe, 0xbe, 0xb7, 0x30, + 0xbe, 0x1b, 0x94, 0x9c, 0x5d, 0xed, 0x74, 0x53, 0xdf, 0xc1, 0xa8, 0xba, + 0x8c, 0xe7, 0x7a, 0x3c, 0x8a, 0xb9, 0xc5, 0xe7, 0x9f, 0x5f, 0x5b, 0x23, + 0xf3, 0xe1, 0x3f, 0x7b, 0x4e, 0x7b, 0xb4, 0xfb, 0xbb, 0x8d, 0xe7, 0x32, + 0x16, 0xb1, 0x45, 0xb1, 0x01, 0x2f, 0xed, 0xe5, 0xf2, 0xfc, 0x3d, 0xc4, + 0xd5, 0xc8, 0x46, 0xb4, 0x34, 0x3c, 0x6a, 0xf7, 0x51, 0x94, 0x14, 0xbf, + 0x51, 0xf0, 0xce, 0x15, 0x0a, 0x8e, 0x86, 0x0c, 0xda, 0xcc, 0x10, 0x71, + 0x01, 0x28, 0x4e, 0xc2, 0xed, 0x89, 0x44, 0x90, 0xe8, 0x83, 0xbb, 0x24, + 0x12, 0xc6, 0xfc, 0xbe, 0xda, 0xf6, 0x53, 0xd0, 0x83, 0x7d, 0x8a, 0xde, + 0x02, 0xd4, 0x99, 0x63, 0xd4, 0xe3, 0x25, 0x8a, 0xee, 0x2f, 0x52, 0xe0, + 0x56, 0x58, 0x2e, 0x90, 0x1e, 0xc2, 0x96, 0x8c, 0xfc, 0x0e, 0xc3, 0x48, + 0xff, 0xb6, 0xd0, 0x17, 0xed, 0x7e, 0x23, 0xed, 0xfe, 0x14, 0xc7, 0xae, + 0xfb, 0x89, 0xaf, 0x6e, 0x57, 0xa4, 0x1d, 0x7b, 0x13, 0x70, 0x17, 0x45, + 0x36, 0xe0, 0xa9, 0x44, 0xf5, 0xf4, 0x42, 0x39, 0x85, 0xe5, 0xfc, 0xe9, + 0xa9, 0xb2, 0xbc, 0x66, 0x45, 0xbd, 0x39, 0x59, 0x4a, 0x93, 0x43, 0xd8, + 0x9e, 0x92, 0xba, 0x11, 0xbb, 0xae, 0x93, 0x7d, 0xf4, 0x24, 0x6a, 0x9b, + 0xaf, 0x55, 0xf4, 0xf0, 0x23, 0xa8, 0x8b, 0xbe, 0xcd, 0x39, 0xec, 0x82, + 0x7e, 0xa6, 0x1d, 0x39, 0x59, 0xe6, 0xa5, 0x73, 0x72, 0x2c, 0x4e, 0x43, + 0xb9, 0x29, 0x05, 0x8f, 0xcf, 0x98, 0x96, 0xf7, 0x65, 0x28, 0xd7, 0x71, + 0xfe, 0x54, 0xc3, 0x8f, 0xeb, 0x68, 0x43, 0x1b, 0x76, 0x5a, 0xe8, 0x0e, + 0x55, 0xd3, 0x57, 0x5b, 0x50, 0x41, 0xbf, 0xbc, 0x53, 0x43, 0xb4, 0x32, + 0x12, 0x56, 0xae, 0xcf, 0x0c, 0xe7, 0xf5, 0x7f, 0xb4, 0x9a, 0xf2, 0x29, + 0x4d, 0xa9, 0x0b, 0xaf, 0x57, 0xe6, 0xe3, 0xde, 0x85, 0xd7, 0x3d, 0x45, + 0x1f, 0x5f, 0xbe, 0x4e, 0x1b, 0x81, 0xc2, 0x78, 0x53, 0x42, 0xfd, 0xea, + 0x26, 0xab, 0x05, 0x5d, 0xf6, 0x35, 0x07, 0x86, 0x9c, 0x51, 0x9f, 0x03, + 0x1f, 0x58, 0xd1, 0x55, 0x72, 0xad, 0x14, 0xb1, 0x96, 0x3a, 0x9f, 0x13, + 0x75, 0xe1, 0x4d, 0xf4, 0xb7, 0xc9, 0x55, 0x8d, 0xbc, 0x17, 0x30, 0x8f, + 0xa1, 0xd6, 0xbf, 0x09, 0xf2, 0xfb, 0x7d, 0xda, 0x48, 0xa3, 0xd4, 0x65, + 0x19, 0xb1, 0x39, 0x5d, 0x3b, 0x06, 0x2f, 0x36, 0xd1, 0xfe, 0x8a, 0x23, + 0xba, 0xb9, 0xcc, 0xe1, 0xc4, 0x7e, 0xe2, 0xb8, 0xc3, 0xe8, 0x45, 0x31, + 0xc7, 0xc8, 0xf8, 0x8a, 0x47, 0x12, 0xc0, 0xb3, 0xfd, 0x16, 0x1a, 0x43, + 0x1e, 0x2c, 0xb1, 0x6d, 0xf3, 0x90, 0x72, 0x75, 0xea, 0x43, 0x6b, 0xc8, + 0x59, 0x12, 0x55, 0x23, 0x01, 0xdf, 0x49, 0xb2, 0x81, 0xa2, 0x48, 0x9d, + 0xe6, 0x44, 0x5c, 0x69, 0xce, 0xf4, 0x28, 0xcb, 0x33, 0xbd, 0xca, 0x92, + 0x8c, 0xb4, 0x7d, 0x48, 0x59, 0x9a, 0xf1, 0x20, 0xdd, 0xaf, 0x60, 0x7b, + 0x88, 0x72, 0xd5, 0xe4, 0xec, 0x38, 0xd3, 0xaf, 0x12, 0x63, 0xdf, 0x21, + 0xc6, 0xea, 0x61, 0xb0, 0xef, 0x27, 0x12, 0xd5, 0x38, 0x44, 0x2c, 0xfd, + 0x71, 0x5a, 0x57, 0x51, 0x7a, 0x11, 0x5e, 0x19, 0xa9, 0xc0, 0xd8, 0xa0, + 0xc9, 0xdf, 0xf5, 0x78, 0x61, 0xc4, 0xb2, 0x7a, 0x4c, 0xcb, 0xda, 0x6b, + 0x1e, 0x52, 0x1a, 0xd9, 0x67, 0xd4, 0x19, 0x8f, 0x16, 0x47, 0x02, 0xe6, + 0x16, 0xf6, 0xe9, 0x88, 0xc4, 0x95, 0x28, 0xfb, 0xbb, 0x9a, 0xfd, 0x2d, + 0xcd, 0xf7, 0x97, 0xeb, 0x57, 0x64, 0x91, 0x7a, 0x85, 0x3a, 0x61, 0xd6, + 0x01, 0xf6, 0x25, 0x02, 0xc1, 0x42, 0xbd, 0xa5, 0xac, 0x73, 0xf5, 0xd9, + 0x3a, 0xc0, 0x70, 0x22, 0xc8, 0x39, 0x15, 0x5b, 0xf7, 0x33, 0x76, 0x7d, + 0x83, 0x18, 0xdb, 0x80, 0xb6, 0x61, 0xc1, 0xdf, 0x6b, 0xd4, 0xdc, 0x3c, + 0xe5, 0xb0, 0x56, 0x62, 0x5e, 0x0e, 0x6f, 0x83, 0xe8, 0xa3, 0x5f, 0x77, + 0xa5, 0xc4, 0xc6, 0xef, 0xf9, 0x72, 0x22, 0xa0, 0xe0, 0xb1, 0x40, 0xb6, + 0xa5, 0x1c, 0x95, 0x68, 0x0f, 0x89, 0x6d, 0x6e, 0xfc, 0xf2, 0x53, 0x86, + 0x1e, 0x5e, 0xa1, 0x70, 0xce, 0x02, 0x7a, 0xf3, 0x52, 0x05, 0x08, 0x8c, + 0x01, 0x6f, 0xa4, 0x2b, 0xb1, 0xda, 0x74, 0x40, 0xad, 0x0a, 0xa2, 0x37, + 0x33, 0x35, 0x2e, 0x98, 0xc4, 0x78, 0x69, 0x2f, 0x48, 0xbf, 0x2e, 0xc3, + 0x32, 0x2d, 0x67, 0xd3, 0x6e, 0xb6, 0xed, 0x0e, 0x64, 0x83, 0x2a, 0xe3, + 0xdd, 0x7e, 0x5e, 0x38, 0x46, 0xfc, 0x6f, 0x34, 0x5c, 0xc4, 0xff, 0x4a, + 0x34, 0x9a, 0xbf, 0xb3, 0x96, 0xad, 0x92, 0x7b, 0x85, 0x76, 0xe0, 0x2e, + 0x66, 0xbf, 0x6f, 0x19, 0xba, 0x7f, 0x94, 0x27, 0xd9, 0x74, 0xee, 0x7a, + 0x9c, 0x31, 0xab, 0x9b, 0xed, 0x6e, 0x66, 0xbb, 0xeb, 0x34, 0x3d, 0x1a, + 0x3f, 0x5b, 0x2e, 0x1b, 0x74, 0x40, 0xd7, 0xa4, 0x6c, 0x13, 0xdb, 0x5d, + 0xcd, 0x76, 0x7b, 0x35, 0x91, 0xef, 0x77, 0xd6, 0xba, 0x55, 0x72, 0x2f, + 0x67, 0x1f, 0xb9, 0x76, 0xef, 0x91, 0x76, 0xcd, 0xd1, 0x7c, 0x5f, 0x47, + 0x13, 0xe8, 0x77, 0x44, 0x18, 0x63, 0x1b, 0x02, 0xfe, 0x2e, 0xc6, 0xdb, + 0x26, 0xc6, 0x8e, 0x9c, 0x4d, 0x4c, 0x8d, 0x77, 0x88, 0x9f, 0x2b, 0x23, + 0xd7, 0xa4, 0x9c, 0xd8, 0xda, 0x24, 0xf5, 0x2c, 0xf1, 0xc5, 0x47, 0xfd, + 0x0a, 0xb6, 0x38, 0x71, 0x20, 0x41, 0xfc, 0xc7, 0x37, 0x68, 0x77, 0x7e, + 0xb4, 0x64, 0x6a, 0xb1, 0x66, 0x27, 0xe3, 0xa0, 0x59, 0x45, 0x5b, 0xcf, + 0xd9, 0xdb, 0x32, 0xb6, 0x3d, 0x69, 0xb7, 0x1d, 0x57, 0x5a, 0x32, 0x75, + 0x5a, 0x15, 0x63, 0xee, 0x91, 0xb3, 0xd8, 0x39, 0x27, 0x5a, 0x1a, 0x09, + 0x34, 0xaf, 0xe7, 0x24, 0xb9, 0x19, 0xdf, 0xbe, 0x37, 0xaf, 0x87, 0x76, + 0xd1, 0x4b, 0x3b, 0xcc, 0xcd, 0x6f, 0x73, 0x66, 0x8f, 0x2a, 0x18, 0x07, + 0xb5, 0x16, 0xeb, 0x76, 0xca, 0x7f, 0x72, 0x95, 0x86, 0xc7, 0x78, 0xad, + 0x16, 0xab, 0x87, 0xbf, 0x47, 0x3b, 0xd3, 0x7d, 0x62, 0x87, 0x5d, 0x67, + 0xe5, 0x12, 0x99, 0x44, 0x36, 0x91, 0xa9, 0x8f, 0xe5, 0x66, 0x51, 0x3f, + 0x82, 0x8d, 0xd5, 0x94, 0x67, 0x2b, 0xf9, 0xd0, 0x21, 0xe5, 0xf3, 0x94, + 0x27, 0xeb, 0xf2, 0xe2, 0xa1, 0x94, 0xc8, 0xa3, 0x44, 0x67, 0x46, 0x66, + 0xe1, 0x4c, 0x2a, 0x10, 0x7f, 0x02, 0x22, 0x5b, 0x8f, 0xd2, 0x2a, 0xf5, + 0x53, 0xbd, 0xbc, 0x57, 0x90, 0x11, 0x5a, 0xa5, 0x2d, 0x5b, 0x4e, 0xa6, + 0xeb, 0x39, 0xd7, 0x2e, 0xe3, 0x6f, 0xcb, 0x51, 0xe1, 0xa4, 0xad, 0x49, + 0xdb, 0xff, 0x61, 0x45, 0xb5, 0x6e, 0x5e, 0xf3, 0x72, 0x9e, 0xdc, 0xe4, + 0x05, 0x7a, 0xf0, 0x3a, 0x87, 0xd2, 0xe2, 0x91, 0x78, 0x4d, 0xfb, 0x4c, + 0xa7, 0x9d, 0x38, 0x9e, 0x58, 0xba, 0xb4, 0xcc, 0xf8, 0x34, 0x1e, 0x1b, + 0xf1, 0x61, 0x84, 0x73, 0xfb, 0x6c, 0x42, 0xe2, 0xeb, 0x2c, 0x3c, 0x9a, + 0xf6, 0xe0, 0x99, 0x84, 0x1f, 0x8f, 0x30, 0xfe, 0x4c, 0x24, 0x0c, 0xec, + 0x4f, 0x7b, 0xf1, 0x34, 0xed, 0x79, 0x34, 0xed, 0xa3, 0xbd, 0xd4, 0x63, + 0x38, 0xdd, 0x66, 0x8f, 0xe1, 0xc9, 0xc4, 0xbf, 0xcb, 0x58, 0x83, 0x32, + 0xd6, 0xcd, 0xf6, 0x58, 0x0b, 0x71, 0x7e, 0xd6, 0xd9, 0x79, 0x38, 0x91, + 0xb0, 0x71, 0xa0, 0x77, 0x99, 0x43, 0xe6, 0x81, 0x36, 0x3b, 0x20, 0x58, + 0xa0, 0xf7, 0xc7, 0x61, 0x61, 0x8f, 0x39, 0x93, 0xfe, 0xdf, 0x4b, 0x79, + 0xa9, 0x53, 0x8e, 0x1f, 0xae, 0x8a, 0x68, 0x79, 0x24, 0x10, 0xeb, 0xa3, + 0xde, 0x9d, 0x11, 0xd1, 0x43, 0x4e, 0xef, 0x2b, 0x32, 0x87, 0x14, 0xe1, + 0x7a, 0x97, 0x0c, 0xc4, 0xad, 0x32, 0x43, 0xf4, 0x1d, 0x20, 0xce, 0x02, + 0xf3, 0xf7, 0x38, 0x39, 0xbe, 0x9b, 0x38, 0x66, 0x13, 0x45, 0x46, 0x9d, + 0x56, 0x4d, 0xd9, 0x8f, 0x7c, 0x24, 0x06, 0x8a, 0x8e, 0xfe, 0x36, 0x3f, + 0x5f, 0xba, 0x83, 0xf2, 0xfa, 0x81, 0xc2, 0xbc, 0x58, 0xd6, 0x0e, 0xb3, + 0x30, 0x37, 0x35, 0xf0, 0x57, 0xeb, 0xf1, 0x21, 0x5a, 0xc4, 0x48, 0x62, + 0x1a, 0xe2, 0x9a, 0x9a, 0x6f, 0x3b, 0xaa, 0x14, 0x31, 0xff, 0xc0, 0xb8, + 0xf8, 0x7e, 0x39, 0xa2, 0x4e, 0xa9, 0x8f, 0x68, 0x51, 0x24, 0x10, 0x9c, + 0xab, 0x4e, 0xb5, 0x19, 0xc1, 0x01, 0xe9, 0x2b, 0x4e, 0x59, 0xcf, 0xc7, + 0x82, 0x91, 0x44, 0x01, 0x37, 0xfe, 0x3b, 0xf5, 0x2e, 0xd4, 0xa9, 0xc8, + 0x29, 0x7a, 0x55, 0x71, 0x74, 0x50, 0xf4, 0xe7, 0xc4, 0x4a, 0x73, 0x7a, + 0x5e, 0xe6, 0x59, 0x9c, 0x17, 0x62, 0x0e, 0xe7, 0xeb, 0x85, 0x7e, 0x2f, + 0xe5, 0xb6, 0x90, 0x0e, 0x5d, 0x8c, 0x4d, 0x36, 0xe7, 0x5c, 0x95, 0xcf, + 0x5b, 0x38, 0x4f, 0xea, 0x76, 0xea, 0xfa, 0xb3, 0x8e, 0xdc, 0x79, 0x9d, + 0xef, 0xa3, 0xfa, 0xd2, 0xb5, 0x18, 0x0a, 0x3a, 0x03, 0x86, 0xd2, 0x88, + 0xb9, 0x23, 0xf5, 0x4d, 0xce, 0xbe, 0xb6, 0x0d, 0xf4, 0xef, 0x7b, 0x4f, + 0x35, 0x7c, 0x16, 0x9b, 0xa9, 0x17, 0xa7, 0x6d, 0x67, 0x51, 0xc5, 0x65, + 0x2c, 0xb1, 0xfd, 0x49, 0x1d, 0x5f, 0x91, 0xef, 0x23, 0x6a, 0xe7, 0x2c, + 0x50, 0x5b, 0xf2, 0xe7, 0x77, 0x53, 0xdf, 0x32, 0x0e, 0x15, 0x3f, 0x20, + 0x97, 0x7d, 0x27, 0xf4, 0x59, 0x64, 0x6d, 0xcc, 0x76, 0xd2, 0xdf, 0xaf, + 0x62, 0x5d, 0xe2, 0xdf, 0xb8, 0xc4, 0x52, 0xc4, 0x4b, 0xe8, 0xd7, 0x45, + 0xf4, 0xd5, 0x6b, 0x32, 0xf7, 0xa0, 0x3d, 0x15, 0x08, 0x97, 0x28, 0xf7, + 0xe0, 0xd6, 0x8c, 0x0b, 0xb1, 0x61, 0x0f, 0xd6, 0x51, 0x27, 0xce, 0xa4, + 0xf8, 0xb9, 0x86, 0x75, 0xa3, 0x47, 0x67, 0x3a, 0xe9, 0x37, 0xeb, 0x46, + 0xbd, 0x3c, 0xa6, 0xf3, 0x70, 0x63, 0x35, 0x8f, 0x3d, 0xb4, 0xcb, 0x36, + 0xc6, 0x86, 0x23, 0x09, 0x13, 0x9d, 0xd4, 0xd5, 0x13, 0x89, 0x06, 0xdc, + 0x4b, 0xbd, 0x1d, 0x4a, 0x7c, 0x8a, 0x3a, 0x0a, 0xa3, 0x83, 0x73, 0xfc, + 0x58, 0x42, 0xb5, 0xf3, 0xab, 0xdb, 0x33, 0xff, 0x62, 0x45, 0xa7, 0x8b, + 0x9c, 0xa2, 0x0b, 0x99, 0xcf, 0x8f, 0xe8, 0x81, 0xfe, 0x3b, 0x55, 0x17, + 0xf5, 0xd8, 0xb6, 0xcb, 0xc0, 0xf6, 0x5d, 0x75, 0xb4, 0xbb, 0x8c, 0xe5, + 0xaf, 0x1a, 0xa0, 0x0e, 0xa6, 0xea, 0xe1, 0x08, 0x79, 0x81, 0xe8, 0x41, + 0xda, 0xbc, 0x8f, 0x63, 0xee, 0xe6, 0x3d, 0x1f, 0x1e, 0x4f, 0x7c, 0x97, + 0xbf, 0xc3, 0xca, 0x5d, 0x19, 0xf1, 0x79, 0xf1, 0xb7, 0x7f, 0x70, 0xe4, + 0x62, 0x6f, 0xa1, 0xdc, 0x16, 0x96, 0xb3, 0xac, 0xcd, 0x67, 0xe3, 0x4a, + 0x51, 0xb4, 0x84, 0x71, 0x65, 0x7f, 0x22, 0x10, 0x7e, 0xc6, 0x8e, 0x7d, + 0x4e, 0xda, 0x8e, 0xd8, 0x47, 0x8f, 0x6d, 0x1b, 0xcb, 0xce, 0xda, 0xc6, + 0xe4, 0x59, 0x0e, 0xd5, 0x9f, 0x9a, 0xea, 0x73, 0x39, 0xbb, 0x70, 0x26, + 0xf5, 0x5e, 0xdb, 0x8e, 0xd3, 0x82, 0x8f, 0x0e, 0x38, 0x06, 0x9c, 0x68, + 0x33, 0x2f, 0xa5, 0xbe, 0xab, 0x19, 0x6f, 0x8a, 0x78, 0x30, 0x4f, 0x1d, + 0xfe, 0x0b, 0x94, 0x0e, 0x64, 0xad, 0x12, 0xfe, 0x6e, 0x0e, 0x89, 0xbe, + 0xaf, 0xc2, 0xad, 0xc3, 0x0e, 0x14, 0x0d, 0x28, 0x78, 0xd2, 0xac, 0xc7, + 0x90, 0x37, 0x87, 0xbb, 0x6a, 0xf2, 0x52, 0x7b, 0x9e, 0x2e, 0x1e, 0x3f, + 0xfa, 0x8c, 0xc4, 0x85, 0x7b, 0x47, 0x3d, 0xf0, 0x25, 0x15, 0x78, 0x88, + 0x2b, 0x65, 0x46, 0x3d, 0xf5, 0xaa, 0xa1, 0x32, 0x69, 0xe2, 0x6b, 0x19, + 0xd2, 0xa6, 0x07, 0xc2, 0xb8, 0x93, 0xf3, 0x52, 0xfe, 0xc0, 0x95, 0xb8, + 0x83, 0xe5, 0x36, 0xf0, 0xde, 0x86, 0xd1, 0x6a, 0x1e, 0x5e, 0x1e, 0xd3, + 0x79, 0x34, 0xe0, 0xf6, 0xe1, 0x5a, 0x44, 0xab, 0xf5, 0xa0, 0x5f, 0x75, + 0xa0, 0x7a, 0x40, 0xf4, 0xae, 0x62, 0xe5, 0x02, 0x05, 0xe6, 0xa7, 0x8b, + 0xa1, 0xce, 0xfd, 0x38, 0xdf, 0xfd, 0x53, 0xb2, 0xbe, 0x6c, 0x0d, 0xd9, + 0x98, 0x2e, 0x3a, 0x16, 0x3b, 0xf9, 0x57, 0xce, 0x85, 0xc8, 0x2b, 0x7d, + 0x48, 0xac, 0x15, 0x1d, 0x7f, 0x12, 0x36, 0x30, 0xb2, 0x54, 0x74, 0xb1, + 0xcc, 0x47, 0x7d, 0x01, 0x67, 0xe7, 0x7f, 0x2a, 0x67, 0x95, 0xb8, 0xaf, + 0x87, 0x87, 0x6c, 0x8e, 0xe3, 0x67, 0xbe, 0xa8, 0xc7, 0x45, 0xe7, 0xe4, + 0x34, 0x6e, 0xd5, 0x80, 0xbf, 0xc8, 0xb8, 0x19, 0xb7, 0x71, 0x9e, 0xf6, + 0x26, 0xd4, 0xa5, 0x2e, 0xa8, 0xb3, 0x5c, 0x4c, 0x9c, 0x47, 0x4c, 0x1d, + 0xed, 0xc3, 0xcc, 0xb5, 0x86, 0xcb, 0xd1, 0xa5, 0x29, 0xee, 0x6d, 0xf5, + 0x8b, 0x24, 0xa7, 0xf6, 0x57, 0x1a, 0x50, 0xcb, 0x18, 0xff, 0xb7, 0x6b, + 0x70, 0x16, 0x19, 0x8a, 0x9a, 0xa8, 0x6f, 0x42, 0xbc, 0x0a, 0xce, 0x0a, + 0x03, 0x0a, 0x73, 0x66, 0xf4, 0x69, 0x10, 0xec, 0x89, 0x16, 0x19, 0xf7, + 0xe0, 0xb6, 0x14, 0xac, 0xd2, 0x08, 0xf3, 0xa1, 0x88, 0x41, 0x8e, 0x1b, + 0xf0, 0x15, 0xd1, 0x3f, 0x56, 0x93, 0x57, 0xac, 0x1d, 0x16, 0x39, 0x3c, + 0xe4, 0x1b, 0x86, 0xbf, 0x0d, 0xcc, 0xe1, 0x5b, 0xf4, 0xe0, 0x24, 0xf3, + 0xd8, 0xd5, 0xd4, 0xfd, 0x48, 0xe2, 0x1e, 0x34, 0xa6, 0x8e, 0x58, 0x1e, + 0xf2, 0xc8, 0x22, 0xa3, 0xf6, 0x4c, 0x17, 0x62, 0xf4, 0x0d, 0xe1, 0x47, + 0x6b, 0xe8, 0x1b, 0x3e, 0x64, 0x12, 0xea, 0x71, 0xb2, 0x0b, 0x74, 0x8c, + 0xae, 0xc7, 0xd7, 0x46, 0x67, 0x61, 0x3c, 0xb1, 0x01, 0x77, 0x66, 0xc8, + 0x95, 0xfa, 0xaf, 0xc2, 0x1d, 0xc3, 0x57, 0xe1, 0xf6, 0x9d, 0x46, 0x70, + 0x03, 0x75, 0xbd, 0x76, 0x98, 0x81, 0x72, 0xba, 0xb4, 0x5b, 0xd0, 0x95, + 0xf0, 0x45, 0xea, 0x22, 0xaf, 0xa7, 0x2c, 0x0a, 0x1c, 0xe6, 0x5f, 0x2d, + 0x5e, 0x8a, 0x17, 0x35, 0x28, 0xfe, 0xdd, 0xf5, 0x2f, 0x31, 0xb7, 0x17, + 0xd9, 0x11, 0x9d, 0x69, 0xfc, 0xc0, 0x7a, 0x50, 0xa3, 0x7f, 0x47, 0x10, + 0x9f, 0xd3, 0xf0, 0xbc, 0xf5, 0xd0, 0x2a, 0xb9, 0x7e, 0x9b, 0x13, 0xa5, + 0x2a, 0xaf, 0x49, 0x9b, 0x82, 0x4b, 0x75, 0x44, 0xe2, 0x8f, 0x6b, 0x33, + 0x6b, 0x25, 0xcf, 0x96, 0x27, 0x2f, 0x24, 0x16, 0x3f, 0x91, 0xf0, 0xa2, + 0x37, 0x95, 0xe3, 0x56, 0x37, 0x65, 0x84, 0x53, 0xb9, 0x51, 0xda, 0x27, + 0x71, 0x25, 0x8a, 0xf5, 0xfc, 0x5d, 0xd2, 0xa7, 0xb7, 0xc4, 0x91, 0x60, + 0x9b, 0x4d, 0x9c, 0x0b, 0xda, 0x6b, 0x9f, 0x03, 0x25, 0x46, 0x73, 0xce, + 0x56, 0xfb, 0x56, 0xd0, 0x56, 0x35, 0x54, 0xf4, 0xf5, 0x70, 0xac, 0xb4, + 0x55, 0xd6, 0xbb, 0x83, 0xba, 0xf0, 0xf4, 0xad, 0xa2, 0xbd, 0xce, 0x42, + 0x59, 0x5f, 0x2b, 0xf1, 0x01, 0x8c, 0xeb, 0x16, 0x8e, 0x9a, 0x95, 0x79, + 0x7e, 0xda, 0x8c, 0x5b, 0x53, 0x51, 0xb4, 0xa5, 0x6a, 0xa3, 0x27, 0x65, + 0xad, 0xca, 0x95, 0xc3, 0xb0, 0x68, 0x8d, 0xe8, 0x62, 0x32, 0x8f, 0xa7, + 0x7a, 0x73, 0x8e, 0xd3, 0xe9, 0x9a, 0x5f, 0x29, 0xc8, 0xde, 0x83, 0x18, + 0xf3, 0x8f, 0x39, 0x91, 0x16, 0x58, 0x29, 0x91, 0x3b, 0x6e, 0xf9, 0x98, + 0x53, 0x7a, 0x22, 0xfa, 0xc6, 0xc5, 0x0e, 0xa3, 0xe3, 0x15, 0x25, 0x88, + 0xeb, 0x29, 0x43, 0x59, 0x5f, 0x27, 0x5e, 0x08, 0xe9, 0xbe, 0xef, 0x2a, + 0xfa, 0x99, 0x0d, 0x78, 0x05, 0x3f, 0xe3, 0xb5, 0xa2, 0xbe, 0x09, 0x3c, + 0x94, 0x79, 0x15, 0xa7, 0x28, 0xab, 0xda, 0xf7, 0xa1, 0xb5, 0xcc, 0x78, + 0x86, 0xe3, 0x77, 0x2b, 0x6f, 0x65, 0xa6, 0xda, 0xe2, 0x55, 0x58, 0xbd, + 0x53, 0xec, 0x4f, 0x0f, 0xc6, 0x89, 0xbd, 0x6d, 0x66, 0x85, 0x70, 0x79, + 0x89, 0x4f, 0x94, 0xbf, 0x45, 0xb0, 0x85, 0xfe, 0x41, 0x3b, 0xb0, 0xc7, + 0xd0, 0x6a, 0x63, 0xb2, 0x33, 0x09, 0x1b, 0x4b, 0x73, 0x7a, 0x8e, 0x28, + 0x6d, 0xa3, 0xbe, 0x52, 0x94, 0xfa, 0xf2, 0x7e, 0x90, 0x5b, 0xb3, 0x38, + 0x57, 0xf7, 0x3f, 0xad, 0x11, 0xef, 0xf9, 0x75, 0x2b, 0x98, 0x83, 0x55, + 0x72, 0x3c, 0xef, 0xf6, 0xc5, 0xad, 0xd2, 0xdc, 0x58, 0x9a, 0x7f, 0xa0, + 0x88, 0x4d, 0x06, 0xc9, 0xed, 0x3b, 0x71, 0x69, 0x48, 0x6f, 0xfd, 0xae, + 0x22, 0x65, 0xf5, 0xf0, 0x06, 0xa5, 0xd0, 0xcf, 0xcb, 0x38, 0x39, 0x22, + 0x7d, 0x48, 0x5f, 0x13, 0xcc, 0xc9, 0x72, 0x63, 0x10, 0x5f, 0x7a, 0xc4, + 0x9e, 0x4b, 0xf1, 0x27, 0x3f, 0x96, 0x73, 0x4c, 0xae, 0x3e, 0x1f, 0x0f, + 0x17, 0xed, 0xd5, 0x87, 0xb5, 0x99, 0x15, 0x58, 0xcd, 0xbc, 0x76, 0x75, + 0xa6, 0x85, 0xba, 0xdf, 0x48, 0x7c, 0x67, 0x46, 0xa0, 0xe5, 0x74, 0x7c, + 0xce, 0x3e, 0x74, 0xff, 0x24, 0x56, 0xf0, 0xfe, 0xcf, 0x9d, 0xa8, 0x68, + 0x61, 0x79, 0xfb, 0xbe, 0x29, 0xf8, 0x7d, 0xae, 0xcc, 0x47, 0x78, 0x98, + 0x1d, 0xe7, 0xf7, 0xda, 0x1c, 0xb1, 0xc5, 0xce, 0xbd, 0xae, 0xb6, 0xe7, + 0x5c, 0x38, 0x82, 0x85, 0x63, 0x66, 0x31, 0xf3, 0xaf, 0xba, 0xe0, 0xf9, + 0x9c, 0x50, 0x67, 0x16, 0x5a, 0xc0, 0x03, 0xe9, 0x4b, 0xf4, 0x72, 0xa2, + 0x26, 0xa7, 0x97, 0x4f, 0x2a, 0x7b, 0x3e, 0x76, 0xec, 0x49, 0x48, 0xdf, + 0x45, 0x36, 0x2f, 0x6d, 0xcc, 0x94, 0x22, 0xee, 0x15, 0x1d, 0x49, 0x7b, + 0xba, 0x5f, 0x64, 0x5a, 0xbb, 0x53, 0xec, 0xd8, 0xc2, 0x08, 0x65, 0xe8, + 0xb6, 0xe7, 0x2d, 0xc7, 0x25, 0x8f, 0x9c, 0x17, 0x9f, 0x65, 0x4c, 0x85, + 0xbe, 0x6f, 0x73, 0xe5, 0xf8, 0x66, 0x81, 0x2b, 0x58, 0xd6, 0x80, 0x59, + 0xe0, 0x0a, 0x32, 0xe6, 0xbf, 0x00, 0x63, 0x9d, 0x3d, 0xde, 0x35, 0xf9, + 0xb6, 0xbb, 0xcc, 0x00, 0xed, 0x5a, 0xb8, 0x54, 0x44, 0x59, 0xb3, 0x2b, + 0xc3, 0xb9, 0x95, 0xdc, 0x06, 0xb8, 0x93, 0xf7, 0xcb, 0x79, 0xff, 0xc5, + 0x90, 0x0b, 0x97, 0x4e, 0x97, 0xbe, 0xaf, 0x42, 0xc7, 0xce, 0x28, 0x2a, + 0x17, 0x06, 0x30, 0x69, 0x73, 0x89, 0x02, 0xef, 0x75, 0xe1, 0x8e, 0x9d, + 0x1f, 0x5a, 0x15, 0x36, 0x17, 0x33, 0x62, 0xe3, 0x8a, 0x8a, 0xed, 0x8b, + 0x84, 0xff, 0xba, 0x88, 0xef, 0xe4, 0xa2, 0xc2, 0xad, 0x5d, 0x65, 0xe4, + 0xb0, 0xc2, 0xe1, 0x02, 0xd9, 0x9b, 0x54, 0x68, 0x5a, 0x44, 0xb8, 0xdc, + 0x2c, 0x9b, 0xc3, 0x0a, 0x97, 0xfd, 0x56, 0xea, 0xd0, 0x14, 0x2e, 0x7b, + 0x96, 0x73, 0x30, 0xf7, 0x69, 0x61, 0x7e, 0xef, 0x81, 0x3b, 0xa2, 0xb7, + 0x6c, 0x52, 0x3a, 0xb1, 0x3c, 0x64, 0x98, 0x92, 0x53, 0x5f, 0xa9, 0xe8, + 0xc1, 0xd3, 0x08, 0x12, 0x6f, 0x5f, 0xc6, 0xc8, 0x60, 0xdc, 0x25, 0x76, + 0xb4, 0x29, 0x73, 0x4e, 0x9e, 0x5b, 0x29, 0x8f, 0x3b, 0x27, 0x8f, 0x79, + 0x1a, 0x2a, 0x9e, 0x6c, 0x70, 0x11, 0xb7, 0xfe, 0x0e, 0x6d, 0x3b, 0x55, + 0x2c, 0xb1, 0xb9, 0xf9, 0xdf, 0x11, 0x7f, 0x2f, 0x2a, 0xcd, 0x95, 0x07, + 0x3a, 0xe9, 0xdf, 0xef, 0x2f, 0x2c, 0x41, 0x68, 0x9a, 0x82, 0x2a, 0xa3, + 0x83, 0xf9, 0xf1, 0x87, 0x56, 0xdc, 0x49, 0x3a, 0x6b, 0x40, 0x2b, 0x89, + 0x44, 0x29, 0x5b, 0x93, 0x72, 0xcd, 0xf0, 0x20, 0xfb, 0xe9, 0x20, 0xef, + 0xf7, 0xe0, 0x2e, 0xda, 0xce, 0x5d, 0x8c, 0x65, 0x77, 0x31, 0x96, 0xdd, + 0x35, 0xfa, 0x2f, 0xbc, 0x3e, 0xdd, 0xfe, 0xbd, 0x29, 0x55, 0xb0, 0x65, + 0x27, 0xe3, 0x82, 0xe8, 0x77, 0x33, 0x7d, 0x47, 0xe2, 0x02, 0x28, 0x93, + 0x85, 0x93, 0x9c, 0xc7, 0x25, 0x9a, 0x1e, 0xcc, 0xe2, 0xeb, 0xae, 0x73, + 0x79, 0x5f, 0x21, 0xb6, 0xc8, 0x3c, 0xba, 0x70, 0x1b, 0x65, 0x0c, 0x86, + 0xfe, 0xcb, 0x42, 0x95, 0xf8, 0xee, 0x85, 0xf7, 0x73, 0xf3, 0x7a, 0xe4, + 0x2c, 0x07, 0x54, 0xc4, 0x4e, 0xe9, 0xf3, 0x7b, 0x6c, 0x4e, 0xf1, 0xa2, + 0xc9, 0xdc, 0x6d, 0xe7, 0xd1, 0xf9, 0x62, 0x2a, 0x6b, 0x47, 0xa3, 0xe8, + 0xe6, 0xb8, 0x57, 0x0f, 0x3f, 0x96, 0xd7, 0x4b, 0x61, 0xbc, 0x0a, 0xd5, + 0xe2, 0xa1, 0xff, 0xe4, 0x72, 0x95, 0xb6, 0x51, 0xe1, 0xb6, 0xd5, 0xfc, + 0x2f, 0xdc, 0xd6, 0xcb, 0xff, 0xc2, 0x73, 0xa7, 0xf3, 0xbf, 0x13, 0xfe, + 0xe9, 0x62, 0xc7, 0xf5, 0xe8, 0xdd, 0x65, 0x59, 0xc5, 0x81, 0x7a, 0x6c, + 0x19, 0xfd, 0x48, 0xbc, 0xbc, 0x40, 0x1e, 0x7b, 0x0e, 0xe8, 0x47, 0x2e, + 0xc1, 0x22, 0xbf, 0x5f, 0x95, 0xbe, 0x2d, 0x6c, 0x34, 0xaf, 0x62, 0x9f, + 0x8c, 0x80, 0xd5, 0x53, 0xfd, 0xa2, 0xd0, 0x46, 0x41, 0xdf, 0xc5, 0xf4, + 0x73, 0x68, 0x2e, 0xea, 0x7b, 0x65, 0x46, 0xea, 0x36, 0x29, 0x4b, 0x87, + 0xa7, 0x96, 0xef, 0x20, 0x1f, 0x3e, 0x4d, 0x5d, 0x17, 0xfc, 0xc8, 0x9b, + 0xcf, 0x2b, 0x98, 0x4b, 0xa4, 0x44, 0x97, 0x32, 0xbe, 0x5c, 0xae, 0x28, + 0xb6, 0x74, 0xe4, 0x6c, 0x1f, 0xa2, 0xb7, 0xf8, 0xf4, 0x12, 0x43, 0xec, + 0x28, 0x48, 0x5c, 0xd1, 0xc3, 0xcd, 0x84, 0xed, 0x53, 0x09, 0xc4, 0x1c, + 0x91, 0xe6, 0xa6, 0xb5, 0x89, 0xb9, 0xda, 0xf1, 0x7c, 0x2e, 0xba, 0x87, + 0x38, 0xae, 0x1a, 0xb2, 0x0e, 0x42, 0x5b, 0x19, 0x16, 0xdd, 0x75, 0x28, + 0xe7, 0xf2, 0xce, 0x28, 0x79, 0x97, 0x6a, 0xcb, 0xe8, 0x8c, 0x88, 0x6c, + 0x52, 0x87, 0xb2, 0x5f, 0xc0, 0xbf, 0x72, 0xba, 0xa8, 0x80, 0x67, 0x40, + 0x78, 0x97, 0x8e, 0x0d, 0x8c, 0xf3, 0x65, 0x03, 0x7e, 0xfa, 0x42, 0x35, + 0x4a, 0x1f, 0x88, 0x60, 0xfd, 0xa8, 0x86, 0x92, 0x07, 0x2c, 0x6b, 0x6e, + 0xa8, 0x87, 0x5c, 0xf6, 0xb2, 0x22, 0xc9, 0x9d, 0x9c, 0x49, 0x62, 0x16, + 0xf1, 0xad, 0x3d, 0xa5, 0xe0, 0x6a, 0xc6, 0xd3, 0x28, 0x71, 0xa8, 0xdd, + 0xc6, 0x39, 0xab, 0x73, 0x4e, 0xc4, 0x45, 0x1b, 0x5a, 0xc5, 0xfb, 0xad, + 0xc4, 0xc0, 0x56, 0x62, 0x9a, 0x65, 0xbd, 0x7f, 0x39, 0x3a, 0xcb, 0x22, + 0x37, 0x13, 0x0b, 0x6b, 0xc9, 0x89, 0x25, 0x7e, 0x5f, 0x8e, 0x35, 0x8c, + 0xfd, 0xc5, 0x49, 0x3b, 0x9f, 0xa2, 0xee, 0x18, 0xa3, 0x32, 0x8c, 0x71, + 0x94, 0xfd, 0x69, 0x72, 0x5c, 0xe1, 0xbb, 0x95, 0xc9, 0x0d, 0x8c, 0x75, + 0x1e, 0x54, 0x0c, 0x5c, 0x86, 0x3b, 0x19, 0xcf, 0xef, 0xd8, 0xe9, 0x47, + 0x7a, 0xd1, 0x55, 0x94, 0xef, 0x1e, 0xac, 0x4f, 0x19, 0x92, 0x43, 0x45, + 0x83, 0x8b, 0xc8, 0xb7, 0x33, 0x82, 0x3b, 0x92, 0x8f, 0x95, 0x61, 0x49, + 0x0b, 0x10, 0x4c, 0x16, 0xf0, 0x2d, 0x2a, 0x6b, 0x47, 0x30, 0x92, 0xe7, + 0x63, 0xdb, 0x39, 0x5e, 0x24, 0xeb, 0x70, 0x2d, 0x98, 0xcf, 0x58, 0x20, + 0xf6, 0xa5, 0x31, 0xc7, 0x2c, 0x51, 0x0c, 0xdf, 0x1e, 0xfa, 0xa9, 0xe4, + 0x3d, 0x57, 0x24, 0x0b, 0xb1, 0x4f, 0xcf, 0x2e, 0x76, 0x74, 0x12, 0x47, + 0xf4, 0x8d, 0xbf, 0x53, 0xf4, 0xf6, 0x13, 0xca, 0x2b, 0xd8, 0x37, 0xf6, + 0x2a, 0x86, 0xc6, 0xdc, 0xca, 0xe8, 0x98, 0xf4, 0x35, 0x81, 0xbe, 0xcc, + 0x9f, 0xea, 0x6b, 0xea, 0xfa, 0xcb, 0xa2, 0xf3, 0xd6, 0x6c, 0xae, 0xce, + 0xe7, 0x89, 0x4b, 0xcf, 0xe3, 0xc7, 0x32, 0x27, 0x62, 0x97, 0x5e, 0xf4, + 0xa4, 0xce, 0xad, 0x0b, 0xf4, 0x27, 0xb6, 0xd9, 0xfe, 0xd9, 0x92, 0x11, + 0x7b, 0x55, 0x19, 0x33, 0x2f, 0xce, 0xe7, 0x2c, 0xb5, 0xd4, 0x41, 0x9f, + 0x7d, 0x6f, 0x9f, 0xf9, 0x29, 0x64, 0xed, 0x6b, 0x8b, 0xe9, 0x9b, 0xd5, + 0x28, 0x26, 0x26, 0x06, 0x43, 0x3e, 0x14, 0x57, 0xc9, 0x3a, 0xce, 0xb9, + 0xdc, 0x7f, 0xc3, 0x4e, 0x86, 0x64, 0x1b, 0x73, 0x1a, 0x89, 0x7f, 0xb5, + 0x9c, 0xef, 0x1c, 0xce, 0xac, 0xa7, 0x0d, 0x5d, 0x27, 0x36, 0xe4, 0xca, + 0xd9, 0xd0, 0x47, 0xd7, 0x17, 0x54, 0x90, 0xfb, 0x69, 0x15, 0x76, 0xde, + 0xd7, 0xa4, 0x5c, 0x9f, 0xb7, 0xab, 0xcf, 0x67, 0x1e, 0x2d, 0xca, 0xe7, + 0x66, 0x17, 0x94, 0xff, 0x38, 0x1d, 0x5c, 0xf6, 0x67, 0xe8, 0x40, 0xe2, + 0x81, 0xe4, 0x04, 0xa2, 0x83, 0xf3, 0xf3, 0xf2, 0xfe, 0x44, 0x35, 0x71, + 0xef, 0x42, 0x5d, 0xcc, 0xcc, 0xeb, 0x62, 0x31, 0xb1, 0x4b, 0xfe, 0x5b, + 0x38, 0x65, 0x7a, 0xf1, 0xa2, 0x26, 0xe3, 0x5e, 0x8c, 0xf5, 0x1c, 0xaf, + 0x9b, 0xba, 0x58, 0x1e, 0xaa, 0x44, 0xf0, 0xbc, 0x78, 0x50, 0xcb, 0xd8, + 0xf1, 0x21, 0x79, 0xa6, 0xfc, 0xf6, 0xe3, 0x05, 0xea, 0xe2, 0x8e, 0xe1, + 0xc5, 0xb8, 0x8b, 0xfe, 0x94, 0xe3, 0x90, 0xb9, 0xd8, 0xb0, 0x76, 0x58, + 0xda, 0x14, 0x8c, 0xfb, 0xd9, 0xd9, 0x71, 0xfe, 0x71, 0x5e, 0xfe, 0x0a, + 0xe5, 0x97, 0x67, 0x07, 0xb2, 0x16, 0x2d, 0xcf, 0x11, 0x64, 0x2c, 0xc6, + 0x14, 0xdc, 0xb1, 0xac, 0x83, 0xe6, 0x3c, 0xc4, 0xaa, 0xf5, 0x7e, 0x89, + 0x8f, 0xfd, 0xc4, 0x03, 0x07, 0xf3, 0xc8, 0xa2, 0x48, 0x94, 0xfe, 0xac, + 0x5e, 0xe5, 0x80, 0x5a, 0xef, 0x40, 0x27, 0xde, 0x30, 0x8d, 0xde, 0x75, + 0xf8, 0x14, 0xba, 0xbc, 0x16, 0xf6, 0xb2, 0x9d, 0xee, 0x54, 0x09, 0xda, + 0xeb, 0x69, 0x56, 0x2b, 0x3d, 0xd8, 0x91, 0x8a, 0xb7, 0x12, 0x16, 0x18, + 0x73, 0x1a, 0xfe, 0x2a, 0x11, 0xd0, 0x5b, 0x36, 0x90, 0xb7, 0x2c, 0xef, + 0x73, 0xc3, 0xaf, 0xe4, 0x72, 0xb4, 0x01, 0x55, 0xd6, 0x09, 0x23, 0x94, + 0xbd, 0xc7, 0xce, 0xf7, 0xfc, 0xd3, 0xa5, 0x1f, 0x3f, 0xe2, 0x19, 0xa9, + 0xeb, 0x47, 0xe9, 0x5c, 0x05, 0xcb, 0xe7, 0xea, 0xf1, 0xa8, 0x62, 0x59, + 0x0b, 0x42, 0x4e, 0xfb, 0xfe, 0xb6, 0x4c, 0x5d, 0xeb, 0x0d, 0xea, 0xab, + 0x56, 0x6e, 0x6d, 0x52, 0xd7, 0xa2, 0x4c, 0x0a, 0x8e, 0xfc, 0xd1, 0xf5, + 0xf9, 0x20, 0xe4, 0xb9, 0x89, 0xdb, 0x58, 0x89, 0xfd, 0xf9, 0xf5, 0x39, + 0x57, 0xe4, 0xbd, 0x2f, 0xef, 0x35, 0x24, 0x6f, 0x11, 0x9d, 0x4b, 0x7f, + 0x62, 0x0b, 0xd7, 0x15, 0x0b, 0x06, 0x76, 0x65, 0x16, 0xd2, 0x16, 0x7f, + 0x6b, 0x8d, 0x7a, 0xa7, 0x96, 0xbd, 0x51, 0xcd, 0xad, 0xb7, 0x4b, 0xd9, + 0x42, 0xb9, 0x8b, 0x89, 0x09, 0x8d, 0x18, 0x3e, 0xaf, 0x4d, 0xc9, 0x75, + 0x0b, 0x6d, 0xde, 0xc6, 0x72, 0xd2, 0xae, 0xe0, 0xef, 0x7f, 0x59, 0xfb, + 0xce, 0x6b, 0xaf, 0xd5, 0x95, 0x6b, 0xef, 0xee, 0x62, 0xc9, 0xdd, 0xfb, + 0x53, 0x45, 0xac, 0xf3, 0x4e, 0x9e, 0x07, 0x16, 0xca, 0x7c, 0xea, 0x82, + 0x32, 0xc4, 0x79, 0xe3, 0x4d, 0x6b, 0xcf, 0x79, 0x65, 0x96, 0x3b, 0xcf, + 0x2f, 0xe3, 0xc4, 0x1c, 0xe3, 0x55, 0xeb, 0xc8, 0x79, 0x65, 0xd2, 0x17, + 0x94, 0xb9, 0x1c, 0x63, 0xf5, 0x8f, 0x58, 0x43, 0xb9, 0xb9, 0xc9, 0xd2, + 0x7d, 0xdc, 0x33, 0x23, 0xad, 0x7f, 0x75, 0xc5, 0x3c, 0xbd, 0x63, 0xa6, + 0x43, 0x9e, 0xd9, 0xb8, 0x91, 0xcd, 0xcd, 0x4d, 0x5c, 0xe6, 0xc6, 0xb5, + 0xa0, 0x30, 0x37, 0xd7, 0xe5, 0xeb, 0x17, 0xda, 0xbd, 0xae, 0xe8, 0xfc, + 0x76, 0x0b, 0xd7, 0xaf, 0xb8, 0x40, 0xee, 0xef, 0x5c, 0x50, 0xee, 0xb7, + 0x7f, 0xa4, 0xde, 0x2f, 0x1c, 0xe7, 0x5f, 0x3f, 0xa0, 0x9e, 0x7f, 0xde, + 0x9c, 0x3f, 0x2f, 0xe8, 0xbf, 0xea, 0x82, 0xf2, 0x35, 0x17, 0x94, 0x7f, + 0x59, 0xfd, 0xf8, 0x7e, 0xd6, 0x5d, 0x50, 0xcf, 0x5e, 0xab, 0xc6, 0x53, + 0x67, 0x7d, 0x1e, 0x4d, 0x45, 0x08, 0x98, 0x4e, 0x05, 0x7e, 0xfa, 0xbe, + 0xff, 0xe9, 0x0b, 0xd6, 0xac, 0x9b, 0xce, 0xfa, 0xfe, 0x79, 0x9c, 0x33, + 0x56, 0x1c, 0x91, 0x18, 0x56, 0x44, 0xee, 0x2c, 0x3c, 0xb0, 0x4e, 0x3b, + 0x97, 0x67, 0x15, 0x62, 0x65, 0x45, 0xac, 0x24, 0xd2, 0x00, 0xff, 0xd8, + 0x2c, 0xff, 0x9b, 0x09, 0x59, 0xb7, 0xfc, 0x80, 0x5c, 0xca, 0xf0, 0xed, + 0xc7, 0x2c, 0xff, 0x4f, 0xd3, 0x6f, 0x15, 0xa3, 0xc2, 0x83, 0xab, 0x13, + 0x1f, 0x5f, 0x4f, 0x8d, 0x40, 0x59, 0xd6, 0xe0, 0x63, 0x7e, 0x05, 0xe7, + 0x35, 0xf3, 0x30, 0xe5, 0xaf, 0x45, 0xf2, 0x3d, 0xf5, 0x58, 0x43, 0x98, + 0xf1, 0x39, 0xf7, 0xbc, 0x76, 0x49, 0x46, 0xf7, 0x45, 0x95, 0xdc, 0x33, + 0xd9, 0xf6, 0xd0, 0x1f, 0xc8, 0x77, 0x3a, 0x29, 0x97, 0xc5, 0xbe, 0x80, + 0x0d, 0x09, 0xcb, 0x7a, 0x8a, 0x79, 0xaa, 0x3c, 0xeb, 0xff, 0x79, 0xfa, + 0xf7, 0xd6, 0x84, 0xd7, 0x89, 0xb7, 0x8c, 0xa9, 0xed, 0xf9, 0x51, 0x19, + 0x31, 0x99, 0x2f, 0xd9, 0x27, 0xea, 0x98, 0x51, 0xb7, 0x71, 0x2f, 0xfd, + 0x6e, 0x7e, 0x40, 0xf7, 0x27, 0xf1, 0xef, 0x96, 0xbf, 0x46, 0x0f, 0x0e, + 0x29, 0x85, 0x75, 0xe2, 0x0b, 0xd7, 0x83, 0x2b, 0x62, 0x2e, 0x8e, 0x6f, + 0x8f, 0xcd, 0xf7, 0x8b, 0x88, 0x71, 0x88, 0x39, 0x23, 0xb3, 0xfc, 0x5b, + 0x12, 0xf6, 0x38, 0xc9, 0x17, 0x15, 0x1c, 0x6b, 0x98, 0xe5, 0xef, 0x4e, + 0x7b, 0xb1, 0x9d, 0xf1, 0xb8, 0xc4, 0x68, 0xc0, 0x23, 0x69, 0x15, 0xb7, + 0xdd, 0xef, 0xc5, 0x5a, 0x72, 0xd1, 0x8d, 0x7d, 0xdf, 0x80, 0x71, 0xa9, + 0x13, 0xb7, 0xd2, 0xfe, 0xd6, 0xf5, 0x15, 0xdb, 0x39, 0xc8, 0xfa, 0x3e, + 0x27, 0xea, 0x2f, 0xad, 0x40, 0xbc, 0xa6, 0x18, 0xdf, 0x37, 0x1d, 0xcc, + 0x7b, 0xca, 0x30, 0x64, 0x63, 0xa2, 0xe4, 0xb2, 0x82, 0x73, 0xa2, 0x37, + 0x87, 0xbd, 0x2e, 0xf9, 0xf1, 0x58, 0xfe, 0x5b, 0x2b, 0x5b, 0xb3, 0xdd, + 0xc6, 0x5f, 0x47, 0xc4, 0xb4, 0xe3, 0x25, 0x90, 0xe3, 0x69, 0x5d, 0xe7, + 0x3d, 0x57, 0x6e, 0x51, 0xe6, 0x44, 0x02, 0x13, 0x8b, 0x15, 0x07, 0xc2, + 0x81, 0x8a, 0x58, 0x65, 0x24, 0x8c, 0x65, 0x99, 0x2e, 0x9f, 0xcf, 0x7e, + 0x56, 0x1d, 0xc1, 0xe9, 0x45, 0x26, 0x73, 0x60, 0x38, 0x97, 0x51, 0xf7, + 0x4d, 0xd4, 0xeb, 0x66, 0xf3, 0x0f, 0x56, 0xd6, 0xf6, 0x7b, 0x37, 0x62, + 0x9a, 0x65, 0xad, 0xa3, 0x7e, 0x1d, 0xd4, 0xe3, 0xcf, 0xf2, 0xfa, 0x15, + 0x9d, 0x96, 0x8d, 0xfd, 0xde, 0x3a, 0x46, 0xfd, 0xba, 0xd9, 0x9e, 0x9b, + 0xed, 0x95, 0x8c, 0x9d, 0xaf, 0xe7, 0x62, 0xca, 0xb3, 0xcc, 0x96, 0xa1, + 0x52, 0x9e, 0xf5, 0xf9, 0xa3, 0x4a, 0x01, 0xb7, 0xff, 0xd4, 0x98, 0x5e, + 0x99, 0x92, 0x83, 0x88, 0xfe, 0xfd, 0xd4, 0xbf, 0x60, 0xb8, 0xcc, 0x41, + 0xbd, 0xac, 0xfb, 0xf4, 0x02, 0xa3, 0x4c, 0xd6, 0x15, 0x4c, 0x33, 0x22, + 0xf8, 0x76, 0x8b, 0x07, 0x6f, 0x26, 0xca, 0xed, 0x71, 0x5f, 0x3a, 0xd7, + 0xb2, 0x1e, 0x0f, 0xf9, 0xf1, 0x73, 0xa3, 0x2e, 0xbc, 0x40, 0xd5, 0x31, + 0xa9, 0x79, 0x91, 0x20, 0xce, 0x76, 0xa5, 0x66, 0x73, 0xbe, 0xbc, 0xd8, + 0x92, 0xc2, 0x46, 0xda, 0x93, 0xdf, 0x11, 0x01, 0xde, 0x48, 0x18, 0xc1, + 0xcd, 0xec, 0x7f, 0xd8, 0xdb, 0x40, 0xfe, 0xad, 0x36, 0x91, 0xaa, 0xc5, + 0x4b, 0x22, 0x46, 0x7c, 0x2b, 0xfe, 0xc3, 0x1a, 0x22, 0xce, 0x17, 0x85, + 0x64, 0x6d, 0x6e, 0x0e, 0x8e, 0x6b, 0x0e, 0x3c, 0x1b, 0x9c, 0x8e, 0x28, + 0xdd, 0xb1, 0xcc, 0x78, 0xcb, 0xfa, 0xa1, 0x57, 0xfa, 0x91, 0xb1, 0xfc, + 0x86, 0xe3, 0x50, 0x6c, 0x2c, 0xdc, 0x92, 0x6a, 0xa0, 0xbe, 0x2f, 0xec, + 0xff, 0xdf, 0xad, 0x49, 0xaf, 0xf4, 0xcf, 0x5c, 0x9e, 0xf1, 0xec, 0xc8, + 0x1f, 0xc5, 0xee, 0x97, 0xac, 0xe7, 0xec, 0x36, 0x17, 0xb9, 0x73, 0x71, + 0x50, 0xda, 0xfb, 0x17, 0x8e, 0x4f, 0xda, 0x2c, 0xf4, 0x23, 0x7a, 0xcb, + 0xba, 0xc5, 0x9f, 0xb7, 0xa4, 0x44, 0x7f, 0x82, 0x57, 0xc7, 0x2c, 0x4c, + 0x97, 0xf3, 0x87, 0xed, 0xb2, 0x71, 0xea, 0xab, 0x8b, 0x36, 0xc4, 0xd8, + 0xcb, 0x3c, 0x4e, 0x76, 0x51, 0x68, 0x76, 0x9e, 0xb6, 0x89, 0xdc, 0x7e, + 0xc8, 0x5b, 0x89, 0x2d, 0x26, 0xed, 0xce, 0x50, 0x2f, 0x76, 0x42, 0x72, + 0x53, 0x39, 0x77, 0x61, 0xd2, 0xeb, 0xc0, 0x56, 0xd3, 0x89, 0x76, 0x43, + 0xd5, 0xe5, 0xba, 0x23, 0x24, 0xe7, 0x2e, 0xf8, 0x6b, 0x14, 0x6c, 0x0f, + 0xab, 0x58, 0x6f, 0x74, 0xf9, 0xe5, 0xfa, 0x92, 0x90, 0x9c, 0x2b, 0x58, + 0x43, 0x9d, 0xc4, 0x35, 0x05, 0x1b, 0x0c, 0x79, 0xbe, 0x98, 0xe3, 0xbe, + 0x31, 0x58, 0xd6, 0x76, 0xb3, 0xf1, 0x8a, 0x32, 0x48, 0x9c, 0x17, 0x2e, + 0xf7, 0xde, 0xcd, 0xf3, 0x03, 0x71, 0x12, 0x31, 0x3d, 0x56, 0x42, 0x3f, + 0xdd, 0xd2, 0x37, 0x87, 0xf5, 0x14, 0x72, 0x1c, 0xa7, 0x6f, 0x1b, 0x24, + 0x7e, 0x06, 0xfc, 0x3f, 0x65, 0xf2, 0x34, 0xe4, 0x9d, 0x47, 0xcd, 0x1a, + 0xfe, 0x93, 0x9c, 0xb7, 0x4a, 0xc3, 0xb9, 0xf1, 0x07, 0xd0, 0xdb, 0x4b, + 0x94, 0x79, 0xc1, 0x0a, 0xe6, 0x00, 0x71, 0xe2, 0xfb, 0xc8, 0x98, 0x13, + 0x9b, 0x53, 0x86, 0xb6, 0xcf, 0xe6, 0x6e, 0x4e, 0xea, 0xc2, 0xc9, 0x1c, + 0x3f, 0xa0, 0x4d, 0x28, 0x85, 0xf3, 0x39, 0x82, 0x0d, 0xe4, 0xe2, 0x82, + 0x6f, 0x71, 0xeb, 0xc9, 0x06, 0x49, 0xdb, 0xdc, 0xfe, 0x58, 0xda, 0xc3, + 0x43, 0xe3, 0xe1, 0xf5, 0xaf, 0x4d, 0xfb, 0xfc, 0x6b, 0xd2, 0xf0, 0xb7, + 0xa5, 0x0b, 0x76, 0x59, 0xf0, 0x6d, 0xc1, 0x36, 0x8b, 0x7c, 0x33, 0x97, + 0x73, 0x75, 0x49, 0x4e, 0x03, 0x79, 0x3e, 0xf6, 0xde, 0xcd, 0x4f, 0xd1, + 0xd6, 0x5d, 0xe4, 0xf2, 0x5b, 0x8d, 0x78, 0x54, 0x9e, 0xd7, 0x19, 0x21, + 0xdd, 0x57, 0xa4, 0xf8, 0xb1, 0xa5, 0xfe, 0x77, 0x9c, 0x4f, 0x72, 0xdc, + 0xf4, 0xa7, 0x4a, 0x72, 0xf3, 0x21, 0x7e, 0x26, 0x18, 0xe0, 0x67, 0x1e, + 0xe4, 0xf3, 0x77, 0xb1, 0x9f, 0x4d, 0xe9, 0xa9, 0x3e, 0xa0, 0xe0, 0x1a, + 0xb6, 0xd5, 0x18, 0x82, 0x73, 0x69, 0xfd, 0x7f, 0x59, 0x59, 0xef, 0xd4, + 0x7d, 0x11, 0x20, 0x87, 0x80, 0xb3, 0xad, 0x5e, 0xce, 0x15, 0x34, 0x86, + 0xe5, 0x5c, 0x41, 0x9b, 0x91, 0x93, 0x4f, 0x7c, 0xb7, 0x9b, 0xb8, 0x7d, + 0xee, 0xfc, 0x42, 0x2c, 0x32, 0x71, 0x7b, 0x0a, 0xb1, 0xa2, 0x88, 0x60, + 0x91, 0xdb, 0xff, 0x5c, 0xba, 0x9e, 0x5c, 0x5c, 0x9e, 0x7f, 0xbb, 0x39, + 0xe7, 0x1e, 0xff, 0xb3, 0xe9, 0x2b, 0x71, 0xdb, 0xae, 0x30, 0xda, 0x77, + 0xc9, 0x86, 0x23, 0xe6, 0x60, 0xa1, 0x80, 0x7f, 0x14, 0x9a, 0xff, 0x38, + 0x75, 0x72, 0x94, 0x72, 0x1e, 0x3b, 0x4f, 0x4e, 0xd1, 0x21, 0xfc, 0x77, + 0x24, 0xdc, 0x48, 0x87, 0xde, 0xb7, 0xe2, 0x36, 0xe7, 0xf0, 0xfa, 0xef, + 0x4c, 0xf8, 0x91, 0xb5, 0xb9, 0xe7, 0xbf, 0xbb, 0x25, 0x47, 0xec, 0x49, + 0xc5, 0xa3, 0x4c, 0x79, 0xf3, 0xf3, 0xab, 0x87, 0x65, 0x6e, 0xdf, 0x48, + 0xc8, 0xbd, 0xe8, 0x37, 0x54, 0xe8, 0x7e, 0x95, 0xb1, 0xb4, 0xdf, 0x14, + 0xfb, 0xb5, 0xec, 0x67, 0xfb, 0xac, 0x18, 0xf7, 0x44, 0x02, 0xad, 0xf5, + 0xbc, 0xae, 0x2d, 0x40, 0xac, 0x8a, 0x7a, 0x2a, 0x35, 0xbc, 0xfe, 0xba, + 0x71, 0x9f, 0xdf, 0x1c, 0x87, 0xff, 0x92, 0xf1, 0xa9, 0x22, 0x90, 0xa3, + 0xab, 0x1f, 0x87, 0x05, 0x5e, 0xff, 0xba, 0xc4, 0x1c, 0xa8, 0x91, 0xb8, + 0xb5, 0xa4, 0xe1, 0xb4, 0x35, 0x27, 0x62, 0x64, 0x8f, 0x51, 0x86, 0xf7, + 0x2f, 0xd7, 0xe3, 0x33, 0x1d, 0x47, 0xef, 0xd5, 0xa6, 0xf4, 0xf1, 0x5e, + 0xe8, 0xff, 0x6f, 0x1f, 0x85, 0x38, 0x47, 0x7b, 0x68, 0x90, 0x31, 0x48, + 0xbc, 0x2b, 0x62, 0xce, 0x29, 0x63, 0xf9, 0x54, 0xe1, 0xb9, 0x47, 0x7e, + 0x5c, 0x0a, 0xe7, 0x1a, 0x36, 0x0f, 0xce, 0xc5, 0x30, 0xcb, 0xea, 0x36, + 0x7c, 0xf9, 0xe7, 0x67, 0x9c, 0xb3, 0xcc, 0xd1, 0x2b, 0x9c, 0x58, 0x4c, + 0x3f, 0x68, 0xfc, 0x4b, 0x27, 0xa2, 0xbe, 0x62, 0xc6, 0x56, 0x59, 0x17, + 0x3a, 0x5e, 0x3f, 0x69, 0x4d, 0x18, 0xf5, 0x68, 0xcc, 0xc8, 0xf3, 0x4c, + 0x07, 0xed, 0xdb, 0xc2, 0x23, 0xa6, 0xdc, 0x17, 0x9c, 0x89, 0xc7, 0x1c, + 0xb4, 0x15, 0xb7, 0xa1, 0xb7, 0xfe, 0xbd, 0x52, 0x81, 0xd2, 0x88, 0x33, + 0x38, 0x01, 0x3d, 0xbc, 0x5e, 0xa1, 0x1f, 0x56, 0xcd, 0x33, 0x65, 0x0a, + 0xde, 0x4e, 0x04, 0xcc, 0x40, 0x3e, 0x2e, 0x9d, 0xe2, 0xdc, 0xbd, 0x93, + 0x30, 0xda, 0x9f, 0xca, 0x9f, 0xff, 0x22, 0x3d, 0x35, 0xa7, 0x15, 0x7b, + 0x74, 0xbb, 0x37, 0x25, 0xf0, 0x9e, 0xa3, 0x01, 0xef, 0xed, 0x31, 0x8b, + 0x98, 0x8b, 0x89, 0x9d, 0xba, 0xdd, 0x5b, 0x12, 0x98, 0x74, 0xf2, 0xda, + 0x29, 0x73, 0x36, 0x31, 0x4d, 0xe5, 0xb5, 0xb0, 0xd8, 0x59, 0x4c, 0x63, + 0x7c, 0x2d, 0x8d, 0x78, 0xdd, 0xa5, 0xe3, 0xd0, 0x4a, 0x8c, 0x0a, 0xe6, + 0xba, 0x68, 0x72, 0x24, 0x75, 0x7f, 0xb3, 0xa3, 0x9e, 0x39, 0xaf, 0x5f, + 0x71, 0x19, 0xdf, 0x63, 0x5e, 0x2f, 0x6b, 0x61, 0x61, 0xda, 0xa4, 0x93, + 0x15, 0x76, 0x4c, 0x57, 0x23, 0x0a, 0xb1, 0xb0, 0x02, 0xb7, 0x6b, 0x1b, + 0x3e, 0xab, 0x46, 0xfa, 0x71, 0x7d, 0x83, 0xbb, 0xa9, 0x72, 0xbc, 0xa0, + 0x13, 0xc4, 0x3c, 0x11, 0xe6, 0x25, 0x06, 0xd4, 0xf2, 0x88, 0xe8, 0xc6, + 0xdf, 0x94, 0x1c, 0x13, 0x59, 0x35, 0x77, 0xdf, 0xd8, 0x3b, 0x25, 0x28, + 0x0d, 0x13, 0xab, 0x7e, 0xe2, 0xfb, 0xef, 0xd5, 0x3b, 0x5a, 0x22, 0x78, + 0xef, 0x32, 0xe4, 0xbf, 0x6d, 0x5b, 0x6e, 0x77, 0xe4, 0x83, 0x98, 0x3b, + 0x60, 0x59, 0x8c, 0x93, 0x3e, 0x28, 0xb3, 0x39, 0x1e, 0xfa, 0x1a, 0xe7, + 0x66, 0x4d, 0xfa, 0x0f, 0xd6, 0xe7, 0x9c, 0x36, 0x07, 0x70, 0x17, 0x47, + 0x3a, 0x6e, 0x79, 0xcb, 0xf8, 0xc0, 0x7a, 0x33, 0xc1, 0x5c, 0xd9, 0x90, + 0x67, 0x43, 0x73, 0xb0, 0xcd, 0x74, 0x36, 0x2f, 0x55, 0x14, 0xf4, 0x18, + 0xf3, 0xb4, 0x12, 0xc6, 0xa9, 0x6e, 0xfa, 0x75, 0xcc, 0x6b, 0x04, 0xf7, + 0x80, 0xe5, 0xd2, 0xeb, 0xd6, 0xb9, 0x22, 0x77, 0xde, 0x32, 0xd2, 0x20, + 0x58, 0x10, 0x6e, 0x7b, 0xca, 0x68, 0x41, 0x4f, 0x66, 0x10, 0xbd, 0x99, + 0x5c, 0x3f, 0x59, 0xcc, 0xf9, 0x98, 0x7e, 0xd6, 0xad, 0x2b, 0x8e, 0x08, + 0xf7, 0x3a, 0x73, 0xcb, 0x5e, 0x23, 0x8a, 0xcd, 0x99, 0x3b, 0x6f, 0x39, + 0xd5, 0xd0, 0xcf, 0xff, 0xb9, 0x3a, 0x43, 0xa8, 0xfc, 0xd8, 0x3a, 0x65, + 0x11, 0xe9, 0xa3, 0xe3, 0x96, 0xa7, 0x8c, 0x3b, 0x6f, 0x69, 0x5f, 0xf4, + 0x4d, 0x6c, 0xca, 0xb4, 0xff, 0xc9, 0x7e, 0xca, 0x59, 0xa7, 0x34, 0x72, + 0xa8, 0xed, 0x9a, 0xc0, 0x9d, 0xb7, 0xa4, 0x17, 0xf5, 0xb2, 0x8f, 0x55, + 0x8c, 0x2f, 0xb9, 0x3a, 0x51, 0xc6, 0xf6, 0x8f, 0xd3, 0x41, 0x49, 0x64, + 0xa2, 0x6d, 0x7e, 0xe0, 0x03, 0x6b, 0x5e, 0x5f, 0x91, 0xad, 0x03, 0x17, + 0x75, 0xf0, 0xa0, 0xe9, 0xcc, 0x06, 0x1c, 0xb6, 0x0e, 0x3a, 0x7c, 0xd4, + 0x41, 0x92, 0x3a, 0xc8, 0xd6, 0x18, 0xe1, 0x77, 0xa9, 0x83, 0x79, 0x63, + 0xeb, 0xd6, 0x95, 0x44, 0xe0, 0x74, 0x18, 0xaf, 0x3a, 0x9c, 0x9c, 0x0b, + 0x97, 0xb1, 0x8e, 0x7a, 0xbb, 0xf3, 0x96, 0x8b, 0x17, 0xd9, 0x3a, 0xff, + 0xb2, 0x3b, 0xb0, 0xc1, 0xde, 0x3b, 0xd7, 0x9d, 0x59, 0xc3, 0xa3, 0x99, + 0xc7, 0x7d, 0x3c, 0x7a, 0x98, 0xb3, 0xdc, 0x4c, 0x5d, 0x35, 0x71, 0x1c, + 0x2b, 0x28, 0xd7, 0x46, 0xfe, 0x6e, 0xe5, 0xef, 0x0e, 0xfe, 0x96, 0xf9, + 0x51, 0xcf, 0xca, 0x16, 0x3b, 0x2b, 0x9b, 0x83, 0xf2, 0x78, 0x88, 0x57, + 0x32, 0x26, 0xf7, 0x57, 0xae, 0x09, 0xc4, 0xd8, 0xc6, 0xfd, 0xa5, 0xb2, + 0x6f, 0xc8, 0x65, 0xc4, 0x7d, 0x4e, 0x88, 0x7c, 0x7a, 0x6b, 0x3b, 0xb2, + 0xc4, 0xde, 0xdf, 0xe7, 0xb0, 0x97, 0xb2, 0x55, 0x70, 0x7e, 0x5e, 0x58, + 0x34, 0x34, 0xc3, 0x63, 0xc0, 0xe7, 0x36, 0xe2, 0xcc, 0xf9, 0x13, 0xd4, + 0x81, 0xd8, 0xc9, 0x3d, 0xd4, 0x5f, 0x27, 0xeb, 0x1c, 0x65, 0x2c, 0xdb, + 0xcd, 0xfe, 0xed, 0xf5, 0xdb, 0xb0, 0xfd, 0x9c, 0x0c, 0xba, 0x79, 0x9c, + 0xed, 0xed, 0x35, 0x7e, 0x53, 0x76, 0xb4, 0x5e, 0xf6, 0x53, 0x3a, 0x31, + 0x6c, 0xcf, 0xbb, 0x42, 0x2e, 0x73, 0x11, 0x79, 0x82, 0x65, 0xfd, 0xd4, + 0x68, 0x9c, 0xef, 0xb0, 0xed, 0xea, 0x50, 0x9b, 0x3b, 0xe0, 0xc6, 0x90, + 0xbd, 0x06, 0x6e, 0x59, 0x45, 0xb6, 0x7d, 0x89, 0x2c, 0x75, 0xcd, 0x9b, + 0x68, 0x78, 0xeb, 0xd2, 0x1f, 0x90, 0x27, 0x8a, 0xfc, 0x73, 0x70, 0x92, + 0x31, 0x35, 0xaa, 0xc5, 0xdb, 0x45, 0xd6, 0x32, 0xc3, 0x19, 0xbe, 0x16, + 0xf1, 0x16, 0x27, 0xfb, 0x6b, 0x26, 0xa7, 0x3c, 0x95, 0xc7, 0xee, 0x7d, + 0x69, 0x3d, 0xb6, 0x5f, 0xc9, 0xf1, 0xd3, 0xde, 0xb1, 0x42, 0xfc, 0x09, + 0x92, 0xcf, 0x7a, 0xe0, 0x8c, 0xe8, 0xfe, 0x26, 0x47, 0x57, 0xd0, 0x05, + 0xfa, 0x58, 0xa9, 0xc8, 0x1b, 0xa7, 0xec, 0x82, 0xc7, 0x6e, 0x6d, 0x8d, + 0x8d, 0xd1, 0xf1, 0xf9, 0x2e, 0x78, 0xb4, 0xb5, 0xe9, 0x42, 0xec, 0xf2, + 0x68, 0x6d, 0x09, 0xf1, 0x77, 0x59, 0xab, 0x0f, 0xdb, 0xdc, 0xe3, 0x48, + 0xe6, 0xa5, 0x52, 0xd9, 0x8b, 0x47, 0xdf, 0xaf, 0x70, 0x1a, 0xb9, 0x76, + 0x35, 0xb6, 0xdb, 0xe2, 0xd0, 0x70, 0xce, 0x77, 0x75, 0xad, 0xc5, 0x21, + 0xfb, 0x5f, 0x89, 0x4a, 0xe9, 0x7c, 0xbd, 0x1c, 0x7e, 0x2d, 0x76, 0xd9, + 0xf8, 0xc5, 0x36, 0x4a, 0x81, 0x25, 0x89, 0x0b, 0xfb, 0x97, 0xfe, 0xa4, + 0xdf, 0xae, 0x2a, 0x15, 0x13, 0xf6, 0xb3, 0x92, 0x83, 0x99, 0x18, 0x06, + 0x53, 0x53, 0xf7, 0xe8, 0xe9, 0x87, 0xd8, 0xfe, 0x81, 0x38, 0xe7, 0x69, + 0xb6, 0x21, 0xfb, 0xf7, 0x64, 0xcf, 0xde, 0xd4, 0xfd, 0x7a, 0x22, 0x5b, + 0x65, 0x19, 0x81, 0x0d, 0x7b, 0x89, 0x7f, 0xd1, 0x16, 0xa9, 0x6f, 0x59, + 0xaf, 0xcd, 0x0b, 0x22, 0x3b, 0xcd, 0x89, 0xc1, 0xb9, 0xc0, 0x40, 0x52, + 0xf6, 0x53, 0x9d, 0x89, 0xad, 0x66, 0x1e, 0x19, 0xad, 0xae, 0xd3, 0xba, + 0x55, 0xd9, 0x0b, 0xf5, 0xc1, 0x97, 0x7b, 0x8c, 0x5a, 0xad, 0x47, 0xcd, + 0xee, 0x67, 0x7c, 0xd9, 0x0d, 0xcc, 0x2e, 0x13, 0x0c, 0xa8, 0x32, 0xa2, + 0xbd, 0x55, 0x98, 0x0b, 0x7f, 0xb5, 0x8d, 0xcb, 0xf1, 0x6f, 0xab, 0x46, + 0x70, 0xa5, 0xf0, 0x4a, 0xf5, 0x7d, 0x6b, 0x88, 0xdc, 0xe4, 0xee, 0xb9, + 0xff, 0xa7, 0x34, 0xbf, 0xee, 0xd4, 0x3e, 0x9d, 0xf3, 0xf2, 0xf3, 0x05, + 0xba, 0x3f, 0xad, 0x88, 0x8e, 0x84, 0x4b, 0x25, 0xb0, 0x95, 0x71, 0xf6, + 0xbf, 0xe6, 0x46, 0xb0, 0x8f, 0xff, 0x7f, 0x76, 0xa5, 0xec, 0x4d, 0xb5, + 0xac, 0x60, 0x60, 0x5e, 0xb8, 0x8a, 0x63, 0x78, 0x96, 0xf7, 0x7b, 0x33, + 0x6f, 0x59, 0xa7, 0xa6, 0x1b, 0xfd, 0xcb, 0x18, 0xec, 0x06, 0xc6, 0x75, + 0x6d, 0x52, 0xfd, 0xef, 0xee, 0x95, 0x83, 0xbb, 0x82, 0x63, 0xf9, 0x7e, + 0xa0, 0x4e, 0x4b, 0xaa, 0xa5, 0x65, 0xa2, 0xd7, 0x81, 0xf1, 0x57, 0xa6, + 0x3c, 0x3b, 0x28, 0xf0, 0x59, 0x7b, 0x5d, 0xa5, 0x77, 0x88, 0xbe, 0x3e, + 0xa4, 0x45, 0xe3, 0xd4, 0xbb, 0x7b, 0x1a, 0xc7, 0x7c, 0xf7, 0xdc, 0x2f, + 0xd9, 0xe3, 0xac, 0x36, 0x66, 0x72, 0x8c, 0x0a, 0xb4, 0xb9, 0xff, 0x99, + 0x5f, 0x7f, 0x6d, 0x24, 0xfb, 0x1a, 0xb2, 0x9a, 0xe8, 0x1b, 0x45, 0xac, + 0x73, 0xb5, 0xf9, 0xf0, 0x8c, 0xae, 0x7a, 0xdd, 0x77, 0x37, 0x6d, 0x34, + 0x34, 0xf7, 0xd7, 0x16, 0x6d, 0xda, 0xfc, 0x16, 0x47, 0x7d, 0x5b, 0xc2, + 0x8e, 0x55, 0x9c, 0x57, 0x23, 0x3a, 0x57, 0x79, 0xc7, 0x42, 0x4d, 0x20, + 0x3c, 0xd7, 0x1e, 0x3f, 0x70, 0x6b, 0x3a, 0x81, 0x6d, 0x29, 0x69, 0x53, + 0xc1, 0xb2, 0xc0, 0xdb, 0x96, 0x7f, 0x7a, 0x02, 0x5b, 0x32, 0x9f, 0xc4, + 0x4d, 0x07, 0xc9, 0x8d, 0xf5, 0xd6, 0x38, 0xf4, 0x68, 0xee, 0xd9, 0xd4, + 0x1c, 0x59, 0xdb, 0x96, 0xbd, 0x45, 0xb7, 0x24, 0x02, 0x70, 0x97, 0x13, + 0x83, 0xc7, 0x02, 0xf2, 0x2c, 0xd3, 0x8b, 0x6c, 0x8b, 0x94, 0xa9, 0xd5, + 0xc6, 0x90, 0x25, 0x73, 0x94, 0xb5, 0xd0, 0xfe, 0xb2, 0xdc, 0x3e, 0x09, + 0x1a, 0x5e, 0x8d, 0xae, 0xbd, 0x41, 0xae, 0xd7, 0x6c, 0x48, 0x1b, 0x0a, + 0xe6, 0x07, 0xa6, 0xa1, 0x6e, 0xe5, 0xab, 0xaf, 0x17, 0x05, 0x8a, 0x18, + 0x4f, 0xc4, 0xb7, 0x8c, 0x8d, 0xc7, 0xf0, 0x1b, 0x62, 0x90, 0xec, 0x19, + 0x4b, 0x4a, 0x3d, 0xb6, 0x35, 0x17, 0x69, 0xf1, 0x53, 0x43, 0xf6, 0x2f, + 0x5b, 0xd6, 0x35, 0x81, 0x37, 0xad, 0x68, 0x0d, 0xe5, 0x21, 0x5f, 0xcb, + 0xd5, 0x95, 0x32, 0xf9, 0xbd, 0x40, 0x4a, 0xe3, 0x2d, 0xa2, 0x93, 0x27, + 0xcd, 0x38, 0xb3, 0x01, 0xc1, 0xfd, 0x0f, 0x62, 0x6f, 0x19, 0x8a, 0xfd, + 0x8c, 0x71, 0x99, 0x52, 0xc9, 0x38, 0xea, 0xf4, 0x8f, 0xd8, 0xeb, 0x05, + 0x1d, 0xc4, 0x68, 0xe1, 0x97, 0x92, 0xf3, 0x39, 0xf1, 0x94, 0x51, 0x85, + 0x27, 0xb5, 0x1c, 0x57, 0x23, 0xd6, 0xe1, 0x07, 0x89, 0x79, 0x59, 0x7a, + 0x08, 0x39, 0xaf, 0xd1, 0x7e, 0x46, 0xf9, 0x0d, 0xfd, 0x1c, 0x78, 0x21, + 0xbd, 0x11, 0x0f, 0xca, 0x1a, 0xa2, 0x52, 0xdb, 0x5c, 0xe7, 0x90, 0xfe, + 0x36, 0x62, 0x6b, 0x46, 0xda, 0xfa, 0x20, 0xb6, 0xd7, 0xd8, 0x9d, 0x97, + 0x55, 0xb0, 0xfc, 0x83, 0xd8, 0x53, 0xc6, 0xe3, 0xf6, 0xdc, 0xc9, 0x73, + 0xaf, 0x5e, 0x53, 0x30, 0xaf, 0x14, 0x2a, 0xf3, 0x06, 0x87, 0x71, 0x33, + 0x1c, 0x55, 0xdf, 0xa4, 0xed, 0xc9, 0xbe, 0x9a, 0xaf, 0xc2, 0x59, 0xe5, + 0xa2, 0x6f, 0xde, 0x0a, 0x57, 0x95, 0x70, 0xf5, 0x02, 0x8f, 0x8e, 0xf2, + 0xbe, 0xe8, 0x36, 0xdc, 0x26, 0xba, 0x75, 0x12, 0x87, 0x7a, 0x24, 0xaf, + 0x33, 0x2a, 0xa9, 0x23, 0xbd, 0x95, 0x9c, 0x1e, 0xe5, 0xc4, 0x4c, 0xc6, + 0x47, 0x37, 0xf3, 0xb7, 0xb6, 0x77, 0xa9, 0xf7, 0x79, 0x7d, 0x65, 0xe4, + 0xf0, 0x96, 0xf5, 0x3e, 0x39, 0xfc, 0xfc, 0x40, 0x5d, 0xd6, 0x20, 0x4e, + 0xe1, 0x06, 0xbd, 0x39, 0x4e, 0xbc, 0x59, 0x6d, 0x9c, 0xb1, 0x62, 0xab, + 0xa4, 0x8c, 0xee, 0x8b, 0x29, 0x85, 0x3e, 0x16, 0xc0, 0x3f, 0xcd, 0x82, + 0x2b, 0x22, 0xcf, 0x14, 0x64, 0xbd, 0xb8, 0x51, 0x9e, 0xf5, 0xb5, 0xc8, + 0xf8, 0x5d, 0xb2, 0xee, 0x86, 0xe8, 0x84, 0x0b, 0x46, 0x76, 0x9f, 0xcc, + 0xd9, 0x0c, 0x0b, 0x81, 0x85, 0xbf, 0x67, 0x2e, 0x24, 0xf3, 0x53, 0x9b, + 0xad, 0x57, 0xb2, 0x41, 0x1f, 0x39, 0xfd, 0xa3, 0xd0, 0x5b, 0x12, 0xd4, + 0x75, 0x53, 0x48, 0x9e, 0xdf, 0x3b, 0x7d, 0x09, 0xd8, 0x3c, 0xde, 0x3c, + 0x89, 0xcf, 0xa1, 0x9c, 0xb9, 0xeb, 0xdc, 0xb1, 0x15, 0xa8, 0xa8, 0x8a, + 0xfa, 0x4a, 0x71, 0x19, 0xcf, 0xd7, 0x30, 0x3f, 0xf9, 0x22, 0x2a, 0x56, + 0xb6, 0x22, 0xc1, 0xb1, 0x97, 0x1b, 0x7f, 0xc5, 0x6b, 0xf7, 0x21, 0x99, + 0x72, 0x71, 0x1c, 0x3f, 0xb1, 0x2a, 0x6a, 0x44, 0x36, 0xd3, 0x5b, 0x66, + 0x30, 0x9f, 0xb6, 0x75, 0x41, 0xdc, 0x4e, 0x09, 0x47, 0xaa, 0x8b, 0xae, + 0x07, 0x73, 0xfb, 0x1a, 0xbd, 0x75, 0x8d, 0xd2, 0x41, 0x9b, 0xed, 0xa1, + 0xce, 0xa5, 0xac, 0x65, 0x2d, 0x0f, 0x9c, 0xa6, 0x8e, 0x3b, 0x78, 0x6e, + 0xf8, 0xdf, 0x84, 0x7a, 0x59, 0x31, 0x4e, 0x58, 0x71, 0xcd, 0x47, 0xbb, + 0x54, 0x57, 0x09, 0x9f, 0x5a, 0x1a, 0x7a, 0x8f, 0xf7, 0xb5, 0xbc, 0x9d, + 0x9e, 0xb9, 0x25, 0xa7, 0xcb, 0x30, 0x75, 0xf9, 0x6f, 0xf6, 0x75, 0x87, + 0x7d, 0xbd, 0x23, 0x7f, 0xfd, 0xcc, 0x2d, 0x3d, 0xc6, 0xcb, 0xbc, 0xde, + 0x4b, 0xdd, 0xab, 0x17, 0x49, 0xfd, 0x75, 0xa6, 0xd4, 0x67, 0x4a, 0x65, + 0xf4, 0xe4, 0xe7, 0xe3, 0x50, 0x7e, 0x3e, 0x26, 0xf2, 0x6d, 0x38, 0xd9, + 0x46, 0x3c, 0x5a, 0x0a, 0x13, 0x65, 0x01, 0xc1, 0x79, 0x91, 0x8b, 0x73, + 0x97, 0x11, 0xb9, 0xd6, 0x30, 0xde, 0x75, 0x3d, 0x53, 0x8a, 0x78, 0xc7, + 0x4c, 0xdb, 0x0e, 0xcf, 0xdc, 0x22, 0xfb, 0xde, 0xde, 0x52, 0x1a, 0x7d, + 0xb2, 0x65, 0x23, 0x45, 0x2e, 0x7b, 0xaf, 0xe9, 0x0c, 0xd7, 0x3b, 0xe6, + 0x65, 0x8b, 0x61, 0xc4, 0xce, 0x28, 0x2e, 0x8f, 0xe0, 0x43, 0x22, 0xdd, + 0xc8, 0xcc, 0x2b, 0x1e, 0x64, 0xce, 0x14, 0xcc, 0x50, 0xb7, 0x6d, 0x44, + 0xec, 0x43, 0xf6, 0xde, 0x37, 0xe7, 0xc4, 0x0a, 0x34, 0xea, 0x0e, 0xcc, + 0x0b, 0xcf, 0x64, 0xe6, 0x45, 0xbb, 0x34, 0x8b, 0x1d, 0xba, 0xff, 0x7a, + 0x2c, 0xb7, 0xeb, 0xed, 0x4b, 0x67, 0xdb, 0x4b, 0x39, 0xa7, 0x8f, 0x51, + 0x8e, 0x6d, 0x01, 0x91, 0xe3, 0x9b, 0x79, 0x39, 0x5a, 0x19, 0x4b, 0x4d, + 0xed, 0xda, 0x40, 0xef, 0x59, 0xbd, 0x3d, 0x63, 0xeb, 0xed, 0x3e, 0x9e, + 0x17, 0x33, 0xbf, 0x2f, 0xc2, 0xd1, 0x7a, 0x6f, 0x7e, 0x1f, 0x9b, 0xe4, + 0x6a, 0x82, 0xbf, 0x0d, 0x7f, 0xbd, 0xda, 0xd0, 0xc3, 0x0e, 0x9b, 0xd7, + 0xbb, 0x11, 0xb7, 0x39, 0xb3, 0x3c, 0xf3, 0xae, 0xc0, 0x23, 0x76, 0x39, + 0x17, 0x75, 0x52, 0x86, 0x47, 0xf3, 0xfe, 0x22, 0x7b, 0x0e, 0x1e, 0xb3, + 0x7f, 0xef, 0xe6, 0xdc, 0xba, 0xe8, 0xab, 0x85, 0x18, 0x25, 0xeb, 0xed, + 0xff, 0xc3, 0xf6, 0xfd, 0x21, 0x1c, 0xb7, 0xff, 0x67, 0x73, 0xf9, 0x16, + 0x7a, 0x4c, 0xd9, 0x3b, 0x53, 0x86, 0x6e, 0x7b, 0x0f, 0xb9, 0xac, 0x01, + 0x5c, 0x89, 0xcd, 0x9a, 0xac, 0x07, 0x93, 0xfb, 0x68, 0x62, 0x13, 0x9d, + 0x48, 0x6a, 0xa6, 0x37, 0x53, 0x3f, 0x35, 0x57, 0x32, 0xb1, 0xa7, 0xfe, + 0x03, 0x2b, 0x6a, 0xe7, 0x4f, 0x27, 0xac, 0xbd, 0xc6, 0xd1, 0x10, 0x3d, + 0xb8, 0xbd, 0xc8, 0xd6, 0x6f, 0xb8, 0xcd, 0xde, 0xff, 0x47, 0x99, 0x9f, + 0x49, 0x48, 0x1c, 0x9d, 0x83, 0xb4, 0x69, 0xc7, 0xe2, 0x96, 0xed, 0x9c, + 0x93, 0x9e, 0x54, 0x20, 0x7a, 0x09, 0xef, 0x4d, 0x30, 0x96, 0x75, 0x53, + 0x9f, 0xb1, 0x16, 0xe1, 0x67, 0x6b, 0xb0, 0x9b, 0x36, 0x36, 0x6e, 0x5a, + 0xd6, 0x3e, 0x62, 0x44, 0xe5, 0x3c, 0x15, 0xd9, 0x9a, 0x35, 0x48, 0x31, + 0x36, 0xed, 0x33, 0x1a, 0x3f, 0x57, 0x84, 0xb8, 0xdf, 0x0d, 0xdd, 0xb7, + 0x85, 0xa3, 0xb9, 0x97, 0xf3, 0x75, 0xd4, 0x14, 0xde, 0xe8, 0x3c, 0xb3, + 0x14, 0x46, 0x78, 0xb1, 0xe3, 0x27, 0xd6, 0xa4, 0xfd, 0xec, 0xb8, 0xeb, + 0x5f, 0x28, 0xc3, 0x46, 0x71, 0xde, 0x4a, 0xce, 0xf1, 0xbb, 0x01, 0x79, + 0x7e, 0x0d, 0xd4, 0xf5, 0x35, 0xb6, 0x8b, 0x0c, 0x7b, 0x43, 0xce, 0xd8, + 0x3e, 0x04, 0x5a, 0x36, 0x28, 0xe7, 0x72, 0x83, 0x4b, 0xc6, 0x4c, 0x8c, + 0xd6, 0x3f, 0x4b, 0x1e, 0x23, 0xf5, 0x8b, 0xf1, 0x84, 0xf9, 0xb4, 0x55, + 0x3b, 0xe3, 0xfb, 0xd6, 0x7e, 0x43, 0x5d, 0x4f, 0x6d, 0xc7, 0xca, 0xd9, + 0x56, 0x19, 0xdb, 0xba, 0x3d, 0xa0, 0x9b, 0xdb, 0xd9, 0xd6, 0xf1, 0xc4, + 0xd1, 0xa0, 0x9b, 0x6d, 0x3d, 0x6a, 0x4a, 0x6e, 0xe0, 0x6c, 0x6e, 0xe6, + 0xdc, 0x76, 0xa5, 0x02, 0xbe, 0xad, 0x94, 0x4b, 0xf2, 0xb7, 0xaf, 0x26, + 0xe4, 0x5d, 0x8f, 0x6f, 0x72, 0x3c, 0xd1, 0x8d, 0x2e, 0x34, 0xde, 0x5b, + 0x41, 0xfb, 0xa9, 0x44, 0xc1, 0xd6, 0x75, 0x1f, 0xf1, 0x0e, 0xb7, 0xb3, + 0xcc, 0xeb, 0x81, 0x39, 0x78, 0x21, 0xd4, 0xb8, 0x72, 0x0e, 0x9c, 0xe4, + 0x21, 0x81, 0xe6, 0x0d, 0x4a, 0x5c, 0x13, 0x5b, 0xbc, 0x2d, 0xad, 0x07, + 0x9b, 0x20, 0xd8, 0xdd, 0x4a, 0x7d, 0xcc, 0xc1, 0xfb, 0x0b, 0x45, 0x2e, + 0x67, 0x38, 0xe8, 0x08, 0x74, 0x3c, 0xcd, 0xf9, 0xad, 0x98, 0x97, 0xcb, + 0x53, 0x33, 0xf6, 0x7e, 0xcd, 0x56, 0x24, 0x33, 0x27, 0xde, 0xdd, 0x6b, + 0xc0, 0x79, 0xa8, 0xfe, 0x41, 0x0b, 0xf6, 0xbb, 0x21, 0x8d, 0x32, 0x0f, + 0xad, 0x32, 0x0f, 0xa5, 0xf4, 0xa7, 0x6b, 0x28, 0xf7, 0x7a, 0x5b, 0xee, + 0x39, 0x18, 0x36, 0x65, 0xfd, 0xcb, 0xa9, 0xdd, 0x86, 0x5e, 0x62, 0x67, + 0xe0, 0x4c, 0x17, 0xfb, 0x79, 0x9d, 0x32, 0xcf, 0xa3, 0xde, 0x27, 0x5b, + 0x84, 0xb7, 0xde, 0x87, 0xbe, 0x54, 0xe1, 0xdd, 0x11, 0x05, 0xe9, 0x80, + 0xf4, 0x71, 0x1f, 0x79, 0x5c, 0x97, 0x35, 0x59, 0x23, 0xd7, 0x77, 0x33, + 0xf7, 0x8f, 0x6a, 0xf4, 0x07, 0xea, 0x1d, 0xfa, 0x1c, 0xe8, 0x13, 0x6f, + 0x38, 0xa2, 0xf4, 0x01, 0xd3, 0x7b, 0x86, 0xd8, 0x70, 0x08, 0x1d, 0x16, + 0xaa, 0x6c, 0x7b, 0xf8, 0xd9, 0x88, 0xf1, 0xa1, 0x22, 0xb1, 0x3d, 0x4b, + 0x1d, 0xa8, 0x9c, 0x13, 0xd1, 0x41, 0x39, 0x7d, 0x76, 0x2c, 0xa0, 0xfb, + 0x5f, 0xa0, 0x3c, 0xdb, 0x29, 0xcf, 0x8a, 0xdc, 0x1c, 0xfa, 0x36, 0x2b, + 0xe2, 0xd3, 0x81, 0x96, 0xd5, 0xbc, 0xbe, 0x8d, 0xf2, 0x04, 0xfa, 0x14, + 0x0c, 0xb5, 0xf4, 0x90, 0x2b, 0x76, 0x50, 0x07, 0xe7, 0xe4, 0x71, 0xdb, + 0x73, 0xd6, 0x41, 0x2e, 0x50, 0x8c, 0xbd, 0xa6, 0xe0, 0xb7, 0x86, 0x61, + 0xda, 0xe9, 0x1e, 0xce, 0x48, 0xd4, 0xab, 0xa2, 0xd8, 0x10, 0x0c, 0xa8, + 0xe1, 0x35, 0x17, 0xe7, 0xa6, 0x12, 0xfb, 0xb5, 0xdd, 0xf6, 0x5e, 0xe5, + 0x1c, 0xb7, 0xfb, 0x83, 0x35, 0xea, 0x15, 0x7e, 0x26, 0xeb, 0x63, 0xb2, + 0x86, 0xd4, 0xeb, 0xc9, 0xed, 0xd7, 0x72, 0x51, 0x27, 0xb9, 0xeb, 0xcf, + 0x68, 0xc2, 0x7d, 0x0b, 0xe5, 0x7f, 0x69, 0x3d, 0x69, 0x97, 0x97, 0x72, + 0x2e, 0x9b, 0xa3, 0x97, 0xda, 0xe5, 0x7e, 0x69, 0x3d, 0xab, 0x39, 0xa7, + 0x94, 0x2b, 0x3c, 0x2f, 0x3c, 0xfa, 0x0d, 0x27, 0x31, 0xaf, 0x78, 0xee, + 0x62, 0x1c, 0x33, 0x4e, 0xd4, 0x9e, 0xac, 0xef, 0x64, 0x1c, 0x9b, 0xba, + 0x7f, 0xcb, 0xc2, 0xe3, 0x76, 0x1e, 0xde, 0x45, 0x3e, 0x7b, 0x74, 0x47, + 0x11, 0x84, 0xa3, 0xca, 0xfa, 0x5d, 0x73, 0xd9, 0xb9, 0x5c, 0x56, 0xf6, + 0x35, 0x5d, 0x66, 0x73, 0xc3, 0xa8, 0x2a, 0xb8, 0xfb, 0x49, 0x7b, 0xf8, + 0x84, 0xbb, 0x74, 0x62, 0x8f, 0x51, 0xe0, 0x2c, 0x47, 0x1f, 0x54, 0x89, + 0x93, 0x03, 0xe6, 0x62, 0x89, 0xcd, 0x7e, 0xd6, 0x0f, 0xc6, 0xd4, 0xa9, + 0xdc, 0xe6, 0x76, 0x0f, 0x2a, 0xba, 0xb6, 0x3a, 0x20, 0xfb, 0x47, 0x65, + 0x2f, 0xa8, 0xf4, 0x55, 0x92, 0x5f, 0x97, 0xfa, 0x38, 0xae, 0x51, 0xe8, + 0x4b, 0xf8, 0xc6, 0xfb, 0xa5, 0x85, 0x7d, 0x86, 0x51, 0x5b, 0xce, 0x5f, + 0x59, 0x2b, 0xb5, 0xec, 0x4c, 0x0d, 0xe7, 0xcb, 0x1e, 0xcd, 0xcb, 0x1e, + 0xfb, 0xd8, 0x75, 0xb5, 0xa9, 0xfb, 0xee, 0x82, 0xf9, 0xe7, 0x5d, 0xf2, + 0x0c, 0x46, 0xd6, 0x5c, 0xe5, 0x9e, 0x82, 0x2e, 0xe2, 0x50, 0x54, 0x6b, + 0x64, 0x9c, 0xd7, 0x7d, 0x6b, 0x39, 0x1f, 0x71, 0xaf, 0xec, 0x51, 0x2f, + 0xc4, 0xc8, 0x62, 0xe4, 0xd6, 0x3e, 0x65, 0x9f, 0x45, 0x6e, 0xbd, 0x93, + 0x76, 0x8f, 0xae, 0xf4, 0xef, 0xad, 0xac, 0xd7, 0xc9, 0x58, 0x78, 0x6e, + 0x7f, 0xf4, 0x10, 0xf5, 0x3a, 0xcc, 0x7b, 0x9b, 0xcf, 0xae, 0xa7, 0xc8, + 0x9a, 0x92, 0xc4, 0xde, 0xdf, 0x59, 0x6d, 0xe7, 0x95, 0x9d, 0xba, 0x57, + 0xbc, 0x26, 0x26, 0xcf, 0xdc, 0x46, 0xf3, 0xeb, 0xee, 0x4d, 0x1f, 0x79, + 0xe6, 0x36, 0x41, 0x5b, 0x42, 0x74, 0x33, 0xb9, 0x5d, 0x1c, 0x3d, 0x18, + 0x4d, 0xd4, 0x69, 0x5b, 0xa0, 0xc9, 0x7a, 0x33, 0xff, 0x7a, 0xb0, 0x3f, + 0x81, 0x68, 0xd1, 0xa5, 0x95, 0xe4, 0x5b, 0x88, 0x3a, 0x18, 0xa3, 0x1e, + 0x4d, 0xd4, 0x35, 0x6f, 0xe3, 0x98, 0xfc, 0x2b, 0x7b, 0x30, 0x9c, 0x68, + 0xfc, 0x2b, 0xc6, 0x11, 0x7f, 0x99, 0xcd, 0x75, 0xe2, 0x7f, 0xbd, 0x97, + 0x38, 0xb0, 0x29, 0xbf, 0xe6, 0xd5, 0x96, 0xf8, 0x35, 0xe5, 0xb7, 0x85, + 0x64, 0xbd, 0x4f, 0x2a, 0x37, 0xc1, 0x3c, 0xff, 0x04, 0xd6, 0xf5, 0x2b, + 0x78, 0xd2, 0x38, 0x81, 0xb5, 0x43, 0x22, 0xcf, 0x09, 0xac, 0xe9, 0x7f, + 0x09, 0x7b, 0xfa, 0x67, 0xa0, 0xc9, 0xd6, 0x4d, 0x07, 0x36, 0xec, 0x3c, + 0x88, 0xed, 0x29, 0x0b, 0xdb, 0x42, 0x1e, 0xac, 0x7f, 0x58, 0xc1, 0xf2, + 0xc0, 0x61, 0x6c, 0xd9, 0x69, 0xe1, 0xe2, 0x50, 0x27, 0x9a, 0xcd, 0x32, + 0x14, 0x57, 0xcd, 0x6b, 0x57, 0x59, 0xae, 0x6d, 0xb8, 0x23, 0xbf, 0x2f, + 0x79, 0x3f, 0xb1, 0x40, 0x85, 0xcf, 0x90, 0x3d, 0xc7, 0x51, 0xe5, 0xa6, + 0x4c, 0x93, 0xd2, 0x9a, 0x7f, 0x66, 0x79, 0x7d, 0xa6, 0xa8, 0x02, 0xa5, + 0x71, 0xec, 0x09, 0x9d, 0xc0, 0xd0, 0xd0, 0x07, 0xe5, 0x39, 0x7f, 0x99, + 0x20, 0x77, 0x90, 0x9c, 0xc3, 0xa4, 0x4d, 0x7d, 0xd2, 0xfb, 0x40, 0x62, + 0x77, 0x93, 0xf8, 0xe9, 0xe0, 0x49, 0x9c, 0x1c, 0xfc, 0x37, 0x2c, 0xd1, + 0x24, 0x7f, 0xb4, 0x3a, 0x9d, 0x11, 0xcb, 0xda, 0xd5, 0x10, 0xb7, 0x6a, + 0x8c, 0x5f, 0xb0, 0xed, 0x0a, 0x4c, 0x8f, 0xbc, 0x88, 0x6d, 0x1a, 0xdb, + 0x4a, 0xed, 0xc7, 0x0e, 0xc6, 0x75, 0x5f, 0xe4, 0x66, 0xf8, 0x52, 0x59, + 0xb3, 0x1a, 0xd1, 0x1d, 0xd5, 0xd0, 0x37, 0x56, 0x39, 0x8c, 0x8e, 0x7f, + 0x55, 0xea, 0x71, 0x7d, 0xe6, 0x24, 0x7e, 0x3e, 0x68, 0xef, 0xa5, 0x6a, + 0xfd, 0xae, 0x62, 0x75, 0x6e, 0x0b, 0xe9, 0xcd, 0xff, 0x43, 0x89, 0xc6, + 0x4b, 0x69, 0x53, 0x25, 0xcc, 0x09, 0x6e, 0x18, 0x94, 0x1c, 0xb1, 0x15, + 0xee, 0x3e, 0x3d, 0xbb, 0x94, 0x3c, 0xfb, 0xee, 0x05, 0xf1, 0x99, 0xd3, + 0x68, 0x97, 0x0e, 0x45, 0x0f, 0x1a, 0x6a, 0x27, 0x8e, 0x98, 0xfa, 0xc4, + 0xef, 0x1c, 0xc6, 0xd0, 0x77, 0x50, 0x8f, 0x55, 0x19, 0x7d, 0xe8, 0x32, + 0xe6, 0x61, 0x5b, 0x92, 0x26, 0x52, 0x49, 0xbd, 0xb5, 0xc3, 0xd1, 0x8b, + 0x3b, 0x02, 0xb5, 0x1b, 0xdf, 0x25, 0x97, 0xf3, 0x10, 0x53, 0x92, 0xe3, + 0x23, 0xcc, 0x5f, 0x7b, 0xb1, 0xe1, 0xe1, 0x08, 0xd6, 0xef, 0x32, 0xd1, + 0x93, 0x1c, 0xa1, 0x6c, 0x3f, 0x2c, 0x97, 0xbd, 0x34, 0x2d, 0xa1, 0xf8, + 0xb5, 0x2a, 0x02, 0x51, 0xf6, 0xd9, 0xa8, 0x46, 0x02, 0x7e, 0x55, 0x61, + 0xf4, 0x1f, 0x77, 0xa2, 0x9b, 0x65, 0xfa, 0x52, 0xb4, 0xb9, 0xa4, 0x9b, + 0xf1, 0x72, 0x16, 0x86, 0xc7, 0x7c, 0xd8, 0x37, 0xe6, 0xc1, 0xd0, 0x98, + 0xc6, 0xa3, 0x14, 0x0f, 0x0d, 0xc8, 0x9e, 0x14, 0x2f, 0x9e, 0xd8, 0xeb, + 0xc6, 0xa6, 0x07, 0x3c, 0x98, 0x13, 0x99, 0x8e, 0xbd, 0x7b, 0x4b, 0xb1, + 0x9b, 0xd7, 0xab, 0x16, 0xfa, 0xf1, 0x38, 0xaf, 0xf7, 0x3f, 0xe0, 0xe2, + 0x3c, 0x5c, 0x8c, 0x03, 0x34, 0xec, 0xa1, 0xb1, 0x32, 0xa4, 0x06, 0x68, + 0xf2, 0xe4, 0xac, 0x6f, 0x31, 0xc3, 0x18, 0xdd, 0xcb, 0xd8, 0xf8, 0xb0, + 0x89, 0x04, 0xfb, 0xd9, 0x4e, 0x5d, 0xf5, 0x10, 0xd7, 0x36, 0x8c, 0x09, + 0xc6, 0xaf, 0xc2, 0x35, 0x7d, 0x7a, 0x73, 0x93, 0x62, 0x44, 0x17, 0xd9, + 0xfb, 0xb4, 0xe4, 0xbd, 0xad, 0x55, 0x68, 0x4c, 0xe8, 0x66, 0x13, 0x3a, + 0x71, 0x8c, 0xe3, 0xfe, 0x7f, 0xe8, 0xb7, 0x8b, 0x1d, 0x7a, 0xef, 0xd5, + 0xea, 0x41, 0xec, 0xc8, 0x1c, 0x22, 0x57, 0x07, 0xc2, 0x7b, 0x0e, 0x92, + 0xbf, 0x1d, 0x21, 0xfe, 0xbc, 0x6e, 0xf9, 0x0c, 0x15, 0xd7, 0xdf, 0x6f, + 0x84, 0xdf, 0x53, 0x02, 0x1b, 0x7f, 0x45, 0x1d, 0x7c, 0x7e, 0xaf, 0x8a, + 0xeb, 0x76, 0x2c, 0x46, 0x3a, 0x14, 0xc5, 0xf6, 0x45, 0x2a, 0xae, 0x7d, + 0xf8, 0x20, 0x71, 0x7f, 0xc2, 0xe6, 0xc9, 0xd9, 0xf4, 0x7d, 0x08, 0xf6, + 0xc9, 0x9a, 0xbc, 0x9b, 0xf1, 0xbb, 0x1c, 0xc7, 0xfb, 0x3b, 0xe9, 0xb7, + 0xe5, 0x38, 0x3a, 0x74, 0x90, 0xf6, 0x58, 0x8e, 0x23, 0xfd, 0xc6, 0xc4, + 0x4f, 0x1d, 0xe5, 0x78, 0x82, 0xe7, 0x3b, 0x78, 0xbe, 0x70, 0xc0, 0xe8, + 0xef, 0x50, 0xcb, 0xb1, 0x60, 0x4f, 0x03, 0xfa, 0x93, 0x62, 0x9b, 0x1a, + 0x36, 0x8e, 0xd5, 0xe7, 0x75, 0x2f, 0x3a, 0xf7, 0xe2, 0x4e, 0xea, 0xea, + 0x8e, 0x1d, 0x9d, 0xec, 0xcf, 0x47, 0x9d, 0x1f, 0xc4, 0x43, 0xcc, 0xeb, + 0xb6, 0x25, 0x7d, 0x38, 0x9d, 0x32, 0xfc, 0x5f, 0x52, 0x0c, 0xb3, 0x44, + 0x09, 0x68, 0xc7, 0xe1, 0xc3, 0xc9, 0x4c, 0x29, 0xba, 0x07, 0x66, 0xe1, + 0xa7, 0xb4, 0xcf, 0x07, 0x1f, 0x90, 0xfe, 0x26, 0x18, 0x1f, 0x66, 0xe3, + 0x89, 0x11, 0x93, 0x6d, 0xcb, 0x3c, 0x49, 0xcc, 0xe9, 0x81, 0x2b, 0x25, + 0xbe, 0x11, 0xdd, 0x41, 0xb3, 0x20, 0x26, 0x1e, 0x46, 0xa6, 0x5f, 0xef, + 0xbd, 0x41, 0x15, 0x5e, 0xad, 0x52, 0x97, 0x0e, 0x4c, 0x6a, 0x7a, 0xbc, + 0x4a, 0x8d, 0xf7, 0x33, 0x7f, 0x8d, 0x57, 0xab, 0x87, 0xf1, 0x44, 0xbf, + 0x13, 0xf3, 0x16, 0xaa, 0xbc, 0x1e, 0x3f, 0xc3, 0xd8, 0x16, 0x9f, 0xa3, + 0x9a, 0xd8, 0x6d, 0xcb, 0x8a, 0x78, 0x11, 0xb9, 0x7d, 0xe5, 0xc2, 0x5a, + 0xc6, 0x2f, 0x87, 0xd8, 0x5e, 0xac, 0x5c, 0x75, 0x52, 0xef, 0x27, 0x31, + 0x42, 0xbb, 0x7e, 0x94, 0xc7, 0x81, 0x41, 0xab, 0x73, 0x39, 0x39, 0xf7, + 0xc5, 0x01, 0xab, 0xf3, 0x06, 0xd3, 0xf0, 0x15, 0xa9, 0x81, 0xe8, 0xdd, + 0x38, 0x89, 0xfd, 0x23, 0x52, 0x06, 0x6e, 0x6f, 0x84, 0x79, 0x75, 0xd2, + 0xea, 0xdc, 0x61, 0x5e, 0x8c, 0x06, 0x3b, 0x37, 0xfe, 0x55, 0x79, 0x0e, + 0x33, 0xc5, 0x8f, 0x64, 0x0d, 0x64, 0x12, 0xbf, 0x62, 0x3b, 0xef, 0x0d, + 0x56, 0x62, 0x5a, 0xb5, 0xf8, 0xc1, 0x09, 0xbc, 0xdd, 0xff, 0x22, 0x4e, + 0xf7, 0x5b, 0x58, 0x10, 0xb2, 0xe0, 0x0c, 0xd5, 0x99, 0x4d, 0xea, 0x65, + 0xc4, 0x08, 0x05, 0xd7, 0xcc, 0x7d, 0x09, 0xef, 0xd0, 0xff, 0xaf, 0x9d, + 0x6b, 0xd9, 0xb2, 0xf4, 0x61, 0xa1, 0xb5, 0xbd, 0x46, 0xfc, 0xc6, 0xb4, + 0xf7, 0xf5, 0x7c, 0x72, 0x1e, 0x5c, 0xd8, 0xb7, 0x26, 0xb9, 0xf0, 0x49, + 0x0c, 0x0f, 0x1a, 0xd1, 0x75, 0x05, 0x39, 0xfb, 0x4f, 0x52, 0x07, 0x16, + 0x76, 0x98, 0x47, 0x1f, 0xae, 0xc2, 0xbc, 0x33, 0xcc, 0x1a, 0xaf, 0x98, + 0x43, 0xdb, 0x59, 0xb0, 0x30, 0x60, 0x2e, 0x53, 0xdf, 0xa4, 0x9f, 0x9e, + 0xc4, 0xbe, 0xa1, 0x02, 0x5e, 0xfb, 0xd0, 0x44, 0x3f, 0xcf, 0xed, 0x65, + 0xf7, 0xa2, 0x31, 0x75, 0xc8, 0x5e, 0x7f, 0x38, 0x40, 0x7c, 0xcc, 0x3d, + 0xd3, 0xd4, 0x30, 0x92, 0x69, 0x22, 0x36, 0x44, 0xf1, 0xcf, 0x99, 0x08, + 0xf1, 0x21, 0x4c, 0x7c, 0x68, 0x20, 0x3e, 0x98, 0xc4, 0x87, 0x7a, 0xe2, + 0x43, 0xd0, 0x7e, 0xd6, 0x2f, 0x6b, 0xe6, 0x43, 0xa3, 0x2f, 0xa2, 0x68, + 0xe0, 0x04, 0x5c, 0xf4, 0x81, 0xe3, 0xa6, 0x45, 0x7e, 0x52, 0xa7, 0xad, + 0xc1, 0xc5, 0x4a, 0x54, 0xf3, 0x62, 0x28, 0x73, 0x02, 0x25, 0x03, 0x1a, + 0xc7, 0x22, 0xfb, 0x33, 0x6a, 0xc3, 0xbd, 0xc4, 0xea, 0x5f, 0x1b, 0x75, + 0xbd, 0x5e, 0xd4, 0xed, 0xae, 0x81, 0xd1, 0xbf, 0x50, 0x9d, 0xab, 0x44, + 0xbf, 0xe0, 0xe5, 0x38, 0xab, 0x31, 0xfb, 0x01, 0x0d, 0x73, 0x78, 0xfc, + 0x53, 0xaa, 0x76, 0xe2, 0x75, 0x07, 0xbc, 0x33, 0x48, 0x77, 0x66, 0x92, + 0x09, 0x90, 0xd5, 0x7a, 0x7d, 0xb8, 0xe4, 0xc0, 0x49, 0x55, 0x41, 0xf6, + 0x0b, 0x12, 0xf3, 0xea, 0x82, 0x3d, 0xaa, 0x2a, 0x6b, 0x48, 0xc4, 0x70, + 0x1e, 0x2a, 0x22, 0x64, 0x11, 0xb3, 0x98, 0x5f, 0x58, 0x6b, 0xcc, 0x12, + 0x6c, 0xae, 0x57, 0x65, 0x6f, 0xc8, 0x21, 0x89, 0x51, 0x33, 0x18, 0x23, + 0x4a, 0x93, 0xf1, 0xdb, 0x66, 0xc0, 0x83, 0x92, 0xa4, 0x65, 0x3d, 0x16, + 0xd2, 0xe0, 0x89, 0x04, 0xa2, 0x1b, 0x98, 0x46, 0x7e, 0x61, 0x5e, 0x18, + 0xd7, 0x64, 0x0e, 0x60, 0x80, 0xe3, 0x5b, 0x9e, 0x29, 0xbc, 0xe3, 0xf9, + 0xc9, 0x7f, 0xe7, 0xde, 0x15, 0xbd, 0x64, 0xf7, 0x0c, 0x18, 0xda, 0x5d, + 0x6a, 0xbc, 0x92, 0x1c, 0xfc, 0x00, 0xe3, 0x9e, 0x32, 0x79, 0xa3, 0x82, + 0xd6, 0x81, 0x38, 0xa6, 0x85, 0x7e, 0xa0, 0xc4, 0xaa, 0x75, 0xbf, 0x5f, + 0xa9, 0xc6, 0x8d, 0x0f, 0x50, 0xd7, 0x0b, 0x26, 0x68, 0x2b, 0x3e, 0x7c, + 0x67, 0x54, 0x74, 0x5b, 0x3b, 0xb4, 0x83, 0xe3, 0x98, 0x98, 0x7b, 0x40, + 0x70, 0xf2, 0xa0, 0x1b, 0x8e, 0x83, 0xd3, 0x99, 0x9b, 0xd6, 0xcf, 0xbd, + 0xa4, 0xe3, 0xdf, 0x54, 0xd1, 0x8b, 0xf0, 0x6b, 0xbd, 0x3f, 0xae, 0x18, + 0xda, 0x2f, 0x95, 0x03, 0xe4, 0x6c, 0x5e, 0x3c, 0x96, 0x39, 0x4c, 0x5d, + 0xee, 0xcf, 0xe7, 0x4b, 0xab, 0x90, 0xe8, 0x93, 0x7d, 0x81, 0x27, 0x30, + 0x7b, 0x40, 0x6f, 0xd9, 0xaa, 0x18, 0xc1, 0x6b, 0x95, 0x13, 0x98, 0x39, + 0x10, 0xe4, 0x5c, 0x6a, 0x58, 0x96, 0x2c, 0xe0, 0xa7, 0x60, 0xf0, 0x2a, + 0x62, 0xb0, 0xb5, 0xf8, 0xa7, 0x66, 0x9c, 0x39, 0x8e, 0x6e, 0x3a, 0x15, + 0xbd, 0x75, 0xae, 0x22, 0xfb, 0x80, 0x8c, 0x33, 0x6d, 0xac, 0xe3, 0x19, + 0xa8, 0xc7, 0x57, 0x39, 0xe6, 0x66, 0xce, 0xdb, 0x8b, 0x0b, 0x2d, 0x2c, + 0x5a, 0xa8, 0xef, 0x2e, 0x71, 0x44, 0xef, 0xaa, 0x42, 0xb6, 0xa3, 0x86, + 0x76, 0x73, 0xc7, 0x02, 0x3d, 0xfc, 0x03, 0xe2, 0x2e, 0x71, 0x1a, 0xdd, + 0x8c, 0x3b, 0x6b, 0x18, 0x8b, 0x4a, 0x23, 0x7a, 0x2f, 0x73, 0xd4, 0xf7, + 0x6e, 0x75, 0x44, 0x43, 0xf2, 0x1e, 0xd1, 0xdf, 0x63, 0x31, 0xdc, 0xa1, + 0x0a, 0xe2, 0xa0, 0x9e, 0x7d, 0x11, 0xfa, 0xee, 0xaf, 0x92, 0x93, 0xfe, + 0x98, 0xfc, 0xae, 0xe6, 0xd2, 0x43, 0xc4, 0xa8, 0x11, 0x3c, 0x98, 0x39, + 0x88, 0xdd, 0x99, 0x34, 0x76, 0x66, 0xb6, 0x29, 0x43, 0xf6, 0xb3, 0x45, + 0x45, 0xde, 0x99, 0x8b, 0x56, 0x28, 0x5f, 0x46, 0x79, 0xe8, 0x5b, 0xd6, + 0x50, 0x95, 0x8a, 0xca, 0x50, 0x10, 0xd7, 0x24, 0xe3, 0x70, 0x44, 0xde, + 0xb5, 0xe4, 0x7d, 0xed, 0xf5, 0xe3, 0x06, 0xae, 0x4e, 0x96, 0x22, 0xb6, + 0xc7, 0xb2, 0x7a, 0x1b, 0x9c, 0x58, 0x3b, 0x5e, 0x8f, 0x65, 0x03, 0x0f, + 0x59, 0x73, 0x18, 0x73, 0x3e, 0xbc, 0xdc, 0x83, 0x5b, 0xf7, 0x78, 0xd0, + 0x96, 0x8c, 0xc2, 0x17, 0x29, 0xe3, 0xef, 0x80, 0xb9, 0x04, 0xc6, 0xc4, + 0x04, 0x8c, 0xde, 0xab, 0x1c, 0x81, 0xfd, 0x61, 0xd5, 0x83, 0xbf, 0x21, + 0x8e, 0x2f, 0x27, 0xee, 0xc4, 0xc6, 0x2d, 0x54, 0x46, 0xbc, 0xb8, 0x8d, + 0xf5, 0xaf, 0xe3, 0xdc, 0xbf, 0xb3, 0x68, 0x3f, 0xb1, 0x40, 0xf6, 0x42, + 0x6a, 0xd8, 0x30, 0xee, 0xa6, 0xae, 0xdc, 0x88, 0xed, 0xab, 0xc6, 0xd5, + 0x0f, 0xf8, 0x71, 0xeb, 0xb8, 0x07, 0x8d, 0x49, 0x6b, 0xf1, 0x01, 0x33, + 0xbe, 0x52, 0x83, 0x81, 0xb6, 0x71, 0x2f, 0xbe, 0x92, 0xd4, 0x7d, 0xd7, + 0x32, 0xe7, 0x1f, 0x31, 0x83, 0xf8, 0x5f, 0xe3, 0x3e, 0xdc, 0x94, 0x3c, + 0x2a, 0x79, 0xe4, 0x12, 0x27, 0x63, 0xcf, 0xbd, 0xe3, 0xb3, 0xb0, 0x32, + 0xa9, 0x9f, 0x99, 0x20, 0xb7, 0xeb, 0xdc, 0x67, 0xe2, 0xae, 0x71, 0x15, + 0xad, 0x6c, 0xe7, 0xc6, 0xe4, 0x6c, 0x74, 0xec, 0x6b, 0xa0, 0x0c, 0x0b, + 0xb1, 0x7c, 0xc0, 0x09, 0x93, 0x2c, 0x1e, 0x5f, 0x04, 0x5a, 0x06, 0x26, + 0x98, 0xc7, 0xdd, 0x87, 0xed, 0x7d, 0x26, 0x6e, 0x1f, 0x97, 0xf3, 0x83, + 0xf6, 0x3b, 0xae, 0xef, 0x3d, 0xbc, 0x10, 0x9f, 0x1f, 0x50, 0x89, 0x03, + 0xc5, 0x18, 0x5a, 0xa9, 0xe0, 0x2b, 0xbc, 0xbe, 0x35, 0x25, 0x7b, 0x90, + 0x81, 0xd0, 0x8e, 0xc0, 0xfe, 0x2a, 0x72, 0x86, 0x45, 0x0f, 0xe7, 0xae, + 0x3f, 0x48, 0x9c, 0x2f, 0x21, 0xce, 0x97, 0x91, 0xc3, 0x5e, 0x35, 0x7c, + 0x10, 0xf7, 0x13, 0x97, 0x0f, 0x0d, 0x74, 0x32, 0xee, 0x94, 0xe3, 0x71, + 0xc6, 0x81, 0x24, 0xcf, 0x4f, 0xec, 0x30, 0x3a, 0x4a, 0x88, 0xd3, 0x3f, + 0x20, 0xfe, 0xf6, 0x12, 0x33, 0xee, 0x48, 0x32, 0xdc, 0xef, 0x60, 0x0e, + 0x70, 0x69, 0x74, 0xbe, 0x87, 0x39, 0xd6, 0xb5, 0x4a, 0xc0, 0xf7, 0x26, + 0xca, 0xe1, 0x78, 0xb8, 0x1a, 0x8d, 0x0f, 0x48, 0x19, 0xc1, 0x2f, 0x15, + 0xea, 0x5e, 0x27, 0x75, 0x7e, 0x18, 0x56, 0xbf, 0x83, 0xe3, 0xad, 0x35, + 0xc9, 0xc0, 0xf1, 0x9a, 0xa9, 0x6b, 0xff, 0x4c, 0xac, 0x7d, 0x9f, 0x98, + 0xea, 0x9f, 0xd1, 0x80, 0x26, 0xc3, 0xe4, 0x71, 0x18, 0x27, 0xfb, 0x0d, + 0x53, 0xf6, 0xe4, 0xbd, 0x4e, 0x9e, 0x37, 0x39, 0x83, 0x31, 0xd3, 0x10, + 0x3f, 0x1c, 0xe1, 0x78, 0x54, 0xc9, 0x4b, 0xe0, 0x18, 0x03, 0xde, 0x7e, + 0x78, 0x31, 0xc7, 0x25, 0xb1, 0x54, 0xe2, 0xdd, 0x08, 0x65, 0x5d, 0x8c, + 0x15, 0xd4, 0x47, 0x53, 0x52, 0x45, 0x7a, 0x5f, 0x04, 0xb7, 0xef, 0xca, + 0xc5, 0xe1, 0x8d, 0xa1, 0xf8, 0x0d, 0x8c, 0xc3, 0xe1, 0x52, 0xc6, 0x61, + 0x57, 0x44, 0x64, 0x73, 0x62, 0x98, 0x71, 0x7b, 0x73, 0x2a, 0x8c, 0x66, + 0xce, 0xe1, 0x44, 0x9a, 0xfd, 0x26, 0x67, 0xe1, 0x78, 0xda, 0xc3, 0x98, + 0xa5, 0xf1, 0x20, 0xaa, 0x8d, 0x4c, 0xe7, 0xe1, 0xe7, 0x71, 0x31, 0x0f, + 0xc3, 0xbe, 0xb6, 0x26, 0xa9, 0x20, 0xde, 0xa2, 0xd8, 0x7c, 0xfe, 0x78, + 0x5a, 0xb0, 0x59, 0xd6, 0x32, 0xef, 0xae, 0x94, 0x3d, 0xa8, 0xfd, 0xa9, + 0x97, 0x50, 0x49, 0x7c, 0xaa, 0xc8, 0xe3, 0xd0, 0xcf, 0x42, 0x82, 0xbb, + 0xb5, 0xc4, 0x5d, 0xd9, 0x4f, 0x64, 0x59, 0xab, 0x02, 0x53, 0xf1, 0xe8, + 0xff, 0xfb, 0x30, 0x6a, 0xef, 0xab, 0x15, 0x4c, 0x22, 0xfe, 0xa5, 0x88, + 0x7f, 0x1c, 0x43, 0xd7, 0x95, 0xc4, 0x40, 0xca, 0xf4, 0x8f, 0x29, 0x62, + 0x20, 0x71, 0xfa, 0x20, 0x71, 0xfa, 0xdb, 0xc4, 0xe9, 0x6f, 0x11, 0xa7, + 0x1f, 0x27, 0x26, 0xe4, 0xd6, 0xf4, 0x9a, 0xe5, 0xb9, 0x0a, 0xe7, 0xe3, + 0x1d, 0x7b, 0x6d, 0xb1, 0x86, 0xba, 0x9a, 0x3d, 0xa0, 0x60, 0x8e, 0xa1, + 0xef, 0x17, 0xbb, 0xff, 0x31, 0xe7, 0xc9, 0x3f, 0x2d, 0xb7, 0xe7, 0xb7, + 0x29, 0xd9, 0x03, 0x77, 0xb2, 0x4e, 0xeb, 0x85, 0xfd, 0x0d, 0x01, 0x53, + 0xb8, 0x68, 0x51, 0x72, 0x0d, 0x1c, 0xc9, 0xba, 0xfd, 0xc7, 0xe4, 0xf9, + 0xed, 0x74, 0xc9, 0xeb, 0xd7, 0xc8, 0x1e, 0xed, 0xfd, 0xb2, 0x37, 0x6c, + 0x19, 0xef, 0xb9, 0x92, 0x75, 0xe6, 0x9b, 0xb0, 0xb1, 0xcd, 0x3f, 0x69, + 0xdf, 0xab, 0x7d, 0xef, 0x7e, 0xea, 0x2b, 0xcb, 0x36, 0xd3, 0x29, 0xd9, + 0x17, 0x3b, 0x0b, 0x8f, 0x66, 0xe4, 0x77, 0x5d, 0x6b, 0x42, 0xdd, 0x8f, + 0x58, 0x8d, 0xf0, 0xf1, 0x30, 0xae, 0x4f, 0x7a, 0x68, 0x07, 0x71, 0x54, + 0xd0, 0xb7, 0xbe, 0x36, 0xde, 0x40, 0x5f, 0x7b, 0xc8, 0xd2, 0x22, 0x81, + 0xd6, 0x71, 0x72, 0x9e, 0xf5, 0xe3, 0x8b, 0xb1, 0x74, 0xc0, 0xb2, 0x3c, + 0x97, 0x19, 0xe1, 0x0d, 0x8a, 0x1f, 0x2e, 0xfa, 0xa0, 0x83, 0x7e, 0xb5, + 0x6e, 0x4f, 0x40, 0x7b, 0x93, 0x78, 0xda, 0xde, 0x70, 0x80, 0xf6, 0x61, + 0x9c, 0x69, 0x26, 0x96, 0x3a, 0x23, 0x01, 0xe6, 0x89, 0x1e, 0xda, 0xbe, + 0x17, 0x67, 0x12, 0xe2, 0x5f, 0x7a, 0xc7, 0x3f, 0x33, 0x37, 0xe9, 0xa0, + 0x6f, 0xfc, 0x32, 0x31, 0x8b, 0x3e, 0xe0, 0xc6, 0xdb, 0x09, 0x83, 0xfe, + 0xe6, 0xc1, 0x3b, 0x89, 0x7a, 0xf6, 0x15, 0x64, 0x19, 0x3f, 0xee, 0x1c, + 0x0f, 0xd3, 0xcf, 0xae, 0xe4, 0x21, 0xef, 0x53, 0xd7, 0xc6, 0xbf, 0xa3, + 0xd4, 0xf6, 0xcf, 0x56, 0xab, 0x10, 0xad, 0xd6, 0xf0, 0xf5, 0xf1, 0xcf, + 0xe2, 0x3f, 0x18, 0xb7, 0xd7, 0x26, 0xc1, 0x39, 0x44, 0x88, 0x3c, 0x70, + 0x62, 0x9f, 0x3c, 0x4b, 0x44, 0x5d, 0x74, 0xae, 0x43, 0x67, 0x6e, 0xab, + 0x67, 0x4f, 0x3b, 0x9c, 0xec, 0x93, 0xac, 0x98, 0x65, 0x7f, 0xd9, 0x5f, + 0x8a, 0xbb, 0xf6, 0x1c, 0xa0, 0x8f, 0x14, 0x61, 0xc1, 0xfd, 0x6e, 0x7c, + 0x7d, 0xdf, 0x08, 0xb9, 0x83, 0x8a, 0x99, 0xcc, 0x95, 0x86, 0x48, 0x14, + 0x66, 0x0e, 0x47, 0x70, 0xdb, 0xae, 0x11, 0x0c, 0xe4, 0x79, 0x5e, 0x28, + 0x14, 0xff, 0x9f, 0x2a, 0x0e, 0x90, 0x47, 0x04, 0xda, 0x3f, 0x43, 0x1b, + 0xab, 0x88, 0x04, 0xe2, 0x32, 0xee, 0x16, 0xda, 0x58, 0x0f, 0xe7, 0x33, + 0xcd, 0x71, 0x24, 0x68, 0x63, 0x8f, 0x51, 0xfe, 0xed, 0xb4, 0xb1, 0x38, + 0x6d, 0x2c, 0x4e, 0x7b, 0x8a, 0xd3, 0xc6, 0xe4, 0x9d, 0xfd, 0x38, 0x6d, + 0x2c, 0x4e, 0x1b, 0x8b, 0xa7, 0x17, 0x63, 0x94, 0x4c, 0x63, 0xcb, 0x48, + 0x03, 0x71, 0x4c, 0xb1, 0xa3, 0x52, 0xf6, 0x86, 0xcf, 0x92, 0xb3, 0x5f, + 0xc5, 0x43, 0x41, 0x33, 0x7d, 0xb2, 0x77, 0x68, 0x84, 0x9c, 0xc7, 0x8d, + 0xdf, 0x64, 0x84, 0xe3, 0x37, 0x30, 0x8f, 0x3d, 0x4c, 0x9e, 0xaf, 0xe2, + 0x49, 0x53, 0xf2, 0x60, 0x93, 0xe7, 0x8c, 0x35, 0x29, 0xe1, 0x6b, 0x87, + 0x71, 0x47, 0x3f, 0x70, 0x2d, 0x79, 0x61, 0x35, 0x79, 0xc9, 0xde, 0x05, + 0xfc, 0xfd, 0xf0, 0x01, 0xda, 0xbc, 0xf8, 0x63, 0x6e, 0xaf, 0xeb, 0xf1, + 0xfe, 0x5a, 0xdf, 0xd5, 0xf4, 0xc1, 0x7b, 0x59, 0xd7, 0xf9, 0xb0, 0xd4, + 0x39, 0xc0, 0xb6, 0xf5, 0xf0, 0x6f, 0x38, 0xff, 0xad, 0xf7, 0x57, 0xe3, + 0xed, 0x5d, 0x7a, 0xf8, 0x7d, 0x62, 0x5e, 0xb5, 0xc3, 0x5a, 0xfc, 0x99, + 0x50, 0x60, 0xe3, 0x67, 0xd4, 0x1c, 0xdf, 0x6b, 0xd9, 0xe1, 0xc4, 0xfe, + 0xd0, 0x62, 0x78, 0x16, 0x14, 0x38, 0x1f, 0x6d, 0xa9, 0x5a, 0x38, 0x96, + 0x1e, 0x3e, 0x4d, 0xae, 0x92, 0x64, 0xfb, 0xa3, 0xe9, 0x23, 0xc4, 0x90, + 0xfb, 0xf0, 0x02, 0xf3, 0xf3, 0x91, 0x4f, 0xbf, 0x4e, 0xee, 0xe8, 0xc6, + 0x18, 0x39, 0xe0, 0x81, 0xfe, 0xe8, 0xe7, 0x9c, 0xc4, 0x7d, 0xcf, 0x82, + 0x72, 0xa4, 0x87, 0x84, 0x2b, 0x96, 0xe3, 0xd9, 0x7e, 0x43, 0xbb, 0x56, + 0xc9, 0xf1, 0xc2, 0x2d, 0x3c, 0x7f, 0xb3, 0xdf, 0x38, 0x33, 0x8c, 0xc0, + 0xc4, 0x69, 0x72, 0xc3, 0xf7, 0x87, 0x24, 0x86, 0x1d, 0xa4, 0x8f, 0xfb, + 0x11, 0x4e, 0x6a, 0x38, 0x34, 0x66, 0x60, 0x7e, 0xd2, 0x8b, 0x47, 0xc6, + 0x82, 0xf8, 0x0c, 0x7d, 0x37, 0x43, 0x7e, 0xf8, 0xe9, 0xa4, 0xf8, 0xe2, + 0x2c, 0x8c, 0x8f, 0xcd, 0xb2, 0xf7, 0x54, 0x7a, 0x8c, 0x5f, 0xc0, 0x53, + 0x2d, 0x3e, 0x49, 0x6e, 0x9d, 0xd2, 0x7b, 0x63, 0x1c, 0x4f, 0xcc, 0xab, + 0xef, 0x8f, 0x41, 0x1f, 0x02, 0xae, 0xf8, 0x70, 0xe8, 0x8b, 0x12, 0x1f, + 0xc5, 0x1f, 0x35, 0x8c, 0x93, 0xef, 0x14, 0x13, 0x53, 0x4b, 0x23, 0xb5, + 0xef, 0xbd, 0xac, 0xe8, 0xd9, 0xa7, 0x55, 0xcb, 0x7a, 0x69, 0xa1, 0x06, + 0xdf, 0x3e, 0x8d, 0xdc, 0xc3, 0x64, 0xec, 0x16, 0x3f, 0xd5, 0x30, 0xe3, + 0x81, 0x6a, 0x4c, 0x7b, 0x20, 0x89, 0xbf, 0xad, 0x8e, 0x7f, 0x6e, 0x3a, + 0xe3, 0xfc, 0x74, 0xe2, 0x7a, 0x65, 0xf2, 0xd8, 0x0c, 0x37, 0xf9, 0xf2, + 0x84, 0x5a, 0xd7, 0xba, 0x1f, 0xfa, 0xfe, 0x93, 0x8a, 0xee, 0x7b, 0x8c, + 0xb1, 0xc1, 0x45, 0x1b, 0x75, 0x8c, 0x6b, 0xf4, 0xdd, 0xba, 0x43, 0xd3, + 0x60, 0xc4, 0x2f, 0x57, 0x5d, 0x16, 0x6c, 0x79, 0xae, 0xa8, 0xcc, 0xe5, + 0x45, 0x82, 0x3b, 0x12, 0x17, 0x1c, 0xb2, 0xff, 0x13, 0xed, 0xf4, 0x97, + 0x15, 0x76, 0x2c, 0x3a, 0x60, 0xef, 0x8f, 0xdb, 0x30, 0x1e, 0xa7, 0x8f, + 0x2c, 0x46, 0xd9, 0x80, 0x07, 0x5f, 0xb3, 0xe3, 0xd0, 0x43, 0x56, 0x15, + 0xfd, 0xe5, 0xf6, 0x3d, 0x81, 0xf6, 0xab, 0xe9, 0x2f, 0xb5, 0x97, 0x49, + 0x0c, 0x63, 0xdc, 0x4e, 0x19, 0xe6, 0x30, 0xb1, 0xe5, 0xa1, 0x06, 0x63, + 0xe2, 0x75, 0xe4, 0x7c, 0x66, 0x6b, 0x5f, 0x35, 0xfe, 0xe1, 0xfe, 0xfd, + 0xf6, 0x5a, 0xc8, 0x6d, 0x3c, 0x4f, 0xf6, 0xf9, 0x6c, 0xff, 0x88, 0xf1, + 0xf7, 0x9d, 0x8c, 0x79, 0x31, 0xfa, 0xd1, 0x96, 0x3e, 0x6b, 0xf1, 0xf7, + 0x17, 0xc6, 0x57, 0x56, 0x20, 0xc8, 0x98, 0xe4, 0x46, 0x6f, 0x9f, 0xde, + 0xdf, 0xca, 0x18, 0x74, 0x62, 0xa1, 0x49, 0x59, 0x3c, 0xd8, 0xd1, 0x27, + 0x98, 0x7a, 0xf4, 0xa6, 0x6a, 0xc4, 0xff, 0xa7, 0xc6, 0xf1, 0x7d, 0xcd, + 0x7e, 0xf6, 0x37, 0x0b, 0x6b, 0xf7, 0x5d, 0x46, 0x99, 0xeb, 0xe9, 0x83, + 0xcc, 0xab, 0x99, 0xef, 0xac, 0xde, 0x25, 0x7e, 0x81, 0x46, 0xc9, 0xd3, + 0x3a, 0xcd, 0x80, 0xf9, 0x06, 0x7d, 0xa8, 0x88, 0x5c, 0xe7, 0x41, 0x62, + 0x59, 0x31, 0x21, 0xb3, 0xcc, 0x08, 0x63, 0x21, 0x6d, 0x54, 0xde, 0xe1, + 0x98, 0x46, 0x5e, 0x37, 0x9f, 0xf3, 0x51, 0x92, 0xf1, 0x00, 0xe4, 0x10, + 0x20, 0x3e, 0x61, 0x94, 0x20, 0x38, 0xea, 0xe7, 0x71, 0x31, 0x0f, 0x2a, + 0x22, 0xa3, 0xa2, 0x66, 0x94, 0x75, 0x87, 0x47, 0x6c, 0x5b, 0xfc, 0x07, + 0xce, 0x7b, 0x82, 0xb6, 0x7e, 0x23, 0xb1, 0x7e, 0x62, 0x27, 0xd0, 0xfb, + 0x70, 0xce, 0xb6, 0x53, 0x6c, 0xbf, 0x85, 0x98, 0xf7, 0x1e, 0x6d, 0xb6, + 0x87, 0xf3, 0xbd, 0x63, 0xd0, 0x08, 0xd6, 0xa9, 0x01, 0x6d, 0x9c, 0xf3, + 0xdc, 0x35, 0xa2, 0xa2, 0xaf, 0x7f, 0x31, 0x86, 0x99, 0x07, 0x75, 0x0f, + 0x89, 0x8f, 0x48, 0x99, 0xc3, 0xe8, 0xa4, 0x8f, 0xfc, 0x6a, 0xa1, 0x82, + 0xd8, 0x17, 0xe4, 0x1d, 0x51, 0x27, 0xf3, 0xfd, 0xfb, 0xb0, 0x36, 0x71, + 0xc4, 0x2a, 0x37, 0xf4, 0xde, 0x21, 0x95, 0x79, 0x16, 0x6d, 0xb3, 0x8b, + 0xf9, 0xc9, 0x12, 0xe6, 0x27, 0xdd, 0x79, 0xbb, 0x3c, 0x4e, 0x3b, 0xec, + 0x63, 0x1c, 0x7b, 0x7d, 0x28, 0x17, 0xf7, 0x7e, 0xbc, 0xc3, 0x8f, 0xf9, + 0x97, 0x97, 0xe3, 0x99, 0x87, 0x73, 0xb2, 0xed, 0xa4, 0x4d, 0x3e, 0x4d, + 0x3d, 0xdf, 0x4a, 0xbd, 0xbe, 0x92, 0x12, 0x8c, 0x0a, 0xe2, 0x59, 0xf2, + 0xe8, 0xf5, 0xe4, 0x02, 0x2f, 0xa5, 0x72, 0x36, 0xf9, 0xf5, 0xf1, 0x2b, + 0xab, 0x72, 0xf1, 0xc1, 0x0b, 0xf5, 0x01, 0x79, 0x27, 0xcf, 0xb2, 0x96, + 0x98, 0xd9, 0x76, 0xf2, 0x1a, 0xb6, 0x1d, 0x21, 0x37, 0x72, 0x62, 0x66, + 0x32, 0x82, 0xa5, 0xa9, 0xda, 0xe6, 0xb9, 0xb2, 0x89, 0x63, 0x66, 0x8e, + 0x03, 0xba, 0x92, 0xf2, 0xcd, 0x0f, 0x0d, 0x65, 0xcc, 0x9d, 0xfe, 0x26, + 0xff, 0x9d, 0x91, 0x1b, 0xff, 0x0c, 0xee, 0xb8, 0x82, 0x32, 0xa5, 0xc8, + 0x1d, 0x27, 0xf3, 0xdf, 0x19, 0xb9, 0xc1, 0xfe, 0xce, 0x88, 0x1b, 0xd3, + 0xc6, 0x9d, 0xce, 0x2f, 0xa5, 0x3c, 0x98, 0x31, 0x7e, 0x96, 0x83, 0xba, + 0x8b, 0x22, 0x4d, 0x78, 0x2a, 0xa1, 0x60, 0xba, 0xf1, 0xbf, 0xf1, 0xb2, + 0xbd, 0x26, 0x50, 0x8d, 0x99, 0x0f, 0xc8, 0x7a, 0x42, 0x54, 0xde, 0x89, + 0x69, 0x7e, 0x82, 0xe7, 0x25, 0xc4, 0xd3, 0x8a, 0x07, 0x14, 0x3c, 0x1d, + 0xf0, 0xa2, 0x98, 0xbf, 0x7d, 0xe4, 0x9a, 0xce, 0x85, 0xcb, 0xad, 0xcd, + 0xab, 0xc4, 0xbe, 0x39, 0x87, 0xfb, 0xa6, 0x55, 0x0a, 0x06, 0xee, 0x35, + 0x65, 0xdd, 0xd2, 0x40, 0x4f, 0xa2, 0x9a, 0xfc, 0xba, 0xb6, 0xbd, 0x09, + 0xb5, 0xe6, 0x2f, 0x1c, 0xd5, 0x28, 0xda, 0x77, 0x63, 0x95, 0xac, 0xd9, + 0x7f, 0x9b, 0x73, 0xd6, 0x4d, 0xec, 0xea, 0x4a, 0xe5, 0xe2, 0x67, 0x53, + 0xfa, 0x17, 0x9a, 0xe8, 0xa5, 0x9b, 0xfc, 0x44, 0x4d, 0x9e, 0xb2, 0xcb, + 0x94, 0x45, 0x0e, 0x11, 0x7f, 0x66, 0xe1, 0x10, 0xf3, 0x1a, 0x89, 0xa5, + 0x65, 0x3c, 0xca, 0xc9, 0x1b, 0x7f, 0xc9, 0x58, 0x7a, 0x67, 0x28, 0x1b, + 0x94, 0x2f, 0xd0, 0x54, 0x91, 0x8b, 0xd3, 0x07, 0xb0, 0x2f, 0xa4, 0xb7, + 0xac, 0x76, 0x44, 0x9f, 0x61, 0x0e, 0x16, 0x5e, 0xcc, 0x9c, 0x7c, 0x79, + 0x60, 0x04, 0x5b, 0xc9, 0x03, 0xb7, 0x30, 0x17, 0x6f, 0xa5, 0x6d, 0xb6, + 0xef, 0x62, 0x6c, 0x73, 0x9c, 0xcb, 0xc5, 0xb5, 0x50, 0x7c, 0x35, 0x39, + 0x40, 0x87, 0x47, 0x15, 0x7b, 0x15, 0xdf, 0x09, 0xb4, 0xbe, 0x41, 0x8c, + 0xae, 0x63, 0xdc, 0x10, 0x7b, 0xdf, 0x9e, 0xd2, 0xdb, 0xa9, 0x80, 0xaa, + 0x72, 0xe6, 0x8e, 0x77, 0x8d, 0x35, 0xd0, 0x6f, 0xac, 0x4e, 0x37, 0xed, + 0xda, 0xb9, 0x68, 0x16, 0x73, 0xce, 0xab, 0xd0, 0xbd, 0x83, 0xf6, 0x4f, + 0x5f, 0xba, 0xb7, 0x0f, 0xe4, 0x67, 0xea, 0x16, 0xce, 0x5f, 0x76, 0x1f, + 0x02, 0x67, 0x5a, 0x50, 0xd7, 0x5c, 0xe4, 0x10, 0x19, 0xf4, 0x96, 0xb7, + 0xc9, 0xd3, 0x3a, 0x98, 0x9f, 0xae, 0x67, 0x2e, 0x1f, 0x63, 0x2e, 0x1f, + 0x63, 0xbd, 0xd4, 0x0e, 0x79, 0x4e, 0x64, 0xb4, 0x1c, 0x67, 0xfe, 0xf3, + 0x35, 0xf2, 0x9f, 0x1d, 0xf7, 0x8b, 0x5c, 0xd3, 0x71, 0xd7, 0xde, 0xab, + 0x90, 0xa4, 0x3d, 0xdd, 0xc9, 0x6b, 0x7d, 0xf7, 0x5f, 0x8c, 0x3b, 0x98, + 0xc7, 0xc7, 0xc6, 0x16, 0xa3, 0x9f, 0x99, 0xe8, 0xc6, 0xbd, 0x9f, 0x45, + 0x17, 0xf9, 0xd4, 0x12, 0x62, 0xf4, 0xea, 0x87, 0x47, 0x6c, 0xcc, 0x16, + 0xcc, 0x7f, 0x2d, 0x0d, 0xbc, 0x49, 0x4e, 0xd6, 0x9f, 0x3a, 0x60, 0xf3, + 0x34, 0x17, 0xe3, 0x43, 0x31, 0x71, 0x29, 0xbc, 0xcb, 0xe8, 0x58, 0xa6, + 0x5a, 0x8b, 0x4b, 0x16, 0x06, 0x7a, 0xdf, 0xa6, 0xaf, 0x56, 0xed, 0x53, + 0x51, 0x3d, 0x20, 0xb9, 0x3a, 0xf9, 0x11, 0x31, 0xfa, 0x05, 0x62, 0x74, + 0xf9, 0x9e, 0x5c, 0x5e, 0x9e, 0x60, 0xde, 0x55, 0x6d, 0xe4, 0x72, 0xf3, + 0xed, 0x7d, 0xb2, 0xf7, 0xc6, 0x8d, 0xe7, 0x68, 0xfb, 0x47, 0xf3, 0xb6, + 0x7f, 0x2c, 0x8f, 0xc1, 0x16, 0x73, 0xf3, 0x37, 0x6d, 0xfc, 0xcd, 0xe5, + 0xe6, 0xf3, 0x07, 0x8c, 0x8e, 0x30, 0x31, 0xfa, 0x33, 0x7b, 0xa4, 0x7f, + 0x0d, 0xd5, 0xc4, 0x93, 0x1a, 0x62, 0x49, 0xc5, 0x80, 0xac, 0xcf, 0x04, + 0xda, 0xc7, 0x55, 0x9f, 0xdd, 0xc7, 0x26, 0xca, 0xd6, 0x9d, 0x92, 0x77, + 0x6c, 0x0d, 0x6d, 0x83, 0x12, 0x30, 0xaf, 0xa1, 0x3e, 0xf7, 0xa5, 0xaf, + 0x42, 0x7b, 0xff, 0x2c, 0xec, 0x1f, 0x92, 0xf8, 0x22, 0xed, 0x4b, 0x2e, + 0xee, 0xc4, 0xfb, 0xbb, 0x66, 0xe3, 0xfd, 0x91, 0x73, 0x79, 0xf8, 0xe6, + 0x54, 0xf4, 0x5e, 0x86, 0xd7, 0xe5, 0x92, 0x87, 0xbf, 0xc4, 0x3c, 0xfc, + 0x6d, 0x45, 0xd6, 0x10, 0x55, 0xdc, 0xb8, 0xc0, 0xc1, 0xf8, 0xa2, 0xfb, + 0x5f, 0x74, 0xc4, 0xe5, 0x39, 0xb2, 0xff, 0x7e, 0xde, 0x7f, 0x9e, 0xf1, + 0x7c, 0x80, 0x33, 0x11, 0xad, 0x76, 0xe0, 0x99, 0x85, 0xf1, 0xa8, 0x8b, + 0xd7, 0x7b, 0xc9, 0x53, 0x66, 0x1a, 0x07, 0xe9, 0x9b, 0xb5, 0xe1, 0xf9, + 0x0e, 0x07, 0xce, 0x98, 0x7a, 0xcb, 0x6e, 0x5e, 0x7b, 0x36, 0x23, 0xbe, + 0x18, 0x26, 0x7e, 0x2d, 0xca, 0xfb, 0xa2, 0xbc, 0x8f, 0x01, 0xf7, 0x6c, + 0xda, 0xeb, 0x6b, 0x29, 0xbd, 0xff, 0x59, 0xda, 0x69, 0xf5, 0x59, 0x3b, + 0x2d, 0xec, 0xd3, 0x82, 0xbb, 0x2a, 0xd2, 0x82, 0x50, 0xb2, 0xb0, 0x5f, + 0x6b, 0x3f, 0x7a, 0x32, 0xf7, 0x60, 0xe3, 0x4e, 0x7d, 0xa3, 0xac, 0x11, + 0xbd, 0x10, 0x8a, 0x5b, 0x95, 0x46, 0x27, 0x5c, 0x0b, 0x8c, 0x16, 0xe6, + 0x2f, 0xb1, 0xef, 0x2a, 0xa5, 0xb4, 0xdf, 0xc3, 0xd8, 0x34, 0xac, 0x07, + 0xb7, 0x2b, 0x06, 0xe3, 0x86, 0x86, 0xfd, 0x83, 0x45, 0xb8, 0x75, 0x57, + 0x1b, 0xf6, 0xf5, 0x9b, 0xc4, 0xcf, 0x5a, 0xff, 0x69, 0xbc, 0x87, 0x63, + 0xa6, 0xbc, 0xaf, 0x54, 0x82, 0x36, 0x4d, 0xf6, 0x29, 0x31, 0xfb, 0x9c, + 0x7e, 0xde, 0x3b, 0xe0, 0x9e, 0x12, 0xa3, 0xf0, 0x2e, 0xbf, 0xc1, 0x7c, + 0x71, 0x12, 0x7b, 0x06, 0x65, 0x6d, 0x60, 0x9a, 0x72, 0xa4, 0x7f, 0xae, + 0xaf, 0x8b, 0xd8, 0x7f, 0xaf, 0x99, 0xc5, 0x99, 0x85, 0xd5, 0xc0, 0x0c, + 0x05, 0xa1, 0xcf, 0x04, 0xe4, 0x5b, 0x35, 0xfc, 0x7b, 0xd7, 0xf2, 0x7f, + 0x51, 0xda, 0xa9, 0xa9, 0xc8, 0xad, 0x17, 0xbc, 0x5e, 0x2d, 0xef, 0xf2, + 0x1d, 0x49, 0xcd, 0xac, 0xcc, 0x3d, 0x77, 0xfe, 0xa4, 0x3e, 0x5e, 0xb3, + 0xfc, 0x76, 0x1b, 0x85, 0xba, 0xaf, 0x5a, 0x51, 0xaf, 0x94, 0x2f, 0x62, + 0xdb, 0xe2, 0x9f, 0xd3, 0x94, 0x76, 0xe2, 0xa9, 0x1a, 0x9a, 0xa6, 0xb4, + 0x0d, 0x5d, 0xd8, 0xee, 0x8b, 0x56, 0xb4, 0x45, 0xce, 0x0b, 0xe5, 0xdc, + 0xd3, 0x50, 0x2a, 0x65, 0x0b, 0xf7, 0x9f, 0xc9, 0xb7, 0x55, 0x4c, 0xae, + 0x9a, 0x2b, 0x73, 0x6b, 0xbf, 0xec, 0xad, 0x8a, 0xe2, 0x68, 0xc3, 0xd4, + 0xf6, 0x0a, 0x7d, 0x7f, 0xef, 0xbc, 0xf6, 0x72, 0x65, 0x67, 0xb1, 0x4d, + 0x29, 0x9f, 0xc5, 0xff, 0x6b, 0xaf, 0x23, 0xbc, 0x61, 0xef, 0x93, 0xdc, + 0x6a, 0x36, 0x46, 0x4b, 0xf0, 0x39, 0xa8, 0x97, 0xc6, 0xe7, 0x97, 0xd8, + 0xfc, 0x36, 0xda, 0x52, 0xc2, 0x1c, 0xd7, 0x6d, 0x44, 0xef, 0x75, 0x23, + 0x9b, 0x65, 0x5c, 0x6e, 0x3d, 0xa3, 0xec, 0x57, 0x6e, 0x0d, 0xe8, 0x1b, + 0xdf, 0x25, 0xdf, 0x78, 0x3e, 0x10, 0x27, 0xd6, 0x1b, 0xbe, 0x3e, 0x45, + 0x37, 0xd7, 0x32, 0xa6, 0x3d, 0xcb, 0x1c, 0x72, 0x4d, 0xa0, 0xd7, 0x7e, + 0xc6, 0xa8, 0x44, 0x56, 0xe0, 0x12, 0xfb, 0xbb, 0x2c, 0x2d, 0x30, 0xd2, + 0xcf, 0xcb, 0x9a, 0x17, 0x7f, 0xc7, 0x30, 0xdf, 0xbe, 0xb6, 0x06, 0x41, + 0xfb, 0xff, 0xaa, 0xfc, 0xb7, 0x5b, 0x5a, 0x51, 0x6b, 0xff, 0xbf, 0x19, + 0x73, 0xd3, 0x67, 0xd7, 0x86, 0xd1, 0x6d, 0x5a, 0xd6, 0x53, 0xa6, 0x85, + 0x37, 0xce, 0xed, 0xd1, 0x5e, 0xe1, 0x60, 0xce, 0x41, 0x17, 0x8e, 0xe5, + 0xbe, 0x5d, 0x75, 0xee, 0xfd, 0x8c, 0xa5, 0xe7, 0xed, 0xd1, 0x96, 0xf7, + 0xe2, 0xab, 0xed, 0x6f, 0x93, 0xcd, 0x5b, 0xe4, 0xc4, 0x73, 0x89, 0x8a, + 0x98, 0x87, 0xbf, 0x37, 0x2d, 0x2a, 0xc2, 0xfa, 0x10, 0x39, 0xdf, 0xa5, + 0xc7, 0x71, 0xda, 0xfe, 0x46, 0x43, 0x3c, 0x24, 0xdf, 0x66, 0x38, 0x9a, + 0x50, 0x71, 0x6c, 0xb0, 0x27, 0xb4, 0xc7, 0xee, 0xfb, 0x55, 0x74, 0x8f, + 0xca, 0x73, 0xbf, 0x16, 0xac, 0x4e, 0x4c, 0xda, 0x7b, 0xda, 0x36, 0xa7, + 0x24, 0xf7, 0xd6, 0xb3, 0x6b, 0x98, 0xaf, 0xaa, 0x8e, 0x20, 0x6e, 0x62, + 0x7c, 0x79, 0x21, 0x41, 0x3b, 0x5d, 0xa8, 0x77, 0x7c, 0x97, 0x1c, 0xa1, + 0x22, 0xa2, 0x07, 0xdf, 0x51, 0x5a, 0xc9, 0xc5, 0xdc, 0x98, 0x48, 0x88, + 0x2d, 0xca, 0xb7, 0x9d, 0x6e, 0xc6, 0x7e, 0x72, 0xd2, 0xe7, 0x13, 0x1a, + 0x4e, 0x37, 0x78, 0x90, 0x26, 0x47, 0x7d, 0x2e, 0xe1, 0xc6, 0x63, 0xe4, + 0xa8, 0x8f, 0x0e, 0xca, 0x1a, 0x61, 0x13, 0x1a, 0x13, 0xb2, 0x3e, 0x4c, + 0xde, 0x35, 0xe2, 0xa5, 0x3d, 0x5a, 0x56, 0x37, 0x6d, 0xb7, 0x4d, 0x9b, + 0x60, 0x9f, 0xb2, 0xae, 0x18, 0xc5, 0x35, 0xe4, 0x1d, 0x8f, 0x8e, 0xf8, + 0xf0, 0x7d, 0x72, 0xf3, 0x24, 0xeb, 0xbd, 0x90, 0xf0, 0xa3, 0x2f, 0xed, + 0xc3, 0xd3, 0xe4, 0xe8, 0x5b, 0x78, 0x2e, 0xdf, 0x09, 0x2b, 0x32, 0x82, + 0xe4, 0xc1, 0x87, 0x51, 0xd6, 0x77, 0x11, 0xd6, 0xad, 0x3c, 0x08, 0xb5, + 0xef, 0x10, 0x8f, 0x2b, 0x19, 0xb3, 0xaf, 0x44, 0x6a, 0x30, 0x82, 0xd4, + 0xc8, 0x8f, 0xd0, 0x3b, 0x28, 0xe3, 0x92, 0xef, 0x3d, 0xc9, 0xbe, 0x27, + 0x72, 0xbd, 0x3e, 0x2f, 0x86, 0x46, 0xa4, 0x9f, 0x6a, 0xf6, 0xfd, 0xe7, + 0xb6, 0xff, 0x1f, 0xd6, 0xba, 0x1b, 0xa5, 0xed, 0x83, 0x9f, 0xd0, 0xbe, + 0xe8, 0xaa, 0xf0, 0x9e, 0xa1, 0xac, 0x75, 0xb8, 0xd9, 0xa6, 0x07, 0x8e, + 0x48, 0x76, 0x65, 0x39, 0xf4, 0xe8, 0x36, 0xc5, 0x68, 0x2e, 0x53, 0x26, + 0xb1, 0x2d, 0x23, 0xef, 0x8d, 0x15, 0xe3, 0x69, 0xe2, 0xa3, 0x2b, 0xa4, + 0x6b, 0xdf, 0xa5, 0xed, 0x2c, 0x21, 0xa6, 0xbc, 0x61, 0x7e, 0x06, 0x71, + 0x4d, 0xf4, 0x57, 0x8c, 0x1f, 0xf4, 0xbb, 0xf1, 0x4e, 0x28, 0x82, 0xdc, + 0xb7, 0xbd, 0x3c, 0xf8, 0x71, 0xc2, 0xcb, 0xf9, 0xaa, 0xcb, 0x1a, 0x8e, + 0xb9, 0xc0, 0xb4, 0xdc, 0xb5, 0xa3, 0x89, 0x35, 0xd8, 0x43, 0x79, 0x5f, + 0x48, 0x9c, 0xe1, 0xfc, 0xb4, 0x53, 0xff, 0xa2, 0xef, 0x78, 0x5e, 0xd7, + 0x3d, 0xd4, 0xf5, 0x2c, 0x3c, 0x9b, 0xb8, 0x0f, 0x8f, 0x52, 0xfe, 0x47, + 0xfa, 0x8d, 0xe8, 0xc5, 0xca, 0x61, 0xe2, 0x65, 0x31, 0x8e, 0xb1, 0xed, + 0x5b, 0x99, 0x29, 0x4f, 0x4a, 0x5f, 0x29, 0x59, 0x9f, 0x54, 0xf0, 0xce, + 0xa2, 0xc3, 0x18, 0xe7, 0xbd, 0x1f, 0xf3, 0x77, 0x78, 0x61, 0x25, 0xfb, + 0x10, 0xfd, 0xf8, 0xed, 0x5c, 0xa0, 0x8b, 0x3c, 0x67, 0x79, 0xc3, 0x61, + 0x6c, 0x1d, 0x92, 0x6b, 0x6d, 0xe8, 0xed, 0x7f, 0x0f, 0x8e, 0x10, 0x71, + 0xc8, 0xdb, 0x40, 0x5b, 0xcf, 0x62, 0x5b, 0xfa, 0xc3, 0x69, 0x39, 0x0e, + 0xfa, 0xca, 0x34, 0xd9, 0x8b, 0x7c, 0x34, 0x51, 0x8c, 0xe7, 0x58, 0x67, + 0x5d, 0xc8, 0x95, 0x7f, 0x66, 0x72, 0x98, 0xfc, 0xc9, 0x89, 0x34, 0xfb, + 0x48, 0xd8, 0x6d, 0x4c, 0x53, 0x76, 0xd3, 0x0f, 0x2b, 0x17, 0x4e, 0x53, + 0x52, 0x43, 0xc2, 0xed, 0x7f, 0x84, 0x27, 0xef, 0xcf, 0xe9, 0x70, 0x8f, + 0xb9, 0x06, 0x43, 0xe9, 0x1f, 0x17, 0xda, 0x9b, 0xf2, 0x2e, 0x9c, 0xbc, + 0x9f, 0x53, 0x78, 0x57, 0x27, 0xf7, 0x4c, 0xeb, 0xdb, 0x99, 0x0a, 0xf2, + 0xe7, 0x52, 0xda, 0x5a, 0x51, 0xcc, 0xcb, 0xb8, 0xba, 0x66, 0x81, 0x86, + 0x9d, 0x97, 0xd5, 0x4d, 0x43, 0x85, 0xe6, 0xfc, 0x75, 0xc3, 0xf3, 0xec, + 0xa7, 0x22, 0x56, 0x15, 0xd9, 0x63, 0xef, 0x83, 0x0a, 0x5d, 0x56, 0xc3, + 0xb8, 0x22, 0xcf, 0x86, 0x63, 0x78, 0x2b, 0x51, 0x1d, 0xab, 0x8e, 0x54, + 0x12, 0x6f, 0x4f, 0xa3, 0x6f, 0xd8, 0x89, 0x0a, 0xf2, 0xe6, 0xf2, 0x64, + 0x35, 0xdc, 0xf6, 0x3a, 0xde, 0x45, 0xe4, 0x2b, 0xb3, 0xc9, 0x49, 0x66, + 0xa1, 0x92, 0xbc, 0xc4, 0x13, 0xb2, 0xac, 0x9f, 0x2d, 0xb4, 0xac, 0x4b, + 0x78, 0x94, 0xf0, 0x38, 0x15, 0x12, 0x3f, 0x8d, 0xa2, 0xce, 0xf6, 0x57, + 0x03, 0xf5, 0xf6, 0xff, 0x26, 0xfa, 0x7a, 0x47, 0x68, 0xfe, 0xf8, 0x7d, + 0xa1, 0xb9, 0xe3, 0x35, 0x50, 0x07, 0xa6, 0xc3, 0xc1, 0xb6, 0xbe, 0x70, + 0x99, 0x85, 0x26, 0xfa, 0xf0, 0x5a, 0x53, 0x78, 0xd1, 0x1a, 0xf2, 0xa2, + 0xde, 0x90, 0x31, 0x7e, 0x10, 0x57, 0x33, 0xce, 0xb9, 0x07, 0x7c, 0xec, + 0x47, 0x72, 0x6c, 0x67, 0x76, 0x0e, 0xf9, 0xf6, 0x67, 0x16, 0x0a, 0x47, + 0x6a, 0x25, 0x47, 0x3a, 0x84, 0xd6, 0xf1, 0xc3, 0xb8, 0x9e, 0x65, 0x3c, + 0xe4, 0x2a, 0xc9, 0xcc, 0x8f, 0xd0, 0x97, 0xb1, 0xb0, 0x3d, 0x94, 0xc5, + 0xb5, 0x6c, 0xbb, 0x74, 0xa0, 0x99, 0xdc, 0x70, 0x05, 0xd6, 0x8d, 0xcb, + 0xbb, 0x52, 0x13, 0x58, 0x3e, 0x4e, 0xce, 0x39, 0x5e, 0xf0, 0x57, 0xe1, + 0x4b, 0x2b, 0xc8, 0x97, 0x64, 0x2d, 0x6d, 0x95, 0xbd, 0x96, 0xa6, 0xd2, + 0x0f, 0x1b, 0x13, 0xf2, 0x9e, 0x50, 0x1c, 0xab, 0xc7, 0x05, 0xab, 0xef, + 0x41, 0xf7, 0xb8, 0xac, 0xcd, 0x7e, 0x33, 0x74, 0xf1, 0xf8, 0xab, 0x68, + 0x1c, 0x1f, 0x0a, 0xcd, 0x1b, 0x1f, 0xa1, 0xdc, 0x09, 0xca, 0xd6, 0x1f, + 0xaa, 0x1d, 0x1f, 0x0c, 0x05, 0xc7, 0x77, 0x87, 0x02, 0xe3, 0x2d, 0xd8, + 0x32, 0xbe, 0x0a, 0x9b, 0xc7, 0x37, 0x62, 0xd3, 0xb8, 0xe0, 0xfc, 0x24, + 0x96, 0x8d, 0xbf, 0x81, 0xa5, 0xe3, 0xcf, 0xa3, 0x69, 0xfc, 0x04, 0x96, + 0x8c, 0xff, 0x08, 0xcd, 0xe3, 0xaf, 0x70, 0x2c, 0xb2, 0xd6, 0x2b, 0xeb, + 0xbc, 0x85, 0xe7, 0x6a, 0x53, 0xf7, 0x24, 0xcb, 0x5a, 0x86, 0x7c, 0xbf, + 0x43, 0xe6, 0xd0, 0x85, 0x95, 0xda, 0x6b, 0xe8, 0xd9, 0x25, 0xdf, 0x24, + 0xac, 0xd3, 0xba, 0xe5, 0xf9, 0xa3, 0xf7, 0x79, 0xd9, 0x63, 0x4f, 0x1b, + 0x3b, 0xff, 0xbd, 0xbc, 0xc9, 0xb3, 0xcf, 0x18, 0xe5, 0x1b, 0x18, 0xf2, + 0xec, 0x73, 0x12, 0x5d, 0x99, 0xdf, 0x5a, 0x51, 0x4d, 0xca, 0xca, 0xf7, + 0x3f, 0xc4, 0x1e, 0x5e, 0xc3, 0x43, 0xbb, 0x26, 0xc9, 0x59, 0xb2, 0xf6, + 0x5a, 0xcd, 0xbb, 0xf3, 0xe4, 0x9b, 0x56, 0xf2, 0xce, 0xfe, 0x6b, 0x48, + 0x8d, 0x02, 0xe3, 0x0f, 0x8b, 0x1f, 0xae, 0xa1, 0x1f, 0x66, 0xc5, 0x27, + 0xe3, 0xc4, 0xe4, 0xaf, 0x78, 0x70, 0x0f, 0x79, 0x49, 0x11, 0xb2, 0x23, + 0xa5, 0x78, 0x66, 0x30, 0x6e, 0xcd, 0x31, 0x3c, 0x28, 0x8f, 0x18, 0xd9, + 0x4b, 0x18, 0x67, 0x5f, 0xe1, 0xb5, 0x89, 0x7e, 0xf8, 0x7d, 0x46, 0xc0, + 0x37, 0x87, 0xe7, 0xc7, 0x86, 0xb2, 0xe4, 0x14, 0x1d, 0x98, 0xe4, 0x7f, + 0xc9, 0x41, 0x81, 0x6e, 0x0c, 0x0d, 0x89, 0x3e, 0x5b, 0xa8, 0x4f, 0xc1, + 0x45, 0xbd, 0xa3, 0x89, 0x78, 0x68, 0x29, 0x82, 0x87, 0x2a, 0xca, 0x1e, + 0xe8, 0xa4, 0xbf, 0xea, 0xb1, 0x9f, 0x30, 0x16, 0xf4, 0x29, 0x3f, 0xc2, + 0x73, 0xcc, 0x19, 0x4a, 0x1f, 0x20, 0xff, 0x20, 0x56, 0x56, 0x44, 0x14, + 0x63, 0x79, 0xe0, 0x14, 0x9e, 0x19, 0x71, 0xc2, 0x9d, 0x74, 0x62, 0x82, + 0x38, 0xe9, 0x48, 0xca, 0xf3, 0x7a, 0x8d, 0xb2, 0xc8, 0xba, 0xd0, 0x09, + 0x64, 0xed, 0xe7, 0x69, 0xf2, 0x3c, 0xe4, 0x45, 0xbb, 0x1f, 0x27, 0x65, + 0xef, 0x21, 0x96, 0x76, 0xa5, 0x5e, 0x42, 0xd3, 0x90, 0x07, 0x73, 0x92, + 0x13, 0xcc, 0x5f, 0x5e, 0x45, 0x6a, 0xd7, 0x2c, 0x7c, 0x95, 0x3c, 0x70, + 0x66, 0xd2, 0x84, 0x46, 0xbd, 0xdd, 0x34, 0x66, 0x22, 0xba, 0x77, 0x15, + 0x56, 0xee, 0xfd, 0x22, 0x8f, 0xe9, 0xb8, 0x7e, 0x6f, 0x3b, 0x3e, 0x3f, + 0x16, 0x47, 0xeb, 0x58, 0x0f, 0x8f, 0x36, 0x5c, 0xb7, 0xa3, 0x12, 0xe9, + 0x90, 0xc6, 0x9c, 0xba, 0x8d, 0x39, 0xb5, 0xf0, 0xa1, 0xd5, 0x78, 0x86, + 0xb8, 0x13, 0x0c, 0xad, 0xc6, 0x84, 0xed, 0x8b, 0xb2, 0x97, 0x71, 0x35, + 0x36, 0x31, 0x5f, 0x1e, 0xc6, 0x6a, 0x74, 0xf1, 0xda, 0x0e, 0x7b, 0x0e, + 0x0e, 0x63, 0x31, 0xf3, 0xa1, 0xf7, 0x2f, 0x3f, 0x8c, 0x2b, 0xf6, 0x48, + 0xdf, 0xa7, 0x91, 0xda, 0xb9, 0x86, 0x6d, 0x66, 0xd1, 0x32, 0xf6, 0x43, + 0x7c, 0x7e, 0x07, 0x6e, 0xab, 0x44, 0x25, 0x9e, 0x0f, 0x05, 0x5a, 0xfb, + 0x94, 0x1f, 0xda, 0x6d, 0x6f, 0xa2, 0x1f, 0x6f, 0x65, 0xb9, 0x47, 0xd2, + 0x27, 0xd0, 0x9b, 0x9a, 0x3a, 0xa7, 0xf6, 0x7b, 0xed, 0x8c, 0x07, 0x2f, + 0x63, 0xdf, 0xc8, 0x24, 0xb1, 0xf7, 0x24, 0x8f, 0x0b, 0x9f, 0x5f, 0x7b, + 0xed, 0x7c, 0x26, 0x67, 0x37, 0x92, 0xbf, 0xc8, 0x3a, 0x70, 0x0b, 0x7c, + 0x29, 0xe1, 0x44, 0xd9, 0xad, 0x33, 0xa1, 0x6f, 0x0c, 0xdb, 0x1c, 0xc9, + 0x88, 0x91, 0x1b, 0xb5, 0x7c, 0x57, 0xf1, 0x90, 0x1b, 0x05, 0xb1, 0x22, + 0xa3, 0x47, 0xaf, 0xa5, 0xbe, 0x4b, 0xee, 0x7f, 0x19, 0xce, 0xfb, 0x9d, + 0x28, 0x4e, 0xca, 0xda, 0xc9, 0x04, 0x7a, 0x33, 0xf2, 0xfe, 0x6e, 0x56, + 0x2f, 0x26, 0xae, 0x16, 0x25, 0xb3, 0x8c, 0xfd, 0xd9, 0xf9, 0x45, 0x90, + 0x77, 0xf1, 0xaf, 0xc2, 0x9a, 0xfe, 0x28, 0xba, 0x4c, 0x79, 0x57, 0x27, + 0x37, 0xfe, 0x39, 0x0d, 0x2f, 0xa3, 0x9b, 0xf1, 0xa7, 0x8d, 0x98, 0xf8, + 0x55, 0xfb, 0x59, 0xe8, 0xcb, 0xe8, 0x19, 0x2c, 0xbc, 0xbb, 0x2e, 0x6d, + 0x3e, 0x4f, 0xbd, 0xb9, 0xf2, 0xdf, 0xec, 0x91, 0x36, 0x75, 0xd3, 0xaf, + 0x4e, 0xcb, 0xbd, 0x8b, 0x03, 0xfb, 0x19, 0x36, 0xed, 0xe3, 0x35, 0xf4, + 0xee, 0x2a, 0x8c, 0x99, 0xb9, 0x41, 0xe0, 0x35, 0xf4, 0x8f, 0xca, 0xd8, + 0xaf, 0x9f, 0x96, 0x7b, 0xc7, 0x78, 0xaa, 0x3e, 0x0a, 0x75, 0x1d, 0xb4, + 0xe7, 0xc2, 0xfd, 0x8f, 0xfb, 0x6e, 0xd0, 0xa7, 0xec, 0x6f, 0xf0, 0xe4, + 0xbe, 0x81, 0x04, 0x3c, 0x99, 0x90, 0x77, 0xfb, 0xd5, 0xc5, 0x2e, 0xa8, + 0x5e, 0x17, 0x8a, 0x19, 0x2f, 0x6a, 0xd0, 0xed, 0xb5, 0x70, 0x35, 0xc7, + 0xb2, 0xbf, 0xfe, 0x3a, 0x66, 0x1a, 0xf1, 0x56, 0x97, 0xfd, 0xce, 0xe1, + 0x8a, 0xbf, 0xfe, 0xe8, 0x3b, 0x87, 0x6f, 0x10, 0x67, 0x15, 0x94, 0x1b, + 0x37, 0xe1, 0x05, 0x3b, 0xa6, 0x28, 0x28, 0x9b, 0x2b, 0xeb, 0x98, 0x7e, + 0x3c, 0x6b, 0xd4, 0xf9, 0xab, 0xe4, 0xf9, 0x94, 0x72, 0xca, 0x92, 0x6f, + 0x06, 0x6c, 0xcb, 0xfc, 0xb1, 0x3d, 0xf1, 0x4f, 0x61, 0xcb, 0xce, 0x30, + 0xe4, 0xfd, 0x15, 0xa7, 0xa1, 0x79, 0x73, 0xfc, 0x4a, 0x64, 0x93, 0xbd, + 0xe4, 0xb7, 0x12, 0x9c, 0xde, 0xa0, 0x9f, 0xbe, 0x21, 0x7b, 0xa6, 0xc8, + 0x99, 0xfe, 0x12, 0xc1, 0xaa, 0xc2, 0x38, 0x65, 0xaf, 0xa9, 0x92, 0x1b, + 0xab, 0x5d, 0x47, 0xca, 0x4a, 0xbd, 0x37, 0xec, 0x35, 0x5c, 0x97, 0xf1, + 0x5b, 0xeb, 0x4d, 0x6f, 0x35, 0xcb, 0x1e, 0xce, 0xdf, 0x9f, 0x14, 0x9f, + 0x33, 0xe5, 0x1b, 0x56, 0x4e, 0xbb, 0x8e, 0xe8, 0xf7, 0x5c, 0x9d, 0xee, + 0x94, 0x83, 0xb8, 0x79, 0xc2, 0xea, 0xf4, 0xca, 0x18, 0xee, 0xbc, 0xa0, + 0x8e, 0xac, 0x2b, 0x68, 0xd2, 0x6f, 0x58, 0xc6, 0xdc, 0x95, 0xf9, 0x68, + 0x9f, 0xb2, 0xde, 0x5b, 0x64, 0x94, 0xe1, 0x54, 0x55, 0x6e, 0x1d, 0xe6, + 0x9c, 0x8c, 0x3d, 0x35, 0xb2, 0x4f, 0xaf, 0xd8, 0x3e, 0xb7, 0xfb, 0x35, + 0xcf, 0xd5, 0xfb, 0xbb, 0xfc, 0x78, 0xab, 0xed, 0x77, 0x86, 0x1e, 0xb4, + 0x79, 0x91, 0x63, 0xca, 0xb8, 0x4b, 0x6a, 0xce, 0xef, 0xe7, 0x2b, 0xf9, + 0x7e, 0x45, 0x1e, 0xef, 0x94, 0x3e, 0x44, 0xae, 0x87, 0xf3, 0x75, 0xf4, + 0x70, 0xd4, 0xee, 0x5f, 0x65, 0xbe, 0x55, 0xe8, 0x93, 0xfe, 0xb8, 0xb0, + 0xd0, 0x46, 0x56, 0xec, 0xb3, 0xb3, 0x98, 0xb1, 0xed, 0x54, 0xc3, 0x3d, + 0xd8, 0x94, 0x10, 0x3d, 0xcb, 0xb7, 0x60, 0x89, 0xe1, 0x36, 0x57, 0x73, + 0xd1, 0x5f, 0x2f, 0xc3, 0x90, 0x16, 0xc7, 0x9e, 0x7a, 0x79, 0x47, 0xce, + 0x45, 0x9f, 0x88, 0xa3, 0xc4, 0x28, 0x96, 0xfd, 0xc7, 0xf6, 0x1e, 0x94, + 0x7d, 0xa6, 0x1e, 0x7d, 0x52, 0xbe, 0x55, 0x76, 0xa9, 0xbd, 0x5e, 0xd5, + 0x3c, 0x04, 0xb9, 0x6e, 0xe2, 0xda, 0xf3, 0xf2, 0xfe, 0x12, 0xda, 0x8e, + 0xbd, 0x27, 0xda, 0x94, 0x77, 0xe8, 0xfa, 0x12, 0xf2, 0x2e, 0x57, 0x5d, + 0x8c, 0xfc, 0x12, 0x2f, 0xa4, 0x65, 0xbf, 0xc2, 0xef, 0xac, 0x78, 0x8d, + 0xec, 0x8b, 0x9c, 0x5a, 0xa7, 0x88, 0xb8, 0x16, 0x08, 0x57, 0x28, 0x85, + 0xf7, 0xb9, 0xce, 0xfd, 0x5d, 0x4f, 0x9b, 0x39, 0x6d, 0xbf, 0x83, 0x27, + 0x67, 0x11, 0x34, 0xa6, 0xe4, 0x9b, 0xa7, 0xfa, 0xc4, 0x72, 0xd4, 0x65, + 0x6b, 0x1d, 0xce, 0x3c, 0x7f, 0x09, 0x63, 0x05, 0xed, 0x66, 0x73, 0x20, + 0x6c, 0xbf, 0x6b, 0xb6, 0x2c, 0x55, 0x1b, 0x7c, 0x04, 0x7a, 0xfb, 0xdb, + 0x2c, 0x7f, 0x5d, 0xe6, 0xfb, 0xd6, 0x90, 0x57, 0xc6, 0x54, 0xc0, 0x88, + 0x13, 0xf4, 0x0d, 0xea, 0x31, 0x22, 0xfe, 0xe1, 0x41, 0x55, 0x24, 0x4c, + 0x3f, 0x96, 0xf8, 0x2f, 0xef, 0xa9, 0xe9, 0xbb, 0xe3, 0x30, 0xd1, 0xc8, + 0x1c, 0xdd, 0x65, 0xef, 0x73, 0xd6, 0xfd, 0x2b, 0x19, 0x87, 0x8e, 0x9c, + 0xdd, 0x13, 0x20, 0x7c, 0xe1, 0xc7, 0x35, 0xf9, 0xbd, 0xd0, 0xee, 0x39, + 0x8c, 0x8f, 0x96, 0xfd, 0x9c, 0x7f, 0x8d, 0x8d, 0x2d, 0x9a, 0xa1, 0xef, + 0xff, 0x95, 0xa3, 0x13, 0x4f, 0x2c, 0x30, 0x3a, 0x0e, 0xa8, 0xd9, 0x21, + 0x1f, 0x71, 0xe6, 0x4a, 0x47, 0x74, 0x07, 0xff, 0xfb, 0x5f, 0xb4, 0xbf, + 0xa1, 0x22, 0x75, 0xf5, 0xe0, 0x2a, 0x55, 0xf6, 0x0f, 0xb5, 0x60, 0xac, + 0x4f, 0xde, 0x7d, 0xd0, 0x5b, 0xbf, 0xad, 0x74, 0x62, 0x43, 0xc8, 0x68, + 0xd9, 0xa8, 0xe8, 0xcd, 0x7f, 0xaf, 0xe8, 0xfe, 0x90, 0x22, 0xe5, 0x82, + 0xb2, 0xb6, 0x77, 0x36, 0xf6, 0xba, 0xd8, 0xc7, 0xde, 0x84, 0x1e, 0x9e, + 0xc6, 0xb2, 0xa7, 0x4c, 0xc3, 0xf7, 0x1e, 0xdb, 0xfc, 0x09, 0x8f, 0x1d, + 0xf6, 0x3b, 0xec, 0x52, 0x3e, 0x3a, 0xdf, 0x65, 0x7f, 0x8f, 0xb8, 0x95, + 0x31, 0x45, 0xbe, 0x35, 0x1c, 0x83, 0x96, 0x9c, 0x45, 0x13, 0xd3, 0x7b, + 0x6f, 0x80, 0xe4, 0xc0, 0x37, 0x4f, 0x47, 0xa9, 0x07, 0xde, 0x48, 0x27, 0xe6, 0x2e, 0x30, 0x7c, 0x8b, 0x54, 0xbb, 0x7e, 0x30, 0xaa, 0x4a, 0x7d, - 0xdd, 0x3f, 0x08, 0x69, 0x23, 0x63, 0x69, 0x73, 0xcb, 0xed, 0x3a, 0x0b, - 0xd4, 0xcf, 0xc0, 0x75, 0xf5, 0xaf, 0xe5, 0x5b, 0x46, 0x5a, 0xa5, 0x21, - 0x75, 0xe2, 0x3b, 0x35, 0xfc, 0xb1, 0x7a, 0x82, 0x2b, 0xbf, 0xb2, 0x30, - 0x4d, 0xea, 0xc9, 0x9e, 0xb1, 0x3b, 0x70, 0xaf, 0xfd, 0x3d, 0x16, 0xf1, - 0x47, 0x3d, 0xfa, 0x15, 0xf2, 0xcf, 0x62, 0x45, 0xb8, 0xa7, 0xf0, 0x84, - 0x56, 0x74, 0x33, 0x8e, 0x69, 0x21, 0xbd, 0xe7, 0x0a, 0xd5, 0x83, 0xc2, - 0xc8, 0x63, 0xb2, 0x6f, 0x66, 0xef, 0x3c, 0x35, 0xbb, 0xbf, 0x26, 0xc6, - 0x76, 0x8f, 0xff, 0xd1, 0xe7, 0xb8, 0xec, 0xab, 0xd8, 0x94, 0xf7, 0x5b, - 0xec, 0x35, 0xc5, 0xd6, 0x84, 0x23, 0xb7, 0x5f, 0x30, 0x3f, 0xb7, 0x1a, - 0xda, 0xc8, 0xf5, 0xd7, 0xc8, 0x37, 0x31, 0x39, 0xd6, 0xb5, 0x09, 0x59, - 0x4d, 0xfa, 0xff, 0x00, 0x85, 0x57, 0x0f, 0xe7, 0xe8, 0x59, 0x00, 0x00, + 0xdd, 0x3f, 0x08, 0x69, 0x23, 0x6b, 0x69, 0x73, 0x2b, 0xed, 0x3a, 0x0b, + 0xd4, 0xcf, 0xc1, 0xf5, 0xe9, 0x5f, 0xcb, 0x37, 0x8b, 0xb4, 0x6a, 0x43, + 0xea, 0xc4, 0x77, 0x68, 0xf8, 0x63, 0xf5, 0x04, 0x57, 0x7e, 0x65, 0x61, + 0xba, 0xd4, 0x93, 0x3d, 0x66, 0x37, 0xe3, 0x76, 0xfb, 0xbb, 0x2b, 0xe2, + 0x8f, 0x7a, 0xf4, 0x6e, 0x72, 0xd5, 0x52, 0x45, 0x78, 0xaa, 0xc4, 0xa2, + 0x36, 0xe2, 0x61, 0x27, 0xb4, 0x90, 0xde, 0x7b, 0x91, 0xea, 0x41, 0x71, + 0x64, 0x54, 0xf6, 0xd9, 0xec, 0x9e, 0xa7, 0xe6, 0xf6, 0xe3, 0xc4, 0xd8, + 0xee, 0x91, 0x3f, 0xfa, 0xdc, 0x97, 0x7d, 0x95, 0x9a, 0xf2, 0xce, 0x8e, + 0xfd, 0x9e, 0x48, 0x5b, 0xc2, 0x91, 0xdf, 0x5f, 0x58, 0x98, 0x5b, 0x0d, + 0x6b, 0x98, 0x17, 0xac, 0x95, 0x6f, 0x63, 0x72, 0xac, 0xeb, 0x12, 0xb2, + 0x0a, 0xf5, 0x7f, 0x01, 0x28, 0xfc, 0xfc, 0x40, 0x38, 0x5a, 0x00, 0x00, 0x00 }; static const u32 bnx2_CP_b06FwData[(0x84/4) + 1] = { @@ -2137,48 +2138,48 @@ static const u32 bnx2_CP_b06FwData[(0x84/4) + 1] = { 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000000 }; static const u32 bnx2_CP_b06FwRodata[(0x130/4) + 1] = { - 0x08001f1c, 0x08001da8, 0x08001ef8, 0x08001ed4, 0x08001eb0, 0x08001e8c, - 0x08001e64, 0x08001e3c, 0x08001e10, 0x08002014, 0x08002004, 0x08001dc4, - 0x08001dc4, 0x08001dc4, 0x08001f44, 0x08001f44, 0x08001dc4, 0x08001dc4, - 0x08001ff4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001fe4, - 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, - 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, - 0x08001dc4, 0x08001dc4, 0x08001fd4, 0x08001dc4, 0x08001dc4, 0x08001fc4, - 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, - 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, - 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001fac, - 0x08001dc4, 0x08001dc4, 0x08001f9c, 0x08001f8c, 0x080031e8, 0x080031f0, - 0x080031b8, 0x080031c4, 0x080031d0, 0x080031dc, 0x08005644, 0x08005604, - 0x080055d0, 0x080055a4, 0x08005580, 0x0800553c, 0x00000000 }; + 0x08001e8c, 0x08001d18, 0x08001e68, 0x08001e44, 0x08001e20, 0x08001dfc, + 0x08001dd4, 0x08001dac, 0x08001d80, 0x08001f84, 0x08001f74, 0x08001d34, + 0x08001d34, 0x08001d34, 0x08001eb4, 0x08001eb4, 0x08001d34, 0x08001d34, + 0x08001f64, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001f54, + 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, + 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, + 0x08001d34, 0x08001d34, 0x08001f44, 0x08001d34, 0x08001d34, 0x08001f34, + 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, + 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, + 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001f1c, + 0x08001d34, 0x08001d34, 0x08001f0c, 0x08001efc, 0x08003208, 0x08003210, + 0x080031d8, 0x080031e4, 0x080031f0, 0x080031fc, 0x08005694, 0x08005654, + 0x08005620, 0x080055f4, 0x080055d0, 0x0800558c, 0x00000000 }; static struct fw_info bnx2_cp_fw_06 = { - /* Firmware version: 4.0.5 */ + /* Firmware version: 4.4.22 */ .ver_major = 0x4, - .ver_minor = 0x0, - .ver_fix = 0x5, + .ver_minor = 0x4, + .ver_fix = 0x16, - .start_addr = 0x08000078, + .start_addr = 0x08000080, .text_addr = 0x08000000, - .text_len = 0x59e4, + .text_len = 0x5a34, .text_index = 0x0, .gz_text = bnx2_CP_b06FwText, .gz_text_len = sizeof(bnx2_CP_b06FwText), - .data_addr = 0x08005b40, + .data_addr = 0x08005b80, .data_len = 0x84, .data_index = 0x0, .data = bnx2_CP_b06FwData, - .sbss_addr = 0x08005bc4, + .sbss_addr = 0x08005c04, .sbss_len = 0xe9, .sbss_index = 0x0, - .bss_addr = 0x08005cb0, + .bss_addr = 0x08005cf0, .bss_len = 0x5d8, .bss_index = 0x0, - .rodata_addr = 0x080059e4, + .rodata_addr = 0x08005a34, .rodata_len = 0x130, .rodata_index = 0x0, .rodata = bnx2_CP_b06FwRodata, @@ -2201,761 +2202,761 @@ static const struct cpu_reg cpu_reg_cp = { }; static u8 bnx2_RXP_b06FwText[] = { - 0xec, 0x5b, 0x5d, 0x70, 0x5c, 0xd7, 0x5d, 0xff, 0xdf, 0xb3, 0x2b, 0x69, - 0x2d, 0x4b, 0xf2, 0x95, 0xbc, 0x71, 0x56, 0xa9, 0x92, 0xec, 0x5a, 0x57, - 0xd2, 0xa6, 0x12, 0xe1, 0xca, 0x6c, 0x12, 0x75, 0xd8, 0x69, 0xb6, 0xbb, - 0xb2, 0xa3, 0xb4, 0x66, 0x46, 0x49, 0x0d, 0xcd, 0xb4, 0x65, 0x10, 0xbb, - 0x0e, 0xa4, 0x0f, 0x0c, 0xc6, 0x40, 0x26, 0x80, 0xc1, 0xcb, 0x4a, 0x71, - 0x94, 0x74, 0xad, 0xdd, 0xda, 0x0a, 0x86, 0x69, 0x61, 0x94, 0xd5, 0x87, - 0x53, 0x66, 0xad, 0x4d, 0xcb, 0x4b, 0x99, 0xd6, 0xb1, 0xea, 0xb8, 0x26, - 0x0f, 0x3c, 0xa4, 0x94, 0xce, 0x64, 0x20, 0x33, 0x35, 0xb2, 0x63, 0xfb, - 0x81, 0x8f, 0xc0, 0x4c, 0x49, 0x20, 0x6e, 0x2e, 0xbf, 0xdf, 0xb9, 0xf7, - 0xca, 0x2b, 0x45, 0xd0, 0x3c, 0xf0, 0x78, 0xcf, 0x8c, 0xe6, 0xde, 0x7b, - 0xce, 0xff, 0xfc, 0xcf, 0xff, 0xfb, 0xe3, 0xac, 0xfd, 0x3b, 0x1d, 0xd2, - 0x2e, 0xde, 0xe8, 0xc4, 0x5f, 0xea, 0xc8, 0x33, 0x47, 0x47, 0xef, 0x1f, - 0xbd, 0x9f, 0xdf, 0x21, 0xc3, 0x08, 0xf3, 0x69, 0x48, 0x30, 0x82, 0x11, - 0x8c, 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, - 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, - 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, - 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23, - 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23, 0x18, - 0xc1, 0x08, 0x46, 0x30, 0xfe, 0x3f, 0x47, 0x48, 0xc4, 0xe4, 0xb3, 0xd3, - 0xfb, 0x93, 0x88, 0x4a, 0xc7, 0x8f, 0x66, 0x2d, 0x89, 0x84, 0xd2, 0x97, - 0x9e, 0x2e, 0x58, 0x22, 0x99, 0xfa, 0x70, 0x3c, 0x27, 0x3f, 0x71, 0x8a, - 0xd1, 0xb0, 0x70, 0xfe, 0xee, 0xf4, 0xad, 0xe3, 0xe7, 0x1f, 0x4a, 0xbc, - 0xb3, 0x10, 0x92, 0x88, 0x99, 0x7e, 0x63, 0xd4, 0x1c, 0x94, 0x48, 0x1f, - 0xf6, 0x7c, 0x6d, 0x68, 0x6d, 0x97, 0x74, 0xf9, 0xb8, 0x44, 0x6a, 0xe5, - 0x84, 0x7d, 0x40, 0x86, 0xcd, 0x8b, 0x12, 0x96, 0x0c, 0xce, 0x58, 0xa9, - 0x8b, 0x94, 0xca, 0x06, 0x71, 0x48, 0xa9, 0x1e, 0x91, 0x2b, 0x21, 0x42, - 0x7d, 0xcb, 0xc8, 0x56, 0x3e, 0x70, 0x32, 0x61, 0x9c, 0x6b, 0xe1, 0xbd, - 0xe1, 0xcf, 0x47, 0x44, 0xa5, 0x13, 0xc9, 0x6c, 0x68, 0x42, 0x6a, 0xf3, - 0x8e, 0x33, 0x63, 0x7f, 0x0c, 0x38, 0x7a, 0x64, 0xc6, 0x72, 0xbf, 0xb3, - 0xf6, 0xc7, 0xcd, 0x71, 0xb9, 0x13, 0x73, 0x21, 0x51, 0xd6, 0x5d, 0xf8, - 0x8b, 0x1b, 0xb9, 0xd3, 0x5f, 0x36, 0xb2, 0x8b, 0x1d, 0x52, 0xaa, 0x38, - 0x52, 0xb0, 0x25, 0x93, 0xb5, 0x77, 0x60, 0xfd, 0x03, 0xa7, 0xb0, 0xb1, - 0x67, 0xd8, 0xcc, 0x49, 0x8b, 0x64, 0xa2, 0x31, 0xc0, 0xcc, 0x1b, 0xb9, - 0xb3, 0x7f, 0xdd, 0x21, 0xed, 0xa0, 0x27, 0xc5, 0xef, 0x0f, 0x9c, 0x90, - 0x65, 0x61, 0x9d, 0xe7, 0xe3, 0xbb, 0x41, 0xbc, 0x7c, 0x27, 0xce, 0x2b, - 0xce, 0xf9, 0xa1, 0x98, 0x7c, 0xb3, 0x11, 0x95, 0x6f, 0x34, 0x4c, 0x79, - 0xa5, 0xd1, 0x27, 0x17, 0x1a, 0x8e, 0xf3, 0x0d, 0xdb, 0x71, 0xde, 0xc0, - 0xdf, 0x7f, 0xd8, 0x1b, 0x3c, 0x60, 0x14, 0x8d, 0xf1, 0xc6, 0x57, 0x3b, - 0xa4, 0x2b, 0x11, 0x17, 0xd5, 0x21, 0xd3, 0x95, 0x98, 0xcc, 0x54, 0xca, - 0xc6, 0x63, 0x67, 0xe7, 0x8c, 0xc9, 0xb3, 0x55, 0x9c, 0x19, 0xc6, 0x9c, - 0x14, 0x4b, 0xf6, 0xcb, 0x46, 0xae, 0x31, 0x6b, 0x3c, 0x7e, 0xb6, 0x0b, - 0x34, 0xf2, 0xfc, 0x3d, 0x46, 0xf6, 0xf4, 0x2d, 0xc9, 0xda, 0x94, 0x71, - 0xc2, 0xfc, 0x3c, 0xc4, 0x9e, 0x2d, 0x93, 0xe6, 0x56, 0x8f, 0x5e, 0xc7, - 0x51, 0x69, 0xe7, 0x78, 0x36, 0x65, 0x99, 0x25, 0x21, 0x7d, 0x7a, 0xee, - 0x82, 0x4b, 0xf3, 0x8a, 0x91, 0x3d, 0xdb, 0x61, 0xe4, 0xce, 0x84, 0x41, - 0x87, 0xf4, 0x85, 0x84, 0xfb, 0x06, 0x62, 0x79, 0xa9, 0xe3, 0x0c, 0x31, - 0x55, 0x9a, 0x72, 0x05, 0xcd, 0xa0, 0xe5, 0x9b, 0x15, 0xf0, 0x50, 0x01, - 0x0f, 0x15, 0xf2, 0x16, 0x97, 0xf3, 0x43, 0x3e, 0x6f, 0x8e, 0xf3, 0x77, - 0x36, 0x69, 0x4f, 0xc4, 0x33, 0xca, 0xe7, 0xd3, 0x71, 0xfe, 0xdd, 0x26, - 0xaf, 0xe4, 0xc7, 0x71, 0x5e, 0xb1, 0x63, 0xa0, 0xdd, 0xb9, 0xa0, 0xac, - 0x32, 0x78, 0xb1, 0x80, 0x9f, 0xb2, 0x9e, 0x03, 0x0f, 0xb3, 0xe0, 0x6f, - 0x05, 0xbc, 0x55, 0x41, 0xc7, 0x4f, 0x3b, 0xaf, 0x68, 0xe4, 0x86, 0x36, - 0xe4, 0x15, 0xa7, 0x8c, 0xf3, 0x4b, 0x0a, 0xb2, 0xde, 0x29, 0xf9, 0x05, - 0x53, 0xa6, 0x96, 0xfc, 0xfd, 0xbe, 0x1d, 0x1c, 0x91, 0x83, 0x95, 0x1e, - 0xc8, 0x86, 0xb2, 0x4c, 0xd8, 0x22, 0x0e, 0x64, 0x54, 0x4a, 0x2a, 0x11, - 0x23, 0x6f, 0x1f, 0xd7, 0xfa, 0x5f, 0xb2, 0x24, 0x93, 0xb7, 0x29, 0x47, - 0x89, 0xe7, 0xed, 0x62, 0x2c, 0x0c, 0x7b, 0x5b, 0xb2, 0x8a, 0x66, 0x58, - 0x28, 0xc7, 0x44, 0xec, 0xf7, 0x21, 0xcb, 0x27, 0xcb, 0x92, 0xf9, 0x74, - 0xd9, 0x97, 0xb1, 0x2b, 0xdf, 0xcf, 0x94, 0x3f, 0xd5, 0x29, 0xed, 0xea, - 0x9e, 0x16, 0xf9, 0x0d, 0xec, 0x25, 0xee, 0x4d, 0x7b, 0xb1, 0xcf, 0x85, - 0x73, 0xf7, 0x26, 0x9e, 0x10, 0x21, 0x6c, 0xa9, 0xbf, 0x45, 0xfb, 0x88, - 0x18, 0x59, 0xab, 0x18, 0x0b, 0x01, 0x2e, 0x2f, 0xa5, 0x51, 0x6f, 0xae, - 0x25, 0x6b, 0xdd, 0x0a, 0xcd, 0xd8, 0x89, 0x78, 0x49, 0x6e, 0x85, 0x2e, - 0xdb, 0x7a, 0x6e, 0x47, 0xd6, 0x72, 0x64, 0x19, 0xd8, 0x9f, 0x83, 0x3f, - 0x5c, 0x04, 0x47, 0x5f, 0x2a, 0xeb, 0xf9, 0x4e, 0xec, 0x4f, 0xb6, 0x00, - 0x67, 0xbb, 0x24, 0x92, 0x35, 0xcc, 0x5f, 0x76, 0xe7, 0xbb, 0x5d, 0xbc, - 0xa5, 0xfe, 0x76, 0x8d, 0x5b, 0xe4, 0x65, 0x77, 0xfe, 0x0e, 0x17, 0x77, - 0xe9, 0x3e, 0xcc, 0x03, 0xff, 0xe0, 0xc4, 0x90, 0xa1, 0xe7, 0x7b, 0xe9, - 0x4f, 0xbf, 0x5e, 0xbe, 0x15, 0x5a, 0xb6, 0x1d, 0xc9, 0x8d, 0x0e, 0x4e, - 0x0c, 0x1a, 0x2e, 0xbe, 0x13, 0xee, 0xbe, 0xbb, 0x5d, 0x7c, 0x83, 0x13, - 0x49, 0xc3, 0xc5, 0xb7, 0x54, 0xd6, 0x7b, 0x25, 0x5f, 0x26, 0xec, 0xe0, - 0x84, 0x65, 0xdc, 0x2d, 0x53, 0xdd, 0x83, 0x13, 0x7b, 0x0d, 0x75, 0xcf, - 0x4e, 0x97, 0x8f, 0x84, 0x4f, 0xc3, 0x4e, 0x4d, 0x03, 0xcf, 0xd5, 0xf3, - 0x03, 0x59, 0xab, 0x74, 0xdf, 0x4e, 0x7d, 0x3e, 0xcf, 0xd4, 0x73, 0xf7, - 0x91, 0x2e, 0x9e, 0x5d, 0x18, 0xdd, 0x74, 0xee, 0xcf, 0xdc, 0x96, 0xcf, - 0x76, 0x67, 0xf2, 0x3c, 0x89, 0x84, 0xd3, 0xe1, 0xd1, 0x99, 0xf2, 0x11, - 0xc9, 0x56, 0xe2, 0x32, 0x3d, 0xb2, 0x43, 0xa6, 0xcc, 0xfe, 0xa9, 0x83, - 0xc2, 0xd8, 0x13, 0x19, 0x2d, 0x78, 0x3a, 0xcc, 0x89, 0x21, 0xd3, 0xe0, - 0xf1, 0x60, 0x5d, 0x22, 0x06, 0xe0, 0xfb, 0xeb, 0x61, 0x79, 0xbe, 0x61, - 0x48, 0xab, 0xf6, 0xcf, 0x84, 0xb9, 0x06, 0x3b, 0x7c, 0xb6, 0x42, 0x3b, - 0xa6, 0xcd, 0x4a, 0xa6, 0x06, 0x3b, 0xbd, 0xa0, 0x7d, 0xb5, 0x9d, 0x7a, - 0x2d, 0x16, 0x05, 0xae, 0x98, 0xb6, 0xcc, 0x9a, 0xb4, 0x49, 0x66, 0x52, - 0x8a, 0x5c, 0xf7, 0x7c, 0x27, 0xb6, 0x28, 0xdf, 0x85, 0x0d, 0x88, 0x99, - 0x4d, 0x71, 0x9e, 0xf0, 0x4d, 0xb0, 0xa6, 0xeb, 0x77, 0x21, 0xf8, 0x5d, - 0x21, 0x45, 0x58, 0x29, 0xea, 0x58, 0xd1, 0x80, 0x2d, 0x36, 0xee, 0xee, - 0x74, 0x63, 0x5d, 0x04, 0xfe, 0xd9, 0x01, 0x1f, 0xbf, 0x07, 0xfe, 0xd7, - 0x67, 0x64, 0xcf, 0x38, 0x0e, 0x62, 0x4f, 0x54, 0x09, 0xfd, 0x0f, 0xbe, - 0xde, 0xe0, 0x5a, 0x07, 0xe6, 0xc5, 0x9c, 0xb6, 0xbb, 0xc1, 0x9f, 0xe3, - 0x4c, 0xd8, 0x71, 0x29, 0xd9, 0xbb, 0xb0, 0xaf, 0x45, 0xba, 0x2d, 0xda, - 0x3b, 0x7d, 0x7a, 0x27, 0xce, 0x33, 0xf8, 0xdd, 0x85, 0xf3, 0x3a, 0x31, - 0x17, 0x9b, 0xa6, 0x1f, 0xa7, 0x18, 0xb3, 0xdc, 0xf8, 0x29, 0x72, 0x15, - 0xb4, 0x72, 0x8f, 0x86, 0x8b, 0xb4, 0xa5, 0x53, 0x72, 0xa3, 0xdc, 0x2b, - 0x57, 0xa2, 0xe4, 0x1f, 0x38, 0x2b, 0x88, 0x87, 0x51, 0x03, 0xf4, 0x93, - 0x6e, 0xc6, 0xbf, 0xdd, 0xde, 0xb7, 0x71, 0xaf, 0x7b, 0x86, 0x98, 0xa1, - 0x74, 0x97, 0xe4, 0xf4, 0x9c, 0x28, 0x35, 0xba, 0xd3, 0x5b, 0xef, 0x32, - 0x0e, 0x9c, 0x51, 0x32, 0xf4, 0x20, 0x62, 0x16, 0xce, 0xba, 0x6c, 0x39, - 0xce, 0x65, 0xfb, 0xc7, 0xf0, 0x79, 0x25, 0x2d, 0xd6, 0x7a, 0x97, 0xb4, - 0x43, 0x9e, 0x15, 0xa3, 0x49, 0x86, 0x31, 0x39, 0x51, 0xe1, 0x9e, 0xa2, - 0x84, 0x2d, 0xc2, 0x10, 0xfe, 0x47, 0x80, 0x0b, 0x49, 0x1b, 0x7c, 0xf1, - 0xa2, 0x1d, 0x25, 0xbd, 0xbb, 0x5c, 0xf8, 0x6e, 0x9c, 0x41, 0xda, 0xe9, - 0x7b, 0x8e, 0xf6, 0xbd, 0x6c, 0x48, 0x65, 0xc6, 0xe7, 0xe1, 0x49, 0x23, - 0x94, 0x77, 0xb6, 0x1b, 0xa1, 0x5f, 0xa6, 0x87, 0x8a, 0xa6, 0xd2, 0xba, - 0x16, 0xc9, 0x95, 0xef, 0x95, 0x19, 0x1b, 0xe7, 0x59, 0x61, 0xd0, 0xcc, - 0x38, 0x33, 0x50, 0x0c, 0x29, 0x78, 0x58, 0x0f, 0x65, 0xe5, 0xd3, 0xfa, - 0x16, 0xce, 0x2b, 0x1a, 0x61, 0x8b, 0x67, 0xfc, 0xb2, 0x27, 0x1f, 0xda, - 0x9d, 0x2d, 0xd9, 0x72, 0x07, 0xbf, 0x41, 0x47, 0xbb, 0xa6, 0x23, 0x94, - 0xd6, 0xba, 0x33, 0x54, 0xda, 0x8f, 0xff, 0x04, 0xdd, 0x84, 0x07, 0x7c, - 0x70, 0xaf, 0x85, 0xbd, 0x11, 0xd0, 0xd8, 0xd9, 0x44, 0x7f, 0x3b, 0xe1, - 0x21, 0xab, 0x88, 0x77, 0x86, 0xe6, 0xdb, 0x70, 0xf9, 0xf6, 0x65, 0xf5, - 0x2a, 0x64, 0xf5, 0xbe, 0x33, 0xb4, 0x8f, 0x38, 0x52, 0xc0, 0x01, 0xb9, - 0x9b, 0x8c, 0x57, 0x8c, 0x51, 0xe6, 0x06, 0x2e, 0xf8, 0x81, 0x0a, 0xa5, - 0x3b, 0x24, 0x67, 0xea, 0x1c, 0x00, 0xd8, 0x31, 0xd1, 0x31, 0xde, 0x22, - 0x8f, 0xde, 0xb7, 0x95, 0xd0, 0x76, 0x93, 0xaf, 0x32, 0x0f, 0xfc, 0x31, - 0x68, 0x5b, 0x4b, 0x28, 0xcd, 0x5a, 0x07, 0x64, 0x2e, 0x91, 0x96, 0xf4, - 0x1b, 0xb2, 0x5c, 0x56, 0x7b, 0x5a, 0x65, 0x97, 0x4c, 0x42, 0x46, 0xb5, - 0x31, 0xe4, 0xaf, 0x91, 0x0e, 0x09, 0xdd, 0xcf, 0x3c, 0x10, 0x03, 0xad, - 0x6b, 0x09, 0x53, 0x6e, 0x39, 0x6a, 0x10, 0xfb, 0x47, 0xa0, 0x87, 0x43, - 0xd4, 0xa9, 0xf2, 0xe0, 0x08, 0x13, 0xa2, 0xcc, 0x7b, 0x5a, 0x85, 0xb8, - 0xb9, 0x36, 0x1c, 0x33, 0x85, 0xf3, 0xc8, 0x95, 0x93, 0xdc, 0x4b, 0xfe, - 0xdc, 0x3d, 0x1f, 0xe6, 0xcf, 0x5f, 0xa7, 0xcc, 0x28, 0x3b, 0xd8, 0x18, - 0x78, 0xcc, 0xda, 0xbf, 0xe0, 0xc9, 0xe6, 0x4e, 0xb9, 0x62, 0x8a, 0x51, - 0xb3, 0xef, 0x68, 0x92, 0x1f, 0x79, 0xee, 0xde, 0xc2, 0x33, 0x71, 0x6c, - 0xcf, 0xf7, 0xe1, 0x2a, 0xcf, 0x74, 0xcf, 0x9e, 0xb1, 0xd6, 0x12, 0x61, - 0xd9, 0x2c, 0x5f, 0xe8, 0x52, 0x0a, 0x65, 0xda, 0x46, 0xab, 0xe4, 0x51, - 0x8f, 0xd8, 0xfb, 0x10, 0x54, 0x1e, 0x57, 0x32, 0xfa, 0x20, 0x71, 0xfe, - 0x23, 0x79, 0x1a, 0x8b, 0x2b, 0x43, 0xf2, 0x3a, 0xf7, 0xfb, 0xfa, 0xe2, - 0x5c, 0xb3, 0x6d, 0xbf, 0xea, 0xd9, 0xf6, 0xfb, 0xce, 0xe8, 0x3e, 0x5f, - 0xef, 0x90, 0xd7, 0x87, 0xf6, 0x08, 0xf4, 0xfc, 0x7f, 0xed, 0xa1, 0xad, - 0x44, 0xb6, 0xec, 0x29, 0x6e, 0xb3, 0x67, 0xb7, 0xc8, 0x2f, 0xd1, 0x87, - 0xba, 0xbd, 0x98, 0xe1, 0xfb, 0x94, 0x8f, 0x07, 0xba, 0xd1, 0xb6, 0xca, - 0xb9, 0xed, 0x7c, 0x91, 0x38, 0x88, 0x8b, 0x7b, 0x09, 0xe3, 0xe7, 0x54, - 0xa8, 0x43, 0xb6, 0xcd, 0xab, 0x18, 0x13, 0x78, 0x57, 0x88, 0x43, 0xcd, - 0xf9, 0x95, 0x73, 0x26, 0xbe, 0xc7, 0xf1, 0xb4, 0x24, 0x5f, 0xa7, 0x3f, - 0x71, 0x3f, 0xf3, 0xed, 0x4d, 0x2f, 0x7e, 0x76, 0x4c, 0x85, 0xd3, 0x51, - 0xc4, 0x4f, 0x99, 0x2c, 0x95, 0x8f, 0xa3, 0x26, 0x92, 0xe2, 0x5d, 0x69, - 0xda, 0x47, 0xc7, 0x18, 0x62, 0xe4, 0x64, 0xa9, 0xce, 0xba, 0x08, 0x61, - 0x0c, 0xfb, 0x90, 0xa3, 0x23, 0x6a, 0x2e, 0x52, 0xfc, 0x58, 0x9a, 0x71, - 0x39, 0x2e, 0xf1, 0xfa, 0x3b, 0xa8, 0x3b, 0x4c, 0xc9, 0x6a, 0x5b, 0xfb, - 0xb3, 0x5e, 0xd2, 0x5b, 0x42, 0x0d, 0x11, 0x4e, 0x4b, 0x58, 0xa5, 0x5b, - 0x23, 0xd3, 0xa9, 0x0e, 0xd4, 0x5a, 0x13, 0xbd, 0x6a, 0xf5, 0x60, 0x6f, - 0x68, 0x75, 0xcf, 0x54, 0x4b, 0xba, 0xd8, 0xab, 0xe6, 0x44, 0x16, 0xcb, - 0xa2, 0x50, 0xd7, 0xc4, 0x0e, 0x0b, 0xbe, 0x57, 0x3f, 0xfb, 0x59, 0x95, - 0x0e, 0x41, 0xb7, 0x72, 0x6c, 0x29, 0x15, 0x66, 0x0d, 0x19, 0x9f, 0x94, - 0x63, 0xa8, 0x1b, 0x9f, 0x91, 0xe9, 0x32, 0xe8, 0xd2, 0x7c, 0xc7, 0xc0, - 0x6f, 0x1f, 0x70, 0x93, 0xf6, 0x28, 0x62, 0xac, 0x4b, 0x3b, 0x68, 0xce, - 0xe4, 0x58, 0x27, 0xa5, 0x98, 0x57, 0xde, 0x81, 0xfd, 0xd0, 0x5f, 0xfe, - 0x59, 0x96, 0xad, 0x1d, 0x92, 0x77, 0xe3, 0x03, 0xed, 0x15, 0x6b, 0x37, - 0xbd, 0xb5, 0x6b, 0x58, 0xa3, 0xfd, 0xee, 0x6c, 0xd2, 0xe1, 0x97, 0x75, - 0xad, 0x73, 0xd9, 0xe6, 0x3b, 0x61, 0xff, 0x76, 0xd4, 0x85, 0x7d, 0x7d, - 0x74, 0xd9, 0xfa, 0xdc, 0x2e, 0x69, 0x37, 0xa9, 0x37, 0x9c, 0x13, 0x65, - 0x8c, 0xc5, 0xfa, 0x15, 0x0f, 0xd7, 0x5b, 0xc0, 0xd5, 0x41, 0xba, 0x31, - 0xc2, 0x58, 0x07, 0x7d, 0xa8, 0x79, 0xf2, 0x1b, 0xb1, 0x86, 0xb0, 0xdf, - 0xf1, 0x70, 0x7d, 0xab, 0x09, 0x17, 0xd7, 0xf8, 0xe4, 0x99, 0x38, 0xbb, - 0x9d, 0xbc, 0x91, 0x1f, 0xea, 0x80, 0xfa, 0x48, 0x1a, 0x93, 0x88, 0xed, - 0x93, 0x0d, 0x5d, 0xdb, 0x19, 0xb9, 0x0a, 0x6a, 0xae, 0xc6, 0x8b, 0xa0, - 0x11, 0xb5, 0x58, 0x63, 0xd0, 0xab, 0xb7, 0x69, 0x47, 0x6b, 0xda, 0x1e, - 0x19, 0x77, 0x4a, 0xda, 0xae, 0x2e, 0xb9, 0x76, 0x65, 0x51, 0x37, 0x97, - 0x64, 0x6f, 0xbd, 0xba, 0xcb, 0xfd, 0xbf, 0xdb, 0xa6, 0x84, 0xb4, 0x3e, - 0x99, 0xdf, 0x68, 0x63, 0x77, 0x22, 0xae, 0x3b, 0xef, 0x32, 0xcf, 0x4c, - 0x32, 0x07, 0x4d, 0x32, 0x77, 0x18, 0x5e, 0x3c, 0x8c, 0x37, 0xe1, 0x88, - 0x03, 0xc7, 0x8a, 0x67, 0xbf, 0x73, 0x1e, 0x2e, 0xbf, 0xfe, 0xf4, 0x63, - 0xea, 0x9f, 0xdf, 0xb5, 0x79, 0x5d, 0x99, 0xee, 0x77, 0xab, 0x8e, 0xc7, - 0xb0, 0x75, 0xd0, 0x1f, 0x9f, 0x52, 0xb0, 0xaf, 0x5c, 0xdd, 0xd5, 0x07, - 0x7c, 0x1f, 0xb6, 0xc7, 0x57, 0x5f, 0xb7, 0x6e, 0xfd, 0xed, 0xca, 0x80, - 0x3a, 0xcd, 0x90, 0xef, 0x4c, 0x98, 0xb4, 0x34, 0x26, 0xb0, 0x5f, 0x8e, - 0x30, 0x37, 0xe6, 0xc1, 0xc7, 0x61, 0x73, 0xd8, 0x9c, 0x26, 0xee, 0xa8, - 0x00, 0x27, 0x6a, 0xc9, 0x74, 0x9b, 0xa7, 0xe7, 0x6f, 0xf3, 0x7c, 0xe0, - 0xde, 0xc9, 0x6f, 0x3c, 0xbf, 0xed, 0xd1, 0x73, 0xa3, 0xcb, 0xa5, 0xc7, - 0x5f, 0x1f, 0x34, 0x37, 0x7f, 0xaf, 0xf4, 0x7a, 0xf2, 0xc4, 0xfb, 0x33, - 0x1e, 0x5d, 0xd4, 0x4d, 0x33, 0x4d, 0xd4, 0xcb, 0xbb, 0xc0, 0xa3, 0x6b, - 0x8d, 0xa2, 0x4a, 0xa3, 0x76, 0x49, 0x31, 0x67, 0x25, 0xc6, 0x32, 0x62, - 0x41, 0x27, 0x09, 0x7b, 0x0a, 0xbb, 0x6e, 0x96, 0xa9, 0xe7, 0x5b, 0x88, - 0xd5, 0xd4, 0xfb, 0x7b, 0x32, 0x53, 0xee, 0xb7, 0x5b, 0x0d, 0xfa, 0x6b, - 0x22, 0xb9, 0x22, 0xc3, 0xf6, 0x8a, 0xae, 0xa1, 0x12, 0xf1, 0x13, 0x42, - 0xd9, 0xde, 0x92, 0x01, 0x5d, 0xdb, 0xbc, 0x27, 0x16, 0xe4, 0x32, 0x59, - 0x81, 0x8f, 0xed, 0xfb, 0x57, 0x47, 0xd7, 0xa4, 0x08, 0x6f, 0xd7, 0xb7, - 0xc1, 0xf5, 0xba, 0xc6, 0x43, 0x7c, 0xcd, 0xb8, 0x0c, 0x69, 0xdb, 0xe7, - 0xe3, 0xb3, 0x64, 0xb6, 0xe1, 0xe3, 0x0c, 0x23, 0x2e, 0x23, 0x06, 0xec, - 0xfb, 0xbc, 0x67, 0x2f, 0x7c, 0xff, 0xbe, 0xc3, 0x5a, 0x48, 0xa5, 0xbf, - 0xea, 0xcd, 0x7d, 0x8f, 0x32, 0xc0, 0xb7, 0x2f, 0xf7, 0x17, 0xbd, 0x78, - 0x53, 0x34, 0x32, 0x0d, 0xca, 0x80, 0xb6, 0x02, 0xfd, 0x6b, 0xfb, 0x84, - 0xcf, 0x54, 0x3e, 0x89, 0x98, 0xd5, 0xed, 0xd6, 0x0f, 0xe8, 0xaf, 0x32, - 0x0d, 0xce, 0xad, 0xb5, 0x65, 0xed, 0x16, 0xcf, 0x97, 0x0e, 0x62, 0x6e, - 0x12, 0x7f, 0x94, 0x1d, 0x61, 0x0e, 0xe1, 0x3d, 0xe3, 0xc1, 0xc9, 0x58, - 0x16, 0xb9, 0x2b, 0x73, 0x68, 0x1c, 0xdf, 0x86, 0xd7, 0x67, 0x69, 0xb9, - 0x57, 0x51, 0xab, 0x40, 0x9e, 0x03, 0xe0, 0x27, 0x2e, 0xe3, 0x0d, 0xe8, - 0x7c, 0x23, 0x9e, 0x6d, 0xc0, 0x14, 0x6f, 0xc3, 0xb8, 0xb1, 0x6f, 0xbc, - 0xf1, 0xa6, 0xc3, 0x78, 0xf0, 0x57, 0xda, 0x5f, 0xe2, 0xa0, 0xdd, 0xef, - 0xd5, 0x32, 0xc6, 0x63, 0x95, 0x09, 0xe3, 0xf1, 0x0a, 0xf7, 0xa8, 0xaf, - 0xf5, 0x88, 0x15, 0xcf, 0x2a, 0xd4, 0xa9, 0xfb, 0xba, 0x70, 0xe6, 0x09, - 0xd8, 0x46, 0xd1, 0x98, 0x1c, 0xda, 0x25, 0xf9, 0x64, 0x0f, 0x68, 0x7e, - 0x08, 0xcf, 0x56, 0xcc, 0xff, 0x3c, 0xe6, 0x61, 0x47, 0x49, 0xfa, 0xc7, - 0x0e, 0xdd, 0x5b, 0x4e, 0x99, 0xa4, 0x71, 0xc0, 0xb3, 0xad, 0x37, 0x4d, - 0xd7, 0x96, 0x9e, 0xc6, 0xf7, 0x4e, 0xcc, 0x7f, 0x01, 0x4f, 0xe4, 0xb2, - 0x7d, 0xfe, 0x3c, 0x7d, 0x70, 0x0c, 0xf3, 0x0f, 0x00, 0xc7, 0x1f, 0xe0, - 0xfd, 0x5e, 0xbc, 0xff, 0xde, 0x96, 0xbd, 0xbf, 0xcb, 0xb3, 0x31, 0x9f, - 0xdd, 0x32, 0xef, 0xc7, 0x6f, 0x9e, 0x27, 0xd2, 0xbd, 0x0a, 0xc6, 0x57, - 0x23, 0xb2, 0x7b, 0xa5, 0x5d, 0x54, 0xcd, 0x8d, 0xe1, 0xaa, 0x66, 0x4a, - 0xcf, 0x0a, 0xe3, 0xf7, 0x0f, 0xb0, 0xc7, 0x12, 0xb5, 0x0a, 0xa5, 0x51, - 0xb7, 0xda, 0x47, 0x9f, 0x39, 0xba, 0x77, 0x81, 0xcf, 0xe2, 0xd1, 0xd1, - 0x3a, 0x61, 0xf8, 0x7e, 0xec, 0xe8, 0xde, 0xfa, 0x3f, 0x00, 0x16, 0x72, - 0xa9, 0xf8, 0xf8, 0x09, 0x7f, 0x7e, 0xcb, 0x99, 0x5a, 0xb6, 0x38, 0x93, - 0x7e, 0xff, 0xcc, 0xd1, 0x6c, 0x95, 0x75, 0x42, 0x22, 0x26, 0xba, 0x16, - 0x2f, 0x1e, 0x2d, 0x20, 0x3f, 0x86, 0x34, 0x2d, 0xfe, 0x3a, 0xd7, 0xa8, - 0x87, 0xed, 0x68, 0x23, 0x5d, 0xcd, 0x78, 0x98, 0x67, 0x88, 0xe7, 0x18, - 0xf0, 0x24, 0x81, 0x87, 0xf9, 0xc6, 0xa5, 0x37, 0xbe, 0xb0, 0x1d, 0x6d, - 0xc4, 0xc5, 0xb3, 0x7c, 0x7c, 0x3d, 0xa2, 0x56, 0x7e, 0x48, 0x7a, 0x4d, - 0xd6, 0xb6, 0x6e, 0xac, 0x69, 0x91, 0xfc, 0x69, 0xe6, 0xec, 0x7d, 0xde, - 0x37, 0xca, 0x18, 0xf4, 0xdc, 0x71, 0xc5, 0x79, 0x3e, 0xb1, 0x96, 0x62, - 0xb9, 0x82, 0xef, 0x45, 0x1f, 0x56, 0x79, 0xb0, 0x9d, 0x4d, 0x7c, 0xb7, - 0x78, 0xb2, 0xe6, 0x99, 0x7e, 0xef, 0xd9, 0x4c, 0x0b, 0x40, 0xa1, 0x87, - 0xee, 0x0d, 0x3d, 0xf8, 0x7c, 0x62, 0x61, 0x95, 0xb4, 0x25, 0xc1, 0xab, - 0x4f, 0xdb, 0x47, 0xd5, 0x1f, 0xf7, 0x26, 0xf1, 0xe7, 0x9f, 0xe7, 0xcb, - 0x80, 0x74, 0xf1, 0x09, 0x5b, 0xfe, 0x50, 0xef, 0x9c, 0x84, 0xdf, 0xf1, - 0x1e, 0xc4, 0x71, 0x96, 0x6d, 0xca, 0xbe, 0x0d, 0x7a, 0x27, 0x2f, 0x06, - 0x7a, 0x09, 0xc5, 0x9a, 0x2e, 0xce, 0x9e, 0xf5, 0x49, 0xb9, 0x0a, 0x5c, - 0x19, 0xf4, 0x95, 0x6e, 0x6f, 0x34, 0x85, 0xf8, 0xb8, 0x06, 0xfb, 0xbc, - 0x6c, 0xf1, 0x3e, 0x26, 0xcc, 0x7c, 0x27, 0xa5, 0xfa, 0xbf, 0x00, 0x86, - 0xf5, 0xd5, 0xed, 0xbb, 0x96, 0x05, 0xc0, 0x2c, 0x62, 0xed, 0x84, 0x1b, - 0x97, 0x19, 0xdb, 0x1d, 0x85, 0xda, 0xa3, 0x60, 0xfd, 0xb7, 0xc3, 0x3a, - 0xeb, 0x36, 0xec, 0x76, 0x77, 0x21, 0xc8, 0x39, 0xf3, 0x89, 0xd9, 0x05, - 0xc4, 0xf0, 0xaa, 0xa5, 0x76, 0x2b, 0x6d, 0x91, 0x89, 0x2a, 0x62, 0x12, - 0xba, 0xde, 0x44, 0x7c, 0x41, 0xfe, 0x53, 0xeb, 0xa1, 0xc5, 0x1a, 0x36, - 0x7b, 0xd4, 0xe7, 0x68, 0x57, 0x9a, 0xf2, 0xd0, 0x29, 0xe4, 0xe5, 0x91, - 0xc7, 0x90, 0x73, 0x20, 0xaf, 0x53, 0x45, 0x74, 0xf2, 0xb4, 0x91, 0x37, - 0x7e, 0xab, 0x60, 0xb9, 0x7d, 0x80, 0xce, 0x67, 0xe2, 0xf2, 0x18, 0x3a, - 0xd5, 0xa1, 0xe3, 0x4c, 0x5e, 0xc7, 0x9b, 0x7e, 0x73, 0x52, 0xb5, 0xa3, - 0xc6, 0x40, 0x01, 0x8a, 0x0a, 0xc7, 0x1c, 0x14, 0xd9, 0x3b, 0x87, 0xb8, - 0x82, 0x38, 0xbc, 0x77, 0x15, 0xd1, 0xed, 0x14, 0xe1, 0x95, 0x84, 0x4f, - 0x85, 0xa4, 0xe5, 0x14, 0xef, 0x43, 0x64, 0x0f, 0xfa, 0x31, 0xe2, 0xdc, - 0x1b, 0xc6, 0x73, 0x1c, 0x7f, 0xfb, 0x51, 0x5b, 0x99, 0xa8, 0x91, 0xb7, - 0x81, 0x07, 0x2c, 0xf7, 0x6c, 0x07, 0x6f, 0x76, 0x4b, 0x7b, 0x04, 0x7b, - 0x08, 0x1f, 0x06, 0x1d, 0x7b, 0x40, 0x8f, 0x7b, 0x3e, 0x71, 0x84, 0x4f, - 0x89, 0xf4, 0xcf, 0x49, 0x8f, 0xd2, 0x7b, 0xc2, 0x52, 0x48, 0x71, 0xad, - 0x03, 0xf0, 0xdc, 0x87, 0x35, 0xbd, 0xcf, 0xbd, 0x57, 0xca, 0xdf, 0xa6, - 0x1b, 0x73, 0x06, 0xde, 0x51, 0x4f, 0xa5, 0x4c, 0xe9, 0xaf, 0xb9, 0xb0, - 0x7b, 0x57, 0xbf, 0xd4, 0xcd, 0xbb, 0x29, 0x65, 0xb9, 0xb4, 0x29, 0xd4, - 0xc4, 0x79, 0x48, 0x35, 0x3c, 0xc8, 0xfb, 0x19, 0xc2, 0xb0, 0xaf, 0x35, - 0x35, 0x8c, 0x39, 0x48, 0xf9, 0xb9, 0x73, 0x4a, 0xfd, 0x6f, 0xf7, 0x2e, - 0xcd, 0x35, 0x85, 0xf6, 0x15, 0xec, 0xff, 0x43, 0xed, 0x2b, 0xa2, 0xe2, - 0x9e, 0xaf, 0xe0, 0x7b, 0x91, 0xdf, 0x7e, 0x2e, 0xfe, 0xed, 0xbb, 0xdc, - 0x78, 0xef, 0xc8, 0xb4, 0xcd, 0x3b, 0x0c, 0x47, 0x2e, 0xdb, 0x45, 0xe3, - 0x91, 0x4d, 0x75, 0x66, 0x52, 0xe7, 0xe7, 0x02, 0x64, 0xbf, 0x5e, 0xd7, - 0x3d, 0x9b, 0x5c, 0xa9, 0x47, 0xe4, 0xea, 0x52, 0xbb, 0xac, 0x2f, 0xb8, - 0x36, 0xbf, 0xbe, 0x40, 0x3b, 0x37, 0xe5, 0xed, 0x25, 0x0b, 0x6b, 0x49, - 0xfc, 0xf5, 0xc8, 0xf5, 0xa5, 0xcd, 0x75, 0xe7, 0x85, 0xc6, 0xc3, 0xa0, - 0xa5, 0x47, 0x42, 0x96, 0xa3, 0xfb, 0xaf, 0x1c, 0x72, 0x5f, 0x51, 0xc6, - 0x25, 0x5f, 0xe9, 0x47, 0x0f, 0x88, 0xe4, 0x1c, 0x66, 0x0e, 0x82, 0xfe, - 0x2b, 0x9f, 0x40, 0x6d, 0x92, 0x80, 0xf3, 0xf4, 0xeb, 0x7b, 0xc5, 0x4f, - 0x85, 0x7b, 0xa4, 0xd5, 0xfa, 0xa3, 0x6e, 0x37, 0x57, 0x99, 0x6e, 0x9f, - 0x6a, 0xf9, 0xf9, 0xfa, 0x75, 0xe0, 0x1e, 0x81, 0x9d, 0xd2, 0x36, 0x6d, - 0xd8, 0xac, 0x29, 0xcb, 0x43, 0x89, 0x6a, 0x51, 0x18, 0x1f, 0x52, 0x38, - 0xd3, 0xc0, 0xbe, 0x24, 0xe4, 0xb1, 0x43, 0xd7, 0x42, 0x19, 0x05, 0xdd, - 0xce, 0xcd, 0x48, 0xbe, 0xf1, 0x9b, 0x98, 0xcf, 0xc8, 0x54, 0x63, 0x0c, - 0x67, 0x9d, 0xa4, 0xdd, 0xf6, 0x48, 0x3b, 0xcf, 0x49, 0x81, 0xc6, 0x87, - 0xa4, 0x70, 0x7a, 0x46, 0x0e, 0x57, 0x48, 0x27, 0xef, 0x19, 0x13, 0xc9, - 0x9c, 0x0c, 0xc7, 0x97, 0x50, 0x3b, 0xb9, 0xfe, 0x98, 0x96, 0xc2, 0x19, - 0xe0, 0xa8, 0xf0, 0x1e, 0xa0, 0x1f, 0x76, 0x33, 0xac, 0xfb, 0x9a, 0x29, - 0x1d, 0x77, 0x38, 0xff, 0x43, 0xe8, 0xa9, 0xbf, 0xb8, 0x1f, 0x70, 0x79, - 0xf4, 0x40, 0x93, 0xa8, 0x97, 0x17, 0x2b, 0xe8, 0xf7, 0xec, 0x10, 0x6b, - 0x2f, 0xa5, 0xee, 0xef, 0x93, 0x5a, 0x65, 0xd8, 0x54, 0x8a, 0x35, 0x15, - 0x75, 0xc1, 0x35, 0xfa, 0x77, 0x4c, 0x85, 0xad, 0x3e, 0x59, 0xaa, 0x14, - 0xd1, 0x37, 0x2b, 0xef, 0x5e, 0x03, 0x16, 0x60, 0xb9, 0x71, 0x2f, 0xa3, - 0xc8, 0x37, 0xea, 0xcf, 0xc6, 0x27, 0x41, 0x63, 0x26, 0x6e, 0xca, 0x71, - 0xd0, 0x87, 0xf7, 0x45, 0xd8, 0xf8, 0x1c, 0x6b, 0xb8, 0x0c, 0xd6, 0xd2, - 0x72, 0xe4, 0xec, 0x24, 0x68, 0xe8, 0x92, 0xfe, 0x3f, 0xa1, 0x8f, 0x3d, - 0x81, 0x39, 0x7e, 0x27, 0x60, 0xaf, 0x5f, 0xc4, 0x3b, 0x61, 0x63, 0x78, - 0x52, 0x0e, 0x7d, 0x78, 0x9a, 0xa0, 0x25, 0xe2, 0xf6, 0x26, 0x87, 0xe2, - 0x52, 0x3b, 0xfd, 0xa0, 0x4c, 0x2d, 0x3e, 0x08, 0xfc, 0x3f, 0x42, 0x5f, - 0x80, 0xfc, 0xb6, 0xc8, 0xb3, 0x58, 0xff, 0xf1, 0x9c, 0x9d, 0x3d, 0xda, - 0x37, 0xe6, 0x38, 0xcf, 0xe7, 0x41, 0xec, 0x47, 0x8f, 0x51, 0xc9, 0x48, - 0xa1, 0xc2, 0xb3, 0xa0, 0x3b, 0xd4, 0x53, 0xf9, 0xd3, 0x93, 0x9e, 0x8e, - 0x7b, 0x24, 0x17, 0x2d, 0xb2, 0xbf, 0x40, 0x9e, 0x58, 0x18, 0xcd, 0x96, - 0x13, 0x66, 0x56, 0x11, 0x57, 0x52, 0x98, 0x1b, 0xdc, 0xb9, 0x88, 0x58, - 0x73, 0xe8, 0x6d, 0xd3, 0x5c, 0x3b, 0xee, 0xdd, 0x1d, 0x10, 0xd7, 0x9b, - 0x32, 0x0e, 0x1b, 0xeb, 0x9f, 0x1b, 0x41, 0x2d, 0xfc, 0x16, 0x6a, 0xc9, - 0x84, 0x27, 0x83, 0x31, 0xcf, 0x36, 0xda, 0x9b, 0x6c, 0x02, 0x7a, 0xae, - 0x40, 0xf7, 0x15, 0xd8, 0x01, 0x62, 0xf5, 0x2b, 0x1b, 0xf6, 0x31, 0xd6, - 0x54, 0x63, 0x76, 0xca, 0xdf, 0x54, 0x13, 0xc9, 0x35, 0xd8, 0xcf, 0x75, - 0xf4, 0x02, 0x6b, 0xe8, 0x55, 0xd7, 0xd1, 0xd7, 0x2d, 0x96, 0x0f, 0x81, - 0x7e, 0xd6, 0x94, 0xfc, 0x8e, 0xe9, 0x5a, 0xa7, 0xcd, 0x7a, 0xe1, 0x2e, - 0x7d, 0xb7, 0x2b, 0x4f, 0xf4, 0xb0, 0xd7, 0x64, 0x5f, 0xce, 0x7b, 0xe9, - 0xab, 0xd0, 0xe3, 0x9a, 0xc9, 0x75, 0x7f, 0x1f, 0x7b, 0x01, 0xdf, 0x7e, - 0x48, 0x0b, 0xed, 0x87, 0x7b, 0x08, 0xd3, 0xa3, 0xfd, 0x24, 0xaf, 0xf1, - 0xd1, 0x66, 0xeb, 0xdd, 0xae, 0x9f, 0xe9, 0x3a, 0xcb, 0xbc, 0x22, 0xbe, - 0xfd, 0xbe, 0xe7, 0xb0, 0xaf, 0xcb, 0x0e, 0x21, 0x76, 0x37, 0x1c, 0x79, - 0xc1, 0xde, 0xec, 0x77, 0x07, 0x2a, 0xbe, 0x9c, 0x28, 0xc7, 0x43, 0x72, - 0xa2, 0x91, 0x80, 0x4f, 0x50, 0x86, 0x56, 0x93, 0x0c, 0x45, 0xbe, 0x5e, - 0x11, 0x79, 0xb9, 0xc2, 0x35, 0x2d, 0xc3, 0x58, 0x36, 0xd4, 0xce, 0xbb, - 0x75, 0xd8, 0xe5, 0xdf, 0xcb, 0xe1, 0x79, 0x91, 0xb3, 0x58, 0x5f, 0xae, - 0xd0, 0x57, 0x47, 0x50, 0xbf, 0xee, 0x94, 0xda, 0x02, 0x7a, 0xb2, 0x8a, - 0x4c, 0x65, 0x1f, 0x60, 0xbe, 0x89, 0xc8, 0xba, 0xbe, 0x93, 0x15, 0x19, - 0x3c, 0x17, 0x96, 0xf0, 0x39, 0x34, 0x7f, 0x90, 0xfd, 0xf9, 0x21, 0xff, - 0x8e, 0xd6, 0xf5, 0xf9, 0x52, 0x19, 0x7b, 0x2b, 0xfd, 0x3a, 0x4e, 0x96, - 0xea, 0x05, 0xc9, 0x57, 0x79, 0x16, 0x9e, 0x0b, 0x71, 0xac, 0xa5, 0x64, - 0xfa, 0xf4, 0x88, 0x3c, 0x8b, 0x33, 0xd0, 0xff, 0xe1, 0x8c, 0x71, 0x29, - 0x9e, 0xc5, 0x7c, 0xfd, 0x9a, 0x2c, 0x2c, 0x15, 0xa4, 0x56, 0xbd, 0xd0, - 0x74, 0xf7, 0x8e, 0xef, 0x85, 0xe6, 0x5e, 0xf6, 0x10, 0xfb, 0x19, 0xf4, - 0xaa, 0x16, 0xbe, 0x21, 0xb3, 0xfa, 0xf4, 0xd4, 0xe6, 0x3b, 0xe3, 0xe6, - 0x1e, 0x76, 0x42, 0x66, 0x2b, 0x29, 0x29, 0x9d, 0x1e, 0xd1, 0x77, 0x0d, - 0x6d, 0xe9, 0xea, 0xd3, 0x37, 0x90, 0x2b, 0x26, 0xf4, 0x9d, 0xf1, 0x2d, - 0x79, 0xd4, 0x9e, 0x95, 0x27, 0xad, 0x83, 0x72, 0x02, 0xf5, 0xf5, 0xa7, - 0xd1, 0xeb, 0xc7, 0xbb, 0xa9, 0x47, 0xd0, 0x6b, 0xb1, 0x07, 0x75, 0x64, - 0xdc, 0xfe, 0xb8, 0xf9, 0x3c, 0x24, 0x7b, 0xb5, 0xce, 0x3c, 0xf9, 0x5f, - 0x4e, 0x06, 0x79, 0xef, 0x06, 0x7a, 0xc7, 0x8c, 0x86, 0x33, 0x5c, 0xb8, - 0x2a, 0xe1, 0x86, 0xcd, 0x17, 0x08, 0xb7, 0x60, 0x78, 0x70, 0x06, 0xe0, - 0x42, 0x72, 0xd1, 0x0e, 0xc3, 0x46, 0x26, 0xc0, 0x27, 0x62, 0xfc, 0x68, - 0xa7, 0x57, 0x07, 0xef, 0x40, 0x6e, 0xbd, 0xbd, 0xff, 0x35, 0x6f, 0xff, - 0xb3, 0xde, 0xfe, 0xcb, 0x1b, 0xfb, 0xfd, 0xfc, 0xfa, 0x13, 0x47, 0x9a, - 0xe8, 0x7a, 0xad, 0xec, 0xc2, 0xcf, 0x7a, 0x74, 0x5d, 0xde, 0xa0, 0xcb, - 0x87, 0x87, 0x3c, 0x35, 0xcf, 0x8c, 0xcd, 0x8c, 0xd1, 0xfd, 0x90, 0xa3, - 0x23, 0x39, 0x1b, 0xbe, 0x51, 0x49, 0x8c, 0x15, 0xf5, 0x9d, 0x9a, 0x92, - 0xb5, 0xe8, 0xac, 0x4c, 0x58, 0x89, 0xb1, 0x69, 0x09, 0xc1, 0x96, 0x19, - 0x5b, 0x42, 0x52, 0x63, 0xcc, 0xc1, 0x33, 0x6f, 0x6f, 0x4f, 0xeb, 0xd5, - 0x26, 0x5a, 0x43, 0x2f, 0x91, 0x46, 0x97, 0xd6, 0xc8, 0xc0, 0x6d, 0x5a, - 0x5d, 0x78, 0x97, 0xd6, 0xab, 0xe5, 0x26, 0xf8, 0x73, 0x61, 0x0f, 0x3e, - 0xdc, 0x04, 0x4f, 0x7b, 0x66, 0x5d, 0x41, 0x7b, 0x26, 0x6d, 0x3f, 0x0b, - 0xdf, 0x90, 0xc8, 0x8e, 0x74, 0xf5, 0xe8, 0x7d, 0x03, 0x8e, 0x44, 0x50, - 0x6f, 0xb4, 0x62, 0x6d, 0xbd, 0xca, 0x5a, 0x44, 0xed, 0x6d, 0x95, 0x41, - 0xd8, 0x2c, 0x75, 0xe7, 0xde, 0x0d, 0x3e, 0xaa, 0x6b, 0x02, 0x47, 0x9e, - 0xb4, 0x49, 0xcb, 0x8f, 0x9d, 0x97, 0xa3, 0x83, 0x76, 0x49, 0x86, 0xcc, - 0x56, 0x9c, 0x5f, 0x6b, 0x68, 0x9c, 0x49, 0xd2, 0xb2, 0x32, 0xd4, 0x6f, - 0x7e, 0x0f, 0x7c, 0x8e, 0x57, 0x0d, 0xa9, 0x59, 0x89, 0xd8, 0x79, 0xe0, - 0xd8, 0x0f, 0xdd, 0xd4, 0x46, 0x48, 0x8f, 0xc8, 0x61, 0xd8, 0x77, 0x4d, - 0xe7, 0x45, 0xda, 0x71, 0x62, 0xa2, 0x88, 0x5a, 0xe7, 0x2f, 0x75, 0x6e, - 0x73, 0x9c, 0x1b, 0xc8, 0x6f, 0x13, 0x5b, 0x6c, 0x4f, 0x9d, 0x73, 0x6d, - 0x4f, 0x9d, 0x43, 0x0f, 0x7c, 0x32, 0x22, 0x6d, 0xcb, 0xf0, 0x9f, 0x97, - 0xf6, 0xb8, 0xf5, 0xdc, 0x4b, 0xfc, 0xdd, 0x09, 0xf1, 0xee, 0x64, 0x58, - 0xac, 0x93, 0x3a, 0x1f, 0x40, 0xde, 0xe3, 0x32, 0x7d, 0x86, 0x31, 0xd5, - 0x92, 0x81, 0x93, 0xd4, 0x07, 0xeb, 0x9a, 0x85, 0xd1, 0x02, 0x7c, 0x64, - 0x06, 0x71, 0x41, 0x2d, 0xdf, 0x94, 0x82, 0x45, 0x39, 0x74, 0x49, 0xfb, - 0x32, 0xfa, 0xf1, 0x65, 0xc4, 0x86, 0xe5, 0x98, 0xb4, 0xc0, 0xb7, 0xd4, - 0xb9, 0xa8, 0x51, 0x9a, 0x7f, 0x17, 0xfe, 0xc0, 0xdf, 0x70, 0x50, 0x5b, - 0x9e, 0x8b, 0x19, 0xf4, 0x2d, 0x75, 0x8e, 0x76, 0x8e, 0x72, 0xea, 0x1c, - 0xed, 0x9c, 0x74, 0xf8, 0xfe, 0x82, 0xf7, 0x73, 0x23, 0xfa, 0x9e, 0xfa, - 0x86, 0x4d, 0x5e, 0x7e, 0x20, 0xd9, 0x2a, 0x6b, 0x44, 0xf2, 0x23, 0xdd, - 0xa8, 0x65, 0x76, 0x65, 0xed, 0x81, 0xb1, 0x75, 0xf9, 0xa8, 0x7c, 0xdd, - 0xf9, 0x11, 0xf8, 0x22, 0x1f, 0xcd, 0x7c, 0x91, 0xa7, 0x2e, 0x69, 0xd1, - 0x7c, 0xf9, 0xfc, 0x40, 0xd0, 0xe0, 0x67, 0xef, 0xc9, 0x18, 0xf0, 0x7f, - 0x11, 0x31, 0xa0, 0x0f, 0xcf, 0x27, 0xf0, 0x44, 0x4a, 0x3b, 0x47, 0xde, - 0xc9, 0xeb, 0x75, 0xd4, 0x8d, 0x3e, 0x9f, 0x53, 0x78, 0x7f, 0x55, 0xa6, - 0xe7, 0x9d, 0xe3, 0xc8, 0xab, 0xbc, 0x43, 0xef, 0x71, 0xef, 0x83, 0xb7, - 0xf2, 0xfe, 0xaa, 0xb8, 0xf2, 0x49, 0x98, 0x35, 0xc1, 0xfb, 0xd2, 0x56, - 0x59, 0x34, 0xc7, 0x8e, 0x98, 0xae, 0xc3, 0x0f, 0xd7, 0x19, 0x27, 0x28, - 0xa3, 0xeb, 0x92, 0x9d, 0xe7, 0xfd, 0x97, 0x8b, 0x6f, 0xaa, 0xee, 0xc7, - 0x8d, 0xe6, 0x3d, 0x36, 0xe0, 0xfa, 0x00, 0x47, 0xba, 0xd6, 0x28, 0x3f, - 0xc4, 0x9c, 0xde, 0xa6, 0x58, 0xd3, 0xbc, 0x6f, 0x4c, 0x9e, 0x43, 0x1d, - 0xf0, 0x9a, 0xbd, 0x49, 0xae, 0x53, 0xac, 0x85, 0x6a, 0xf5, 0x49, 0xf8, - 0x64, 0x0b, 0x62, 0x99, 0x29, 0xeb, 0xe5, 0x56, 0xa9, 0xa1, 0xde, 0x59, - 0x5c, 0x62, 0x2c, 0x24, 0xed, 0xed, 0x98, 0x77, 0xe3, 0x17, 0x63, 0xed, - 0x7a, 0x19, 0x79, 0x16, 0xbe, 0xbd, 0x5e, 0x8e, 0xe2, 0xd9, 0x87, 0xa7, - 0x85, 0x67, 0x1c, 0xcf, 0x24, 0x9e, 0x23, 0x78, 0x8e, 0xe0, 0x69, 0x61, - 0x6f, 0x0c, 0x4f, 0xbf, 0x67, 0x20, 0xae, 0xdb, 0x7c, 0x97, 0xf4, 0x79, - 0xa8, 0x15, 0x2d, 0xe6, 0xb4, 0xb0, 0x9d, 0x43, 0x1f, 0x91, 0x1d, 0x61, - 0xad, 0xc7, 0x9a, 0xef, 0x03, 0xc7, 0xb4, 0xd8, 0x97, 0x17, 0x8d, 0xfd, - 0x43, 0xcc, 0x0b, 0x55, 0xe4, 0x85, 0xf7, 0x76, 0xa3, 0x7f, 0x34, 0x0f, - 0xe8, 0xbb, 0xa3, 0x79, 0x7c, 0xf3, 0x1d, 0x3d, 0x6f, 0x74, 0x06, 0x79, - 0x8a, 0xf1, 0xd3, 0xc1, 0x9e, 0x3c, 0xe2, 0xf8, 0x2e, 0xf8, 0x5f, 0x06, - 0x71, 0x1b, 0xef, 0x0b, 0x97, 0x76, 0xbb, 0x39, 0x15, 0xf9, 0x56, 0x6d, - 0xbd, 0xaf, 0xb1, 0xb1, 0x67, 0xbb, 0xde, 0xa0, 0x13, 0x38, 0x12, 0xd5, - 0x05, 0xf8, 0xe0, 0xf7, 0xed, 0xe3, 0xba, 0xb6, 0xa3, 0x2e, 0x9e, 0x45, - 0x8d, 0x9a, 0x9b, 0x63, 0x0d, 0x73, 0x0c, 0x7d, 0x09, 0xfa, 0xb3, 0x28, - 0x7b, 0x72, 0xe6, 0x02, 0x5d, 0x8b, 0x46, 0xa5, 0x9d, 0x79, 0xe0, 0x06, - 0xce, 0x03, 0x5f, 0x8b, 0x0e, 0x64, 0xf6, 0x08, 0x6a, 0x42, 0xc7, 0x09, - 0x5b, 0xfb, 0x25, 0xfe, 0x38, 0x63, 0x8e, 0x60, 0xbf, 0x29, 0xee, 0xbd, - 0x3a, 0xe2, 0xee, 0xa4, 0xfe, 0xbd, 0x18, 0xc6, 0x65, 0x63, 0xef, 0x1d, - 0xc0, 0xc5, 0x79, 0xde, 0x69, 0x8b, 0xec, 0x9f, 0x73, 0x6b, 0x5a, 0x65, - 0x35, 0xe3, 0xfb, 0x39, 0x0f, 0x1f, 0xd7, 0x95, 0xf7, 0xdb, 0xc6, 0x1e, - 0xc8, 0x08, 0xfe, 0x00, 0x1d, 0x9f, 0x40, 0xfd, 0x7c, 0x11, 0x7a, 0x79, - 0x0d, 0x3a, 0xb9, 0x54, 0xa6, 0xad, 0x0f, 0xc3, 0xee, 0x21, 0xc3, 0x49, - 0xe2, 0x1a, 0xd1, 0x67, 0x5f, 0x2c, 0x23, 0x76, 0x32, 0xfe, 0xa9, 0x5f, - 0x8d, 0xb2, 0x3e, 0x64, 0x1e, 0x74, 0xf1, 0xf4, 0xb9, 0x70, 0xe2, 0xaf, - 0xed, 0xd6, 0xf4, 0xd4, 0xf4, 0x3d, 0x18, 0xe5, 0x04, 0x1b, 0xe4, 0x6f, - 0x04, 0x1a, 0xe6, 0x0b, 0x51, 0x7d, 0x0f, 0xaf, 0x38, 0x47, 0x3e, 0x46, - 0x24, 0x3b, 0xe7, 0xef, 0xeb, 0xc6, 0xbe, 0x1d, 0x4d, 0xb8, 0xee, 0xdc, - 0xc2, 0x83, 0xf2, 0x78, 0xe0, 0xfa, 0xd6, 0xba, 0x3f, 0x61, 0x16, 0x37, - 0xee, 0x86, 0x99, 0x7f, 0xa9, 0x9b, 0x14, 0xf6, 0xfb, 0xfa, 0xe9, 0xf3, - 0x7a, 0x81, 0xc4, 0x6c, 0x51, 0x58, 0xab, 0x50, 0x47, 0x63, 0xf0, 0x6b, - 0x13, 0xf8, 0x6d, 0xa9, 0x96, 0xdb, 0x44, 0xf5, 0xb0, 0x37, 0x66, 0xad, - 0xdc, 0x7c, 0xe6, 0xaf, 0x78, 0x67, 0xa2, 0x9f, 0x3e, 0xc5, 0xba, 0x59, - 0xe7, 0x19, 0xc0, 0x74, 0x6c, 0xa1, 0xed, 0x17, 0x3d, 0x38, 0xae, 0x27, - 0xa5, 0x88, 0x3a, 0x34, 0x37, 0x87, 0x8a, 0x1e, 0xf1, 0x5b, 0xa5, 0xf9, - 0xbb, 0x16, 0xef, 0xf0, 0x86, 0xe3, 0xd3, 0xa0, 0xb1, 0x68, 0x66, 0x78, - 0x6f, 0x06, 0x1c, 0xbd, 0x5b, 0x70, 0x8c, 0x7b, 0x38, 0xc6, 0xa5, 0x74, - 0x66, 0x02, 0xbe, 0x96, 0x41, 0x7e, 0xef, 0x37, 0x1f, 0x91, 0x4f, 0xa0, - 0xb9, 0xc6, 0xdc, 0xd9, 0x11, 0xe8, 0xc9, 0x71, 0xf6, 0xdb, 0x87, 0x40, - 0xf7, 0x77, 0x90, 0x5b, 0xfd, 0x9a, 0xa7, 0x14, 0x0b, 0x21, 0x87, 0x1d, - 0xd1, 0xbf, 0xc3, 0x16, 0x4d, 0x13, 0xf6, 0xaa, 0x8c, 0xe1, 0x24, 0xda, - 0x7b, 0xe4, 0xb7, 0x59, 0xe4, 0x2a, 0xf2, 0xd9, 0x29, 0x25, 0xd3, 0x78, - 0x38, 0x84, 0xba, 0x26, 0x3b, 0x47, 0x3f, 0x92, 0x81, 0x50, 0xba, 0x15, - 0x35, 0xa9, 0x23, 0x6f, 0xdb, 0xfc, 0x77, 0x0a, 0xb3, 0x72, 0xb1, 0x6e, - 0xe2, 0xf9, 0x5d, 0xe8, 0xe1, 0x4f, 0xf1, 0xfe, 0x76, 0x0f, 0xea, 0x3e, - 0xac, 0x64, 0x60, 0xbb, 0x49, 0x5d, 0xcf, 0xb0, 0x8e, 0xa8, 0x21, 0xdf, - 0x2a, 0xe4, 0x1a, 0xd4, 0x55, 0x63, 0xac, 0x5d, 0x9f, 0x5b, 0xbc, 0x26, - 0x97, 0xe6, 0xf9, 0x3b, 0x28, 0xf3, 0xf2, 0x41, 0xc6, 0x03, 0x73, 0x26, - 0x85, 0xb9, 0x25, 0xc6, 0x32, 0x7c, 0x37, 0xe0, 0x40, 0x3d, 0xa8, 0x11, - 0x50, 0x6b, 0xaf, 0x5b, 0x49, 0xf0, 0x79, 0x4d, 0x2e, 0xce, 0x87, 0x65, - 0xd1, 0x62, 0x5d, 0x24, 0xf1, 0x2c, 0x60, 0x2f, 0x2e, 0xfd, 0x93, 0x6b, - 0x13, 0x84, 0x47, 0xcf, 0x53, 0x44, 0x5d, 0xf7, 0x88, 0xde, 0xfb, 0xd3, - 0xf4, 0x4c, 0x9a, 0x9a, 0xfb, 0xbc, 0x82, 0x5c, 0xa4, 0x3f, 0xe9, 0xdf, - 0x28, 0x58, 0x1b, 0x1c, 0x83, 0xcd, 0xb2, 0x76, 0x67, 0x3f, 0x80, 0xf7, - 0x3a, 0xd7, 0xc9, 0x3b, 0x9e, 0x0b, 0xfd, 0x90, 0x0d, 0xfd, 0x9e, 0x77, - 0x62, 0xc8, 0xa3, 0x8a, 0xbe, 0x5e, 0xd2, 0xb1, 0xa0, 0x54, 0x29, 0x20, - 0xa7, 0x20, 0x06, 0xd8, 0xbd, 0xb0, 0xc5, 0x49, 0xe8, 0x72, 0x0c, 0x70, - 0x5b, 0x72, 0xc9, 0x6a, 0x49, 0xd7, 0x65, 0x6a, 0xe5, 0xf6, 0xfd, 0x4d, - 0x1e, 0xfe, 0xa3, 0x56, 0x61, 0x5b, 0xf0, 0x21, 0xb5, 0x1a, 0xc5, 0x13, - 0xf1, 0x78, 0x15, 0xfd, 0x45, 0x99, 0xf7, 0x43, 0xe8, 0x0d, 0xca, 0xbc, - 0x3b, 0x49, 0xe2, 0x39, 0xc2, 0xfb, 0x22, 0x2f, 0xae, 0x11, 0x3f, 0xe9, - 0xf0, 0xe3, 0x0b, 0x6b, 0x49, 0xc6, 0x17, 0xbf, 0x9e, 0x74, 0x6d, 0xe1, - 0x44, 0x85, 0x31, 0x84, 0x76, 0xdd, 0x8f, 0xb8, 0x45, 0x5b, 0x70, 0x6b, - 0xc9, 0xa5, 0xaa, 0x2b, 0xb3, 0xe9, 0xc6, 0x05, 0x9d, 0x23, 0x0e, 0x88, - 0x05, 0x1b, 0xa3, 0xec, 0xb0, 0xa6, 0x73, 0xc0, 0x79, 0xc9, 0xe8, 0x27, - 0x65, 0xf6, 0xaa, 0x64, 0x96, 0x46, 0xe4, 0x05, 0x1d, 0xb7, 0xfc, 0x98, - 0xc5, 0x1a, 0x92, 0xbf, 0x1f, 0x27, 0xe5, 0xf9, 0xd3, 0xd7, 0x24, 0xfb, - 0x22, 0xe3, 0xd6, 0x70, 0x6c, 0x87, 0xc1, 0x58, 0xe5, 0x48, 0x1d, 0xb9, - 0xe9, 0x11, 0x9b, 0xff, 0x16, 0x20, 0x84, 0x9e, 0xce, 0x91, 0xd6, 0xd1, - 0x84, 0x1d, 0x37, 0xfa, 0x9f, 0xd8, 0x61, 0x30, 0x37, 0x0e, 0x9b, 0x4f, - 0x89, 0x7f, 0x1f, 0xd5, 0x26, 0x4f, 0xe9, 0xbb, 0x0a, 0xb8, 0xed, 0xdc, - 0xfb, 0xfa, 0x77, 0x94, 0x1b, 0x29, 0xca, 0x1a, 0xdf, 0xab, 0x9c, 0x2f, - 0x46, 0x6e, 0xa4, 0x5a, 0xa4, 0x74, 0x87, 0xe3, 0x3c, 0x39, 0xfa, 0xc0, - 0x6e, 0xf7, 0xdf, 0x8b, 0x3c, 0x7d, 0x87, 0x1b, 0x0b, 0x7e, 0xcd, 0xfb, - 0xfe, 0x3a, 0x9e, 0xb4, 0x6d, 0xe6, 0x5b, 0xe6, 0x47, 0xea, 0x0d, 0xcf, - 0x25, 0xbe, 0x33, 0xf7, 0xce, 0x22, 0xf7, 0x32, 0x5f, 0xee, 0x92, 0x1c, - 0x7f, 0xe7, 0x53, 0x7a, 0xbe, 0xe8, 0xd6, 0xd2, 0x1e, 0x5c, 0x75, 0x4a, - 0xa6, 0xab, 0xac, 0xa1, 0x2e, 0x22, 0x97, 0x0d, 0xc1, 0x56, 0x99, 0xd3, - 0x8e, 0x23, 0x9f, 0xf3, 0xf7, 0x69, 0xac, 0x2d, 0x70, 0x5f, 0x22, 0x19, - 0x57, 0xcd, 0xbf, 0x2b, 0xdd, 0x8c, 0xf2, 0x3e, 0xea, 0xfc, 0x10, 0xf4, - 0xfe, 0x15, 0xf6, 0x16, 0x03, 0xda, 0x46, 0xb2, 0x2f, 0x51, 0xf6, 0xee, - 0xef, 0xd7, 0xd2, 0xed, 0xfa, 0x00, 0xeb, 0x80, 0xcf, 0x40, 0x2e, 0x07, - 0xec, 0x6b, 0xcc, 0xdd, 0xff, 0xa6, 0xac, 0xe1, 0xe4, 0x53, 0x06, 0x7d, - 0x1b, 0xdf, 0x4b, 0x21, 0x59, 0x88, 0x92, 0x7f, 0xc8, 0xcb, 0xa0, 0xef, - 0x6c, 0x27, 0x87, 0xad, 0x32, 0xf8, 0x0b, 0xc8, 0x80, 0xb2, 0xf4, 0x65, - 0xc0, 0xf7, 0x09, 0xe8, 0x8b, 0x3d, 0x43, 0xbf, 0xee, 0x23, 0x4b, 0x0d, - 0xf7, 0xec, 0x52, 0xa5, 0x99, 0x66, 0xd2, 0x4b, 0x9d, 0x9e, 0x97, 0x9c, - 0xd6, 0xef, 0xac, 0xe4, 0xaa, 0xe7, 0x65, 0x7f, 0x75, 0x56, 0x1e, 0xb5, - 0x1e, 0x06, 0xbf, 0x57, 0x9c, 0x82, 0xa5, 0x7b, 0x95, 0xb1, 0x3c, 0xce, - 0x2e, 0x8c, 0xf4, 0xca, 0x4d, 0xd4, 0x1d, 0xcf, 0x2e, 0x9a, 0xf2, 0x3f, - 0x9d, 0x5b, 0x5f, 0x6c, 0x5b, 0xd5, 0x19, 0xff, 0x7c, 0x6d, 0x27, 0x69, - 0x68, 0xc2, 0xad, 0xeb, 0x24, 0x6e, 0x9a, 0x51, 0x3b, 0xbe, 0x6d, 0x23, - 0x92, 0xa2, 0xdb, 0x10, 0x68, 0xd4, 0x65, 0x8a, 0x71, 0x42, 0x17, 0xb6, - 0x22, 0xd2, 0xae, 0xab, 0x2a, 0x8d, 0x81, 0xe5, 0xa6, 0x7f, 0xd8, 0xc3, - 0x0a, 0x85, 0x75, 0x08, 0x21, 0xd5, 0xb8, 0xe9, 0xd6, 0x69, 0x21, 0x4e, - 0xff, 0x2d, 0x8c, 0x87, 0xcd, 0x4a, 0xd2, 0x96, 0x4d, 0x11, 0x2e, 0x88, - 0xb2, 0x3d, 0x6c, 0xa3, 0x4a, 0x01, 0xed, 0x79, 0x7b, 0x99, 0x34, 0x36, - 0x65, 0x05, 0x36, 0x5e, 0x36, 0xf5, 0x81, 0x07, 0xa6, 0xd1, 0x79, 0xbf, - 0xdf, 0x77, 0xee, 0x75, 0x6c, 0x13, 0x84, 0xb4, 0x48, 0x91, 0xef, 0x39, - 0xf7, 0xdc, 0x73, 0xce, 0x3d, 0xdf, 0xff, 0xef, 0xfb, 0xdd, 0x8c, 0x3d, - 0x28, 0x3f, 0xd2, 0x5c, 0x3e, 0xe3, 0x93, 0x00, 0x7c, 0x52, 0x83, 0x2d, - 0x90, 0x36, 0x27, 0x76, 0x53, 0xe8, 0x53, 0x86, 0x41, 0xeb, 0xb8, 0xf1, - 0x9b, 0x6d, 0x73, 0x7f, 0xcb, 0x59, 0xf8, 0xee, 0xee, 0x7d, 0x6d, 0x7e, - 0xce, 0xd7, 0xf8, 0xb7, 0x7f, 0xf2, 0x6a, 0x68, 0x83, 0x32, 0x83, 0xfd, - 0xbc, 0xa1, 0x7a, 0xd6, 0x01, 0x2f, 0x31, 0x37, 0x1d, 0xd3, 0xfc, 0x43, - 0x78, 0x9a, 0x3a, 0xea, 0x2a, 0x74, 0xd4, 0x10, 0x75, 0xd7, 0xf0, 0xbc, - 0xcb, 0xfc, 0x40, 0x54, 0xfe, 0x38, 0x45, 0x3d, 0x1c, 0x97, 0x3f, 0x4c, - 0x3d, 0x8b, 0xfd, 0x24, 0x8a, 0xcc, 0x51, 0xde, 0x98, 0xc9, 0xd1, 0x4f, - 0x52, 0x7f, 0x3e, 0xed, 0x3e, 0xad, 0x76, 0x20, 0x6e, 0xe5, 0xd7, 0x87, - 0x55, 0xdf, 0x1c, 0xd3, 0xda, 0x6e, 0xdc, 0xea, 0x92, 0x1b, 0x17, 0x8c, - 0x8e, 0x0d, 0x4f, 0x47, 0x03, 0x23, 0x0b, 0xb4, 0x4b, 0xc9, 0x58, 0xd6, - 0x6a, 0x94, 0x43, 0x51, 0xe6, 0x9e, 0x53, 0xd4, 0xcf, 0xb0, 0x85, 0xbd, - 0x76, 0xd6, 0x6a, 0xf2, 0xec, 0x4f, 0xac, 0x4e, 0xcf, 0x1e, 0xf3, 0xf4, - 0x2c, 0xef, 0xa5, 0x68, 0x03, 0x20, 0x93, 0x89, 0x99, 0x51, 0x2b, 0x09, - 0x9b, 0x87, 0xeb, 0x45, 0xce, 0x1f, 0x97, 0xe3, 0x8b, 0x47, 0xe1, 0x7f, - 0xf7, 0xda, 0x7b, 0x69, 0x57, 0xed, 0x21, 0xe2, 0x71, 0xb0, 0xfe, 0x97, - 0xea, 0xe6, 0x7a, 0xd4, 0x9b, 0x8b, 0xf7, 0x21, 0xe7, 0xd3, 0xac, 0xd7, - 0x36, 0x32, 0x9f, 0xa3, 0x7b, 0xad, 0x1d, 0xbb, 0xa7, 0xb2, 0xee, 0x64, - 0xc1, 0xf1, 0xb0, 0x61, 0xf8, 0x85, 0x2f, 0xf4, 0x8d, 0x08, 0xd7, 0xe4, - 0x7a, 0xad, 0x92, 0xde, 0x0f, 0xfd, 0x32, 0xcd, 0xff, 0x9c, 0x57, 0xbb, - 0x42, 0xbc, 0x12, 0xed, 0x5c, 0xc5, 0x36, 0x7d, 0xc5, 0x9b, 0xaf, 0xbf, - 0x5d, 0x9a, 0xa3, 0x55, 0xe3, 0x99, 0x5b, 0x61, 0x3b, 0x2e, 0xb9, 0x45, - 0xfe, 0x96, 0xcb, 0x11, 0xa7, 0x41, 0xf6, 0xda, 0x1b, 0xeb, 0xe6, 0xd8, - 0x86, 0x3e, 0xe3, 0x13, 0x04, 0xa7, 0x03, 0x9e, 0x6f, 0xb1, 0x89, 0x7e, - 0x93, 0x77, 0xdd, 0xa4, 0x39, 0x99, 0xb8, 0xd5, 0x59, 0xf7, 0x1e, 0x9b, - 0x2a, 0x76, 0x38, 0x6e, 0x51, 0x77, 0x36, 0x46, 0xa5, 0x95, 0x3c, 0x54, - 0x56, 0x3f, 0x3e, 0xe4, 0x18, 0xcc, 0x45, 0xd4, 0x39, 0xd2, 0xce, 0x9c, - 0xfd, 0x5b, 0x7a, 0x6e, 0x2d, 0xf4, 0x09, 0x70, 0x0d, 0x3e, 0xf9, 0x4c, - 0xbe, 0x97, 0xb9, 0x5e, 0xcc, 0xdf, 0xcc, 0xf9, 0x5d, 0xef, 0x9c, 0x13, - 0x6e, 0xce, 0xba, 0x5f, 0xb2, 0x17, 0x0c, 0xff, 0xa5, 0x1d, 0xf0, 0x5e, - 0x2b, 0xda, 0x0b, 0xb4, 0x09, 0x9f, 0x37, 0x8f, 0x6f, 0x1b, 0x7a, 0xd4, - 0x36, 0x9c, 0x2a, 0x90, 0x3f, 0xc9, 0x97, 0x3e, 0x3f, 0xfa, 0x3a, 0x8f, - 0x3c, 0x4a, 0x3d, 0x3b, 0x28, 0x67, 0x0b, 0x3c, 0x9b, 0x94, 0xd6, 0xb4, - 0x36, 0x9f, 0x3b, 0xa8, 0x98, 0xac, 0xee, 0xe9, 0xc4, 0x4b, 0x39, 0x19, - 0x96, 0xab, 0x2e, 0xcf, 0x2c, 0x51, 0xcc, 0x04, 0x5b, 0xaa, 0xde, 0x7f, - 0xbf, 0x9e, 0x59, 0x58, 0x7d, 0xc6, 0x18, 0xc6, 0x3e, 0xef, 0xd1, 0xbb, - 0x55, 0xcf, 0x36, 0x53, 0x43, 0x9f, 0xaf, 0xeb, 0x39, 0x85, 0xa1, 0x13, - 0x59, 0xdf, 0x0f, 0x47, 0xf8, 0x0c, 0xd7, 0xa5, 0xcf, 0xc7, 0xb5, 0xc8, - 0x7b, 0xdd, 0xb0, 0xd8, 0xfd, 0x12, 0xdc, 0x09, 0xd1, 0xdf, 0xc9, 0x3a, - 0x72, 0x00, 0xb2, 0xba, 0xd9, 0x60, 0x60, 0xc6, 0x8d, 0xaf, 0x91, 0xb1, - 0xae, 0xe1, 0x1c, 0x11, 0xab, 0xc0, 0x8f, 0x3e, 0xf5, 0x93, 0xdb, 0x98, - 0x2f, 0xe3, 0xf9, 0xeb, 0x03, 0x98, 0xdf, 0xf1, 0xea, 0xea, 0x53, 0xdb, - 0xc9, 0xab, 0xa3, 0x5a, 0x1f, 0xe4, 0x33, 0x94, 0x63, 0x9e, 0x19, 0xe9, - 0xf2, 0x1e, 0x9e, 0x67, 0x7b, 0x5b, 0x1d, 0x1d, 0x93, 0xde, 0xfe, 0xfc, - 0xfb, 0x61, 0x09, 0xb7, 0x53, 0xc7, 0x45, 0x25, 0x39, 0xcd, 0x98, 0x05, - 0xb6, 0x6b, 0x9c, 0x73, 0x7d, 0xb1, 0x2e, 0xce, 0xfc, 0x9f, 0xba, 0x38, - 0x63, 0x7d, 0xa4, 0xbc, 0x13, 0xd6, 0x3c, 0xd6, 0xe7, 0xd3, 0xb5, 0x58, - 0x43, 0x57, 0xbf, 0x76, 0x1f, 0xad, 0xd0, 0xf1, 0x87, 0x05, 0xda, 0xab, - 0x94, 0xe6, 0x94, 0xff, 0x3e, 0xc5, 0xb3, 0xe5, 0x1e, 0xaf, 0x72, 0x8f, - 0xc3, 0x4b, 0x8a, 0x83, 0x7c, 0x58, 0x65, 0xf8, 0x74, 0x81, 0x3a, 0xa6, - 0x45, 0xe6, 0x67, 0x7c, 0x3d, 0x33, 0xe6, 0xf9, 0xb8, 0xf9, 0xf5, 0x0d, - 0xaa, 0x67, 0xe0, 0xdd, 0x38, 0x23, 0x9e, 0x7d, 0xe9, 0x92, 0xb9, 0x0b, - 0xb4, 0xbb, 0x49, 0xf4, 0x45, 0x03, 0x73, 0x0b, 0xac, 0x4d, 0x12, 0x8b, - 0x32, 0x2c, 0xac, 0xfb, 0x8f, 0xd8, 0xa7, 0x20, 0x6f, 0x31, 0x79, 0x7f, - 0x8a, 0x3e, 0x7d, 0x03, 0x7c, 0xe3, 0xd6, 0xba, 0xf3, 0xdd, 0x51, 0xf1, - 0x09, 0x6b, 0xe9, 0x1e, 0xef, 0x90, 0x66, 0xf2, 0xb9, 0x63, 0xdf, 0x10, - 0xfa, 0x60, 0xbc, 0xce, 0x22, 0x16, 0x60, 0xec, 0x11, 0xd7, 0xd8, 0x63, - 0xae, 0xc8, 0xbe, 0x16, 0x2f, 0xaf, 0xd4, 0xa2, 0xbc, 0x42, 0x7e, 0xcb, - 0xa8, 0xff, 0x3d, 0xa4, 0x3a, 0x2b, 0x3f, 0xd5, 0x6b, 0x70, 0x2c, 0x76, - 0x4c, 0x79, 0x4f, 0x6a, 0x78, 0x2f, 0xe6, 0xad, 0x3d, 0xd6, 0x61, 0x7c, - 0x2b, 0x5b, 0xf5, 0x4d, 0x58, 0xc7, 0xd1, 0xae, 0x70, 0x7e, 0xf2, 0x06, - 0x79, 0x84, 0x3a, 0xcf, 0x1f, 0xe7, 0xd3, 0xc3, 0x6f, 0x73, 0x3c, 0xf9, - 0xbf, 0x1a, 0x8b, 0xe0, 0xcb, 0xaa, 0xdf, 0xe7, 0xcb, 0x1d, 0xef, 0x55, - 0xdb, 0x04, 0xca, 0x5d, 0x75, 0x7d, 0xd2, 0x96, 0xc8, 0xf4, 0x0a, 0x5d, - 0xd2, 0xfd, 0xdc, 0xff, 0xf3, 0xcc, 0xed, 0x42, 0xde, 0x56, 0xa3, 0xcd, - 0x09, 0xa5, 0x4d, 0x06, 0xb4, 0x89, 0x28, 0x6d, 0x18, 0xef, 0x3d, 0xe5, - 0xf1, 0x5b, 0x0b, 0xce, 0x8b, 0xb9, 0x5a, 0xe8, 0xba, 0x7d, 0xd4, 0xf9, - 0xcf, 0x76, 0x68, 0x7d, 0xd0, 0xa1, 0xee, 0x5b, 0x0b, 0x7d, 0xc6, 0xf6, - 0x56, 0xf5, 0x47, 0x4c, 0xbc, 0x15, 0xd7, 0x3c, 0x68, 0x10, 0xfa, 0x79, - 0x6e, 0x0a, 0xbe, 0x1a, 0x71, 0x6f, 0x35, 0xb4, 0xfa, 0x8e, 0x77, 0x5e, - 0xf3, 0x4a, 0x1b, 0xca, 0x00, 0xf5, 0xe6, 0x3a, 0xcc, 0xb7, 0x27, 0xda, - 0x07, 0xfe, 0xfa, 0x19, 0xfa, 0x37, 0x6b, 0x3c, 0x11, 0x84, 0xcc, 0xdf, - 0x9c, 0x6a, 0xf7, 0x62, 0x38, 0x07, 0x6d, 0xc4, 0xad, 0x53, 0x11, 0xc6, - 0x14, 0x68, 0xf7, 0x48, 0xc3, 0x34, 0xe2, 0x57, 0xe8, 0xf1, 0x25, 0xb5, - 0x47, 0x7d, 0xb8, 0x7f, 0x07, 0x71, 0x7e, 0xb8, 0x3e, 0x8a, 0xe7, 0x7a, - 0x0d, 0x16, 0x21, 0xba, 0x45, 0xcf, 0x74, 0x6e, 0x2a, 0x11, 0x3b, 0x2c, - 0x5e, 0xdf, 0xb8, 0xab, 0xfa, 0x60, 0x65, 0x5f, 0x0f, 0xca, 0x9e, 0x8a, - 0xbd, 0x60, 0x1c, 0x0d, 0x1f, 0x7e, 0xc6, 0xd8, 0x83, 0x7c, 0xb1, 0x4f, - 0xf1, 0x51, 0xc1, 0xa1, 0x45, 0x9c, 0x25, 0x7d, 0xd2, 0x65, 0xf8, 0xe1, - 0x2e, 0xce, 0x90, 0x7e, 0x77, 0xf9, 0xe4, 0xa4, 0x9b, 0x62, 0x7d, 0x0c, - 0xfa, 0xe0, 0xa4, 0x8c, 0x20, 0x2e, 0x18, 0x09, 0xb6, 0x32, 0xaf, 0x0c, - 0xdf, 0x30, 0xe7, 0xe5, 0x1e, 0xfb, 0x98, 0x33, 0x95, 0x73, 0x0b, 0xdc, - 0x3b, 0x65, 0xdb, 0xc4, 0xde, 0x73, 0x53, 0xdc, 0xaf, 0xc9, 0x43, 0xb0, - 0x6d, 0x4d, 0xbb, 0xf8, 0xe5, 0x59, 0x0c, 0xe0, 0x77, 0x10, 0xf2, 0xc0, - 0xb1, 0xf8, 0x5d, 0x58, 0x96, 0x77, 0x2f, 0xf8, 0xb6, 0x3d, 0x20, 0x6f, - 0x3b, 0xe5, 0x93, 0xa7, 0xdc, 0xf5, 0x3c, 0x03, 0x37, 0xc7, 0x9a, 0xb5, - 0xe3, 0xb8, 0x79, 0x29, 0x97, 0x97, 0xdc, 0xa5, 0xf5, 0x96, 0xd2, 0x92, - 0xf2, 0xbf, 0x8c, 0x33, 0xbc, 0x7e, 0xaf, 0x25, 0x86, 0x7e, 0xa4, 0xcd, - 0x67, 0x6b, 0x7f, 0xd5, 0xb6, 0xc0, 0xd7, 0x7f, 0xe4, 0x47, 0xf2, 0xe5, - 0xb2, 0xec, 0x52, 0xfd, 0xbf, 0xda, 0x73, 0xd5, 0xba, 0xdf, 0xf7, 0x6f, - 0xa9, 0xdf, 0xb5, 0xfe, 0xa3, 0xf1, 0xc1, 0x96, 0xe9, 0x7a, 0x9d, 0xf0, - 0x98, 0x57, 0x57, 0x58, 0x8d, 0xf7, 0x0e, 0x78, 0x7a, 0x21, 0xa5, 0xbe, - 0x73, 0xca, 0xa6, 0x7e, 0xe0, 0x7e, 0x9a, 0xe5, 0xe0, 0xec, 0x6d, 0xd0, - 0xc4, 0xd7, 0xc1, 0x8c, 0xfb, 0x7c, 0xdd, 0xd1, 0xea, 0xf9, 0xc2, 0x96, - 0x74, 0x9f, 0xa3, 0xef, 0xe4, 0x40, 0x8f, 0xb6, 0x49, 0x66, 0x3c, 0x28, - 0xc9, 0x73, 0x1b, 0x62, 0xc6, 0xd7, 0x25, 0xff, 0x41, 0xde, 0xb4, 0x4f, - 0x7d, 0x51, 0xf4, 0xdf, 0x29, 0x5c, 0xdb, 0xf0, 0x33, 0xe4, 0x79, 0x9f, - 0x7f, 0xcf, 0xae, 0xe3, 0xd1, 0x9d, 0x1e, 0x8f, 0xf2, 0xbe, 0x65, 0xea, - 0x1f, 0x18, 0xdb, 0x7d, 0x8e, 0x7b, 0x34, 0xcf, 0x75, 0x9f, 0x33, 0xf1, - 0x7a, 0xed, 0x73, 0x7d, 0x95, 0xe7, 0x70, 0xbf, 0x47, 0xb1, 0x61, 0x98, - 0x7b, 0xd7, 0x20, 0x7c, 0xba, 0x3e, 0xda, 0x1c, 0xda, 0xef, 0xcd, 0xee, - 0x2e, 0x21, 0xbf, 0x27, 0x3c, 0x9e, 0xa3, 0xbe, 0x89, 0x78, 0xfa, 0x66, - 0xc5, 0xbe, 0x8c, 0x18, 0xfc, 0x09, 0x73, 0x22, 0x55, 0xf6, 0xe5, 0x71, - 0xf3, 0x6e, 0x35, 0xf6, 0xe5, 0x4e, 0x6f, 0x1e, 0xff, 0x9e, 0xaf, 0x57, - 0xfc, 0xb6, 0xaf, 0x57, 0xea, 0x7d, 0x5a, 0x9f, 0xf6, 0xb5, 0xb8, 0xaf, - 0xea, 0x98, 0x2f, 0xbf, 0x6a, 0xde, 0x25, 0x8b, 0x98, 0x8d, 0x3e, 0x65, - 0x22, 0x67, 0x30, 0xd3, 0xd6, 0x59, 0x8b, 0xb8, 0x0f, 0xe7, 0xc7, 0x92, - 0x8e, 0xdc, 0xd6, 0xd8, 0xfa, 0xf4, 0xec, 0x98, 0xe6, 0x79, 0xe6, 0x5c, - 0x4f, 0xef, 0x44, 0x77, 0x43, 0xae, 0x5e, 0x89, 0xac, 0x60, 0x8a, 0x66, - 0x4e, 0xa4, 0x61, 0x87, 0x52, 0x5a, 0x2f, 0xfb, 0x2e, 0xf6, 0x3b, 0xa8, - 0x78, 0xae, 0x35, 0xce, 0x73, 0xf2, 0x90, 0x5d, 0xd6, 0xda, 0x4d, 0xd3, - 0x50, 0xf1, 0x44, 0xd3, 0x8b, 0x3e, 0xdf, 0x93, 0x9f, 0x66, 0x4e, 0x1c, - 0x9c, 0x29, 0x0f, 0x87, 0xb6, 0xf7, 0xda, 0x79, 0x21, 0x66, 0x7f, 0x58, - 0x8e, 0x28, 0x76, 0xf8, 0x15, 0xdc, 0xdf, 0xc7, 0xf8, 0x32, 0x11, 0x52, - 0x4c, 0x70, 0x22, 0x36, 0x01, 0x59, 0xcc, 0xba, 0xc4, 0xf8, 0xaf, 0x55, - 0xac, 0xff, 0x9c, 0xd0, 0xcf, 0x22, 0xa6, 0xe0, 0x59, 0x39, 0xec, 0x6e, - 0x76, 0x97, 0xc4, 0xf8, 0xbf, 0x59, 0xad, 0x09, 0x35, 0xca, 0x84, 0x1b, - 0x6a, 0x4a, 0x97, 0x8c, 0x0c, 0x8c, 0x06, 0x53, 0x6b, 0x26, 0x9d, 0x68, - 0xd3, 0xae, 0x12, 0x64, 0xbc, 0x04, 0xfd, 0x5f, 0x8a, 0x05, 0x46, 0x14, - 0x9b, 0xf6, 0x65, 0x49, 0xb7, 0xd3, 0xcf, 0xa7, 0x3e, 0xf9, 0x8a, 0xdc, - 0xb4, 0xb7, 0xca, 0xcd, 0x1e, 0xe2, 0x31, 0xfb, 0xd1, 0xa6, 0x2e, 0x19, - 0x44, 0x5f, 0x12, 0x7d, 0x4d, 0xca, 0x8f, 0x1a, 0x9f, 0x41, 0x67, 0xdd, - 0xb4, 0xa9, 0xab, 0xee, 0xe2, 0x2f, 0xde, 0xf5, 0x6f, 0xa0, 0x09, 0xb1, - 0x1d, 0xdb, 0xd0, 0xa6, 0x8e, 0xb3, 0xeb, 0xfa, 0x3b, 0xd1, 0xbe, 0x17, - 0x73, 0x34, 0xe8, 0xfb, 0x59, 0xce, 0x76, 0x53, 0xe7, 0xac, 0x19, 0xb3, - 0xae, 0xae, 0xfd, 0xfb, 0x36, 0x83, 0x4f, 0xf8, 0x94, 0xf4, 0xce, 0xa5, - 0xe4, 0xe1, 0x8e, 0xda, 0xf6, 0xbf, 0xea, 0xda, 0xad, 0xb2, 0xa6, 0x8d, - 0x64, 0x38, 0xd6, 0x5e, 0xdb, 0xef, 0xf3, 0x93, 0xdf, 0xee, 0xc0, 0xfb, - 0x42, 0x66, 0xac, 0xa4, 0xc6, 0x52, 0x37, 0xa3, 0x5c, 0xeb, 0xc3, 0xba, - 0x67, 0x78, 0xcd, 0x67, 0xf8, 0x2c, 0xf3, 0x7a, 0xb7, 0xd9, 0x8f, 0x67, - 0x98, 0x13, 0x60, 0x5e, 0x83, 0x3c, 0xbb, 0x5a, 0x9c, 0xc5, 0x31, 0x9f, - 0xcd, 0x37, 0x64, 0x2a, 0xbc, 0xe7, 0xeb, 0x95, 0x58, 0x05, 0xab, 0xb6, - 0xab, 0xe0, 0xe7, 0x84, 0x49, 0x3b, 0xad, 0x49, 0xc5, 0x6e, 0x80, 0xce, - 0x87, 0x40, 0xe7, 0x07, 0x83, 0x8c, 0x0b, 0x9b, 0x3d, 0x5a, 0x3b, 0x32, - 0x52, 0xfa, 0x0d, 0x64, 0x9c, 0x3c, 0x0a, 0x9f, 0xa2, 0x64, 0x79, 0xf8, - 0x8c, 0x01, 0xd8, 0x34, 0x57, 0x82, 0x9a, 0x77, 0x40, 0x7c, 0x3f, 0x7f, - 0x5d, 0x46, 0xa6, 0x98, 0x13, 0x20, 0x3f, 0x33, 0xae, 0x4f, 0xe1, 0xde, - 0x2d, 0x8c, 0x75, 0x21, 0xc3, 0x63, 0xe0, 0xd7, 0x90, 0x38, 0xd3, 0xdb, - 0x24, 0x37, 0x3e, 0xa6, 0x3e, 0x40, 0x37, 0x6c, 0xd4, 0x29, 0x77, 0x54, - 0x26, 0xaf, 0x6c, 0x82, 0xac, 0x32, 0xee, 0xd7, 0x9c, 0x46, 0x39, 0xac, - 0xbe, 0x39, 0x7d, 0x0e, 0xe6, 0xe1, 0x4c, 0x8d, 0xd9, 0xc8, 0xed, 0xa1, - 0x98, 0xb4, 0x8e, 0xca, 0xcc, 0xac, 0xad, 0x78, 0x97, 0x94, 0xdc, 0x2e, - 0x93, 0x76, 0xd9, 0x7d, 0x71, 0xe8, 0x2a, 0xfa, 0xf2, 0x3f, 0x88, 0x98, - 0xb3, 0xdc, 0xbd, 0x81, 0x31, 0x71, 0x72, 0xba, 0x7a, 0x0e, 0xc5, 0xc8, - 0xe0, 0xde, 0x2f, 0xdb, 0x8c, 0xcc, 0x30, 0x3e, 0xfe, 0xa0, 0x9c, 0x8a, - 0x72, 0x4d, 0x8e, 0x65, 0xed, 0x96, 0x3c, 0xc2, 0xbd, 0xfd, 0xc7, 0xe3, - 0xe5, 0x97, 0x31, 0x5f, 0x5c, 0xba, 0x5f, 0x1d, 0xd3, 0xb8, 0xfe, 0x54, - 0x4d, 0x0c, 0x6b, 0xf2, 0x05, 0x26, 0x8e, 0xbd, 0x2e, 0x13, 0x8b, 0xa4, - 0x0f, 0x6d, 0x7c, 0x40, 0x7e, 0xe1, 0xf4, 0xda, 0x4f, 0x68, 0xad, 0x31, - 0x91, 0x62, 0x7d, 0xa6, 0xd9, 0x49, 0xda, 0xf3, 0x12, 0x1a, 0xfc, 0x1a, - 0xae, 0x19, 0xd7, 0xe6, 0xdd, 0x5e, 0xf7, 0x09, 0xf1, 0x71, 0x20, 0x9b, - 0x53, 0x8d, 0x81, 0x4f, 0xca, 0xd7, 0xf7, 0x71, 0x8c, 0xc1, 0x81, 0x48, - 0x80, 0xb4, 0x7a, 0xef, 0x2e, 0xe2, 0x67, 0x6a, 0xf3, 0x7f, 0x0f, 0x1c, - 0xdb, 0x3b, 0x90, 0x38, 0xc3, 0x18, 0x36, 0xec, 0x3c, 0xba, 0xc1, 0xbc, - 0x6b, 0x2e, 0xb7, 0x4e, 0xb4, 0x7e, 0x76, 0xfc, 0x1f, 0x0e, 0xf1, 0x10, - 0x89, 0x58, 0xa3, 0xc5, 0x3c, 0x38, 0x75, 0x1c, 0x6b, 0x2a, 0xcc, 0xb9, - 0x11, 0xcb, 0xdf, 0x24, 0x97, 0xfb, 0x2c, 0x79, 0x20, 0x94, 0x8a, 0x5b, - 0xb2, 0x25, 0x7e, 0x4e, 0xb0, 0x26, 0xeb, 0x2b, 0x8b, 0x89, 0x1c, 0xc7, - 0x87, 0xa6, 0x39, 0x5f, 0x5c, 0xe3, 0x95, 0xe4, 0x96, 0x72, 0xf9, 0x29, - 0x57, 0x02, 0xc9, 0x7b, 0x3e, 0x2c, 0xb3, 0x16, 0x6e, 0xbd, 0xfa, 0x79, - 0x38, 0x05, 0xea, 0x0a, 0x7b, 0xc2, 0x60, 0x0e, 0x27, 0x8f, 0x77, 0x2f, - 0xb2, 0xfd, 0xe4, 0x43, 0xa6, 0x7d, 0x06, 0xed, 0x06, 0x0f, 0xeb, 0x34, - 0x75, 0xbc, 0xbb, 0x78, 0x6c, 0x83, 0x89, 0xbf, 0x97, 0x15, 0xff, 0xf5, - 0x56, 0x4d, 0x4c, 0x93, 0x0a, 0x8c, 0x17, 0xc6, 0x02, 0x63, 0x05, 0xab, - 0xaf, 0x09, 0xb4, 0x5a, 0x70, 0x99, 0xab, 0xf1, 0x73, 0x56, 0xcc, 0xf7, - 0x8b, 0x3c, 0xa9, 0x18, 0x29, 0xd6, 0x14, 0x2d, 0xf5, 0x85, 0x0e, 0x2d, - 0x30, 0xc7, 0x1f, 0x51, 0x7d, 0x70, 0x78, 0xb1, 0x55, 0xf2, 0xf6, 0x7a, - 0xc9, 0xab, 0x8c, 0x47, 0x55, 0x07, 0x58, 0xce, 0x3d, 0xe8, 0xe3, 0xbe, - 0x1f, 0x57, 0x5c, 0xc4, 0xeb, 0x85, 0x4e, 0xb4, 0x99, 0x6b, 0xde, 0x51, - 0xd7, 0x5f, 0x5d, 0x97, 0x4d, 0xd8, 0x96, 0x55, 0x5f, 0x93, 0x65, 0x5f, - 0x7d, 0x2d, 0xf6, 0xb4, 0x5c, 0x27, 0xdf, 0x94, 0xfc, 0x9c, 0xbb, 0xeb, - 0xe5, 0xdc, 0x1f, 0xc3, 0x9c, 0x9c, 0x5b, 0x32, 0xa1, 0xa1, 0xa6, 0xbe, - 0x53, 0x53, 0xc1, 0x5b, 0x2b, 0xf9, 0x53, 0xb4, 0x17, 0x2b, 0xb5, 0x72, - 0xdc, 0x7b, 0x06, 0xbe, 0x48, 0x1e, 0x7e, 0x45, 0xce, 0xfb, 0xfe, 0x80, - 0xf7, 0x2b, 0xcf, 0x7f, 0xc1, 0x9e, 0x9a, 0xb5, 0xce, 0x6e, 0xd5, 0xd4, - 0xd9, 0xbf, 0x8d, 0x67, 0x59, 0x63, 0xcf, 0x95, 0x1b, 0xc0, 0xbb, 0x0d, - 0xc4, 0x89, 0x54, 0xc6, 0x53, 0xc7, 0xab, 0x2e, 0xd7, 0xb9, 0x76, 0x79, - 0x73, 0x05, 0xa1, 0xe7, 0x0f, 0x4e, 0xf9, 0x63, 0x4e, 0x4a, 0x63, 0x7f, - 0x22, 0x16, 0xb4, 0x38, 0xc6, 0xe8, 0xfb, 0xb4, 0x7b, 0x12, 0x7a, 0x9c, - 0x3a, 0x9f, 0xef, 0xed, 0xc0, 0xd7, 0xa3, 0x2e, 0xa0, 0x3e, 0x57, 0x1b, - 0x10, 0xcf, 0x43, 0xd7, 0x8f, 0x94, 0x34, 0x97, 0x1f, 0xfb, 0x6a, 0x30, - 0x31, 0x93, 0x55, 0xdd, 0x00, 0x7f, 0xaf, 0xf4, 0x26, 0xf3, 0x41, 0x67, - 0x24, 0x50, 0x5d, 0xa7, 0x61, 0x6c, 0xc6, 0x9a, 0x46, 0x0b, 0x74, 0x83, - 0xc8, 0x55, 0xf0, 0xc6, 0x6b, 0x0b, 0xe4, 0xd7, 0x60, 0xbb, 0x89, 0xaf, - 0x96, 0x76, 0x58, 0xd2, 0xae, 0xb5, 0xcf, 0xbc, 0x13, 0xa1, 0x7f, 0x32, - 0x9c, 0xec, 0x87, 0x9f, 0xad, 0xd8, 0x03, 0xe6, 0x2b, 0x0f, 0x22, 0x1e, - 0xab, 0xce, 0xb1, 0x40, 0xbe, 0xc6, 0xd9, 0x9f, 0x85, 0x5f, 0xb9, 0x52, - 0xf7, 0xc8, 0x17, 0x27, 0x35, 0xb7, 0x39, 0xb7, 0xd0, 0xa2, 0x3a, 0x76, - 0xae, 0x38, 0x86, 0x73, 0x91, 0xad, 0xd6, 0x50, 0xde, 0xeb, 0x0f, 0x4b, - 0xb1, 0xc8, 0xb6, 0x74, 0x35, 0xe8, 0xb9, 0xfb, 0xb5, 0x1d, 0x5b, 0xe6, - 0xe1, 0x2b, 0x16, 0x17, 0x1d, 0xfc, 0xf7, 0xe0, 0xbf, 0x0f, 0xff, 0xbb, - 0x25, 0x3d, 0x4d, 0xff, 0x95, 0xb5, 0x9c, 0x96, 0xba, 0xf5, 0xe9, 0x23, - 0x75, 0x29, 0x0e, 0x2c, 0xef, 0xc5, 0x39, 0xf9, 0x62, 0xbd, 0x9c, 0x30, - 0x4f, 0xea, 0xeb, 0x08, 0xe6, 0x4b, 0xfd, 0x5a, 0x5f, 0x75, 0x0d, 0xcb, - 0xf2, 0xea, 0x5e, 0xe4, 0xe9, 0x66, 0x39, 0x5c, 0xf4, 0x6b, 0x57, 0x31, - 0x39, 0x52, 0xa9, 0x5d, 0x49, 0x26, 0x38, 0xf4, 0xc9, 0x23, 0xd9, 0x29, - 0xc5, 0x13, 0x58, 0xd6, 0xd0, 0xf5, 0x47, 0x26, 0x16, 0xdf, 0x7e, 0x64, - 0x05, 0x13, 0x8e, 0x7b, 0x8b, 0xab, 0x61, 0x86, 0x88, 0xa5, 0xe3, 0xb7, - 0x72, 0xea, 0xbb, 0x61, 0xdf, 0x7e, 0xcc, 0x43, 0x9c, 0x1d, 0xf4, 0x4c, - 0xf3, 0x0a, 0x76, 0xd7, 0xc4, 0xa3, 0xc4, 0x91, 0xf2, 0xb9, 0x6a, 0xec, - 0x47, 0x08, 0xe7, 0x2f, 0x01, 0xcb, 0xc9, 0x61, 0x1f, 0x3f, 0xed, 0x34, - 0x7e, 0x20, 0x71, 0xa6, 0x89, 0x2a, 0xec, 0x91, 0x8f, 0x35, 0x7d, 0x09, - 0x73, 0x65, 0xe4, 0x77, 0xa5, 0x47, 0xe5, 0x57, 0xa5, 0x31, 0xc8, 0xf7, - 0x04, 0xe6, 0x3c, 0x20, 0x6f, 0x96, 0xf6, 0xc9, 0xb5, 0xd2, 0xb8, 0xbc, - 0x51, 0xda, 0x8d, 0x98, 0x6a, 0x94, 0x58, 0x4f, 0x0f, 0x2b, 0x3d, 0x2c, - 0x07, 0xcf, 0x2b, 0x06, 0xf0, 0x16, 0xfd, 0x9e, 0xe3, 0xea, 0x67, 0x13, - 0x5f, 0x9f, 0xf8, 0x35, 0xe3, 0x79, 0x62, 0x33, 0x8b, 0x25, 0x1f, 0xc3, - 0x71, 0xb4, 0x0b, 0x6b, 0xdb, 0xfc, 0x36, 0x65, 0xe4, 0x7c, 0x24, 0x30, - 0x7a, 0x3e, 0x14, 0x78, 0x50, 0xbf, 0x73, 0x61, 0xbd, 0xb3, 0x2c, 0x93, - 0xae, 0x43, 0xde, 0x1c, 0x1c, 0x81, 0x2c, 0x8c, 0x42, 0xd5, 0x3f, 0xe4, - 0xac, 0x17, 0x90, 0x34, 0xf5, 0x11, 0xfc, 0xcc, 0xe4, 0x8b, 0xae, 0x64, - 0x0b, 0xf3, 0x01, 0x83, 0x47, 0xb3, 0xd1, 0xee, 0x43, 0xfb, 0xe7, 0x5e, - 0x7b, 0xa7, 0x64, 0x67, 0x25, 0xf5, 0xbe, 0xfa, 0xc3, 0x2f, 0x7b, 0x7d, - 0x83, 0xe8, 0x03, 0x67, 0x5e, 0x64, 0xdf, 0x45, 0xaf, 0x8f, 0x67, 0xc2, - 0x5a, 0x7d, 0x5c, 0xf9, 0x2a, 0x6b, 0x8f, 0x8b, 0x7e, 0xd7, 0xa0, 0xb5, - 0xf8, 0x0f, 0x3a, 0x8d, 0x6e, 0x23, 0x26, 0xf0, 0x9f, 0x9d, 0x8c, 0xc1, - 0x8a, 0x90, 0xaf, 0xbb, 0xa0, 0x13, 0xff, 0xba, 0x75, 0xa5, 0x6d, 0x0d, - 0x7d, 0x5c, 0x85, 0xd1, 0xfe, 0x58, 0xba, 0x17, 0xff, 0xed, 0xe1, 0x79, - 0x9f, 0xc0, 0xbb, 0xe1, 0xac, 0x0a, 0xc4, 0x8d, 0xc7, 0x21, 0xdb, 0x2d, - 0xb2, 0xfe, 0x2c, 0xe9, 0xd5, 0x0b, 0x5d, 0x9d, 0x82, 0xdc, 0xba, 0xb2, - 0x50, 0x0a, 0x05, 0x46, 0x0a, 0x29, 0x31, 0x78, 0x6a, 0x4b, 0x32, 0xd1, - 0x94, 0x9c, 0x1e, 0x48, 0xf4, 0x30, 0x0f, 0x99, 0xed, 0x77, 0xe5, 0x52, - 0x89, 0xf6, 0x38, 0x27, 0x97, 0x07, 0x12, 0x6e, 0x51, 0x88, 0x8b, 0x71, - 0xe5, 0x32, 0x64, 0xf3, 0x9d, 0xf3, 0xbb, 0xe5, 0x48, 0x41, 0xfd, 0xe0, - 0xde, 0xb0, 0xbc, 0x20, 0x97, 0x06, 0x5e, 0xb8, 0x75, 0xc9, 0x3d, 0x84, - 0x33, 0x25, 0x1f, 0x1e, 0xee, 0x32, 0xfb, 0x56, 0x1c, 0x92, 0x30, 0x1f, - 0xa2, 0x35, 0x35, 0xa7, 0x51, 0xd2, 0xfb, 0x23, 0x5e, 0x5c, 0x0e, 0x9f, - 0x3b, 0x30, 0x60, 0xea, 0x29, 0x01, 0x7f, 0x9f, 0x61, 0xf8, 0x31, 0x7c, - 0xce, 0xa7, 0x8d, 0x3f, 0x4f, 0x67, 0x20, 0x3d, 0xdb, 0x2a, 0xa1, 0x8b, - 0xf7, 0x81, 0xae, 0x21, 0x39, 0xd4, 0x5f, 0x2e, 0x7f, 0xd3, 0x0d, 0xc5, - 0x27, 0x10, 0xa3, 0x60, 0xff, 0xb2, 0xee, 0xc5, 0x36, 0xd0, 0xa4, 0x49, - 0xa2, 0x2f, 0xfa, 0xeb, 0x35, 0x7a, 0x58, 0x86, 0x8b, 0xeb, 0x8c, 0x2d, - 0xf3, 0xb1, 0x0d, 0xfe, 0x7c, 0x06, 0x53, 0xd6, 0x6d, 0xf5, 0x07, 0xbc, - 0xef, 0x24, 0xbc, 0xf6, 0x3d, 0x81, 0x07, 0x42, 0xed, 0x12, 0x72, 0x9e, - 0xdf, 0x48, 0x6c, 0xe4, 0x52, 0xc1, 0xef, 0x87, 0x9f, 0x18, 0xf2, 0xfd, - 0x61, 0xd9, 0xbe, 0x72, 0xd6, 0xb2, 0xbd, 0x7b, 0xf1, 0x5b, 0xde, 0x9c, - 0x29, 0x6f, 0x2c, 0x62, 0x8e, 0xd8, 0x5a, 0xb5, 0x4f, 0x66, 0xec, 0xa7, - 0xf2, 0x74, 0x7f, 0xe2, 0x15, 0xc5, 0xc9, 0x56, 0x9e, 0xe1, 0x7d, 0xc4, - 0x90, 0x25, 0x7d, 0x26, 0xb6, 0x07, 0xf4, 0xcd, 0xc4, 0xee, 0xb6, 0xe7, - 0xad, 0x60, 0xc0, 0xf8, 0x23, 0x0d, 0xf2, 0xbd, 0x28, 0xec, 0x36, 0xbf, - 0x61, 0x61, 0xfe, 0xcb, 0xbd, 0xed, 0xf9, 0x29, 0xec, 0x4b, 0x9c, 0x49, - 0x5a, 0x13, 0xd8, 0x1f, 0xcf, 0x80, 0x18, 0x50, 0x0b, 0x74, 0xea, 0xc4, - 0xfb, 0x21, 0x7e, 0xea, 0xf7, 0xdf, 0x7f, 0x1d, 0x74, 0x18, 0xf7, 0x6f, - 0x70, 0x61, 0x62, 0x31, 0x17, 0x32, 0xec, 0x61, 0x60, 0xab, 0xe5, 0xd6, - 0xc7, 0xc6, 0xfa, 0x78, 0x3a, 0x62, 0x94, 0x62, 0xf0, 0x03, 0x29, 0x13, - 0xe4, 0xcd, 0x0e, 0xf4, 0xaf, 0xf9, 0x24, 0xa5, 0xaf, 0xee, 0xf7, 0x7d, - 0x58, 0xc1, 0x76, 0x4f, 0x14, 0xf6, 0x19, 0x6c, 0x9e, 0xb5, 0x2c, 0xa9, - 0xae, 0xa4, 0x3d, 0x89, 0xfd, 0xa6, 0x43, 0x89, 0x62, 0x4e, 0x62, 0x32, - 0x0f, 0x7d, 0xf1, 0x1a, 0x64, 0xff, 0x5a, 0x29, 0x1e, 0x48, 0x63, 0x4f, - 0x87, 0x0b, 0x43, 0x32, 0x31, 0xab, 0xdf, 0x7e, 0x41, 0xef, 0x0f, 0xc9, - 0x5c, 0x21, 0xd1, 0x33, 0x0f, 0xfe, 0x9b, 0x2f, 0x10, 0x5f, 0xd4, 0x1b, - 0x1f, 0xc5, 0x8c, 0x4b, 0x85, 0xcd, 0xb0, 0x0f, 0x92, 0xba, 0x04, 0xff, - 0xe7, 0x52, 0xa9, 0x07, 0x7c, 0x86, 0xfb, 0x25, 0x07, 0xbf, 0xd0, 0x99, - 0xa5, 0x01, 0xc8, 0x39, 0xf7, 0x62, 0xcb, 0xc2, 0x56, 0x9c, 0x1d, 0x71, - 0x44, 0x8a, 0x1f, 0xff, 0x2f, 0xce, 0xd7, 0x7f, 0xef, 0x1d, 0x6a, 0xa7, - 0xe7, 0x75, 0x5f, 0xb0, 0xcb, 0x88, 0x01, 0xb2, 0xfd, 0xc6, 0x6e, 0xa7, - 0x23, 0x6d, 0x92, 0xbe, 0x9b, 0x76, 0xbc, 0x5d, 0x63, 0x44, 0xe5, 0xc5, - 0x08, 0xef, 0xbf, 0xb3, 0xd1, 0xd0, 0x2f, 0x5c, 0xd7, 0xbe, 0x8e, 0xdf, - 0x56, 0xe9, 0x70, 0xf8, 0x6b, 0xe3, 0xf7, 0xed, 0x8d, 0xac, 0xef, 0x76, - 0x38, 0x49, 0xac, 0xf5, 0x5b, 0x2f, 0x5f, 0x80, 0xeb, 0x79, 0x3e, 0xb3, - 0xc1, 0x5b, 0x97, 0xf3, 0xb6, 0x62, 0x9e, 0x16, 0x6f, 0xad, 0x56, 0xcd, - 0x4f, 0x9a, 0xb5, 0x10, 0xe3, 0x16, 0xfe, 0xb2, 0x51, 0xbf, 0x35, 0x86, - 0xbd, 0xa8, 0x6d, 0xff, 0x79, 0x23, 0x71, 0x73, 0x1d, 0x4e, 0xab, 0x62, - 0x3c, 0x6f, 0xb6, 0xb7, 0xe3, 0x9a, 0x6b, 0x72, 0x8c, 0xc9, 0x87, 0xcf, - 0x95, 0x38, 0x3f, 0xdb, 0x29, 0x39, 0xa1, 0xf9, 0x0c, 0x83, 0xe5, 0x9b, - 0x2b, 0xdc, 0x2f, 0x13, 0xe7, 0x15, 0x5f, 0x37, 0x93, 0xb7, 0xf8, 0xdd, - 0x0b, 0xbf, 0x97, 0xa3, 0x2f, 0x31, 0x26, 0x07, 0x71, 0x7e, 0x97, 0xe1, - 0x53, 0x2d, 0x99, 0xef, 0x62, 0xf1, 0x77, 0x00, 0xe7, 0x12, 0x82, 0x8c, - 0x51, 0x46, 0x29, 0x53, 0x38, 0xbf, 0x71, 0x5b, 0xde, 0x1d, 0xa0, 0x3c, - 0x0f, 0xc8, 0x95, 0x8a, 0x3c, 0xe7, 0x20, 0xcf, 0x94, 0xe5, 0x1c, 0x64, - 0xda, 0xf0, 0xf5, 0x7e, 0x7e, 0x67, 0x1d, 0x83, 0xbd, 0x52, 0x1f, 0xe2, - 0x25, 0xf0, 0xb5, 0xed, 0x7d, 0x2b, 0x15, 0xd0, 0x1c, 0x4e, 0x76, 0xb6, - 0xc1, 0xfb, 0x0e, 0x00, 0xd7, 0x57, 0x9e, 0x93, 0xf4, 0x6c, 0x33, 0xbf, - 0xe7, 0xea, 0xe2, 0x99, 0x65, 0xaf, 0xf0, 0xdf, 0xe7, 0x45, 0xe2, 0x4d, - 0xe9, 0xcf, 0xf2, 0x9a, 0x71, 0xde, 0x26, 0x8c, 0x19, 0x04, 0x9d, 0x9b, - 0x31, 0x3f, 0xf7, 0xb8, 0xda, 0x38, 0xde, 0x0f, 0x55, 0xe1, 0x53, 0x7d, - 0x7a, 0xaf, 0xd5, 0x35, 0xb3, 0xfd, 0xcd, 0xde, 0xfb, 0xf1, 0x1c, 0x94, - 0xef, 0xc1, 0xb7, 0xf4, 0x89, 0xc9, 0x2f, 0x29, 0x3d, 0x87, 0xb9, 0x02, - 0xf9, 0x37, 0xa4, 0x39, 0x8c, 0x2c, 0x6c, 0xcb, 0x5e, 0x1d, 0x1f, 0x5b, - 0x91, 0xef, 0xae, 0x80, 0xc6, 0xdd, 0xd9, 0xc2, 0x1a, 0xe9, 0x56, 0x1d, - 0xd4, 0xe5, 0xf1, 0x36, 0xec, 0x85, 0x62, 0xb9, 0x0f, 0xc8, 0xf1, 0xd2, - 0x20, 0xe8, 0x10, 0x93, 0xa7, 0xe0, 0x37, 0x3f, 0x53, 0xba, 0x43, 0x96, - 0x23, 0xd8, 0x57, 0x45, 0xc6, 0x86, 0xe5, 0xfb, 0xf3, 0x09, 0xef, 0x3a, - 0xe1, 0x2e, 0x5b, 0x3b, 0xb0, 0x07, 0xca, 0x13, 0xe5, 0x8a, 0xe3, 0x82, - 0x88, 0x45, 0x38, 0xef, 0xd3, 0x46, 0xb7, 0x61, 0xde, 0x62, 0x84, 0xf2, - 0xcb, 0xbd, 0x85, 0x3c, 0x99, 0x65, 0x5c, 0xc5, 0x77, 0x36, 0x36, 0x29, - 0x53, 0x73, 0x16, 0x09, 0xc5, 0x81, 0xae, 0x9c, 0x81, 0x3f, 0x8f, 0x2f, - 0x97, 0xfe, 0x77, 0x14, 0xd4, 0xa3, 0xb0, 0x95, 0x05, 0xd8, 0xca, 0x02, - 0x6c, 0x24, 0x64, 0xe1, 0x5a, 0x01, 0x36, 0xb2, 0x00, 0x1b, 0x09, 0x7d, - 0xf6, 0x3a, 0x62, 0xbb, 0xd7, 0xc0, 0x43, 0xc6, 0xd7, 0x3e, 0x4a, 0x5f, - 0x1b, 0x7f, 0xff, 0x03, 0x4c, 0x03, 0x3a, 0xe1, 0xd4, 0x71, 0x00, 0x00, - 0x00 }; + 0xec, 0x5b, 0x5f, 0x6c, 0x5b, 0xd7, 0x79, 0xff, 0xee, 0x21, 0x25, 0x51, + 0xb2, 0xfe, 0x5c, 0xc9, 0x8c, 0x43, 0x27, 0x4a, 0x43, 0x4a, 0x57, 0x12, + 0x13, 0x69, 0xe9, 0x95, 0xc6, 0x26, 0x2a, 0x46, 0x34, 0x2c, 0x29, 0xdb, + 0x4a, 0xe3, 0x07, 0xc5, 0xf5, 0xda, 0xac, 0xeb, 0x30, 0x81, 0xb2, 0xb1, + 0xec, 0x61, 0x83, 0x67, 0xac, 0x41, 0xb6, 0xb9, 0x30, 0x41, 0x29, 0x8e, + 0x92, 0xd2, 0x22, 0x67, 0x2b, 0x73, 0xb1, 0x65, 0x80, 0x42, 0x49, 0x76, + 0xb6, 0xd1, 0x62, 0xda, 0xbd, 0x74, 0x45, 0x1c, 0x0b, 0x8a, 0xe7, 0xe5, + 0xa1, 0x0f, 0x69, 0x17, 0x60, 0xed, 0xd0, 0x61, 0x86, 0xe2, 0xda, 0x79, + 0x28, 0xb6, 0x6c, 0x40, 0x96, 0x6c, 0x71, 0x73, 0xf7, 0xfb, 0x9d, 0x7b, + 0xaf, 0x4c, 0x2b, 0x1a, 0x9a, 0x87, 0x3d, 0xde, 0x03, 0x08, 0xe7, 0x9e, + 0x73, 0xbe, 0xf3, 0x9d, 0xef, 0xfb, 0xce, 0xf7, 0xf7, 0xd0, 0xfe, 0xc3, + 0x76, 0x69, 0x13, 0xaf, 0x75, 0xe0, 0x2f, 0x75, 0xec, 0x99, 0xe3, 0x63, + 0x0f, 0xa5, 0x1e, 0xe2, 0x38, 0xa4, 0xc2, 0x61, 0xf6, 0x86, 0x04, 0x2d, + 0x68, 0x41, 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, + 0x41, 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, + 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b, + 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b, 0x5a, + 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b, 0x5a, 0xd0, + 0x82, 0x16, 0xb4, 0xa0, 0x05, 0xed, 0xff, 0xb3, 0x85, 0x44, 0x4c, 0xf6, + 0x1d, 0xde, 0x9f, 0x44, 0x54, 0x3a, 0x7e, 0x3c, 0x6b, 0x49, 0x24, 0x94, + 0xbe, 0xf2, 0xf4, 0x8c, 0x25, 0x92, 0xa9, 0x0d, 0xc7, 0x73, 0xf2, 0x0b, + 0xa7, 0x10, 0x0d, 0x0b, 0xe7, 0xef, 0x4b, 0xdf, 0x3a, 0x79, 0xe9, 0x91, + 0xc4, 0x7b, 0x4b, 0x21, 0x89, 0x98, 0xe9, 0xb7, 0x46, 0xcd, 0x41, 0x89, + 0xf4, 0x62, 0xcf, 0x4b, 0x43, 0x97, 0xbb, 0xa4, 0xd3, 0xc7, 0x25, 0x52, + 0x2d, 0x25, 0xec, 0xfd, 0x32, 0x6c, 0x6e, 0x48, 0x58, 0x32, 0x38, 0xe3, + 0x7c, 0x4d, 0xa4, 0x58, 0x32, 0x88, 0x43, 0x8a, 0xb5, 0x88, 0x5c, 0x0b, + 0x11, 0xea, 0x7b, 0x46, 0xb6, 0xfc, 0xb1, 0x93, 0x09, 0xe3, 0x5c, 0x0b, + 0xdf, 0x75, 0x7f, 0x3e, 0x22, 0x2a, 0x9d, 0x48, 0x66, 0x43, 0x93, 0x52, + 0x5d, 0x74, 0x9c, 0x39, 0xfb, 0x5e, 0xe0, 0xe8, 0x91, 0x39, 0xcb, 0x1d, + 0x67, 0xed, 0x07, 0xcd, 0x09, 0xb9, 0x1b, 0x73, 0x21, 0x51, 0xd6, 0x3d, + 0xf8, 0x8b, 0x1b, 0xb9, 0xb3, 0xdf, 0x32, 0xb2, 0xcb, 0xed, 0x52, 0x2c, + 0x3b, 0x32, 0x63, 0x4b, 0x26, 0x6b, 0xb7, 0x62, 0xfd, 0x63, 0x67, 0x66, + 0x6b, 0xcf, 0xb0, 0x99, 0x93, 0x26, 0xc9, 0x44, 0x63, 0x80, 0x59, 0x34, + 0x72, 0x17, 0xfe, 0xae, 0x5d, 0xda, 0x40, 0x4f, 0x8a, 0xe3, 0x8f, 0x9d, + 0x90, 0x65, 0x61, 0x9d, 0xe7, 0x63, 0x5c, 0x27, 0x5e, 0x7e, 0x13, 0xe7, + 0x35, 0xe7, 0xd2, 0x50, 0x4c, 0xbe, 0x5b, 0x8f, 0xca, 0x77, 0xea, 0xa6, + 0xbc, 0x5a, 0xef, 0x95, 0xcb, 0x75, 0xc7, 0xf9, 0x8e, 0xed, 0x38, 0x6f, + 0xe1, 0xef, 0x3f, 0xed, 0x2d, 0x1e, 0xd0, 0x0a, 0xc6, 0x44, 0xfd, 0x2f, + 0xda, 0xa5, 0x33, 0x11, 0x17, 0xd5, 0x2e, 0xb3, 0xe5, 0x98, 0xcc, 0x95, + 0x4b, 0xc6, 0x13, 0x17, 0x16, 0x8c, 0xa9, 0x0b, 0x15, 0x9c, 0x19, 0xc6, + 0x9c, 0x14, 0x8a, 0xf6, 0x2b, 0x46, 0xae, 0x3e, 0x6f, 0x1c, 0xba, 0xd0, + 0x09, 0x1a, 0x79, 0xfe, 0x1e, 0x23, 0x7b, 0xf6, 0x96, 0x64, 0x6d, 0xca, + 0x38, 0x61, 0x7e, 0x0d, 0x62, 0xcf, 0x96, 0x48, 0x73, 0xb3, 0x47, 0xaf, + 0xe3, 0xa8, 0xb4, 0x73, 0x32, 0x9b, 0xb2, 0xcc, 0xa2, 0x90, 0x3e, 0x3d, + 0x77, 0xd9, 0xa5, 0xf9, 0xbc, 0x91, 0xbd, 0xd0, 0x6e, 0xe4, 0xce, 0x85, + 0x41, 0x87, 0xf4, 0x86, 0x84, 0xfb, 0x06, 0x62, 0x79, 0xa9, 0xe1, 0x0c, + 0x31, 0x55, 0x9a, 0x72, 0x05, 0xcd, 0xa0, 0xe5, 0xbb, 0x65, 0xf0, 0x50, + 0x06, 0x0f, 0x65, 0xf2, 0x16, 0x97, 0x4b, 0x43, 0x3e, 0x6f, 0x8e, 0xf3, + 0x23, 0x9b, 0xb4, 0x27, 0xe2, 0x19, 0xe5, 0xf3, 0xe9, 0x38, 0xff, 0x61, + 0x93, 0x57, 0xf2, 0xe3, 0x38, 0xaf, 0xda, 0x31, 0xd0, 0xee, 0x5c, 0x56, + 0x56, 0x09, 0xbc, 0x58, 0xc0, 0x4f, 0x59, 0x2f, 0x80, 0x87, 0x79, 0xf0, + 0x77, 0x1e, 0xbc, 0x55, 0x40, 0xc7, 0x2f, 0x3b, 0xaf, 0x60, 0xe4, 0x86, + 0xb6, 0xe4, 0x15, 0xa7, 0x8c, 0xf3, 0x2b, 0x0a, 0xb2, 0xde, 0x25, 0xf9, + 0x25, 0x53, 0xa6, 0x57, 0xfc, 0xfd, 0xbe, 0x1e, 0x1c, 0x93, 0x83, 0xe5, + 0x1e, 0xc8, 0x86, 0xb2, 0x4c, 0xd8, 0x22, 0x0e, 0x64, 0x54, 0x4c, 0x2a, + 0x11, 0x23, 0x6f, 0x9f, 0xd4, 0xf7, 0xbf, 0x62, 0x49, 0x26, 0x6f, 0x53, + 0x8e, 0x12, 0xcf, 0xdb, 0x85, 0x58, 0x18, 0xfa, 0xb6, 0x62, 0x15, 0xcc, + 0xb0, 0x50, 0x8e, 0x89, 0xd8, 0x1f, 0x43, 0x96, 0x47, 0x4b, 0x92, 0xf9, + 0x52, 0xc9, 0x97, 0xb1, 0x2b, 0xdf, 0xc7, 0x4b, 0x5f, 0xec, 0x90, 0x36, + 0xf5, 0x99, 0x26, 0xf9, 0x3d, 0xec, 0x25, 0xee, 0x3b, 0xf6, 0x62, 0x9f, + 0x0b, 0xe7, 0xee, 0x4d, 0x3c, 0x29, 0x42, 0xd8, 0x62, 0x7f, 0x93, 0xb6, + 0x11, 0x31, 0xb2, 0x56, 0x21, 0x16, 0x02, 0x5c, 0x5e, 0x8a, 0xa3, 0xde, + 0x5c, 0x53, 0xd6, 0xba, 0x15, 0x9a, 0xb3, 0x13, 0xf1, 0xa2, 0xdc, 0x0a, + 0x5d, 0xb5, 0xf5, 0x5c, 0x6b, 0xd6, 0x72, 0x64, 0x15, 0xd8, 0x9f, 0x83, + 0x3d, 0x6c, 0x80, 0xa3, 0xdf, 0x2d, 0xe9, 0xf9, 0x0e, 0xec, 0x4f, 0x36, + 0x01, 0x67, 0x9b, 0x24, 0x92, 0x55, 0xcc, 0x5f, 0x75, 0xe7, 0xbb, 0x5d, + 0xbc, 0xc5, 0xfe, 0x36, 0x8d, 0x5b, 0xe4, 0x15, 0x77, 0xfe, 0x2e, 0x17, + 0x77, 0xf1, 0x01, 0xcc, 0x03, 0xff, 0xe0, 0xe4, 0x90, 0xa1, 0xe7, 0xf7, + 0xd2, 0x9e, 0x7e, 0xa7, 0x74, 0x2b, 0xb4, 0x6a, 0x3b, 0x92, 0x1b, 0x1d, + 0x9c, 0x1c, 0x34, 0x5c, 0x7c, 0xa7, 0xdc, 0x7d, 0xf7, 0xb9, 0xf8, 0x06, + 0x27, 0x93, 0x86, 0x8b, 0x6f, 0xa5, 0xa4, 0xf7, 0x4a, 0xbe, 0x44, 0xd8, + 0xc1, 0x49, 0xcb, 0xb8, 0x4f, 0xa6, 0xbb, 0x07, 0x27, 0xfb, 0x0c, 0xf5, + 0x99, 0x5d, 0x2e, 0x1f, 0x09, 0x9f, 0x86, 0x5d, 0x9a, 0x06, 0x9e, 0xab, + 0xe7, 0x07, 0xb2, 0x56, 0xf1, 0x81, 0x5d, 0xfa, 0x7c, 0x9e, 0xa9, 0xe7, + 0x1e, 0x20, 0x5d, 0x3c, 0x7b, 0x66, 0xf4, 0x8e, 0x73, 0x7f, 0xe5, 0xb6, + 0x7c, 0x76, 0x3a, 0x93, 0xe7, 0x49, 0x24, 0x9c, 0x0e, 0x8f, 0xce, 0x95, + 0x8e, 0x49, 0xb6, 0x1c, 0x97, 0xd9, 0x91, 0x56, 0x99, 0x36, 0xfb, 0xa7, + 0x0f, 0x0a, 0x7d, 0x4f, 0x64, 0x74, 0xc6, 0xbb, 0xc3, 0x9c, 0x18, 0x32, + 0x0b, 0x1e, 0x0f, 0xd6, 0x24, 0x62, 0x00, 0xbe, 0xbf, 0x16, 0x96, 0xe7, + 0xeb, 0x86, 0x34, 0x6b, 0xfb, 0x4c, 0x98, 0xeb, 0xd0, 0xc3, 0x67, 0xcb, + 0xd4, 0x63, 0xea, 0xac, 0x64, 0xaa, 0x5a, 0x67, 0x7d, 0x7b, 0x6d, 0xe3, + 0xdd, 0x16, 0x0a, 0x02, 0x73, 0x4c, 0x5b, 0x66, 0x55, 0x5a, 0x24, 0x33, + 0x25, 0x85, 0xaa, 0xbd, 0x65, 0x3f, 0xb1, 0x65, 0xd9, 0x80, 0x1e, 0x88, + 0x99, 0x4d, 0x71, 0x9e, 0xf0, 0x0d, 0xb0, 0xa6, 0x6b, 0x7b, 0x21, 0xd8, + 0xde, 0x4c, 0x8a, 0xb0, 0x52, 0xd0, 0xfe, 0xa2, 0x0e, 0x7d, 0xac, 0xdf, + 0xd7, 0xe1, 0xfa, 0xbb, 0x08, 0x6c, 0xb4, 0x1d, 0x76, 0xfe, 0x19, 0xd8, + 0x60, 0xaf, 0x91, 0x3d, 0xe7, 0x38, 0xf0, 0x3f, 0x51, 0x25, 0xb4, 0x41, + 0xd8, 0x7b, 0x9d, 0x6b, 0xed, 0x98, 0x17, 0x73, 0xd6, 0xee, 0x06, 0x8f, + 0x8e, 0x33, 0x69, 0xc7, 0xa5, 0x68, 0x77, 0x61, 0x5f, 0x93, 0xf4, 0x58, + 0xd4, 0x79, 0xda, 0xf5, 0x2e, 0x9c, 0x67, 0x70, 0xdc, 0x89, 0xf3, 0x3a, + 0x30, 0x17, 0x9b, 0xa5, 0x2d, 0xa7, 0xe8, 0xb7, 0x5c, 0x1f, 0x2a, 0x72, + 0x1d, 0xb4, 0x72, 0x8f, 0x86, 0x8b, 0xb4, 0xa4, 0x53, 0x72, 0xb3, 0xb4, + 0x57, 0xae, 0x45, 0x29, 0x03, 0xe0, 0x2c, 0xc3, 0x27, 0x46, 0x0d, 0xd0, + 0x4f, 0xba, 0xe9, 0x03, 0x77, 0x7b, 0x63, 0xe3, 0x7e, 0xf7, 0x0c, 0x31, + 0x43, 0xe9, 0x4e, 0xc9, 0xe9, 0x39, 0x51, 0x6a, 0x74, 0x97, 0xb7, 0xde, + 0x69, 0xec, 0x3f, 0xa7, 0xe4, 0xc0, 0xc3, 0xf0, 0x5b, 0x38, 0xeb, 0xaa, + 0xe5, 0x38, 0x57, 0xed, 0xf7, 0x61, 0xf7, 0x4a, 0x9a, 0xac, 0x6b, 0x9d, + 0xd2, 0x46, 0x7b, 0x36, 0x1a, 0x64, 0x18, 0x93, 0x53, 0x65, 0xee, 0x29, + 0x48, 0xd8, 0x22, 0x0c, 0xe1, 0xff, 0x05, 0x70, 0x21, 0x69, 0x81, 0x3d, + 0x6e, 0xd8, 0x51, 0xd2, 0xdb, 0xe5, 0xc2, 0x77, 0xe3, 0x0c, 0xd2, 0x4e, + 0xfb, 0x73, 0xb4, 0xfd, 0x65, 0x43, 0x2a, 0x33, 0xb1, 0x08, 0x6b, 0x1a, + 0xa1, 0xbc, 0xb3, 0xdd, 0x70, 0xff, 0x32, 0x3b, 0x54, 0x30, 0x95, 0xbe, + 0x6f, 0x91, 0x5c, 0xe9, 0x7e, 0x99, 0xb3, 0x71, 0x9e, 0x15, 0x06, 0xcd, + 0xf4, 0x35, 0x03, 0x85, 0x90, 0x82, 0x95, 0xf5, 0x50, 0x56, 0x3e, 0xad, + 0xff, 0x8c, 0xf3, 0x0a, 0x46, 0xd8, 0xe2, 0x19, 0xbf, 0xe5, 0xc9, 0x87, + 0xba, 0x67, 0x4b, 0xb6, 0xd4, 0xce, 0x31, 0xe8, 0x68, 0xd3, 0x74, 0x84, + 0xd2, 0xfa, 0xee, 0x0c, 0x95, 0xf6, 0x63, 0x00, 0x41, 0xef, 0xc0, 0x03, + 0x3e, 0xb8, 0xd7, 0xc2, 0xde, 0x08, 0x68, 0xec, 0x68, 0xa0, 0xbf, 0x8d, + 0xf0, 0x90, 0x55, 0xc4, 0x3b, 0x43, 0xf3, 0x6d, 0xb8, 0x7c, 0xfb, 0xb2, + 0x7a, 0x1d, 0xb2, 0xfa, 0xc8, 0x39, 0x30, 0x46, 0x1c, 0x29, 0xe0, 0x80, + 0xdc, 0x4d, 0xfa, 0x2c, 0xfa, 0x29, 0x73, 0x0b, 0x17, 0x6c, 0x41, 0x85, + 0xd2, 0xed, 0x92, 0x33, 0x75, 0x1c, 0x00, 0xec, 0xb8, 0x68, 0x3f, 0x6f, + 0x91, 0x47, 0x6f, 0x6c, 0x25, 0xb4, 0xde, 0xe4, 0x2b, 0x8c, 0x05, 0x45, + 0xd0, 0xb6, 0x9e, 0x50, 0x9a, 0xb5, 0x76, 0xc8, 0x5c, 0x22, 0x4d, 0xe9, + 0xb7, 0x64, 0xb5, 0xa4, 0xf6, 0x34, 0x4b, 0x97, 0x4c, 0x41, 0x46, 0xd5, + 0x71, 0xc4, 0xb0, 0x91, 0x76, 0x09, 0x3d, 0xc4, 0x58, 0x10, 0x03, 0xad, + 0xeb, 0x09, 0x53, 0x6e, 0x39, 0x6a, 0x10, 0xfb, 0x47, 0x70, 0x0f, 0x87, + 0x79, 0xa7, 0xca, 0x83, 0x23, 0x4c, 0x88, 0x32, 0xef, 0x69, 0x16, 0xe2, + 0xe6, 0xda, 0x70, 0xcc, 0x14, 0xce, 0x23, 0x5e, 0x4e, 0x71, 0x2f, 0xf9, + 0x73, 0xf7, 0x7c, 0x92, 0x3f, 0x7f, 0x9d, 0x32, 0xa3, 0xec, 0xa0, 0x63, + 0xa0, 0xa9, 0x1b, 0x72, 0x1b, 0x5d, 0x80, 0x4f, 0xb4, 0x1f, 0xd7, 0x3a, + 0xdc, 0x37, 0x76, 0xaf, 0x5c, 0x83, 0xdd, 0xc5, 0x95, 0x18, 0x55, 0x7b, + 0xaf, 0x9e, 0x53, 0x96, 0x2f, 0x4f, 0xca, 0x60, 0xf7, 0x36, 0x19, 0x10, + 0xe7, 0xce, 0x72, 0x38, 0x52, 0x21, 0x0d, 0x2e, 0x2d, 0x73, 0xd6, 0x7a, + 0x22, 0x2c, 0x8d, 0xf4, 0x7c, 0xec, 0x28, 0xcb, 0x2a, 0xf4, 0x29, 0xe2, + 0x6f, 0x16, 0xb5, 0x27, 0x2c, 0x4f, 0x8c, 0x19, 0x12, 0x3f, 0xa4, 0xe4, + 0xd0, 0xc3, 0xc4, 0xf9, 0x13, 0xf2, 0x38, 0x9e, 0xe1, 0xfa, 0x18, 0x75, + 0x21, 0x8c, 0x5e, 0xf3, 0x87, 0xb9, 0x46, 0x5d, 0x7f, 0xdd, 0xd3, 0xf5, + 0x8f, 0x9c, 0x43, 0x63, 0x61, 0x0f, 0x36, 0xd2, 0x00, 0x2b, 0xb8, 0xef, + 0x9d, 0x60, 0x09, 0xd3, 0xa8, 0x17, 0x84, 0x2d, 0xec, 0x00, 0x8b, 0xe0, + 0xf4, 0x15, 0xda, 0x50, 0xb7, 0xe7, 0x33, 0x7c, 0x9b, 0xe2, 0x39, 0xec, + 0x77, 0xb2, 0x3f, 0xee, 0xe3, 0x7e, 0xc2, 0x6f, 0x8f, 0xa7, 0xb8, 0x06, + 0xd9, 0x31, 0xa6, 0xa2, 0x4d, 0xe2, 0x5b, 0xc1, 0xff, 0x34, 0xc6, 0x56, + 0xce, 0x99, 0x18, 0x4f, 0xa0, 0xb7, 0x24, 0x5f, 0xa3, 0x1d, 0x71, 0x3f, + 0x63, 0xed, 0xbb, 0x9e, 0xef, 0x6c, 0x9f, 0x0e, 0xa7, 0xa3, 0xf0, 0x9d, + 0x32, 0x55, 0x2c, 0x9d, 0x44, 0x3e, 0x24, 0x85, 0x7b, 0xd2, 0xd4, 0x8b, + 0xf6, 0x71, 0xf8, 0xc6, 0xa9, 0x62, 0x8d, 0x39, 0x11, 0xdc, 0x17, 0xf6, + 0x21, 0x3e, 0x47, 0xd4, 0x42, 0xa4, 0x70, 0x6f, 0x9a, 0x3e, 0x39, 0x2e, + 0xf1, 0xda, 0x7b, 0xc8, 0x39, 0x4c, 0xc9, 0x6a, 0x1d, 0xfb, 0xf6, 0x5e, + 0xd2, 0x5c, 0x44, 0xfe, 0x10, 0x4e, 0x4b, 0x58, 0xa5, 0x9b, 0x23, 0xb3, + 0xa9, 0x76, 0xe4, 0x59, 0x93, 0x7b, 0xd5, 0xda, 0xc1, 0xbd, 0xa1, 0xb5, + 0x3d, 0xd3, 0x4d, 0xe9, 0xc2, 0x5e, 0xb5, 0x20, 0xb2, 0x5c, 0x12, 0x85, + 0x9c, 0x26, 0x76, 0x44, 0x30, 0x5e, 0xfb, 0xf2, 0x97, 0x55, 0x3a, 0x24, + 0xf9, 0xa8, 0x9c, 0x58, 0x49, 0x85, 0x99, 0x3f, 0xc6, 0xa7, 0xe4, 0x04, + 0x72, 0xc6, 0x67, 0x64, 0xb6, 0x04, 0xba, 0x34, 0xdf, 0x31, 0xf0, 0xdb, + 0x0b, 0xdc, 0xa4, 0x3d, 0x0a, 0xdf, 0xea, 0xd2, 0x0e, 0x9a, 0x33, 0x39, + 0xe6, 0x48, 0x29, 0xc6, 0x94, 0xf7, 0xa0, 0x27, 0xb4, 0x93, 0x9f, 0xcb, + 0xaa, 0xd5, 0x2a, 0x79, 0xd7, 0x2f, 0x68, 0x3d, 0x0d, 0xa7, 0xdf, 0xf5, + 0xd6, 0xae, 0x63, 0x8d, 0xfa, 0xba, 0xab, 0xe1, 0xee, 0xbe, 0xa5, 0xf3, + 0x9c, 0xab, 0x36, 0xbf, 0x09, 0xfb, 0x83, 0x51, 0x17, 0xf6, 0xcd, 0xd1, + 0x55, 0xeb, 0x2b, 0x5d, 0xd2, 0x86, 0x73, 0xca, 0x3c, 0x27, 0x4a, 0xdf, + 0x8a, 0xf5, 0x6b, 0x1e, 0xae, 0x9f, 0x02, 0x57, 0x3b, 0xe9, 0x46, 0x0b, + 0x63, 0x1d, 0xf4, 0x21, 0xdf, 0xc9, 0x6f, 0xf9, 0x18, 0xc2, 0xbe, 0xe6, + 0xe1, 0xfa, 0x5e, 0x03, 0x2e, 0xae, 0xb1, 0xe7, 0x99, 0x38, 0xbb, 0x8d, + 0xbc, 0x91, 0x1f, 0xde, 0x01, 0xef, 0x23, 0x69, 0x4c, 0xc1, 0xa7, 0x4f, + 0xd5, 0x75, 0x5e, 0x67, 0xe4, 0xca, 0xc8, 0xb7, 0xea, 0x2f, 0x82, 0x46, + 0xe4, 0x61, 0xf5, 0x01, 0x2f, 0xd7, 0xa6, 0xad, 0xac, 0x6b, 0x9f, 0x45, + 0x7f, 0x53, 0xd4, 0xf6, 0x74, 0x05, 0x63, 0x9d, 0x67, 0xe3, 0x6e, 0xae, + 0x48, 0x5f, 0xad, 0xdc, 0xe5, 0xfe, 0xbf, 0x6d, 0x53, 0x42, 0xfa, 0x3e, + 0x19, 0xd7, 0xa8, 0x67, 0x77, 0xc3, 0x9f, 0x3b, 0x1f, 0x30, 0xbe, 0x4c, + 0x31, 0xf6, 0x4c, 0x31, 0x66, 0x18, 0x9e, 0x1f, 0x8c, 0x37, 0xe0, 0x88, + 0x03, 0xc7, 0x79, 0x4f, 0x6f, 0x4f, 0x7b, 0xb8, 0xfc, 0xdc, 0xd3, 0xf7, + 0xa5, 0x2f, 0xdd, 0x73, 0xe7, 0xba, 0x61, 0xba, 0xe3, 0x66, 0xed, 0x87, + 0x61, 0xf7, 0xa0, 0x3f, 0x3e, 0xad, 0xa0, 0x5f, 0xb9, 0x9a, 0x7b, 0x1f, + 0xb0, 0x71, 0xe8, 0x1e, 0x3f, 0xfd, 0xbb, 0x75, 0x73, 0x6f, 0x57, 0x06, + 0xbc, 0xd3, 0x0c, 0xf9, 0xce, 0x84, 0x49, 0x4b, 0x7d, 0x12, 0xfb, 0xe5, + 0x18, 0x63, 0x62, 0x1e, 0x7c, 0x1c, 0x31, 0x87, 0xcd, 0x59, 0xe2, 0x8e, + 0x0a, 0x70, 0x22, 0x8f, 0x4c, 0xb7, 0x78, 0xf7, 0xfc, 0x7d, 0x9e, 0x0f, + 0xdc, 0xbb, 0x38, 0x46, 0xff, 0x7d, 0x8f, 0x9e, 0x1b, 0x9d, 0x2e, 0x3d, + 0xfe, 0xfa, 0x80, 0x79, 0xe7, 0x78, 0x75, 0xaf, 0x27, 0x4f, 0x7c, 0x3f, + 0xe3, 0xd1, 0xc5, 0xbb, 0x69, 0xa4, 0x89, 0xf7, 0xf2, 0x5f, 0xc0, 0xa3, + 0xf3, 0x8c, 0x82, 0x4a, 0x23, 0x6f, 0x49, 0x31, 0x56, 0xc1, 0xe6, 0xc5, + 0xc2, 0x9d, 0x24, 0xec, 0x69, 0xec, 0x7a, 0xb7, 0xc4, 0x7b, 0xbe, 0x05, + 0x1f, 0xcd, 0x7b, 0xff, 0x50, 0xe6, 0x4a, 0xfd, 0x76, 0xb3, 0x41, 0x7b, + 0x4d, 0x24, 0xcf, 0xcb, 0xb0, 0x7d, 0x5e, 0xe7, 0x4f, 0x89, 0xf8, 0x29, + 0xa1, 0x6c, 0x6f, 0xc9, 0x80, 0xce, 0x6b, 0x3e, 0x14, 0x0b, 0x72, 0x99, + 0x2a, 0xc3, 0xc6, 0xc6, 0xfe, 0xcd, 0xd1, 0xf9, 0x28, 0xf2, 0xa5, 0x1b, + 0x3b, 0xe0, 0x7a, 0x53, 0xe3, 0x21, 0xbe, 0x46, 0x5c, 0x86, 0xb4, 0x8c, + 0xf9, 0xf8, 0x2c, 0x99, 0xaf, 0xfb, 0x38, 0xc3, 0xf0, 0xc3, 0xf0, 0x01, + 0x63, 0xbf, 0xe1, 0xe9, 0x0b, 0xbf, 0x7f, 0xe8, 0x30, 0x07, 0x52, 0xe9, + 0x3f, 0xf7, 0xe6, 0xae, 0x50, 0x06, 0x18, 0xfb, 0x72, 0x7f, 0xd1, 0xf3, + 0x39, 0x05, 0x23, 0x53, 0xa7, 0x0c, 0xa8, 0x2b, 0xb8, 0x7f, 0xad, 0x9f, + 0xb0, 0x99, 0xf2, 0x17, 0x10, 0x1f, 0xbb, 0xdd, 0xbc, 0x01, 0xb5, 0x55, + 0xa6, 0xce, 0xb9, 0xf5, 0x96, 0xac, 0xdd, 0xe4, 0xd9, 0xd2, 0x41, 0xcc, + 0x4d, 0xe1, 0x8f, 0xb2, 0x23, 0xcc, 0x61, 0x7c, 0x67, 0x3c, 0x38, 0x19, + 0xcf, 0x22, 0x66, 0x65, 0x0e, 0x4f, 0x60, 0x6c, 0x78, 0x35, 0x96, 0x96, + 0x7b, 0x05, 0x39, 0x0a, 0xe4, 0x39, 0x00, 0x7e, 0xe2, 0x32, 0x51, 0xc7, + 0x9d, 0x6f, 0xf9, 0xb3, 0x2d, 0x98, 0xc2, 0x6d, 0x18, 0xd7, 0xf7, 0x4d, + 0xd4, 0x7f, 0xec, 0xd0, 0x1f, 0xfc, 0xad, 0xb6, 0x97, 0x78, 0x43, 0xde, + 0x97, 0x31, 0x9e, 0x28, 0x4f, 0x1a, 0x87, 0xca, 0xdc, 0xa3, 0x5e, 0xea, + 0x11, 0x2b, 0x9e, 0x55, 0xc8, 0x51, 0xc7, 0x3a, 0x71, 0xe6, 0x29, 0xe8, + 0x46, 0xc1, 0x98, 0x1a, 0xea, 0x92, 0x7c, 0xb2, 0x07, 0x34, 0x3f, 0x82, + 0x1e, 0xb1, 0xc3, 0xfa, 0x35, 0xcc, 0x43, 0x8f, 0x92, 0xb4, 0x8f, 0x56, + 0x5d, 0x57, 0x4e, 0xeb, 0xb8, 0x35, 0xe0, 0xe9, 0xd6, 0x3f, 0x99, 0xae, + 0x2e, 0x3d, 0x8d, 0xf1, 0x2e, 0xcc, 0xff, 0x26, 0x7a, 0xc4, 0xac, 0x31, + 0x7f, 0x9e, 0x36, 0x38, 0x8e, 0xf9, 0xcf, 0x01, 0xc7, 0x9f, 0xe0, 0xfb, + 0x7e, 0x7c, 0xff, 0xd1, 0xb6, 0xbd, 0xdf, 0xe0, 0xd9, 0x98, 0xcf, 0x6e, + 0x9b, 0xf7, 0xfd, 0xb7, 0x8e, 0x93, 0xd2, 0xbd, 0x06, 0xc6, 0xd7, 0x22, + 0xb2, 0xfb, 0x7c, 0x9b, 0xa8, 0xaa, 0xeb, 0xc3, 0x55, 0xd5, 0x94, 0x9e, + 0xf3, 0xf4, 0xdf, 0x3f, 0xc2, 0x1e, 0x4b, 0xd4, 0x1a, 0x2e, 0x8d, 0x77, + 0xab, 0x6d, 0xf4, 0x99, 0xe3, 0x7d, 0x4b, 0xec, 0x0b, 0xc7, 0x47, 0x6b, + 0x84, 0xe1, 0xf7, 0x89, 0xe3, 0x7d, 0xb5, 0x9f, 0x00, 0x16, 0x72, 0x29, + 0xfb, 0xf8, 0x09, 0xff, 0xda, 0xb6, 0x33, 0xb5, 0x6c, 0x71, 0x26, 0xed, + 0xfe, 0x99, 0xe3, 0xd9, 0x0a, 0xf3, 0x83, 0x44, 0x4c, 0x74, 0x1e, 0x5e, + 0x38, 0x3e, 0x53, 0x0a, 0x4b, 0x48, 0xd3, 0xe2, 0xaf, 0x73, 0x8d, 0xf7, + 0xb0, 0x13, 0x6d, 0xa4, 0xab, 0x11, 0x0f, 0xe3, 0x0c, 0xf1, 0x9c, 0x00, + 0x9e, 0x24, 0xf0, 0x30, 0xde, 0xb8, 0xf4, 0xc6, 0x97, 0x76, 0xa2, 0x8d, + 0xb8, 0x78, 0x96, 0x8f, 0xaf, 0x47, 0xd4, 0xf9, 0xb7, 0x49, 0xaf, 0xc9, + 0x9c, 0xd6, 0xf5, 0x35, 0x4d, 0x92, 0x3f, 0x8b, 0xdc, 0xc6, 0x1e, 0xf3, + 0xc6, 0x77, 0x9b, 0xac, 0xb7, 0xe3, 0x8a, 0xf3, 0xec, 0xb1, 0x96, 0x8a, + 0x63, 0x0e, 0xe3, 0x65, 0x1f, 0x56, 0x79, 0xb0, 0x1d, 0x0d, 0x7c, 0x37, + 0x79, 0xb2, 0xe6, 0x99, 0x7e, 0xdd, 0xd9, 0x48, 0x0b, 0x40, 0x71, 0x0f, + 0xdd, 0x5b, 0xf7, 0xe0, 0xf3, 0x89, 0x85, 0x35, 0xd2, 0x96, 0x04, 0xaf, + 0x3e, 0x6d, 0x9f, 0xf6, 0xfe, 0xb8, 0x37, 0x89, 0x3f, 0xff, 0x3c, 0x5f, + 0x06, 0xa4, 0x8b, 0x3d, 0x74, 0xf9, 0x13, 0x75, 0x73, 0x12, 0x76, 0xc7, + 0x37, 0x10, 0xc7, 0x59, 0xb5, 0x29, 0xfb, 0x16, 0xdc, 0xbb, 0xf6, 0xb1, + 0xa8, 0x21, 0x14, 0x73, 0xb9, 0x38, 0xeb, 0xd5, 0xa3, 0xb2, 0x09, 0x5c, + 0x19, 0xd4, 0x94, 0x6e, 0x5d, 0x34, 0x0d, 0xff, 0xb8, 0x0e, 0xfd, 0xbc, + 0x6a, 0xf1, 0x2d, 0x26, 0xcc, 0x78, 0x27, 0xc5, 0xda, 0xcf, 0x01, 0xc3, + 0x3c, 0xea, 0xf6, 0x3b, 0xcb, 0x12, 0x60, 0x96, 0xb1, 0x76, 0xca, 0xf5, + 0xcb, 0xf4, 0xed, 0xc8, 0xa9, 0x50, 0xc3, 0x58, 0xff, 0xe3, 0xe4, 0xa3, + 0x8d, 0xb0, 0x3b, 0xbd, 0x83, 0x20, 0xe6, 0x2c, 0x26, 0xe6, 0x97, 0xe0, + 0xc3, 0x2b, 0x96, 0xda, 0xad, 0xb4, 0x46, 0x26, 0x2a, 0xf0, 0x49, 0xa8, + 0x78, 0x13, 0xf1, 0x25, 0x79, 0x5f, 0xdf, 0x43, 0x93, 0x35, 0x6c, 0xf6, + 0xa8, 0xaf, 0x52, 0xaf, 0x34, 0xe5, 0xa1, 0x33, 0x88, 0xcb, 0x23, 0x4f, + 0x20, 0xe6, 0x40, 0x5e, 0x67, 0x0a, 0xa8, 0xe2, 0xa9, 0x23, 0x3f, 0xf8, + 0x83, 0x19, 0xcb, 0xcd, 0xff, 0x75, 0x3c, 0x13, 0x97, 0xc7, 0xd0, 0x99, + 0x76, 0xed, 0x67, 0xf2, 0xda, 0xdf, 0xf4, 0x9b, 0x53, 0xaa, 0x0d, 0x39, + 0x06, 0x12, 0x4f, 0x64, 0x38, 0xe6, 0xa0, 0x48, 0x1f, 0xf3, 0x4e, 0xf8, + 0xe1, 0xbe, 0x35, 0x78, 0xb7, 0x33, 0x84, 0x57, 0x12, 0x3e, 0x13, 0x92, + 0xa6, 0x33, 0x7c, 0x0b, 0x91, 0x3d, 0xa8, 0xc3, 0x88, 0xb3, 0x2f, 0x8c, + 0x7e, 0x02, 0x7f, 0xfb, 0x90, 0x5f, 0x99, 0xc8, 0x8d, 0x77, 0x80, 0x07, + 0x2c, 0xf7, 0xec, 0x04, 0xdf, 0xd5, 0x2d, 0x6d, 0x11, 0xec, 0x21, 0x3c, + 0xf2, 0x43, 0x6b, 0x0f, 0xe8, 0x71, 0xcf, 0x27, 0x8e, 0xf0, 0x19, 0x91, + 0xfe, 0x05, 0xe9, 0x51, 0x7a, 0x4f, 0x58, 0x66, 0x52, 0x5c, 0x6b, 0x07, + 0x3c, 0xf7, 0x61, 0x4d, 0xef, 0x73, 0xdf, 0x94, 0xf2, 0xb7, 0xe9, 0xc6, + 0x9c, 0x81, 0x6f, 0xe4, 0x53, 0x29, 0x53, 0xfa, 0xab, 0x2e, 0x6c, 0xdf, + 0xda, 0x53, 0xdd, 0x7c, 0x97, 0x52, 0x96, 0x4b, 0x9b, 0x42, 0xee, 0x9b, + 0x87, 0x54, 0xc3, 0x83, 0x7c, 0x9b, 0x21, 0x0c, 0xeb, 0xd9, 0x2e, 0x0d, + 0x63, 0x0e, 0x52, 0x7e, 0xee, 0x9c, 0x52, 0xff, 0xd7, 0x9b, 0x4b, 0x63, + 0x4e, 0xa1, 0x6d, 0x05, 0xfb, 0xbf, 0xa9, 0x6d, 0x45, 0x54, 0xdc, 0xb3, + 0x15, 0x8c, 0x97, 0x39, 0xf6, 0x63, 0xf1, 0xf1, 0x7b, 0x5c, 0x7f, 0xef, + 0xc8, 0xac, 0xcd, 0xf7, 0x0b, 0x47, 0xae, 0xda, 0x05, 0xe3, 0xc0, 0x1d, + 0x79, 0x66, 0x52, 0xc7, 0xe7, 0x19, 0xc8, 0x7e, 0xb3, 0xa6, 0x6b, 0x35, + 0xb9, 0x56, 0x8b, 0xc8, 0x3b, 0x2b, 0x6d, 0xb2, 0xb9, 0xe4, 0xea, 0xfc, + 0xe6, 0x12, 0xf5, 0xdc, 0x94, 0x9f, 0xad, 0x58, 0x58, 0x4b, 0xe2, 0xaf, + 0x47, 0x6e, 0xac, 0xdc, 0x99, 0x77, 0x5e, 0xae, 0x3f, 0x0a, 0x5a, 0x7a, + 0x24, 0x64, 0x39, 0xba, 0xee, 0xca, 0x21, 0xf6, 0x15, 0x64, 0x42, 0xf2, + 0xe5, 0x7e, 0xd4, 0x7e, 0x08, 0xce, 0x61, 0xc6, 0x20, 0xdc, 0x7f, 0xf9, + 0xf3, 0xc8, 0x4d, 0x12, 0x30, 0x9e, 0x7e, 0xfd, 0xa6, 0xf8, 0xc5, 0x70, + 0x8f, 0x34, 0x5b, 0xdf, 0xec, 0x76, 0x63, 0x95, 0xe9, 0xd6, 0xa7, 0x96, + 0x1f, 0xaf, 0xdf, 0x04, 0xee, 0x11, 0xe8, 0x29, 0x75, 0xd3, 0x86, 0xce, + 0x9a, 0xb2, 0x3a, 0x94, 0xa8, 0x14, 0x84, 0xfe, 0x21, 0xc5, 0x7c, 0x11, + 0xfb, 0x92, 0x90, 0x47, 0xab, 0xce, 0x85, 0x32, 0x0a, 0x77, 0xbb, 0x30, + 0x27, 0xf9, 0xfa, 0xef, 0x63, 0x3e, 0x23, 0xd3, 0xf5, 0x71, 0x9c, 0x75, + 0x1a, 0x7a, 0xfb, 0x60, 0x8f, 0xb4, 0xf1, 0x9c, 0x14, 0x68, 0x7c, 0x44, + 0x66, 0xce, 0xce, 0xc9, 0x91, 0x32, 0xe9, 0xe4, 0x1b, 0x63, 0x22, 0x99, + 0x93, 0xe1, 0xf8, 0x0a, 0x72, 0x27, 0xd7, 0x1e, 0xd3, 0x32, 0x73, 0x0e, + 0x38, 0xca, 0xac, 0xff, 0xfb, 0xa1, 0x37, 0xc3, 0xba, 0x7e, 0x99, 0xd6, + 0x7e, 0x87, 0xf3, 0x6f, 0xe3, 0x9e, 0xfa, 0x0b, 0xfb, 0x00, 0x97, 0x47, + 0xad, 0x33, 0x85, 0x7c, 0x79, 0xb9, 0x8c, 0x3a, 0xcf, 0x0e, 0x31, 0xf7, + 0x52, 0xea, 0xa1, 0x5e, 0xa9, 0x96, 0x87, 0x4d, 0xa5, 0x98, 0x53, 0xf1, + 0x2e, 0xb8, 0x46, 0xfb, 0x8e, 0xa9, 0xb0, 0xd5, 0x2b, 0x2b, 0xe5, 0x02, + 0xea, 0x65, 0xe5, 0xbd, 0x67, 0x14, 0xc4, 0xb4, 0x5c, 0xbf, 0xa7, 0x6b, + 0x1b, 0xe6, 0x9f, 0xf5, 0x2f, 0x80, 0xc6, 0x0c, 0x2e, 0xf3, 0x24, 0xe8, + 0xc3, 0xf7, 0x32, 0x74, 0x7c, 0x81, 0x39, 0x5c, 0x06, 0x6b, 0x69, 0x39, + 0x76, 0x61, 0x0a, 0x34, 0x74, 0x4a, 0xff, 0x9f, 0xd1, 0xc6, 0x9e, 0xc4, + 0x1c, 0xc7, 0x09, 0xe8, 0xeb, 0xd7, 0xf1, 0x4d, 0xd8, 0x18, 0x7a, 0xca, + 0xa1, 0x17, 0xbd, 0x09, 0x5a, 0x58, 0x07, 0x43, 0xfe, 0x87, 0xe3, 0x52, + 0x3d, 0xfb, 0xb0, 0x4c, 0x2f, 0x3f, 0x0c, 0xfc, 0xff, 0x8a, 0xba, 0x00, + 0xf1, 0x6d, 0x99, 0x67, 0x31, 0xff, 0xe3, 0x39, 0x10, 0x10, 0x6d, 0x63, + 0x81, 0xf3, 0xec, 0x0f, 0x62, 0x3f, 0x6a, 0x8c, 0x72, 0x46, 0x66, 0xca, + 0x3c, 0x0b, 0x77, 0x87, 0x7c, 0x2a, 0x7f, 0x76, 0xca, 0xbb, 0xe3, 0x1e, + 0xc9, 0x45, 0x0b, 0xac, 0x2f, 0x10, 0x27, 0x96, 0x46, 0xb3, 0xa5, 0x84, + 0x99, 0x55, 0xc4, 0x95, 0x14, 0xc6, 0x06, 0x77, 0x2e, 0x22, 0xd6, 0x02, + 0x6a, 0xda, 0x34, 0xd7, 0x4e, 0x7a, 0x6f, 0x06, 0xc4, 0xf5, 0x63, 0x99, + 0x80, 0x8e, 0xf5, 0x2f, 0x8c, 0x20, 0x17, 0xfe, 0x29, 0x72, 0xc9, 0xb8, + 0x27, 0x83, 0x71, 0x4f, 0x37, 0xda, 0x1a, 0x74, 0x02, 0xf7, 0x5c, 0xc6, + 0xdd, 0x97, 0xa1, 0x07, 0xf0, 0xd5, 0xaf, 0x6e, 0xe9, 0xc7, 0x78, 0x43, + 0x8e, 0xd9, 0x21, 0xff, 0x50, 0x49, 0x24, 0xd7, 0xa1, 0x3f, 0x37, 0x50, + 0x0b, 0xac, 0xa3, 0x3e, 0xdc, 0xb4, 0x23, 0xa8, 0x4b, 0x0e, 0x83, 0x7e, + 0xe6, 0x94, 0x1c, 0xc7, 0x74, 0xae, 0xd3, 0x62, 0x3d, 0x7f, 0x8f, 0x7e, + 0xd7, 0x95, 0xaf, 0xf6, 0xb0, 0xa6, 0x64, 0x3d, 0xce, 0x37, 0xe9, 0x77, + 0x70, 0x8f, 0xeb, 0x26, 0xd7, 0xfd, 0x7d, 0xac, 0x05, 0x7c, 0xfd, 0x21, + 0x2d, 0xd4, 0x1f, 0xee, 0x21, 0x4c, 0x8f, 0xb6, 0x93, 0xbc, 0xc6, 0x47, + 0x9d, 0xfd, 0x9b, 0x6e, 0xd7, 0xce, 0x74, 0x9e, 0x65, 0x5e, 0x13, 0x5f, + 0x7f, 0x3f, 0x74, 0x58, 0xd7, 0x65, 0x87, 0xe0, 0xbb, 0xeb, 0x8e, 0xbc, + 0x60, 0xdf, 0x69, 0x77, 0xfb, 0xcb, 0xbe, 0x9c, 0x28, 0xc7, 0xc3, 0x72, + 0xaa, 0x9e, 0x80, 0x4d, 0x50, 0x86, 0x56, 0x83, 0x0c, 0x45, 0xfe, 0xaa, + 0x2c, 0xf2, 0x4a, 0x99, 0x6b, 0x5a, 0x86, 0xb1, 0x6c, 0xa8, 0x8d, 0xef, + 0xea, 0xd0, 0xcb, 0xb7, 0xe5, 0xc8, 0xa2, 0xc8, 0x05, 0xac, 0xaf, 0x96, + 0x69, 0xab, 0x23, 0xc8, 0x5f, 0x77, 0x49, 0x75, 0x09, 0x35, 0x59, 0x59, + 0xa6, 0xb3, 0x9f, 0x63, 0xbc, 0x89, 0xc8, 0xa6, 0x7e, 0x8f, 0x15, 0x19, + 0xbc, 0x18, 0x96, 0xf0, 0x45, 0x14, 0x7f, 0x90, 0xfd, 0xa5, 0x21, 0xff, + 0x7d, 0xd6, 0xb5, 0xf9, 0x62, 0x09, 0x7b, 0xcb, 0xfd, 0xda, 0x4f, 0x16, + 0x6b, 0x33, 0x92, 0xaf, 0xf0, 0x2c, 0xf4, 0x4b, 0x71, 0xac, 0xa5, 0x64, + 0xf6, 0xec, 0x88, 0x3c, 0x8b, 0x33, 0x50, 0xff, 0xe1, 0x8c, 0x09, 0x29, + 0x5c, 0xc0, 0x7c, 0xed, 0xba, 0x2c, 0xad, 0xcc, 0x48, 0xb5, 0x72, 0xb9, + 0xe1, 0xdd, 0x1d, 0xe3, 0xa5, 0xc6, 0x5a, 0xf6, 0x30, 0xeb, 0x19, 0xd4, + 0xaa, 0x16, 0xc6, 0x90, 0x59, 0x6d, 0x76, 0xfa, 0xce, 0xf7, 0xe2, 0xc6, + 0x1a, 0x76, 0x52, 0xe6, 0xcb, 0x29, 0x29, 0x9e, 0x1d, 0xd1, 0x6f, 0x0a, + 0x2d, 0xe9, 0xca, 0xd3, 0x37, 0x11, 0x2b, 0x26, 0xf5, 0x7b, 0xf1, 0x2d, + 0x79, 0xcc, 0x9e, 0x97, 0xa3, 0xd6, 0x41, 0x39, 0x85, 0xfc, 0xfa, 0x4b, + 0x76, 0xab, 0xc4, 0xbb, 0x79, 0x8f, 0xa0, 0xd7, 0x62, 0x0d, 0xea, 0xc8, + 0x84, 0xfd, 0xa0, 0xf9, 0x3c, 0x24, 0xfb, 0x4e, 0x8d, 0x71, 0xf2, 0xbf, + 0x9d, 0x0c, 0xe2, 0xde, 0x4d, 0xd4, 0x8e, 0x19, 0x0d, 0x67, 0xb8, 0x70, + 0x15, 0xc2, 0x0d, 0x9b, 0x2f, 0x10, 0x6e, 0xc9, 0xf0, 0xe0, 0x0c, 0xc0, + 0x85, 0x64, 0xc3, 0x0e, 0x43, 0x47, 0x26, 0xc1, 0x27, 0x7c, 0xfc, 0x68, + 0x87, 0x97, 0x07, 0xb7, 0x22, 0xb6, 0xde, 0xde, 0xff, 0x86, 0xb7, 0xff, + 0x59, 0x6f, 0xff, 0xd5, 0xad, 0xfd, 0x7e, 0x7c, 0xfd, 0x85, 0x23, 0x0d, + 0x74, 0xbd, 0x51, 0x72, 0xe1, 0xe7, 0x3d, 0xba, 0xae, 0x6e, 0xd1, 0xe5, + 0xc3, 0x43, 0x9e, 0x9a, 0x67, 0xfa, 0x66, 0xfa, 0xe8, 0x7e, 0xc8, 0xd1, + 0x91, 0x9c, 0x0d, 0xdb, 0x28, 0x27, 0xc6, 0x0b, 0xfa, 0x2d, 0x4d, 0xc9, + 0x7a, 0x74, 0x5e, 0x26, 0xad, 0xc4, 0xf8, 0xac, 0x84, 0xa0, 0xcb, 0xf4, + 0x2d, 0x21, 0xa9, 0xd2, 0xe7, 0xa0, 0xcf, 0xdb, 0x3b, 0xd3, 0xfa, 0x4e, + 0x03, 0xad, 0xa1, 0x97, 0x49, 0xa3, 0x4b, 0x6b, 0x64, 0xe0, 0x36, 0xad, + 0x2e, 0xbc, 0x4b, 0xeb, 0x3b, 0xa5, 0x06, 0xf8, 0x8b, 0x61, 0x0f, 0x3e, + 0xdc, 0x00, 0x4f, 0x7d, 0x66, 0x5e, 0x41, 0x7d, 0x26, 0x6d, 0x9f, 0x85, + 0x6d, 0x48, 0xa4, 0x35, 0x5d, 0x39, 0xfe, 0xc0, 0x80, 0x23, 0x11, 0xe4, + 0x1b, 0xcd, 0x58, 0xdb, 0xac, 0x30, 0x17, 0x51, 0x7d, 0xcd, 0x32, 0x08, + 0x9d, 0xe5, 0xdd, 0xb9, 0x6f, 0x82, 0x8f, 0xe9, 0x9c, 0xc0, 0x91, 0xa3, + 0x36, 0x69, 0x79, 0xdf, 0x79, 0x25, 0x3a, 0x68, 0x17, 0x65, 0xc8, 0x6c, + 0xc6, 0xf9, 0xd5, 0xba, 0xc6, 0x99, 0x24, 0x2d, 0xe7, 0x87, 0xfa, 0xcd, + 0xbf, 0x07, 0x9f, 0x13, 0x15, 0x43, 0xaa, 0x56, 0x22, 0x76, 0x09, 0x38, + 0xf6, 0xe1, 0x6e, 0xaa, 0x23, 0xa4, 0x47, 0xe4, 0x08, 0xf4, 0xbb, 0xaa, + 0xe3, 0x22, 0xf5, 0x38, 0x31, 0x59, 0x40, 0xae, 0xf3, 0xd7, 0x3a, 0xb6, + 0x39, 0xce, 0x4d, 0xc4, 0xb7, 0xc9, 0x6d, 0xba, 0xa7, 0x2e, 0xba, 0xba, + 0xa7, 0x2e, 0xa2, 0x06, 0x3e, 0x1d, 0x91, 0x96, 0x55, 0xd8, 0xcf, 0xcb, + 0x7b, 0xdc, 0x7c, 0xee, 0x65, 0xfe, 0xe6, 0x04, 0x7f, 0x77, 0x3a, 0x2c, + 0xd6, 0x69, 0x1d, 0x0f, 0x20, 0xef, 0x09, 0x99, 0x3d, 0x47, 0x9f, 0x6a, + 0xc9, 0xc0, 0x69, 0xde, 0x07, 0xf3, 0x9a, 0xa5, 0xd1, 0x19, 0xd8, 0xc8, + 0x1c, 0xfc, 0x82, 0x5a, 0x7d, 0x57, 0x66, 0x2c, 0xca, 0xa1, 0x53, 0xda, + 0x56, 0x51, 0x8f, 0xaf, 0xc2, 0x37, 0xac, 0xc6, 0xa4, 0x09, 0xb6, 0xa5, + 0x2e, 0x46, 0x8d, 0xe2, 0xe2, 0x07, 0xb0, 0x07, 0xfe, 0x7e, 0x83, 0xdc, + 0xf2, 0x62, 0xcc, 0xa0, 0x6d, 0xa9, 0x8b, 0xd4, 0x73, 0xa4, 0x53, 0x17, + 0xa9, 0xe7, 0xa4, 0xc3, 0xb7, 0x17, 0x7c, 0x5f, 0x1c, 0xd1, 0xef, 0xd3, + 0x37, 0x6d, 0xf2, 0xf2, 0x8f, 0x92, 0xad, 0x30, 0x47, 0x24, 0x3f, 0xd2, + 0x8d, 0x5c, 0xa6, 0x2b, 0x6b, 0x0f, 0x8c, 0x6f, 0xca, 0xa7, 0xe5, 0xeb, + 0xee, 0x4f, 0xc1, 0x17, 0xf9, 0x68, 0xe4, 0x8b, 0x3c, 0x75, 0x4a, 0x93, + 0xe6, 0xcb, 0xe7, 0x07, 0x82, 0x06, 0x3f, 0x7d, 0xa7, 0x63, 0xc0, 0xff, + 0x75, 0xf8, 0x80, 0x5e, 0xf4, 0x4f, 0xa2, 0x47, 0x48, 0xbb, 0x48, 0xde, + 0xc9, 0xeb, 0x0d, 0xe4, 0x8d, 0x3e, 0x9f, 0xd3, 0xf8, 0x7e, 0x5d, 0x66, + 0x17, 0x9d, 0x93, 0x88, 0xab, 0x7c, 0x3b, 0xef, 0x71, 0xdf, 0x81, 0xb7, + 0xf3, 0xfe, 0xba, 0xb8, 0xf2, 0x49, 0x98, 0x55, 0xc1, 0xf7, 0xca, 0x76, + 0x59, 0x34, 0xfa, 0x8e, 0x98, 0xce, 0xc3, 0x8f, 0xd4, 0xe8, 0x27, 0x28, + 0xa3, 0x1b, 0x92, 0x5d, 0xe4, 0xfb, 0x97, 0x8b, 0x6f, 0xba, 0xe6, 0xfb, + 0x8d, 0xc6, 0x3d, 0x36, 0xe0, 0x7a, 0x01, 0x47, 0xba, 0xd6, 0x29, 0x3f, + 0xf8, 0x9c, 0xbd, 0x0d, 0xbe, 0xa6, 0x71, 0xdf, 0xb8, 0x3c, 0x87, 0x3c, + 0xe0, 0x0d, 0xfb, 0x0e, 0xb9, 0x4e, 0x33, 0x17, 0xaa, 0xd6, 0xa6, 0x60, + 0x93, 0x4d, 0xf0, 0x65, 0xa6, 0x6c, 0x96, 0x9a, 0xa5, 0x8a, 0x7c, 0x67, + 0x79, 0x85, 0xbe, 0x90, 0xb4, 0xb7, 0x61, 0xde, 0xf5, 0x5f, 0xf4, 0xb5, + 0x9b, 0x25, 0xc4, 0x59, 0xd8, 0xf6, 0x66, 0x29, 0x8a, 0xbe, 0x17, 0xbd, + 0x85, 0x3e, 0x8e, 0x3e, 0x89, 0x7e, 0x04, 0xfd, 0x08, 0x7a, 0x0b, 0x7b, + 0x63, 0xe8, 0xfd, 0x9a, 0x81, 0xb8, 0x6e, 0xf3, 0x5d, 0xd4, 0xe7, 0x21, + 0x57, 0xb4, 0x18, 0xd3, 0xc2, 0x76, 0x0e, 0x75, 0x44, 0x76, 0x84, 0xb9, + 0x1e, 0x73, 0xbe, 0x8f, 0x1d, 0xd3, 0x62, 0x5d, 0x5e, 0x30, 0xf6, 0x0d, + 0x31, 0x2e, 0x54, 0x10, 0x17, 0x3e, 0xd8, 0x8d, 0xfa, 0xd1, 0xdc, 0xaf, + 0xdf, 0x8e, 0x16, 0x31, 0xe6, 0x37, 0x6a, 0xde, 0xe8, 0x1c, 0xe2, 0x14, + 0xfd, 0xa7, 0x83, 0x3d, 0x79, 0xf8, 0xf1, 0x2e, 0xd8, 0x5f, 0x06, 0x7e, + 0x1b, 0xdf, 0x4b, 0x6f, 0xec, 0x76, 0x63, 0x2a, 0xf2, 0x77, 0xb5, 0xfd, + 0xbd, 0xc6, 0xc6, 0x9e, 0x9d, 0x6a, 0x83, 0x0e, 0xe0, 0x48, 0x54, 0x96, + 0x60, 0x83, 0x3f, 0xb4, 0x4f, 0xea, 0xdc, 0x8e, 0x77, 0xf1, 0x2c, 0x72, + 0xd4, 0xdc, 0x02, 0x73, 0x98, 0x13, 0xa8, 0x4b, 0x50, 0x9f, 0x45, 0x59, + 0x93, 0x33, 0x16, 0xe8, 0x5c, 0x34, 0x2a, 0x6d, 0x8c, 0x03, 0x37, 0x70, + 0x1e, 0xf8, 0x5a, 0x76, 0x20, 0xb3, 0x03, 0xc8, 0x09, 0x1d, 0x27, 0x6c, + 0xed, 0x93, 0xf8, 0x21, 0xfa, 0x1c, 0xc1, 0x7e, 0x53, 0xdc, 0xf7, 0x74, + 0xf8, 0xdd, 0x29, 0xfd, 0x5b, 0x31, 0x94, 0xeb, 0xb3, 0xd8, 0x7b, 0x17, + 0x70, 0x71, 0x9e, 0x6f, 0xd9, 0x22, 0xfb, 0x16, 0xdc, 0x9c, 0x56, 0x59, + 0x8d, 0xf8, 0x7e, 0xd5, 0xc3, 0xc7, 0x75, 0xe5, 0xfd, 0xa6, 0xb1, 0xc7, + 0x7d, 0x1b, 0xc6, 0x1d, 0x9f, 0x42, 0xfe, 0xbc, 0x81, 0x7b, 0x79, 0x03, + 0x77, 0x72, 0xa5, 0x44, 0x5d, 0x1f, 0x86, 0xde, 0x43, 0x86, 0x53, 0xc4, + 0x35, 0xa2, 0xcf, 0xde, 0x28, 0xc1, 0x77, 0xd2, 0xff, 0x29, 0x64, 0x77, + 0x6d, 0x6e, 0x4c, 0x77, 0xf1, 0xf4, 0xba, 0x70, 0xe2, 0xaf, 0xed, 0xd6, + 0xf4, 0x54, 0xf5, 0x3b, 0x18, 0xe5, 0x04, 0x1d, 0xe4, 0x6f, 0x03, 0x1a, + 0xe6, 0x6b, 0x51, 0xfd, 0xfe, 0xae, 0x38, 0x47, 0x3e, 0x46, 0x24, 0xbb, + 0xe0, 0xef, 0xeb, 0xc6, 0xbe, 0xd6, 0x06, 0x5c, 0x77, 0x6f, 0xe3, 0x41, + 0x79, 0x3c, 0x70, 0xfd, 0x93, 0x6f, 0xc3, 0x85, 0xad, 0xb7, 0x61, 0xc6, + 0x5f, 0xde, 0x4d, 0x0a, 0xfb, 0xfd, 0xfb, 0xe9, 0xf5, 0x6a, 0x81, 0xc4, + 0x7c, 0x41, 0x98, 0xab, 0xf0, 0x8e, 0xc6, 0x61, 0xd7, 0x5d, 0xc0, 0x6f, + 0x4b, 0xa5, 0xd4, 0x22, 0xaa, 0x87, 0xb5, 0x31, 0x73, 0xe5, 0xc6, 0x33, + 0x7f, 0xdb, 0x3b, 0x13, 0xf5, 0xf4, 0x19, 0xe6, 0xcd, 0x3a, 0xce, 0x00, + 0xa6, 0x7d, 0x1b, 0x6d, 0xbf, 0xee, 0xc1, 0x71, 0x3d, 0x29, 0x05, 0xe4, + 0xa1, 0xb9, 0x05, 0x64, 0xf4, 0xf0, 0xdf, 0x2a, 0xcd, 0xdf, 0xb3, 0xf8, + 0x86, 0x37, 0x1c, 0x9f, 0x05, 0x8d, 0x05, 0x33, 0xc3, 0x77, 0x33, 0xe0, + 0xd8, 0xbb, 0x0d, 0xc7, 0x84, 0x87, 0x63, 0x42, 0x8a, 0xe7, 0x26, 0x61, + 0x6b, 0x19, 0xc4, 0xf7, 0x7e, 0xf3, 0x80, 0x7c, 0x1e, 0xc5, 0x35, 0xe6, + 0x2e, 0x8c, 0xe0, 0x9e, 0x1c, 0x67, 0x9f, 0x7d, 0x18, 0x74, 0xbf, 0x86, + 0xd8, 0xea, 0xe7, 0x3c, 0xc5, 0x58, 0x08, 0x31, 0xec, 0x98, 0xfe, 0x0d, + 0xb6, 0x60, 0x9a, 0xd0, 0x57, 0x65, 0x0c, 0x27, 0x51, 0xde, 0x23, 0xbe, + 0xcd, 0x23, 0x56, 0x91, 0xcf, 0x0e, 0x29, 0x9a, 0xc6, 0xa3, 0x21, 0xe4, + 0x35, 0xd9, 0x05, 0xda, 0x91, 0x0c, 0x84, 0xd2, 0xcd, 0xc8, 0x49, 0x1d, + 0xf9, 0x99, 0xcd, 0x7f, 0xa3, 0x30, 0x2f, 0x1b, 0x35, 0x13, 0xfd, 0x3a, + 0xee, 0xe1, 0xdb, 0xf8, 0xbe, 0xde, 0x83, 0xbc, 0x0f, 0x2b, 0x19, 0xe8, + 0x6e, 0x52, 0xe7, 0x33, 0xcc, 0x23, 0xaa, 0x88, 0xb7, 0x0a, 0xb1, 0x06, + 0x79, 0xd5, 0x38, 0x73, 0xd7, 0xe7, 0x96, 0xaf, 0xcb, 0x95, 0x45, 0xfe, + 0x06, 0xca, 0xb8, 0x7c, 0x90, 0xfe, 0xc0, 0x9c, 0x4b, 0x61, 0x6e, 0x85, + 0xbe, 0x0c, 0xe3, 0x3a, 0x0c, 0xa8, 0x07, 0x39, 0x02, 0x72, 0xed, 0x4d, + 0x2b, 0x09, 0x3e, 0xaf, 0xcb, 0xc6, 0x62, 0x58, 0x96, 0x2d, 0xe6, 0x45, + 0x12, 0xcf, 0x02, 0x76, 0x63, 0xe5, 0x9a, 0xab, 0x13, 0x84, 0x47, 0xcd, + 0x53, 0x40, 0x5e, 0x77, 0x40, 0xef, 0xfd, 0x65, 0xf7, 0x4c, 0x9a, 0x1a, + 0xeb, 0xbc, 0x19, 0xd9, 0xa0, 0x3d, 0xd9, 0x7c, 0x93, 0x62, 0x6e, 0x70, + 0x02, 0x3a, 0xcb, 0xdc, 0x9d, 0xf5, 0x00, 0xbe, 0x6b, 0x5c, 0x27, 0xef, + 0xe8, 0x97, 0xfa, 0x21, 0x1b, 0xda, 0x3d, 0xdf, 0xc4, 0x10, 0x47, 0x15, + 0x6d, 0xbd, 0xa8, 0x7d, 0x41, 0xb1, 0x3c, 0x83, 0x98, 0x02, 0x1f, 0xc0, + 0xdf, 0x70, 0xa6, 0xa6, 0x70, 0x97, 0xe3, 0x80, 0xdb, 0x16, 0x4b, 0xd6, + 0x8a, 0x3a, 0x2f, 0x53, 0xe7, 0x6f, 0xbf, 0xdf, 0xe4, 0x61, 0x3f, 0x6a, + 0x0d, 0xba, 0x05, 0x1b, 0x52, 0x6b, 0x51, 0xf4, 0xf0, 0xc7, 0x6b, 0xa8, + 0x2f, 0x4a, 0x7c, 0x1f, 0x42, 0x6d, 0x50, 0xe2, 0xdb, 0x49, 0x12, 0xfd, + 0x08, 0xdf, 0x8b, 0x3c, 0xbf, 0x46, 0xfc, 0xa4, 0xc3, 0xf7, 0x2f, 0xcc, + 0x25, 0xe9, 0x5f, 0xfc, 0x7c, 0xd2, 0xd5, 0x85, 0x53, 0x65, 0xfa, 0x10, + 0xea, 0x75, 0x3f, 0xfc, 0x16, 0x75, 0xc1, 0xcd, 0x25, 0x57, 0x2a, 0xae, + 0xcc, 0x66, 0xeb, 0x97, 0x75, 0x8c, 0xd8, 0x2f, 0x16, 0x74, 0x8c, 0xb2, + 0xc3, 0x9a, 0x8e, 0x01, 0x97, 0x24, 0xa3, 0x7b, 0xca, 0xec, 0x75, 0xc9, + 0xac, 0x8c, 0xc8, 0x0b, 0xda, 0x6f, 0xf9, 0x3e, 0x8b, 0x39, 0x64, 0x0c, + 0xf2, 0x4b, 0xca, 0xf3, 0x67, 0xaf, 0x4b, 0xf6, 0x45, 0xfa, 0xad, 0xe1, + 0x58, 0xab, 0x41, 0x5f, 0xe5, 0x48, 0x0d, 0xb1, 0xe9, 0x80, 0xcd, 0x7f, + 0x07, 0x10, 0x42, 0x4d, 0xe7, 0x48, 0xf3, 0x68, 0xc2, 0x8e, 0x1b, 0xfd, + 0x4f, 0xb6, 0x1a, 0x8c, 0x8d, 0xc3, 0xe6, 0x53, 0xe2, 0xbf, 0x47, 0xb5, + 0xc8, 0x53, 0xfa, 0xad, 0x02, 0x66, 0xbb, 0xf0, 0x91, 0xfe, 0x1d, 0xe5, + 0x66, 0x8a, 0xb2, 0xc6, 0x78, 0x8d, 0xf3, 0x85, 0xc8, 0xcd, 0x54, 0x93, + 0x14, 0xef, 0x72, 0x9c, 0xa3, 0xa3, 0xa9, 0xdd, 0xee, 0xbf, 0x15, 0xf9, + 0xc6, 0x5d, 0xae, 0x2f, 0x38, 0xea, 0x8d, 0x5f, 0x41, 0x4f, 0xdd, 0x66, + 0xbc, 0x65, 0x7c, 0xe4, 0xbd, 0xa1, 0x5f, 0xe1, 0x37, 0x63, 0xef, 0x3c, + 0x62, 0x2f, 0xe3, 0x65, 0x97, 0xe4, 0x0e, 0x6b, 0x9f, 0xc1, 0xf9, 0x82, + 0x9b, 0x4b, 0x7b, 0x70, 0x95, 0x69, 0x99, 0xad, 0x30, 0x87, 0xda, 0x40, + 0x2c, 0x1b, 0x82, 0xae, 0x32, 0xa6, 0x9d, 0x44, 0x3c, 0xe7, 0xef, 0xd2, + 0x58, 0x5b, 0xe2, 0xbe, 0x44, 0x32, 0xae, 0xc0, 0xf3, 0x96, 0x4e, 0xdd, + 0x8c, 0xf2, 0x3d, 0xea, 0xd2, 0x10, 0xee, 0xfd, 0x4f, 0x59, 0x5b, 0x0c, + 0x68, 0x1d, 0xc9, 0xbe, 0x4c, 0xd9, 0xbb, 0xbf, 0x5b, 0x4b, 0xb7, 0x6b, + 0x03, 0xcc, 0x03, 0x1e, 0x87, 0x5c, 0xf6, 0xdb, 0xd7, 0x19, 0xbb, 0xff, + 0x5d, 0x59, 0xc3, 0xc9, 0xa7, 0x0c, 0xda, 0x36, 0xc6, 0x2b, 0x21, 0x59, + 0x8a, 0x92, 0x7f, 0xc8, 0xcb, 0xa0, 0xed, 0xec, 0x24, 0x87, 0xed, 0x32, + 0xf8, 0x4b, 0xc8, 0x80, 0xb2, 0xf4, 0x65, 0xc0, 0xef, 0x49, 0xdc, 0x17, + 0x6b, 0x86, 0x7e, 0x5d, 0x47, 0x16, 0xeb, 0xee, 0xd9, 0xc5, 0x72, 0x23, + 0xcd, 0xa4, 0x97, 0x77, 0x7a, 0x49, 0x72, 0xfa, 0x7e, 0xe7, 0x25, 0x57, + 0xb9, 0x24, 0xfb, 0x2a, 0xf3, 0xf2, 0x98, 0xf5, 0x28, 0xf8, 0xbd, 0xe6, + 0xcc, 0x58, 0xba, 0x56, 0x19, 0xcf, 0xff, 0x6f, 0xe7, 0x56, 0x1b, 0xdb, + 0x56, 0x75, 0x86, 0x5f, 0x5f, 0xdb, 0x69, 0x1a, 0x9a, 0x70, 0xeb, 0x3a, + 0x89, 0x9b, 0x66, 0xad, 0x1d, 0xdf, 0x7e, 0x88, 0xa4, 0xe8, 0x36, 0x64, + 0x34, 0xea, 0x82, 0x62, 0x9c, 0x50, 0xc2, 0xe8, 0x44, 0xda, 0x75, 0x55, + 0xb5, 0x31, 0x64, 0x39, 0xe9, 0x07, 0xd3, 0x06, 0xa3, 0xb0, 0x82, 0x18, + 0x52, 0x8d, 0xdb, 0x6a, 0x9d, 0x96, 0xc6, 0xe9, 0x07, 0x6b, 0x37, 0x69, + 0x9a, 0xe5, 0xa4, 0x2d, 0x48, 0x11, 0x2e, 0x88, 0x6e, 0xfb, 0xb1, 0x8d, + 0x2a, 0x65, 0xec, 0xff, 0xf6, 0x67, 0xda, 0xd0, 0x16, 0x15, 0x18, 0xfc, + 0xd8, 0xa4, 0xfe, 0xe0, 0x47, 0x25, 0xe8, 0xbc, 0xe7, 0x79, 0xcf, 0xbd, + 0x8e, 0x6d, 0x82, 0x26, 0x2d, 0x52, 0xe4, 0x7b, 0xce, 0x3d, 0xf7, 0x9c, + 0x73, 0xcf, 0xfb, 0xfd, 0xbe, 0xcf, 0xc5, 0xda, 0x13, 0x7d, 0x6b, 0xe5, + 0x63, 0xf8, 0x1d, 0x27, 0x67, 0x6d, 0xc9, 0xd8, 0x83, 0xf2, 0x63, 0xcd, + 0xe5, 0x33, 0x3e, 0x09, 0xc0, 0x27, 0x35, 0xb8, 0x02, 0x69, 0x77, 0x62, + 0x37, 0x85, 0x3e, 0x65, 0x18, 0xb4, 0x8e, 0x1b, 0xbf, 0xd9, 0x36, 0xf7, + 0x37, 0x9d, 0x81, 0xef, 0xee, 0x0e, 0xb4, 0xfb, 0x39, 0x5f, 0xe3, 0xdf, + 0xfe, 0xc5, 0xab, 0xa1, 0x0d, 0xca, 0x0c, 0xf6, 0xf3, 0x96, 0xea, 0x59, + 0x07, 0xbc, 0xc4, 0xdc, 0x74, 0x4c, 0xf3, 0x0f, 0xe1, 0x69, 0xea, 0xa8, + 0xab, 0xd0, 0x51, 0x43, 0xd4, 0x5d, 0xc3, 0xb3, 0x2e, 0xf3, 0x03, 0x51, + 0xf9, 0xf3, 0x14, 0xf5, 0x70, 0x5c, 0xfe, 0x34, 0xf5, 0x02, 0xf6, 0x93, + 0x28, 0x32, 0x47, 0x79, 0x63, 0x26, 0x47, 0x3f, 0x49, 0xfd, 0xf9, 0xb4, + 0xfb, 0xac, 0xda, 0x81, 0xb8, 0x95, 0x5f, 0x13, 0x56, 0x7d, 0xf3, 0xb4, + 0xd6, 0x74, 0xe3, 0x56, 0xb7, 0xdc, 0x38, 0x6f, 0x74, 0x6c, 0x78, 0x3a, + 0x1a, 0x18, 0x99, 0xa3, 0x5d, 0x4a, 0xc6, 0xb2, 0xd6, 0x0a, 0x39, 0x10, + 0x65, 0xee, 0x39, 0x45, 0xfd, 0x0c, 0x5b, 0xd8, 0x6b, 0x67, 0xad, 0x66, + 0xcf, 0xfe, 0xc4, 0x1a, 0xf4, 0xec, 0xd3, 0x9e, 0x9e, 0xe5, 0xbd, 0x14, + 0x68, 0x4a, 0x5b, 0x94, 0x98, 0x19, 0xb5, 0x92, 0xb0, 0x79, 0xb8, 0x9e, + 0xe7, 0xfc, 0x71, 0x39, 0x32, 0x7f, 0x18, 0xfe, 0x77, 0xaf, 0xbd, 0x87, + 0x76, 0xd5, 0x1e, 0x22, 0x16, 0x07, 0xeb, 0x7f, 0xa9, 0x61, 0xae, 0xc7, + 0xbd, 0xb9, 0x78, 0x1f, 0x72, 0x3e, 0xed, 0xc8, 0x04, 0x6c, 0xc9, 0x88, + 0x6d, 0xf6, 0x5a, 0x3f, 0x76, 0x77, 0x75, 0xdd, 0x13, 0x05, 0xc7, 0xc3, + 0x85, 0xe1, 0x17, 0xbe, 0xd0, 0xd7, 0x23, 0x5c, 0x93, 0xeb, 0xb5, 0x49, + 0x7a, 0x1f, 0xf4, 0xcb, 0x34, 0xff, 0x73, 0x5e, 0xed, 0x0a, 0xf1, 0x4a, + 0xb4, 0x6b, 0x19, 0xdb, 0xf4, 0x80, 0x37, 0xdf, 0xb6, 0x0e, 0x69, 0x89, + 0xd6, 0x8c, 0x67, 0x6e, 0x85, 0xed, 0xb8, 0xe4, 0xe6, 0xf9, 0x5b, 0xa9, + 0x44, 0x9c, 0x26, 0xd9, 0x63, 0xaf, 0x6b, 0x98, 0x63, 0x2b, 0xfa, 0x8c, + 0x4f, 0x10, 0x9c, 0x0e, 0x78, 0xbe, 0xc5, 0x06, 0xfa, 0x4d, 0xde, 0x75, + 0xb3, 0xe6, 0x64, 0xe2, 0x56, 0x57, 0xc3, 0x7b, 0x6c, 0xa8, 0xda, 0xe1, + 0xb8, 0x45, 0xdd, 0xd9, 0x14, 0x95, 0x36, 0xf2, 0x50, 0x45, 0xfd, 0xf8, + 0x90, 0x63, 0xb0, 0x16, 0x51, 0xe7, 0x60, 0x07, 0x73, 0xf6, 0x6f, 0xeb, + 0xb9, 0xb5, 0xd2, 0x27, 0xc0, 0x35, 0xf8, 0xe4, 0x73, 0xf9, 0x5e, 0xe6, + 0x7a, 0x31, 0x7f, 0x0b, 0xe7, 0x77, 0xbd, 0x73, 0x4e, 0xb8, 0x39, 0xeb, + 0x7e, 0xc9, 0x9e, 0x37, 0xfc, 0x97, 0x76, 0xc0, 0x7b, 0x6d, 0x68, 0xcf, + 0xd1, 0x26, 0x7c, 0xd1, 0x3c, 0xbe, 0x6d, 0xd8, 0xa2, 0xb6, 0xe1, 0x78, + 0x81, 0xfc, 0x49, 0xbe, 0xf4, 0xf9, 0xd1, 0xd7, 0x79, 0xe4, 0x51, 0xea, + 0xd9, 0x41, 0x39, 0x53, 0xe0, 0xd9, 0xa4, 0xb4, 0xa6, 0xb5, 0xf1, 0xec, + 0x84, 0xe2, 0xb1, 0x7a, 0xa6, 0x13, 0x17, 0x73, 0x32, 0x2c, 0x57, 0x5d, + 0x9e, 0x59, 0xa2, 0x98, 0x09, 0xb6, 0xd6, 0xbc, 0xff, 0x3e, 0x3d, 0xb3, + 0xb0, 0xfa, 0x8c, 0x31, 0x8c, 0x7d, 0xc9, 0xa3, 0x77, 0x9b, 0x9e, 0x6d, + 0xa6, 0x8e, 0x3e, 0x8f, 0xea, 0x39, 0x85, 0xa1, 0x13, 0x59, 0xc7, 0x0f, + 0x47, 0xf8, 0x0c, 0xd7, 0xa5, 0xcf, 0xc7, 0xb5, 0xc8, 0x7b, 0x3d, 0xb0, + 0xd8, 0xfd, 0x12, 0xdc, 0x01, 0xd1, 0xdf, 0xc1, 0x3a, 0x72, 0x00, 0xb2, + 0xba, 0xd1, 0x60, 0x5f, 0xc6, 0x8d, 0xaf, 0x91, 0xb1, 0xde, 0xc2, 0x39, + 0x22, 0x56, 0x81, 0x1f, 0x7d, 0xfc, 0xa7, 0x77, 0x30, 0x5f, 0xc6, 0xf3, + 0xd7, 0x07, 0x30, 0x3f, 0xcf, 0x82, 0x32, 0x36, 0xb5, 0x8d, 0xbc, 0x3a, + 0xaa, 0xf5, 0x41, 0x3e, 0x43, 0x39, 0xe6, 0x99, 0x91, 0x2e, 0x7f, 0xc3, + 0xf3, 0x6c, 0x6f, 0x6d, 0xa0, 0x63, 0xd2, 0xdb, 0x9f, 0x7f, 0x3f, 0x2c, + 0xe1, 0x0e, 0xea, 0xb8, 0xa8, 0x24, 0xa7, 0x19, 0xb3, 0xc0, 0x76, 0x8d, + 0x73, 0xae, 0xff, 0xad, 0x8b, 0x33, 0xff, 0xa7, 0x2e, 0xce, 0x58, 0x1f, + 0x29, 0xef, 0x84, 0x35, 0x8f, 0xf5, 0xc5, 0x74, 0x2d, 0xd6, 0xd1, 0xd5, + 0xaf, 0xdd, 0x47, 0xab, 0x74, 0xfc, 0x51, 0x81, 0xf6, 0x2a, 0xa5, 0x39, + 0xe5, 0x7f, 0x4e, 0xf1, 0x6c, 0xb9, 0xc7, 0xab, 0xdc, 0xe3, 0xf0, 0x82, + 0x62, 0x20, 0xbf, 0xa6, 0x32, 0x7c, 0xb2, 0x40, 0x1d, 0xd3, 0x2a, 0xb3, + 0x33, 0xbe, 0x9e, 0x19, 0xf3, 0x7c, 0xdc, 0xfc, 0x9a, 0x26, 0xd5, 0x33, + 0xf0, 0x6e, 0x9c, 0x11, 0xcf, 0xbe, 0x74, 0x4b, 0xe9, 0x3c, 0xed, 0x6e, + 0x12, 0x7d, 0xd1, 0x40, 0x69, 0x8e, 0xb5, 0x49, 0x62, 0x50, 0x86, 0x85, + 0x75, 0xff, 0x11, 0xfb, 0x38, 0xe4, 0x2d, 0x26, 0xef, 0x4f, 0xd1, 0xa7, + 0x6f, 0x82, 0x6f, 0xdc, 0xd6, 0x70, 0xbe, 0xdb, 0xab, 0x3e, 0x61, 0x3d, + 0xdd, 0x37, 0x74, 0x4a, 0x0b, 0xf9, 0xdc, 0xb1, 0x6f, 0x08, 0x7d, 0x30, + 0x5e, 0x67, 0x11, 0x0b, 0x30, 0xf6, 0x88, 0x6b, 0xec, 0x51, 0x2a, 0xb2, + 0xaf, 0xd5, 0xcb, 0x2b, 0xb5, 0x2a, 0xaf, 0x90, 0xdf, 0x32, 0xea, 0x7f, + 0x0f, 0xa9, 0xce, 0xca, 0x4f, 0xf5, 0x1a, 0xfc, 0x8a, 0x1d, 0x53, 0xde, + 0x93, 0x3a, 0xde, 0x8b, 0x79, 0x6b, 0x3f, 0xdc, 0x69, 0x7c, 0x2b, 0x5b, + 0xf5, 0x4d, 0x58, 0xc7, 0xd1, 0xae, 0x70, 0x7e, 0xf2, 0x06, 0x79, 0x84, + 0x3a, 0xcf, 0x1f, 0xe7, 0xd3, 0xc3, 0x6f, 0x73, 0x3c, 0xf9, 0xbf, 0x16, + 0x8b, 0xe0, 0xcb, 0xaa, 0xdf, 0xe7, 0xcb, 0x1d, 0xef, 0xd5, 0xda, 0x04, + 0xca, 0x5d, 0x6d, 0x7d, 0xd2, 0x96, 0xc8, 0xf4, 0x12, 0x5d, 0xd2, 0xfd, + 0xdc, 0xff, 0x4b, 0xcc, 0xed, 0x42, 0xde, 0x96, 0xa3, 0xcd, 0x51, 0xa5, + 0x4d, 0x06, 0xb4, 0x89, 0x28, 0x6d, 0x18, 0xef, 0x3d, 0xe3, 0xf1, 0x5b, + 0x2b, 0xce, 0x8b, 0xb9, 0x5a, 0xe8, 0xba, 0xbd, 0xd4, 0xf9, 0xcf, 0x77, + 0x6a, 0x7d, 0xd0, 0xa1, 0xee, 0x5b, 0x05, 0x7d, 0xc6, 0xf6, 0x66, 0xf5, + 0x47, 0x4c, 0xbc, 0x15, 0xd7, 0x3c, 0x68, 0x10, 0xfa, 0xb9, 0x34, 0x05, + 0x5f, 0x8d, 0x78, 0xb7, 0x3a, 0x5a, 0x7d, 0xc7, 0x3b, 0xaf, 0x92, 0xd2, + 0x86, 0x32, 0x40, 0xbd, 0xb9, 0x1a, 0xf3, 0xed, 0x8e, 0xf6, 0x81, 0xbf, + 0x7e, 0x81, 0xfe, 0x8d, 0x1a, 0x4f, 0x04, 0x21, 0xf3, 0x37, 0xa7, 0x3a, + 0xbc, 0x18, 0xce, 0x41, 0x1b, 0x71, 0xeb, 0x54, 0x84, 0x31, 0x05, 0xda, + 0x5b, 0xa4, 0x69, 0x1a, 0xf1, 0x2b, 0xf4, 0xf8, 0x82, 0xda, 0xa3, 0x3e, + 0xdc, 0xbf, 0x8b, 0x18, 0x3f, 0x5c, 0x1f, 0xc6, 0x73, 0xbd, 0x06, 0x8b, + 0x10, 0xdd, 0xa4, 0x67, 0x5a, 0x9a, 0x4a, 0xc4, 0x0e, 0x8a, 0xd7, 0x37, + 0xee, 0xaa, 0x3e, 0x58, 0xda, 0xd7, 0x43, 0xb2, 0xbb, 0x6a, 0x2f, 0x18, + 0x47, 0xc3, 0x87, 0x9f, 0x31, 0xf6, 0x20, 0x5f, 0xec, 0x53, 0x5c, 0x54, + 0x70, 0x68, 0x1e, 0x67, 0x49, 0x9f, 0x74, 0x11, 0x7e, 0xb8, 0x8b, 0x33, + 0xa4, 0xdf, 0x5d, 0x39, 0x76, 0xc2, 0x4d, 0xb1, 0x3e, 0x06, 0x7d, 0x70, + 0x4c, 0x46, 0x10, 0x17, 0x8c, 0x04, 0xdb, 0x98, 0x57, 0x86, 0x6f, 0x98, + 0xf3, 0x72, 0x8f, 0x7d, 0xcc, 0x99, 0xca, 0xd9, 0x39, 0xee, 0x9d, 0xb2, + 0x6d, 0x62, 0xef, 0xd2, 0x14, 0xf7, 0x6b, 0xf2, 0x10, 0x6c, 0x5b, 0xd3, + 0x2e, 0x7e, 0x79, 0x16, 0x03, 0xf8, 0x1d, 0x84, 0x3c, 0x70, 0x2c, 0x7e, + 0xe7, 0x16, 0xe5, 0xdd, 0xf3, 0xbe, 0x6d, 0x0f, 0xc8, 0x3b, 0x4e, 0xe5, + 0xd8, 0x71, 0x77, 0x0d, 0xcf, 0xc0, 0xcd, 0xb1, 0x66, 0xed, 0x38, 0x6e, + 0x5e, 0x2a, 0x95, 0x05, 0x77, 0x61, 0x8d, 0xa5, 0xb4, 0xa4, 0xfc, 0xff, + 0x03, 0x67, 0x78, 0xfd, 0x3e, 0x4b, 0x0c, 0xfd, 0x48, 0x9b, 0xcf, 0xd7, + 0xfe, 0x6a, 0x6d, 0x81, 0xaf, 0xff, 0xc8, 0x8f, 0xe4, 0xcb, 0x45, 0xd9, + 0xa9, 0xfa, 0x7f, 0xb9, 0xe7, 0x6a, 0x75, 0xbf, 0xef, 0xdf, 0x52, 0xbf, + 0x93, 0x17, 0x63, 0x1a, 0x1f, 0x6c, 0x9a, 0x6e, 0xd4, 0x09, 0x4f, 0x78, + 0x75, 0x85, 0xe5, 0x78, 0x6f, 0xbf, 0xa7, 0x17, 0x52, 0xea, 0x3b, 0xa7, + 0x6c, 0xea, 0x07, 0xee, 0xa7, 0x45, 0x26, 0x2e, 0xdc, 0x01, 0x4d, 0x7c, + 0x1d, 0xcc, 0xb8, 0xcf, 0xd7, 0x1d, 0x6d, 0x9e, 0x2f, 0x6c, 0x49, 0xcf, + 0x59, 0xfa, 0x4e, 0x0e, 0xf4, 0x68, 0xbb, 0x64, 0xc6, 0x83, 0x92, 0x3c, + 0x1b, 0x8b, 0x19, 0x5f, 0x97, 0xfc, 0x07, 0x79, 0xd3, 0x3e, 0xad, 0x45, + 0xa1, 0xff, 0x6e, 0xe1, 0xda, 0x86, 0x9f, 0x21, 0xcf, 0x7b, 0xfd, 0x7b, + 0x76, 0x03, 0x8f, 0xee, 0xf0, 0x78, 0x94, 0xf7, 0x2d, 0x53, 0xff, 0xc0, + 0xd8, 0x9e, 0xb3, 0xdc, 0xa3, 0x79, 0xae, 0xe7, 0xac, 0x89, 0xd7, 0xeb, + 0x9f, 0xeb, 0xab, 0x3e, 0x87, 0xfb, 0xf0, 0x7d, 0xcd, 0xdc, 0x3b, 0x07, + 0xe1, 0xd3, 0xf5, 0xd1, 0xe6, 0xd0, 0x7e, 0x6f, 0x74, 0x77, 0x0a, 0xf9, + 0x3d, 0xe1, 0xf1, 0x1c, 0xf5, 0x4d, 0xc4, 0xd3, 0x37, 0x4b, 0xf6, 0x65, + 0xc4, 0xe0, 0x4f, 0x98, 0x13, 0xa9, 0xb1, 0x2f, 0x4f, 0x98, 0x77, 0xab, + 0xb3, 0x2f, 0x77, 0x7b, 0xf3, 0xf8, 0xf7, 0x7c, 0xbd, 0xe2, 0xb7, 0x7d, + 0xbd, 0xd2, 0xe8, 0xd3, 0xfa, 0xb4, 0xaf, 0xed, 0xaf, 0x8f, 0xf9, 0xf2, + 0xcb, 0xe6, 0x5d, 0xb2, 0x88, 0xd9, 0xe8, 0x53, 0x26, 0x72, 0x06, 0x2f, + 0x6d, 0x9d, 0xb1, 0x88, 0xfb, 0x70, 0x7e, 0x22, 0xe9, 0xc8, 0x1d, 0x8d, + 0xad, 0x4f, 0x5e, 0x18, 0xd3, 0x3c, 0x4f, 0xc9, 0xf5, 0xf4, 0x4e, 0x74, + 0x17, 0xe4, 0xea, 0x4a, 0x64, 0x09, 0x53, 0x34, 0x73, 0x34, 0x0d, 0x3b, + 0x94, 0xd2, 0x7a, 0xd9, 0xf7, 0xb0, 0xdf, 0x41, 0xc5, 0x73, 0xad, 0x74, + 0x5e, 0x94, 0x47, 0xec, 0x8a, 0xd6, 0x6e, 0x9a, 0x87, 0x8a, 0x47, 0x9b, + 0x4f, 0xfb, 0x7c, 0x4f, 0x7e, 0x9a, 0x39, 0x3a, 0x31, 0x53, 0x19, 0x0e, + 0x6d, 0xeb, 0xb5, 0xf3, 0x42, 0xbc, 0xfe, 0xb0, 0x1c, 0x52, 0xdc, 0xf0, + 0xab, 0xb8, 0xbf, 0x97, 0xf1, 0x65, 0x22, 0xa4, 0x78, 0xe0, 0x44, 0x6c, + 0x12, 0xb2, 0x98, 0x75, 0x89, 0xef, 0x5f, 0xa5, 0x38, 0xff, 0x92, 0xd0, + 0xcf, 0x22, 0xa6, 0xe0, 0x05, 0x39, 0xe8, 0x6e, 0x74, 0x17, 0xc4, 0xf8, + 0xbf, 0x59, 0xad, 0x09, 0xad, 0x90, 0x49, 0x37, 0xd4, 0x9c, 0x2e, 0x1b, + 0x19, 0x18, 0x0d, 0xa6, 0x56, 0x9e, 0x70, 0xa2, 0xcd, 0x3b, 0xcb, 0x90, + 0xf1, 0x32, 0xf4, 0x7f, 0x39, 0x16, 0x18, 0x51, 0x6c, 0xda, 0x57, 0x24, + 0xdd, 0x41, 0x3f, 0x9f, 0xfa, 0xe4, 0x01, 0xb9, 0x69, 0x6f, 0x96, 0x9b, + 0x5b, 0x88, 0xc3, 0xec, 0x47, 0x9b, 0xba, 0x64, 0x10, 0x7d, 0x49, 0xf4, + 0x35, 0x2b, 0x3f, 0x6a, 0x7c, 0x06, 0x9d, 0x75, 0xd3, 0xa6, 0xae, 0x5a, + 0xcf, 0x5f, 0xbc, 0xeb, 0x22, 0x68, 0x42, 0x6c, 0xc7, 0x56, 0xb4, 0xa9, + 0xe3, 0xec, 0x86, 0xfe, 0x2e, 0xb4, 0xef, 0xc3, 0x1c, 0x4d, 0xfa, 0x7e, + 0x96, 0xb3, 0xcd, 0xd4, 0x39, 0xeb, 0xc6, 0xac, 0x6e, 0x68, 0xff, 0xb1, + 0xdd, 0xe0, 0x13, 0x3e, 0x25, 0xbd, 0x73, 0x29, 0xd9, 0xd5, 0x59, 0xdf, + 0xfe, 0x77, 0x43, 0xbb, 0x4d, 0x56, 0xb6, 0x93, 0x0c, 0x4f, 0x75, 0xd4, + 0xf7, 0xfb, 0xfc, 0xe4, 0xb7, 0x3b, 0xf1, 0xbe, 0x09, 0x18, 0xbc, 0xa4, + 0xc6, 0x52, 0x37, 0xa3, 0x5c, 0xeb, 0x83, 0x86, 0x67, 0x78, 0xcd, 0x67, + 0xf8, 0x2c, 0xf3, 0x7a, 0x9f, 0xb1, 0x1f, 0xcf, 0x30, 0x27, 0xc0, 0xbc, + 0x06, 0x79, 0x76, 0xb9, 0x38, 0x8b, 0x63, 0x3e, 0x9f, 0x6f, 0xc8, 0x54, + 0x79, 0xcf, 0xd7, 0x2b, 0xb1, 0x2a, 0x56, 0x6d, 0x67, 0xc1, 0xcf, 0x09, + 0x93, 0x76, 0x5a, 0x93, 0x8a, 0xdd, 0x00, 0x9d, 0x0f, 0x80, 0xce, 0x0f, + 0x05, 0x19, 0x17, 0xb6, 0x78, 0xb4, 0x76, 0x64, 0xa4, 0xfc, 0x5b, 0xc8, + 0x38, 0x79, 0x14, 0x3e, 0x45, 0xd9, 0xf2, 0xf0, 0x19, 0x03, 0xb0, 0x69, + 0xae, 0x04, 0x35, 0xef, 0x80, 0xf8, 0x7e, 0xf6, 0xba, 0x8c, 0x4c, 0x31, + 0x27, 0x40, 0x7e, 0x66, 0x5c, 0x9f, 0xc2, 0xbd, 0x5b, 0x18, 0xeb, 0x42, + 0x86, 0xc7, 0xc0, 0xaf, 0x21, 0x71, 0xa6, 0xb7, 0x4a, 0x6e, 0x7c, 0x4c, + 0x7d, 0x80, 0x1e, 0xd8, 0xa8, 0xe3, 0xee, 0xa8, 0x9c, 0xb8, 0xb2, 0x01, + 0xb2, 0xca, 0xb8, 0x5f, 0x73, 0x1a, 0x95, 0xb0, 0xfa, 0xe6, 0xf4, 0x39, + 0x98, 0x87, 0x33, 0x35, 0x66, 0x23, 0xb7, 0x93, 0x31, 0x69, 0x1b, 0x95, + 0x99, 0x0b, 0xb6, 0xe2, 0x5d, 0x52, 0x72, 0xa7, 0x42, 0xda, 0x65, 0xf7, + 0xc6, 0xa1, 0xab, 0xe8, 0xcb, 0x9f, 0x8c, 0x98, 0xb3, 0x7c, 0x74, 0x2d, + 0x63, 0xe2, 0xe4, 0x74, 0xed, 0x1c, 0x8a, 0x91, 0xc1, 0xbd, 0xd7, 0xda, + 0x8d, 0xcc, 0x30, 0x3e, 0xfe, 0xa0, 0x92, 0x8a, 0x72, 0x4d, 0x8e, 0x65, + 0xed, 0x96, 0x3c, 0xc2, 0xbd, 0x7d, 0xea, 0xf1, 0xf2, 0xcf, 0x30, 0x5f, + 0x5c, 0x7a, 0x5e, 0x1f, 0xd3, 0xb8, 0xfe, 0x78, 0x5d, 0x0c, 0x6b, 0xf2, + 0x05, 0x26, 0x8e, 0xbd, 0x2e, 0x93, 0xf3, 0xa4, 0x0f, 0x6d, 0x7c, 0x40, + 0x5e, 0x73, 0x7a, 0xed, 0x27, 0xb5, 0xd6, 0x98, 0x48, 0xb1, 0x3e, 0xd3, + 0xe2, 0x24, 0xed, 0x59, 0x09, 0x0d, 0x7e, 0x15, 0xd7, 0x8c, 0x6b, 0xf3, + 0x6e, 0xaf, 0xfb, 0xa4, 0xf8, 0x38, 0x90, 0x8d, 0xa9, 0x15, 0x81, 0xdb, + 0x95, 0xeb, 0x7b, 0x39, 0xc6, 0xe0, 0x40, 0x24, 0x40, 0x5a, 0xbd, 0xb7, + 0x9e, 0xf8, 0x99, 0xfa, 0xfc, 0xdf, 0x83, 0x4f, 0xef, 0x19, 0x48, 0x9c, + 0x62, 0x0c, 0x1b, 0x76, 0xbe, 0xb5, 0xd6, 0xbc, 0x6b, 0x2e, 0xb7, 0x5a, + 0xb4, 0x7e, 0x76, 0xe4, 0x23, 0x87, 0x78, 0x88, 0x44, 0x6c, 0x85, 0xc5, + 0x3c, 0x38, 0x75, 0x1c, 0x6b, 0x2a, 0xcc, 0xb9, 0x11, 0xc7, 0xdf, 0x2c, + 0x97, 0xfb, 0x2c, 0x79, 0x30, 0x94, 0x8a, 0x5b, 0xb2, 0x29, 0x7e, 0x56, + 0xb0, 0x26, 0xeb, 0x2b, 0xf3, 0x89, 0x1c, 0xc7, 0x87, 0xa6, 0x39, 0x5f, + 0x5c, 0xe3, 0x95, 0xe4, 0xa6, 0x4a, 0xe5, 0x19, 0x57, 0x02, 0xc9, 0x7b, + 0x3f, 0xac, 0xb0, 0x16, 0x6e, 0xbd, 0xfe, 0x45, 0x38, 0x05, 0xea, 0x8a, + 0x55, 0x93, 0x06, 0x73, 0x78, 0xe2, 0x48, 0xcf, 0x3c, 0xdb, 0xdf, 0x7d, + 0xc4, 0xb4, 0x4f, 0xa1, 0xdd, 0xe4, 0x61, 0x9d, 0xa6, 0x8e, 0xf4, 0x14, + 0x9f, 0x5a, 0x6b, 0xe2, 0xef, 0x45, 0xc5, 0x7f, 0xbd, 0x5d, 0x17, 0xd3, + 0xa4, 0x02, 0xe3, 0x85, 0xb1, 0xc0, 0x58, 0xc1, 0xea, 0x6b, 0x06, 0xad, + 0xe6, 0x5c, 0xe6, 0x6a, 0xfc, 0x9c, 0x15, 0xf3, 0xfd, 0x22, 0xdf, 0x57, + 0x8c, 0x14, 0x6b, 0x8a, 0x96, 0xfa, 0x42, 0x07, 0xe6, 0x98, 0xe3, 0x8f, + 0xa8, 0x3e, 0x38, 0x38, 0xdf, 0x26, 0x79, 0x7b, 0x8d, 0xe4, 0x55, 0xc6, + 0xa3, 0xaa, 0x03, 0x2c, 0xe7, 0x5e, 0xf4, 0x71, 0xdf, 0x4f, 0x28, 0x2e, + 0xe2, 0xcd, 0x42, 0x17, 0xda, 0xcc, 0x35, 0x6f, 0x6f, 0xe8, 0xaf, 0xad, + 0xcb, 0x26, 0x6c, 0xcb, 0x6a, 0xac, 0xc9, 0xb2, 0xaf, 0xb1, 0x16, 0x7b, + 0x52, 0xae, 0x93, 0x6f, 0xca, 0x7e, 0xce, 0xdd, 0xf5, 0x72, 0xee, 0xdf, + 0xee, 0x32, 0x18, 0x61, 0xc9, 0x84, 0x86, 0x9a, 0xfb, 0x8e, 0x4f, 0x05, + 0x6f, 0x2d, 0xe5, 0x4f, 0xd1, 0x9e, 0xaf, 0xd6, 0xca, 0x71, 0xef, 0x39, + 0x62, 0xc5, 0xe1, 0x57, 0xe4, 0xbc, 0xef, 0x0e, 0x78, 0xbf, 0xfa, 0xfc, + 0xff, 0xd8, 0x53, 0x8b, 0xd6, 0xd9, 0xad, 0xba, 0x3a, 0xfb, 0xe3, 0x78, + 0x96, 0x35, 0xf6, 0x5c, 0xa5, 0x09, 0xbc, 0xdb, 0x44, 0x9c, 0x48, 0x75, + 0x3c, 0x75, 0xbc, 0xea, 0x72, 0x9d, 0x6b, 0xa7, 0x37, 0x57, 0x10, 0x7a, + 0x7e, 0x62, 0xca, 0x1f, 0x73, 0x4c, 0x56, 0xf4, 0x27, 0x62, 0x41, 0x8b, + 0x63, 0x8c, 0xbe, 0x4f, 0xbb, 0xc7, 0xa0, 0xc7, 0xa9, 0xf3, 0xf9, 0xde, + 0x0e, 0x7c, 0x3d, 0xea, 0x02, 0xea, 0x73, 0xb5, 0x01, 0xf1, 0x3c, 0x74, + 0xfd, 0x48, 0x59, 0x73, 0xf9, 0xb1, 0x87, 0x83, 0x89, 0x99, 0xac, 0xea, + 0x06, 0xf8, 0x7b, 0xe5, 0x6b, 0xcc, 0x07, 0x9d, 0x92, 0x40, 0x6d, 0x9d, + 0x86, 0xb1, 0x19, 0x6b, 0x1a, 0xad, 0xd0, 0x0d, 0x22, 0x57, 0xc1, 0x1b, + 0x6f, 0xcc, 0x91, 0x5f, 0x83, 0x1d, 0x26, 0xbe, 0x5a, 0xd8, 0x6e, 0x49, + 0x87, 0xd6, 0x3e, 0xf3, 0x4e, 0x84, 0xfe, 0xc9, 0x70, 0xb2, 0x1f, 0x7e, + 0xb6, 0x62, 0x0f, 0x98, 0xaf, 0x9c, 0x40, 0x3c, 0x56, 0x9b, 0x63, 0x81, + 0x7c, 0x8d, 0xb3, 0x3f, 0x0b, 0xbf, 0x72, 0xa9, 0xee, 0x91, 0x2f, 0x9e, + 0xd0, 0xdc, 0x66, 0x69, 0xae, 0x55, 0x75, 0x6c, 0xa9, 0xf8, 0x30, 0xce, + 0x45, 0x36, 0x5b, 0x43, 0x79, 0xaf, 0x3f, 0x2c, 0xc5, 0x22, 0xdb, 0xd2, + 0xdd, 0xa4, 0xe7, 0xee, 0xd7, 0x76, 0x6c, 0x99, 0x85, 0xaf, 0x58, 0x9c, + 0x77, 0xf0, 0xbf, 0x05, 0xff, 0x7d, 0xf8, 0xdf, 0x25, 0xe9, 0x69, 0xfa, + 0xaf, 0xac, 0xe5, 0xb4, 0x36, 0xac, 0x1f, 0xf6, 0x70, 0xe0, 0xf4, 0x6b, + 0x4d, 0x9c, 0x93, 0x2f, 0x36, 0xca, 0x09, 0xf3, 0xa4, 0xbe, 0x8e, 0x60, + 0xbe, 0xd4, 0xaf, 0xf5, 0xd5, 0xd6, 0xb0, 0x2c, 0xaf, 0xee, 0x45, 0x9e, + 0x6e, 0x91, 0x83, 0x45, 0xbf, 0x76, 0x15, 0x93, 0x43, 0xd5, 0xda, 0x95, + 0x64, 0x82, 0x43, 0xb7, 0x1f, 0xcb, 0x4e, 0x29, 0x9e, 0xc0, 0xb2, 0x86, + 0xae, 0x3f, 0x36, 0x39, 0xff, 0xce, 0x63, 0x4b, 0x98, 0x70, 0xdc, 0x9b, + 0x5f, 0x0e, 0x33, 0x44, 0x2c, 0x1d, 0xbf, 0x93, 0x53, 0xdf, 0x0d, 0xfb, + 0xf6, 0x63, 0x1e, 0xe2, 0xec, 0xe2, 0xf6, 0x12, 0x7e, 0xd9, 0x8f, 0x47, + 0x89, 0x23, 0xe5, 0x73, 0xb5, 0xd8, 0x8f, 0x10, 0xce, 0x5f, 0x02, 0x96, + 0x93, 0xc3, 0x3e, 0x2e, 0x76, 0x19, 0x3f, 0x90, 0x38, 0xd3, 0x44, 0x0d, + 0xf6, 0xc8, 0xc7, 0x9a, 0x5e, 0xc4, 0x5c, 0x19, 0xf9, 0x7d, 0xf9, 0x71, + 0xf9, 0x75, 0x79, 0x0c, 0xf2, 0x3d, 0x89, 0x39, 0xf7, 0xcb, 0xaf, 0xca, + 0x7b, 0xe5, 0x5a, 0x79, 0x5c, 0xde, 0x2a, 0xef, 0x42, 0x4c, 0x35, 0x4a, + 0xac, 0xa7, 0x87, 0x95, 0x1e, 0x96, 0x89, 0x73, 0x8a, 0x01, 0xbc, 0x45, + 0xbf, 0xe7, 0x88, 0xfa, 0xd9, 0x01, 0xf2, 0xf4, 0x6f, 0x18, 0xcf, 0x13, + 0x9b, 0x59, 0x2c, 0xfb, 0x18, 0x8e, 0x43, 0xdd, 0x58, 0xdb, 0xe6, 0x37, + 0x29, 0x23, 0xe7, 0x22, 0x81, 0xd1, 0x73, 0xa1, 0xc0, 0x43, 0xfa, 0x7d, + 0x0b, 0xeb, 0x9d, 0x15, 0x39, 0xe1, 0x3a, 0xe4, 0xcd, 0xc1, 0x11, 0xc8, + 0xc2, 0x28, 0x54, 0xfd, 0x23, 0xce, 0x1a, 0x01, 0x49, 0x53, 0x1f, 0xc3, + 0xcf, 0x4c, 0x9e, 0x76, 0x25, 0x5b, 0x98, 0x0d, 0x18, 0x3c, 0x9a, 0x8d, + 0x76, 0x1f, 0xda, 0xbf, 0xf4, 0xda, 0x3b, 0x24, 0x7b, 0x41, 0x52, 0xef, + 0xab, 0x3f, 0xfc, 0x73, 0xaf, 0x6f, 0x10, 0x7d, 0xe0, 0xcc, 0x57, 0xd8, + 0xf7, 0x8a, 0xd7, 0xc7, 0x33, 0x61, 0xad, 0x3e, 0xae, 0x7c, 0x95, 0xb5, + 0xc7, 0x85, 0xdf, 0x2f, 0x18, 0x4c, 0xe8, 0xfb, 0x5d, 0x46, 0xb7, 0x11, + 0x13, 0xf8, 0xaf, 0x2e, 0xc6, 0x60, 0x45, 0xc8, 0xd7, 0x7a, 0xe8, 0xc4, + 0xbf, 0x6f, 0x5e, 0x6a, 0x5b, 0x43, 0x9f, 0xd4, 0x60, 0xb4, 0x3f, 0x91, + 0x9e, 0xf9, 0xdb, 0x1e, 0x9e, 0xf7, 0x30, 0xde, 0x0d, 0x67, 0x55, 0x20, + 0x6e, 0x3c, 0x0e, 0xd9, 0x6e, 0x95, 0x35, 0x67, 0x48, 0xaf, 0x5e, 0xe8, + 0xea, 0x14, 0xe4, 0xd6, 0x95, 0xb9, 0x72, 0x28, 0x30, 0x52, 0x48, 0x89, + 0xc1, 0x53, 0x5b, 0x92, 0x89, 0xa6, 0xe4, 0xe4, 0x40, 0x62, 0x0b, 0xf3, + 0x90, 0xd9, 0x7e, 0x57, 0x2e, 0x95, 0x69, 0x8f, 0x73, 0x72, 0x79, 0x20, + 0xe1, 0x16, 0x85, 0xb8, 0x18, 0x57, 0x2e, 0x43, 0x36, 0xff, 0x70, 0x6e, + 0x97, 0x1c, 0x2a, 0xa8, 0x1f, 0xdc, 0x1b, 0x96, 0x97, 0xe5, 0xd2, 0xc0, + 0xcb, 0xb7, 0x2e, 0xb9, 0x93, 0x38, 0x53, 0xf2, 0xe1, 0x81, 0x6e, 0xb3, + 0x6f, 0xc5, 0x21, 0x09, 0xf3, 0x21, 0x5a, 0x53, 0x73, 0x56, 0x48, 0x7a, + 0x5f, 0xc4, 0x8b, 0xcb, 0xe1, 0x73, 0x07, 0xee, 0x33, 0xf5, 0x94, 0x80, + 0xbf, 0xcf, 0x30, 0xfc, 0x18, 0x3e, 0xe7, 0xd3, 0xc6, 0x9f, 0xa7, 0x2b, + 0x90, 0xbe, 0xd0, 0x26, 0xa1, 0x57, 0xbe, 0x0c, 0xba, 0x86, 0xe4, 0x40, + 0x7f, 0xa5, 0xf2, 0x0d, 0x37, 0x14, 0x9f, 0x44, 0x8c, 0x82, 0xfd, 0xcb, + 0xea, 0xd3, 0xed, 0xa0, 0x49, 0xb3, 0x44, 0x4f, 0xfb, 0xeb, 0xad, 0xf0, + 0xb0, 0x0c, 0xe7, 0x57, 0x1b, 0x5b, 0xe6, 0x63, 0x1b, 0xfc, 0xf9, 0x0c, + 0xa6, 0xac, 0xc7, 0xea, 0x0f, 0x78, 0xdf, 0x49, 0x78, 0xed, 0x7b, 0x03, + 0x0f, 0x86, 0x3a, 0x24, 0xe4, 0xfc, 0x70, 0x1d, 0xb1, 0x91, 0x0b, 0x05, + 0xbf, 0x1f, 0x7e, 0x62, 0xc8, 0xf7, 0x87, 0x65, 0xdb, 0xd2, 0x59, 0xcb, + 0xb6, 0x9e, 0xf9, 0x6f, 0x7a, 0x73, 0xa6, 0xbc, 0xb1, 0x88, 0x39, 0x62, + 0xab, 0xd4, 0x3e, 0x99, 0xb1, 0x9f, 0xc9, 0xb3, 0xfd, 0x89, 0x57, 0x15, + 0x27, 0x5b, 0x7d, 0x86, 0xf7, 0x11, 0x43, 0x96, 0xf5, 0x99, 0xd8, 0x6e, + 0xd0, 0x37, 0x13, 0xbb, 0xc7, 0x9e, 0xb5, 0x82, 0x01, 0xe3, 0x8f, 0x34, + 0xc9, 0x0f, 0xa2, 0xb0, 0xdb, 0x88, 0xf1, 0xb2, 0xcc, 0x7f, 0xb9, 0x77, + 0x3c, 0x3f, 0x85, 0x7d, 0x89, 0x53, 0x49, 0x6b, 0x02, 0xfb, 0xe3, 0x19, + 0x10, 0x03, 0x6a, 0x81, 0x4e, 0x5d, 0x78, 0x3f, 0xc4, 0x4f, 0xfd, 0xfe, + 0xfb, 0xaf, 0x86, 0x0e, 0xe3, 0xfe, 0x0d, 0x2e, 0x4c, 0x2c, 0xe6, 0x42, + 0x86, 0x3d, 0x0c, 0x6c, 0xad, 0xdc, 0xfa, 0xd8, 0x58, 0x1f, 0x4f, 0x47, + 0x8c, 0x52, 0x0c, 0x7e, 0x20, 0x65, 0x82, 0xbc, 0xd9, 0x89, 0xfe, 0x95, + 0xb7, 0x53, 0xfa, 0xea, 0x7e, 0xdf, 0x87, 0x55, 0x6c, 0xf7, 0x64, 0x61, + 0xaf, 0xc1, 0xe6, 0x59, 0x8b, 0x92, 0xea, 0x4e, 0xda, 0x27, 0xb0, 0xdf, + 0x74, 0x28, 0x51, 0xcc, 0x49, 0x4c, 0x66, 0xa1, 0x2f, 0xde, 0x80, 0xec, + 0x5f, 0x2b, 0xc7, 0x03, 0x69, 0xec, 0xe9, 0x60, 0x61, 0x48, 0x26, 0x2f, + 0xe8, 0x37, 0x5f, 0xd0, 0xfb, 0x43, 0x52, 0x2a, 0x24, 0xb6, 0xcc, 0x82, + 0xff, 0x66, 0x0b, 0xc4, 0x17, 0xf5, 0xc6, 0x47, 0x31, 0xe3, 0x42, 0x61, + 0x23, 0xec, 0x83, 0xa4, 0x2e, 0xc1, 0xff, 0xb9, 0x54, 0xde, 0x02, 0x3e, + 0xc3, 0xfd, 0xb2, 0x83, 0x5f, 0xe8, 0xcc, 0xf2, 0x00, 0xe4, 0x9c, 0x7b, + 0xb1, 0x65, 0x6e, 0x33, 0xce, 0x8e, 0x38, 0x22, 0xc5, 0x8f, 0xff, 0x07, + 0xe7, 0xeb, 0xbf, 0xf7, 0x76, 0xb5, 0xd3, 0xb3, 0xba, 0x2f, 0xd8, 0x65, + 0xc4, 0x00, 0xd9, 0x7e, 0x63, 0xb7, 0xd3, 0x91, 0x76, 0x49, 0xdf, 0x43, + 0x3b, 0xde, 0xa1, 0x31, 0xa2, 0xf2, 0x62, 0x84, 0xf7, 0xdf, 0x59, 0x67, + 0xe8, 0x17, 0x6e, 0x68, 0xbf, 0x8d, 0xdf, 0x36, 0xe9, 0x74, 0xf8, 0x6b, + 0xe3, 0xf7, 0xc6, 0x3a, 0xd6, 0x77, 0x3b, 0x9d, 0x24, 0xd6, 0xfa, 0x9d, + 0x97, 0x2f, 0xc0, 0xf5, 0x2c, 0x9f, 0x59, 0xeb, 0xad, 0xcb, 0x79, 0xdb, + 0x30, 0x4f, 0xab, 0xb7, 0x56, 0x9b, 0xe6, 0x27, 0xcd, 0x5a, 0x88, 0x71, + 0x0b, 0xef, 0xad, 0xd3, 0xef, 0x8c, 0x61, 0x2f, 0xea, 0xdb, 0x7f, 0x5d, + 0x47, 0xdc, 0x5c, 0xa7, 0xd3, 0xa6, 0x18, 0xcf, 0x9b, 0x1d, 0x1d, 0xb8, + 0xe6, 0x9a, 0x1c, 0x63, 0xf2, 0xe1, 0xa5, 0x32, 0xe7, 0x67, 0x3b, 0x25, + 0x47, 0x35, 0x9f, 0x61, 0xb0, 0x7c, 0xa5, 0xc2, 0xfd, 0x32, 0x79, 0x4e, + 0xf1, 0x75, 0x33, 0x79, 0x8b, 0xdf, 0xbd, 0xf0, 0x3b, 0x39, 0xfa, 0x12, + 0x63, 0x32, 0x81, 0xf3, 0xbb, 0x0c, 0x9f, 0x6a, 0xc1, 0x7c, 0x13, 0x8b, + 0xbf, 0xfd, 0x38, 0x97, 0x10, 0x64, 0x8c, 0x32, 0x4a, 0x99, 0xc2, 0xf9, + 0x8d, 0xdb, 0xf2, 0xee, 0x00, 0xe5, 0x79, 0x40, 0xae, 0x54, 0xe5, 0x39, + 0x07, 0x79, 0xa6, 0x2c, 0xe7, 0x20, 0xd3, 0x86, 0xaf, 0xf7, 0xf1, 0x1b, + 0x6b, 0x84, 0xeb, 0x25, 0xf5, 0x21, 0x2e, 0x82, 0xaf, 0x6d, 0x13, 0x97, + 0x2b, 0x2e, 0xfe, 0x30, 0xf4, 0x5a, 0x93, 0xf7, 0x1d, 0x00, 0xae, 0xaf, + 0xbc, 0x28, 0xe9, 0x0b, 0x2d, 0xd8, 0x77, 0xbc, 0x9b, 0x67, 0x96, 0xbd, + 0xc2, 0x7f, 0x9f, 0x17, 0x89, 0x37, 0xa5, 0x3f, 0xcb, 0x6b, 0xc6, 0x79, + 0xeb, 0x31, 0x66, 0x10, 0x74, 0x6e, 0xc1, 0xfc, 0xdc, 0xe3, 0x72, 0xe3, + 0x78, 0x3f, 0x54, 0x83, 0x4f, 0xf5, 0xe9, 0xbd, 0x4a, 0xd7, 0xcc, 0xea, + 0x37, 0x5a, 0x46, 0x06, 0x27, 0x0a, 0xe4, 0xfb, 0x18, 0xf8, 0x96, 0x3e, + 0x31, 0xf9, 0x25, 0xa5, 0xe7, 0x50, 0x2a, 0x90, 0x7f, 0x43, 0x9a, 0xc3, + 0xc8, 0xc2, 0xb6, 0xec, 0xd1, 0xf1, 0xb1, 0x25, 0xf9, 0xee, 0x0e, 0x68, + 0xdc, 0x9d, 0x2d, 0xac, 0x94, 0x1e, 0xd5, 0x41, 0xdd, 0x1e, 0x6f, 0xc3, + 0x5e, 0x28, 0x96, 0x7b, 0xbf, 0x1c, 0x29, 0x0f, 0x82, 0x0e, 0x31, 0x79, + 0x06, 0x7e, 0xf3, 0x73, 0xe5, 0xbb, 0x64, 0x31, 0x82, 0x7d, 0x55, 0x65, + 0x6c, 0x58, 0x9e, 0x9f, 0x8d, 0x7b, 0xd7, 0x09, 0x77, 0xd1, 0xda, 0x8e, + 0x3d, 0x50, 0x9e, 0x28, 0x57, 0x1c, 0x17, 0x44, 0x2c, 0xc2, 0x79, 0x8f, + 0x18, 0xdd, 0x86, 0x79, 0x8b, 0x11, 0xca, 0x2f, 0xf7, 0x16, 0xf2, 0x64, + 0x96, 0x71, 0x15, 0xdf, 0xd9, 0xd8, 0xa4, 0x4c, 0xdd, 0x59, 0x24, 0x14, + 0x07, 0xba, 0x74, 0x06, 0xfe, 0x3c, 0xbe, 0x5c, 0xfa, 0xdf, 0x51, 0x50, + 0x8f, 0xc2, 0x56, 0x16, 0x60, 0x2b, 0x0b, 0xb0, 0x91, 0x90, 0x85, 0x6b, + 0x05, 0xd8, 0xc8, 0x02, 0x6c, 0x24, 0xf4, 0xd9, 0x9b, 0x88, 0xed, 0xde, + 0x00, 0x0f, 0x19, 0x5f, 0xfb, 0x30, 0x7d, 0x6d, 0xfc, 0xfd, 0x17, 0xea, + 0x52, 0x61, 0x78, 0xd0, 0x71, 0x00, 0x00, 0x00 }; static const u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static const u32 bnx2_RXP_b06FwRodata[(0x24/4) + 1] = { - 0x08004590, 0x08004590, 0x08004508, 0x08004540, 0x08004574, 0x08004598, - 0x08004598, 0x08004598, 0x08004478, 0x00000000 }; + 0x0800458c, 0x0800458c, 0x08004504, 0x0800453c, 0x08004570, 0x08004594, + 0x08004594, 0x08004594, 0x08004474, 0x00000000 }; static struct fw_info bnx2_rxp_fw_06 = { - /* Firmware version: 4.1.1 */ + /* Firmware version: 4.4.2 */ .ver_major = 0x4, - .ver_minor = 0x1, - .ver_fix = 0x1, + .ver_minor = 0x4, + .ver_fix = 0x2, .start_addr = 0x080031d0, .text_addr = 0x08000000, - .text_len = 0x71d0, + .text_len = 0x71cc, .text_index = 0x0, .gz_text = bnx2_RXP_b06FwText, .gz_text_len = sizeof(bnx2_RXP_b06FwText), @@ -2973,7 +2974,7 @@ static struct fw_info bnx2_rxp_fw_06 = { .bss_len = 0x44c, .bss_index = 0x0, - .rodata_addr = 0x080071d0, + .rodata_addr = 0x080071cc, .rodata_len = 0x24, .rodata_index = 0x0, .rodata = bnx2_RXP_b06FwRodata, @@ -2996,687 +2997,639 @@ static const struct cpu_reg cpu_reg_rxp = { }; static u8 bnx2_rv2p_proc1[] = { - /* Date: 12/07/2007 15:02 */ - 0xd5, 0x56, 0x41, 0x6b, 0x13, 0x51, 0x10, 0x9e, 0xdd, 0x6c, 0xbb, 0xdb, - 0x64, 0xb3, 0x59, 0xaa, 0xd6, 0x50, 0x53, 0x93, 0x06, 0x2f, 0xad, 0x29, - 0x6d, 0xaa, 0x82, 0x42, 0xa1, 0x92, 0x4b, 0xc1, 0xf6, 0x20, 0xf5, 0x22, - 0x22, 0xd8, 0x46, 0xd1, 0x5f, 0x21, 0x06, 0xdb, 0xd4, 0x73, 0x05, 0x0b, - 0xf5, 0xa0, 0x3d, 0x59, 0x11, 0xc1, 0x04, 0x14, 0x44, 0x04, 0x41, 0x45, - 0x04, 0x3d, 0x78, 0xa8, 0x60, 0x2f, 0xad, 0x22, 0x56, 0x3c, 0x78, 0xd4, - 0x93, 0x26, 0xbe, 0x37, 0x33, 0xaf, 0xdd, 0xdd, 0x66, 0x9b, 0x2a, 0x82, - 0x18, 0x68, 0x3f, 0xde, 0xec, 0xbc, 0x37, 0x33, 0xdf, 0xcc, 0x9b, 0x79, - 0x2e, 0x00, 0xe8, 0x50, 0xaa, 0xa6, 0x05, 0x82, 0xa5, 0x69, 0x96, 0x00, - 0x0d, 0xe0, 0xae, 0x8d, 0x58, 0xea, 0x77, 0x05, 0xda, 0xda, 0x70, 0x46, - 0x62, 0x04, 0x86, 0xbb, 0x25, 0xee, 0x87, 0x27, 0x99, 0xa4, 0xc0, 0x9f, - 0x75, 0x28, 0xc9, 0xf5, 0xee, 0xca, 0xc3, 0x6a, 0x0c, 0xcf, 0x59, 0xed, - 0x07, 0xfc, 0xbd, 0x8b, 0x10, 0x1e, 0xce, 0x59, 0x88, 0x25, 0x46, 0xe8, - 0x73, 0x11, 0x96, 0x66, 0x2d, 0x34, 0x57, 0xea, 0xb3, 0x70, 0x1f, 0xe8, - 0x24, 0x5f, 0x99, 0x4d, 0x88, 0xff, 0x29, 0x78, 0x5f, 0x90, 0x6b, 0x2b, - 0x3a, 0x8d, 0x7a, 0x15, 0xde, 0x2f, 0xfe, 0x50, 0xff, 0xb8, 0xd8, 0x07, - 0xfc, 0x53, 0xfb, 0x5c, 0x3c, 0xa7, 0x98, 0x93, 0x7e, 0xb5, 0x0b, 0x83, - 0xca, 0x1f, 0x9b, 0xe2, 0x4b, 0x93, 0xb6, 0x89, 0xdf, 0xd7, 0x84, 0xdf, - 0xca, 0x6e, 0x33, 0x7b, 0x41, 0x7f, 0x83, 0x76, 0xe5, 0x79, 0x86, 0xb0, - 0xe7, 0xb7, 0x03, 0x20, 0xe5, 0xcb, 0xf5, 0x75, 0x79, 0x8f, 0xff, 0xfb, - 0x6a, 0xaf, 0x3c, 0xaf, 0x05, 0xa0, 0x57, 0xea, 0x2d, 0xb1, 0x3f, 0x83, - 0xb0, 0x4f, 0x4f, 0xe2, 0x77, 0x03, 0xf7, 0xef, 0x11, 0xe7, 0x4a, 0xec, - 0x62, 0xec, 0x66, 0x1c, 0x67, 0xbc, 0xca, 0xb8, 0x8b, 0x71, 0x27, 0xe3, - 0x0e, 0xc6, 0x76, 0xc6, 0x97, 0x8c, 0x2e, 0x63, 0x82, 0xd1, 0x61, 0x7c, - 0xce, 0x68, 0x33, 0xc6, 0x18, 0x5f, 0x30, 0xbe, 0x62, 0xb4, 0x18, 0x6f, - 0x30, 0x7e, 0x61, 0xfc, 0xaa, 0xfc, 0xd0, 0x08, 0x1f, 0xf1, 0xfa, 0x10, - 0xaf, 0x8f, 0x30, 0x02, 0xf3, 0xa4, 0x05, 0x78, 0xba, 0xcf, 0x75, 0x24, - 0x79, 0xe6, 0xef, 0x3d, 0x4a, 0x8f, 0xf3, 0x84, 0x3c, 0xdd, 0x63, 0xbd, - 0xf6, 0xca, 0x42, 0xa0, 0xde, 0x32, 0x5b, 0xd6, 0x59, 0xaa, 0x41, 0xde, - 0x12, 0x18, 0xcf, 0xc4, 0x48, 0x02, 0xed, 0x38, 0xad, 0x24, 0x57, 0x6e, - 0x9d, 0x4c, 0x10, 0x9e, 0x8b, 0x12, 0x7e, 0x62, 0x3c, 0x1f, 0x23, 0x9c, - 0x8c, 0x2b, 0x9e, 0xd5, 0x39, 0xca, 0x9f, 0x66, 0x7e, 0x84, 0xd9, 0x53, - 0x7e, 0x35, 0xb3, 0x4b, 0x58, 0xd4, 0xfd, 0xf1, 0x5f, 0x1f, 0x20, 0x34, - 0xf2, 0x44, 0xea, 0x9c, 0xdd, 0x26, 0xa0, 0x5e, 0x9f, 0xb7, 0x0d, 0xb9, - 0x3e, 0x38, 0xff, 0x1a, 0xef, 0xc7, 0xe0, 0x5c, 0x95, 0xfd, 0x4b, 0x28, - 0x9e, 0xe9, 0xde, 0x64, 0x81, 0xd6, 0xe3, 0xc8, 0xbb, 0xa8, 0xb0, 0x1e, - 0xee, 0x03, 0x59, 0x7f, 0xbe, 0xa8, 0x6e, 0x23, 0x9c, 0x8f, 0x8b, 0x9c, - 0x8f, 0xae, 0x90, 0x7c, 0x84, 0xdd, 0xa3, 0xcd, 0xf7, 0xf7, 0x4c, 0x26, - 0xc8, 0x5b, 0xd8, 0x7d, 0x53, 0x7c, 0x93, 0xf4, 0x77, 0x79, 0xbc, 0xc0, - 0x3c, 0x16, 0x89, 0xc7, 0xe4, 0xe7, 0x86, 0x3c, 0x65, 0x3c, 0x3c, 0xc9, - 0x38, 0xf7, 0x86, 0xe4, 0x39, 0x2c, 0xbe, 0xdc, 0x1f, 0xe7, 0x39, 0xe0, - 0x1f, 0x9c, 0xc5, 0xfe, 0xe4, 0x42, 0x71, 0x44, 0xf9, 0xeb, 0xe7, 0xb9, - 0x93, 0xf2, 0x0d, 0xd3, 0x79, 0x29, 0xaf, 0x03, 0x3c, 0xd5, 0x71, 0x6d, - 0x14, 0x34, 0x09, 0x56, 0x31, 0x4f, 0xfb, 0x1d, 0x5d, 0xe7, 0xf5, 0x76, - 0xeb, 0x42, 0xe5, 0x5d, 0x62, 0x2b, 0x14, 0x26, 0x39, 0xce, 0x2c, 0xd9, - 0xa3, 0x3a, 0x30, 0xb8, 0x0e, 0x86, 0xb8, 0x7f, 0x05, 0xf9, 0xb0, 0x2a, - 0x0b, 0xb3, 0xde, 0x7b, 0x9d, 0x84, 0x62, 0x9e, 0xea, 0x6a, 0x73, 0x5e, - 0xd5, 0xdc, 0x51, 0x7d, 0x09, 0xc5, 0x95, 0x52, 0xc4, 0x17, 0xef, 0x51, - 0xc8, 0x79, 0x79, 0xd6, 0x1a, 0xd4, 0x47, 0x33, 0x3b, 0xbe, 0xf3, 0x1c, - 0xc8, 0x35, 0xea, 0x37, 0x26, 0xc7, 0xd5, 0xcd, 0xf5, 0xdd, 0xb1, 0xa9, - 0xbe, 0xd5, 0x7c, 0xfb, 0x7b, 0x75, 0xce, 0xf1, 0x9b, 0xa8, 0x97, 0x5a, - 0x79, 0xe0, 0x9d, 0x67, 0x51, 0xcf, 0x3c, 0xa3, 0x6d, 0xa6, 0xf2, 0x3b, - 0xed, 0x9d, 0x43, 0xb1, 0x90, 0x3c, 0x78, 0xe7, 0x57, 0x30, 0x5e, 0x7f, - 0x3d, 0x52, 0x5e, 0xa3, 0x1c, 0xbf, 0xd6, 0xa4, 0x2f, 0xb7, 0xb1, 0xde, - 0x8f, 0x5a, 0xb8, 0x1e, 0x9d, 0x5b, 0xe8, 0xf1, 0xf6, 0xf1, 0xef, 0x35, - 0x9a, 0x07, 0xdf, 0x6a, 0x8a, 0xdf, 0xc7, 0x21, 0xfc, 0x0e, 0xfd, 0x53, - 0x7e, 0x21, 0xc0, 0xef, 0x6a, 0x6d, 0x7b, 0xfc, 0x02, 0xc7, 0x0f, 0x21, - 0xfc, 0xb6, 0x32, 0x0f, 0x6f, 0xb7, 0xe0, 0x4d, 0xea, 0xc5, 0x58, 0xef, - 0x8d, 0x47, 0x0f, 0xfd, 0x1e, 0xa2, 0x7b, 0x65, 0x16, 0xd7, 0x02, 0xbc, - 0xe5, 0x73, 0xf2, 0x7e, 0x5f, 0x82, 0x2a, 0xc7, 0xbf, 0xec, 0xe3, 0x21, - 0x2e, 0xfc, 0x73, 0xd1, 0xfe, 0xed, 0xaa, 0xe2, 0x8b, 0x3e, 0x67, 0x72, - 0x84, 0x8b, 0xa8, 0xef, 0x7a, 0x78, 0xf3, 0xbe, 0xaf, 0x5c, 0xb8, 0x55, - 0x55, 0xfd, 0x4c, 0xf6, 0x15, 0x13, 0x06, 0x78, 0x4e, 0x4e, 0x70, 0xff, - 0xfa, 0x10, 0xa5, 0x3e, 0x59, 0x1c, 0xc5, 0x3e, 0x03, 0x1d, 0xeb, 0xfd, - 0x8c, 0xd6, 0x9d, 0x71, 0x7a, 0x47, 0x0e, 0x98, 0x36, 0xea, 0x75, 0xc6, - 0x09, 0x3b, 0x62, 0x72, 0x5f, 0x12, 0x3e, 0x8e, 0xa1, 0x7a, 0x6e, 0xa3, - 0x3f, 0x05, 0xfb, 0x12, 0xc7, 0x79, 0x40, 0xca, 0x3b, 0x02, 0xfd, 0x48, - 0xe8, 0xf4, 0x92, 0x7f, 0x37, 0x81, 0xe3, 0x52, 0xfb, 0xd2, 0x92, 0xc7, - 0xc5, 0x9a, 0xea, 0xe3, 0xd9, 0x11, 0xe9, 0x4f, 0x02, 0x1c, 0x93, 0xf2, - 0x48, 0x28, 0xf4, 0x74, 0x53, 0x6e, 0x4b, 0x95, 0x75, 0x5a, 0x97, 0x2f, - 0xe3, 0x31, 0x63, 0x65, 0x25, 0x2f, 0x60, 0x61, 0x8e, 0xdf, 0x79, 0x86, - 0x72, 0xa7, 0x1a, 0x21, 0xb9, 0x39, 0xaa, 0xf8, 0x48, 0x60, 0x7c, 0x73, - 0xc4, 0xc7, 0xe9, 0x6b, 0x84, 0xa7, 0xe0, 0x18, 0x62, 0x74, 0x63, 0x2e, - 0x5b, 0x88, 0x10, 0xf7, 0xf6, 0xdf, 0x16, 0xe1, 0x1e, 0xf6, 0x4d, 0x4f, - 0x7e, 0x82, 0x73, 0xb5, 0x59, 0x9e, 0xbc, 0x73, 0x5d, 0xe6, 0xa9, 0xd1, - 0xfc, 0x8e, 0x73, 0x5d, 0x95, 0x9b, 0xd4, 0x9f, 0xea, 0x83, 0x25, 0xae, - 0xfb, 0x46, 0xef, 0x1a, 0x89, 0x4e, 0xc8, 0xfc, 0x4f, 0xad, 0xfb, 0x95, - 0x0e, 0x7d, 0x77, 0x91, 0xfe, 0xf6, 0xde, 0x5b, 0x6e, 0xc8, 0x1c, 0xfe, - 0x1f, 0xde, 0x55, 0x5b, 0xbd, 0xa7, 0x1c, 0xe6, 0xf9, 0x04, 0xf3, 0x6c, - 0x40, 0x4b, 0x04, 0x89, 0xb1, 0x8d, 0x29, 0x3c, 0x57, 0x2f, 0xd3, 0x58, - 0xb7, 0x5b, 0x66, 0x70, 0xae, 0x3b, 0xf6, 0x0c, 0xe9, 0x19, 0x24, 0x4f, - 0x2a, 0xbc, 0x32, 0x45, 0xef, 0x6c, 0x1d, 0x7e, 0x01, 0x50, 0xb6, 0x82, - 0xa7, 0xd8, 0x0d, 0x00, 0x00, 0x00 }; + /* Date: 05/13/2008 13:50 */ + 0xa5, 0x56, 0x4f, 0x48, 0x14, 0x61, 0x14, 0x7f, 0x3b, 0xfb, 0x67, 0xd6, + 0xdd, 0xd9, 0x9d, 0x25, 0xff, 0x6d, 0x66, 0xb8, 0x49, 0x97, 0xd5, 0x15, + 0xb5, 0x22, 0x3a, 0x18, 0x86, 0x17, 0x21, 0x3b, 0x84, 0x20, 0x45, 0x04, + 0xd9, 0x12, 0xde, 0x82, 0x0e, 0xd1, 0x29, 0x68, 0xd1, 0x34, 0x8a, 0x0a, + 0x16, 0x52, 0x30, 0xa2, 0xa4, 0x43, 0x85, 0x04, 0xed, 0x74, 0x0a, 0x12, + 0x82, 0x8a, 0x88, 0xea, 0x12, 0x78, 0xa8, 0x4b, 0x16, 0x61, 0xd0, 0xa1, + 0x83, 0x9d, 0xba, 0xe4, 0xf4, 0xbd, 0xef, 0xbd, 0xcf, 0x9d, 0xf9, 0x9c, + 0x55, 0x21, 0x41, 0x7f, 0xbc, 0x6f, 0xde, 0x7b, 0xdf, 0x9b, 0xdf, 0x7b, + 0xef, 0x37, 0x66, 0x00, 0xc0, 0x80, 0x92, 0xd3, 0x26, 0x10, 0x52, 0x46, + 0x28, 0x2e, 0x20, 0x04, 0xf0, 0x18, 0xe8, 0x27, 0x6a, 0x49, 0xbb, 0xd4, + 0xcd, 0x76, 0x27, 0x41, 0xa9, 0x33, 0x23, 0xfe, 0x9e, 0x85, 0xfe, 0x1c, + 0x62, 0x18, 0xfa, 0x77, 0x21, 0x1e, 0x84, 0x17, 0xb9, 0xac, 0xc0, 0xbf, + 0x2e, 0x94, 0xd0, 0x6e, 0xa8, 0x3c, 0x73, 0x92, 0x32, 0xff, 0x12, 0xc7, + 0x7f, 0x0a, 0x13, 0x1e, 0x28, 0xc4, 0x29, 0x0f, 0x23, 0x74, 0x65, 0x24, + 0x2c, 0x96, 0xd1, 0x1e, 0x19, 0x81, 0x18, 0xe6, 0x99, 0x12, 0x0e, 0x68, + 0xb7, 0x86, 0x4a, 0x5d, 0x5c, 0x97, 0x41, 0x7e, 0x5f, 0xca, 0x36, 0x9e, + 0xc3, 0xd7, 0x01, 0xb4, 0xb7, 0x27, 0x2e, 0x97, 0x11, 0xb3, 0x30, 0x16, + 0xb7, 0xe8, 0x7d, 0xda, 0x28, 0xed, 0x52, 0x07, 0xc6, 0x09, 0xdf, 0x0e, + 0xce, 0x1b, 0xc5, 0xbc, 0x3f, 0x5d, 0xca, 0x8b, 0xf9, 0xbc, 0x79, 0x5a, + 0x45, 0x1e, 0x3c, 0x8f, 0x71, 0x5d, 0x31, 0xad, 0xae, 0x98, 0xa8, 0x83, + 0x79, 0x00, 0x55, 0x07, 0x62, 0xa3, 0xb8, 0x17, 0xf3, 0xae, 0xf0, 0x7b, + 0x03, 0x9c, 0xca, 0x71, 0x7e, 0x07, 0xb1, 0xc2, 0xf9, 0xc4, 0x2f, 0xbf, + 0xc7, 0xfa, 0x3c, 0x8a, 0x27, 0x7f, 0xfd, 0x66, 0x41, 0x3d, 0x57, 0xfd, + 0xc0, 0x7b, 0x3e, 0x8a, 0x7b, 0xbc, 0xfe, 0xb0, 0x89, 0xff, 0x7b, 0xe1, + 0xef, 0xcf, 0x4b, 0xe7, 0x6f, 0xab, 0xe7, 0xf9, 0x20, 0xde, 0xa2, 0x1a, + 0x6f, 0x2f, 0x99, 0xb7, 0x41, 0xd8, 0x6d, 0x64, 0xa5, 0x5f, 0x04, 0x10, + 0x77, 0x88, 0x02, 0x10, 0x77, 0x32, 0x1e, 0x63, 0xbc, 0xc9, 0x78, 0x83, + 0xb1, 0x91, 0xb1, 0x81, 0xb1, 0x9e, 0x71, 0x1b, 0xe3, 0x3b, 0xc6, 0x0c, + 0xa3, 0xcd, 0x98, 0x66, 0x7c, 0xc3, 0x68, 0x31, 0x26, 0xb5, 0x7c, 0x2d, + 0x8c, 0x71, 0xc6, 0xbb, 0x8c, 0xfb, 0xb5, 0xf8, 0xdf, 0x8c, 0x0b, 0x8c, + 0xcd, 0x21, 0xc2, 0x43, 0x6c, 0x23, 0xa1, 0x3c, 0xf7, 0x3e, 0xbe, 0xee, + 0xaf, 0xf5, 0x77, 0xb1, 0xcc, 0xcf, 0xf3, 0xca, 0x2f, 0x2e, 0xf9, 0x83, + 0x0e, 0xaf, 0xff, 0x9d, 0x0d, 0xfc, 0xc9, 0x6d, 0x20, 0x1f, 0x14, 0x37, + 0xed, 0x52, 0x1d, 0xb7, 0x38, 0xbe, 0xbe, 0xb2, 0x50, 0x63, 0x8f, 0xfa, + 0x0a, 0xfa, 0x7c, 0x05, 0xed, 0xd1, 0x4e, 0xde, 0xa3, 0xa3, 0xeb, 0xe6, + 0x97, 0xe6, 0xd4, 0xbb, 0x87, 0x32, 0x4f, 0x8d, 0x39, 0x7f, 0x1a, 0x2a, + 0x16, 0xb2, 0x34, 0x17, 0xa5, 0x8d, 0xee, 0xc5, 0x78, 0x9e, 0xcb, 0xbc, + 0x9a, 0x4f, 0xff, 0x5c, 0xd2, 0x7c, 0xc5, 0xb4, 0xf9, 0xba, 0xb0, 0x09, + 0xbf, 0x49, 0x8d, 0xa7, 0x73, 0xae, 0xea, 0x97, 0xc1, 0xc7, 0xe3, 0xb1, + 0x8c, 0xcc, 0x7b, 0xcd, 0x91, 0x66, 0x83, 0x35, 0x85, 0x76, 0x04, 0xae, + 0x3b, 0x2a, 0x8e, 0xf7, 0xb2, 0x43, 0xdd, 0x43, 0xf1, 0x29, 0x20, 0x9e, + 0xe7, 0x34, 0x9e, 0x73, 0x5b, 0xd2, 0xa9, 0x15, 0xb7, 0xaa, 0x53, 0xf4, + 0xbc, 0x0d, 0xbc, 0x3a, 0x15, 0x87, 0xd1, 0x41, 0x5b, 0xde, 0x9b, 0x8e, + 0x51, 0x9a, 0xe3, 0x36, 0xe1, 0x99, 0x04, 0xe1, 0x72, 0xa2, 0x4e, 0xfc, + 0x75, 0xdd, 0xb1, 0x24, 0xd9, 0xa7, 0x53, 0x6a, 0x3f, 0x54, 0xbc, 0xaa, + 0x6b, 0xa3, 0x7a, 0xf0, 0x7e, 0x75, 0x8f, 0xaa, 0x43, 0xdd, 0xe7, 0xe7, + 0xbf, 0xf6, 0xbd, 0x84, 0x45, 0xc3, 0xcf, 0xc3, 0xed, 0x1e, 0xc2, 0x48, + 0xaf, 0x84, 0xec, 0x8c, 0x45, 0x71, 0xb3, 0x56, 0x04, 0xed, 0x7d, 0xb3, + 0x1f, 0x30, 0xbf, 0xb1, 0x67, 0xc6, 0xe1, 0xfa, 0x6c, 0xd5, 0x3f, 0x79, + 0x0e, 0xed, 0x40, 0xf6, 0x30, 0xcf, 0xc3, 0xb0, 0x9c, 0x7b, 0xb1, 0xd7, + 0x06, 0x62, 0x0b, 0x94, 0xa4, 0xae, 0x1b, 0x89, 0xd7, 0x32, 0x3e, 0xcc, + 0xe7, 0xa2, 0x4f, 0xed, 0xfe, 0x7d, 0x59, 0xa2, 0xfe, 0xc7, 0xfd, 0x73, + 0xd3, 0xed, 0x06, 0xcf, 0x63, 0xa2, 0x32, 0x57, 0x0e, 0xea, 0xd7, 0x73, + 0xd6, 0xbd, 0x2c, 0x14, 0x7b, 0x6b, 0xe9, 0xb1, 0xfa, 0x0e, 0x2a, 0x3d, + 0x92, 0xc7, 0x95, 0x52, 0xd8, 0xc7, 0xcb, 0x21, 0x28, 0x04, 0xe5, 0x7f, + 0xa2, 0xbe, 0x2f, 0x01, 0x7b, 0xb4, 0xd9, 0xbd, 0xbe, 0xfc, 0x69, 0x28, + 0x04, 0xed, 0x81, 0xa9, 0xed, 0x8d, 0xcd, 0x7b, 0xd3, 0xbc, 0x6e, 0x7e, + 0x95, 0x4e, 0xe4, 0x36, 0xd4, 0x89, 0xff, 0xd5, 0x05, 0x03, 0x48, 0x17, + 0x50, 0x8f, 0xfd, 0xf7, 0x9b, 0xaa, 0x7e, 0x6d, 0xff, 0xa9, 0xee, 0x3f, + 0xab, 0x5b, 0xd3, 0x11, 0xef, 0xfb, 0x07, 0xe9, 0x48, 0x42, 0xd3, 0x85, + 0x5f, 0xab, 0x55, 0x1d, 0xc1, 0xe7, 0xf3, 0xf3, 0xd4, 0x97, 0x8b, 0xee, + 0x9a, 0xae, 0xfb, 0xf8, 0xac, 0x63, 0x3e, 0x85, 0x9f, 0x8c, 0x5f, 0xd6, + 0xe2, 0x55, 0x5f, 0xcf, 0x33, 0xcf, 0x46, 0x1f, 0xcd, 0x95, 0x59, 0xfc, + 0xa1, 0xf1, 0xdd, 0x5b, 0xc0, 0xbd, 0xb8, 0x04, 0x0e, 0xf3, 0xf6, 0xd9, + 0xc7, 0x5f, 0x8a, 0xf5, 0xc1, 0x84, 0x47, 0x8e, 0xe2, 0x59, 0xf5, 0x87, + 0xf0, 0xa1, 0xf4, 0xcf, 0x6c, 0xc2, 0x77, 0x06, 0x1e, 0x38, 0x6a, 0xbf, + 0x6d, 0x99, 0xaf, 0x87, 0xf5, 0x64, 0x94, 0xf7, 0xfa, 0x5b, 0x82, 0x74, + 0xa3, 0x38, 0x24, 0xf7, 0x14, 0x9a, 0x78, 0xbf, 0x8b, 0x29, 0xb2, 0x5b, + 0x52, 0xf4, 0x7f, 0x5b, 0x8f, 0x69, 0x49, 0xbf, 0x96, 0x14, 0x61, 0x53, + 0x12, 0xe3, 0xb2, 0xf0, 0xfd, 0x88, 0x74, 0x2f, 0x54, 0xf7, 0x5b, 0xdf, + 0x6b, 0x7e, 0xdf, 0xbd, 0x78, 0xde, 0x24, 0xf6, 0xd4, 0xdb, 0x0f, 0x6b, + 0x4d, 0x5f, 0xef, 0x71, 0xf5, 0x39, 0xdb, 0xcb, 0xb7, 0x9a, 0xdb, 0x67, + 0x35, 0xfa, 0x34, 0xe8, 0x2a, 0xdd, 0x6b, 0x1f, 0xc4, 0x7a, 0x6d, 0x48, + 0x9b, 0x34, 0x1f, 0x84, 0x22, 0x8f, 0x61, 0x62, 0x58, 0xeb, 0x24, 0xeb, + 0xc4, 0xe4, 0xb8, 0x4c, 0x73, 0x64, 0x52, 0x9d, 0x0f, 0xc8, 0xc1, 0x1f, + 0x9e, 0x7f, 0x25, 0xcf, 0xd3, 0x4e, 0x98, 0xce, 0xcd, 0x21, 0xc5, 0x97, + 0x2d, 0xdf, 0x7f, 0x86, 0xf8, 0x3a, 0x39, 0x4d, 0x78, 0x02, 0x0e, 0x4b, + 0x4c, 0x54, 0xf5, 0x2d, 0x2e, 0x11, 0x52, 0x5e, 0x7d, 0x8b, 0x8a, 0xf2, + 0xd0, 0xae, 0xf3, 0xf4, 0x51, 0xff, 0x6e, 0x6c, 0xb5, 0x9f, 0x5e, 0x9d, + 0xc4, 0x7e, 0xea, 0x7a, 0x27, 0xe7, 0x46, 0x9b, 0xcf, 0x72, 0x8d, 0xf9, + 0xcc, 0xd5, 0x98, 0x6f, 0x5d, 0x2f, 0xae, 0xf2, 0xde, 0x45, 0x20, 0x1a, + 0x96, 0x1f, 0x24, 0x2b, 0x32, 0x21, 0xfb, 0x6b, 0x4c, 0xd2, 0x87, 0xd4, + 0x8a, 0x4e, 0x85, 0x24, 0x6f, 0xd6, 0x14, 0xf9, 0x45, 0xe8, 0x3c, 0xab, + 0xf0, 0xca, 0x84, 0xfa, 0xee, 0xfe, 0x03, 0x65, 0x6c, 0x9a, 0x59, 0x40, + 0x0c, 0x00, 0x00, 0x00 }; static u8 bnx2_rv2p_proc2[] = { - /* Date: 12/07/2007 15:02 */ - 0xed, 0x59, 0x5d, 0x6c, 0x54, 0xc7, 0x15, 0x9e, 0xbd, 0xbb, 0x7b, 0xf7, - 0x7a, 0x7d, 0xf7, 0xae, 0x71, 0xa8, 0xff, 0xf9, 0xb3, 0x09, 0xd8, 0xa9, - 0x21, 0xce, 0x9a, 0x98, 0x02, 0x55, 0x63, 0x39, 0x95, 0x81, 0xa6, 0x55, - 0x0c, 0x49, 0x9b, 0xbe, 0x35, 0x76, 0x02, 0xb6, 0xa9, 0x4d, 0x2d, 0x43, - 0x83, 0x4a, 0x1b, 0x65, 0x85, 0xd7, 0xf6, 0xcb, 0x26, 0xea, 0x22, 0xc0, - 0x24, 0xaa, 0xa8, 0x1b, 0xa4, 0x28, 0xea, 0xdb, 0x56, 0x6a, 0x6d, 0xda, - 0x97, 0xfe, 0x10, 0xb7, 0x4a, 0xa4, 0x42, 0xa5, 0xf6, 0xa1, 0x52, 0x85, - 0x44, 0xda, 0x62, 0x99, 0xc4, 0x20, 0x63, 0xba, 0x79, 0x21, 0x75, 0x67, - 0xce, 0x77, 0xe6, 0xee, 0xbd, 0xeb, 0xb5, 0x21, 0x2d, 0x8f, 0xdd, 0x07, - 0x1f, 0x66, 0xee, 0x99, 0x33, 0xe7, 0xe7, 0x9b, 0x33, 0x67, 0x0e, 0x65, - 0x42, 0x08, 0x43, 0x24, 0xb3, 0x1b, 0x24, 0x15, 0x56, 0x20, 0x20, 0xf0, - 0x7b, 0xac, 0x8c, 0xc8, 0x9f, 0xb3, 0x96, 0xfc, 0x1b, 0x16, 0xcf, 0x1b, - 0x55, 0x34, 0x0e, 0x09, 0x45, 0x1d, 0x21, 0x92, 0x5e, 0x5a, 0xce, 0xf4, - 0x67, 0x4c, 0x77, 0x1b, 0xa0, 0x3d, 0x4c, 0xeb, 0x98, 0x9e, 0x64, 0xba, - 0x91, 0xe9, 0x56, 0xa6, 0x27, 0x98, 0x7e, 0x8f, 0xe9, 0x07, 0x4c, 0x77, - 0xb2, 0x3c, 0xf9, 0x4b, 0xda, 0xf2, 0x4f, 0x40, 0x24, 0x9b, 0xb4, 0x7e, - 0x36, 0xa6, 0x9b, 0xa0, 0xe7, 0x73, 0x1b, 0x15, 0xdf, 0xcd, 0xa5, 0x3c, - 0x1f, 0xe6, 0xaf, 0x65, 0x40, 0x37, 0x60, 0xd5, 0x4f, 0x93, 0x8f, 0xeb, - 0xf5, 0x20, 0xdd, 0x31, 0xd0, 0x9e, 0x20, 0x68, 0x7b, 0x33, 0x91, 0xf4, - 0x4b, 0x06, 0xc6, 0x9d, 0x5b, 0x2c, 0xb2, 0x2f, 0x64, 0x28, 0x39, 0xeb, - 0x2d, 0xf3, 0x12, 0xe6, 0xbf, 0x19, 0x07, 0x7d, 0x39, 0x0a, 0xfa, 0x4f, - 0xa6, 0x87, 0x4b, 0x59, 0xbe, 0xcd, 0x6a, 0x97, 0x62, 0xfd, 0x8c, 0xad, - 0x68, 0x50, 0x24, 0x79, 0x9d, 0x10, 0xd0, 0xeb, 0xc7, 0x02, 0xdf, 0xd7, - 0x6c, 0xc5, 0xec, 0x0f, 0x0f, 0x63, 0x5c, 0x7b, 0xb1, 0x8c, 0xf8, 0xcf, - 0x67, 0xb5, 0xfe, 0x16, 0x79, 0x3f, 0x19, 0x87, 0x1c, 0x51, 0x6f, 0xd1, - 0x26, 0xc9, 0x66, 0x50, 0xb1, 0x4d, 0xcb, 0xc3, 0xef, 0xdc, 0xa3, 0xda, - 0x3f, 0x18, 0xaf, 0x4d, 0x80, 0x9e, 0x65, 0x5a, 0xd1, 0x4a, 0x64, 0xfb, - 0xdf, 0x9f, 0xb0, 0x48, 0x97, 0xe4, 0x36, 0xaf, 0x1f, 0x7f, 0x23, 0xfd, - 0xc8, 0x82, 0x1a, 0x40, 0x6e, 0x3c, 0xaa, 0xf8, 0xa4, 0x71, 0xf5, 0x90, - 0x7b, 0xb0, 0xbf, 0x98, 0xff, 0x7f, 0xf9, 0x19, 0xfc, 0xaf, 0xe4, 0xb5, - 0xb3, 0xfe, 0x1b, 0xa5, 0xfe, 0x8a, 0xd6, 0x05, 0x92, 0xdb, 0xfc, 0xfe, - 0xb9, 0x96, 0x89, 0xd3, 0xbf, 0x6f, 0x76, 0x94, 0x91, 0xfd, 0xcf, 0x62, - 0xfe, 0x74, 0xe7, 0x14, 0xfc, 0xb4, 0x9f, 0xe2, 0x22, 0xa2, 0xa9, 0x9f, - 0x63, 0x55, 0x77, 0x4c, 0x8d, 0x5f, 0xd8, 0x71, 0x23, 0x8b, 0xef, 0xe1, - 0x11, 0x35, 0x36, 0xe4, 0x3a, 0xfc, 0xf6, 0x07, 0x09, 0xe0, 0x69, 0x73, - 0x84, 0x86, 0xf6, 0x0c, 0x7d, 0xb7, 0xc5, 0x78, 0x16, 0xdf, 0x8f, 0x96, - 0xaa, 0xf1, 0xb3, 0xcd, 0x73, 0x18, 0x37, 0xf7, 0x8f, 0xf1, 0x42, 0xa3, - 0x44, 0xfe, 0x59, 0x5a, 0xba, 0x69, 0x40, 0x1e, 0x87, 0x37, 0x1a, 0x32, - 0xe2, 0x64, 0xaf, 0xdd, 0x09, 0x3a, 0x4a, 0xdf, 0xef, 0x05, 0xd2, 0x64, - 0x77, 0xa7, 0x13, 0x9a, 0x02, 0x23, 0xe3, 0xca, 0xc5, 0x8d, 0xc6, 0xdd, - 0x83, 0xe2, 0x67, 0xcc, 0xc5, 0x0f, 0xfb, 0xbf, 0x69, 0x25, 0xfc, 0x80, - 0x76, 0x6e, 0x01, 0x35, 0x1b, 0x14, 0x5f, 0xb8, 0x08, 0x8e, 0xfc, 0x7e, - 0xe6, 0xf8, 0x14, 0xe2, 0x44, 0xe2, 0x03, 0x63, 0xc6, 0x8b, 0xc4, 0x95, - 0xe2, 0xaf, 0x96, 0xfe, 0xd2, 0xf1, 0x57, 0x82, 0x22, 0xe2, 0xdb, 0x2c, - 0xaf, 0x9f, 0xed, 0x1a, 0x60, 0x7b, 0xe6, 0xa3, 0xda, 0xaf, 0xda, 0x1e, - 0xd0, 0x71, 0x9f, 0x3d, 0x01, 0x89, 0x27, 0x8d, 0x23, 0x9f, 0x3e, 0xe9, - 0xf7, 0xea, 0xf1, 0x8f, 0x5a, 0xc6, 0xa1, 0x6b, 0xe7, 0x16, 0xc5, 0x67, - 0x26, 0x26, 0xb2, 0x7e, 0x1c, 0x6e, 0x10, 0x5a, 0x8e, 0x96, 0xaf, 0x70, - 0x99, 0x93, 0xb8, 0x44, 0xdc, 0xce, 0x67, 0xbd, 0xe7, 0xa8, 0xa6, 0xc8, - 0x39, 0xf2, 0x9f, 0x07, 0xed, 0x97, 0xa3, 0x31, 0x4a, 0x10, 0x3b, 0xae, - 0xcc, 0xfa, 0xf7, 0x03, 0xbe, 0x23, 0x2e, 0x7e, 0xd6, 0xb6, 0xb1, 0xff, - 0x98, 0x56, 0xec, 0x54, 0xf2, 0xba, 0x58, 0x7e, 0x0b, 0xcb, 0xb7, 0x0b, - 0xce, 0xdb, 0x73, 0xee, 0x79, 0xd3, 0x71, 0xcb, 0x9f, 0x3b, 0xed, 0x3f, - 0xda, 0xbf, 0xf9, 0xca, 0xac, 0x5a, 0x5f, 0x7b, 0x9f, 0x73, 0xb8, 0xbf, - 0xc8, 0x39, 0x84, 0x9c, 0xbf, 0x3c, 0xee, 0xb7, 0x6b, 0x88, 0xf3, 0x5c, - 0x0f, 0xe2, 0x66, 0xbd, 0xf4, 0x2b, 0xfe, 0xf0, 0x18, 0xe1, 0x5d, 0xbc, - 0x18, 0x41, 0x7c, 0x1d, 0xd2, 0x5f, 0xb0, 0x1d, 0x2f, 0x7b, 0xce, 0x6b, - 0x09, 0xf9, 0xb5, 0xc3, 0xc4, 0x7e, 0x1d, 0xdd, 0x58, 0xde, 0xce, 0x78, - 0xc8, 0xf1, 0x79, 0x99, 0xb5, 0x49, 0xff, 0xe8, 0x9d, 0x53, 0x98, 0x1f, - 0xdd, 0x43, 0x24, 0x7d, 0xd5, 0xd0, 0xf6, 0x86, 0xd4, 0xdf, 0xc9, 0x41, - 0x7c, 0x9f, 0x0c, 0xf1, 0xf9, 0x7c, 0xaf, 0x9e, 0xd6, 0x5b, 0xf3, 0x19, - 0xac, 0xcf, 0xb1, 0x7e, 0x27, 0x82, 0xc4, 0x1f, 0x1d, 0x63, 0xbe, 0xf1, - 0x11, 0xbf, 0x9d, 0x3f, 0x40, 0x3e, 0xb7, 0xbf, 0x3f, 0x42, 0xe7, 0xdd, - 0x31, 0x5d, 0x3e, 0xa2, 0xce, 0xe8, 0x29, 0xc5, 0x5f, 0x29, 0xc6, 0xb2, - 0x4a, 0xd1, 0x2a, 0xd1, 0xbd, 0x17, 0xeb, 0xde, 0x30, 0x91, 0x6f, 0x7a, - 0xf7, 0x82, 0x7e, 0x88, 0xf9, 0xf5, 0xce, 0xb8, 0xe2, 0x5f, 0x53, 0xe3, - 0x4c, 0x29, 0x1a, 0x97, 0xf6, 0x28, 0xfb, 0xa5, 0xed, 0x8c, 0xcf, 0xc1, - 0x46, 0xf0, 0xf7, 0x1d, 0xa2, 0x8d, 0xcf, 0x0c, 0xe4, 0x28, 0x5f, 0x4d, - 0x0e, 0x5f, 0x52, 0x7e, 0xa9, 0x16, 0xb3, 0xc7, 0x14, 0x0d, 0x89, 0x8e, - 0x4d, 0xec, 0x97, 0x3d, 0xfe, 0xfc, 0x3c, 0xbf, 0x53, 0x8d, 0x6b, 0x24, - 0x9f, 0x17, 0xbf, 0x16, 0xc7, 0x39, 0xe4, 0xfa, 0xf5, 0x13, 0x03, 0x76, - 0xa7, 0x48, 0xff, 0x3d, 0xd1, 0x14, 0x9d, 0xeb, 0x98, 0xe8, 0x25, 0x3c, - 0x85, 0xac, 0xc1, 0x4b, 0xf8, 0x3e, 0xff, 0x0b, 0x2d, 0x57, 0xe1, 0x61, - 0x17, 0xdf, 0x9f, 0xc2, 0x95, 0x13, 0xda, 0xc9, 0x71, 0xd0, 0xfb, 0xb6, - 0xe2, 0xbe, 0xe9, 0x08, 0xa8, 0xf1, 0x3a, 0x39, 0xb6, 0x29, 0x6e, 0x1d, - 0xdd, 0x6a, 0xbd, 0x4c, 0x02, 0x74, 0x7e, 0x1c, 0x29, 0x5f, 0xcd, 0x47, - 0xa4, 0x1d, 0xfe, 0x7d, 0x06, 0x11, 0x0f, 0xfb, 0x28, 0xf9, 0xe7, 0xf3, - 0xf6, 0xad, 0x8c, 0xb6, 0x07, 0xf3, 0xb7, 0x5d, 0x7d, 0x6c, 0xb2, 0xab, - 0x63, 0x13, 0xf6, 0x9b, 0x75, 0x78, 0x9f, 0x4d, 0xbc, 0xef, 0x31, 0xb5, - 0x5f, 0x83, 0x47, 0x5f, 0xc5, 0x67, 0x45, 0x6f, 0x91, 0xdc, 0x75, 0xd6, - 0x77, 0x2e, 0x91, 0x7f, 0xad, 0xa3, 0x53, 0xd8, 0xff, 0xf6, 0xd4, 0x6a, - 0x7a, 0xd7, 0xb0, 0x9c, 0x75, 0xec, 0xd7, 0xd8, 0x43, 0x8c, 0xdb, 0xea, - 0x71, 0xca, 0xfb, 0x57, 0xfb, 0x87, 0xe4, 0xdb, 0x0b, 0xd3, 0xab, 0xe9, - 0x2b, 0x6d, 0x4a, 0x82, 0x3f, 0x65, 0xd0, 0xc1, 0xa8, 0x82, 0x5f, 0xf2, - 0x71, 0xd3, 0xfa, 0xce, 0x1f, 0xc2, 0x7d, 0x34, 0xe8, 0xe6, 0x0b, 0x25, - 0xb7, 0x9d, 0xf1, 0x20, 0xe5, 0x05, 0xe0, 0x9f, 0x85, 0x69, 0x9c, 0x9b, - 0x13, 0x74, 0x3e, 0xbe, 0x68, 0x87, 0x68, 0xff, 0xa8, 0x75, 0x83, 0xef, - 0xa5, 0xfc, 0xfd, 0x03, 0x79, 0x7d, 0x36, 0x68, 0x2f, 0xe7, 0xe9, 0x1b, - 0x4c, 0x53, 0xb6, 0x5a, 0x57, 0x2a, 0xf3, 0xad, 0x45, 0xf2, 0x91, 0x57, - 0x4b, 0x5c, 0x7d, 0x8f, 0xb0, 0x9c, 0x8f, 0x98, 0x0a, 0x96, 0x33, 0xc0, - 0xeb, 0xe7, 0x7c, 0x72, 0x0c, 0x8f, 0x1c, 0x7f, 0x3e, 0x1a, 0xe3, 0x7b, - 0xef, 0xbc, 0xb9, 0x52, 0xbd, 0xa4, 0x68, 0xb9, 0x5c, 0x8f, 0x59, 0x7d, - 0x2f, 0xa4, 0x1a, 0x89, 0xb4, 0x85, 0x0c, 0xb2, 0x77, 0x32, 0x35, 0x02, - 0x3f, 0x8d, 0xb3, 0x9f, 0x22, 0xf0, 0x53, 0x4d, 0xfe, 0x9e, 0xe4, 0x8d, - 0xf8, 0xfc, 0xcd, 0x6c, 0xf6, 0x9f, 0xc7, 0xf3, 0xa6, 0x8e, 0x2f, 0x91, - 0x34, 0xf2, 0x90, 0xbe, 0x3f, 0xf5, 0xbd, 0x72, 0x4b, 0xe7, 0x6d, 0xb9, - 0x6f, 0x81, 0x3e, 0x41, 0x8a, 0x73, 0x74, 0x9c, 0xf3, 0xd1, 0xd5, 0xa0, - 0x8e, 0x27, 0xf4, 0x1b, 0xff, 0x8c, 0xfa, 0xe5, 0xef, 0xe5, 0xb0, 0x22, - 0xcd, 0xb3, 0xc7, 0x88, 0xb6, 0xf4, 0x1d, 0xc7, 0x7c, 0x65, 0xab, 0xd2, - 0xe7, 0x27, 0x01, 0x9c, 0xd3, 0xb0, 0x98, 0xc9, 0xe0, 0x9e, 0x13, 0x11, - 0xd2, 0xa3, 0xee, 0x32, 0xe1, 0xc2, 0x8c, 0xa6, 0x32, 0x3e, 0x7f, 0x79, - 0xec, 0x2e, 0x66, 0xef, 0x84, 0xc4, 0x93, 0xfa, 0x6e, 0xf2, 0x79, 0x95, - 0x78, 0xb5, 0xf9, 0xbc, 0x3c, 0x4d, 0x7c, 0xf6, 0x22, 0xd9, 0xf9, 0x0d, - 0x6b, 0x9c, 0xeb, 0xb4, 0x8f, 0x3b, 0xd5, 0xf8, 0x79, 0xfb, 0x75, 0x9c, - 0x77, 0xfb, 0x75, 0xe4, 0x5b, 0x2b, 0x7c, 0x11, 0x79, 0xb8, 0xf3, 0xa2, - 0x6f, 0xff, 0x74, 0xc8, 0xd0, 0xe7, 0xe7, 0x7f, 0xf2, 0x9b, 0xfd, 0x5d, - 0xf6, 0xdb, 0xdd, 0xd5, 0xe3, 0x9a, 0x36, 0xf9, 0x1c, 0xf6, 0xdd, 0x2d, - 0xb4, 0x57, 0xf9, 0xef, 0x43, 0xf7, 0x1e, 0x0e, 0xed, 0x62, 0x7d, 0x76, - 0x71, 0x1e, 0xe0, 0xfa, 0x67, 0x7d, 0x50, 0xdf, 0x8b, 0x1a, 0x0f, 0x7c, - 0x3f, 0x02, 0xa7, 0xd6, 0x28, 0xec, 0x15, 0xaf, 0xf2, 0x39, 0xf8, 0x37, - 0xd3, 0xd7, 0x18, 0xff, 0x27, 0xb9, 0x3e, 0xd2, 0xf5, 0xdd, 0x3d, 0xcc, - 0x3b, 0x13, 0x6e, 0x3d, 0xa4, 0xef, 0x1f, 0x35, 0x0e, 0x08, 0x27, 0x52, - 0x4a, 0xfb, 0x25, 0x7f, 0x07, 0x80, 0x8d, 0x3f, 0x0d, 0x3f, 0xce, 0xb6, - 0x82, 0xef, 0x0d, 0xf8, 0xc7, 0xd1, 0xfa, 0x2d, 0x36, 0xfa, 0xde, 0x01, - 0x6d, 0xf0, 0xaf, 0xe9, 0xfa, 0x57, 0xe3, 0x73, 0x89, 0x69, 0xed, 0x66, - 0xb6, 0xf3, 0xbf, 0xf3, 0xbb, 0xa7, 0x1e, 0x5b, 0xc9, 0xef, 0xb4, 0xbe, - 0xad, 0xef, 0x2e, 0xe6, 0xcb, 0x76, 0x83, 0x66, 0x76, 0xd3, 0xfc, 0x66, - 0xe4, 0xdb, 0x70, 0xdb, 0xe9, 0xfb, 0xd4, 0xa7, 0xfa, 0x5d, 0x53, 0xf9, - 0x25, 0xd0, 0x33, 0x4c, 0x3f, 0xf7, 0x14, 0xe8, 0xb9, 0xa7, 0xfc, 0x79, - 0xc4, 0x8c, 0xfb, 0xe2, 0xdb, 0x86, 0xf8, 0xbe, 0xe3, 0xc6, 0x77, 0x3d, - 0xea, 0x03, 0x19, 0xaf, 0x55, 0xe3, 0xe9, 0xc6, 0xe9, 0x7e, 0xf1, 0x7c, - 0xd8, 0x71, 0x4c, 0xed, 0xc2, 0x3d, 0x37, 0xcc, 0xef, 0xcd, 0x45, 0xf7, - 0x9e, 0x2a, 0x16, 0xdf, 0xc8, 0xff, 0xe3, 0x4b, 0xf1, 0x3d, 0xb2, 0xa4, - 0xf3, 0x1f, 0xee, 0x79, 0x5d, 0xd7, 0x0f, 0x79, 0xea, 0x7a, 0xff, 0xbe, - 0xdf, 0xa2, 0x7a, 0x79, 0x34, 0xe0, 0xe2, 0x82, 0xf8, 0xa7, 0x79, 0x5d, - 0x19, 0xaf, 0xdb, 0xb7, 0x6c, 0xdd, 0xb5, 0x8c, 0x5a, 0xf7, 0xb7, 0x4f, - 0x97, 0xf7, 0x25, 0x7c, 0x7a, 0x26, 0x45, 0x1c, 0xf1, 0xc1, 0x7d, 0x61, - 0x16, 0xe9, 0x63, 0xf8, 0x71, 0xb7, 0x37, 0x8e, 0x7c, 0xa8, 0xdf, 0x79, - 0xfe, 0xba, 0xfe, 0x8f, 0x9f, 0xae, 0x5c, 0xd7, 0x6b, 0x79, 0x88, 0x5f, - 0xb7, 0x11, 0x23, 0xbe, 0xeb, 0x43, 0x6a, 0x5d, 0xbf, 0x6b, 0x5f, 0x3b, - 0xd9, 0x75, 0x99, 0xed, 0xab, 0x63, 0xfb, 0xe4, 0xe7, 0x6d, 0x74, 0x9f, - 0x58, 0xd7, 0x87, 0xbc, 0xf6, 0xfd, 0x7a, 0x95, 0xfd, 0x1e, 0xf4, 0x1d, - 0xc1, 0xfb, 0xc6, 0xf5, 0xfe, 0x4a, 0x5e, 0x2d, 0xd7, 0x63, 0x8e, 0xe0, - 0xe7, 0x54, 0x91, 0xba, 0x46, 0xed, 0xff, 0x7b, 0xe9, 0x00, 0xbe, 0xc7, - 0xe8, 0x1d, 0x11, 0xb4, 0x2e, 0x67, 0x8a, 0xf9, 0xe5, 0x6b, 0x01, 0xf0, - 0x15, 0x8b, 0x9b, 0xfa, 0x1e, 0x66, 0x39, 0xc5, 0xec, 0x66, 0x3d, 0x5d, - 0x3c, 0xf0, 0x3a, 0xe2, 0xeb, 0x63, 0xbe, 0x50, 0x91, 0xbe, 0x04, 0x46, - 0xb9, 0xad, 0x54, 0x2f, 0x5e, 0x38, 0x39, 0xad, 0xf8, 0x62, 0xee, 0xbb, - 0xcc, 0xaf, 0xdf, 0xc4, 0x43, 0xf0, 0x23, 0xbd, 0x3f, 0x44, 0xaf, 0xb3, - 0x92, 0xbf, 0xf0, 0x7e, 0x5a, 0x98, 0xd6, 0xfe, 0xb6, 0xc9, 0x4e, 0xd4, - 0xd3, 0x17, 0x0a, 0xfc, 0x68, 0x78, 0xfc, 0x08, 0xfe, 0x95, 0x71, 0xef, - 0x7f, 0x97, 0x03, 0x17, 0xaf, 0x16, 0xc1, 0x3d, 0xf5, 0xf7, 0x1e, 0xd8, - 0xce, 0x03, 0xad, 0x5e, 0xbb, 0x1a, 0xc4, 0x4c, 0x16, 0xf8, 0xef, 0x62, - 0x9c, 0xbc, 0xc8, 0x79, 0xf6, 0x7a, 0x54, 0x4d, 0x58, 0xa2, 0xe7, 0x19, - 0xe4, 0xe9, 0x8a, 0x52, 0xd8, 0xdd, 0xf3, 0x55, 0xed, 0x27, 0xcc, 0xd7, - 0xc4, 0x50, 0x57, 0x77, 0x45, 0xf0, 0xbe, 0xa8, 0x89, 0x81, 0x56, 0x70, - 0x9e, 0x9e, 0x71, 0xfb, 0x29, 0xa0, 0xf9, 0xfa, 0x12, 0x7d, 0xa5, 0xdf, - 0x9a, 0xa8, 0xc3, 0x45, 0x13, 0xd7, 0xcf, 0x94, 0xef, 0x82, 0xe2, 0x60, - 0x13, 0x70, 0x22, 0xea, 0xfd, 0x79, 0x8a, 0xf3, 0xec, 0xb2, 0x7a, 0x0d, - 0x7d, 0x99, 0x12, 0x4f, 0x5f, 0x42, 0xef, 0xa7, 0xfd, 0xa8, 0xe5, 0xd2, - 0x70, 0x85, 0xba, 0x72, 0x91, 0xf3, 0xd8, 0x23, 0xe2, 0x0f, 0x59, 0xd8, - 0x35, 0x93, 0x2d, 0xc4, 0x95, 0xde, 0x4f, 0xcb, 0x83, 0xde, 0xda, 0x8e, - 0xbc, 0x7c, 0xec, 0x7f, 0x88, 0xf5, 0xfc, 0x07, 0xf5, 0x33, 0x2b, 0xd8, - 0x1e, 0x25, 0x17, 0xf3, 0xfb, 0xb8, 0x4f, 0x94, 0x74, 0xc7, 0xfe, 0xfe, - 0x4e, 0x17, 0xe9, 0xb5, 0x86, 0x71, 0x54, 0xe1, 0xc1, 0x39, 0xf8, 0xd7, - 0xb6, 0x80, 0x9e, 0x6d, 0xd1, 0x71, 0xd0, 0xf1, 0xd2, 0xf1, 0x41, 0x1c, - 0x2b, 0xd0, 0x4f, 0xda, 0xd1, 0xf3, 0x04, 0xdd, 0x0f, 0x2d, 0x3d, 0x0b, - 0xfa, 0xdc, 0x61, 0xfd, 0x81, 0x66, 0xc5, 0xff, 0x9a, 0xf8, 0x13, 0xf7, - 0x1b, 0xfe, 0xca, 0xb4, 0xb0, 0x6f, 0x82, 0xbe, 0x8b, 0x8c, 0x5b, 0x98, - 0x03, 0xd2, 0xaa, 0xf3, 0xac, 0xf7, 0x9d, 0xa0, 0xcf, 0xdf, 0xd6, 0x65, - 0x78, 0xcd, 0xe7, 0x4b, 0x6d, 0x9f, 0xe2, 0x6f, 0x66, 0x1c, 0xca, 0xf7, - 0xe9, 0x5e, 0xa5, 0x47, 0x5c, 0xde, 0xdb, 0xc8, 0xc7, 0x4e, 0xc4, 0x1b, - 0x27, 0x89, 0x87, 0x92, 0x88, 0x1a, 0xd6, 0x95, 0x97, 0x90, 0x1d, 0xa7, - 0xdf, 0xff, 0x80, 0x3e, 0xbf, 0x3d, 0x51, 0x8a, 0xf9, 0xca, 0x67, 0xe2, - 0xe4, 0x87, 0x73, 0xc0, 0xf1, 0x8f, 0xce, 0x82, 0xbe, 0x25, 0xbe, 0x82, - 0xf5, 0xe5, 0xa7, 0xe8, 0xfe, 0xb7, 0x2a, 0x19, 0x97, 0x55, 0x38, 0xf7, - 0x69, 0xd4, 0x0f, 0x4b, 0x4b, 0x22, 0x86, 0xba, 0x4d, 0xdf, 0x03, 0xc0, - 0x65, 0xc8, 0x13, 0xdf, 0xfb, 0xe1, 0x54, 0x51, 0xbb, 0xf0, 0x9d, 0x64, - 0x15, 0xe2, 0x55, 0xfb, 0xa3, 0xca, 0x28, 0x8a, 0xcf, 0x36, 0x3f, 0x3e, - 0x4d, 0xc6, 0xe7, 0x5d, 0xb7, 0x8e, 0x5a, 0x2e, 0x97, 0xde, 0x89, 0x12, - 0xb7, 0x0f, 0x0b, 0xaf, 0xa0, 0xfb, 0x1a, 0xd4, 0xfe, 0x95, 0xcb, 0xf2, - 0xeb, 0x06, 0x5f, 0x9c, 0x6f, 0xde, 0xd3, 0x7a, 0x9d, 0x32, 0xbd, 0xdf, - 0x5b, 0xdc, 0x7b, 0x66, 0x98, 0xfb, 0xfc, 0x39, 0xf4, 0xa3, 0x12, 0xf3, - 0x69, 0x1a, 0xda, 0xd5, 0xef, 0x52, 0xdf, 0x22, 0x31, 0xcc, 0xf9, 0xf3, - 0xfd, 0xa0, 0xae, 0xb7, 0x30, 0xbe, 0xc2, 0x79, 0xe3, 0x0e, 0xeb, 0x75, - 0x80, 0x61, 0x39, 0xdf, 0x48, 0x79, 0x37, 0xa1, 0xeb, 0xb4, 0x61, 0x7e, - 0x5f, 0xe8, 0x3e, 0xd5, 0x97, 0x83, 0x9c, 0x4f, 0xc9, 0x8f, 0xa1, 0xc4, - 0xed, 0x29, 0xdd, 0x4f, 0xd0, 0xfd, 0x05, 0xd6, 0x07, 0xfd, 0x30, 0x71, - 0x30, 0x02, 0x2a, 0x9a, 0xfc, 0xf1, 0x11, 0xae, 0x9d, 0x18, 0x99, 0x05, - 0xfd, 0x86, 0x08, 0xf7, 0x09, 0x27, 0x58, 0xbf, 0x33, 0xfc, 0xbe, 0x73, - 0xc8, 0x4f, 0x65, 0xd2, 0x7e, 0xea, 0x5b, 0x25, 0x8e, 0x4d, 0xc3, 0xae, - 0x01, 0xf7, 0xfd, 0x06, 0x3e, 0xa6, 0xce, 0x9b, 0xdc, 0x2f, 0xe3, 0xbe, - 0x9a, 0x63, 0x8e, 0xc0, 0x9e, 0x81, 0x1c, 0xc6, 0x8b, 0x78, 0x17, 0x39, - 0xff, 0xe2, 0x3a, 0xef, 0xf8, 0x49, 0xfd, 0x1e, 0x2c, 0xbe, 0x4e, 0xd7, - 0x85, 0x83, 0xf4, 0x2e, 0x79, 0x61, 0x92, 0xfb, 0xea, 0xa2, 0x9f, 0xea, - 0xd1, 0xaf, 0xdb, 0x39, 0x1e, 0xe7, 0xfb, 0x07, 0xfe, 0xbe, 0x81, 0xae, - 0xbf, 0xe7, 0xd0, 0xff, 0x9c, 0xcc, 0xa5, 0x81, 0x97, 0x64, 0x89, 0x17, - 0xe7, 0x25, 0x89, 0x4a, 0x8e, 0xdb, 0xda, 0x27, 0x41, 0xcf, 0x3e, 0x89, - 0x77, 0xf2, 0xc0, 0x2b, 0xec, 0x97, 0x1d, 0x14, 0xa7, 0xed, 0xe8, 0xbf, - 0x78, 0xeb, 0x50, 0x85, 0x9b, 0x4f, 0x5c, 0x3c, 0xcf, 0x91, 0x5e, 0xb5, - 0x93, 0x39, 0xe2, 0xab, 0x11, 0x8f, 0xd0, 0xbd, 0x57, 0xed, 0x2c, 0x40, - 0xcf, 0xc4, 0x04, 0xdb, 0x37, 0xf4, 0x05, 0xd0, 0x57, 0x38, 0xce, 0x3a, - 0x7e, 0x57, 0xdd, 0x3e, 0x1e, 0xf4, 0xd5, 0xf7, 0xf1, 0xf2, 0xf7, 0x3b, - 0xc6, 0xd5, 0xad, 0x48, 0x60, 0x7d, 0xc7, 0x8b, 0xf7, 0xa7, 0xfc, 0x78, - 0x50, 0x78, 0xd1, 0xb8, 0xf4, 0xe2, 0xa8, 0xf0, 0x9c, 0xe5, 0x71, 0xe1, - 0x34, 0x55, 0x91, 0xbf, 0x70, 0x9f, 0x98, 0x89, 0x89, 0xcc, 0xea, 0x7e, - 0x7a, 0x13, 0x7e, 0x4a, 0xb0, 0xde, 0x76, 0xff, 0x08, 0xee, 0xa1, 0x31, - 0x8e, 0xd3, 0x5c, 0x23, 0xd7, 0x11, 0xac, 0xdf, 0xc7, 0xfc, 0xce, 0x40, - 0x3c, 0x23, 0xf6, 0xe1, 0x69, 0x8e, 0x1f, 0xe3, 0xea, 0x08, 0xdb, 0xfd, - 0x11, 0xec, 0xb6, 0xb5, 0xdd, 0xfd, 0xae, 0xdd, 0xba, 0x4e, 0xf1, 0xca, - 0x29, 0x97, 0xb8, 0xa0, 0x7a, 0xc7, 0xbe, 0x4a, 0x79, 0x24, 0xcc, 0x76, - 0x4a, 0xbe, 0x56, 0xfd, 0xff, 0x8e, 0xf0, 0x57, 0xef, 0x76, 0xef, 0xba, - 0x52, 0x5e, 0x17, 0x95, 0xeb, 0x30, 0x8f, 0xf3, 0x67, 0xaf, 0xe0, 0x4f, - 0xe5, 0x37, 0x2d, 0xb7, 0xf0, 0x7c, 0x79, 0xfd, 0x47, 0x95, 0x1d, 0xfd, - 0x90, 0x57, 0x64, 0x9c, 0xe8, 0x1e, 0xb2, 0xdd, 0xbc, 0x72, 0x87, 0xea, - 0xc0, 0xe8, 0x85, 0x41, 0xe4, 0x81, 0x0b, 0x83, 0xef, 0x72, 0x1d, 0xce, - 0x7e, 0xe9, 0xa2, 0xff, 0xaf, 0x92, 0xb1, 0xab, 0xf7, 0xe7, 0x15, 0xbf, - 0x1e, 0xb5, 0x1e, 0x3d, 0xf4, 0xbe, 0xff, 0x01, 0xfe, 0xf0, 0x11, 0xdc, - 0xa0, 0x1d, 0x00, 0x00, 0x00 }; + /* Date: 05/13/2008 13:50 */ + 0xad, 0x58, 0x4d, 0x6c, 0x54, 0x55, 0x14, 0xbe, 0x7d, 0xf3, 0xdb, 0x99, + 0x37, 0x3f, 0xb4, 0xb5, 0xbf, 0x68, 0xa1, 0x95, 0xd2, 0x92, 0x29, 0x94, + 0x69, 0x01, 0x95, 0x44, 0x49, 0x31, 0x05, 0x94, 0x84, 0x52, 0x5d, 0x10, + 0x37, 0xd0, 0x22, 0xa5, 0x83, 0x2d, 0x69, 0x28, 0x61, 0xc1, 0xc6, 0x09, + 0xc5, 0xe2, 0x62, 0x12, 0x2d, 0xb1, 0x14, 0x8c, 0xc1, 0x46, 0x37, 0xc4, + 0xb8, 0x19, 0x83, 0x52, 0xd4, 0xc4, 0x84, 0x60, 0x43, 0x70, 0x01, 0x26, + 0x9a, 0xe0, 0x42, 0x13, 0xa2, 0x50, 0x0b, 0x36, 0x58, 0x7e, 0x46, 0x17, + 0xca, 0x78, 0xef, 0xf9, 0xce, 0x7d, 0x7d, 0x6f, 0x3a, 0xb5, 0x2c, 0xe8, + 0xe6, 0xeb, 0xbd, 0xef, 0xdc, 0x73, 0xcf, 0xcf, 0x77, 0xcf, 0x39, 0x6d, + 0x54, 0x08, 0xe1, 0x16, 0xc9, 0x74, 0xb5, 0x44, 0x11, 0x32, 0x0a, 0xfc, + 0x12, 0xb2, 0x42, 0x78, 0xca, 0xd5, 0x5a, 0x18, 0x82, 0x7f, 0x56, 0x44, + 0x09, 0x7e, 0x48, 0xab, 0xef, 0x3e, 0xf1, 0xaa, 0x81, 0xef, 0x6e, 0xa1, + 0x30, 0x22, 0x44, 0x52, 0x61, 0x94, 0x71, 0x3d, 0x63, 0x86, 0x31, 0x58, + 0x00, 0x6c, 0x66, 0x7c, 0xc0, 0xfb, 0x77, 0x78, 0x7d, 0x93, 0xf1, 0x6f, + 0xde, 0x37, 0x19, 0x6f, 0xf3, 0xfe, 0xf3, 0x06, 0x30, 0xc1, 0xfb, 0x3f, + 0x4b, 0xd4, 0x76, 0xa9, 0xf5, 0x74, 0x56, 0x24, 0xe5, 0x19, 0x21, 0xc5, + 0x1b, 0xf4, 0xbe, 0x49, 0x90, 0x6c, 0x80, 0xdd, 0xaf, 0x2c, 0x51, 0x72, + 0xbf, 0xe7, 0x91, 0x53, 0xfb, 0x37, 0xb2, 0xd0, 0x3b, 0xeb, 0xaf, 0xe1, + 0x51, 0xe7, 0x96, 0xb6, 0x9c, 0x18, 0xc6, 0xf9, 0x9d, 0x4b, 0xb0, 0xff, + 0x54, 0x4c, 0xf9, 0xef, 0x15, 0x49, 0x46, 0xd1, 0xa8, 0xd0, 0x28, 0x48, + 0x36, 0xea, 0x40, 0x41, 0xfe, 0x97, 0x61, 0xac, 0x3a, 0x43, 0xd0, 0x1b, + 0x70, 0xe8, 0x2d, 0x9d, 0xa3, 0xf7, 0x5a, 0xa1, 0x5d, 0xff, 0x67, 0xac, + 0x3f, 0xb0, 0xa0, 0xfe, 0xae, 0x10, 0xb0, 0x38, 0x96, 0xef, 0x9e, 0xc2, + 0x05, 0xec, 0xdf, 0xb7, 0xa0, 0xfe, 0xc3, 0x96, 0xfd, 0x3a, 0x6e, 0xfa, + 0x3b, 0xb0, 0x1a, 0x62, 0x9f, 0x24, 0x57, 0xe9, 0x78, 0x6a, 0xbf, 0xd9, + 0x3e, 0x17, 0x70, 0x43, 0x8c, 0x20, 0xb5, 0x9b, 0x03, 0xdc, 0x56, 0xa7, + 0xee, 0x2d, 0x12, 0x6e, 0x43, 0xe9, 0x59, 0xee, 0xf7, 0x9e, 0xc7, 0xfe, + 0x8e, 0x08, 0xf0, 0x75, 0x76, 0xe4, 0x46, 0x40, 0x05, 0x26, 0x9b, 0xed, + 0x0e, 0xb2, 0x7e, 0xa4, 0x55, 0x24, 0x83, 0x38, 0x3f, 0x61, 0x2a, 0xfb, + 0x2e, 0xcb, 0xfc, 0xa9, 0xb5, 0x4b, 0x24, 0x23, 0x4e, 0x3f, 0x3e, 0x14, + 0x90, 0x5b, 0xb4, 0x1c, 0xbb, 0xef, 0x76, 0x63, 0x5d, 0xf5, 0x71, 0x94, + 0xe4, 0x4f, 0xa6, 0xb5, 0x1f, 0x6a, 0x5f, 0xbe, 0x83, 0x08, 0xf4, 0x88, + 0x1a, 0x3f, 0x5d, 0x86, 0x38, 0xc9, 0x4b, 0x1b, 0xb5, 0x3e, 0xfc, 0x9c, + 0x58, 0xa6, 0xf9, 0x85, 0x75, 0xb7, 0x97, 0xa0, 0xbc, 0x73, 0x48, 0xd9, + 0x1b, 0x11, 0xbb, 0x0c, 0x65, 0x88, 0xc1, 0xfe, 0xb9, 0xfc, 0xe6, 0x17, + 0x90, 0xff, 0xa6, 0xda, 0x24, 0xdb, 0xba, 0x9b, 0x71, 0xae, 0x24, 0x0e, + 0x1c, 0x89, 0x7b, 0x14, 0xc4, 0xba, 0x07, 0x68, 0xb9, 0xf2, 0xd7, 0xd5, + 0x7e, 0x92, 0x4b, 0x36, 0x6a, 0xfe, 0xea, 0xb8, 0x2b, 0x7f, 0xdf, 0xc9, + 0x5a, 0xfc, 0xaf, 0x45, 0x7c, 0x6e, 0x2e, 0x53, 0xf2, 0x32, 0x48, 0x35, + 0xb8, 0xa7, 0x23, 0x91, 0x8f, 0xff, 0x6f, 0xdb, 0xf8, 0xff, 0x68, 0x79, + 0xdc, 0x40, 0xfe, 0x6f, 0xe0, 0x38, 0x2c, 0x61, 0xbe, 0x2c, 0xce, 0xc3, + 0x97, 0x08, 0xfd, 0x7e, 0xab, 0x35, 0x4a, 0x71, 0xdc, 0x86, 0xfd, 0xe3, + 0x6d, 0xe7, 0x10, 0xef, 0x2d, 0x14, 0x07, 0x11, 0x38, 0xfa, 0x39, 0x4e, + 0x75, 0x86, 0xd4, 0xfa, 0xb5, 0x96, 0xee, 0x2f, 0xb1, 0xee, 0x72, 0xa9, + 0xf5, 0x0e, 0x73, 0xf7, 0x38, 0xe4, 0x3d, 0x83, 0x51, 0x8a, 0xdf, 0x36, + 0xbe, 0x65, 0x8b, 0xab, 0x40, 0x41, 0xca, 0x3b, 0x48, 0x4b, 0x73, 0x82, + 0xbe, 0x47, 0xc5, 0xb1, 0x34, 0xbe, 0xef, 0x0f, 0x52, 0x7d, 0x90, 0xfe, + 0x91, 0x5c, 0x49, 0xc2, 0x8b, 0xf3, 0xa9, 0x61, 0x3f, 0xf9, 0x3b, 0x75, + 0x56, 0xad, 0xb7, 0xc6, 0xa6, 0x20, 0x1f, 0x4b, 0x0c, 0xb1, 0x62, 0x03, + 0xf1, 0xbb, 0x65, 0x40, 0x9e, 0xe9, 0x15, 0x70, 0x53, 0xfe, 0x0a, 0x84, + 0xd9, 0x06, 0x7c, 0x8b, 0xbe, 0xff, 0x53, 0x90, 0xa2, 0x78, 0x6d, 0x0c, + 0xbb, 0xcf, 0xe9, 0xf8, 0x30, 0x46, 0xb4, 0x5f, 0xc0, 0x47, 0xe5, 0xef, + 0x90, 0xa9, 0x79, 0xcb, 0x79, 0x6b, 0x98, 0x8f, 0xb7, 0xc0, 0xb6, 0x3a, + 0xa0, 0xb7, 0x56, 0xc9, 0x79, 0xf2, 0xf0, 0xd7, 0x99, 0x17, 0xce, 0xab, + 0x8d, 0x67, 0x04, 0x92, 0x5f, 0x0e, 0xbe, 0x49, 0x3e, 0x53, 0x5d, 0x92, + 0xf1, 0xd4, 0xbc, 0x51, 0x8a, 0x7c, 0xe2, 0x0d, 0xd6, 0x97, 0x60, 0xbf, + 0x7a, 0xd9, 0xaf, 0xe9, 0x80, 0x8e, 0xbb, 0xf6, 0x07, 0x78, 0xcc, 0x04, + 0xbf, 0x3a, 0x12, 0xda, 0x2f, 0x27, 0x7f, 0xd9, 0x9e, 0xd4, 0xb7, 0x35, + 0xf8, 0xa5, 0xaa, 0x16, 0x68, 0xf9, 0x59, 0x47, 0xef, 0x25, 0x5c, 0x36, + 0xae, 0xed, 0x50, 0x79, 0xfd, 0x4b, 0xe6, 0x15, 0xf9, 0x39, 0x99, 0xb6, + 0xbf, 0xd3, 0xca, 0x3c, 0xef, 0xd4, 0xf9, 0x6e, 0xb4, 0xff, 0xfb, 0x43, + 0x54, 0x88, 0x5a, 0xae, 0x4c, 0x3a, 0xdf, 0x05, 0xf8, 0xef, 0xb3, 0x78, + 0x54, 0xb2, 0x96, 0xe3, 0xc4, 0x58, 0xba, 0x4e, 0xe9, 0x6b, 0x67, 0xfd, + 0x4d, 0xac, 0xdf, 0xb4, 0xbd, 0x4b, 0x65, 0xdf, 0x93, 0xd6, 0x7b, 0xd4, + 0xf9, 0x99, 0x7d, 0x97, 0x3a, 0x4e, 0x74, 0x7f, 0xec, 0xca, 0xa4, 0x3a, + 0x5f, 0xb5, 0xc0, 0x3b, 0x2d, 0xb6, 0xf4, 0xfd, 0x68, 0xbd, 0x47, 0xf5, + 0x3d, 0x28, 0x5e, 0xe0, 0xa5, 0xb3, 0xde, 0xfc, 0x29, 0xeb, 0x0d, 0xf9, + 0xe1, 0x37, 0xcf, 0x71, 0x7d, 0x19, 0x50, 0xf7, 0x94, 0xb3, 0xdd, 0xe5, + 0xba, 0xce, 0x4b, 0xbb, 0xb9, 0x0e, 0xed, 0xb4, 0xd7, 0x13, 0x8f, 0xad, + 0x2e, 0xa8, 0xb5, 0x2b, 0x4f, 0x9f, 0x74, 0xc4, 0x33, 0x29, 0x22, 0x98, + 0x03, 0x92, 0x11, 0x25, 0x7f, 0x4f, 0xcc, 0xad, 0x2b, 0xb9, 0xf6, 0x23, + 0x1e, 0x9d, 0x46, 0x88, 0xe4, 0xae, 0xf7, 0xab, 0x73, 0xd7, 0xac, 0x3e, + 0x8e, 0x3a, 0x73, 0x91, 0xed, 0x5d, 0xcc, 0xf6, 0x4a, 0x7d, 0x8d, 0xc4, + 0x53, 0xff, 0xf5, 0x7e, 0xbb, 0xbd, 0x77, 0x1e, 0xce, 0x7f, 0x9f, 0x33, + 0xef, 0xfd, 0xdc, 0x6f, 0xb8, 0x4f, 0xfa, 0x77, 0x7f, 0xa5, 0xed, 0xe1, + 0x7b, 0x23, 0xfa, 0x7e, 0x93, 0xf2, 0x32, 0x39, 0xa0, 0xce, 0x87, 0x05, + 0xd3, 0x44, 0xf4, 0xd5, 0xa3, 0xae, 0x4d, 0xef, 0x81, 0xfd, 0x7d, 0x75, + 0xea, 0xfe, 0x16, 0x81, 0x7e, 0xe3, 0x96, 0x21, 0x45, 0x7d, 0xbf, 0x38, + 0x9c, 0x2f, 0x8f, 0x5f, 0xb3, 0xdc, 0x38, 0xfb, 0x15, 0x65, 0xbf, 0x36, + 0x4b, 0xbf, 0x28, 0xee, 0xfc, 0x3d, 0x9f, 0xdf, 0x6c, 0xa7, 0xd0, 0xfd, + 0x9b, 0xcf, 0x91, 0x5c, 0x0f, 0xcb, 0xb9, 0xe7, 0xed, 0xdb, 0x99, 0xe5, + 0x54, 0x87, 0x4f, 0x1f, 0xa6, 0x7a, 0x1a, 0xb2, 0xf8, 0xe6, 0xb4, 0x6f, + 0xe2, 0x31, 0xc4, 0x51, 0xc9, 0x2d, 0x12, 0x7b, 0xc3, 0xf3, 0xc5, 0xcb, + 0xad, 0xb6, 0xc7, 0x66, 0xc6, 0x75, 0xbc, 0x4d, 0xf2, 0x73, 0x72, 0x80, + 0xe6, 0xc2, 0x9c, 0x38, 0x1a, 0xb6, 0x38, 0x42, 0x1e, 0xf3, 0x4a, 0xbe, + 0xf8, 0xe5, 0xeb, 0x8b, 0x9f, 0x3e, 0xd4, 0x7c, 0x3a, 0xe2, 0xd5, 0xf6, + 0x2b, 0x5c, 0x65, 0xe5, 0xf3, 0x00, 0xcf, 0x23, 0x19, 0x93, 0x7e, 0x89, + 0x4f, 0xa7, 0x68, 0x69, 0x56, 0x9c, 0x51, 0x72, 0x2b, 0xe2, 0x07, 0xd8, + 0xce, 0xcb, 0x2e, 0xf8, 0xd1, 0xb3, 0x07, 0xeb, 0x2b, 0x5c, 0xdf, 0xee, + 0x72, 0x9d, 0xda, 0xee, 0x07, 0x4e, 0xd7, 0x93, 0x7f, 0xf1, 0x03, 0xe7, + 0xb5, 0x7e, 0xd2, 0x6b, 0x66, 0x38, 0x3e, 0x2f, 0xba, 0xd8, 0xee, 0x1a, + 0xca, 0x47, 0xfc, 0x0e, 0xbd, 0x4f, 0xb7, 0x68, 0x5d, 0xaa, 0xb0, 0x42, + 0xc6, 0x81, 0xed, 0x59, 0x0f, 0xec, 0xf0, 0x71, 0x5c, 0x1b, 0x72, 0xf3, + 0x85, 0x6d, 0x6f, 0x0d, 0x9f, 0xef, 0xc4, 0xda, 0xc7, 0xf5, 0x65, 0x94, + 0xed, 0x7a, 0xaf, 0x1e, 0x18, 0x6e, 0x40, 0x7f, 0x9c, 0x34, 0x15, 0x46, + 0xe2, 0x03, 0xe3, 0xf0, 0xa7, 0x77, 0x23, 0xfc, 0xbd, 0xc7, 0x71, 0x60, + 0x0c, 0x9f, 0x1a, 0xa4, 0xbe, 0x19, 0x1e, 0x42, 0x7f, 0x0d, 0x7b, 0x07, + 0xe1, 0x47, 0x6f, 0x06, 0xeb, 0x7b, 0xcf, 0x02, 0x1f, 0x3c, 0x87, 0x73, + 0x07, 0x0f, 0x73, 0x7c, 0x36, 0xe6, 0x3f, 0xd7, 0x73, 0x1f, 0x72, 0x7d, + 0xf5, 0xd4, 0xe7, 0xc7, 0xb8, 0xef, 0x8a, 0x04, 0xf7, 0xf9, 0x0c, 0xaf, + 0xf7, 0x71, 0x1f, 0xb9, 0xcd, 0x7d, 0xb2, 0x37, 0xa7, 0x4f, 0x4e, 0xa1, + 0x6e, 0x8e, 0x65, 0x52, 0x6a, 0x43, 0xd6, 0xaf, 0x42, 0xdd, 0x1f, 0x15, + 0x06, 0xe2, 0x65, 0x9c, 0xaf, 0x92, 0x35, 0xc0, 0x91, 0x35, 0xe8, 0x6b, + 0xbd, 0x87, 0x38, 0x2e, 0x2d, 0x94, 0x9f, 0x95, 0x33, 0xe3, 0x9a, 0x0f, + 0x34, 0x3f, 0x3d, 0xd4, 0xbc, 0x43, 0xfd, 0xca, 0x58, 0xf5, 0x76, 0x8a, + 0xec, 0xab, 0x1a, 0xcb, 0x90, 0x7c, 0xa5, 0x28, 0x26, 0x7e, 0x55, 0x84, + 0x67, 0x60, 0x6f, 0x7c, 0x94, 0xfd, 0xec, 0x7f, 0x06, 0x78, 0x88, 0xf3, + 0xac, 0xf3, 0x77, 0x75, 0x9d, 0x49, 0xe7, 0x26, 0x07, 0x60, 0xb7, 0xe6, + 0x7d, 0xee, 0x9c, 0xa7, 0xf3, 0x5e, 0xd1, 0x4c, 0x6b, 0xd1, 0x73, 0x50, + 0xdd, 0x13, 0x92, 0xf9, 0x52, 0x76, 0xc9, 0x58, 0x70, 0x7f, 0x74, 0xf2, + 0x41, 0xf1, 0x45, 0xf3, 0xd2, 0xce, 0x23, 0x3b, 0x4f, 0x9c, 0xfc, 0x08, + 0x53, 0x3d, 0x97, 0x8f, 0x97, 0xfa, 0xa7, 0x37, 0x3e, 0x3a, 0xfc, 0xff, + 0xf1, 0x3a, 0x85, 0x78, 0xc5, 0xd9, 0x6e, 0x33, 0x41, 0x73, 0xd6, 0x13, + 0x62, 0x88, 0xf3, 0x35, 0x55, 0xcf, 0xef, 0xb5, 0x06, 0xf9, 0xea, 0x7f, + 0x1a, 0xf6, 0xf4, 0xf3, 0x3b, 0xf9, 0x83, 0xfb, 0x39, 0xf2, 0xec, 0x33, + 0xbb, 0xc7, 0x39, 0xaf, 0xcc, 0xb7, 0x7d, 0x1c, 0x87, 0xdb, 0x88, 0x83, + 0xa9, 0xe3, 0x90, 0xb0, 0xe2, 0xa0, 0xeb, 0x83, 0x5d, 0x4f, 0x91, 0xe4, + 0x0b, 0xd5, 0x19, 0xf3, 0x2a, 0xcd, 0x27, 0x1e, 0xf6, 0x5b, 0xca, 0x35, + 0x2b, 0xff, 0xc2, 0xec, 0x5f, 0x48, 0xec, 0x5d, 0x69, 0x3f, 0x17, 0xe4, + 0x73, 0x01, 0x79, 0x0e, 0xfb, 0x78, 0x8f, 0xe6, 0x3c, 0xf1, 0x55, 0x71, + 0xd4, 0x7a, 0x73, 0xdf, 0x9d, 0x3d, 0x9e, 0x54, 0x51, 0xe9, 0x07, 0x75, + 0x46, 0xe6, 0x8d, 0xea, 0x91, 0x69, 0xd5, 0x99, 0xbb, 0x54, 0x7f, 0x03, + 0xa7, 0xfb, 0x50, 0x17, 0x4e, 0xf7, 0x9d, 0xe1, 0xfe, 0xc7, 0x71, 0x69, + 0xa7, 0xb9, 0x58, 0xc6, 0xae, 0xc6, 0x59, 0x67, 0x9c, 0x76, 0x54, 0xd9, + 0xec, 0xd0, 0xf7, 0xce, 0xd7, 0x97, 0x31, 0xaf, 0x6d, 0xa2, 0xbe, 0xec, + 0xb7, 0xe6, 0x49, 0x67, 0xbd, 0xf7, 0x3f, 0x72, 0xbd, 0xdf, 0xde, 0x6c, + 0xd7, 0x5f, 0x2b, 0x26, 0xd2, 0xd0, 0xdf, 0xce, 0xfd, 0x72, 0x17, 0xbf, + 0xdb, 0xeb, 0x81, 0x08, 0xdd, 0xd7, 0xf5, 0x32, 0xf9, 0x27, 0x4a, 0x83, + 0xf0, 0xa7, 0x6b, 0x2b, 0xbe, 0x77, 0x85, 0xb0, 0x5f, 0x19, 0xc2, 0xdf, + 0x5b, 0xed, 0x3e, 0x93, 0xe4, 0x2b, 0x43, 0xc0, 0x52, 0x7e, 0xef, 0x13, + 0xd6, 0x5c, 0x0c, 0x3c, 0xe9, 0xb5, 0xcf, 0x8f, 0x6e, 0x71, 0xc1, 0x8b, + 0xf7, 0x2f, 0x1a, 0x30, 0x07, 0xb6, 0xd6, 0x99, 0xf4, 0xbd, 0xa3, 0x01, + 0xfd, 0x12, 0xf5, 0x75, 0xf6, 0xef, 0x33, 0x9e, 0x2b, 0x2b, 0x67, 0xe7, + 0x67, 0xfb, 0x7c, 0x5d, 0x18, 0x1f, 0xb5, 0xe6, 0x5c, 0x7d, 0x9f, 0xfd, + 0xfd, 0x28, 0xbd, 0xb4, 0x94, 0x73, 0xaa, 0x7d, 0xbe, 0x76, 0xe9, 0x79, + 0x87, 0xe7, 0xd1, 0x62, 0x71, 0x29, 0x0d, 0xbf, 0x26, 0xd2, 0xf9, 0xde, + 0xa1, 0xba, 0x4f, 0xeb, 0x83, 0xdd, 0xda, 0x8f, 0x59, 0xfd, 0xb8, 0x7f, + 0x0f, 0xdb, 0xf9, 0x1b, 0xfd, 0x5d, 0x5c, 0xca, 0xfe, 0x28, 0xbd, 0xd8, + 0xdf, 0xcc, 0xf3, 0x7e, 0xd2, 0x5a, 0x3b, 0xe7, 0xf4, 0x76, 0xb2, 0xab, + 0x88, 0xfb, 0x69, 0xa9, 0xad, 0xdf, 0x43, 0xbe, 0xa4, 0x09, 0x38, 0xd2, + 0xa4, 0xf3, 0xa0, 0xf3, 0xa5, 0xf3, 0x83, 0x3c, 0x96, 0xae, 0x26, 0xb1, + 0x96, 0xae, 0xd5, 0xf4, 0x60, 0x9b, 0xba, 0x66, 0x9c, 0xff, 0x3f, 0xd8, + 0x1e, 0x53, 0xf2, 0x6f, 0x8a, 0xef, 0x63, 0x68, 0x80, 0x3f, 0x31, 0xce, + 0xce, 0xc5, 0x9c, 0x00, 0x6b, 0x1e, 0xc1, 0x7d, 0x17, 0x3c, 0xbc, 0xdd, + 0xac, 0xe7, 0x46, 0x67, 0xff, 0xfe, 0x90, 0xea, 0xf2, 0xd9, 0x7f, 0x73, + 0xe7, 0xce, 0xd9, 0xf9, 0x51, 0xfb, 0xa9, 0xe4, 0x1b, 0x99, 0x8f, 0x7e, + 0xd1, 0xba, 0x09, 0x7f, 0x6f, 0x87, 0x7d, 0xe0, 0x7d, 0xd8, 0x67, 0xcf, + 0x97, 0xe4, 0x45, 0x21, 0x3d, 0xf0, 0xc5, 0x45, 0x85, 0xe4, 0xcf, 0xf1, + 0xcb, 0xdf, 0xd1, 0xe7, 0x8f, 0x46, 0x83, 0xd8, 0x2f, 0x6b, 0x85, 0x7a, + 0x37, 0xf1, 0xd6, 0x25, 0x8e, 0x82, 0xd7, 0x1f, 0x8c, 0x00, 0xdf, 0x17, + 0x2f, 0x41, 0x4f, 0xd1, 0x11, 0xea, 0x73, 0xfe, 0x32, 0x84, 0x35, 0x35, + 0xca, 0x7c, 0x2d, 0x37, 0xe8, 0xff, 0x65, 0x59, 0x11, 0xe2, 0xff, 0xab, + 0xf0, 0xbb, 0x03, 0x4f, 0xdd, 0xb6, 0x7c, 0x2f, 0xc4, 0x5b, 0xaa, 0x1f, + 0x92, 0x97, 0x38, 0xce, 0xfc, 0xf5, 0xe7, 0xf2, 0x57, 0xc7, 0xa5, 0xdc, + 0xc8, 0xcb, 0xd7, 0xb5, 0x4e, 0xbe, 0x7a, 0x99, 0xaf, 0xf7, 0xad, 0xfe, + 0x36, 0x57, 0x2f, 0xfe, 0xae, 0xb8, 0xf4, 0xd8, 0xf8, 0x0b, 0xdc, 0x5c, + 0xab, 0xee, 0x2f, 0x9b, 0x33, 0x77, 0x56, 0x0b, 0x7b, 0x3d, 0x3a, 0x24, + 0xf3, 0xfd, 0x1f, 0xfe, 0xac, 0x5e, 0x92, 0x80, 0x14, 0x00, 0x00, 0x00 }; static u8 bnx2_TPAT_b06FwText[] = { - 0xbd, 0x59, 0x6f, 0x70, 0x5c, 0xd5, 0x7d, 0x3d, 0x6f, 0xf7, 0xed, 0xee, - 0x93, 0xb4, 0x92, 0x9e, 0x90, 0x0c, 0xab, 0x56, 0x8d, 0xf6, 0x59, 0x6f, - 0xa5, 0xc5, 0xab, 0xd8, 0x6f, 0x2d, 0xb9, 0xac, 0x87, 0x37, 0xcd, 0xb3, - 0x2c, 0x29, 0x8b, 0xec, 0xd8, 0xeb, 0x42, 0x66, 0xe4, 0x09, 0x1d, 0x0b, - 0x59, 0xd8, 0xc2, 0x18, 0xa2, 0x12, 0x3e, 0xa8, 0x13, 0x4f, 0xbd, 0xe8, - 0x9f, 0x85, 0xbd, 0xd2, 0x23, 0x02, 0x2c, 0x3b, 0x93, 0x0e, 0x1e, 0xf9, - 0x8f, 0x18, 0x58, 0x6b, 0xa1, 0xfd, 0x92, 0x69, 0xc3, 0x44, 0x13, 0x1b, - 0xec, 0x90, 0x38, 0x4e, 0xa7, 0x5f, 0xcc, 0xb4, 0x9d, 0xaa, 0x80, 0x29, - 0x50, 0x70, 0xdc, 0xce, 0xa4, 0x63, 0x0a, 0xf5, 0xed, 0xb9, 0x6f, 0x57, - 0x46, 0x38, 0x4e, 0x3f, 0xd6, 0x33, 0x8b, 0x76, 0xef, 0x7b, 0xf7, 0xde, - 0xdf, 0xbd, 0xbf, 0x73, 0xce, 0xef, 0xdc, 0xcb, 0x6a, 0x1f, 0xca, 0x51, - 0xfa, 0x57, 0xc9, 0x4f, 0xfb, 0x23, 0x43, 0x4f, 0x6f, 0x58, 0x6b, 0xad, - 0x95, 0xbf, 0x95, 0x00, 0x54, 0xfc, 0x3f, 0xfe, 0xf3, 0x03, 0xfa, 0x72, - 0x1c, 0xf2, 0x03, 0xcd, 0x67, 0x2f, 0xae, 0xee, 0x30, 0xa1, 0xf9, 0xed, - 0x87, 0x5a, 0x76, 0x9b, 0x80, 0x93, 0x4f, 0x44, 0x37, 0xe3, 0x7f, 0x44, - 0xb6, 0x4e, 0x85, 0x6c, 0xff, 0x23, 0xfb, 0x8b, 0x75, 0x6f, 0xdc, 0x67, - 0x5c, 0x3f, 0xe1, 0x87, 0xa6, 0xdb, 0x93, 0x9a, 0xde, 0x0c, 0xad, 0x81, - 0x7d, 0x7e, 0xd4, 0xb2, 0x2b, 0x88, 0xaa, 0xe5, 0xb1, 0x80, 0x93, 0x39, - 0xc3, 0xda, 0x83, 0x84, 0x7e, 0x8e, 0x0b, 0x72, 0x38, 0xc7, 0x99, 0x3c, - 0x70, 0x28, 0xa7, 0xe0, 0x2a, 0xc7, 0x1c, 0xcf, 0x6b, 0x58, 0xf2, 0x7b, - 0xd3, 0xf5, 0x95, 0xd9, 0xc8, 0x98, 0x53, 0x07, 0x45, 0xc8, 0x44, 0xf6, - 0x0f, 0x6c, 0x33, 0x7e, 0x08, 0xe1, 0xd4, 0x5c, 0x3b, 0x32, 0xab, 0xcf, - 0x6a, 0xd8, 0xe9, 0x36, 0xf4, 0x69, 0x36, 0xf8, 0x8e, 0x82, 0xd4, 0x7d, - 0x1a, 0x7a, 0x0b, 0x71, 0x64, 0x0b, 0x59, 0x38, 0x85, 0x31, 0x7e, 0x34, - 0x84, 0xa6, 0x34, 0x6d, 0xdd, 0xd4, 0xdd, 0xf2, 0x1d, 0x84, 0xa7, 0xae, - 0x8b, 0x6b, 0x49, 0x1d, 0x6f, 0x6f, 0x14, 0xa2, 0xd2, 0x46, 0xb6, 0xa2, - 0x3d, 0x0b, 0xbf, 0x6d, 0x58, 0x5b, 0xfc, 0x0a, 0x3a, 0xbf, 0x6e, 0xc6, - 0xa7, 0x94, 0x07, 0x1f, 0xf4, 0xd9, 0xd0, 0x14, 0x3b, 0xaa, 0x35, 0xe5, - 0x1b, 0x30, 0x51, 0xd0, 0x71, 0xa8, 0x50, 0x87, 0xb1, 0x02, 0x0e, 0xf8, - 0x37, 0x04, 0x31, 0xa7, 0xc3, 0xf9, 0x4e, 0xcb, 0x01, 0xec, 0xcb, 0x0d, - 0x63, 0x77, 0x2e, 0x85, 0xc3, 0x05, 0x19, 0x63, 0x14, 0xa3, 0x05, 0x15, - 0xc1, 0x29, 0x23, 0xf2, 0x73, 0xdc, 0xe9, 0x99, 0x10, 0x63, 0x56, 0x08, - 0x23, 0x56, 0x1c, 0xe3, 0xae, 0x8f, 0xeb, 0x0c, 0x61, 0xd4, 0xbc, 0x21, - 0x06, 0x2c, 0xc3, 0x1a, 0x87, 0x68, 0x3c, 0x6f, 0x19, 0x91, 0x4e, 0x3f, - 0x9c, 0xef, 0x9b, 0x11, 0x8c, 0x33, 0xf6, 0x31, 0xaf, 0xdf, 0x18, 0x3a, - 0x6f, 0xf5, 0x73, 0xd8, 0x4f, 0xc7, 0xc4, 0x57, 0xfb, 0x46, 0xc7, 0x91, - 0x88, 0x4c, 0xc0, 0x87, 0xbe, 0xba, 0x56, 0xf6, 0x6b, 0x8a, 0x4e, 0xc0, - 0x88, 0x73, 0x9c, 0x6c, 0xb0, 0xdd, 0xe1, 0x18, 0x59, 0xf6, 0x37, 0xa2, - 0x67, 0x20, 0xc7, 0x6a, 0xe0, 0xef, 0x76, 0xf6, 0x57, 0xe0, 0xb3, 0x63, - 0xd1, 0x11, 0xf6, 0x39, 0x67, 0xa9, 0x78, 0x93, 0x9f, 0x3e, 0xdd, 0x90, - 0x99, 0x55, 0x42, 0x6c, 0x3f, 0x04, 0x3e, 0x37, 0x2b, 0x70, 0x22, 0x63, - 0x61, 0x84, 0xeb, 0xd6, 0xd8, 0x36, 0xc9, 0xb6, 0x80, 0x69, 0x71, 0x7c, - 0xe8, 0x9d, 0x85, 0x95, 0x98, 0x58, 0xce, 0xcd, 0xef, 0x6b, 0xe7, 0x18, - 0x6e, 0x31, 0xa7, 0xf2, 0x9d, 0xcd, 0xee, 0x4d, 0xf1, 0x88, 0xba, 0xf2, - 0xf9, 0xb0, 0xd2, 0xc1, 0x36, 0x47, 0x6d, 0xc0, 0x21, 0x17, 0x5a, 0xd0, - 0xd4, 0x38, 0x8f, 0x86, 0xf7, 0x72, 0xc3, 0x4a, 0x77, 0xc1, 0x51, 0xba, - 0xe6, 0x3b, 0x14, 0x67, 0x5e, 0x55, 0x3a, 0x67, 0x65, 0xdc, 0x42, 0x3c, - 0x6b, 0x29, 0x8c, 0xf9, 0x07, 0x32, 0x5e, 0x27, 0xaa, 0xdc, 0x14, 0x6b, - 0x62, 0x3e, 0x54, 0x98, 0xdd, 0xca, 0x96, 0x79, 0x21, 0xd2, 0xc9, 0xb4, - 0xd2, 0x33, 0x0f, 0x2d, 0x6c, 0xdb, 0x5a, 0x6e, 0xea, 0x30, 0xb2, 0xab, - 0x4c, 0x1c, 0x77, 0xa3, 0xb8, 0x64, 0xf9, 0x70, 0x62, 0x55, 0x19, 0x54, - 0x53, 0xe1, 0x07, 0xe1, 0xcb, 0x16, 0xd4, 0x2a, 0x7e, 0xbf, 0xb6, 0x43, - 0xc5, 0x58, 0x7b, 0x8f, 0xd2, 0xc9, 0x3e, 0x01, 0xe6, 0xf9, 0x74, 0x2e, - 0x8d, 0x30, 0xb1, 0x53, 0x61, 0xc7, 0x22, 0x79, 0xee, 0xcd, 0xdb, 0x56, - 0x2c, 0xfe, 0xb8, 0xc4, 0x63, 0x8d, 0x11, 0x91, 0x7b, 0x53, 0x69, 0xc7, - 0xe2, 0x67, 0xb9, 0x0f, 0x7e, 0x53, 0xc5, 0xaf, 0xac, 0x00, 0x16, 0x77, - 0x58, 0xcc, 0xa9, 0x8e, 0x20, 0xdb, 0xcf, 0x78, 0xed, 0xf2, 0x37, 0xf4, - 0xae, 0xaf, 0xec, 0x43, 0x71, 0x0f, 0x46, 0xdd, 0x26, 0xc6, 0x5c, 0xdc, - 0x83, 0xed, 0x5c, 0xef, 0xbf, 0x06, 0xe4, 0xd7, 0xaf, 0xdd, 0x6a, 0xdb, - 0xc9, 0x38, 0x7d, 0xb6, 0xb9, 0xb8, 0xda, 0x5f, 0x0f, 0xd4, 0xb6, 0xe3, - 0x30, 0x73, 0xdc, 0x99, 0xbc, 0x1b, 0x59, 0xef, 0x79, 0x9d, 0xbe, 0x65, - 0xb6, 0x16, 0x7d, 0xab, 0xbc, 0x7d, 0xd3, 0xb7, 0xcd, 0x0a, 0xf1, 0x66, - 0x32, 0x88, 0xb3, 0xe6, 0x48, 0xa4, 0x12, 0x59, 0xcb, 0xcf, 0x7c, 0x5f, - 0xe0, 0xfc, 0xf9, 0xa4, 0x1f, 0x27, 0x93, 0x27, 0x90, 0xad, 0x01, 0xe6, - 0x72, 0x92, 0x57, 0xc6, 0xe2, 0x05, 0xfe, 0xd7, 0x57, 0x90, 0xeb, 0xb3, - 0xb8, 0x3e, 0x05, 0x67, 0x4c, 0x89, 0x69, 0x4b, 0x6b, 0x26, 0xbf, 0xf6, - 0x71, 0x3f, 0xeb, 0xdb, 0xc3, 0xc4, 0x27, 0xf0, 0x6e, 0x6e, 0x00, 0x3b, - 0x8b, 0xb1, 0xe0, 0x46, 0x8e, 0xc2, 0xd2, 0x96, 0xc6, 0x89, 0xe2, 0x6f, - 0x72, 0x3c, 0xad, 0x75, 0xe4, 0x8c, 0x4c, 0x1a, 0x89, 0x8b, 0x1d, 0x8a, - 0xec, 0x9f, 0xd6, 0xd6, 0xe4, 0x83, 0x88, 0xd6, 0x16, 0x9f, 0x57, 0xd8, - 0x5b, 0xb5, 0xc7, 0xa7, 0x14, 0xec, 0x8d, 0xc9, 0x67, 0x5b, 0xb5, 0x96, - 0x3c, 0xb4, 0x4a, 0x7b, 0x48, 0x3b, 0x3b, 0x65, 0xf4, 0xbd, 0xac, 0x24, - 0xa2, 0x53, 0x5e, 0x9f, 0x21, 0xad, 0x35, 0x1f, 0xe2, 0x7a, 0xe2, 0xcc, - 0x09, 0xb4, 0x2a, 0xfb, 0x69, 0xed, 0x57, 0x7c, 0x70, 0xd1, 0xeb, 0xf3, - 0xb4, 0x16, 0xcf, 0xcb, 0x76, 0xc3, 0x8a, 0x2a, 0x21, 0xdc, 0x9b, 0xd4, - 0xb0, 0xa6, 0x45, 0x34, 0x76, 0x25, 0x8d, 0xc5, 0x2e, 0x7f, 0x04, 0xc7, - 0xc9, 0x05, 0xe2, 0xce, 0xf9, 0xc3, 0x96, 0x31, 0x74, 0x15, 0xfc, 0x88, - 0xd6, 0x38, 0x38, 0xe2, 0x86, 0xf0, 0x33, 0xe2, 0xbf, 0xdb, 0xd2, 0x31, - 0xe6, 0x1a, 0xf1, 0x5f, 0x20, 0x91, 0x3a, 0xc5, 0x9c, 0x2d, 0x91, 0x03, - 0x47, 0x0a, 0x4d, 0xf1, 0x53, 0x30, 0x06, 0xbb, 0xc8, 0x01, 0xad, 0x5d, - 0xc6, 0x00, 0x5d, 0xb5, 0xc9, 0x9d, 0x42, 0x03, 0x72, 0xe4, 0x43, 0x97, - 0xc7, 0xab, 0x61, 0xa5, 0xb3, 0xf0, 0x4b, 0x6a, 0x6b, 0x37, 0xf1, 0x85, - 0xea, 0x88, 0x19, 0x44, 0xaa, 0x36, 0x8a, 0xf3, 0xc4, 0x4a, 0xb6, 0xae, - 0x8c, 0xb9, 0x94, 0xf9, 0x7c, 0x87, 0xcf, 0x7b, 0x94, 0xcd, 0xf3, 0x51, - 0xfc, 0xcc, 0xfa, 0x42, 0x38, 0x75, 0x95, 0x6c, 0x0b, 0xac, 0x68, 0xd7, - 0x70, 0xf5, 0x85, 0x72, 0x7c, 0xfc, 0x42, 0x18, 0x9f, 0xbd, 0x40, 0x7e, - 0xbb, 0x68, 0x2f, 0x87, 0x10, 0xa9, 0x36, 0x21, 0x0a, 0x56, 0x2b, 0xde, - 0xab, 0x89, 0x45, 0xaf, 0x40, 0x6a, 0xa3, 0xa3, 0xed, 0xce, 0x19, 0x43, - 0x83, 0x48, 0x38, 0xe7, 0xbc, 0xbd, 0x70, 0xb4, 0xb5, 0xf9, 0xf3, 0x02, - 0x3b, 0x8a, 0x7b, 0x11, 0xb4, 0x3b, 0xb5, 0xb7, 0x98, 0x9b, 0xcb, 0x5e, - 0x6e, 0x3a, 0xb5, 0x75, 0xf9, 0xfb, 0xfd, 0x28, 0x2f, 0x3e, 0x53, 0xed, - 0x8c, 0x36, 0x96, 0x33, 0x7a, 0x27, 0xb9, 0xbe, 0x01, 0xaf, 0x6f, 0x46, - 0x4b, 0x70, 0xef, 0x97, 0x4a, 0xb9, 0xa9, 0xb4, 0x1f, 0xe2, 0x3e, 0x33, - 0xf7, 0xde, 0x3e, 0x3e, 0xc4, 0x3d, 0x96, 0xf3, 0x0d, 0xdf, 0x36, 0xdf, - 0x30, 0xe7, 0x7b, 0x79, 0xc5, 0x7c, 0x07, 0x56, 0xcc, 0x77, 0x60, 0xc5, - 0x7c, 0x29, 0x72, 0xf5, 0x1f, 0xc4, 0x48, 0x5d, 0x71, 0x6c, 0xd5, 0x1e, - 0xbc, 0x6d, 0xee, 0x41, 0xce, 0x7d, 0x54, 0x2c, 0x65, 0x8a, 0xe3, 0x54, - 0xda, 0xfb, 0x57, 0xcc, 0xbd, 0x9f, 0x73, 0x2f, 0x8f, 0xa3, 0x53, 0x8b, - 0x84, 0xd8, 0x66, 0x09, 0xa1, 0xda, 0xa6, 0xde, 0x89, 0xe6, 0x4c, 0x27, - 0xb1, 0x53, 0x8e, 0xc4, 0xa2, 0x0f, 0xe6, 0x70, 0xbd, 0x3f, 0x80, 0xa5, - 0x9a, 0x65, 0x6e, 0x54, 0x96, 0xfe, 0xbe, 0xa4, 0x80, 0x5a, 0xff, 0x6a, - 0xae, 0x9a, 0x63, 0xc4, 0xf4, 0x01, 0x45, 0x88, 0x73, 0x1b, 0x13, 0x83, - 0x7e, 0x24, 0xfa, 0xaa, 0x60, 0x12, 0x43, 0x81, 0x12, 0x17, 0x56, 0xf6, - 0x79, 0xd9, 0xeb, 0x53, 0xf0, 0xfa, 0x08, 0xf1, 0xee, 0x86, 0x0f, 0xc5, - 0x1b, 0x2d, 0x75, 0xf8, 0x29, 0x39, 0xf9, 0x5a, 0x61, 0x59, 0x57, 0xa4, - 0x6e, 0xc0, 0x77, 0xce, 0x0a, 0x32, 0xa6, 0x91, 0x7d, 0xc1, 0xaf, 0xf4, - 0x27, 0x60, 0x4c, 0xd9, 0xe6, 0xc7, 0x2b, 0x49, 0x3c, 0x52, 0x0e, 0xa3, - 0xf7, 0xb0, 0x92, 0x4d, 0x57, 0xc0, 0x70, 0xd6, 0x28, 0xd9, 0x94, 0x06, - 0xc9, 0x1b, 0xb5, 0xe9, 0xb4, 0x69, 0x64, 0xaf, 0xf2, 0x65, 0x75, 0xfa, - 0x4e, 0x31, 0xa8, 0x1c, 0x23, 0x8c, 0x27, 0xdd, 0x0b, 0x58, 0x0c, 0x34, - 0x50, 0x9f, 0xa5, 0x76, 0x72, 0xe0, 0x05, 0x8d, 0x35, 0x2d, 0x44, 0x22, - 0xaa, 0x38, 0xe8, 0xfa, 0xce, 0x37, 0x42, 0x20, 0xd8, 0x16, 0xc0, 0x3b, - 0xe6, 0xa8, 0x55, 0x8f, 0x4d, 0xb8, 0xdc, 0xca, 0x3d, 0x58, 0xa5, 0x22, - 0x32, 0xb7, 0x72, 0xac, 0x08, 0xc7, 0xfa, 0xb3, 0x10, 0xaa, 0xea, 0xa0, - 0x36, 0xab, 0xd8, 0xeb, 0x6a, 0x4a, 0x97, 0x2b, 0xb1, 0x6b, 0x46, 0x4e, - 0xe1, 0x14, 0xb5, 0x82, 0x35, 0xec, 0x8c, 0xaa, 0x6c, 0x99, 0x0d, 0xa1, - 0x7c, 0xe6, 0x13, 0xf1, 0x18, 0xb5, 0x2f, 0xbd, 0x41, 0x08, 0x33, 0x19, - 0x82, 0xc6, 0x79, 0x86, 0xc9, 0xe7, 0xea, 0xb6, 0x5a, 0x5c, 0xfb, 0x3a, - 0xb5, 0xe9, 0xdb, 0x21, 0xf8, 0x67, 0x42, 0x08, 0xce, 0x28, 0x78, 0xa7, - 0x3d, 0x84, 0xfa, 0x39, 0xf9, 0x5b, 0x41, 0xa3, 0x79, 0x14, 0x07, 0x75, - 0x3f, 0x63, 0xfc, 0x2b, 0xf4, 0xeb, 0x0d, 0x98, 0xa4, 0x36, 0x3f, 0xea, - 0x6a, 0xa8, 0x3a, 0x4a, 0x2d, 0xb0, 0x85, 0x38, 0x49, 0xfc, 0x1f, 0x64, - 0x8c, 0x32, 0xde, 0x0b, 0x56, 0x36, 0x1a, 0x42, 0x00, 0xc1, 0x39, 0x23, - 0x3d, 0xc9, 0xe8, 0x52, 0x53, 0xaa, 0xb2, 0x7d, 0x96, 0xb5, 0xd7, 0x36, - 0x7b, 0xeb, 0xfd, 0x42, 0x7c, 0x9a, 0x6c, 0xea, 0x5b, 0xa0, 0x06, 0x8f, - 0xc4, 0x62, 0x99, 0x7e, 0x05, 0x58, 0x73, 0x96, 0x76, 0x64, 0xe6, 0xbf, - 0x44, 0x98, 0xe3, 0x1c, 0xd9, 0x20, 0x30, 0x6e, 0x65, 0x23, 0x01, 0x18, - 0x37, 0x86, 0x50, 0x87, 0x0f, 0x9e, 0x17, 0x42, 0xb4, 0x57, 0xe3, 0x1d, - 0xcb, 0x18, 0x34, 0xfd, 0x02, 0x3f, 0x4e, 0x66, 0x87, 0x22, 0x30, 0x86, - 0x7f, 0xad, 0x44, 0xf1, 0xf1, 0x94, 0x91, 0xbe, 0xa8, 0x04, 0x51, 0x39, - 0x67, 0xea, 0x5b, 0x94, 0x30, 0xca, 0x17, 0xc2, 0x58, 0x7d, 0x36, 0x88, - 0xc0, 0x4c, 0x18, 0xc1, 0x69, 0xf3, 0xe2, 0x2e, 0x78, 0xe3, 0x2c, 0x0e, - 0xa1, 0x19, 0xd5, 0xb3, 0x66, 0xf4, 0x5f, 0x20, 0xb1, 0x1d, 0x86, 0xba, - 0x10, 0x45, 0x7d, 0xc1, 0x44, 0x35, 0xf3, 0x7d, 0xf9, 0xac, 0xcc, 0xb3, - 0x8e, 0xb0, 0xe9, 0xe3, 0xda, 0x1c, 0x65, 0xab, 0x57, 0x37, 0x3a, 0xf9, - 0xe9, 0x56, 0x3a, 0xe6, 0xe5, 0x9e, 0x29, 0x28, 0xe3, 0xb3, 0x8b, 0xd6, - 0x4d, 0xb1, 0x2f, 0x26, 0xeb, 0x44, 0x19, 0x02, 0x76, 0x8f, 0xf2, 0xc0, - 0x3c, 0x8b, 0x90, 0xa7, 0xef, 0x65, 0x4a, 0xc0, 0x2e, 0x6a, 0xfb, 0x25, - 0x6a, 0xfb, 0x89, 0x92, 0xb6, 0x57, 0x51, 0xdb, 0x17, 0xfe, 0x4f, 0x6d, - 0x67, 0xbd, 0x9f, 0xf1, 0xe1, 0xbc, 0x19, 0xc2, 0x71, 0xab, 0x69, 0xb1, - 0x1e, 0x21, 0x54, 0xb7, 0xe9, 0xa8, 0x5e, 0xb0, 0xf0, 0x1c, 0xf7, 0x16, - 0x77, 0x15, 0xf5, 0xfd, 0x9b, 0x52, 0xf3, 0x4b, 0x5e, 0xed, 0x71, 0x77, - 0x59, 0x13, 0xc2, 0xd4, 0x2a, 0x55, 0xe9, 0xa1, 0x9e, 0x3f, 0x90, 0xbc, - 0x29, 0xe2, 0x31, 0x23, 0x4e, 0xce, 0xde, 0x38, 0x89, 0xa2, 0x46, 0xc4, - 0xa8, 0x97, 0x4b, 0xb5, 0x71, 0x1c, 0x73, 0x65, 0x4d, 0xeb, 0x64, 0x4d, - 0x53, 0x30, 0x12, 0x2b, 0x6a, 0xc4, 0xea, 0xbc, 0x6c, 0xd7, 0x51, 0x4f, - 0x9d, 0x5c, 0xd7, 0x16, 0xc1, 0x31, 0x6a, 0xa4, 0x4b, 0x9f, 0xb3, 0x9d, - 0xe3, 0x6d, 0x9b, 0x35, 0xb2, 0xdb, 0x99, 0x9f, 0xf3, 0xc4, 0xc5, 0x14, - 0xab, 0xc3, 0x89, 0x1a, 0x6a, 0x67, 0x73, 0x08, 0x13, 0xd4, 0xcb, 0xf3, - 0xf4, 0x10, 0x2f, 0xb1, 0xdf, 0xb8, 0x6b, 0x44, 0x5f, 0x22, 0xaf, 0xc7, - 0x4b, 0x9a, 0xf9, 0x12, 0x7d, 0xc3, 0x38, 0xf3, 0xf4, 0x53, 0x3e, 0x7b, - 0xcd, 0x35, 0x1c, 0xe9, 0x1f, 0xfc, 0x9e, 0x7f, 0x30, 0xe2, 0x7e, 0x45, - 0x7a, 0x88, 0x08, 0xde, 0x68, 0x91, 0x58, 0x24, 0xc6, 0x6f, 0xe9, 0xa7, - 0xaa, 0x7c, 0x6b, 0xf6, 0xba, 0xc8, 0xc7, 0xca, 0x55, 0xc9, 0xbf, 0xb1, - 0xa4, 0xc4, 0x93, 0x10, 0x65, 0x76, 0x98, 0x5e, 0xcb, 0x8c, 0x7f, 0x84, - 0x18, 0x71, 0x1b, 0xe1, 0xb3, 0x30, 0xfc, 0x67, 0xb7, 0xa8, 0x9e, 0x8f, - 0x5d, 0x90, 0x7e, 0x8b, 0x79, 0x9a, 0x32, 0x7b, 0xa7, 0x94, 0x58, 0x66, - 0x40, 0x91, 0xcf, 0x75, 0x94, 0x9f, 0x5d, 0x22, 0x77, 0x23, 0xe4, 0x6e, - 0x1d, 0x5e, 0xbf, 0x8d, 0xbf, 0xd4, 0x55, 0xdf, 0x00, 0xf9, 0x9b, 0xad, - 0x1b, 0xe9, 0xf7, 0x7f, 0x85, 0x7b, 0x87, 0x24, 0x7f, 0xd9, 0xe6, 0xc7, - 0xb3, 0x49, 0xec, 0x2c, 0x83, 0x91, 0x79, 0x4c, 0xc9, 0x3a, 0xe4, 0x71, - 0xaa, 0x4c, 0xc9, 0xd2, 0x31, 0x7d, 0xc9, 0xdf, 0x37, 0xf9, 0xb6, 0x9f, - 0xfc, 0xed, 0xab, 0xbb, 0x9d, 0xbf, 0x47, 0x38, 0x86, 0x8a, 0x27, 0xdc, - 0xe3, 0x98, 0x0b, 0x04, 0x11, 0x99, 0x09, 0x20, 0x34, 0xa3, 0xa2, 0x92, - 0x5c, 0x09, 0xdb, 0xd9, 0x78, 0x08, 0x46, 0xfa, 0x35, 0x44, 0x90, 0x98, - 0xd2, 0xf0, 0xe7, 0x2d, 0x01, 0x9c, 0x89, 0x19, 0x99, 0xfd, 0x4a, 0x84, - 0x58, 0x1f, 0x61, 0x44, 0x46, 0x34, 0xea, 0x2b, 0xf2, 0x35, 0xd0, 0x1c, - 0x84, 0x36, 0x23, 0xb9, 0x2e, 0x0e, 0xfa, 0xec, 0x6c, 0x54, 0x23, 0x46, - 0x7f, 0x40, 0x6c, 0x5c, 0x99, 0x12, 0x62, 0x73, 0xbb, 0x79, 0xf1, 0x3d, - 0xbf, 0x41, 0xdd, 0x53, 0x89, 0xd3, 0xe2, 0xf8, 0x15, 0x33, 0x1a, 0x82, - 0x47, 0xbd, 0xf1, 0x6f, 0xbc, 0xce, 0x28, 0x3e, 0x75, 0x55, 0x65, 0x2b, - 0x71, 0x40, 0x6e, 0x45, 0xe6, 0xa9, 0x7d, 0x87, 0x93, 0x46, 0x7a, 0x8b, - 0xd2, 0xe4, 0x34, 0xf3, 0xbb, 0x2f, 0x19, 0x8b, 0xf6, 0xf3, 0x9d, 0xf7, - 0x0b, 0x45, 0x0e, 0xd7, 0x9b, 0xbb, 0xf1, 0x17, 0xe4, 0x70, 0x95, 0xf9, - 0x14, 0x9e, 0xf4, 0xf4, 0x88, 0x38, 0x98, 0x2e, 0x27, 0xb7, 0x1d, 0x65, - 0x17, 0x71, 0xbf, 0x73, 0x9e, 0xba, 0x32, 0xd3, 0xee, 0x69, 0x51, 0xc8, - 0xec, 0x54, 0x7a, 0xe7, 0xbb, 0x3d, 0x0f, 0xb5, 0x7d, 0xd6, 0x87, 0xd7, - 0xad, 0x4d, 0xf4, 0x2b, 0x69, 0x65, 0xfb, 0xbc, 0xc4, 0x7c, 0x8f, 0xf2, - 0x4d, 0xe2, 0x3f, 0x7a, 0x97, 0x8a, 0x39, 0x6b, 0x93, 0x12, 0xf4, 0xf0, - 0x1f, 0x80, 0x93, 0x29, 0x62, 0xdf, 0x6f, 0xc7, 0xac, 0x73, 0x2b, 0xb0, - 0xdf, 0x7d, 0x07, 0x5f, 0x23, 0xf5, 0x03, 0x45, 0x2d, 0xd7, 0x3b, 0x99, - 0xaf, 0x67, 0x4a, 0x18, 0x7f, 0x92, 0xed, 0x81, 0x19, 0x68, 0xe5, 0xc4, - 0x71, 0xcf, 0x54, 0x18, 0xd3, 0x1e, 0x56, 0x04, 0x5e, 0x65, 0x4d, 0xc8, - 0x27, 0x0d, 0x6b, 0xbf, 0x62, 0xa4, 0xbb, 0x95, 0x44, 0x76, 0x4d, 0xa9, - 0x1e, 0xde, 0xcb, 0x9a, 0x86, 0xbb, 0xa8, 0x0b, 0x16, 0xb4, 0x10, 0xf1, - 0xfd, 0x6f, 0xac, 0x4f, 0xff, 0x51, 0xaa, 0x87, 0xc9, 0x7c, 0x39, 0xaa, - 0x5b, 0xa8, 0xef, 0xc4, 0x73, 0x97, 0xc4, 0x33, 0x3d, 0xc4, 0x18, 0xeb, - 0xff, 0x4e, 0xe2, 0x79, 0x75, 0x9b, 0x91, 0xed, 0xa4, 0x77, 0xf6, 0xad, - 0x8f, 0x10, 0xab, 0x71, 0xfa, 0xd5, 0x31, 0x74, 0x70, 0xae, 0xf4, 0xac, - 0x11, 0xe9, 0x20, 0x07, 0x54, 0xf6, 0x79, 0x89, 0x7d, 0x96, 0x6a, 0xa5, - 0xaf, 0x0e, 0xe1, 0x59, 0xf6, 0x31, 0x93, 0x8e, 0xa7, 0x15, 0x92, 0x03, - 0x13, 0x48, 0x64, 0x24, 0x07, 0x9c, 0x55, 0xad, 0xf4, 0xf8, 0x92, 0x03, - 0xc4, 0xa0, 0x4b, 0x0c, 0x16, 0x79, 0x30, 0x28, 0x79, 0x50, 0x45, 0x0f, - 0xb1, 0x40, 0x0f, 0x51, 0x61, 0x47, 0xc9, 0x01, 0xc9, 0x89, 0xa2, 0x8f, - 0xe8, 0x2c, 0xf1, 0x60, 0x8b, 0x37, 0x9f, 0x4a, 0xed, 0x0b, 0xa3, 0x69, - 0xda, 0xd0, 0x55, 0xe5, 0x3f, 0xc5, 0x2e, 0xd3, 0x5c, 0xdc, 0x4b, 0x2f, - 0xf0, 0x59, 0x5b, 0x8c, 0x79, 0x0f, 0x63, 0xdd, 0x42, 0x79, 0x40, 0xe2, - 0xbc, 0x7e, 0x3a, 0x8c, 0xea, 0x69, 0xc9, 0x83, 0xec, 0x24, 0xf5, 0x6f, - 0xc8, 0xf2, 0xfd, 0x13, 0xf1, 0x1f, 0x25, 0x2e, 0x54, 0xa5, 0x8b, 0x63, - 0x54, 0xcd, 0xe8, 0x68, 0x9d, 0x36, 0x06, 0x17, 0x70, 0x4d, 0xbc, 0x1a, - 0x33, 0x33, 0x87, 0x98, 0xff, 0x3d, 0xc9, 0x18, 0xf7, 0x4a, 0xc7, 0xbd, - 0xb7, 0xc6, 0xf0, 0x38, 0xe1, 0xf4, 0x5b, 0xe1, 0x92, 0xaf, 0xd6, 0xd0, - 0xef, 0x02, 0x7b, 0x5c, 0x1a, 0x5b, 0xd3, 0xb7, 0x36, 0x88, 0xeb, 0x38, - 0x49, 0xf4, 0x0f, 0xe8, 0x0e, 0xf3, 0x1f, 0xc2, 0xde, 0xd2, 0x3b, 0x45, - 0xbf, 0xfd, 0xe3, 0xd2, 0x79, 0xf2, 0x17, 0xfe, 0xe2, 0xdf, 0xbf, 0x55, - 0x97, 0xcf, 0x97, 0xfd, 0xc4, 0xe0, 0x66, 0x62, 0xb0, 0x9b, 0x39, 0xda, - 0x6b, 0x91, 0xdf, 0xcc, 0x67, 0x56, 0x0d, 0x51, 0x0f, 0x9b, 0xfa, 0x2a, - 0xa9, 0x6b, 0x87, 0xa9, 0x51, 0x3f, 0x37, 0xcb, 0xe9, 0xb7, 0x1d, 0xfa, - 0xed, 0x0e, 0x6a, 0x68, 0x27, 0xf5, 0x53, 0x62, 0x2b, 0x4d, 0x1c, 0x69, - 0x4a, 0x9a, 0x1e, 0x36, 0x90, 0xa4, 0xd7, 0xae, 0x5b, 0xf6, 0xda, 0x32, - 0x4e, 0xe9, 0xaf, 0x8d, 0xb8, 0x2c, 0xb5, 0x4f, 0x32, 0x0f, 0x8b, 0x35, - 0x9b, 0xa0, 0xda, 0x9b, 0x14, 0xd5, 0x96, 0xe7, 0x09, 0x15, 0xdf, 0xa5, - 0xd6, 0x2e, 0xed, 0x90, 0xe7, 0x0a, 0xae, 0x8b, 0x6d, 0x11, 0x33, 0x16, - 0x3d, 0x4e, 0x5c, 0x1d, 0xfb, 0x9d, 0x73, 0x46, 0x11, 0x6f, 0xa3, 0xae, - 0x7a, 0xcb, 0x33, 0x4b, 0x7d, 0xd8, 0x74, 0x0b, 0x6f, 0x1a, 0x9e, 0x68, - 0x89, 0x12, 0x8f, 0x12, 0x6b, 0x1a, 0xf2, 0x2f, 0x96, 0xe3, 0xd5, 0x17, - 0xc3, 0x78, 0xe5, 0x45, 0x21, 0xc6, 0x93, 0xe0, 0x69, 0x46, 0x6a, 0xec, - 0x46, 0xbc, 0xac, 0xc7, 0xa2, 0xcf, 0x7a, 0x9e, 0xd5, 0xa1, 0x67, 0x35, - 0x06, 0x2f, 0xe0, 0x26, 0xf5, 0x4b, 0x72, 0x3a, 0x41, 0xbe, 0x15, 0xb1, - 0xe8, 0x79, 0xdb, 0x1a, 0x0d, 0x57, 0x88, 0xbf, 0x6a, 0xe2, 0xef, 0x37, - 0xd4, 0xdd, 0x6b, 0x25, 0xdd, 0x5d, 0x9b, 0x27, 0x1f, 0xdb, 0x42, 0xe8, - 0x96, 0x6b, 0x21, 0x0e, 0x47, 0x6f, 0xe1, 0x50, 0x88, 0x0f, 0xb8, 0xe7, - 0x17, 0x2c, 0x23, 0xbe, 0x99, 0x78, 0x9c, 0xb3, 0x0c, 0xa7, 0x83, 0xde, - 0x75, 0xd4, 0xc3, 0x24, 0xf5, 0x37, 0x26, 0x71, 0x49, 0x1c, 0x32, 0x27, - 0x87, 0xd9, 0xe7, 0x3c, 0xfb, 0x4c, 0x94, 0xbc, 0xeb, 0xdb, 0x48, 0xa4, - 0xa5, 0x77, 0x8d, 0x12, 0x83, 0x87, 0x3d, 0xef, 0x2a, 0xbd, 0xaa, 0xf4, - 0xa9, 0x32, 0xce, 0x76, 0x2f, 0xce, 0xae, 0x5b, 0x38, 0xa4, 0x86, 0xd5, - 0x48, 0xfc, 0x7d, 0x03, 0x13, 0xcf, 0x57, 0xa1, 0xda, 0xbc, 0x07, 0x97, - 0x33, 0xdf, 0x50, 0x23, 0x26, 0xf4, 0x7a, 0xbb, 0x88, 0xc7, 0x9d, 0x85, - 0x14, 0x5c, 0xf7, 0x2d, 0xe1, 0xd6, 0x19, 0xce, 0x05, 0xcf, 0x7f, 0x0e, - 0xb2, 0xd6, 0xdc, 0x14, 0xbe, 0x98, 0x71, 0xb1, 0x9f, 0x1e, 0xac, 0xc9, - 0x5f, 0xf4, 0x72, 0x1b, 0xf3, 0xbf, 0x14, 0xa8, 0x2d, 0xae, 0x53, 0xa5, - 0x7f, 0x1b, 0x23, 0xe7, 0xc6, 0xcd, 0xa2, 0x97, 0x8b, 0xe5, 0xaf, 0x06, - 0xa4, 0xa6, 0xfb, 0xda, 0xe4, 0xb8, 0x69, 0x6a, 0xc8, 0xf2, 0xd8, 0x5f, - 0xea, 0xf2, 0x18, 0x31, 0x38, 0x2a, 0x7d, 0x15, 0x7d, 0x09, 0xcf, 0xe5, - 0x2b, 0x34, 0x75, 0xd8, 0x0f, 0x53, 0xb6, 0x39, 0xca, 0x03, 0x5c, 0x83, - 0x66, 0x0e, 0x2b, 0x69, 0x9e, 0x3b, 0x0f, 0x11, 0x5f, 0xdd, 0xac, 0xc3, - 0x57, 0xad, 0x66, 0x72, 0x98, 0xf5, 0x89, 0xb5, 0xf8, 0xb0, 0xb9, 0x7c, - 0x7e, 0x93, 0x35, 0x99, 0x35, 0xcc, 0xad, 0x64, 0xfd, 0xee, 0x61, 0xcd, - 0xe6, 0x28, 0xcc, 0xe9, 0x67, 0x31, 0xd1, 0xb8, 0xb6, 0xcd, 0x18, 0xdc, - 0xe6, 0x0f, 0x21, 0x47, 0xbc, 0x1f, 0x63, 0x1d, 0x72, 0xb9, 0xa7, 0xd3, - 0x05, 0x23, 0x95, 0xc5, 0x18, 0xb6, 0x71, 0x4f, 0x79, 0xde, 0x71, 0xfe, - 0x2e, 0x56, 0x3c, 0x0f, 0xef, 0x65, 0x7d, 0x9b, 0x2c, 0x71, 0xfb, 0x43, - 0x24, 0x2c, 0xc9, 0xed, 0x45, 0xd6, 0xb7, 0x49, 0x8f, 0xdb, 0x46, 0x4a, - 0xf2, 0xb9, 0xac, 0x54, 0xd7, 0x3e, 0x82, 0xe4, 0xf0, 0xed, 0x35, 0x4d, - 0xe2, 0xd9, 0x0e, 0x4a, 0x1f, 0xeb, 0xba, 0xb2, 0x26, 0xc9, 0x5a, 0xb4, - 0x5c, 0x97, 0x34, 0x79, 0x77, 0x90, 0x69, 0x9c, 0x3a, 0x28, 0x7c, 0xc5, - 0xfb, 0x87, 0x8b, 0xef, 0xfa, 0xc3, 0xa9, 0xd4, 0x7d, 0xc8, 0x44, 0xce, - 0x6a, 0xd8, 0xe1, 0x36, 0xf4, 0x85, 0x6c, 0xf0, 0x1d, 0x05, 0xd6, 0x1f, - 0x6b, 0xc8, 0xdc, 0x76, 0xff, 0xf0, 0x41, 0x4e, 0xd3, 0xaa, 0xa7, 0xee, - 0x96, 0xef, 0xe0, 0x93, 0xdc, 0x1d, 0xef, 0x1f, 0xd2, 0xbf, 0xef, 0xfe, - 0xe1, 0x59, 0xf2, 0x63, 0xa2, 0x78, 0xff, 0xe0, 0x7c, 0xa7, 0xc5, 0x8f, - 0xb9, 0x3a, 0x1c, 0x78, 0xaf, 0x5d, 0xc5, 0xd5, 0x9c, 0x11, 0x79, 0x19, - 0x07, 0x30, 0xe0, 0xdd, 0x35, 0xf0, 0xcc, 0x6f, 0x0f, 0xe1, 0xd7, 0xed, - 0xf2, 0xae, 0x21, 0x25, 0xd7, 0x38, 0xc9, 0xe5, 0x43, 0xa3, 0xde, 0x6c, - 0x61, 0x2d, 0xd8, 0xb7, 0x51, 0xc1, 0x03, 0xc9, 0x7b, 0x3c, 0x6c, 0x4f, - 0x16, 0x8c, 0x74, 0x94, 0xcf, 0xd6, 0x4d, 0xc9, 0x1a, 0xf9, 0x30, 0xcf, - 0x86, 0xd0, 0x1a, 0xed, 0x5e, 0x4d, 0xb8, 0x4d, 0x91, 0x0f, 0x15, 0xc3, - 0x39, 0x09, 0x79, 0x1f, 0x90, 0xb8, 0xe8, 0x57, 0x8c, 0xc5, 0x77, 0xfd, - 0x46, 0xaa, 0xde, 0xc3, 0xcc, 0xc3, 0x3c, 0xa7, 0xc9, 0xbf, 0xbd, 0xf2, - 0x8c, 0x87, 0x6d, 0x1c, 0xf3, 0xd2, 0x46, 0x79, 0xee, 0xfc, 0x54, 0x64, - 0x57, 0x19, 0xce, 0x92, 0xa2, 0x31, 0x37, 0xa0, 0x3e, 0x49, 0x0d, 0x7f, - 0x98, 0x1a, 0x2e, 0xcf, 0x08, 0xbd, 0x3c, 0x23, 0x34, 0x2d, 0xc6, 0xfd, - 0x46, 0xe6, 0x06, 0xf5, 0x8e, 0x63, 0xf6, 0xf5, 0x2a, 0x46, 0xef, 0x02, - 0xf5, 0x7f, 0xbf, 0x52, 0x1c, 0x73, 0x4d, 0x69, 0xcc, 0x7b, 0xf3, 0x9a, - 0xb2, 0xd9, 0x05, 0x75, 0x07, 0xd1, 0x3d, 0x16, 0xb5, 0xa3, 0x50, 0x4e, - 0x8e, 0x99, 0x72, 0xcd, 0x8c, 0xad, 0x95, 0xb1, 0x29, 0xf8, 0xb0, 0x45, - 0xbe, 0xdb, 0x2a, 0xe3, 0x70, 0x2a, 0xec, 0x14, 0xb5, 0xf7, 0xb9, 0x60, - 0x49, 0xbf, 0x7c, 0xfd, 0xd6, 0x2a, 0x38, 0x75, 0xa8, 0x0e, 0x98, 0xb5, - 0x18, 0xd7, 0x51, 0x19, 0x36, 0x9b, 0x91, 0xd3, 0x83, 0xe8, 0xb7, 0x7e, - 0x2b, 0xa8, 0x93, 0x7c, 0x1f, 0x78, 0xec, 0x79, 0x9e, 0xd7, 0xcd, 0xeb, - 0x88, 0x25, 0x9f, 0xc6, 0x19, 0x7d, 0x08, 0xe5, 0xac, 0xa5, 0xaf, 0x78, - 0x7a, 0x62, 0x13, 0xcf, 0x0a, 0x31, 0x64, 0xcb, 0x5a, 0x77, 0xdb, 0xd8, - 0xf2, 0xfe, 0xe1, 0x7d, 0x91, 0x2d, 0x8e, 0xe1, 0xec, 0xb1, 0x32, 0x8c, - 0xeb, 0x4b, 0xdd, 0xdd, 0x47, 0xdd, 0xa5, 0xb7, 0xfc, 0x5a, 0x39, 0x75, - 0x77, 0xb7, 0xf5, 0x6d, 0x3c, 0x46, 0x8e, 0x57, 0x98, 0x9f, 0x88, 0xc7, - 0xeb, 0xe4, 0x98, 0xd4, 0xd7, 0xaa, 0x95, 0xe3, 0xff, 0x33, 0xc7, 0x94, - 0x73, 0xc8, 0x7a, 0x78, 0x59, 0x48, 0x6f, 0x56, 0x61, 0x0f, 0x2b, 0xdb, - 0xc8, 0xa9, 0x45, 0x96, 0xde, 0xef, 0x92, 0x4f, 0x4b, 0xcc, 0x4f, 0xe3, - 0x1d, 0xf8, 0xd4, 0x48, 0x3e, 0xed, 0x5a, 0xc1, 0xa7, 0xe3, 0xe4, 0x53, - 0x2f, 0xf9, 0xd4, 0xd2, 0xf6, 0x27, 0xd4, 0x15, 0x21, 0x82, 0x6d, 0x37, - 0xc5, 0x9b, 0x9e, 0xff, 0x95, 0x9e, 0x37, 0xad, 0x74, 0xcd, 0x4b, 0x7d, - 0xaa, 0xa4, 0x27, 0xee, 0xa1, 0x1f, 0x06, 0x06, 0xc8, 0xa7, 0xc7, 0x4d, - 0xd1, 0xb8, 0x2f, 0x69, 0xa4, 0x16, 0xe9, 0x6b, 0x7a, 0xc8, 0xa9, 0xb7, - 0xc8, 0xa9, 0xb1, 0x42, 0x51, 0xa7, 0x0e, 0x73, 0xdd, 0xf7, 0x53, 0xa7, - 0x7a, 0x0a, 0x52, 0xdb, 0x1c, 0xe2, 0x3f, 0x84, 0x4f, 0xc9, 0xa9, 0xf9, - 0xa4, 0xa7, 0x53, 0xd6, 0x6f, 0x90, 0x18, 0x3a, 0x2f, 0xf9, 0x44, 0x9d, - 0x72, 0x0b, 0x4d, 0xd6, 0x79, 0xae, 0x69, 0xd2, 0x35, 0x6e, 0x74, 0x93, - 0x53, 0x81, 0x76, 0xe3, 0xe2, 0x55, 0x62, 0x37, 0x14, 0x83, 0x1e, 0xb1, - 0xe5, 0x9a, 0x58, 0x63, 0x59, 0x27, 0x8f, 0x13, 0xff, 0xdd, 0xd4, 0x8c, - 0xde, 0x82, 0x8d, 0x43, 0x85, 0x95, 0x7b, 0xca, 0x3a, 0x74, 0xc7, 0x7d, - 0x19, 0x0d, 0xdd, 0xb9, 0x9d, 0xf5, 0xea, 0x8e, 0xed, 0x92, 0xaf, 0x7a, - 0x48, 0xf2, 0x75, 0xd4, 0xfd, 0x61, 0xe0, 0xce, 0xef, 0xc8, 0xfb, 0x33, - 0x21, 0x4e, 0x5b, 0xf2, 0xfe, 0x41, 0xfa, 0x1e, 0xfa, 0x68, 0x4b, 0xde, - 0xa1, 0x75, 0x44, 0x55, 0x18, 0x91, 0x47, 0xf1, 0xb9, 0xc8, 0xd6, 0x39, - 0xf1, 0x80, 0x57, 0x23, 0x0d, 0xbd, 0x8f, 0xb5, 0x6e, 0xb1, 0x74, 0xce, - 0x9b, 0xcb, 0x09, 0xf1, 0x16, 0xeb, 0xd4, 0x69, 0x9e, 0xe9, 0x46, 0xf2, - 0x9f, 0x8b, 0xc5, 0x3a, 0x15, 0x63, 0xe6, 0xad, 0xfb, 0x48, 0x4f, 0xc7, - 0x4e, 0xf2, 0xd9, 0x44, 0x7e, 0xb9, 0x46, 0x51, 0x33, 0x4d, 0x21, 0x76, - 0x9b, 0xff, 0x2d, 0xfa, 0xbf, 0xf2, 0xae, 0x10, 0xd3, 0x8c, 0xe1, 0x8a, - 0x85, 0x03, 0x01, 0xc4, 0xfa, 0x6e, 0xb0, 0xae, 0x5f, 0xda, 0x68, 0x64, - 0xf2, 0x4a, 0xa2, 0x77, 0xab, 0x22, 0xbd, 0x9e, 0xaf, 0xb3, 0x8c, 0xef, - 0xb4, 0xd0, 0x1b, 0x7d, 0xc8, 0x0c, 0x06, 0xf9, 0xfd, 0x4d, 0xcb, 0xa0, - 0x7f, 0x16, 0xa2, 0x3f, 0x25, 0xc7, 0x10, 0xa2, 0xc3, 0x92, 0xe7, 0x80, - 0x31, 0x9e, 0x03, 0xb2, 0xa2, 0xc2, 0xbc, 0x42, 0x6d, 0x32, 0x32, 0x63, - 0x8a, 0xc9, 0xbe, 0x51, 0x78, 0x3a, 0xcb, 0x67, 0xda, 0x54, 0x04, 0x7f, - 0xed, 0xf9, 0xe7, 0x28, 0x35, 0xab, 0x01, 0x7f, 0xe3, 0xe9, 0x96, 0x8a, - 0x3d, 0xcf, 0x1b, 0x29, 0x55, 0x39, 0x88, 0xf7, 0x2d, 0x43, 0xff, 0x21, - 0xe3, 0xa6, 0xd6, 0x3c, 0xb7, 0x19, 0x51, 0x70, 0x8e, 0x6c, 0x9f, 0xbf, - 0x46, 0xd1, 0x58, 0x3b, 0xbe, 0xdf, 0x22, 0x6b, 0xf7, 0x10, 0xba, 0x9b, - 0xf7, 0xf3, 0xa3, 0xa2, 0x76, 0x46, 0x55, 0x76, 0xd0, 0x93, 0x54, 0xcf, - 0x54, 0x63, 0xef, 0x7a, 0x21, 0xd6, 0xae, 0x77, 0xc0, 0x33, 0x5f, 0xfc, - 0x02, 0x6b, 0xd0, 0x89, 0x1a, 0x23, 0x0d, 0xfc, 0x04, 0x3b, 0xe9, 0x65, - 0x53, 0x6d, 0x39, 0xe0, 0x1e, 0xb9, 0xc6, 0x9f, 0x60, 0xb3, 0xf4, 0xc0, - 0x56, 0xb5, 0xf4, 0x5b, 0x1e, 0x7e, 0x8b, 0x77, 0x48, 0x4c, 0xf5, 0xd1, - 0xac, 0x28, 0x37, 0x8d, 0xbe, 0x79, 0xd6, 0xdb, 0x4b, 0xb1, 0xbb, 0xf5, - 0x6f, 0xcd, 0x4b, 0x0f, 0x6c, 0x46, 0xb7, 0x28, 0x82, 0xb9, 0x78, 0x86, - 0xb9, 0x88, 0x39, 0x61, 0x5a, 0x86, 0x6a, 0x3b, 0xe6, 0x54, 0x2b, 0xc3, - 0xca, 0x83, 0xe4, 0x43, 0x5f, 0xb0, 0x9c, 0x1e, 0xc2, 0xa1, 0x7f, 0xf0, - 0xa1, 0xf2, 0xa8, 0xf4, 0x14, 0x21, 0x6a, 0x4d, 0x53, 0x2f, 0x4f, 0x17, - 0xd8, 0x97, 0x94, 0xfe, 0x83, 0x58, 0x3f, 0x7a, 0x53, 0x6c, 0xa6, 0xc7, - 0xdd, 0x5c, 0xf2, 0xb8, 0xbb, 0x66, 0xd3, 0xf4, 0xc0, 0x9a, 0x22, 0xef, - 0xd3, 0x52, 0x6d, 0x3c, 0x94, 0x3e, 0x28, 0x7d, 0x88, 0x5c, 0x83, 0x8e, - 0x6b, 0x49, 0x89, 0x5d, 0x1d, 0xa3, 0xed, 0x46, 0x24, 0x0b, 0x79, 0x7f, - 0x73, 0xbb, 0xbf, 0x80, 0x9e, 0xfe, 0x1d, 0xcf, 0x01, 0x7d, 0x07, 0x63, - 0x31, 0x82, 0x42, 0xd4, 0x26, 0xfd, 0xe8, 0xf3, 0xce, 0x73, 0x11, 0x3d, - 0x4d, 0xde, 0x5f, 0xa4, 0x4f, 0xf0, 0xf3, 0xdc, 0x7c, 0x90, 0x58, 0xfa, - 0xac, 0x65, 0xe4, 0x58, 0x3d, 0xb2, 0x93, 0xb5, 0x30, 0xac, 0xfb, 0xa9, - 0xab, 0x57, 0x72, 0x0f, 0xb2, 0x9e, 0xfb, 0xda, 0x23, 0x3c, 0x03, 0x34, - 0xce, 0x64, 0x45, 0x3d, 0xfd, 0xe0, 0x37, 0x78, 0xee, 0xad, 0x69, 0x8b, - 0xd3, 0x6f, 0x2f, 0xef, 0x95, 0x0f, 0x4f, 0x59, 0x26, 0x1c, 0xef, 0x77, - 0x58, 0xef, 0x9a, 0xbd, 0x29, 0xe6, 0xcc, 0xbb, 0xf5, 0x8e, 0x62, 0x5c, - 0x6a, 0x99, 0x6d, 0xa1, 0x65, 0x03, 0xcf, 0x8e, 0x77, 0x88, 0xa9, 0x47, - 0x7a, 0x9f, 0x40, 0xb1, 0xdf, 0x9f, 0xce, 0x36, 0xe8, 0xdb, 0x59, 0xef, - 0x16, 0x89, 0x95, 0x5d, 0xeb, 0x2d, 0x19, 0xcb, 0xa2, 0x8c, 0x85, 0xfe, - 0xd2, 0xb9, 0xdf, 0x47, 0x5f, 0x92, 0x04, 0xaa, 0xcf, 0x3e, 0x45, 0x5e, - 0xf9, 0x5a, 0xab, 0x91, 0x1d, 0x62, 0x8c, 0xc7, 0xfe, 0x91, 0x5b, 0x33, - 0x30, 0x8d, 0x01, 0x1f, 0xfb, 0x4c, 0x59, 0xc0, 0x13, 0x0b, 0x3c, 0x97, - 0x4e, 0xc7, 0xe8, 0xcb, 0xe9, 0x23, 0x17, 0x34, 0x3c, 0x3a, 0x5b, 0x8e, - 0xef, 0xcd, 0x86, 0xb1, 0x6f, 0xd6, 0xbb, 0xd7, 0xda, 0x5a, 0xcb, 0xf7, - 0x3a, 0x92, 0x42, 0xcc, 0x5b, 0xeb, 0xf1, 0x1e, 0x3d, 0xd4, 0x6a, 0xc5, - 0x87, 0xc8, 0x51, 0xe8, 0x3a, 0x71, 0x53, 0xd3, 0xf2, 0x3d, 0x26, 0x58, - 0x08, 0x73, 0xbd, 0xd4, 0xc9, 0x67, 0xbc, 0xef, 0x63, 0xf4, 0x8f, 0x19, - 0x89, 0x41, 0x97, 0x18, 0x74, 0x89, 0xc9, 0x5b, 0x9e, 0x5a, 0x62, 0x39, - 0x4e, 0x1f, 0xfd, 0xb4, 0x28, 0x62, 0xe3, 0x0b, 0x71, 0xda, 0x7c, 0x95, - 0xfc, 0x55, 0xa9, 0xa1, 0xc0, 0xdf, 0xe7, 0x22, 0xfa, 0x8e, 0x82, 0xcc, - 0xff, 0x5f, 0x96, 0xf2, 0xbf, 0x18, 0x2a, 0xea, 0x85, 0xe1, 0xcc, 0xa3, - 0x01, 0xd3, 0x6e, 0x83, 0xbe, 0xd5, 0x1d, 0x19, 0xd6, 0x90, 0x8d, 0x56, - 0xc3, 0x18, 0x9c, 0x86, 0xaf, 0x35, 0x0c, 0xb9, 0x76, 0x20, 0xef, 0xad, - 0x51, 0x88, 0x09, 0xea, 0x9b, 0xcc, 0xc1, 0xbf, 0xe7, 0xd0, 0xea, 0x63, - 0x3e, 0x1c, 0xc6, 0xbe, 0x8f, 0x7b, 0xf0, 0x71, 0x5e, 0xde, 0x73, 0xc6, - 0xd2, 0x5d, 0xb8, 0xee, 0x8d, 0xf9, 0x51, 0x3e, 0x85, 0x23, 0xee, 0x25, - 0x71, 0xa4, 0xae, 0xa8, 0xf1, 0x69, 0x9e, 0x8f, 0xaa, 0x8f, 0x96, 0xbc, - 0x10, 0x39, 0x5c, 0xc9, 0xf5, 0x5e, 0x4b, 0x7a, 0xde, 0x9f, 0x35, 0x72, - 0x50, 0x3b, 0x6d, 0x6e, 0xe4, 0xda, 0x6e, 0x8a, 0x89, 0x58, 0xb3, 0x56, - 0x8c, 0x29, 0xa1, 0x9f, 0x42, 0x19, 0xb1, 0x2b, 0xcf, 0x48, 0x52, 0x3f, - 0xe4, 0x6f, 0x9e, 0x4f, 0x54, 0x27, 0xe2, 0xe7, 0xba, 0x9c, 0x87, 0x64, - 0x5b, 0xa8, 0xe4, 0x57, 0x97, 0xbd, 0x48, 0x07, 0x9f, 0x49, 0x2f, 0xf2, - 0xb9, 0xe8, 0xab, 0xeb, 0xb8, 0xa5, 0x39, 0x59, 0xbe, 0x31, 0xee, 0xca, - 0xfb, 0xab, 0x16, 0x3a, 0x62, 0x05, 0xe7, 0x18, 0xf9, 0xa9, 0xd6, 0x98, - 0x3e, 0xca, 0xf1, 0x1c, 0x5d, 0x27, 0x97, 0x0f, 0xd2, 0x2f, 0xf3, 0x9d, - 0x42, 0x0b, 0xfb, 0x48, 0x2d, 0xdb, 0xc1, 0xb5, 0xfe, 0xb6, 0x59, 0x62, - 0x7b, 0xd4, 0x7d, 0xc3, 0xa7, 0x9a, 0x72, 0x9d, 0x89, 0xd4, 0x28, 0xe3, - 0x59, 0xd2, 0xa5, 0xb7, 0x76, 0xa8, 0x6d, 0x09, 0xaf, 0x7f, 0x56, 0x95, - 0x71, 0x78, 0xf1, 0xb0, 0x4d, 0x6a, 0x96, 0x91, 0x39, 0x87, 0x84, 0x33, - 0x20, 0xcd, 0xc1, 0x2a, 0x19, 0x43, 0x53, 0x64, 0x80, 0xf1, 0x9c, 0xa8, - 0xf3, 0xf4, 0x90, 0xcf, 0x38, 0x9f, 0xeb, 0xdb, 0x5a, 0x0e, 0x81, 0xd5, - 0x49, 0xef, 0xdc, 0x5f, 0xfa, 0x7f, 0x18, 0x2a, 0x7d, 0x88, 0xc4, 0xe2, - 0xff, 0x02, 0xc7, 0x2a, 0x26, 0xcf, 0x94, 0x1a, 0x00, 0x00, 0x00 }; + 0xbd, 0x59, 0x6d, 0x70, 0x5b, 0x55, 0x7a, 0x7e, 0xae, 0x74, 0x25, 0x5d, + 0xdb, 0xb2, 0x75, 0x8d, 0x95, 0x20, 0xb7, 0x2e, 0xd6, 0x8d, 0xaf, 0x6c, + 0x11, 0xb9, 0xe1, 0x2a, 0x36, 0x45, 0x19, 0xee, 0x94, 0x1b, 0x7f, 0x21, + 0x92, 0x10, 0x94, 0x42, 0x5b, 0x67, 0x96, 0x19, 0x4c, 0xe2, 0x4d, 0x4c, + 0x08, 0x6c, 0xba, 0xcb, 0x4c, 0xdd, 0xd9, 0x4c, 0x23, 0xfc, 0x15, 0x93, + 0xc8, 0x16, 0x6b, 0x20, 0x26, 0x3b, 0x3b, 0x43, 0xc6, 0xf9, 0x70, 0x0a, + 0x72, 0x14, 0xda, 0x3f, 0x3b, 0xd3, 0x65, 0xf0, 0x6c, 0x12, 0x12, 0x58, + 0xd8, 0xb4, 0xd3, 0x3f, 0xc9, 0xf4, 0xc7, 0x7a, 0x21, 0xa1, 0x81, 0x42, + 0x36, 0xed, 0x0c, 0x9d, 0x50, 0x68, 0x4e, 0x9f, 0x73, 0x25, 0x07, 0x13, + 0xb2, 0xfd, 0xd9, 0xcc, 0x08, 0x4b, 0xe7, 0xde, 0x73, 0xce, 0x7b, 0xce, + 0xfb, 0x3c, 0xcf, 0xfb, 0x9c, 0xc3, 0x0a, 0x05, 0x95, 0x28, 0xff, 0xab, + 0xe6, 0xa7, 0xfd, 0xc9, 0x5d, 0xcf, 0xad, 0x5e, 0xd5, 0xbe, 0x8a, 0x5f, + 0x57, 0x2b, 0xcb, 0x55, 0x15, 0xff, 0x8f, 0xff, 0xbc, 0x80, 0xbe, 0x18, + 0x87, 0xfc, 0x40, 0xf3, 0xd8, 0xf3, 0x77, 0x75, 0x98, 0xd0, 0xbc, 0xf6, + 0x63, 0x4d, 0x5b, 0x4d, 0xc0, 0x29, 0x24, 0xa2, 0x9d, 0xf8, 0x1f, 0x91, + 0x0d, 0xab, 0x90, 0xed, 0x7f, 0x64, 0x7f, 0x7d, 0xcf, 0x5b, 0xf7, 0x19, + 0xd7, 0x0e, 0x79, 0xa1, 0xe9, 0xf6, 0xb8, 0xaa, 0x37, 0x43, 0x6b, 0x60, + 0x9f, 0x9f, 0xb5, 0xf4, 0xfb, 0x50, 0xb3, 0x38, 0x16, 0x70, 0x38, 0x67, + 0x58, 0xdb, 0x90, 0xd0, 0x4f, 0x41, 0x85, 0xc3, 0x39, 0x8e, 0x15, 0x80, + 0xbd, 0x39, 0x05, 0x97, 0x39, 0xe6, 0x68, 0x41, 0xc3, 0x82, 0xd7, 0x9d, + 0xae, 0xaf, 0xc2, 0x46, 0xc6, 0x9c, 0xd8, 0x23, 0x02, 0x26, 0xb2, 0x7f, + 0x60, 0x9b, 0xf1, 0xbd, 0x08, 0xa6, 0x66, 0xda, 0x91, 0x59, 0x31, 0xa7, + 0x61, 0x73, 0xbe, 0xa1, 0x4f, 0xb3, 0xc1, 0x77, 0x14, 0xa4, 0xee, 0xd3, + 0xd0, 0x5b, 0x8c, 0x23, 0x5b, 0xcc, 0xc2, 0x29, 0x8e, 0xf0, 0xa3, 0x21, + 0x30, 0xa1, 0x69, 0xf7, 0x4c, 0x2c, 0x97, 0xef, 0x20, 0x38, 0x71, 0x4d, + 0x5c, 0x4d, 0xea, 0x78, 0x6f, 0x8d, 0x10, 0xd5, 0x36, 0xb2, 0x55, 0xed, + 0x59, 0x78, 0x6d, 0xc3, 0x5a, 0xef, 0x55, 0xd0, 0xf5, 0xc7, 0x66, 0x7c, + 0x42, 0x79, 0xf4, 0x51, 0x8f, 0x0d, 0x4d, 0xb1, 0xa3, 0x6a, 0x53, 0xa1, + 0x01, 0x63, 0x45, 0x1d, 0x7b, 0x8b, 0x61, 0x8c, 0x14, 0xb1, 0xdb, 0x7b, + 0xaf, 0x1f, 0x33, 0x3a, 0x9c, 0xef, 0xb5, 0xec, 0xc6, 0x8e, 0xdc, 0x20, + 0xb6, 0xe6, 0x52, 0xd8, 0x57, 0x94, 0x31, 0x46, 0x31, 0x5c, 0x54, 0xe1, + 0x9f, 0x30, 0x22, 0xef, 0xe2, 0x76, 0xcf, 0x84, 0x18, 0xb1, 0x02, 0x18, + 0xb2, 0xe2, 0x18, 0xcd, 0x7b, 0xb8, 0xce, 0x00, 0x86, 0xcd, 0xeb, 0xa2, + 0xdf, 0x32, 0xac, 0x51, 0x88, 0xc6, 0xd3, 0x96, 0x11, 0xe9, 0xf2, 0xc2, + 0xf9, 0xb1, 0x19, 0xc1, 0x28, 0x63, 0x1f, 0x71, 0xfb, 0x8d, 0xa0, 0xeb, + 0x66, 0x3f, 0x87, 0xfd, 0x74, 0x8c, 0x7d, 0xbb, 0x6f, 0x74, 0x14, 0x89, + 0xc8, 0x18, 0x3c, 0xe8, 0x0b, 0xb7, 0xb2, 0x5f, 0x53, 0x74, 0x0c, 0x46, + 0x9c, 0xe3, 0x64, 0xfd, 0xed, 0x0e, 0xc7, 0xc8, 0xb2, 0xbf, 0x11, 0x3d, + 0x06, 0x39, 0x56, 0x03, 0x7f, 0xb7, 0xb3, 0xbf, 0x02, 0x8f, 0x1d, 0x8b, + 0x0e, 0xb1, 0xcf, 0x29, 0x4b, 0xc5, 0x19, 0x7e, 0xfa, 0x74, 0x43, 0x66, + 0x56, 0x09, 0xb0, 0x7d, 0x2f, 0xf8, 0xdc, 0xac, 0xc2, 0xa1, 0x8c, 0x85, + 0x21, 0xae, 0x5b, 0x63, 0xdb, 0x38, 0xdb, 0x7c, 0xa6, 0xc5, 0xf1, 0xa1, + 0x77, 0x15, 0x97, 0x62, 0x62, 0x31, 0x37, 0xbf, 0xaf, 0x9d, 0x63, 0xe4, + 0x4b, 0x39, 0x95, 0xef, 0x74, 0xe6, 0x6f, 0x88, 0x27, 0xd5, 0xa5, 0xcf, + 0x07, 0x95, 0x0e, 0xb6, 0x39, 0x6a, 0x03, 0xf6, 0xe6, 0xa1, 0xf9, 0x4d, + 0x8d, 0xf3, 0x68, 0xf8, 0x28, 0x37, 0xa8, 0xf4, 0x14, 0x1d, 0xa5, 0x7b, + 0xb6, 0x43, 0x71, 0x66, 0x55, 0xa5, 0x6b, 0x5a, 0xc6, 0x2d, 0xc4, 0x0b, + 0x96, 0xc2, 0x98, 0x7f, 0x22, 0xe3, 0x75, 0xa2, 0xca, 0x0d, 0xb1, 0x32, + 0xe6, 0x41, 0x95, 0xd9, 0xa3, 0xac, 0x9f, 0x15, 0x22, 0x9d, 0x4c, 0x2b, + 0xeb, 0x66, 0xa1, 0x05, 0x6d, 0x5b, 0xcd, 0x4d, 0xec, 0x43, 0x76, 0x99, + 0x89, 0x83, 0xf9, 0x28, 0x3e, 0xb0, 0x3c, 0x38, 0xb4, 0xac, 0x02, 0xaa, + 0xa9, 0xf0, 0x83, 0xe0, 0x79, 0x0b, 0x6a, 0x0d, 0xbf, 0x5f, 0xdd, 0xa4, + 0x62, 0xa4, 0x7d, 0x9d, 0xd2, 0xc5, 0x3e, 0x3e, 0xe6, 0xf9, 0x68, 0x2e, + 0x8d, 0x20, 0xb1, 0x53, 0x65, 0xc7, 0x22, 0x05, 0xee, 0xcd, 0x7b, 0x56, + 0x2c, 0xfe, 0xb4, 0xc4, 0x63, 0xad, 0x11, 0x91, 0x7b, 0x53, 0x6d, 0xc7, + 0xe2, 0x73, 0xdc, 0x07, 0xaf, 0xa9, 0xe2, 0xd7, 0x96, 0x0f, 0xf3, 0x9b, + 0x2c, 0xe6, 0x54, 0x87, 0x9f, 0xed, 0xc7, 0xdc, 0x76, 0xf9, 0x1b, 0x7a, + 0xf7, 0xb7, 0xf6, 0xa1, 0xb4, 0x07, 0xc3, 0xf9, 0x26, 0xc6, 0x5c, 0xda, + 0x83, 0x47, 0xb8, 0xde, 0xdf, 0xfa, 0xe4, 0xd7, 0xbb, 0x6e, 0xb6, 0x6d, + 0x66, 0x9c, 0x1e, 0xdb, 0x9c, 0x5f, 0xe1, 0xad, 0x07, 0xea, 0xda, 0xb1, + 0x8f, 0x39, 0xee, 0x4a, 0x2e, 0x47, 0xd6, 0x7d, 0x1e, 0xd6, 0xd7, 0x4f, + 0xd7, 0xa1, 0x6f, 0x99, 0xbb, 0x6f, 0xfa, 0xc6, 0x69, 0x21, 0xce, 0x24, + 0xfd, 0x98, 0x33, 0x87, 0x22, 0xd5, 0xc8, 0x5a, 0x5e, 0xe6, 0xfb, 0x2c, + 0xe7, 0x2f, 0x24, 0xbd, 0x38, 0x9c, 0x3c, 0x84, 0x6c, 0x2d, 0x30, 0x93, + 0x93, 0xbc, 0x32, 0xe6, 0xcf, 0xf2, 0xbf, 0x9e, 0xa2, 0x5c, 0x9f, 0xc5, + 0xf5, 0x29, 0x38, 0x66, 0x4a, 0x4c, 0x5b, 0x6a, 0x33, 0xf9, 0xb5, 0x83, + 0xfb, 0x59, 0xdf, 0x1e, 0x24, 0x3e, 0x81, 0x0f, 0x73, 0xfd, 0xd8, 0x5c, + 0x8a, 0x05, 0xd7, 0x73, 0x50, 0x7c, 0x6d, 0x69, 0x1c, 0x2a, 0xfd, 0x26, + 0xc7, 0xd3, 0x6a, 0x47, 0xce, 0xc8, 0xa4, 0x91, 0x38, 0xd7, 0xa1, 0xc8, + 0xfe, 0x69, 0x75, 0x65, 0xc1, 0x8f, 0x68, 0x5d, 0xe9, 0x79, 0x95, 0xbd, + 0x41, 0x7d, 0x7a, 0x42, 0xc1, 0xf6, 0x98, 0x7c, 0xb6, 0x41, 0x6d, 0x29, + 0x40, 0xab, 0xb6, 0x77, 0xa9, 0x73, 0x13, 0x46, 0xdf, 0x71, 0x25, 0x11, + 0x9d, 0x70, 0xfb, 0xec, 0x52, 0x5b, 0x0b, 0x01, 0xae, 0x27, 0xce, 0x9c, + 0x40, 0xab, 0xb1, 0x9f, 0x53, 0x7f, 0xcd, 0x07, 0xe7, 0xdc, 0x3e, 0xcf, + 0xa9, 0xf1, 0x82, 0x6c, 0x37, 0xac, 0xa8, 0x12, 0xc0, 0xdd, 0x49, 0x0d, + 0x2b, 0x5b, 0x44, 0x63, 0x77, 0xd2, 0x98, 0xef, 0xf6, 0x46, 0x70, 0x90, + 0x5c, 0x20, 0xee, 0x9c, 0x3f, 0x6c, 0x19, 0x41, 0x77, 0xd1, 0x8b, 0x68, + 0xad, 0x83, 0xfd, 0xf9, 0x00, 0x7e, 0x49, 0xfc, 0xf7, 0x58, 0x3a, 0x46, + 0xf2, 0x46, 0xfc, 0x57, 0x48, 0xa4, 0x8e, 0x30, 0x67, 0x0b, 0xe4, 0xc0, + 0xfe, 0x62, 0x53, 0xfc, 0x08, 0x8c, 0x81, 0x6e, 0x72, 0x40, 0x6b, 0x97, + 0x31, 0x40, 0x57, 0x6d, 0x72, 0xa7, 0xd8, 0x80, 0x1c, 0xf9, 0xd0, 0xed, + 0xf2, 0x6a, 0x50, 0xe9, 0x2a, 0xbe, 0x4f, 0x6d, 0xed, 0x21, 0xbe, 0x10, + 0x8a, 0x98, 0x7e, 0xa4, 0xea, 0xa2, 0x38, 0x4d, 0xac, 0x64, 0xc3, 0x15, + 0xcc, 0xa5, 0xcc, 0xe7, 0x45, 0x3e, 0x5f, 0xa7, 0x74, 0xce, 0x46, 0xf1, + 0x4b, 0xeb, 0x6b, 0xe1, 0x84, 0xab, 0xd9, 0xe6, 0x5b, 0xd2, 0xae, 0xe1, + 0xf2, 0xcb, 0x95, 0xf8, 0xf4, 0xe5, 0x20, 0xbe, 0x7c, 0x99, 0xfc, 0xce, + 0xa3, 0xbd, 0x12, 0x42, 0xa4, 0xda, 0x84, 0x28, 0x5a, 0xad, 0xf8, 0xa8, + 0x36, 0x16, 0xbd, 0x00, 0xa9, 0x8d, 0x8e, 0xba, 0x35, 0x67, 0xec, 0x1a, + 0x40, 0xc2, 0x39, 0xe5, 0xee, 0x85, 0xa3, 0xae, 0x2a, 0x9c, 0x16, 0xd8, + 0x54, 0xda, 0x0b, 0xbf, 0xdd, 0xa5, 0xbe, 0xc3, 0xdc, 0x9c, 0x77, 0x73, + 0xd3, 0xa5, 0xde, 0x53, 0xb8, 0xdf, 0x83, 0xca, 0xd2, 0x33, 0xd5, 0xce, + 0xa8, 0x23, 0x39, 0xa3, 0x77, 0x9c, 0xeb, 0xeb, 0x77, 0xfb, 0x66, 0xd4, + 0x04, 0xf7, 0x7e, 0xa1, 0x9c, 0x9b, 0x6a, 0xfb, 0x31, 0xee, 0x33, 0x73, + 0xef, 0xee, 0xe3, 0x63, 0xdc, 0x63, 0x39, 0xdf, 0xe0, 0x2d, 0xf3, 0x0d, + 0x72, 0xbe, 0xe3, 0x4b, 0xe6, 0xdb, 0xbd, 0x64, 0xbe, 0xdd, 0x4b, 0xe6, + 0x4b, 0x91, 0xab, 0xff, 0x22, 0x86, 0xc2, 0xa5, 0xb1, 0x55, 0x7b, 0xe0, + 0x96, 0xb9, 0x07, 0x38, 0xf7, 0x01, 0xb1, 0x90, 0x29, 0x8d, 0x53, 0x6d, + 0xef, 0x5c, 0x32, 0xf7, 0x4e, 0xce, 0xbd, 0x38, 0x8e, 0x4e, 0x2d, 0x12, + 0x62, 0xa3, 0x25, 0x84, 0x6a, 0x9b, 0x7a, 0x17, 0x9a, 0x33, 0x5d, 0xc4, + 0x4e, 0x25, 0x12, 0xf3, 0x1e, 0x98, 0x83, 0xf5, 0x5e, 0x1f, 0x16, 0x6a, + 0x17, 0xb9, 0x51, 0x5d, 0xfe, 0xfb, 0x9a, 0x02, 0x6a, 0xfd, 0x1b, 0xb9, + 0x10, 0xc7, 0x88, 0xe9, 0xfd, 0x8a, 0x10, 0xa7, 0xd6, 0x24, 0x06, 0xbc, + 0x48, 0xf4, 0xd5, 0xc0, 0x24, 0x86, 0x7c, 0x65, 0x2e, 0x2c, 0xed, 0x73, + 0xdc, 0xed, 0x53, 0x74, 0xfb, 0x08, 0xf1, 0xe1, 0xbd, 0x57, 0xc4, 0x5b, + 0x2d, 0x61, 0xbc, 0x4d, 0x4e, 0x9e, 0x2c, 0x2e, 0xea, 0x8a, 0xd4, 0x0d, + 0x78, 0x4e, 0x59, 0x7e, 0xc6, 0x34, 0xb4, 0xc3, 0xff, 0xad, 0xfe, 0x04, + 0x8c, 0x29, 0xdb, 0xbc, 0x78, 0x3d, 0x89, 0x27, 0x2b, 0x61, 0xf4, 0xee, + 0x53, 0xb2, 0xe9, 0x2a, 0x18, 0xce, 0x4a, 0x25, 0x9b, 0xd2, 0x20, 0x79, + 0xa3, 0x36, 0x1e, 0x35, 0x8d, 0xec, 0x65, 0xbe, 0xac, 0x4e, 0xde, 0x2e, + 0x06, 0x95, 0x63, 0x04, 0xf1, 0x6c, 0xfe, 0x7d, 0xcc, 0xfb, 0xa4, 0x86, + 0x49, 0xed, 0xe4, 0xc0, 0x27, 0xa4, 0x86, 0x05, 0x48, 0x44, 0x15, 0x7b, + 0xf2, 0x9e, 0xd3, 0x8d, 0x10, 0xf0, 0xb7, 0xf9, 0x70, 0xd1, 0x1c, 0xb6, + 0xea, 0xb1, 0x16, 0xe7, 0x5b, 0xb9, 0x07, 0xcb, 0x54, 0x44, 0x66, 0x96, + 0x8e, 0x15, 0xe1, 0x58, 0x11, 0x7c, 0x92, 0x13, 0xa2, 0xd2, 0x36, 0xe2, + 0x0b, 0x30, 0x19, 0x47, 0x04, 0x57, 0x0a, 0x5b, 0xfc, 0xa8, 0x09, 0x43, + 0x6d, 0x56, 0xb1, 0x3d, 0xaf, 0x29, 0xdd, 0x79, 0xe8, 0x5e, 0xdb, 0x8c, + 0x1e, 0xc6, 0x51, 0xc6, 0xc3, 0xba, 0x76, 0x4c, 0x55, 0x36, 0x4e, 0x07, + 0x50, 0x3d, 0xf5, 0x99, 0x78, 0x9f, 0x7a, 0xf8, 0xc6, 0xbd, 0xac, 0x17, + 0xc9, 0x00, 0xaa, 0xdc, 0xb9, 0x85, 0xf8, 0xb8, 0xad, 0x0e, 0x17, 0x39, + 0x5f, 0xf4, 0x2f, 0x03, 0xf0, 0x4e, 0x05, 0xe0, 0x9b, 0x52, 0x30, 0xd3, + 0x1e, 0x80, 0x67, 0x46, 0xfe, 0x56, 0x10, 0x30, 0xa7, 0xb1, 0x5d, 0x6f, + 0xc0, 0x78, 0x9e, 0x45, 0xda, 0xfc, 0x19, 0x06, 0xdc, 0xef, 0x2a, 0x9e, + 0xca, 0x6b, 0x08, 0x1d, 0x10, 0xa2, 0xd1, 0x16, 0x22, 0x96, 0xf4, 0x60, + 0xd6, 0x1c, 0x8e, 0x06, 0xb8, 0x8e, 0x61, 0x4b, 0x6a, 0x8e, 0x0f, 0xea, + 0x8c, 0x91, 0x39, 0xc7, 0xa8, 0x37, 0x4f, 0xa8, 0x4a, 0xef, 0xf4, 0x1e, + 0xc1, 0x98, 0xfa, 0x1e, 0xf0, 0x0a, 0x51, 0xd3, 0xd6, 0x34, 0x70, 0x9e, + 0xda, 0x3c, 0x13, 0x8b, 0xf5, 0x0e, 0x29, 0xc0, 0xfa, 0x39, 0x1f, 0xfc, + 0x53, 0xff, 0xc5, 0x3a, 0x2b, 0x44, 0xe1, 0x5e, 0x81, 0x77, 0xad, 0x6c, + 0xbc, 0x02, 0x46, 0xea, 0x24, 0xc2, 0xb8, 0xf4, 0xa2, 0x10, 0xdb, 0xdb, + 0x43, 0x78, 0xcd, 0x32, 0x76, 0x7d, 0xec, 0x15, 0xb8, 0x98, 0xcc, 0x0e, + 0xd6, 0x53, 0xb7, 0xae, 0x29, 0x51, 0x54, 0xe5, 0x8d, 0xcc, 0x15, 0x85, + 0x4b, 0x9f, 0x31, 0xf5, 0x9d, 0x4a, 0x10, 0x55, 0x27, 0x82, 0xe8, 0x98, + 0xf3, 0xa3, 0x62, 0x2a, 0x08, 0xef, 0xa4, 0x79, 0xfd, 0x41, 0xb8, 0xe3, + 0x58, 0x27, 0xd1, 0x8c, 0x8b, 0x2f, 0x1b, 0xf3, 0xc7, 0x89, 0x93, 0xed, + 0x88, 0xe2, 0x37, 0x05, 0x13, 0x17, 0x0b, 0x41, 0xa8, 0x27, 0x74, 0xd4, + 0xbb, 0xf5, 0x4e, 0x47, 0xb5, 0xe9, 0x61, 0x5e, 0x1c, 0xe5, 0x61, 0xb7, + 0x9e, 0x74, 0xf1, 0xd3, 0xa3, 0x74, 0xb0, 0xae, 0x6c, 0x98, 0x26, 0x95, + 0xf9, 0xec, 0x9c, 0x75, 0x43, 0xec, 0x8f, 0xa5, 0x59, 0x47, 0x2a, 0xe0, + 0xb3, 0xd7, 0xb1, 0x8e, 0xb0, 0x38, 0xb9, 0xba, 0x5f, 0xa1, 0xf8, 0xec, + 0xef, 0x6a, 0x7e, 0x88, 0x9a, 0x5f, 0xfc, 0x3f, 0x35, 0x5f, 0x85, 0x3a, + 0xe5, 0xc1, 0x98, 0x19, 0xc0, 0x6f, 0xac, 0xa6, 0x73, 0x8d, 0x08, 0x20, + 0xd5, 0xa6, 0x23, 0x72, 0xc2, 0xc2, 0x8b, 0xdc, 0x5b, 0xdc, 0x71, 0x6b, + 0x3d, 0x04, 0x76, 0x92, 0x53, 0x15, 0xd4, 0x86, 0xbb, 0x27, 0x82, 0xd4, + 0x29, 0x55, 0x59, 0x4f, 0x9d, 0xdf, 0x91, 0xbc, 0x21, 0xd2, 0x31, 0x23, + 0x1e, 0x57, 0x12, 0xa9, 0xbf, 0x43, 0x49, 0x3b, 0x62, 0xd4, 0xd1, 0x05, + 0x7d, 0x91, 0x83, 0x5d, 0x2e, 0x07, 0x67, 0x62, 0x25, 0xed, 0x58, 0x51, + 0x28, 0xf1, 0xef, 0x01, 0xea, 0xe7, 0xf5, 0xb6, 0x92, 0x76, 0xbe, 0x4a, + 0xff, 0xd3, 0xcb, 0xf1, 0x1e, 0x99, 0x36, 0xb2, 0xbd, 0xcc, 0xcf, 0x25, + 0x62, 0x63, 0x92, 0x19, 0x9c, 0xaf, 0xa5, 0xa6, 0x36, 0x07, 0x18, 0xe3, + 0x75, 0x71, 0x9a, 0xde, 0x62, 0x98, 0xfd, 0x46, 0xf3, 0x46, 0x74, 0x98, + 0x7c, 0x1f, 0x2d, 0x6b, 0xe9, 0x30, 0xfd, 0xc4, 0x28, 0xf3, 0xf4, 0x36, + 0x9f, 0x9d, 0xcc, 0x1b, 0xe9, 0x2e, 0x57, 0x53, 0xa5, 0xaf, 0x90, 0x31, + 0x49, 0x6f, 0x11, 0xc1, 0x5b, 0x2d, 0x52, 0x5f, 0x1b, 0xa8, 0xaf, 0x8b, + 0xba, 0x2a, 0xf1, 0x70, 0x4d, 0x84, 0x5a, 0x42, 0x5e, 0xc9, 0xcb, 0x4b, + 0x49, 0x21, 0xaa, 0xec, 0x20, 0x2a, 0x27, 0xcc, 0xf4, 0x7a, 0x25, 0x16, + 0x31, 0x95, 0xbb, 0xd8, 0xce, 0x1c, 0xce, 0x6d, 0xf2, 0xba, 0xde, 0xf6, + 0x84, 0x10, 0x21, 0x5b, 0x47, 0xcd, 0x84, 0x49, 0xdc, 0xc4, 0xfa, 0x8e, + 0xb8, 0xcf, 0x75, 0x04, 0xe7, 0x16, 0xc8, 0xe7, 0x08, 0xf9, 0x1c, 0xc6, + 0x9b, 0xb7, 0x70, 0x9a, 0x5a, 0xeb, 0xe9, 0x27, 0xa7, 0xb3, 0xe1, 0xa1, + 0x2d, 0xde, 0x6f, 0xf1, 0x71, 0xbf, 0xe4, 0x34, 0xdb, 0xbc, 0x78, 0x21, + 0x89, 0xcd, 0xc4, 0x47, 0xe6, 0x29, 0x25, 0xeb, 0x90, 0xdb, 0xa9, 0x0a, + 0x25, 0x4b, 0x17, 0xf5, 0x0d, 0xa7, 0xcf, 0xf0, 0x6d, 0x2f, 0x39, 0xdd, + 0x17, 0xbe, 0x95, 0xd3, 0x2c, 0xbe, 0xcc, 0xf7, 0x33, 0xf9, 0x83, 0x98, + 0xf1, 0xf9, 0x11, 0x99, 0xf2, 0x21, 0x30, 0xa5, 0x92, 0x5f, 0x0a, 0xfd, + 0x41, 0x36, 0x1e, 0x80, 0x91, 0x3e, 0x89, 0x08, 0x12, 0x13, 0x1a, 0xfe, + 0xaa, 0xc5, 0x87, 0x63, 0x31, 0x23, 0xb3, 0x93, 0x3c, 0x5d, 0x39, 0x37, + 0xc4, 0x88, 0x8c, 0x68, 0xd4, 0x53, 0xe2, 0xab, 0xaf, 0xd9, 0x0f, 0x6d, + 0xca, 0xe5, 0xe0, 0x1e, 0x8f, 0x9d, 0x8d, 0x6a, 0x30, 0x76, 0xfd, 0x84, + 0xb8, 0xb8, 0x30, 0x21, 0x44, 0x67, 0xbb, 0x79, 0xee, 0x23, 0xaf, 0x41, + 0x2d, 0x54, 0x71, 0x7e, 0xae, 0x34, 0x7e, 0xd5, 0x94, 0x06, 0xff, 0x01, + 0x77, 0xfc, 0xeb, 0x6f, 0x32, 0x8a, 0xcf, 0xf3, 0x12, 0x9f, 0x42, 0x04, + 0x6c, 0x33, 0x32, 0x4b, 0x3d, 0xdc, 0x97, 0x34, 0xb8, 0x7f, 0x4d, 0x4e, + 0x33, 0xbf, 0x7b, 0x92, 0xb1, 0xe8, 0x16, 0xbe, 0x73, 0xa9, 0x58, 0xe2, + 0x70, 0xbd, 0xb9, 0x15, 0x7f, 0xa3, 0x7b, 0x51, 0x63, 0xfe, 0x10, 0xcf, + 0xba, 0x1a, 0x45, 0xec, 0x4f, 0x56, 0xa2, 0x91, 0x98, 0x7f, 0x82, 0x98, + 0xdf, 0x3c, 0x4b, 0xad, 0x99, 0x6a, 0x67, 0x7e, 0x25, 0xdf, 0xbb, 0x94, + 0xde, 0xd9, 0x1e, 0xd7, 0x57, 0x3d, 0x32, 0xed, 0xc1, 0x9b, 0xd6, 0x5a, + 0x7a, 0x98, 0xb4, 0xf2, 0xc8, 0xac, 0xc4, 0xfb, 0x3a, 0xe5, 0x41, 0x62, + 0x3f, 0x7a, 0x87, 0x8a, 0x19, 0x6b, 0xad, 0xe2, 0x77, 0xb1, 0xef, 0x83, + 0x93, 0x29, 0xe1, 0xde, 0x6b, 0xc7, 0xac, 0x53, 0x4b, 0x70, 0xdf, 0x73, + 0x1b, 0xaf, 0x23, 0xb5, 0x03, 0x25, 0x7d, 0xd7, 0xbb, 0x98, 0xaf, 0xe7, + 0xcb, 0xf8, 0x7e, 0x96, 0xed, 0xbe, 0x29, 0x68, 0x95, 0xc4, 0xf0, 0x3a, + 0x62, 0x7c, 0x92, 0x38, 0x79, 0x78, 0x5a, 0xe0, 0x0d, 0xd6, 0x89, 0x42, + 0xd2, 0xb0, 0x76, 0x2a, 0x46, 0xba, 0x47, 0x49, 0x64, 0x57, 0x96, 0x6b, + 0xe4, 0xdd, 0xac, 0x73, 0xb8, 0x43, 0xe0, 0xe7, 0x16, 0xb4, 0x00, 0xb1, + 0xfd, 0x6f, 0xac, 0x59, 0xff, 0x51, 0xae, 0x91, 0xc9, 0x42, 0x25, 0x42, + 0x2d, 0xd4, 0x7c, 0x62, 0xb9, 0x9b, 0x58, 0x3e, 0x44, 0x3e, 0x8c, 0xd0, + 0x13, 0x6c, 0x26, 0x96, 0x57, 0xb4, 0x19, 0xd9, 0x2e, 0xfa, 0x69, 0xcf, + 0xea, 0x08, 0x71, 0x1a, 0xa7, 0x87, 0x1d, 0x41, 0x07, 0xe7, 0x4a, 0x4f, + 0x1b, 0x91, 0x0e, 0xe2, 0x5f, 0x65, 0x9f, 0xd7, 0xd8, 0x67, 0xa1, 0x4e, + 0x7a, 0xed, 0x00, 0x5e, 0x60, 0x1f, 0x33, 0xe9, 0xb8, 0x3a, 0x21, 0xf1, + 0x3f, 0x86, 0x44, 0x46, 0xe2, 0xdf, 0x59, 0xd6, 0x4a, 0xdf, 0x2f, 0xf1, + 0x4f, 0x0c, 0xe6, 0x89, 0xc1, 0x12, 0x07, 0x06, 0x24, 0x07, 0x6a, 0xe8, + 0x2b, 0x4e, 0xd0, 0x57, 0x54, 0xd9, 0x51, 0xe2, 0x5f, 0xf2, 0xa1, 0xe4, + 0x2d, 0xba, 0xca, 0x1c, 0x58, 0xef, 0xce, 0x27, 0x35, 0x20, 0x88, 0xa6, + 0x49, 0x43, 0x57, 0x95, 0xff, 0x14, 0x4f, 0x98, 0xe6, 0xfc, 0x76, 0xfa, + 0x83, 0x2f, 0xdb, 0x62, 0xcc, 0x7b, 0x10, 0xf7, 0x9c, 0x08, 0xa9, 0x12, + 0xe7, 0xf5, 0x93, 0x41, 0x84, 0x26, 0x25, 0x0f, 0xb2, 0xe3, 0x11, 0x62, + 0xc4, 0xf2, 0xfc, 0x96, 0xf8, 0x8f, 0x12, 0x17, 0xaa, 0xd2, 0xcd, 0x31, + 0x6a, 0xa6, 0x74, 0xb4, 0x4e, 0x1a, 0x03, 0x27, 0x70, 0x55, 0xbc, 0x11, + 0x33, 0x33, 0x7b, 0x99, 0xff, 0x6d, 0xc9, 0x18, 0xf7, 0x4a, 0xc7, 0xdd, + 0x37, 0xc7, 0x70, 0x39, 0xe1, 0x6c, 0xb1, 0x82, 0x65, 0xaf, 0xad, 0x61, + 0x4b, 0x1e, 0xd8, 0x96, 0xa7, 0xd9, 0x35, 0x3d, 0xab, 0xfc, 0xb8, 0x86, + 0xc3, 0x44, 0x7f, 0xbf, 0xee, 0x30, 0xff, 0x01, 0xea, 0x7d, 0xe9, 0x9d, + 0x92, 0x07, 0xff, 0x79, 0xf9, 0x8c, 0xf9, 0x2b, 0x4f, 0xe9, 0xef, 0xdb, + 0xde, 0xc5, 0x33, 0xe7, 0x16, 0x62, 0xb0, 0x93, 0x18, 0xec, 0x61, 0x8e, + 0xb6, 0x5b, 0xe4, 0x36, 0xf3, 0x99, 0x55, 0x03, 0xf4, 0xd4, 0x4d, 0x7d, + 0xd5, 0xd4, 0xb4, 0x7d, 0xd4, 0xa7, 0x77, 0xcd, 0x4a, 0x7a, 0x70, 0x87, + 0xda, 0xd9, 0x41, 0xdd, 0xec, 0x52, 0x1e, 0x72, 0xb1, 0x95, 0x26, 0x8e, + 0x34, 0x25, 0x4d, 0x5f, 0xeb, 0x63, 0xed, 0x38, 0x14, 0x5e, 0xf4, 0xdf, + 0x32, 0x4e, 0xe9, 0xb9, 0x8d, 0xb8, 0x2c, 0xbf, 0xcf, 0xba, 0x3a, 0xb4, + 0x16, 0xaa, 0xbd, 0x56, 0x51, 0x6d, 0x79, 0xc6, 0x50, 0xf1, 0x03, 0xea, + 0xec, 0xc2, 0x26, 0x79, 0xd6, 0xe0, 0xba, 0xd8, 0x16, 0x31, 0x63, 0xd1, + 0x83, 0xc4, 0xd5, 0xab, 0xdf, 0x39, 0x7b, 0x94, 0xf0, 0x36, 0x9c, 0x57, + 0x6f, 0xfa, 0x68, 0xa9, 0x0f, 0x6b, 0x6f, 0xe2, 0x4d, 0xc3, 0x33, 0x2d, + 0x51, 0xe2, 0x51, 0x62, 0x4d, 0x43, 0xe1, 0x95, 0x4a, 0xbc, 0xf1, 0x4a, + 0x10, 0xaf, 0xbf, 0x22, 0xc4, 0x68, 0x12, 0x3c, 0xe1, 0x08, 0xf1, 0x50, + 0x72, 0x0d, 0x8e, 0xeb, 0xb1, 0xe8, 0x0b, 0xae, 0x8f, 0x75, 0xe8, 0x63, + 0x8d, 0x81, 0xb3, 0xb8, 0x21, 0x0a, 0x2e, 0xa7, 0x13, 0xe4, 0x5b, 0x09, + 0x8b, 0xae, 0xdf, 0xad, 0xd5, 0x70, 0x81, 0xf8, 0x0b, 0x11, 0x7f, 0xbf, + 0xa3, 0xe6, 0x5e, 0x2d, 0x6b, 0xee, 0xaa, 0x02, 0xf9, 0xd8, 0x16, 0x40, + 0x8f, 0x5c, 0x0b, 0x71, 0x38, 0x7c, 0x13, 0x87, 0xac, 0xbd, 0xdc, 0xf3, + 0xb3, 0x96, 0x11, 0xef, 0x24, 0x1e, 0x67, 0x2c, 0xc3, 0xe9, 0xa0, 0x9f, + 0x1d, 0x76, 0x31, 0x49, 0xed, 0x8d, 0x49, 0x5c, 0x12, 0x87, 0xcc, 0xc9, + 0x3e, 0xf6, 0x39, 0xcd, 0x3e, 0x63, 0x65, 0x3f, 0xfb, 0x1e, 0x12, 0x69, + 0xe9, 0x67, 0xa3, 0xc4, 0xe0, 0x3e, 0xd7, 0xcf, 0x4a, 0xff, 0x2a, 0xbd, + 0xab, 0x8c, 0xb3, 0xdd, 0x8d, 0xb3, 0xfb, 0x26, 0x0e, 0xa9, 0x61, 0xb5, + 0x12, 0x7f, 0x0f, 0x60, 0xec, 0xa5, 0x1a, 0x84, 0xcc, 0x3b, 0x71, 0x3e, + 0xf3, 0x80, 0x1a, 0x31, 0xa1, 0xd7, 0xdb, 0x25, 0x3c, 0x6e, 0x2e, 0xa6, + 0x90, 0xcf, 0xbf, 0x23, 0xf2, 0x61, 0xc3, 0x39, 0xeb, 0x7a, 0xd2, 0x01, + 0x7a, 0xc4, 0x1b, 0xc2, 0x13, 0x33, 0xce, 0x6d, 0xa1, 0x2f, 0x6b, 0xf2, + 0x96, 0xfc, 0xdd, 0x9a, 0xc2, 0xfb, 0x02, 0x75, 0xa5, 0x75, 0xaa, 0xf4, + 0x74, 0x23, 0xe4, 0xdc, 0xa8, 0x59, 0xf2, 0x77, 0xb1, 0xc2, 0xa7, 0xaa, + 0xd4, 0x73, 0x4f, 0x9b, 0x1c, 0x37, 0x4d, 0x0d, 0x59, 0x1c, 0xfb, 0x1b, + 0x5d, 0x1e, 0x21, 0x06, 0x87, 0xa5, 0xd7, 0xa2, 0x2f, 0xe1, 0x59, 0x7d, + 0x89, 0xa6, 0xee, 0xf6, 0xc2, 0x94, 0x6d, 0x8e, 0xf2, 0x10, 0xd7, 0xa0, + 0x99, 0x83, 0x4a, 0x9a, 0xb5, 0x79, 0x2f, 0xf1, 0xd5, 0xc3, 0x1a, 0x7c, + 0xd9, 0x6a, 0x26, 0x87, 0x05, 0xeb, 0xd0, 0x0d, 0xb1, 0xcf, 0x5c, 0x3c, + 0xd3, 0xc9, 0xf3, 0x5c, 0x9c, 0x71, 0x57, 0xb3, 0x76, 0xaf, 0x63, 0xbd, + 0xe6, 0x69, 0x91, 0x39, 0xfd, 0x32, 0x26, 0x1a, 0x57, 0xb5, 0x19, 0x03, + 0x1b, 0xbd, 0x01, 0xe4, 0x88, 0xf7, 0x57, 0x59, 0x83, 0xf2, 0xdc, 0xd3, + 0xc9, 0xa2, 0x91, 0xca, 0x62, 0x04, 0x1b, 0xb9, 0xa7, 0x3c, 0x03, 0x39, + 0xff, 0x18, 0x2b, 0x9d, 0x91, 0xb7, 0xb3, 0xb6, 0x8d, 0x97, 0xb9, 0x7d, + 0x05, 0x09, 0x4b, 0x72, 0x7b, 0x9e, 0xb5, 0x6d, 0xdc, 0xe5, 0xb6, 0x91, + 0x92, 0x7c, 0xae, 0x28, 0xd7, 0xb4, 0x4f, 0x20, 0x39, 0x7c, 0x6b, 0x3d, + 0x93, 0x78, 0x5e, 0xeb, 0x93, 0xde, 0x36, 0x9f, 0x97, 0x35, 0x49, 0xd6, + 0xa2, 0xc5, 0xba, 0xa4, 0xc9, 0xfb, 0x84, 0x4c, 0xe3, 0xc4, 0x1e, 0xe1, + 0x29, 0xdd, 0x49, 0x9c, 0xfb, 0xd0, 0x1b, 0x4c, 0xa5, 0xee, 0x43, 0x26, + 0x32, 0xa7, 0x61, 0x53, 0xbe, 0xa1, 0x2f, 0x60, 0x83, 0xef, 0x28, 0xb0, + 0xfe, 0x44, 0x43, 0xe6, 0x96, 0x3b, 0x89, 0x8f, 0x73, 0x9a, 0x16, 0x9a, + 0x58, 0x2e, 0xdf, 0xc1, 0x67, 0xb9, 0xdb, 0xde, 0x49, 0xa4, 0x7f, 0xdf, + 0x9d, 0xc4, 0x0b, 0xe4, 0xc7, 0x58, 0xe9, 0x4e, 0xc2, 0xf9, 0x5e, 0x8b, + 0x17, 0x33, 0x61, 0xec, 0xfe, 0xa8, 0x5d, 0xc5, 0xe5, 0x9c, 0x11, 0x39, + 0x8e, 0xdd, 0xe8, 0x77, 0xef, 0x1f, 0x90, 0xf5, 0xdb, 0xbb, 0xf0, 0x4f, + 0xed, 0xf2, 0xfe, 0x21, 0x25, 0xd7, 0x38, 0xce, 0xe5, 0x43, 0xa3, 0xde, + 0xac, 0x67, 0x2d, 0xd8, 0xb1, 0x46, 0xc1, 0x43, 0xc9, 0x3b, 0x5d, 0x6c, + 0x8f, 0x17, 0x8d, 0x74, 0x94, 0xcf, 0xee, 0x99, 0x90, 0x35, 0xf2, 0x71, + 0x9e, 0x17, 0xa1, 0x35, 0xda, 0xbd, 0xaa, 0xc8, 0x37, 0x45, 0xae, 0x28, + 0x86, 0x73, 0x18, 0xf2, 0x8e, 0x20, 0x71, 0xce, 0xab, 0x18, 0xf3, 0x1f, + 0x7a, 0x8d, 0x54, 0xbd, 0x8b, 0x99, 0xc7, 0x79, 0x76, 0x93, 0x7f, 0x7b, + 0xe5, 0xb9, 0x0f, 0x1b, 0x39, 0xe6, 0x07, 0x6b, 0xe4, 0x59, 0xf4, 0x73, + 0x91, 0x5d, 0x66, 0x38, 0x0b, 0x8a, 0xc6, 0xdc, 0x80, 0xfa, 0x24, 0x35, + 0xfc, 0x71, 0x6a, 0xb8, 0xf4, 0x2c, 0xbd, 0xf4, 0x2c, 0x4d, 0xf3, 0x71, + 0xaf, 0x91, 0xb9, 0x4e, 0xbd, 0xe3, 0x98, 0x7d, 0xbd, 0x8a, 0xd1, 0x7b, + 0x82, 0xfa, 0xbf, 0x53, 0x29, 0x8d, 0xb9, 0xb2, 0x3c, 0xe6, 0xdd, 0x05, + 0x4d, 0xe9, 0xcc, 0x83, 0xba, 0x83, 0xe8, 0x36, 0x8b, 0xda, 0x51, 0xac, + 0x24, 0xc7, 0x4c, 0xb9, 0x66, 0xc6, 0xd6, 0xca, 0xd8, 0x14, 0x5c, 0x69, + 0x91, 0xef, 0xb6, 0xca, 0x38, 0x9c, 0x2a, 0x3b, 0x45, 0xed, 0x7d, 0xc5, + 0x57, 0xd6, 0x2f, 0xcf, 0x16, 0x6b, 0x19, 0x9c, 0x30, 0x42, 0x3e, 0xb3, + 0x0e, 0xa3, 0xb4, 0x81, 0x41, 0xb3, 0x19, 0x39, 0xdd, 0x8f, 0x2d, 0xd6, + 0x17, 0x82, 0x3a, 0xc9, 0xf7, 0x81, 0xa7, 0x5e, 0xe2, 0x19, 0xde, 0xbc, + 0x86, 0x58, 0xf2, 0x39, 0x1c, 0xd3, 0x77, 0xd1, 0x0f, 0x6e, 0xc5, 0xeb, + 0xae, 0x9e, 0xd8, 0xc4, 0xb3, 0x42, 0x0c, 0xd9, 0xb2, 0xd6, 0xdd, 0x32, + 0xb6, 0xbc, 0x93, 0xb8, 0x24, 0xb2, 0xa5, 0x31, 0x9c, 0x6d, 0x56, 0x86, + 0x71, 0x7d, 0xa3, 0xbb, 0x3b, 0xa8, 0xbb, 0x15, 0xa6, 0xe7, 0xae, 0x4a, + 0xea, 0xee, 0x56, 0xeb, 0xcf, 0xf1, 0x14, 0x39, 0x5e, 0x65, 0x7e, 0x26, + 0x9e, 0x0e, 0xcb, 0x31, 0xa9, 0xaf, 0x35, 0x4b, 0xc7, 0xff, 0x90, 0x63, + 0xca, 0x39, 0x64, 0x3d, 0x3c, 0x2f, 0x0e, 0xd5, 0xca, 0x31, 0x07, 0x95, + 0x8d, 0xe4, 0xd4, 0x3c, 0x4b, 0xef, 0x0f, 0xc8, 0xa7, 0x05, 0xe6, 0xa7, + 0xf1, 0x36, 0x7c, 0x6a, 0x24, 0x9f, 0x9e, 0x58, 0xc2, 0xa7, 0x83, 0x79, + 0xe9, 0xbd, 0x14, 0xb4, 0xb4, 0xfd, 0x29, 0x75, 0x45, 0x08, 0x7f, 0xdb, + 0x0d, 0x71, 0xc6, 0xf5, 0xbe, 0xd2, 0xef, 0xa6, 0x95, 0xee, 0x59, 0xa9, + 0x4f, 0xd5, 0x08, 0x92, 0x4f, 0x1b, 0xc8, 0xa7, 0x7e, 0xf2, 0xe9, 0x69, + 0x53, 0x34, 0xee, 0x48, 0x1a, 0xa9, 0x79, 0xfa, 0x9a, 0x75, 0xe4, 0xd4, + 0x3b, 0xe4, 0xd4, 0x48, 0xb1, 0xa4, 0x53, 0xfb, 0xb8, 0xee, 0xfb, 0xa9, + 0x53, 0xeb, 0x8a, 0x52, 0xdb, 0x1c, 0xe2, 0x3f, 0x80, 0xcf, 0xc9, 0xa9, + 0xd9, 0xa4, 0xab, 0x53, 0xd6, 0xef, 0x90, 0xd8, 0x75, 0x5a, 0xf2, 0x89, + 0x3a, 0x95, 0x2f, 0x36, 0x59, 0xa7, 0xb9, 0xa6, 0xf1, 0xbc, 0x71, 0xbd, + 0x87, 0x9c, 0xf2, 0xb5, 0x1b, 0xe7, 0x2e, 0x13, 0xbb, 0x81, 0x18, 0xf4, + 0x88, 0x2d, 0xd7, 0xc4, 0x1a, 0xcb, 0x3a, 0x79, 0x90, 0xf8, 0xef, 0xa1, + 0x66, 0xf4, 0x16, 0x6d, 0xec, 0x2d, 0x2e, 0xdd, 0x53, 0xd6, 0xa1, 0xdb, + 0xee, 0xcb, 0xb8, 0xff, 0xf6, 0xed, 0xac, 0x57, 0xb7, 0x6d, 0x97, 0x7c, + 0x5d, 0xe6, 0x97, 0x7c, 0x1d, 0xce, 0xbf, 0xa6, 0xde, 0xfe, 0x1d, 0x79, + 0xa7, 0x26, 0xc4, 0x51, 0x4b, 0xde, 0x49, 0x48, 0xdf, 0xa3, 0x60, 0xc8, + 0x92, 0xf7, 0x6a, 0x1d, 0x51, 0x15, 0x46, 0xe4, 0xfb, 0xf8, 0x4a, 0x64, + 0xc3, 0x4e, 0xdc, 0xe7, 0xd6, 0x48, 0x43, 0xef, 0x63, 0xad, 0x9b, 0x2f, + 0x9f, 0xfd, 0x66, 0x78, 0x3e, 0x7b, 0x87, 0x75, 0xea, 0x28, 0xcf, 0x79, + 0x43, 0x85, 0xaf, 0xc4, 0x7c, 0x58, 0xc5, 0x88, 0x79, 0xf3, 0x8e, 0xd2, + 0xd5, 0xb1, 0xc3, 0x7c, 0x36, 0x56, 0x58, 0xac, 0x51, 0xd4, 0x4c, 0x53, + 0x88, 0xad, 0xe6, 0x7f, 0x8b, 0x2d, 0xdf, 0x7a, 0x57, 0x88, 0x49, 0xc6, + 0x70, 0xc1, 0xc2, 0x6e, 0x1f, 0x62, 0x7d, 0xd7, 0x59, 0xd7, 0x3f, 0x58, + 0x63, 0x64, 0x0a, 0x4a, 0xa2, 0x77, 0x83, 0x22, 0xbd, 0x9e, 0xa7, 0xab, + 0x82, 0xef, 0xb4, 0xd0, 0x1b, 0x5d, 0x61, 0x06, 0xfd, 0xfc, 0x7e, 0xc6, + 0x32, 0x22, 0x47, 0xf8, 0x77, 0x4b, 0x4a, 0x8e, 0x21, 0x44, 0x87, 0x25, + 0xef, 0xbb, 0x46, 0xd4, 0xdc, 0x44, 0x56, 0x54, 0x99, 0x17, 0xa8, 0x4d, + 0x46, 0x66, 0x44, 0x91, 0x3e, 0x3b, 0x0a, 0x57, 0x67, 0xf9, 0x4c, 0x9b, + 0x88, 0xe0, 0xef, 0x5d, 0xff, 0x1c, 0xa5, 0x66, 0x35, 0xe0, 0x1f, 0x5c, + 0xdd, 0x52, 0xb1, 0xed, 0x25, 0x23, 0xa5, 0x2a, 0x7b, 0x70, 0xc9, 0x32, + 0xf4, 0x9f, 0x32, 0x6e, 0x6a, 0xcd, 0x8b, 0x9d, 0x3c, 0x3f, 0x71, 0x8e, + 0x6c, 0x9f, 0xb7, 0x56, 0xd1, 0x58, 0x3b, 0x7e, 0xdc, 0x22, 0x6b, 0xf7, + 0x2e, 0xf4, 0x34, 0xef, 0xe4, 0x47, 0x45, 0xdd, 0x94, 0xaa, 0x6c, 0xa2, + 0x27, 0x09, 0x4d, 0x85, 0xb0, 0x7d, 0xb5, 0x10, 0xab, 0x56, 0x3b, 0xf8, + 0x3c, 0xd9, 0x14, 0x3f, 0xcb, 0x1a, 0x74, 0xa8, 0xd6, 0x48, 0x03, 0xbf, + 0xc0, 0x66, 0x7a, 0xd9, 0x54, 0x5b, 0x0e, 0xb8, 0x53, 0xae, 0xf1, 0x17, + 0xe8, 0x94, 0x1e, 0xd8, 0x0a, 0x49, 0xbf, 0xe5, 0xe2, 0xb7, 0x74, 0xaf, + 0xc4, 0xd4, 0x1d, 0xc8, 0x8a, 0x4a, 0xd3, 0xe8, 0x9b, 0x65, 0xbd, 0xfd, + 0x20, 0xb6, 0x5c, 0x7f, 0x78, 0x56, 0x7a, 0x60, 0x33, 0xba, 0x5e, 0x11, + 0xcc, 0xc5, 0xf3, 0xcc, 0x45, 0xcc, 0x09, 0xd2, 0x32, 0xf0, 0xac, 0xe5, + 0x84, 0x94, 0x41, 0xe5, 0x51, 0xf2, 0xa1, 0xcf, 0x5f, 0x49, 0x0f, 0xe1, + 0xd0, 0x3f, 0x78, 0x50, 0x7d, 0x40, 0x7a, 0x8a, 0x00, 0xb5, 0xa6, 0xa9, + 0x37, 0xc8, 0xfc, 0xec, 0x48, 0x4a, 0xff, 0x41, 0xac, 0x1f, 0xb8, 0x21, + 0x3a, 0xe9, 0x71, 0x3b, 0xcb, 0x1e, 0xf7, 0x89, 0xe9, 0x34, 0x3d, 0xb0, + 0xa6, 0xc8, 0x3b, 0xb6, 0x54, 0x1b, 0x0f, 0xa4, 0x8f, 0x4a, 0x1f, 0x22, + 0xd7, 0xa0, 0xe3, 0x6a, 0x52, 0x62, 0x57, 0xc7, 0x70, 0xbb, 0x11, 0xc9, + 0x42, 0xde, 0xe9, 0xdc, 0xea, 0x2f, 0xa0, 0xa7, 0xbf, 0xe3, 0x39, 0xa0, + 0x6f, 0x62, 0x2c, 0x86, 0x5f, 0x88, 0xba, 0xa4, 0x17, 0x7d, 0xee, 0x59, + 0x2e, 0xa2, 0xa7, 0xc9, 0xfb, 0x73, 0xf4, 0x09, 0x5e, 0x9e, 0x99, 0xf7, + 0x10, 0x4b, 0x5f, 0xb6, 0x0c, 0xbd, 0x5a, 0x8f, 0xec, 0x78, 0x1d, 0xcf, + 0xa8, 0xf7, 0x53, 0x57, 0x2f, 0xe4, 0x1e, 0x65, 0x3d, 0xf7, 0xb4, 0x47, + 0x78, 0x06, 0x68, 0x9c, 0xca, 0x8a, 0x7a, 0xfa, 0x41, 0x9e, 0x97, 0x51, + 0xdb, 0x16, 0xa7, 0xdf, 0x5e, 0xdc, 0x2b, 0x0f, 0x7e, 0x68, 0x99, 0x70, + 0xdc, 0xdf, 0x41, 0xbd, 0x7b, 0x9a, 0xe7, 0x68, 0x73, 0xb9, 0xde, 0x51, + 0x8a, 0x4b, 0xad, 0xb0, 0x2d, 0xb4, 0xdc, 0x0b, 0xfd, 0xc1, 0xdb, 0xc4, + 0xb4, 0x4e, 0x7a, 0x1f, 0x5f, 0xa9, 0xdf, 0x9f, 0x4d, 0x37, 0xe8, 0x8f, + 0xb0, 0xde, 0xcd, 0x13, 0x2b, 0x4f, 0xac, 0xb6, 0x64, 0x2c, 0xf3, 0x32, + 0x16, 0xfa, 0x4b, 0xe7, 0x7e, 0x0f, 0x7d, 0x49, 0x12, 0x08, 0xcd, 0xfd, + 0x35, 0x79, 0xe5, 0x69, 0x0d, 0x21, 0xbb, 0x8b, 0x31, 0xbe, 0xfa, 0xaf, + 0xdc, 0x9a, 0xfe, 0x49, 0xf4, 0x7b, 0xd8, 0x67, 0xc2, 0x02, 0x9e, 0x39, + 0x01, 0x3c, 0x3d, 0x19, 0xa3, 0x2f, 0xa7, 0x8f, 0x3c, 0xa1, 0xe1, 0xfb, + 0xd3, 0x95, 0xf8, 0xd1, 0x74, 0x10, 0x3b, 0xa6, 0xdd, 0xbb, 0xae, 0x0d, + 0x75, 0x7c, 0xaf, 0x83, 0x67, 0xbb, 0x59, 0x6b, 0x35, 0x3e, 0xa2, 0x87, + 0x5a, 0xa1, 0x78, 0x10, 0x39, 0x00, 0x5d, 0x27, 0x6e, 0x6a, 0x5b, 0x7e, + 0x44, 0x2e, 0x0b, 0x61, 0xae, 0x96, 0x3a, 0xf9, 0xbc, 0xfb, 0x7d, 0x84, + 0xfe, 0x31, 0x23, 0x31, 0x98, 0x27, 0x06, 0xf3, 0xc4, 0xe4, 0x4d, 0x4f, + 0x2d, 0xb1, 0x1c, 0xa7, 0x8f, 0x7e, 0x4e, 0x94, 0xb0, 0xf1, 0xb5, 0x38, + 0x6a, 0x9e, 0x24, 0x7f, 0x55, 0x6a, 0x28, 0xf0, 0xcf, 0xb9, 0x88, 0xbe, + 0xa9, 0x28, 0xf3, 0xff, 0xb7, 0xe5, 0xfc, 0x9f, 0xf1, 0x97, 0xf4, 0xc2, + 0x70, 0x66, 0xd1, 0x80, 0xc9, 0x7c, 0x83, 0xbe, 0x21, 0x3f, 0x34, 0xa8, + 0x21, 0x1b, 0x0d, 0xc1, 0x18, 0x98, 0x84, 0xa7, 0x35, 0x08, 0xb9, 0x76, + 0xa0, 0xe0, 0xae, 0x51, 0x88, 0x31, 0xea, 0x9b, 0xcc, 0xc1, 0xbf, 0xe7, + 0xd0, 0xea, 0x61, 0x3e, 0x1c, 0xc8, 0xb3, 0x35, 0xf0, 0x69, 0x41, 0xde, + 0x7d, 0xc6, 0xd2, 0xdd, 0xf8, 0xc2, 0x1d, 0xf3, 0x93, 0x42, 0x0a, 0xfb, + 0xf3, 0x1f, 0x88, 0xfd, 0xe1, 0x92, 0xc6, 0xa7, 0x79, 0x3e, 0x0a, 0x1d, + 0x28, 0x7b, 0x21, 0x72, 0xb8, 0x9a, 0xeb, 0xbd, 0x9a, 0x74, 0xbd, 0x3f, + 0x6b, 0xe4, 0x80, 0x7a, 0xd4, 0x64, 0xb1, 0xab, 0xb9, 0x21, 0xc6, 0x62, + 0x89, 0x40, 0x29, 0xa6, 0x84, 0x7e, 0x04, 0x15, 0xc4, 0xae, 0x3c, 0x23, + 0x49, 0xfd, 0x90, 0xbf, 0x79, 0x3e, 0x51, 0x9d, 0x88, 0x97, 0xeb, 0x72, + 0x1e, 0x93, 0x6d, 0x81, 0xb2, 0x5f, 0x5d, 0xf4, 0x22, 0x1d, 0x7c, 0x26, + 0xbd, 0xc8, 0x57, 0xa2, 0x2f, 0xdc, 0x71, 0x53, 0x73, 0xb2, 0x7c, 0x63, + 0x34, 0x2f, 0xef, 0xb4, 0x5a, 0xe8, 0x88, 0x15, 0x9c, 0x62, 0xe4, 0x47, + 0x5a, 0x63, 0xfa, 0x30, 0xc7, 0x73, 0x74, 0x9d, 0x5c, 0xde, 0x43, 0xbf, + 0xcc, 0x77, 0x8a, 0x2d, 0xec, 0x23, 0xb5, 0xec, 0x2f, 0xb8, 0xd6, 0x2f, + 0x9a, 0x25, 0xb6, 0x87, 0xf3, 0x6f, 0x79, 0x54, 0x53, 0xae, 0x33, 0x91, + 0x1a, 0x66, 0x3c, 0x0b, 0xba, 0xf4, 0xd6, 0x0e, 0xb5, 0x2d, 0xe1, 0xf6, + 0xcf, 0xaa, 0x32, 0x0e, 0x37, 0x1e, 0xb6, 0x49, 0xcd, 0x32, 0x32, 0xa7, + 0x90, 0x70, 0xfa, 0xa5, 0x39, 0x58, 0x26, 0x63, 0x68, 0x8a, 0xf4, 0x33, + 0x9e, 0x43, 0x61, 0x57, 0x0f, 0xf9, 0x8c, 0xf3, 0xe5, 0x3d, 0x1b, 0x2a, + 0x21, 0xb0, 0x22, 0xe9, 0x9e, 0xf9, 0xcb, 0xff, 0x5f, 0x43, 0xa5, 0x0f, + 0x91, 0x58, 0xfc, 0x5f, 0x69, 0xd7, 0x8a, 0xc0, 0xa8, 0x1a, 0x00, 0x00, + 0x00 }; static const u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 }; static const u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; static struct fw_info bnx2_tpat_fw_06 = { - /* Firmware version: 4.0.5 */ + /* Firmware version: 4.4.22 */ .ver_major = 0x4, - .ver_minor = 0x0, - .ver_fix = 0x5, + .ver_minor = 0x4, + .ver_fix = 0x16, - .start_addr = 0x08000888, + .start_addr = 0x08000488, - .text_addr = 0x08000800, - .text_len = 0x1a90, + .text_addr = 0x08000400, + .text_len = 0x1aa4, .text_index = 0x0, .gz_text = bnx2_TPAT_b06FwText, .gz_text_len = sizeof(bnx2_TPAT_b06FwText), @@ -3686,11 +3639,11 @@ static struct fw_info bnx2_tpat_fw_06 = { .data_index = 0x0, .data = bnx2_TPAT_b06FwData, - .sbss_addr = 0x080022c0, + .sbss_addr = 0x08001ec0, .sbss_len = 0x44, .sbss_index = 0x0, - .bss_addr = 0x08002304, + .bss_addr = 0x08001f04, .bss_len = 0x450, .bss_index = 0x0, @@ -3717,862 +3670,862 @@ static const struct cpu_reg cpu_reg_tpat = { }; static u8 bnx2_TXP_b06FwText[] = { - 0xad, 0x7b, 0x7f, 0x70, 0x9b, 0x75, 0x7a, 0xe7, 0xe7, 0xd5, 0x0f, 0x5b, - 0xb2, 0x65, 0x59, 0x0e, 0x4a, 0x90, 0x77, 0xbd, 0x8d, 0x5e, 0xf4, 0xca, - 0x16, 0xd8, 0x49, 0x5e, 0x25, 0xce, 0xc6, 0x59, 0xab, 0x44, 0x75, 0x1c, - 0xdb, 0x71, 0x1c, 0x30, 0xc1, 0xdd, 0x3a, 0x3d, 0xae, 0xf1, 0x25, 0x26, - 0x31, 0x10, 0xc0, 0xe9, 0xa6, 0x7b, 0x62, 0x8f, 0xd6, 0xc2, 0x76, 0x82, - 0x43, 0x64, 0xbf, 0xce, 0x2a, 0x59, 0x87, 0x4e, 0x67, 0xd6, 0x60, 0x07, - 0x07, 0x56, 0x8e, 0x60, 0xdb, 0x6b, 0xbb, 0x73, 0xbb, 0x83, 0x8e, 0x40, - 0xf0, 0x72, 0x01, 0xb6, 0xfd, 0xa3, 0x47, 0x6f, 0xee, 0xda, 0xcc, 0x02, - 0x59, 0xa0, 0x4b, 0xa0, 0x3b, 0x7b, 0x53, 0x67, 0x0b, 0xbc, 0xf7, 0x79, - 0xde, 0x57, 0x4a, 0xb2, 0x94, 0x4e, 0x67, 0x3a, 0xe7, 0x19, 0x8f, 0xac, - 0xf7, 0xc7, 0xf3, 0x7d, 0x7e, 0x3f, 0x9f, 0xe7, 0xf9, 0x7e, 0x5d, 0x0f, - 0x54, 0xa0, 0xf8, 0x53, 0xc5, 0xdf, 0xe6, 0xe1, 0xd4, 0xe1, 0x8d, 0x6b, - 0xf5, 0xb5, 0xd6, 0x05, 0x37, 0x5c, 0x72, 0xf3, 0xab, 0x0a, 0x30, 0xf0, - 0x01, 0xfe, 0x5d, 0x3f, 0x5f, 0xf9, 0xf7, 0xbd, 0x66, 0xfd, 0x38, 0x81, - 0x40, 0x89, 0x2f, 0xf9, 0x85, 0xc7, 0x91, 0x40, 0x6b, 0x9b, 0x06, 0x8f, - 0x33, 0xf1, 0x67, 0x89, 0x7d, 0x1a, 0x90, 0xcc, 0x35, 0x86, 0xb7, 0xe2, - 0x53, 0x33, 0x1d, 0x74, 0x41, 0xae, 0x7f, 0x25, 0xf1, 0xc9, 0xc8, 0x8f, - 0x36, 0xa9, 0x1f, 0xcf, 0x3a, 0xe1, 0x09, 0x24, 0x4e, 0x23, 0x50, 0x0f, - 0x4f, 0x1d, 0xdf, 0xf9, 0x93, 0x86, 0x6a, 0x27, 0xfc, 0x25, 0x5a, 0x2d, - 0x18, 0x33, 0x90, 0xf6, 0x24, 0x86, 0x51, 0xbe, 0x11, 0x78, 0x37, 0x13, - 0xd5, 0xc7, 0x80, 0x69, 0x47, 0x22, 0x1a, 0x7e, 0x09, 0x3a, 0x8e, 0xe4, - 0xc3, 0x68, 0xe7, 0xef, 0x76, 0xe3, 0x33, 0x33, 0xec, 0x46, 0xda, 0xc9, - 0xe7, 0xf6, 0x36, 0x03, 0xdb, 0x32, 0x3a, 0x8e, 0x1a, 0xf0, 0xd4, 0x26, - 0x1e, 0xc5, 0x66, 0x7e, 0xfa, 0x13, 0x29, 0xbc, 0x31, 0x19, 0x09, 0x3f, - 0x03, 0xb5, 0x5f, 0x73, 0xaa, 0x29, 0xa0, 0x71, 0x68, 0x50, 0x51, 0x07, - 0xde, 0x54, 0xd4, 0xde, 0x49, 0x05, 0x1e, 0x85, 0xcf, 0x35, 0xe6, 0xe4, - 0x33, 0x85, 0xdb, 0x72, 0x1e, 0x5c, 0x72, 0xca, 0xfa, 0xbf, 0x49, 0x7d, - 0x2b, 0x70, 0x69, 0x2d, 0x18, 0x27, 0x0f, 0xee, 0x84, 0x82, 0xa7, 0x9b, - 0xa3, 0xa1, 0x51, 0xc8, 0xfd, 0x30, 0xb6, 0xe6, 0xe5, 0x53, 0xa5, 0xd4, - 0xa6, 0x39, 0xae, 0x9b, 0xe6, 0x19, 0xbd, 0x1c, 0xe9, 0x80, 0x1a, 0x02, - 0x14, 0x8c, 0xea, 0x0e, 0x24, 0x03, 0x6d, 0x61, 0x17, 0xd4, 0xd0, 0xbd, - 0xf8, 0x67, 0xca, 0x9c, 0x8c, 0xb9, 0x61, 0x3f, 0x3f, 0x80, 0x72, 0x14, - 0x02, 0xb6, 0xd6, 0x9e, 0xce, 0x98, 0xe6, 0x05, 0xcd, 0x85, 0x33, 0xd4, - 0xcf, 0x68, 0xee, 0x9f, 0xcd, 0x02, 0x75, 0x33, 0xae, 0x95, 0xd6, 0xf7, - 0x60, 0x36, 0x60, 0x9a, 0x73, 0xbc, 0x77, 0x34, 0x57, 0xd2, 0xb3, 0x69, - 0x3a, 0x34, 0xd3, 0xdc, 0xa7, 0xfd, 0xca, 0xdc, 0xfb, 0x6b, 0xcf, 0x9a, - 0xe6, 0x13, 0xfa, 0x4d, 0x38, 0x9b, 0x6d, 0x57, 0xba, 0x17, 0x56, 0xf9, - 0xb7, 0xcf, 0x98, 0xb8, 0xa0, 0x23, 0xe0, 0x48, 0x74, 0x28, 0xdb, 0x17, - 0xba, 0x94, 0x6d, 0xf9, 0x5d, 0x4a, 0xc7, 0xdc, 0xef, 0x2a, 0x5d, 0x0b, - 0x03, 0x4a, 0x67, 0x3e, 0x84, 0x79, 0x23, 0x88, 0x39, 0xa3, 0x5f, 0x69, - 0x5f, 0xe8, 0x53, 0x6c, 0x39, 0x52, 0x4a, 0x5b, 0xbe, 0x44, 0xeb, 0xba, - 0x1e, 0xb7, 0x67, 0x12, 0x98, 0x30, 0xca, 0xb9, 0xce, 0xb2, 0xf9, 0xa3, - 0x86, 0x65, 0xca, 0xa9, 0xe3, 0x58, 0xfe, 0x09, 0xec, 0x9c, 0x31, 0xcd, - 0x5c, 0x1c, 0xc8, 0xe5, 0x81, 0xef, 0x19, 0x91, 0xde, 0x21, 0xc5, 0x34, - 0x3b, 0xa3, 0xe6, 0xea, 0xcb, 0x7a, 0x63, 0xec, 0x65, 0xfc, 0x93, 0x39, - 0x1b, 0x44, 0xda, 0x47, 0x1a, 0xc7, 0x69, 0xb3, 0xfb, 0x27, 0xe1, 0x29, - 0x4f, 0x8c, 0xe3, 0x67, 0x19, 0x78, 0xca, 0x12, 0x69, 0x5c, 0xc8, 0x8c, - 0x06, 0x3c, 0x88, 0x84, 0xb6, 0x2b, 0xe9, 0x94, 0x03, 0xea, 0xf0, 0xdb, - 0x50, 0xc3, 0xb4, 0xc7, 0xd2, 0x79, 0x45, 0x2d, 0xbc, 0x0c, 0x35, 0xf9, - 0x2b, 0x45, 0xed, 0xaa, 0x75, 0x22, 0xe9, 0x88, 0x7a, 0xf0, 0xa3, 0x06, - 0xb1, 0xc9, 0x38, 0xd6, 0x5a, 0xb6, 0x49, 0xe3, 0xd6, 0x6b, 0xb6, 0x49, - 0x60, 0x94, 0x7c, 0x1d, 0x25, 0x5f, 0xaf, 0xe8, 0x6a, 0xe8, 0x69, 0x98, - 0xab, 0x07, 0x75, 0xb9, 0x97, 0xc0, 0x78, 0xde, 0x0c, 0xfb, 0x13, 0x97, - 0xc8, 0x2f, 0xd2, 0x5f, 0x4a, 0x78, 0xd2, 0xd5, 0x89, 0x4f, 0xcd, 0xd7, - 0x37, 0x86, 0xf0, 0x62, 0x3e, 0x88, 0x17, 0xf2, 0x01, 0x3c, 0x9f, 0x6f, - 0x87, 0x91, 0x87, 0x7f, 0x67, 0xfe, 0x8b, 0xfc, 0xd8, 0x84, 0x8f, 0xcf, - 0x93, 0x6f, 0xff, 0x8e, 0xbc, 0x6b, 0xa0, 0x2c, 0x81, 0xde, 0x1f, 0x67, - 0x46, 0xcc, 0x0a, 0x0d, 0x03, 0x35, 0x09, 0x2d, 0x79, 0x9b, 0xe2, 0x6b, - 0xa1, 0x1f, 0xf6, 0xbe, 0x9a, 0x6b, 0x71, 0x69, 0x53, 0x5e, 0xb8, 0xa9, - 0xff, 0x6d, 0x79, 0xd3, 0x1c, 0xd3, 0x0f, 0xad, 0xdb, 0xdb, 0xf2, 0xa7, - 0x85, 0x5e, 0xad, 0x07, 0xe9, 0xfc, 0x20, 0xe0, 0x4f, 0xf0, 0x93, 0xa1, - 0xb8, 0xab, 0xa9, 0x3d, 0x7c, 0xee, 0x41, 0x97, 0xed, 0xcf, 0xe4, 0x81, - 0x7a, 0x7f, 0xc1, 0x20, 0x0f, 0xc6, 0xb4, 0x1f, 0x15, 0x61, 0xca, 0xf7, - 0x13, 0xf2, 0x19, 0xc3, 0xf7, 0xf3, 0x1a, 0x79, 0x6b, 0x22, 0x8f, 0x61, - 0xf2, 0xe7, 0xc1, 0xde, 0xac, 0x3a, 0x9d, 0x86, 0x3a, 0x31, 0x8b, 0x35, - 0x48, 0x06, 0x03, 0xf4, 0xc1, 0x3f, 0x86, 0x4d, 0xa3, 0x07, 0x53, 0x06, - 0xd6, 0x07, 0x12, 0xb4, 0x6f, 0x1c, 0x8f, 0x96, 0x21, 0x3a, 0xf0, 0xb1, - 0xa2, 0xe0, 0xf5, 0x68, 0x0f, 0x26, 0x29, 0x4f, 0x4f, 0xce, 0x8b, 0x07, - 0xb2, 0x15, 0xb8, 0x2f, 0x6b, 0xe2, 0xfe, 0x38, 0x12, 0x15, 0x94, 0x27, - 0x16, 0x8f, 0x86, 0xdf, 0x83, 0x0b, 0xed, 0xb9, 0x1e, 0xc6, 0xd2, 0x56, - 0x24, 0xcb, 0x3c, 0xd8, 0x9a, 0xf3, 0x31, 0x1e, 0x93, 0x38, 0x3d, 0xe3, - 0x81, 0x7b, 0x83, 0x03, 0xb3, 0xc1, 0x32, 0xc4, 0xea, 0x1d, 0xfc, 0x0d, - 0xfa, 0xdb, 0x66, 0xea, 0xfc, 0xdb, 0x0c, 0x17, 0x0e, 0x18, 0x0e, 0x8c, - 0x64, 0x4d, 0xb3, 0x5d, 0x37, 0x71, 0x75, 0x43, 0x00, 0x3f, 0xa0, 0xfe, - 0x0e, 0x19, 0x21, 0x9c, 0xcd, 0x3f, 0x4e, 0x5e, 0x82, 0x36, 0xbf, 0x06, - 0x79, 0x37, 0xc8, 0xbb, 0x41, 0xbe, 0x0d, 0xe1, 0xf3, 0x3c, 0x63, 0x46, - 0xa7, 0x5c, 0x5e, 0xf2, 0x50, 0x89, 0x21, 0xf2, 0x11, 0x89, 0x9b, 0x70, - 0xc4, 0xd5, 0xf4, 0x5e, 0x26, 0xaf, 0xd5, 0xf5, 0xa6, 0xf9, 0xf1, 0x06, - 0x91, 0x85, 0x36, 0x77, 0xf4, 0x48, 0x8c, 0xfe, 0x56, 0x15, 0xe3, 0xea, - 0x6f, 0xa9, 0xb7, 0x27, 0xf3, 0x5e, 0xa4, 0xb2, 0x96, 0xdf, 0x1e, 0x2e, - 0x23, 0xdf, 0xc2, 0x57, 0x5e, 0x8b, 0x32, 0x46, 0xa3, 0xfd, 0x8c, 0x51, - 0xec, 0x20, 0xcf, 0xf7, 0x1b, 0xd1, 0x96, 0x5d, 0x8a, 0x0b, 0x9d, 0xb9, - 0xa0, 0xbf, 0xfd, 0x06, 0x3e, 0x29, 0xaf, 0xc4, 0x20, 0x65, 0x0d, 0x90, - 0xbf, 0x20, 0xf6, 0x91, 0xcf, 0x17, 0x8a, 0x7c, 0xce, 0xe5, 0x65, 0xad, - 0xcf, 0xf3, 0x5a, 0xe2, 0x13, 0xe9, 0x15, 0x89, 0xa0, 0x82, 0x0a, 0x1f, - 0x76, 0xe5, 0xde, 0xa2, 0x2d, 0xea, 0xf0, 0xa7, 0xb4, 0xc1, 0x8b, 0x8c, - 0x91, 0xef, 0x5f, 0xf3, 0x17, 0xb1, 0xc7, 0x63, 0xb4, 0x83, 0x7a, 0x3a, - 0x0d, 0x1f, 0x06, 0xf2, 0x49, 0x1c, 0x99, 0x41, 0x72, 0x5e, 0x3f, 0xce, - 0x78, 0x5f, 0x05, 0xa7, 0x56, 0x9e, 0x0c, 0x68, 0x15, 0xd8, 0x37, 0x17, - 0xc4, 0x70, 0xbe, 0x0d, 0x46, 0x36, 0x88, 0x83, 0xf4, 0xcd, 0x2b, 0xf1, - 0xe4, 0xfd, 0x7e, 0x08, 0xef, 0x41, 0x3c, 0xc0, 0x77, 0x9e, 0x98, 0x09, - 0x62, 0x88, 0x3a, 0xda, 0x1e, 0x8f, 0xb6, 0x78, 0x79, 0xed, 0x00, 0xaf, - 0x1d, 0xa5, 0xfe, 0xcf, 0xeb, 0x93, 0x18, 0xe8, 0x55, 0x63, 0x40, 0x10, - 0xfb, 0x0d, 0x04, 0xe8, 0xc2, 0x8f, 0x31, 0xbf, 0xc5, 0xce, 0xf3, 0xfb, - 0xbd, 0xf9, 0x0a, 0xca, 0xe9, 0x47, 0x48, 0xfb, 0xc4, 0x74, 0x37, 0x9b, - 0xe6, 0x77, 0xf5, 0xe8, 0xd2, 0x4f, 0x9d, 0x2e, 0x3c, 0x92, 0x77, 0x20, - 0x35, 0x57, 0x81, 0xdf, 0xcf, 0xba, 0x70, 0x57, 0x7d, 0x05, 0x0e, 0xcd, - 0x25, 0x31, 0x36, 0x53, 0x81, 0xc1, 0x2c, 0x56, 0xef, 0xd7, 0xc7, 0x6a, - 0xca, 0xa0, 0x2e, 0xb7, 0x23, 0x86, 0xab, 0xb4, 0xc3, 0x23, 0x73, 0x3e, - 0x7f, 0xff, 0x4c, 0x00, 0xa9, 0x05, 0x2f, 0x9f, 0x77, 0xf0, 0xf9, 0x72, - 0xe8, 0xeb, 0x23, 0xa9, 0x00, 0x84, 0xc7, 0x4a, 0x3c, 0x34, 0xe7, 0xc5, - 0x83, 0xd9, 0x00, 0x0e, 0xce, 0x34, 0x63, 0xda, 0x48, 0xe2, 0x18, 0x73, - 0xc7, 0xf7, 0xe2, 0x6a, 0xef, 0x41, 0x45, 0x4d, 0x6e, 0x53, 0x92, 0x68, - 0x88, 0xbb, 0x71, 0x89, 0x79, 0xc8, 0x1d, 0x6f, 0x6c, 0x79, 0x9e, 0xb9, - 0xa1, 0x2c, 0x11, 0xe4, 0x77, 0x75, 0x82, 0x31, 0x9b, 0x74, 0x3b, 0x36, - 0x00, 0x2b, 0x25, 0x7e, 0x83, 0xfe, 0x6e, 0x23, 0xe0, 0xef, 0xce, 0xd7, - 0xf9, 0xb7, 0x1b, 0x21, 0xff, 0x76, 0xc6, 0xd7, 0x36, 0xf1, 0x47, 0xc3, - 0x83, 0xe3, 0xf1, 0x4f, 0xcd, 0x81, 0x1a, 0x2b, 0x9f, 0xf9, 0x77, 0xce, - 0xa8, 0xe9, 0x59, 0xa8, 0x3a, 0xab, 0x01, 0x26, 0x17, 0x5c, 0xb4, 0x9f, - 0x82, 0x1a, 0xad, 0x99, 0x79, 0x3c, 0x80, 0x87, 0x98, 0x53, 0xfe, 0x9a, - 0x39, 0x65, 0x70, 0x2a, 0x12, 0x98, 0x86, 0x97, 0xfa, 0x06, 0xf6, 0x9e, - 0x0b, 0xd2, 0xe6, 0x5d, 0x78, 0x9c, 0x7c, 0x6d, 0xdf, 0x18, 0xc4, 0x7d, - 0xf9, 0x80, 0xbf, 0x8b, 0xf6, 0x7b, 0x2f, 0x17, 0xf2, 0x6f, 0xa5, 0x2d, - 0xdf, 0xce, 0xa9, 0xe1, 0x02, 0xfe, 0xaf, 0xf8, 0x53, 0x0c, 0x0e, 0x60, - 0xff, 0x94, 0x1b, 0x85, 0xa0, 0xac, 0x45, 0x9d, 0x1b, 0x2f, 0x9a, 0x3e, - 0x4d, 0x3b, 0x7d, 0x90, 0xba, 0xfe, 0x46, 0xde, 0x87, 0x07, 0x0d, 0x35, - 0xf6, 0x7d, 0xc5, 0x47, 0x9d, 0x7a, 0xa8, 0x07, 0x26, 0x98, 0x55, 0xf2, - 0x5c, 0x1c, 0xe1, 0x55, 0x76, 0xae, 0x3d, 0x34, 0x27, 0x7e, 0x42, 0xdb, - 0x1b, 0xf4, 0x01, 0xfa, 0xcf, 0xf7, 0xaf, 0xc5, 0xaa, 0x1a, 0x48, 0x5b, - 0xb9, 0x3b, 0x46, 0x7f, 0xb1, 0x75, 0x74, 0x62, 0x46, 0xf4, 0xa0, 0x4e, - 0xc3, 0x91, 0xc4, 0xba, 0xf5, 0x7f, 0x6d, 0x5e, 0x5a, 0x29, 0xfa, 0x08, - 0x60, 0x84, 0x3a, 0x3c, 0x6d, 0x98, 0xe6, 0xd5, 0x0d, 0x1f, 0x9a, 0x2d, - 0x37, 0x8b, 0x5e, 0x44, 0xd6, 0x1f, 0x28, 0x52, 0x47, 0x6a, 0x34, 0xff, - 0xff, 0x07, 0x5f, 0xf9, 0xa6, 0x39, 0x60, 0xc9, 0x27, 0xfe, 0xe2, 0xa2, - 0x2f, 0x3e, 0x4e, 0xda, 0x0e, 0x0c, 0x90, 0xde, 0xc3, 0x86, 0xf9, 0x51, - 0x6d, 0xe2, 0x33, 0xb3, 0x65, 0x93, 0x36, 0xbc, 0xac, 0xfc, 0x4f, 0x5e, - 0x0f, 0xe2, 0xa1, 0x7c, 0x0b, 0x75, 0xd7, 0x8e, 0x27, 0xa8, 0xc3, 0xa3, - 0x86, 0xe4, 0xc4, 0x10, 0xfd, 0xb9, 0x8e, 0xfe, 0xed, 0x52, 0xb6, 0x19, - 0x39, 0x6c, 0x9f, 0x4c, 0xa3, 0x93, 0xfe, 0xbe, 0x94, 0x89, 0xb4, 0x3c, - 0x0b, 0x35, 0x4d, 0x19, 0xfc, 0x5d, 0xd4, 0x71, 0xbb, 0xa1, 0x76, 0x89, - 0x4d, 0xdb, 0x99, 0x97, 0x5e, 0xca, 0x84, 0xfc, 0x6d, 0x79, 0xd1, 0x77, - 0x9d, 0x7f, 0x6b, 0xfe, 0xab, 0xb4, 0xbd, 0x82, 0xcd, 0x6b, 0x3c, 0xcc, - 0x33, 0x77, 0xc1, 0xb6, 0xab, 0x6d, 0xbb, 0xd7, 0xe3, 0x8d, 0x03, 0x1f, - 0x32, 0x3f, 0xa5, 0x57, 0xda, 0xd7, 0x52, 0xbc, 0x56, 0xbd, 0x01, 0xfe, - 0x3b, 0xe9, 0x07, 0x7b, 0xe8, 0x07, 0x57, 0x37, 0x7c, 0x6a, 0x86, 0x6f, - 0xb2, 0xfd, 0xa0, 0x6d, 0xc6, 0xe5, 0xef, 0xa0, 0x9e, 0xb6, 0xe9, 0x0a, - 0xe6, 0xf4, 0x0c, 0x06, 0xae, 0x61, 0x87, 0xe4, 0xec, 0x59, 0x3d, 0xc9, - 0x3c, 0xf2, 0x9b, 0x70, 0xd5, 0x60, 0xf6, 0x59, 0xfd, 0x71, 0x84, 0x6d, - 0xdf, 0xc1, 0xc1, 0xac, 0x17, 0xe9, 0xbb, 0x02, 0x98, 0x6f, 0x08, 0xe0, - 0x61, 0xd2, 0xbe, 0x12, 0x6f, 0x1c, 0x7a, 0x83, 0x3a, 0x98, 0xad, 0x91, - 0x6b, 0x49, 0xfc, 0xa5, 0xfe, 0x28, 0x70, 0x93, 0xbd, 0xf6, 0x82, 0xc4, - 0xe8, 0x42, 0x33, 0x8e, 0xe6, 0xfb, 0x15, 0x3b, 0x6f, 0xaa, 0x5d, 0x49, - 0xfc, 0xc4, 0x94, 0x5c, 0xba, 0x60, 0x30, 0xc7, 0x51, 0x1f, 0xe3, 0xf4, - 0xa3, 0xd1, 0x5c, 0x9d, 0xbf, 0x93, 0x7e, 0xf4, 0x78, 0x4e, 0x64, 0x8a, - 0xea, 0xba, 0xb3, 0x96, 0xb5, 0x99, 0xfa, 0x31, 0xac, 0x9a, 0x5f, 0x1d, - 0xd0, 0x8e, 0x61, 0xda, 0xe2, 0x2d, 0xa5, 0xf4, 0x13, 0x63, 0x30, 0x64, - 0xaa, 0xcb, 0xb5, 0x43, 0x78, 0xdc, 0xba, 0x16, 0xf4, 0xef, 0x9e, 0x49, - 0x3a, 0x1c, 0x1a, 0x02, 0x95, 0x89, 0x76, 0x65, 0x37, 0xeb, 0x6e, 0xc7, - 0x4c, 0x87, 0xd2, 0xb1, 0x20, 0x31, 0xd0, 0xa5, 0x6c, 0x67, 0xcd, 0x4d, - 0xb2, 0xe6, 0x26, 0x59, 0x73, 0x93, 0xe4, 0x23, 0xc9, 0x5a, 0xdb, 0x96, - 0x4f, 0x29, 0x3b, 0x44, 0xff, 0xf4, 0xaf, 0xe7, 0x0d, 0x1b, 0x47, 0x30, - 0x07, 0xf9, 0x3b, 0xf3, 0x6b, 0x1d, 0x36, 0xb6, 0x4b, 0x29, 0x45, 0x2c, - 0xe3, 0xa9, 0xd0, 0x58, 0xcb, 0x8c, 0x94, 0xd2, 0xcd, 0x7a, 0xdb, 0x6f, - 0xe9, 0x32, 0x32, 0xfc, 0x0e, 0xeb, 0xec, 0xeb, 0xac, 0xb3, 0xb9, 0x38, - 0xe3, 0x6a, 0xcd, 0x55, 0x73, 0x60, 0xa5, 0x5d, 0x13, 0xc6, 0xc8, 0xef, - 0x77, 0x69, 0xb3, 0x02, 0x6b, 0x69, 0xbb, 0x53, 0xc1, 0x7e, 0x0d, 0xd5, - 0xb5, 0xcc, 0xa9, 0x47, 0xf3, 0xac, 0x03, 0x7a, 0xa4, 0xe5, 0x7d, 0x2a, - 0xf6, 0xa8, 0xe6, 0xc6, 0xd5, 0x9b, 0x08, 0x76, 0xb4, 0x36, 0x1c, 0xcf, - 0x96, 0x63, 0x28, 0x9e, 0x5c, 0xe1, 0x21, 0x56, 0xe9, 0x6a, 0xc6, 0xa3, - 0x5c, 0x5a, 0x09, 0x25, 0xa2, 0xf4, 0x1b, 0x24, 0xa7, 0x58, 0x27, 0x26, - 0x8d, 0xaf, 0x22, 0xc7, 0x7a, 0x3a, 0xaf, 0xbb, 0xf0, 0x7a, 0x6e, 0x2d, - 0xf3, 0x5c, 0x54, 0xf7, 0x29, 0x15, 0x8c, 0xdf, 0x04, 0x32, 0x86, 0xe4, - 0x27, 0xd3, 0x9c, 0x17, 0x1e, 0xa2, 0xd1, 0xe4, 0x28, 0x24, 0x67, 0x99, - 0xab, 0xef, 0x8d, 0x97, 0x61, 0x73, 0xd4, 0x8f, 0xd5, 0xda, 0x80, 0xd2, - 0x95, 0x8f, 0xea, 0xe7, 0xf1, 0xbb, 0xca, 0x9e, 0x85, 0x04, 0x63, 0xbb, - 0x9f, 0xba, 0xa9, 0xc0, 0xa5, 0xa0, 0xf0, 0x88, 0x6a, 0xb7, 0xe6, 0xc0, - 0xbb, 0x77, 0x2b, 0x08, 0x68, 0x49, 0x5c, 0x68, 0x0e, 0xd0, 0xaf, 0xba, - 0x88, 0x31, 0xc2, 0x70, 0x2e, 0x86, 0xfc, 0x3b, 0x68, 0x8b, 0xca, 0xc5, - 0x3a, 0xda, 0x87, 0xbe, 0x47, 0x1d, 0xb6, 0x51, 0x87, 0xdd, 0x73, 0x08, - 0x54, 0x24, 0xfa, 0x94, 0x8e, 0x7c, 0xbb, 0xd2, 0x9e, 0x57, 0xa9, 0x27, - 0xd1, 0xc9, 0x37, 0x89, 0x95, 0xc4, 0x57, 0x4a, 0xb6, 0x14, 0x7f, 0xbd, - 0xd1, 0x9e, 0xfd, 0x0e, 0x89, 0xb9, 0xcd, 0x6b, 0x12, 0x8c, 0x47, 0x07, - 0xf9, 0x12, 0x1e, 0x3c, 0xa8, 0x6e, 0x30, 0x57, 0x5f, 0x89, 0x33, 0x79, - 0x56, 0x24, 0x30, 0x95, 0xef, 0xa1, 0x5d, 0x36, 0x14, 0xfd, 0x2b, 0xe0, - 0xdf, 0x36, 0xd3, 0xae, 0x6c, 0x5b, 0x58, 0xe1, 0xef, 0xa5, 0x0d, 0x7b, - 0x17, 0x42, 0x42, 0x97, 0xeb, 0x8b, 0x6d, 0x93, 0x70, 0x68, 0xff, 0x9a, - 0x2d, 0xbf, 0x41, 0x5a, 0x62, 0x4f, 0x6f, 0xc9, 0x4f, 0xfd, 0x7b, 0x66, - 0x92, 0x78, 0x77, 0x83, 0x9b, 0x35, 0xb5, 0x84, 0x29, 0xaa, 0x8a, 0x9f, - 0xa7, 0x1d, 0xd0, 0x52, 0x4a, 0x97, 0xf8, 0x91, 0xdb, 0x5e, 0xf3, 0xce, - 0x19, 0xb8, 0x09, 0x15, 0xc2, 0x4e, 0x62, 0xba, 0x0f, 0xe3, 0xd1, 0x81, - 0x73, 0x4a, 0x8f, 0xd2, 0x93, 0x97, 0x1a, 0x6c, 0xfb, 0x54, 0x1b, 0x7d, - 0xaa, 0x9d, 0xfc, 0xb4, 0xd3, 0xa7, 0xba, 0xc9, 0x4f, 0xb7, 0xe5, 0x53, - 0xe2, 0x9b, 0xbf, 0xce, 0xcb, 0xd6, 0xfc, 0x1e, 0x4b, 0x2f, 0x3b, 0xf8, - 0x6e, 0x17, 0xe5, 0xe8, 0xe2, 0x7b, 0x7b, 0xf8, 0xde, 0x9e, 0x85, 0xff, - 0x2d, 0xfc, 0x51, 0x16, 0x3b, 0xf6, 0xaf, 0xd7, 0x34, 0xc9, 0x01, 0xaf, - 0x15, 0x31, 0x05, 0xd2, 0x8e, 0x84, 0xe4, 0x88, 0x61, 0xf4, 0x36, 0xc3, - 0xb3, 0x22, 0xf1, 0x93, 0xd6, 0x5d, 0xf5, 0xcc, 0x67, 0xcc, 0xa7, 0x9e, - 0x29, 0x62, 0x69, 0xe6, 0xe8, 0xf9, 0x16, 0x05, 0x63, 0xfa, 0xcd, 0x8c, - 0x53, 0x1d, 0x13, 0x79, 0xb5, 0x2b, 0xcc, 0x7b, 0x4d, 0x93, 0x82, 0xf1, - 0x0f, 0xa2, 0x8d, 0xb8, 0x2e, 0x94, 0x18, 0x42, 0xc8, 0x88, 0x84, 0x26, - 0x14, 0x75, 0x68, 0x2b, 0xd4, 0x25, 0xd6, 0x86, 0xd4, 0x9c, 0xa2, 0x0e, - 0xd7, 0x3a, 0xd5, 0xe4, 0x9b, 0x16, 0xbe, 0x3e, 0x88, 0x35, 0x16, 0x86, - 0x1b, 0x42, 0x8c, 0x58, 0x76, 0x07, 0x69, 0x1e, 0xd8, 0xac, 0xe0, 0xb2, - 0xfe, 0x21, 0xed, 0xa8, 0x26, 0xd3, 0x8a, 0x8e, 0x0c, 0xf3, 0x44, 0x68, - 0x4a, 0xb0, 0xfa, 0x41, 0x62, 0x75, 0x78, 0x7c, 0x7c, 0x36, 0x33, 0x19, - 0x49, 0x79, 0x9c, 0x6a, 0x8c, 0x38, 0x3d, 0x49, 0x9a, 0x7a, 0x9e, 0xf8, - 0x9d, 0x6b, 0x84, 0xf7, 0x17, 0x69, 0x46, 0x8b, 0x34, 0xb5, 0x1c, 0x18, - 0x37, 0x13, 0xe8, 0x8c, 0xb2, 0x56, 0x30, 0xe7, 0x1d, 0x93, 0x9e, 0x80, - 0xf4, 0xca, 0xa7, 0x74, 0x7e, 0x4f, 0x29, 0xbb, 0x25, 0xa6, 0xca, 0x6d, - 0x2b, 0x54, 0x73, 0x8d, 0xaa, 0xc4, 0x61, 0x2c, 0x5a, 0x6b, 0x0c, 0xcb, - 0x1a, 0xc3, 0x3f, 0x53, 0xd4, 0xd8, 0x39, 0x45, 0x72, 0x75, 0x63, 0xff, - 0x39, 0xc6, 0xd0, 0x51, 0x45, 0x6d, 0x39, 0x4e, 0xf1, 0xbd, 0x9a, 0xd0, - 0x3f, 0x5c, 0x5c, 0x67, 0x18, 0x0d, 0x39, 0xc6, 0x67, 0xde, 0xa3, 0x6c, - 0xcd, 0xb6, 0x61, 0x6c, 0xae, 0x0d, 0xa3, 0x59, 0x05, 0x7b, 0xf4, 0x95, - 0xb8, 0x74, 0xb3, 0xd5, 0xa7, 0x54, 0xad, 0xd6, 0x6a, 0x31, 0x12, 0x40, - 0xb5, 0x43, 0xfb, 0x0a, 0xf6, 0x16, 0x31, 0x7e, 0xe7, 0x89, 0x5e, 0xe6, - 0x7d, 0x13, 0xef, 0x33, 0x96, 0x22, 0x35, 0x48, 0xba, 0x13, 0x2d, 0xc4, - 0xe3, 0x75, 0x4e, 0x3b, 0xde, 0xff, 0xc9, 0x63, 0xdb, 0x40, 0xf4, 0xff, - 0xf9, 0x7b, 0x6d, 0x78, 0x32, 0x5b, 0x86, 0x96, 0x0d, 0xb8, 0x2b, 0x84, - 0x2a, 0x07, 0x6b, 0xdc, 0x5b, 0xbb, 0x94, 0x14, 0xef, 0x59, 0xcf, 0x7a, - 0xbe, 0x9c, 0xe8, 0x4d, 0xfc, 0x97, 0x06, 0xb9, 0x6e, 0xe5, 0x8d, 0x1b, - 0xae, 0x0f, 0x7f, 0xc1, 0x75, 0x05, 0xcf, 0x31, 0x91, 0x7d, 0x8f, 0x35, - 0x25, 0x97, 0x31, 0xe1, 0x4c, 0xb8, 0x30, 0x34, 0x19, 0xc6, 0xc1, 0xc5, - 0x20, 0x16, 0x33, 0xea, 0xc0, 0x25, 0xf6, 0x0f, 0x7b, 0x9b, 0x35, 0x3c, - 0xb8, 0x18, 0xc2, 0x42, 0x06, 0xa6, 0x37, 0xa1, 0x15, 0xbc, 0x4a, 0x0c, - 0x07, 0x16, 0xeb, 0x70, 0x2e, 0xa3, 0x2d, 0x8d, 0x2a, 0xd1, 0x54, 0x2d, - 0x71, 0xc7, 0xc3, 0x8b, 0x4d, 0x78, 0x68, 0xd1, 0xc3, 0x77, 0x4c, 0x74, - 0xc7, 0xeb, 0xf8, 0xbc, 0x03, 0xcf, 0x9e, 0x34, 0x4d, 0xc1, 0x5d, 0x43, - 0x8b, 0xc0, 0xc2, 0x34, 0x6b, 0xd1, 0x19, 0xd6, 0xa5, 0xa7, 0x80, 0x03, - 0x4f, 0x39, 0x30, 0x37, 0x6d, 0x62, 0xaf, 0x3e, 0x5a, 0xeb, 0xa0, 0xc3, - 0x0f, 0xb0, 0x6e, 0xb8, 0x59, 0x03, 0xef, 0x0d, 0xd8, 0xf9, 0xfc, 0x12, - 0xf3, 0xd4, 0xfd, 0x4f, 0xc5, 0xf0, 0x56, 0x26, 0x8d, 0x6e, 0xe2, 0xf3, - 0x14, 0x79, 0x79, 0x33, 0xc3, 0x3a, 0xb6, 0xa8, 0xe3, 0x8d, 0x8c, 0x87, - 0xeb, 0x34, 0xe1, 0xe5, 0x8c, 0x3c, 0x23, 0xcf, 0xfa, 0x30, 0x48, 0x5e, - 0x5e, 0xcf, 0x84, 0xb8, 0x66, 0x10, 0x3f, 0xe6, 0x73, 0xf7, 0x2d, 0x6a, - 0xac, 0x5b, 0x1e, 0xae, 0x1b, 0xc6, 0xab, 0x19, 0x1f, 0x79, 0x0d, 0xb2, - 0x56, 0x0d, 0x62, 0x2c, 0xd3, 0xb8, 0xb4, 0x95, 0x89, 0xda, 0xae, 0x35, - 0x72, 0xed, 0x1d, 0xb3, 0xc7, 0x8a, 0x45, 0x59, 0xa7, 0xb4, 0xee, 0x20, - 0x46, 0x33, 0x6f, 0x38, 0x4b, 0xfd, 0xf4, 0x73, 0xd3, 0xcb, 0x16, 0xf6, - 0x7b, 0xd6, 0xe0, 0xdf, 0x73, 0xc0, 0x39, 0x23, 0x6d, 0x56, 0x27, 0x88, - 0x75, 0x59, 0xa3, 0x7e, 0xba, 0xb1, 0x89, 0xeb, 0x6a, 0x03, 0x2f, 0x29, - 0xd2, 0xef, 0xb8, 0x10, 0x7e, 0x4a, 0xf4, 0x45, 0xcc, 0xbc, 0x00, 0xfc, - 0x25, 0xf1, 0x67, 0xc3, 0xa4, 0x2a, 0x7e, 0xdf, 0x4f, 0x5c, 0xd3, 0x5b, - 0x40, 0x7d, 0xec, 0x41, 0x8c, 0x98, 0x65, 0xc4, 0xe7, 0xd5, 0xc4, 0xb5, - 0x8b, 0x4d, 0xac, 0x53, 0x1b, 0x4d, 0xf3, 0x6f, 0x9b, 0x61, 0x3a, 0x12, - 0x9a, 0x5e, 0xeb, 0x2c, 0x7c, 0xa5, 0x0a, 0xda, 0x92, 0x5f, 0xd1, 0x0a, - 0x3f, 0x45, 0x74, 0xf8, 0x3c, 0x44, 0xaf, 0xc0, 0xda, 0x45, 0x17, 0xd6, - 0x51, 0x9e, 0x6d, 0x93, 0x5c, 0x9b, 0xf8, 0x24, 0x4a, 0x99, 0x76, 0x4e, - 0x12, 0x73, 0x69, 0x3e, 0xac, 0xa1, 0x8e, 0x87, 0x4e, 0x99, 0x66, 0x39, - 0x75, 0xdc, 0x40, 0xfb, 0xec, 0x3f, 0x61, 0xe2, 0x25, 0xfd, 0x25, 0xea, - 0x54, 0x21, 0x6e, 0x6c, 0xe6, 0x3b, 0x41, 0x3e, 0xef, 0xc1, 0x81, 0x49, - 0xe9, 0x97, 0xea, 0xf8, 0xcc, 0x45, 0x1c, 0xcf, 0xc4, 0xd0, 0x44, 0xfd, - 0x85, 0x49, 0xb3, 0x91, 0xef, 0x84, 0x49, 0x2f, 0xbc, 0xf8, 0x35, 0x6c, - 0x3f, 0xa5, 0x40, 0x8b, 0x8a, 0x0e, 0xbe, 0x86, 0xf6, 0x33, 0x5f, 0x94, - 0x13, 0x98, 0xa5, 0xa6, 0xd5, 0x89, 0x02, 0xf1, 0x77, 0x55, 0x62, 0x04, - 0xac, 0xdf, 0x78, 0x73, 0x56, 0xc1, 0xd4, 0x34, 0xfb, 0xbd, 0x8d, 0x30, - 0x2b, 0x28, 0xd3, 0x1b, 0xb3, 0xbf, 0x81, 0x67, 0x4e, 0x52, 0x0f, 0x4f, - 0x07, 0xf1, 0xbd, 0x8c, 0x0b, 0xb7, 0x4e, 0x09, 0xa6, 0xd3, 0x62, 0x07, - 0x15, 0xe9, 0x8f, 0xa4, 0x6f, 0x89, 0x86, 0xdd, 0x8a, 0x03, 0xf5, 0xcf, - 0xb8, 0xa0, 0x9d, 0x0b, 0xc3, 0x5d, 0xef, 0x81, 0x56, 0xff, 0xfb, 0xcc, - 0x35, 0x0e, 0x94, 0xb1, 0x97, 0xed, 0xfc, 0x76, 0x8c, 0xd7, 0x82, 0xbc, - 0x86, 0xdf, 0x28, 0x87, 0x73, 0x95, 0x93, 0x35, 0xbc, 0x4c, 0x23, 0x1e, - 0x73, 0x99, 0xa6, 0x93, 0xb5, 0x61, 0xf7, 0x77, 0x4c, 0x33, 0xb2, 0x41, - 0x9e, 0x0f, 0x20, 0x72, 0x4e, 0xe3, 0x73, 0x76, 0xbd, 0xbc, 0x8e, 0xc7, - 0x9c, 0xf4, 0x23, 0x89, 0x55, 0xd6, 0x7b, 0xab, 0x87, 0xb2, 0x71, 0xfb, - 0x0b, 0x79, 0xc1, 0x36, 0x61, 0x4b, 0x86, 0xb3, 0xd3, 0x0a, 0x73, 0x76, - 0x82, 0xcf, 0x6e, 0x81, 0x33, 0xae, 0x4e, 0xa4, 0xe9, 0x07, 0x7b, 0x03, - 0x2d, 0x78, 0xce, 0x70, 0xa3, 0x52, 0x5b, 0x85, 0x07, 0x7a, 0x03, 0x78, - 0x8e, 0x7d, 0x01, 0x6d, 0x16, 0x2b, 0x80, 0x8d, 0xb4, 0x9f, 0xf4, 0x1c, - 0x3f, 0x84, 0xf6, 0x6d, 0x07, 0xf3, 0x9c, 0xd3, 0xca, 0x73, 0x65, 0xf5, - 0x40, 0x21, 0xe7, 0xc2, 0x05, 0xcd, 0xc6, 0x84, 0x2f, 0x58, 0x35, 0x5b, - 0x0d, 0x14, 0xae, 0x61, 0x41, 0xb5, 0x25, 0xa9, 0x90, 0x19, 0xbf, 0xe8, - 0xae, 0xdf, 0x65, 0xfb, 0xd2, 0xdf, 0x38, 0xa5, 0xe7, 0xb8, 0xfe, 0xbd, - 0x02, 0x8e, 0x84, 0x1a, 0x6a, 0x73, 0xc2, 0xe3, 0x4a, 0x0c, 0xb5, 0x8e, - 0x6b, 0x5f, 0xba, 0x81, 0xf7, 0x26, 0x8c, 0xe5, 0xaf, 0xf7, 0xda, 0x5d, - 0x19, 0xcb, 0x87, 0xba, 0x44, 0xf7, 0x4f, 0xe8, 0x92, 0x67, 0x53, 0x4a, - 0x3b, 0xf3, 0x56, 0xda, 0x85, 0x74, 0x15, 0x9f, 0xa1, 0xfe, 0x71, 0x74, - 0x52, 0xe8, 0x1c, 0xc6, 0x78, 0x46, 0x66, 0x1b, 0xc3, 0xd8, 0x6c, 0x44, - 0x62, 0x4b, 0xec, 0xa1, 0x8f, 0x40, 0xe6, 0x10, 0x8d, 0x85, 0x57, 0x14, - 0x35, 0x75, 0x8b, 0x53, 0x1d, 0x5a, 0x56, 0xec, 0xbc, 0xb5, 0xb6, 0x98, - 0xb7, 0xd6, 0xe4, 0x56, 0xf9, 0x7b, 0x58, 0x0f, 0x7a, 0x16, 0x4a, 0xf5, - 0xa1, 0x47, 0xe9, 0xb4, 0x6a, 0x6b, 0xbf, 0xb2, 0x63, 0xc1, 0xa3, 0x74, - 0x64, 0x3d, 0x78, 0x85, 0x58, 0x6c, 0xb6, 0x0f, 0x81, 0x5b, 0x37, 0xc2, - 0xbb, 0x23, 0xdb, 0x8b, 0x72, 0x4d, 0x7a, 0xc8, 0x72, 0x74, 0x5a, 0x75, - 0xad, 0xce, 0xdf, 0xc3, 0xfa, 0xd3, 0x93, 0xef, 0x63, 0xfe, 0x43, 0xc0, - 0x9b, 0xb0, 0x67, 0x06, 0x92, 0x0b, 0xef, 0xe0, 0xbb, 0x4b, 0xf1, 0x15, - 0x80, 0x5d, 0xff, 0x94, 0x7e, 0xf6, 0x12, 0xd5, 0x1b, 0x14, 0x5c, 0xba, - 0xcb, 0x03, 0xd2, 0x62, 0xcf, 0x7f, 0xb1, 0xf5, 0xc2, 0x74, 0xaf, 0xd2, - 0x31, 0x37, 0xef, 0xdd, 0x66, 0xc8, 0x2c, 0x62, 0xd6, 0xdb, 0x4e, 0x1e, - 0xda, 0x17, 0x9e, 0xf6, 0x6e, 0x25, 0x4f, 0x5b, 0x17, 0x3e, 0x4f, 0x53, - 0xea, 0xca, 0x44, 0x6b, 0x1b, 0x63, 0x7b, 0xb7, 0xfe, 0x91, 0x19, 0xfe, - 0x1d, 0xa1, 0xb3, 0x58, 0xd4, 0x67, 0x92, 0x7c, 0x05, 0x3d, 0x9d, 0xf9, - 0x80, 0x27, 0x99, 0x6f, 0xf7, 0xb6, 0x19, 0xbd, 0xde, 0xad, 0x46, 0x9f, - 0xb7, 0xdd, 0xb8, 0x87, 0xb4, 0x7b, 0xbc, 0x1d, 0x06, 0xe3, 0x3a, 0xdf, - 0x47, 0xbd, 0xf6, 0x62, 0x3c, 0x7f, 0x0f, 0xb1, 0x87, 0xd0, 0x1c, 0x20, - 0x0e, 0xf2, 0x52, 0xc6, 0x11, 0xca, 0x58, 0x08, 0xb9, 0x91, 0x54, 0xdd, - 0xd4, 0xd7, 0x98, 0x65, 0xc7, 0x09, 0x6b, 0x16, 0x55, 0x91, 0x98, 0x6c, - 0xed, 0x3e, 0xc1, 0x7c, 0x9f, 0x38, 0xda, 0x7a, 0xeb, 0x29, 0xd4, 0xb8, - 0x13, 0xd2, 0x3b, 0xb3, 0x1f, 0x8e, 0x46, 0xf5, 0xf7, 0x10, 0x0d, 0xbd, - 0xc2, 0x67, 0x47, 0xe9, 0xbb, 0x63, 0xd6, 0xfc, 0x81, 0x06, 0xc9, 0x35, - 0xa1, 0xdb, 0xf0, 0x78, 0x77, 0xb2, 0x37, 0xf3, 0x27, 0xd4, 0x96, 0x3b, - 0x9c, 0x32, 0x0f, 0x29, 0xfc, 0x96, 0x0f, 0x4d, 0xe8, 0xca, 0x7b, 0x28, - 0xd7, 0x97, 0xf0, 0x0f, 0x27, 0x59, 0xd7, 0x20, 0x7e, 0x68, 0x9a, 0xf7, - 0xb1, 0xaf, 0x39, 0x96, 0xab, 0xc3, 0x65, 0xcb, 0xc6, 0x2e, 0x1c, 0xcd, - 0x85, 0xf1, 0x0e, 0xe5, 0x73, 0x2d, 0xd6, 0xe2, 0xed, 0x69, 0x27, 0xf6, - 0xe9, 0xb7, 0x17, 0xeb, 0x85, 0x03, 0xf7, 0xc6, 0x0e, 0x11, 0x3b, 0x38, - 0x50, 0x4d, 0xfc, 0xf6, 0xb0, 0x75, 0xcd, 0xc9, 0xfe, 0xef, 0xb7, 0x91, - 0xb2, 0xeb, 0x09, 0x79, 0x7c, 0x94, 0x3c, 0x36, 0x7b, 0xb7, 0x66, 0x55, - 0xef, 0x9d, 0x59, 0x78, 0xdc, 0x89, 0xd1, 0xd6, 0x33, 0x27, 0x4d, 0x0c, - 0xea, 0xb7, 0xe1, 0xca, 0xc9, 0xd1, 0x21, 0x17, 0xfd, 0xe7, 0xe7, 0xf1, - 0x7e, 0x18, 0x33, 0xb8, 0x40, 0xe4, 0x71, 0xd1, 0xc7, 0xdc, 0xde, 0x10, - 0x8f, 0x06, 0x58, 0x8b, 0xf5, 0x05, 0xc6, 0x66, 0x07, 0xd4, 0x21, 0xd6, - 0xe4, 0xa4, 0x33, 0x11, 0x1d, 0x18, 0x23, 0x78, 0xac, 0x22, 0x3f, 0x5e, - 0xe6, 0x6e, 0xdf, 0x62, 0xd8, 0xbb, 0x9b, 0xf5, 0x26, 0xc4, 0xfe, 0xce, - 0x1b, 0xc5, 0xed, 0xb5, 0x88, 0xc6, 0x96, 0x29, 0xb7, 0x7b, 0xb1, 0xc9, - 0x7b, 0x07, 0xeb, 0xc7, 0xe5, 0xa8, 0x39, 0xf2, 0x92, 0xee, 0x83, 0x7f, - 0x51, 0xa7, 0xbe, 0xfb, 0x31, 0xba, 0xc0, 0x96, 0x2b, 0xca, 0x9e, 0x7f, - 0xb1, 0xc5, 0xbb, 0x93, 0xb1, 0x59, 0x45, 0x13, 0x35, 0x2e, 0x26, 0xbd, - 0xd2, 0xf3, 0x35, 0x2d, 0x6e, 0x22, 0x7f, 0xe2, 0xa3, 0x99, 0xd6, 0xcd, - 0xf4, 0x87, 0xf0, 0x22, 0x3a, 0x99, 0xe6, 0x5e, 0x26, 0xcd, 0xfe, 0x10, - 0x31, 0xec, 0x81, 0x8d, 0x3e, 0xe6, 0x29, 0xd1, 0x25, 0xf5, 0x98, 0x2f, - 0xc9, 0x24, 0x75, 0xf9, 0x68, 0xeb, 0xe2, 0x29, 0xa9, 0xcb, 0xa9, 0xd6, - 0xcc, 0x29, 0x0d, 0xef, 0xb0, 0xb6, 0xac, 0x8d, 0xab, 0xfa, 0x39, 0x25, - 0x12, 0xba, 0x48, 0x59, 0x5c, 0xf8, 0x85, 0xb9, 0x57, 0x8b, 0x16, 0x6e, - 0x61, 0x3c, 0x55, 0x33, 0x37, 0x86, 0x98, 0xf3, 0xab, 0x17, 0xa9, 0x98, - 0x45, 0xa7, 0x1b, 0x15, 0x21, 0x78, 0xa2, 0x1a, 0xde, 0x3d, 0x19, 0xa3, - 0x1e, 0xae, 0xd1, 0x3c, 0x48, 0xa8, 0x35, 0xc8, 0x52, 0xf8, 0xd8, 0x33, - 0xf4, 0xc5, 0x71, 0xae, 0x5b, 0xb6, 0x28, 0x3c, 0xcb, 0xf3, 0x41, 0x3e, - 0x7f, 0x7d, 0xed, 0x6a, 0xae, 0xfd, 0xd1, 0x29, 0xf1, 0xd7, 0x54, 0xeb, - 0x85, 0x93, 0xf6, 0xda, 0xd1, 0x78, 0x0c, 0x1f, 0x9e, 0x54, 0x87, 0xdf, - 0x55, 0x22, 0x03, 0x17, 0x14, 0x59, 0x1f, 0x75, 0x55, 0xb8, 0x62, 0x8e, - 0x46, 0xa3, 0xa9, 0xbd, 0xa4, 0xd9, 0xb2, 0x89, 0xfa, 0xb7, 0xf8, 0xa0, - 0xcf, 0x33, 0xcf, 0xba, 0xc9, 0x8f, 0xcd, 0x4b, 0x1d, 0x69, 0x9f, 0x2c, - 0xf6, 0x6a, 0xec, 0x53, 0xaf, 0xf3, 0x13, 0xa4, 0x1e, 0x3c, 0xbb, 0x9b, - 0x7d, 0xa8, 0xb5, 0x9e, 0x0b, 0xf0, 0x39, 0xd1, 0xc3, 0x2f, 0x15, 0x87, - 0xf6, 0x1e, 0xf3, 0x98, 0xe4, 0x92, 0x20, 0x73, 0xd8, 0x3d, 0xd2, 0xd3, - 0xa6, 0xd3, 0xf4, 0x77, 0x37, 0xfd, 0x7d, 0x9b, 0xf8, 0xb4, 0x41, 0x9f, - 0x36, 0xe8, 0xd3, 0x86, 0x1a, 0x1a, 0x46, 0x24, 0x30, 0x48, 0xbb, 0x25, - 0x43, 0xe2, 0xeb, 0x7d, 0xd8, 0xc7, 0xdf, 0xfd, 0xbc, 0x7f, 0x94, 0x7d, - 0x2e, 0x56, 0xc8, 0x9a, 0x87, 0xd1, 0x6e, 0x3c, 0x86, 0xa1, 0x2c, 0x7e, - 0xe5, 0x6d, 0x2e, 0x47, 0xf9, 0x1a, 0xe9, 0xe1, 0xd5, 0xc0, 0x31, 0x3c, - 0xc6, 0x3e, 0xea, 0x97, 0x4a, 0xa5, 0xe6, 0xea, 0x3d, 0xae, 0xa8, 0x81, - 0x76, 0xf6, 0xc3, 0x7b, 0xf3, 0xf7, 0xd0, 0xbe, 0x91, 0xa1, 0x57, 0x14, - 0xf6, 0x52, 0xb5, 0x5c, 0x9b, 0xb1, 0x74, 0x27, 0xd7, 0x31, 0x84, 0x0f, - 0x2b, 0xdf, 0xfe, 0x1e, 0x44, 0xb7, 0x3f, 0x6a, 0x18, 0xe4, 0xfa, 0x36, - 0x1f, 0xa3, 0xec, 0x29, 0x07, 0x19, 0x63, 0xfb, 0xac, 0xf8, 0xea, 0x23, - 0x8d, 0xeb, 0x79, 0x6c, 0x6b, 0x46, 0x6a, 0xa9, 0x89, 0xc7, 0x75, 0x13, - 0xcf, 0xf2, 0x77, 0x89, 0xb9, 0x6c, 0xec, 0x86, 0x5c, 0xe6, 0xe0, 0x73, - 0xbb, 0xf9, 0x5c, 0x0b, 0x53, 0xe7, 0xc2, 0x9c, 0xcc, 0x06, 0x0f, 0xcb, - 0x6c, 0x10, 0x39, 0x43, 0x74, 0x3f, 0x8c, 0x0b, 0x99, 0x48, 0xca, 0xe9, - 0x34, 0x47, 0x18, 0x57, 0x4b, 0x1f, 0xd1, 0x77, 0x5f, 0xdf, 0xa8, 0xf6, - 0x52, 0x87, 0xb1, 0x49, 0x45, 0x0d, 0xbd, 0x86, 0x42, 0xa7, 0x07, 0x8d, - 0xe1, 0x75, 0xce, 0x68, 0xe0, 0x2c, 0xd4, 0xc2, 0x20, 0x25, 0x7d, 0x3a, - 0x6f, 0xe7, 0xba, 0xcd, 0xc5, 0x5c, 0xd7, 0x92, 0xab, 0x50, 0xee, 0xcc, - 0xb2, 0x3e, 0xcf, 0x99, 0x69, 0x3f, 0xeb, 0x55, 0x7e, 0x4e, 0x68, 0x8f, - 0xa0, 0x31, 0x2e, 0xb4, 0xb4, 0xae, 0x49, 0x05, 0x5f, 0xaf, 0x44, 0x94, - 0xb5, 0x0a, 0x7a, 0xb9, 0x96, 0x36, 0x59, 0x93, 0x02, 0xee, 0x84, 0xd4, - 0xce, 0x1e, 0xf6, 0x2d, 0x7d, 0xcc, 0x8b, 0x82, 0xa9, 0x65, 0x5e, 0x6a, - 0xe7, 0xa3, 0x6d, 0x79, 0xb1, 0x8b, 0xd8, 0x44, 0x6c, 0x73, 0x18, 0x07, - 0xac, 0x79, 0xb4, 0x89, 0x69, 0x5d, 0x72, 0x83, 0xd8, 0xe9, 0x30, 0xf6, - 0xe7, 0xdd, 0xb8, 0x97, 0x79, 0x70, 0xbe, 0x99, 0xba, 0xf2, 0xbb, 0x31, - 0x38, 0x77, 0x3b, 0xf6, 0x65, 0x65, 0x9e, 0xe0, 0xa6, 0xfd, 0x92, 0xc4, - 0x40, 0xcc, 0x3a, 0xc4, 0x3f, 0x65, 0x5a, 0x49, 0xa7, 0x42, 0x5b, 0x74, - 0x5a, 0xfa, 0xbe, 0xe0, 0xb6, 0x75, 0x6c, 0xcf, 0x2d, 0x9d, 0x09, 0x59, - 0xab, 0x34, 0xb3, 0xb4, 0xf5, 0xda, 0x99, 0x91, 0x35, 0x4d, 0x9c, 0xd5, - 0x6d, 0x4c, 0x5b, 0xd2, 0x67, 0x88, 0x32, 0xd7, 0x6c, 0x02, 0xd6, 0xdd, - 0x80, 0x6b, 0x2b, 0x78, 0xad, 0xfb, 0x3a, 0xae, 0xed, 0x17, 0xec, 0x4c, - 0x5c, 0xdb, 0xb5, 0x83, 0xb8, 0xb6, 0x5e, 0x29, 0x61, 0x5a, 0x99, 0x59, - 0x94, 0x70, 0x6d, 0x75, 0x31, 0x7f, 0x1f, 0xc6, 0x5e, 0x62, 0x9e, 0xda, - 0xfa, 0x11, 0x78, 0xd6, 0x3b, 0x3e, 0x73, 0x60, 0x84, 0xbd, 0x4c, 0x19, - 0xb0, 0xd2, 0xc4, 0x2d, 0x1b, 0xd2, 0x66, 0xb9, 0x56, 0x1f, 0x2e, 0x77, - 0xc8, 0x4c, 0x3a, 0x9a, 0x1e, 0x63, 0x9e, 0x71, 0xac, 0x57, 0xd3, 0x49, - 0x78, 0x02, 0x35, 0xda, 0x3d, 0xc5, 0x5e, 0x22, 0xe4, 0xd9, 0x4e, 0x4c, - 0x14, 0x8d, 0x7f, 0x6a, 0xce, 0x06, 0x85, 0x46, 0xa1, 0xe0, 0x41, 0xf2, - 0x11, 0x0f, 0x6b, 0xd4, 0xb2, 0x32, 0x81, 0xd7, 0xa3, 0x21, 0xcf, 0xce, - 0x7c, 0xda, 0xdb, 0xdd, 0x70, 0x0b, 0x7a, 0x4e, 0x49, 0x3d, 0x0a, 0x63, - 0xc7, 0xa9, 0x76, 0xd6, 0x20, 0x0d, 0x1d, 0x93, 0x5d, 0xec, 0xf1, 0x7a, - 0x95, 0xde, 0x39, 0xd1, 0xa1, 0xd8, 0x40, 0x0d, 0x84, 0x1d, 0x37, 0xce, - 0x4c, 0x4b, 0xfd, 0xf2, 0x7b, 0x96, 0x7f, 0x8d, 0xeb, 0x01, 0xea, 0xe7, - 0xaa, 0x1b, 0x7e, 0x13, 0x67, 0x74, 0xf1, 0x4b, 0x7e, 0x37, 0x92, 0xd8, - 0xd6, 0x3c, 0x6d, 0xba, 0x34, 0x99, 0x7d, 0x87, 0x2c, 0x9b, 0x6e, 0x65, - 0x9d, 0x6b, 0x9f, 0xeb, 0xa3, 0x1d, 0x4b, 0x73, 0xee, 0x1b, 0xed, 0xb9, - 0xc5, 0xbb, 0x8d, 0x39, 0x8f, 0x3d, 0xbc, 0xc7, 0xc3, 0x3c, 0xea, 0x39, - 0x65, 0x62, 0x4e, 0x7f, 0xcb, 0x7c, 0x5c, 0x73, 0xd1, 0x6e, 0x5f, 0x65, - 0x4e, 0x16, 0xcc, 0x92, 0xf0, 0xde, 0x31, 0xe3, 0x72, 0x54, 0x25, 0xd0, - 0x5c, 0x46, 0x7f, 0xbc, 0x18, 0xb7, 0xe7, 0x91, 0xc7, 0x73, 0xb7, 0x7b, - 0xbb, 0xb3, 0xec, 0x33, 0xd8, 0x07, 0xdb, 0xbd, 0xdf, 0x57, 0xbd, 0x7b, - 0xb2, 0x4e, 0xa5, 0x36, 0x01, 0x67, 0xcb, 0x26, 0x13, 0x1f, 0x6f, 0x88, - 0xa6, 0x42, 0x0e, 0xe6, 0x4f, 0xd2, 0x32, 0x72, 0xcd, 0xde, 0x7e, 0xe6, - 0xeb, 0x9d, 0x59, 0xba, 0x01, 0x7d, 0xc7, 0xbf, 0x61, 0x74, 0xc0, 0x0f, - 0x99, 0xb3, 0xe1, 0xeb, 0x8c, 0xd8, 0x20, 0xfd, 0x31, 0xd4, 0xa6, 0x44, - 0x97, 0x87, 0x10, 0x5d, 0xfa, 0xd8, 0xf9, 0x96, 0xf9, 0x64, 0x6e, 0x13, - 0x9f, 0xef, 0x62, 0x2e, 0x4d, 0x32, 0xb7, 0x8e, 0xa6, 0xdc, 0x90, 0x77, - 0xd4, 0xfe, 0x37, 0x95, 0x08, 0xe3, 0x00, 0xbf, 0xc3, 0xe7, 0x03, 0x1d, - 0xcc, 0xa3, 0x73, 0x7a, 0x34, 0xb9, 0x15, 0xe9, 0xae, 0x6a, 0xa8, 0x7a, - 0x83, 0x22, 0x73, 0x31, 0xb1, 0x43, 0x0c, 0x3f, 0xe1, 0x9a, 0x2e, 0x4d, - 0xf4, 0xb8, 0x85, 0xbe, 0x48, 0x6c, 0xe0, 0xf8, 0xbc, 0xdf, 0xfd, 0x5e, - 0x19, 0x2a, 0x56, 0x50, 0xb6, 0x9f, 0x58, 0x39, 0xc7, 0xab, 0x69, 0xf8, - 0xaf, 0xc4, 0x4e, 0x7f, 0x96, 0x97, 0xf9, 0x67, 0x09, 0x0f, 0x8a, 0x6f, - 0x64, 0x5a, 0x6f, 0x9d, 0x8d, 0x15, 0xe7, 0xa1, 0x1e, 0x6f, 0xd7, 0x8c, - 0x89, 0xac, 0xee, 0x87, 0xf4, 0xff, 0xe5, 0xf1, 0x02, 0xd1, 0x41, 0x13, - 0x3a, 0x78, 0xbd, 0x7d, 0xa6, 0x52, 0x69, 0xcf, 0x9a, 0xf8, 0x33, 0x5d, - 0x4d, 0xb7, 0x39, 0x19, 0xef, 0xba, 0x7a, 0x16, 0xf8, 0x19, 0x71, 0x94, - 0xf8, 0x98, 0x0b, 0x3e, 0xcd, 0xa6, 0xd5, 0x34, 0x7b, 0x3b, 0xb1, 0x85, - 0xc4, 0x9f, 0x73, 0x6d, 0x05, 0x9a, 0x95, 0x59, 0x97, 0xe8, 0xad, 0x0b, - 0xc9, 0x7c, 0xa5, 0xb2, 0x8b, 0xba, 0xbc, 0x73, 0xbd, 0x17, 0x97, 0x2c, - 0x5d, 0xde, 0x4e, 0x5d, 0xe2, 0x8d, 0xd5, 0x70, 0x5e, 0xa8, 0x05, 0xc1, - 0x44, 0xb9, 0x1a, 0x1e, 0x70, 0x88, 0x4d, 0x18, 0x27, 0x82, 0xd5, 0x50, - 0xc9, 0x7a, 0x9e, 0x24, 0x0e, 0x26, 0x6e, 0x0c, 0xf4, 0xe1, 0xdb, 0xcc, - 0x4b, 0x8f, 0xd3, 0x6f, 0x7f, 0xa1, 0x35, 0xa1, 0xe2, 0x3b, 0xcd, 0xb4, - 0xe9, 0x26, 0xef, 0xf6, 0x6c, 0x3f, 0x9e, 0x58, 0x30, 0xf1, 0x0c, 0x63, - 0xa6, 0x21, 0x9e, 0x0e, 0x94, 0xb3, 0xaf, 0x63, 0xed, 0x5b, 0x3e, 0x61, - 0xf9, 0xfc, 0x68, 0xeb, 0x96, 0xf9, 0x10, 0x9c, 0xdf, 0xb6, 0xf6, 0x7e, - 0x5a, 0xc3, 0xf3, 0xd6, 0xde, 0x0f, 0x3f, 0x4d, 0x0c, 0xeb, 0x6a, 0xf2, - 0x63, 0x67, 0x05, 0x2a, 0xa3, 0xa6, 0x39, 0x1c, 0xb7, 0xf6, 0x1f, 0x5a, - 0x63, 0xd6, 0xfd, 0xa3, 0xfc, 0x2c, 0xcd, 0xae, 0xff, 0x46, 0x30, 0x63, - 0x38, 0x49, 0xf9, 0x77, 0x10, 0x07, 0xf4, 0x13, 0x07, 0xd4, 0x26, 0xd4, - 0xe4, 0x6e, 0xa7, 0xcc, 0x69, 0x0a, 0x87, 0xaa, 0x79, 0xfd, 0x8e, 0x22, - 0x0e, 0xa8, 0x3a, 0x25, 0xb3, 0x3f, 0x62, 0x45, 0xd8, 0x7b, 0x26, 0x3d, - 0xc4, 0x01, 0x15, 0x93, 0x2e, 0x74, 0x13, 0x03, 0xb8, 0x89, 0xd9, 0xb7, - 0xe5, 0x6a, 0xe1, 0x3d, 0xe1, 0x44, 0x24, 0xfe, 0x23, 0x1c, 0xa2, 0xbf, - 0x1d, 0x8a, 0x79, 0x94, 0xf0, 0x2a, 0x07, 0x75, 0xf6, 0x2b, 0x1c, 0x0c, - 0x38, 0x51, 0xa5, 0xbd, 0x86, 0x07, 0xbf, 0xa0, 0xf6, 0xf7, 0x67, 0x25, - 0xce, 0x47, 0x5b, 0xbb, 0x4f, 0xd9, 0xb5, 0xdf, 0x77, 0x6a, 0x74, 0x59, - 0x6a, 0x7f, 0xed, 0x86, 0x7e, 0x9c, 0x9e, 0xc1, 0x37, 0x57, 0x13, 0x64, - 0xd6, 0x72, 0xcd, 0xfa, 0x78, 0x94, 0x3d, 0xb8, 0x3a, 0xd4, 0xa1, 0x44, - 0x27, 0xaa, 0x98, 0x0f, 0x4e, 0xb3, 0xf6, 0x7b, 0x12, 0xd1, 0x40, 0xcc, - 0x81, 0x1e, 0x37, 0x6d, 0xf3, 0x3e, 0xfb, 0xf1, 0x9f, 0xe6, 0xc2, 0xa4, - 0x59, 0x06, 0x17, 0x6b, 0xff, 0xfb, 0x1a, 0x3e, 0x73, 0xd2, 0x0f, 0xdf, - 0x71, 0x7a, 0x70, 0x35, 0x67, 0xd7, 0xfe, 0xea, 0x06, 0x73, 0xe4, 0x72, - 0xdc, 0x87, 0x2b, 0x39, 0x9d, 0xfe, 0xd8, 0x8f, 0xa3, 0xac, 0xfd, 0x97, - 0xb5, 0x00, 0x3e, 0xcc, 0xb5, 0xd0, 0x47, 0x83, 0xf8, 0x39, 0x71, 0xf2, - 0x7a, 0xd6, 0xfe, 0xbb, 0xe8, 0x5f, 0x71, 0xd6, 0xfe, 0x36, 0x0b, 0x97, - 0x64, 0x5a, 0xcf, 0x4c, 0x5b, 0xb5, 0xbf, 0xc1, 0xc1, 0xba, 0xe9, 0x46, - 0x74, 0x99, 0x39, 0xc3, 0xfc, 0xc5, 0x26, 0x1f, 0x9f, 0xa5, 0xde, 0xf2, - 0x1b, 0x30, 0x6b, 0xd5, 0xaa, 0x2d, 0xde, 0x5d, 0x5c, 0x7b, 0xa5, 0x15, - 0x73, 0x26, 0x76, 0xac, 0xff, 0x6b, 0xfc, 0x41, 0x8d, 0x83, 0x3e, 0x99, - 0xf0, 0xde, 0xc9, 0xb8, 0xf3, 0x27, 0x4a, 0xb3, 0x91, 0x18, 0xd7, 0xb9, - 0xdd, 0x7b, 0x17, 0xfd, 0xe4, 0x96, 0xf5, 0xcc, 0x2a, 0x01, 0x3b, 0xe6, - 0xda, 0x19, 0x73, 0x21, 0xc6, 0xdc, 0x6a, 0xc6, 0xdc, 0x93, 0x7a, 0x34, - 0xb6, 0x85, 0xf8, 0xec, 0x95, 0x9c, 0xc4, 0x5d, 0x33, 0xe9, 0xaa, 0x94, - 0x6b, 0x74, 0x40, 0xe2, 0x67, 0xc7, 0xfa, 0xd1, 0xb3, 0x95, 0x10, 0x5d, - 0xe1, 0xb3, 0x95, 0xc4, 0x22, 0xcc, 0x52, 0x4b, 0xcb, 0xce, 0x68, 0xea, - 0x36, 0x67, 0x74, 0xf8, 0x3d, 0xe5, 0x2d, 0xf3, 0x0d, 0xc6, 0xdc, 0x4e, - 0xc6, 0xdc, 0x2e, 0xc6, 0x5c, 0x9b, 0x61, 0xe2, 0x85, 0xb8, 0xda, 0xdf, - 0xe4, 0x88, 0xe8, 0x6d, 0x0e, 0xac, 0xae, 0x64, 0x09, 0xf1, 0x22, 0xda, - 0xf5, 0x07, 0xe4, 0x7f, 0x49, 0x8f, 0xf6, 0xc6, 0x14, 0x89, 0xb3, 0x30, - 0x3e, 0xa0, 0xdc, 0xe5, 0xc5, 0x38, 0x3b, 0x30, 0x77, 0xbe, 0xe8, 0x1b, - 0x25, 0xd9, 0x9d, 0x78, 0x5e, 0x67, 0x5e, 0x5d, 0x21, 0xbe, 0xdb, 0x87, - 0x09, 0xea, 0xd1, 0x1b, 0xed, 0xc3, 0x31, 0xd6, 0xcd, 0xfb, 0x58, 0xaf, - 0xef, 0x37, 0x22, 0x2d, 0xdb, 0xd9, 0x27, 0x5d, 0x0a, 0xa9, 0xe1, 0xb0, - 0xd2, 0x87, 0x41, 0xfa, 0xf0, 0x20, 0xeb, 0x4b, 0x9b, 0xf1, 0x4b, 0xa5, - 0x83, 0x98, 0x62, 0x7f, 0x5e, 0xde, 0x53, 0x63, 0x69, 0xc7, 0x10, 0x06, - 0x16, 0x24, 0xcf, 0x21, 0x70, 0x53, 0xa2, 0x0f, 0x53, 0x46, 0x19, 0xfa, - 0x9a, 0x7b, 0x94, 0x3b, 0xf2, 0x32, 0xa7, 0x63, 0x6c, 0x1a, 0x8c, 0x5d, - 0x8b, 0x5f, 0x05, 0xb9, 0x68, 0x0f, 0x32, 0x12, 0xab, 0xc6, 0x2e, 0xe5, - 0xae, 0x39, 0x89, 0xf7, 0x3e, 0xa5, 0x4f, 0xe2, 0xd9, 0x48, 0x29, 0x77, - 0x4b, 0x7c, 0x5b, 0xb3, 0x6d, 0xc9, 0x01, 0xb2, 0xf7, 0x71, 0x3b, 0xf1, - 0x1e, 0x18, 0x5f, 0xce, 0xef, 0x84, 0x18, 0x83, 0x6d, 0x65, 0x0e, 0xfa, - 0x69, 0x84, 0xb6, 0x73, 0xa0, 0x5d, 0xff, 0xb2, 0x99, 0x0e, 0x0c, 0x30, - 0xa6, 0xfa, 0x70, 0xd4, 0x08, 0x99, 0x97, 0x2d, 0x1c, 0x53, 0xca, 0xf1, - 0x5b, 0x58, 0xeb, 0x56, 0xc1, 0xa3, 0x49, 0x7d, 0xf7, 0x21, 0x56, 0xe3, - 0x41, 0x85, 0x26, 0xb5, 0x27, 0xd3, 0xba, 0x78, 0x42, 0x91, 0x3e, 0xa5, - 0x18, 0xeb, 0x5b, 0xf0, 0x00, 0x73, 0xc2, 0xbe, 0xf8, 0xbd, 0xb8, 0x3f, - 0x50, 0x01, 0x3f, 0xf5, 0xf4, 0x50, 0xc0, 0xc7, 0x5c, 0xfb, 0x7b, 0x45, - 0x3a, 0x7f, 0x51, 0x56, 0xec, 0xbf, 0xaf, 0x61, 0xb0, 0x5a, 0xc6, 0xd8, - 0xe6, 0x19, 0x99, 0x27, 0xa5, 0x5a, 0x43, 0x33, 0x1a, 0xfc, 0xec, 0x7b, - 0xb7, 0xc4, 0xd5, 0xd4, 0x16, 0x67, 0x44, 0x7a, 0x9a, 0x8c, 0x9f, 0xf8, - 0x2f, 0x17, 0x8d, 0xf6, 0x36, 0x89, 0x8e, 0xb5, 0x10, 0x3a, 0xa9, 0xa7, - 0xee, 0x5c, 0x90, 0x31, 0xe4, 0x28, 0x17, 0x2c, 0x95, 0xcc, 0x5d, 0xa7, - 0x15, 0x22, 0xad, 0xd0, 0x8c, 0xe0, 0xba, 0x14, 0x71, 0x9d, 0xc6, 0x38, - 0x34, 0xcd, 0xcd, 0xc4, 0x73, 0xbe, 0x53, 0x32, 0x97, 0x8a, 0x4c, 0x10, - 0x03, 0x37, 0x11, 0x1f, 0xf7, 0xd1, 0xab, 0xcd, 0x5b, 0xea, 0xa3, 0x7a, - 0x9b, 0x82, 0xc7, 0xe6, 0x9b, 0xe1, 0x71, 0x92, 0xe6, 0x3b, 0xb9, 0x00, - 0x2e, 0xe7, 0x42, 0x78, 0x9b, 0xb4, 0x2f, 0x59, 0xb4, 0xeb, 0xf0, 0xb3, - 0x62, 0x0e, 0x8b, 0x33, 0x87, 0x6d, 0xcd, 0x2a, 0xf4, 0xd7, 0x30, 0x46, - 0xf4, 0xbf, 0xfa, 0xec, 0xd2, 0xcd, 0x1e, 0xea, 0x4d, 0x64, 0x71, 0xf1, - 0x73, 0x1c, 0x0f, 0x59, 0x39, 0xfb, 0xb5, 0xcf, 0x66, 0x6b, 0x68, 0x2b, - 0xea, 0xbe, 0xba, 0xf8, 0xde, 0xba, 0xd9, 0x3f, 0x2f, 0xca, 0xdb, 0x53, - 0xb4, 0x35, 0x71, 0x9b, 0x71, 0x9e, 0xd7, 0x04, 0x47, 0x69, 0x70, 0x9c, - 0x8a, 0xa1, 0xec, 0xd4, 0x35, 0xfe, 0x35, 0x89, 0x19, 0x56, 0xde, 0xc7, - 0xbe, 0x4b, 0x9e, 0x1e, 0x21, 0x5e, 0x34, 0xc9, 0xd3, 0x55, 0x8b, 0x97, - 0x20, 0x79, 0xf9, 0xe4, 0xb3, 0x12, 0xb6, 0x0c, 0x5d, 0x7b, 0x27, 0x40, - 0x7d, 0xe0, 0xd1, 0x10, 0xf5, 0x79, 0x65, 0xa3, 0x3c, 0xe7, 0xc3, 0x1d, - 0xb9, 0x44, 0xb9, 0xe4, 0x79, 0xaf, 0xb6, 0x05, 0x7b, 0xe7, 0x3e, 0xaf, - 0xf7, 0x20, 0x6d, 0x11, 0xa0, 0xf1, 0xe4, 0xde, 0x17, 0xd5, 0xd4, 0x3f, - 0x42, 0x8a, 0x3d, 0xd3, 0x23, 0xd9, 0x34, 0x1e, 0xca, 0x7e, 0xcb, 0xda, - 0xcb, 0x5b, 0xb7, 0x01, 0xfb, 0x49, 0xff, 0x60, 0x35, 0xe3, 0xe8, 0x7f, - 0xc4, 0xa3, 0x82, 0xa5, 0x76, 0x55, 0x42, 0xea, 0x6e, 0xb4, 0xe5, 0x36, - 0xc5, 0x44, 0x59, 0x1c, 0xc3, 0xed, 0xcd, 0xd1, 0xd8, 0x65, 0x3c, 0x66, - 0xca, 0x5c, 0xdc, 0x59, 0xac, 0xc1, 0xc4, 0xaf, 0x4a, 0x3b, 0xeb, 0x70, - 0x5b, 0x11, 0x53, 0x6d, 0xcd, 0xbf, 0xf5, 0xb9, 0xd9, 0x83, 0xf4, 0xed, - 0x52, 0x7b, 0xbc, 0x4a, 0x1b, 0xd7, 0x39, 0xca, 0x9c, 0xfd, 0xbc, 0xfe, - 0x52, 0x88, 0x95, 0x19, 0xae, 0xf5, 0x0a, 0x0e, 0x11, 0x3f, 0xa5, 0x83, - 0x26, 0x76, 0xf1, 0xf3, 0x00, 0x71, 0xd6, 0xbb, 0x7a, 0x15, 0x66, 0x03, - 0x01, 0x62, 0x4b, 0xe6, 0x60, 0xc7, 0xdf, 0x49, 0x4d, 0x88, 0x85, 0x1d, - 0xb2, 0x57, 0xff, 0x6f, 0xed, 0xdf, 0xac, 0x27, 0x96, 0x11, 0xd9, 0xbd, - 0x0a, 0x73, 0x68, 0x0c, 0xc4, 0x37, 0x7b, 0xf5, 0x42, 0xd8, 0x81, 0xe4, - 0x55, 0x07, 0xd4, 0xd3, 0xef, 0xb0, 0x1f, 0x7c, 0xa4, 0x5e, 0x3d, 0xdd, - 0xea, 0xd4, 0x90, 0x9a, 0xf2, 0xe0, 0xe1, 0xa9, 0x0e, 0x54, 0x5b, 0x73, - 0xa4, 0x71, 0xda, 0xcc, 0xc1, 0x3e, 0x6c, 0xf4, 0x53, 0x17, 0xfb, 0xb1, - 0xab, 0x1b, 0x1e, 0x45, 0x8b, 0x75, 0x7d, 0x0c, 0xfb, 0xb3, 0x5e, 0xa5, - 0x3b, 0xeb, 0x42, 0xc7, 0x5d, 0x8f, 0xc2, 0xbd, 0x7e, 0x80, 0x7c, 0xc9, - 0x75, 0xf9, 0xfb, 0x6e, 0xf6, 0x71, 0xc2, 0x5f, 0x19, 0xc2, 0xab, 0xc8, - 0xdb, 0x7a, 0x0d, 0x23, 0x53, 0x2e, 0x65, 0xb7, 0xf1, 0x37, 0xe6, 0x55, - 0x6b, 0x6f, 0x48, 0xae, 0x55, 0xc8, 0x99, 0x01, 0x3e, 0x23, 0x39, 0x67, - 0x10, 0x59, 0xc6, 0xf6, 0xdd, 0xd6, 0xfb, 0xa7, 0xca, 0x6c, 0x99, 0x92, - 0xec, 0x6f, 0xdb, 0xe9, 0x1f, 0xf2, 0x4c, 0x5b, 0xf1, 0xda, 0x76, 0x8f, - 0x7d, 0x2e, 0x41, 0xec, 0x3e, 0x88, 0x5b, 0x69, 0x84, 0xfa, 0xa8, 0xf8, - 0xd8, 0x20, 0xea, 0x73, 0x4c, 0xa8, 0xab, 0x6c, 0x7e, 0x1f, 0x34, 0x0a, - 0xec, 0x4d, 0x35, 0xe6, 0x4d, 0xea, 0x6e, 0xa5, 0xbc, 0x4f, 0x47, 0xfd, - 0xb5, 0xf7, 0x4b, 0xf5, 0x54, 0x70, 0xe9, 0x17, 0xdd, 0xff, 0x4d, 0xc8, - 0x3d, 0x97, 0xf6, 0x87, 0x8c, 0xe3, 0x68, 0x6f, 0xa5, 0x43, 0xfc, 0xe7, - 0x0f, 0x71, 0xff, 0x1c, 0x1b, 0xd7, 0x0a, 0xa1, 0x4f, 0xdc, 0x6b, 0xb8, - 0x94, 0x2e, 0xe6, 0x9f, 0x03, 0x53, 0x8e, 0x3b, 0xca, 0xf0, 0xe7, 0x66, - 0xf9, 0xca, 0x11, 0xd4, 0xc7, 0xc7, 0xf8, 0xbc, 0x82, 0x76, 0x62, 0xc8, - 0x27, 0xf4, 0xad, 0xe8, 0xa8, 0x91, 0x1c, 0xf0, 0xbc, 0x39, 0xd8, 0x27, - 0x3a, 0x54, 0xb0, 0x8d, 0xd7, 0x5f, 0xa0, 0x7d, 0x9f, 0xd6, 0x5d, 0xa8, - 0x5f, 0x21, 0x33, 0x41, 0x75, 0x3a, 0x89, 0x3d, 0x1e, 0x7b, 0x8f, 0x2c, - 0x6d, 0x56, 0x6b, 0xda, 0xf0, 0x9d, 0x8e, 0xfa, 0xe9, 0x37, 0xe9, 0x4f, - 0x6d, 0xeb, 0x6f, 0xbc, 0x57, 0xd2, 0x89, 0x8e, 0xd0, 0xfa, 0xe7, 0x4c, - 0xdc, 0x34, 0x8a, 0xc0, 0xfa, 0x1b, 0xed, 0x5f, 0xe2, 0xfb, 0x30, 0x63, - 0x10, 0xe9, 0xea, 0x84, 0xcc, 0x89, 0xa2, 0xa4, 0x73, 0x18, 0xbf, 0x9f, - 0x1f, 0xc3, 0xa1, 0xac, 0xc8, 0xb9, 0x60, 0xf9, 0xb6, 0xb6, 0xfe, 0xba, - 0x6c, 0x0f, 0x66, 0xa3, 0x03, 0x55, 0x45, 0xd9, 0x0e, 0xb2, 0x1f, 0xa9, - 0x64, 0x8e, 0x7d, 0x80, 0x3a, 0x1d, 0xb6, 0x74, 0xda, 0x07, 0x3d, 0x77, - 0x9d, 0xee, 0x10, 0xe9, 0x7a, 0x13, 0xa2, 0x37, 0xd9, 0x97, 0x63, 0x2f, - 0x40, 0xba, 0xfb, 0x6e, 0xa0, 0x3b, 0xa8, 0x5f, 0xa7, 0xbb, 0x37, 0x1b, - 0x3d, 0xed, 0x28, 0xd2, 0xfd, 0xc6, 0x5c, 0x89, 0x46, 0x1a, 0x3b, 0xd7, - 0xa7, 0x91, 0xdb, 0x7c, 0xd0, 0x3c, 0x68, 0xe9, 0xe3, 0xfb, 0xd6, 0xf5, - 0x6d, 0xf5, 0x12, 0x0f, 0xfc, 0x33, 0xa1, 0x59, 0x67, 0x00, 0x6c, 0x1c, - 0x76, 0x63, 0x7c, 0xa8, 0x6f, 0x75, 0x3b, 0x93, 0x8c, 0xe3, 0xa0, 0x67, - 0xfb, 0xe7, 0x66, 0x1f, 0x1d, 0xec, 0xd7, 0x3a, 0x8d, 0x1e, 0x6f, 0x97, - 0xe1, 0x21, 0x06, 0xab, 0x54, 0xb6, 0x65, 0x65, 0x06, 0x22, 0xb1, 0x5c, - 0xc4, 0xc5, 0x79, 0xe9, 0x0b, 0xef, 0x61, 0xcf, 0xb0, 0x81, 0xf6, 0x1d, - 0xc0, 0x44, 0x7e, 0x40, 0x49, 0x06, 0xb9, 0x8e, 0x21, 0x75, 0x05, 0xac, - 0x79, 0xbd, 0xa8, 0xa4, 0x2f, 0x05, 0x13, 0xd3, 0x89, 0x93, 0xf5, 0x26, - 0x88, 0x51, 0x3c, 0x2b, 0x12, 0xb3, 0x89, 0x5d, 0xf5, 0x4e, 0x1c, 0xb7, - 0xb0, 0x98, 0x3a, 0xcb, 0xdf, 0x69, 0x89, 0x99, 0x3b, 0xb3, 0x52, 0xc7, - 0x08, 0x27, 0xb5, 0x11, 0xfc, 0x63, 0xbc, 0x30, 0x5c, 0x83, 0xe4, 0x7d, - 0x35, 0x90, 0x1e, 0x63, 0x02, 0x7f, 0xa9, 0x85, 0x3c, 0xfd, 0x79, 0x97, - 0xd2, 0x6d, 0xcc, 0x7b, 0x77, 0x18, 0x7e, 0xf8, 0xd8, 0xbf, 0xf5, 0x38, - 0x23, 0xec, 0x39, 0xac, 0x19, 0x7d, 0xeb, 0xad, 0xb9, 0x7e, 0x6f, 0xbb, - 0x61, 0xe7, 0xc2, 0x5b, 0x66, 0x3d, 0xde, 0x8e, 0x99, 0x48, 0x68, 0xc2, - 0xc2, 0x62, 0x07, 0x5b, 0x23, 0x39, 0xd3, 0x7c, 0x55, 0x2f, 0x5c, 0x2d, - 0xb7, 0xbe, 0x4f, 0xb7, 0xc6, 0x72, 0x4d, 0xd8, 0x43, 0xfc, 0xd4, 0x36, - 0xd3, 0x04, 0x7d, 0x06, 0x38, 0x31, 0x15, 0xc2, 0xba, 0xac, 0x7a, 0x3a, - 0xe5, 0xec, 0xc7, 0xf4, 0x42, 0x17, 0xb2, 0x79, 0xef, 0x72, 0xd8, 0x41, - 0x8c, 0x1d, 0x77, 0xe0, 0x0e, 0x7d, 0x83, 0x52, 0xb0, 0x62, 0x5a, 0xc1, - 0xdd, 0xfa, 0x2e, 0x65, 0xc0, 0xc2, 0x14, 0xf3, 0xc4, 0x22, 0x0a, 0x6e, - 0xb2, 0x72, 0xef, 0xc9, 0xd6, 0x38, 0xf1, 0xf7, 0x1d, 0x59, 0xa9, 0xef, - 0x26, 0x2e, 0xc6, 0xa9, 0x97, 0x78, 0xba, 0xdf, 0xcd, 0x7e, 0xe8, 0xa0, - 0xa2, 0xf6, 0xea, 0x8a, 0x8d, 0xf1, 0x6e, 0x9b, 0xb7, 0x71, 0xe1, 0xad, - 0xf3, 0xcd, 0x5e, 0xc9, 0x41, 0xed, 0xba, 0x1a, 0x72, 0x39, 0x02, 0x18, - 0xb6, 0x68, 0xa4, 0x5b, 0xf5, 0xf9, 0x32, 0xac, 0xd6, 0xfa, 0x70, 0xda, - 0x92, 0x61, 0xa2, 0x75, 0x0b, 0xb1, 0xf6, 0x93, 0x46, 0x3f, 0x7b, 0x65, - 0xd9, 0x37, 0x8d, 0xc4, 0x5a, 0x9c, 0x6d, 0xc4, 0xb3, 0x91, 0xf0, 0xb2, - 0x92, 0x54, 0xd2, 0xae, 0xc6, 0xe4, 0x3c, 0x58, 0x51, 0x6a, 0xec, 0xfa, - 0x26, 0x32, 0x46, 0x89, 0xb3, 0xda, 0xa6, 0xbc, 0xcb, 0x49, 0xd8, 0x73, - 0x9e, 0x4e, 0xfd, 0xff, 0xe0, 0x52, 0x50, 0x9d, 0x48, 0x92, 0xef, 0x0e, - 0xe6, 0xdd, 0x42, 0x9f, 0x8b, 0xf7, 0x65, 0xbe, 0x37, 0xdc, 0x3a, 0x9e, - 0x41, 0xc1, 0x99, 0x90, 0x1e, 0x0b, 0xfe, 0xde, 0x3c, 0x64, 0xd6, 0xc4, - 0x3e, 0xe3, 0x53, 0xb3, 0xb4, 0xc7, 0xd4, 0x33, 0x63, 0xef, 0x9f, 0x65, - 0x16, 0x5c, 0xfe, 0x1d, 0x46, 0x33, 0x8e, 0xe7, 0x5d, 0x37, 0xd0, 0x8e, - 0x4e, 0xdc, 0xe2, 0x70, 0x20, 0xba, 0xfe, 0x6e, 0xa5, 0xb8, 0x07, 0xc5, - 0x3c, 0x91, 0xb2, 0x6a, 0x62, 0x19, 0xe5, 0xbc, 0x70, 0x52, 0xd6, 0xf8, - 0x56, 0xeb, 0xf8, 0x49, 0xa9, 0x91, 0xc3, 0xad, 0x21, 0x43, 0xed, 0x95, - 0x9e, 0xb0, 0x9a, 0x7a, 0xfa, 0x68, 0x52, 0x6a, 0xf0, 0x14, 0x6b, 0xb0, - 0xba, 0xdc, 0xae, 0x48, 0x1d, 0x53, 0x63, 0x5e, 0xa7, 0x03, 0x57, 0x1a, - 0xd4, 0xfe, 0x1f, 0x40, 0x1d, 0xb0, 0xe7, 0x8a, 0x8f, 0xb6, 0x36, 0x16, - 0xf1, 0xf0, 0x6d, 0xf3, 0x83, 0x72, 0xee, 0xc4, 0xd2, 0x71, 0x53, 0x4e, - 0xb0, 0xb1, 0x69, 0xbe, 0x1c, 0xef, 0x21, 0x6e, 0x10, 0x6c, 0x2c, 0xd7, - 0x27, 0x5b, 0x1b, 0x66, 0x3d, 0xe4, 0x4d, 0xc1, 0x7b, 0x5a, 0x0f, 0x7d, - 0xaf, 0xc4, 0xa3, 0x8d, 0x9b, 0xb7, 0x13, 0x37, 0x3b, 0x13, 0x6a, 0xcb, - 0x56, 0xe2, 0x66, 0x8d, 0xfd, 0x84, 0x0b, 0x7d, 0x78, 0xc2, 0xb0, 0x7b, - 0x0a, 0xc1, 0xce, 0xe6, 0x49, 0x35, 0x29, 0xb8, 0xf9, 0xea, 0x06, 0x60, - 0x37, 0x71, 0xf3, 0x72, 0xc6, 0x85, 0x7e, 0xe2, 0xe6, 0x8f, 0x98, 0x82, - 0xee, 0x24, 0x6e, 0xbe, 0x42, 0x8c, 0x75, 0x3e, 0xfe, 0x73, 0x7c, 0xa3, - 0x38, 0x3b, 0xdb, 0x4b, 0xec, 0x9c, 0x0c, 0xde, 0x88, 0x9d, 0xff, 0xe2, - 0x5f, 0x60, 0xe7, 0x3d, 0xc4, 0x84, 0x3d, 0x59, 0xd9, 0x67, 0x1a, 0x6d, - 0x7d, 0xe3, 0x94, 0x9c, 0x6d, 0xb9, 0x0d, 0xef, 0x9e, 0x1c, 0x1d, 0x22, - 0x56, 0xc6, 0x58, 0xbc, 0x1f, 0x99, 0x19, 0xac, 0x22, 0x2e, 0x78, 0xd9, - 0xc9, 0x75, 0xd7, 0xc5, 0x55, 0xfd, 0x4d, 0x25, 0xda, 0xd5, 0x8f, 0x28, - 0xfb, 0x66, 0x75, 0x99, 0x26, 0x4c, 0xba, 0x12, 0xc4, 0xc6, 0xac, 0x81, - 0xab, 0x89, 0x9d, 0xab, 0x16, 0x81, 0xda, 0x45, 0x1b, 0x3b, 0xcb, 0xdc, - 0xac, 0x2a, 0x8a, 0x3f, 0x22, 0x76, 0x66, 0xaf, 0xcb, 0x50, 0x5b, 0x6c, - 0x62, 0x8c, 0x2a, 0x38, 0x1a, 0xf5, 0xa1, 0x67, 0x8a, 0xb8, 0xc7, 0x9a, - 0x9b, 0x99, 0x23, 0x3f, 0xd6, 0xfb, 0x71, 0x6c, 0xc1, 0x9e, 0x9b, 0x75, - 0x12, 0xbf, 0xb9, 0xa2, 0x41, 0x94, 0x2f, 0xba, 0xf0, 0x1c, 0xf1, 0xf3, - 0x36, 0xda, 0xf9, 0x0c, 0xf1, 0xf3, 0x9e, 0x1b, 0x66, 0x67, 0xb3, 0x8b, - 0x78, 0x95, 0x58, 0xbe, 0xae, 0x16, 0x51, 0x99, 0x8b, 0x98, 0x57, 0x36, - 0xfa, 0x70, 0xce, 0xc2, 0xcf, 0xde, 0xe5, 0xb4, 0x62, 0xcb, 0x56, 0x46, - 0x5b, 0x88, 0x5d, 0x1d, 0xb4, 0x6b, 0xdb, 0x49, 0xb5, 0xeb, 0x25, 0xea, - 0xa2, 0x31, 0x7a, 0xde, 0xb2, 0xc7, 0x60, 0x5c, 0x66, 0x2c, 0x43, 0xad, - 0x72, 0xfe, 0xaa, 0x82, 0xf6, 0xee, 0x9e, 0x8c, 0x24, 0x3f, 0x80, 0x1d, - 0x93, 0xb1, 0x5c, 0x59, 0xb1, 0x1e, 0xca, 0xbd, 0x09, 0xde, 0x4b, 0xa2, - 0x6b, 0xa3, 0xed, 0xdf, 0xb1, 0xdc, 0x71, 0x62, 0x57, 0xd9, 0x5b, 0x0d, - 0xf8, 0x3b, 0x8d, 0x2e, 0x4c, 0x1b, 0x61, 0x94, 0x9f, 0x2b, 0xee, 0xd1, - 0x9e, 0x93, 0x33, 0x7b, 0x8f, 0xb6, 0x06, 0xbe, 0x53, 0xc2, 0x84, 0x49, - 0xe2, 0xbb, 0xa0, 0xe7, 0x8e, 0xbc, 0xe0, 0xc5, 0x5e, 0x1c, 0x33, 0xd4, - 0xd0, 0x4f, 0x18, 0x13, 0xf7, 0xc9, 0xfe, 0xfc, 0x0d, 0x33, 0xaa, 0x87, - 0x79, 0xcf, 0xf8, 0xdc, 0x8c, 0x2a, 0x95, 0xc5, 0xaf, 0x9c, 0xcd, 0xe5, - 0x70, 0xac, 0x93, 0x19, 0x89, 0x1a, 0x1a, 0xc3, 0x63, 0xc4, 0x1c, 0xbf, - 0x54, 0x7c, 0x9a, 0x6b, 0xa8, 0xc9, 0xa9, 0x86, 0xe6, 0x15, 0x1f, 0xdf, - 0xbd, 0x87, 0xf9, 0xed, 0x1e, 0xfa, 0x46, 0x64, 0xb9, 0x42, 0x71, 0xe2, - 0xd2, 0x97, 0x2d, 0x3c, 0xea, 0xed, 0xe5, 0xb5, 0xe9, 0x7c, 0x09, 0xd7, - 0xf4, 0x09, 0xaf, 0xe8, 0x9c, 0xb2, 0x73, 0x88, 0x96, 0xf3, 0x2e, 0x5f, - 0x82, 0x2d, 0x5b, 0x25, 0x65, 0x7d, 0x60, 0x32, 0x60, 0x0e, 0xac, 0x94, - 0x18, 0xd6, 0xb0, 0xd3, 0x10, 0xff, 0x1a, 0x24, 0x9f, 0x7d, 0x38, 0x62, - 0xac, 0x66, 0xef, 0x26, 0xf3, 0xd2, 0x26, 0x62, 0xeb, 0x5e, 0xd6, 0x60, - 0xd3, 0x4c, 0xe9, 0x69, 0xb3, 0x69, 0x93, 0xa6, 0xe7, 0x94, 0x42, 0x4d, - 0x88, 0xf8, 0x66, 0x3d, 0x6b, 0x77, 0x5b, 0xbe, 0x09, 0x6f, 0x9e, 0xd1, - 0xe8, 0x9b, 0xed, 0xc4, 0xef, 0xbd, 0xb8, 0x97, 0xf2, 0x7c, 0x23, 0xff, - 0x4d, 0x24, 0xbf, 0xee, 0xc2, 0xc4, 0x54, 0x12, 0x5b, 0xd6, 0x8f, 0xe0, - 0xd2, 0xef, 0x78, 0x98, 0xab, 0x7c, 0x78, 0x72, 0x4a, 0xf2, 0x6b, 0x09, - 0x6f, 0xdf, 0x88, 0x45, 0x3c, 0x08, 0x5b, 0x38, 0xe4, 0x8b, 0xef, 0xd9, - 0x18, 0xc5, 0xcb, 0x5e, 0xb8, 0xf4, 0x3e, 0xf3, 0xd0, 0xfa, 0x7f, 0x81, - 0x67, 0x88, 0x5b, 0x88, 0x05, 0x2a, 0x62, 0xd6, 0xf9, 0xb8, 0x12, 0xde, - 0x75, 0xd1, 0x07, 0x24, 0xa6, 0x57, 0x33, 0xd6, 0x4d, 0x62, 0xe7, 0xe5, - 0xe2, 0xfc, 0xf2, 0xed, 0x93, 0xea, 0xd2, 0x11, 0x44, 0x88, 0xa1, 0x31, - 0x28, 0xd8, 0xcd, 0x49, 0xbc, 0x7b, 0x25, 0x1a, 0xd5, 0xcf, 0x11, 0xef, - 0x8e, 0xd2, 0xd6, 0x2e, 0x4d, 0x7c, 0x33, 0x80, 0xb2, 0xc5, 0x10, 0x7d, - 0x52, 0xe6, 0x97, 0x7f, 0xe5, 0xb5, 0xe7, 0x97, 0x32, 0x33, 0x97, 0xf3, - 0x23, 0xe8, 0x28, 0x63, 0xef, 0x56, 0xae, 0xa4, 0x99, 0x93, 0x67, 0xbd, - 0xbb, 0x99, 0xdf, 0xfb, 0x8d, 0xa0, 0x7f, 0x77, 0x3e, 0xc0, 0xdf, 0x3a, - 0x7f, 0x7f, 0x7e, 0x07, 0x9f, 0x0f, 0xf1, 0x33, 0x8c, 0x6c, 0x2e, 0x52, - 0x21, 0xcd, 0x40, 0x36, 0x67, 0xe7, 0xbc, 0x70, 0xee, 0x90, 0x57, 0xb0, - 0x66, 0xdb, 0x94, 0xfd, 0x5d, 0xbb, 0xe1, 0xfb, 0xe7, 0x31, 0xbf, 0x9b, - 0x7c, 0x9f, 0x39, 0xa9, 0xe1, 0xa3, 0x93, 0x16, 0xe6, 0x2f, 0x10, 0xf3, - 0x0f, 0xbb, 0x9d, 0x82, 0x35, 0x7f, 0x61, 0x9e, 0x8f, 0x46, 0x07, 0xe6, - 0xe8, 0x07, 0x3d, 0xa4, 0xeb, 0xd0, 0x82, 0x16, 0xbf, 0x36, 0x9f, 0xf6, - 0xcc, 0xf7, 0xf2, 0xc9, 0x18, 0xde, 0xb9, 0x3e, 0x63, 0xfd, 0xa4, 0xcc, - 0x9a, 0x15, 0xe3, 0xb1, 0x77, 0x37, 0xc1, 0xd3, 0xc2, 0x7e, 0xd3, 0xcd, - 0xe7, 0x43, 0xd6, 0xf3, 0x32, 0xf3, 0xbd, 0x8e, 0x9d, 0x3f, 0xba, 0xfe, - 0xce, 0x61, 0x76, 0x6a, 0x9e, 0xf3, 0x8c, 0x2d, 0xa7, 0xf5, 0x9c, 0xcc, - 0x65, 0xbd, 0xcb, 0xb0, 0xe2, 0x6b, 0x88, 0x32, 0x89, 0x7d, 0x0f, 0x99, - 0xb6, 0xdf, 0x06, 0xfd, 0x3b, 0x19, 0x0f, 0xdf, 0xa6, 0x7d, 0x76, 0x9e, - 0xab, 0xf3, 0xdf, 0x6d, 0xec, 0xb2, 0x64, 0xbe, 0xfb, 0x9c, 0xd4, 0x24, - 0xb9, 0xff, 0x40, 0x85, 0x60, 0xef, 0x27, 0x59, 0xb3, 0x46, 0x0d, 0xd9, - 0x03, 0x80, 0xe2, 0x4a, 0x1c, 0x41, 0xe7, 0x74, 0x18, 0x6f, 0xeb, 0xde, - 0xe2, 0x59, 0x17, 0x89, 0xc9, 0x69, 0xc6, 0x64, 0x10, 0x63, 0x46, 0x24, - 0xfc, 0x36, 0xf1, 0x69, 0x9a, 0x0c, 0x1f, 0xcb, 0x3a, 0xf1, 0x36, 0x31, - 0x23, 0x14, 0xfb, 0xac, 0xa8, 0xfd, 0x6e, 0xe9, 0xef, 0x4a, 0x84, 0x6b, - 0x22, 0x2d, 0x07, 0x50, 0x87, 0x0c, 0x73, 0xbe, 0x57, 0xfb, 0x21, 0x8e, - 0x9f, 0x70, 0xe0, 0x7e, 0xf6, 0x7d, 0xc9, 0xbb, 0x74, 0x7e, 0x6f, 0x1c, - 0x7a, 0x1f, 0xff, 0x68, 0xce, 0xca, 0x79, 0x2c, 0x45, 0xce, 0x7c, 0x7c, - 0x62, 0xd6, 0x6a, 0x5a, 0xe1, 0x07, 0xd0, 0x52, 0x57, 0xd1, 0x38, 0xbc, - 0x8c, 0x0f, 0xcc, 0x02, 0xef, 0xbd, 0xc7, 0xf8, 0x79, 0x49, 0x8f, 0x84, - 0x1c, 0x14, 0xa6, 0x10, 0x74, 0xe2, 0x3e, 0x5d, 0xe6, 0x29, 0xea, 0xf0, - 0xb3, 0x50, 0x87, 0x2e, 0x28, 0x72, 0x86, 0xe7, 0x92, 0x99, 0xae, 0x91, - 0x75, 0x15, 0xac, 0x5b, 0xd3, 0xd8, 0x55, 0x06, 0xb5, 0xc5, 0xad, 0x68, - 0xfa, 0xfb, 0xca, 0xff, 0x32, 0x0b, 0xc1, 0x4f, 0xcc, 0x77, 0xb4, 0x12, - 0x5d, 0x35, 0xec, 0x71, 0x96, 0x78, 0xab, 0xc3, 0x71, 0x43, 0xf6, 0xf1, - 0x7e, 0x88, 0xfb, 0x4f, 0xb8, 0xd0, 0x1e, 0xff, 0xb9, 0x99, 0x0e, 0x0a, - 0xcd, 0x50, 0x25, 0x2a, 0x84, 0xbe, 0x3d, 0xdb, 0x7e, 0x31, 0x0f, 0xa5, - 0xc3, 0x10, 0xbc, 0x2c, 0x7e, 0x3a, 0x0d, 0xd3, 0x90, 0x99, 0xa2, 0x89, - 0x3b, 0xe3, 0x23, 0x78, 0x2f, 0x9e, 0xfc, 0x4f, 0x1e, 0xa8, 0x4b, 0x97, - 0x9d, 0x6a, 0xa1, 0xc9, 0x19, 0x56, 0xbc, 0x0d, 0xda, 0x70, 0x83, 0x55, - 0x6f, 0x2e, 0xb2, 0x77, 0xf2, 0x31, 0xb7, 0x48, 0x8f, 0x39, 0x8d, 0xc5, - 0xc9, 0x34, 0x5c, 0xc4, 0x76, 0xa3, 0xcd, 0x6a, 0xff, 0x33, 0x8a, 0x1a, - 0x3a, 0xa8, 0x84, 0x95, 0x7b, 0xb5, 0x14, 0x9e, 0xd3, 0xa3, 0xc9, 0x36, - 0xa5, 0xce, 0xd3, 0x95, 0x2f, 0xd1, 0x6e, 0x27, 0x56, 0x51, 0x0b, 0x97, - 0x9d, 0xe5, 0xa8, 0xdd, 0xa0, 0x75, 0x95, 0x3b, 0xd5, 0xd4, 0xd7, 0x18, - 0x5f, 0xdb, 0xf3, 0x05, 0xef, 0xfb, 0x51, 0x07, 0xd6, 0x5a, 0xfb, 0x0d, - 0x99, 0xe2, 0xbc, 0x74, 0x1a, 0xdd, 0x93, 0xe6, 0x96, 0x8b, 0x71, 0x35, - 0xf4, 0x8c, 0x92, 0xde, 0xed, 0x23, 0xa6, 0x79, 0x00, 0x5a, 0x78, 0x81, - 0x75, 0xaa, 0x3d, 0xef, 0xc0, 0x2d, 0xa7, 0x84, 0x66, 0x86, 0x34, 0x8f, - 0xa0, 0xfc, 0x84, 0xb9, 0x65, 0xb7, 0xae, 0xa6, 0x2e, 0x3b, 0xd3, 0xff, - 0xbd, 0x96, 0x7a, 0xeb, 0x50, 0x64, 0xbf, 0x6d, 0x84, 0xb8, 0x62, 0x44, - 0xce, 0xcd, 0xc5, 0xfe, 0x98, 0x98, 0xe2, 0x5b, 0xf4, 0x55, 0x67, 0xc2, - 0x4f, 0x3e, 0xd5, 0xd8, 0x1c, 0x64, 0xce, 0x1e, 0xc6, 0x65, 0x3d, 0xed, - 0xed, 0x6c, 0x88, 0x11, 0x9b, 0x85, 0x58, 0x07, 0xc3, 0x38, 0x46, 0x8c, - 0x77, 0x24, 0x5f, 0x86, 0x42, 0x40, 0x23, 0x36, 0xeb, 0x85, 0x63, 0xd2, - 0xa7, 0xcc, 0x67, 0x22, 0x7a, 0x3b, 0xfe, 0x33, 0x0a, 0x21, 0x71, 0x91, - 0x23, 0xf0, 0x9d, 0xf8, 0x7b, 0xb3, 0x4a, 0xd3, 0x5a, 0x26, 0x15, 0xae, - 0xfb, 0x54, 0x88, 0x3a, 0xe6, 0x7b, 0x72, 0xbe, 0xc5, 0xe8, 0xc1, 0xbd, - 0x93, 0x41, 0xbe, 0x5f, 0x85, 0x75, 0x27, 0xc2, 0xb8, 0x12, 0xbf, 0x19, - 0x85, 0x1a, 0x1b, 0x03, 0x79, 0x35, 0xfa, 0x11, 0xfb, 0xac, 0x34, 0x7b, - 0x4a, 0xd9, 0x63, 0x3a, 0x62, 0x48, 0x7f, 0xee, 0xe2, 0x77, 0x1f, 0x7f, - 0x45, 0x9f, 0xdf, 0x2a, 0x62, 0x9d, 0xa9, 0xd6, 0xf0, 0xfc, 0xcf, 0x2b, - 0xec, 0x79, 0x5a, 0x98, 0xcf, 0x05, 0xac, 0x19, 0xe1, 0x28, 0x69, 0x9e, - 0x9d, 0x96, 0xbe, 0xad, 0x6d, 0xb3, 0xa7, 0xb8, 0x4f, 0xff, 0x53, 0xdd, - 0x81, 0x2d, 0xec, 0xed, 0x43, 0x9a, 0xd4, 0xcb, 0x51, 0xb5, 0x16, 0x9b, - 0x71, 0x3a, 0xc0, 0x26, 0x5c, 0xfb, 0x0f, 0x98, 0x08, 0xc4, 0x98, 0xf3, - 0x35, 0xbc, 0x9b, 0xf9, 0x32, 0xfb, 0x9d, 0x3a, 0x39, 0xe3, 0x83, 0x5b, - 0x4e, 0xb8, 0xb9, 0xe6, 0x16, 0xe2, 0x9a, 0x4e, 0xbc, 0x16, 0xb0, 0x7b, - 0x8d, 0xa3, 0xbc, 0x3e, 0x3e, 0xe7, 0x23, 0x16, 0xf5, 0xf0, 0xf7, 0x46, - 0xde, 0xbe, 0x88, 0x27, 0x91, 0xe5, 0xdf, 0xe2, 0xc9, 0x43, 0x3c, 0xa0, - 0xe1, 0x6a, 0xe6, 0x65, 0x5c, 0x21, 0xed, 0xf4, 0x9c, 0x4d, 0x73, 0x2a, - 0x2f, 0x74, 0x65, 0xbd, 0x48, 0xaa, 0xd6, 0x29, 0xf4, 0x7d, 0x72, 0xde, - 0xf7, 0xdf, 0xb9, 0x06, 0x91, 0xdd, 0x09, 0xf6, 0xc7, 0x7a, 0x03, 0xda, - 0x03, 0xb4, 0x97, 0x21, 0x6b, 0xa8, 0xec, 0x45, 0xe5, 0xdd, 0x10, 0xd6, - 0x4e, 0x9a, 0x23, 0xa1, 0x84, 0x5c, 0x37, 0xcd, 0xea, 0x4d, 0x5a, 0xe8, - 0x4d, 0xc5, 0xc5, 0x5a, 0xe7, 0xa2, 0x0e, 0xc6, 0x71, 0x36, 0xd3, 0xb8, - 0xf4, 0x1e, 0xb1, 0x53, 0x98, 0xbd, 0xde, 0x25, 0xe7, 0x38, 0xe6, 0x33, - 0x0b, 0x95, 0x32, 0x23, 0x18, 0xcf, 0xfb, 0x94, 0xb9, 0xcc, 0x91, 0x4a, - 0xc9, 0x45, 0x63, 0xf4, 0x85, 0xa6, 0x49, 0xe1, 0xd5, 0x1c, 0xa9, 0x22, - 0x9d, 0x63, 0xa4, 0x33, 0xb7, 0x51, 0xeb, 0x1f, 0x53, 0x44, 0x67, 0x3e, - 0xe2, 0xba, 0x8b, 0x32, 0x3f, 0xa3, 0xde, 0xfe, 0x94, 0xcf, 0x8b, 0xde, - 0x82, 0x78, 0xad, 0x48, 0xe7, 0x89, 0xfc, 0x12, 0xe6, 0x32, 0x1f, 0x58, - 0x7f, 0x8f, 0xe5, 0x63, 0xac, 0x7d, 0x83, 0xc8, 0x31, 0x9f, 0x4c, 0x66, - 0x1a, 0xfb, 0x27, 0xc9, 0x87, 0x7d, 0x36, 0x6f, 0x10, 0x4f, 0x17, 0x9f, - 0x19, 0xe5, 0xbb, 0xa3, 0xd7, 0xfe, 0x16, 0x1d, 0xd9, 0xfb, 0xff, 0xf6, - 0x1e, 0x43, 0x39, 0x6d, 0x67, 0xf7, 0xe1, 0x47, 0x0d, 0xb7, 0xcc, 0xc3, - 0xf1, 0xf2, 0xf4, 0x16, 0x8c, 0xe9, 0x7f, 0x8e, 0xbd, 0x94, 0x7b, 0x9c, - 0xfa, 0x3c, 0x61, 0x58, 0xfb, 0xfc, 0x72, 0xfe, 0x8b, 0xb9, 0xfa, 0x60, - 0xeb, 0x19, 0x62, 0xb1, 0xe3, 0x8c, 0x99, 0xfd, 0xf1, 0xc6, 0xde, 0x57, - 0xe8, 0x77, 0xc9, 0xdf, 0x96, 0xbd, 0x74, 0x60, 0x32, 0xfb, 0x0d, 0xcc, - 0xd6, 0x34, 0x2e, 0x3f, 0xcf, 0x9c, 0x70, 0x9a, 0x79, 0xca, 0xc5, 0x9c, - 0x50, 0x9d, 0x25, 0x86, 0x64, 0x9e, 0x2a, 0x30, 0x4f, 0xb9, 0xb4, 0xc6, - 0xa5, 0x79, 0xfc, 0x15, 0xf5, 0x22, 0xfc, 0x45, 0x62, 0xf3, 0x90, 0x67, - 0xed, 0xf9, 0xab, 0x36, 0x3f, 0x84, 0x4b, 0x37, 0xdb, 0x33, 0x34, 0x27, - 0x6b, 0xf6, 0xbe, 0x4c, 0x63, 0x60, 0x4c, 0x68, 0xf7, 0xa9, 0xa1, 0x34, - 0x6d, 0x35, 0x61, 0x61, 0xef, 0x61, 0xf6, 0x0b, 0x72, 0xde, 0xab, 0x0a, - 0x2e, 0xfa, 0xfe, 0x98, 0x2e, 0xe7, 0x20, 0x42, 0xfe, 0xed, 0xb4, 0xe1, - 0x98, 0xd1, 0xd8, 0x12, 0x51, 0x76, 0xe3, 0x52, 0x31, 0xc7, 0xda, 0x58, - 0x5a, 0xed, 0x3f, 0x86, 0xc6, 0xde, 0x07, 0xf0, 0x75, 0x24, 0x6b, 0x1a, - 0x07, 0xa6, 0x11, 0xd1, 0xef, 0x83, 0x9c, 0x1b, 0xb5, 0x69, 0xd5, 0xe7, - 0x9c, 0xc4, 0x23, 0x9f, 0x98, 0xab, 0xb5, 0x27, 0x30, 0x4d, 0xcc, 0xd8, - 0xb0, 0x5e, 0x5b, 0xfa, 0x6e, 0xf1, 0x9e, 0xbd, 0xa7, 0x24, 0xfe, 0xe2, - 0xa1, 0x0e, 0xca, 0xe1, 0x5a, 0x51, 0xc7, 0x35, 0xa8, 0x0b, 0xeb, 0x4c, - 0xf1, 0x45, 0x1c, 0xa2, 0xbf, 0x4d, 0xe7, 0x15, 0xe8, 0xf5, 0x17, 0x31, - 0x2c, 0xb5, 0x89, 0xef, 0xb4, 0x65, 0x7c, 0xc4, 0x29, 0x21, 0x94, 0x6b, - 0x91, 0xf0, 0x28, 0xe5, 0x6b, 0x63, 0x2e, 0x1f, 0x67, 0x0e, 0x49, 0x07, - 0x7c, 0xd6, 0x39, 0xd7, 0x72, 0x2d, 0x64, 0xfd, 0x6f, 0x82, 0xf4, 0x41, - 0x0d, 0xb3, 0xb2, 0x9f, 0x7d, 0x04, 0x17, 0xa7, 0x0b, 0x38, 0x1e, 0x4f, - 0xe2, 0x40, 0x4d, 0x00, 0x93, 0xc6, 0x4a, 0x6b, 0x6e, 0x20, 0xfd, 0x56, - 0x77, 0xf6, 0xb0, 0x35, 0x8b, 0xdc, 0x16, 0x77, 0xd4, 0xcb, 0x79, 0x8f, - 0x39, 0xf6, 0x5d, 0xd3, 0xfa, 0x08, 0x0e, 0xe9, 0xdf, 0x82, 0xbe, 0x42, - 0x72, 0xe7, 0x18, 0xce, 0xcf, 0x4a, 0x0d, 0x9b, 0x68, 0xbd, 0x75, 0x52, - 0xf4, 0xe3, 0x20, 0xe6, 0xf5, 0xa0, 0xc9, 0xc2, 0x70, 0xaf, 0xb7, 0xae, - 0x99, 0xb5, 0xb1, 0x5c, 0x53, 0x4e, 0xce, 0x66, 0x57, 0xc1, 0x4f, 0x7d, - 0x5d, 0x88, 0xbb, 0x99, 0x73, 0x44, 0x9f, 0x72, 0x16, 0xd0, 0x96, 0x33, - 0x96, 0x53, 0x30, 0xd6, 0x7c, 0xe3, 0x5e, 0x8b, 0xfc, 0x9f, 0xc2, 0xb5, - 0xf3, 0x89, 0xc5, 0xd9, 0xf8, 0x1f, 0x9b, 0x97, 0x6e, 0x12, 0xb9, 0x5b, - 0x7d, 0xcc, 0xe9, 0xe1, 0xd9, 0x6b, 0xfa, 0x15, 0x9d, 0x9e, 0x93, 0x9a, - 0x61, 0xe9, 0xdc, 0x9e, 0xb7, 0xa9, 0xc3, 0xef, 0x28, 0x8d, 0xac, 0x27, - 0xf4, 0xab, 0x1a, 0xfa, 0x5b, 0x13, 0x06, 0x56, 0x27, 0x5c, 0x7d, 0x57, - 0x8d, 0x2d, 0x68, 0xd9, 0xf0, 0xae, 0x89, 0x9b, 0xdb, 0xe0, 0xd4, 0xe4, - 0xfa, 0xac, 0x99, 0x0c, 0xc8, 0xdf, 0x4f, 0xfa, 0xa4, 0x96, 0xbf, 0x68, - 0x14, 0xcc, 0x35, 0x2b, 0x6d, 0x6c, 0xf8, 0xf7, 0x19, 0xd9, 0x07, 0x4b, - 0x9b, 0xec, 0xb5, 0x97, 0xde, 0x76, 0x1e, 0xc6, 0xdf, 0xe6, 0x8e, 0xe0, - 0xad, 0x69, 0x17, 0x71, 0xa6, 0xc8, 0xb2, 0x05, 0xd5, 0x1b, 0xa2, 0xc9, - 0x77, 0x99, 0x17, 0x97, 0x66, 0x4b, 0x7e, 0xf1, 0x7a, 0xeb, 0xda, 0x59, - 0x85, 0xb4, 0xaa, 0x50, 0x46, 0x39, 0x7f, 0xac, 0x3b, 0x11, 0x2e, 0x62, - 0x5b, 0x27, 0xf9, 0xdc, 0x97, 0xb1, 0x31, 0x6f, 0x24, 0x37, 0xed, 0xb3, - 0xe7, 0x5f, 0x3e, 0xe6, 0xd1, 0x71, 0x4c, 0x64, 0x1a, 0x63, 0xef, 0xc9, - 0x79, 0x1e, 0xf6, 0x62, 0x97, 0x30, 0x8e, 0x13, 0x99, 0x52, 0x0e, 0x0d, - 0xc9, 0x39, 0xd8, 0x58, 0xd8, 0x61, 0xe7, 0xc8, 0xb0, 0x43, 0x4d, 0xf3, - 0xd7, 0x27, 0xd8, 0x60, 0x34, 0x1f, 0x09, 0x95, 0xc3, 0x89, 0xfd, 0xba, - 0xed, 0x1f, 0xf5, 0xf3, 0x6e, 0x84, 0x57, 0x48, 0x5d, 0x96, 0x9a, 0xec, - 0x62, 0x4d, 0x5e, 0x89, 0xe4, 0x4a, 0x17, 0x5e, 0xd7, 0x44, 0x1f, 0x53, - 0x25, 0x7d, 0xe8, 0xe7, 0xf0, 0x90, 0x59, 0xe8, 0x15, 0x5f, 0x72, 0xe3, - 0x48, 0xd3, 0x9c, 0x39, 0x1b, 0x14, 0xd9, 0x9d, 0x38, 0xcd, 0xfc, 0x8a, - 0x9b, 0x23, 0xa1, 0xd3, 0xac, 0xd9, 0x63, 0x5a, 0xc9, 0xc7, 0xff, 0x63, - 0x91, 0x4f, 0xad, 0x7f, 0x01, 0x47, 0xf8, 0x77, 0x7d, 0xe8, 0x80, 0x62, - 0xaf, 0xb7, 0x66, 0xfe, 0x43, 0x5f, 0x69, 0x76, 0x2a, 0xcf, 0x86, 0x73, - 0xa7, 0xf9, 0x5d, 0x68, 0xf9, 0xe8, 0x9f, 0xe5, 0x18, 0x08, 0xca, 0x79, - 0x10, 0xd1, 0x8b, 0xec, 0x3f, 0x82, 0xfa, 0x30, 0xf1, 0x32, 0xf5, 0x71, - 0xe4, 0xda, 0xd9, 0x2b, 0x3b, 0x7f, 0x55, 0xf0, 0xfa, 0xf6, 0xf8, 0x4b, - 0x9b, 0xbd, 0xf8, 0x95, 0x79, 0x29, 0x18, 0x62, 0x4e, 0x10, 0x9b, 0xa6, - 0x2c, 0x1c, 0xe9, 0x24, 0x3e, 0xd9, 0x67, 0x9f, 0x33, 0x69, 0x95, 0xff, - 0xa1, 0x29, 0xca, 0x51, 0x18, 0x24, 0xce, 0x5e, 0xcc, 0x58, 0x67, 0xfb, - 0x06, 0xde, 0x54, 0x22, 0xcc, 0x35, 0x5f, 0xc2, 0x40, 0xad, 0xd0, 0x0b, - 0xf8, 0x77, 0xce, 0xc4, 0xa8, 0x83, 0x3a, 0xa1, 0x6b, 0x3e, 0xc3, 0x6e, - 0xee, 0xc8, 0xa4, 0xd0, 0x07, 0xc6, 0x26, 0x23, 0x43, 0x3f, 0x06, 0x36, - 0x57, 0x41, 0x4d, 0x2d, 0x14, 0xff, 0xdf, 0xe3, 0x67, 0x8a, 0xd0, 0x12, - 0x3a, 0x2e, 0x18, 0xcc, 0x71, 0x53, 0x8b, 0x15, 0xd4, 0x9d, 0xda, 0xfb, - 0x3d, 0xa5, 0x02, 0x4f, 0x3c, 0x15, 0x23, 0xef, 0x2b, 0xfc, 0xdb, 0x67, - 0x3c, 0xf0, 0x9e, 0xa9, 0x62, 0xcd, 0xf5, 0xe0, 0x72, 0x33, 0xed, 0xfa, - 0x54, 0x89, 0x77, 0x6b, 0x9f, 0x14, 0x8f, 0x67, 0xc3, 0x30, 0xe8, 0xb3, - 0x8b, 0x86, 0xec, 0x17, 0x7b, 0xac, 0xfc, 0xb9, 0xb4, 0xb1, 0xce, 0xda, - 0xaf, 0x7a, 0x3e, 0xaf, 0x85, 0xce, 0x2a, 0x55, 0xf8, 0xe0, 0x44, 0xe1, - 0xe6, 0x72, 0x98, 0x2f, 0xae, 0x4e, 0x44, 0xfb, 0xf7, 0xd2, 0xe7, 0xd7, - 0xae, 0x09, 0xb2, 0x97, 0x61, 0x4f, 0xb9, 0x49, 0xfa, 0xdf, 0x69, 0xf6, - 0xbf, 0xa5, 0xbd, 0x7f, 0x6d, 0xe8, 0x11, 0x25, 0xdd, 0xe9, 0x87, 0xf9, - 0x51, 0x79, 0xc2, 0xfc, 0xd8, 0x9d, 0x88, 0xf2, 0x7d, 0xd9, 0xdf, 0x33, - 0xcd, 0x9f, 0x36, 0x9b, 0x66, 0xae, 0x39, 0xd2, 0x1f, 0x70, 0x06, 0x70, - 0xa6, 0x41, 0xf6, 0x04, 0x1d, 0xf8, 0x20, 0xaa, 0x85, 0xf6, 0x42, 0xf6, - 0xe8, 0x99, 0xe3, 0x57, 0xca, 0xf9, 0xc4, 0x3a, 0x7f, 0x97, 0xb1, 0x02, - 0xcf, 0x2d, 0x6c, 0xc2, 0x80, 0x1b, 0xd6, 0xf9, 0x19, 0x53, 0xc7, 0x9b, - 0xab, 0x21, 0x75, 0x3b, 0xda, 0xf2, 0x08, 0x82, 0x58, 0xc8, 0x1f, 0xc1, - 0xc3, 0x27, 0x64, 0xaf, 0x71, 0xb2, 0xd5, 0x73, 0xc2, 0xfc, 0xfb, 0x50, - 0xa2, 0xc0, 0xbc, 0x68, 0x9a, 0x15, 0x9b, 0x1a, 0x43, 0x2c, 0x47, 0xc4, - 0x18, 0x69, 0xc1, 0xee, 0x43, 0x1f, 0xa0, 0x06, 0x67, 0xe7, 0x92, 0x37, - 0xb3, 0x97, 0xec, 0x7a, 0x5a, 0x09, 0xe0, 0x07, 0x94, 0xf1, 0xd9, 0xbc, - 0xe0, 0x14, 0xa3, 0xb5, 0xfb, 0xc4, 0x2a, 0xbc, 0xb8, 0x10, 0xc4, 0x59, - 0x43, 0x23, 0x4e, 0x82, 0x52, 0x99, 0x30, 0xab, 0xab, 0xc9, 0x6b, 0xa5, - 0xd3, 0x89, 0xce, 0xb8, 0xf4, 0x87, 0xda, 0x90, 0x4f, 0xc1, 0xaa, 0x72, - 0x68, 0xcb, 0x0f, 0x01, 0xc3, 0x5e, 0xf6, 0xab, 0x4f, 0x2b, 0xd1, 0xfe, - 0xf7, 0x9d, 0x41, 0xfc, 0x80, 0xf9, 0xe7, 0x7b, 0x79, 0x39, 0x5b, 0xc5, - 0x1c, 0x33, 0x17, 0xa6, 0xad, 0x3c, 0x70, 0xd4, 0x57, 0xe1, 0x28, 0xe3, - 0xe5, 0x65, 0xbd, 0x8c, 0x39, 0x4a, 0xce, 0x5a, 0x49, 0x7e, 0x7f, 0x54, - 0xce, 0x94, 0x98, 0xcf, 0x6b, 0x76, 0xbf, 0xaf, 0xcf, 0xdf, 0x78, 0x5e, - 0x39, 0xc0, 0xbc, 0xde, 0xd8, 0x1b, 0x52, 0x5e, 0x35, 0x93, 0xbf, 0xad, - 0x50, 0xce, 0x07, 0xab, 0x50, 0x61, 0xc9, 0x8a, 0xd1, 0x6c, 0xa9, 0xa6, - 0x54, 0x4b, 0x2f, 0xd7, 0x9b, 0x2e, 0xfa, 0x60, 0x25, 0x63, 0xfd, 0x18, - 0x6b, 0x74, 0xf9, 0x09, 0xa9, 0x25, 0xec, 0x5f, 0x94, 0x2d, 0xc4, 0xc2, - 0x82, 0x1b, 0x3c, 0x78, 0x20, 0xa0, 0xb6, 0xc8, 0x99, 0xed, 0x67, 0xf3, - 0x1d, 0x2e, 0x39, 0x3b, 0xf5, 0x5c, 0x5e, 0x6a, 0xb9, 0xe4, 0x82, 0xd2, - 0x7a, 0x21, 0xd4, 0x4e, 0x8a, 0x8d, 0x86, 0x5b, 0x3f, 0x9a, 0xf4, 0xc9, - 0xf9, 0xfa, 0x11, 0x07, 0x7b, 0x6d, 0xcf, 0xa4, 0x69, 0xee, 0x69, 0xd6, - 0x86, 0xb6, 0x38, 0x65, 0x6f, 0x39, 0x32, 0x70, 0x4e, 0x51, 0x5b, 0x26, - 0x94, 0x1b, 0xe9, 0xfc, 0xb7, 0x2a, 0x89, 0x91, 0x34, 0xe5, 0x7c, 0xdc, - 0x92, 0x69, 0x8a, 0x32, 0x95, 0xce, 0x16, 0x55, 0xe1, 0xf2, 0x34, 0x34, - 0x46, 0x2d, 0xce, 0xeb, 0x4c, 0x4e, 0x81, 0x68, 0xb2, 0x1d, 0xe2, 0xff, - 0xea, 0x80, 0x60, 0xa8, 0x4a, 0xe6, 0xe4, 0xb9, 0x69, 0xa9, 0x31, 0x8a, - 0xe0, 0x93, 0x34, 0xd7, 0xc6, 0x95, 0x8d, 0xc0, 0xab, 0x93, 0xf6, 0xde, - 0x7b, 0xf1, 0x2c, 0xb8, 0x75, 0xe6, 0xe1, 0x11, 0xeb, 0x2c, 0x83, 0xd0, - 0x3f, 0x8c, 0x33, 0x19, 0xc1, 0x94, 0xc3, 0xc4, 0x94, 0x91, 0x14, 0xf1, - 0x66, 0x4b, 0xde, 0x3e, 0x97, 0xa5, 0x7f, 0x44, 0x9f, 0x7f, 0x9a, 0x58, - 0xf5, 0x28, 0xec, 0xbd, 0xf7, 0x86, 0xe2, 0x59, 0x85, 0x48, 0xae, 0x4b, - 0xd9, 0x91, 0x97, 0x18, 0x9b, 0x66, 0x8c, 0xb5, 0x2b, 0xdb, 0x17, 0x3a, - 0x94, 0xee, 0x85, 0x1e, 0x65, 0x77, 0x5e, 0x7a, 0xd6, 0xc9, 0xd6, 0x07, - 0x4e, 0xec, 0x52, 0x76, 0xcc, 0xf5, 0x29, 0xc4, 0xb4, 0x01, 0x4f, 0xa2, - 0x5f, 0xe9, 0x59, 0xb0, 0xe7, 0xe7, 0x5d, 0xec, 0xbb, 0x76, 0x18, 0xa5, - 0x7e, 0x5e, 0xfe, 0xdf, 0x2b, 0x28, 0xff, 0x5b, 0x31, 0xb0, 0x4d, 0x31, - 0xcd, 0xdb, 0xe2, 0x7f, 0x27, 0xf6, 0x30, 0x9f, 0x8d, 0xb3, 0x36, 0x1a, - 0x55, 0x18, 0x64, 0xdf, 0x31, 0xaa, 0xdf, 0x5a, 0xdc, 0x2f, 0x13, 0x99, - 0xe4, 0x3c, 0x85, 0xf8, 0x2b, 0xd2, 0xe5, 0xe4, 0xe1, 0x1f, 0xc8, 0xff, - 0x81, 0xa2, 0x5c, 0x3d, 0x72, 0xa6, 0xc0, 0x7d, 0xfd, 0xbc, 0xd9, 0xf1, - 0xc9, 0xeb, 0x72, 0x31, 0xd7, 0x63, 0x9c, 0xf8, 0xf4, 0x80, 0xa2, 0xa6, - 0x9e, 0xb1, 0xe5, 0x5a, 0xba, 0xcc, 0x18, 0x1e, 0xb5, 0x62, 0xd8, 0x96, - 0x6b, 0x5d, 0x51, 0xae, 0xb5, 0xb9, 0x2e, 0xeb, 0x1c, 0x17, 0xf1, 0x7a, - 0xeb, 0xe2, 0xa4, 0x9c, 0x37, 0x93, 0xd9, 0xa5, 0xc8, 0x26, 0x72, 0x9c, - 0x30, 0x2b, 0xb4, 0x1e, 0x65, 0xa7, 0x75, 0xfe, 0x4c, 0xce, 0x7e, 0xc9, - 0x5e, 0x7f, 0x49, 0x2e, 0xa9, 0xe3, 0x2b, 0xfc, 0x1d, 0x33, 0x72, 0x1e, - 0xdb, 0x34, 0x5f, 0xd3, 0x83, 0x7e, 0x91, 0xe5, 0xac, 0x2e, 0xb2, 0xc8, - 0xb9, 0x92, 0x92, 0x3c, 0x5f, 0x2b, 0xca, 0x23, 0xb6, 0xba, 0x6e, 0xa7, - 0xd2, 0xff, 0x09, 0xbe, 0x9d, 0xb1, 0xcf, 0x9c, 0x94, 0xe4, 0xf1, 0x27, - 0x84, 0xff, 0x8b, 0xad, 0xe3, 0xd3, 0xc3, 0x78, 0x95, 0xf7, 0x7f, 0x9e, - 0x29, 0xc9, 0xe5, 0xc4, 0xfc, 0x5c, 0xe9, 0x2c, 0x1d, 0x5b, 0x4a, 0x23, - 0xa2, 0x8f, 0xd1, 0x8f, 0x6c, 0xf9, 0xe4, 0x2c, 0x5d, 0x63, 0xe1, 0xb2, - 0x35, 0xf7, 0x8a, 0x26, 0xd9, 0x2f, 0xe3, 0x6c, 0xfe, 0xd7, 0xed, 0xd7, - 0x94, 0xab, 0x60, 0x8f, 0x2c, 0xb4, 0x5f, 0x27, 0x6d, 0x39, 0x73, 0xa2, - 0xe0, 0x99, 0x39, 0x60, 0xce, 0xe0, 0xb2, 0x89, 0x11, 0x3c, 0xa9, 0x9b, - 0xe6, 0xd3, 0xcd, 0x9a, 0x9c, 0x15, 0xba, 0x50, 0x6b, 0xcd, 0x85, 0xa0, - 0x57, 0x69, 0xb2, 0x77, 0x27, 0xe7, 0x4d, 0xfa, 0xa8, 0x03, 0x91, 0x5d, - 0x7c, 0xa0, 0x64, 0x7b, 0x39, 0x07, 0x97, 0xa6, 0x7e, 0x44, 0x37, 0xa5, - 0xf3, 0x70, 0x32, 0x73, 0xb9, 0x51, 0x27, 0x5d, 0x96, 0x4e, 0x9e, 0xd5, - 0xc5, 0x5f, 0x99, 0x7d, 0xe8, 0xab, 0xf3, 0xc4, 0x0f, 0x63, 0xba, 0xdb, - 0xc2, 0x6a, 0x47, 0x89, 0x4f, 0x26, 0x18, 0x3b, 0x8f, 0x1b, 0x4b, 0x58, - 0xca, 0xbd, 0x8c, 0x57, 0xaf, 0xfd, 0xcf, 0x9c, 0xf8, 0x8b, 0xde, 0xd2, - 0x6d, 0x9d, 0x79, 0xfa, 0xa4, 0xe5, 0xd6, 0xa8, 0xe4, 0xa1, 0x1f, 0x36, - 0xc9, 0x19, 0xa8, 0xf2, 0x44, 0xe0, 0x6b, 0xb2, 0xbf, 0x55, 0x96, 0x98, - 0xfd, 0xea, 0x05, 0x4d, 0x74, 0xa3, 0x35, 0x9f, 0xd1, 0x44, 0xae, 0x1e, - 0x7d, 0xdc, 0xfa, 0x1f, 0xce, 0x96, 0x4d, 0xfb, 0x34, 0x89, 0x1d, 0xdf, - 0xc6, 0x36, 0x2b, 0x27, 0x9c, 0x4e, 0xdc, 0x66, 0xe9, 0xe0, 0x64, 0xe2, - 0x56, 0xeb, 0x73, 0x3a, 0x11, 0xb3, 0x3e, 0xff, 0x24, 0x61, 0xeb, 0x26, - 0x97, 0xa8, 0xb7, 0x3e, 0xe7, 0x13, 0xf6, 0xd9, 0xe9, 0xd9, 0x84, 0x66, - 0x7d, 0x3e, 0x9f, 0x88, 0x58, 0x9f, 0x67, 0x13, 0xb7, 0x5c, 0xe7, 0x8b, - 0x3f, 0xff, 0x0f, 0x4c, 0xd3, 0x85, 0x76, 0xdc, 0x3a, 0x00, 0x00, 0x00 }; + 0xad, 0x7b, 0x0d, 0x70, 0x94, 0xf7, 0x79, 0xe7, 0xef, 0xbf, 0x1f, 0xd2, + 0xae, 0xb4, 0x5a, 0xad, 0xf0, 0x82, 0x57, 0x89, 0x52, 0xf6, 0xf5, 0xbe, + 0x2b, 0x2d, 0x96, 0x80, 0x77, 0x41, 0x04, 0x11, 0x6d, 0xcd, 0x56, 0x08, + 0x21, 0x40, 0xd8, 0x32, 0x56, 0x92, 0x25, 0xc7, 0xd4, 0x2a, 0xc8, 0x20, + 0xdb, 0x18, 0x8b, 0x86, 0xe6, 0xe4, 0xd6, 0xad, 0xd6, 0x92, 0xc0, 0x60, + 0x56, 0xbc, 0x22, 0x82, 0x08, 0x77, 0xee, 0x26, 0xb2, 0x25, 0x2c, 0xec, + 0xac, 0x58, 0x3b, 0xbd, 0xeb, 0xc5, 0x33, 0xc9, 0x58, 0x67, 0x6c, 0x4c, + 0x72, 0xfe, 0xc8, 0x75, 0x3a, 0x3d, 0xf7, 0xe6, 0xee, 0xca, 0xf8, 0x83, + 0xd8, 0x6e, 0x8c, 0xdd, 0x4c, 0x3a, 0x27, 0x52, 0xdb, 0xef, 0xfd, 0x9e, + 0xf7, 0xdd, 0x05, 0xe2, 0xba, 0xd3, 0x99, 0xce, 0x69, 0x66, 0x67, 0xa5, + 0xf7, 0xe3, 0xf9, 0x3f, 0xdf, 0xcf, 0xef, 0x79, 0xfe, 0x7f, 0xd5, 0x03, + 0x15, 0x28, 0xfe, 0x54, 0xf1, 0xd3, 0x3c, 0x30, 0x78, 0x70, 0xd5, 0x8a, + 0xe6, 0x15, 0xf6, 0x05, 0x97, 0xc7, 0x23, 0x37, 0xbf, 0xaa, 0x80, 0xde, + 0x0f, 0xf0, 0x6f, 0xfa, 0xf9, 0xca, 0xbf, 0xed, 0x35, 0xfb, 0xc7, 0x0d, + 0x84, 0x4a, 0x7c, 0xc9, 0x07, 0x3e, 0x57, 0xea, 0xd2, 0xd7, 0xda, 0x74, + 0xf8, 0xdc, 0xa9, 0x93, 0xa9, 0xdd, 0x3a, 0x90, 0xce, 0x37, 0x46, 0x37, + 0xe0, 0x53, 0x2b, 0x1b, 0xf6, 0x40, 0xae, 0x7f, 0x25, 0xf5, 0xc9, 0xd0, + 0x4f, 0xd6, 0x6a, 0x1f, 0x4f, 0xb9, 0xe1, 0x0b, 0xa5, 0x4e, 0x23, 0x54, + 0x0f, 0x5f, 0x1d, 0xdf, 0xf9, 0x0f, 0x0d, 0xd5, 0x6e, 0x04, 0x4b, 0xb4, + 0x5a, 0x30, 0x62, 0x22, 0xeb, 0x4b, 0x0d, 0xa0, 0x7c, 0x0d, 0xf0, 0x6e, + 0x2e, 0x6e, 0x8c, 0x00, 0xe3, 0xae, 0x54, 0x3c, 0xfa, 0x22, 0x0c, 0x1c, + 0x2a, 0x44, 0xd1, 0xce, 0xcf, 0x66, 0xf3, 0x33, 0x2b, 0xea, 0x45, 0xd6, + 0xcd, 0xe7, 0x76, 0x35, 0x03, 0x1b, 0x73, 0x06, 0x0e, 0x9b, 0xf0, 0xd5, + 0xa6, 0x1e, 0xc6, 0x3a, 0x7e, 0x07, 0x53, 0x83, 0x78, 0x7d, 0x2c, 0x16, + 0x7d, 0x0a, 0x5a, 0x46, 0x77, 0x6b, 0x83, 0x40, 0x63, 0x7f, 0x9f, 0xd2, + 0x7a, 0xdf, 0x50, 0x5a, 0xf7, 0x98, 0x82, 0x4f, 0xf1, 0xb9, 0xc6, 0xbc, + 0x7c, 0x0f, 0xe2, 0xd6, 0xbc, 0x0f, 0x97, 0xdc, 0xb2, 0xfe, 0xef, 0x52, + 0xdf, 0x0a, 0x1e, 0xbd, 0x05, 0xa3, 0xe4, 0xc1, 0x9b, 0x52, 0x78, 0xb2, + 0x39, 0x1e, 0x19, 0x86, 0xdc, 0x8f, 0x62, 0x43, 0x41, 0xbe, 0x35, 0x4a, + 0x6d, 0x59, 0xa3, 0x86, 0x65, 0x9d, 0x31, 0xca, 0x91, 0x0d, 0x69, 0x11, + 0x40, 0x61, 0xd8, 0x70, 0x21, 0x1d, 0x6a, 0x8b, 0x7a, 0xa0, 0x45, 0xee, + 0xc1, 0x3f, 0x51, 0xe6, 0x74, 0xc2, 0x0b, 0xe7, 0xf9, 0x5e, 0x94, 0x63, + 0x3e, 0xe4, 0x68, 0xed, 0xc9, 0x9c, 0x65, 0x5d, 0xd0, 0x3d, 0x38, 0x43, + 0xfd, 0x0c, 0xe7, 0xff, 0xc9, 0x9a, 0xa7, 0x6e, 0x46, 0xf5, 0xd2, 0xfa, + 0x3e, 0x4c, 0x85, 0x2c, 0x6b, 0x9a, 0xf7, 0x0e, 0xe7, 0x4b, 0x7a, 0xb6, + 0x2c, 0x97, 0x6e, 0x59, 0xbb, 0xf5, 0xdf, 0x58, 0xbb, 0x7e, 0xeb, 0x59, + 0xcb, 0x7a, 0xcc, 0xb8, 0x09, 0x67, 0x27, 0xda, 0xd5, 0x96, 0xd9, 0x25, + 0xc1, 0xcd, 0x93, 0x16, 0x2e, 0x18, 0x08, 0xb9, 0x52, 0x1d, 0x6a, 0xf3, + 0x6c, 0xa7, 0xda, 0x58, 0xd8, 0xae, 0x3a, 0xa6, 0xbf, 0xa5, 0x3a, 0x67, + 0x7b, 0xd5, 0xa6, 0x42, 0x04, 0x33, 0x66, 0x18, 0xd3, 0x66, 0x46, 0xb5, + 0xcf, 0xf6, 0x28, 0x47, 0x8e, 0x41, 0xd5, 0x56, 0x28, 0xd1, 0xba, 0xae, + 0xc7, 0xcd, 0xb9, 0x14, 0x8e, 0x98, 0xe5, 0x5c, 0x67, 0xc1, 0xfa, 0x49, + 0xc3, 0x02, 0xe5, 0x34, 0x70, 0xb4, 0xf0, 0x18, 0xb6, 0x4d, 0x5a, 0x56, + 0x3e, 0x09, 0xe4, 0x0b, 0xc0, 0x0f, 0xcc, 0x58, 0x77, 0xbf, 0xb2, 0xac, + 0x4d, 0x71, 0x6b, 0xe9, 0x65, 0xa3, 0x31, 0xf1, 0x12, 0xfe, 0xaf, 0x35, + 0x15, 0x46, 0x36, 0x40, 0x1a, 0xc7, 0x68, 0xb3, 0xfb, 0xc6, 0xe0, 0x2b, + 0x4f, 0x8d, 0xe2, 0x17, 0x39, 0xf8, 0xca, 0x52, 0x59, 0x5c, 0xc8, 0x0d, + 0x87, 0x7c, 0x88, 0x45, 0x36, 0xab, 0xec, 0xa0, 0x0b, 0xda, 0xc0, 0xdb, + 0xd0, 0xa2, 0xb4, 0xc7, 0xc5, 0xf3, 0x4a, 0x9b, 0x7f, 0x09, 0x5a, 0xfa, + 0x37, 0x4a, 0xeb, 0xac, 0x75, 0x23, 0xed, 0x8a, 0xfb, 0xf0, 0x93, 0x06, + 0xb1, 0xc9, 0x28, 0x56, 0xd8, 0xb6, 0xc9, 0x62, 0xd9, 0x35, 0xdb, 0xa4, + 0x30, 0x4c, 0xbe, 0x0e, 0x93, 0xaf, 0x97, 0x0d, 0x2d, 0xf2, 0x24, 0xac, + 0xa5, 0x7d, 0x86, 0xdc, 0x4b, 0x61, 0xb4, 0x60, 0x45, 0x83, 0xa9, 0x4b, + 0xe4, 0x17, 0xd9, 0x2f, 0xa5, 0x7c, 0xd9, 0xea, 0xd4, 0xa7, 0xd6, 0x6b, + 0x6b, 0x22, 0x78, 0xa1, 0x10, 0xc6, 0x73, 0x85, 0x10, 0x9e, 0x2d, 0xb4, + 0xc3, 0x2c, 0x20, 0xb8, 0xad, 0xf0, 0x45, 0x7e, 0x6c, 0x21, 0xc0, 0xe7, + 0xc9, 0x77, 0x70, 0x6b, 0xc1, 0xd3, 0x5b, 0x96, 0x42, 0xf7, 0x4f, 0x73, + 0x43, 0x56, 0x85, 0x8e, 0xde, 0x9a, 0x94, 0x9e, 0xbe, 0x55, 0x05, 0x5a, + 0xe8, 0x87, 0xdd, 0xaf, 0xe4, 0x5b, 0x3c, 0xfa, 0x71, 0x3f, 0xbc, 0xd4, + 0xff, 0xc6, 0x82, 0x65, 0x8d, 0x18, 0x07, 0x56, 0xee, 0x6a, 0xf9, 0x8b, + 0xf9, 0x6e, 0xbd, 0x0b, 0xd9, 0x42, 0x1f, 0x10, 0x4c, 0xf1, 0x9b, 0xa1, + 0xb8, 0xbd, 0xa9, 0x3d, 0x7a, 0xee, 0x01, 0x8f, 0xe3, 0xcf, 0xe4, 0x81, + 0x7a, 0x7f, 0xce, 0x24, 0x0f, 0xe6, 0xe1, 0x20, 0x2a, 0xa2, 0x94, 0xef, + 0xe7, 0xe4, 0x33, 0x81, 0x1f, 0x16, 0x74, 0xf2, 0xd6, 0x44, 0x1e, 0xa3, + 0xe4, 0xcf, 0x87, 0x5d, 0x13, 0xda, 0x78, 0x16, 0xda, 0x91, 0x29, 0x2c, + 0x47, 0x3a, 0x1c, 0xa2, 0x0f, 0xfe, 0x39, 0x1c, 0x1a, 0x5d, 0x38, 0x6e, + 0x62, 0x55, 0x28, 0x45, 0xfb, 0x26, 0xf1, 0x70, 0x19, 0xe2, 0xbd, 0x1f, + 0x2b, 0x85, 0xd7, 0xe2, 0x5d, 0x18, 0xa3, 0x3c, 0x5d, 0x79, 0x3f, 0xee, + 0x9f, 0xa8, 0xc0, 0xbd, 0x13, 0x16, 0xee, 0x4b, 0x22, 0x55, 0x41, 0x79, + 0x12, 0xc9, 0x78, 0xf4, 0x3d, 0x78, 0xd0, 0x9e, 0xef, 0x62, 0x2c, 0x6d, + 0x40, 0xba, 0xcc, 0x87, 0x0d, 0xf9, 0x00, 0xe3, 0x31, 0x8d, 0xd3, 0x93, + 0x3e, 0x78, 0x57, 0xbb, 0x30, 0x15, 0x2e, 0x43, 0xa2, 0xde, 0xc5, 0x4f, + 0x38, 0xd8, 0x36, 0x59, 0x17, 0xdc, 0x68, 0x7a, 0xb0, 0xd7, 0x74, 0x61, + 0x68, 0xc2, 0xb2, 0xda, 0x0d, 0x0b, 0x57, 0x57, 0x87, 0xf0, 0x3c, 0xf5, + 0x77, 0xc0, 0x8c, 0xe0, 0x6c, 0xe1, 0x51, 0xf2, 0x12, 0x76, 0xf8, 0x35, + 0xc9, 0xbb, 0x49, 0xde, 0x4d, 0xf2, 0x6d, 0x0a, 0x9f, 0xe7, 0x19, 0x33, + 0x06, 0xe5, 0xf2, 0x93, 0x87, 0x4a, 0xf4, 0x93, 0x8f, 0x58, 0xd2, 0x82, + 0x2b, 0xa9, 0x65, 0x77, 0x31, 0x79, 0x2d, 0xad, 0xb7, 0xac, 0x8f, 0x57, + 0x8b, 0x2c, 0xb4, 0xb9, 0xab, 0x4b, 0x62, 0xf4, 0xf7, 0xaa, 0x18, 0x57, + 0x7f, 0x4b, 0xbd, 0x3d, 0x5e, 0xf0, 0x63, 0x70, 0xc2, 0xf6, 0xdb, 0x83, + 0x65, 0xe4, 0x5b, 0xf8, 0x2a, 0xe8, 0x71, 0xc6, 0x68, 0x3c, 0xc3, 0x18, + 0xc5, 0x56, 0xf2, 0x7c, 0x9f, 0x19, 0x6f, 0xd9, 0xae, 0x3c, 0xd8, 0x94, + 0x0f, 0x07, 0xdb, 0x6f, 0xe0, 0x93, 0xf2, 0x4a, 0x0c, 0x52, 0xd6, 0x10, + 0xf9, 0x0b, 0x63, 0x37, 0xf9, 0x7c, 0xae, 0xc8, 0xe7, 0x74, 0x41, 0xd6, + 0xfa, 0x3c, 0xaf, 0x25, 0x3e, 0x91, 0x5d, 0x94, 0x0a, 0x2b, 0x54, 0x04, + 0xb0, 0x3d, 0xff, 0x26, 0x6d, 0x51, 0x87, 0xbf, 0xa0, 0x0d, 0x5e, 0x60, + 0x8c, 0xfc, 0xf0, 0x9a, 0xbf, 0x88, 0x3d, 0x1e, 0xa1, 0x1d, 0xb4, 0xd3, + 0x59, 0x04, 0xd0, 0x5b, 0x48, 0xe3, 0xd0, 0x24, 0xd2, 0x33, 0xc6, 0x31, + 0xc6, 0xfb, 0x12, 0xb8, 0xf5, 0xf2, 0x74, 0x48, 0xaf, 0xc0, 0xee, 0xe9, + 0x30, 0x06, 0x0a, 0x6d, 0x30, 0x27, 0xc2, 0xd8, 0x47, 0xdf, 0xbc, 0x92, + 0x4c, 0xdf, 0x17, 0x84, 0xf0, 0x1e, 0xc6, 0xfd, 0x7c, 0xe7, 0xb1, 0xc9, + 0x30, 0xfa, 0xa9, 0xa3, 0xcd, 0xc9, 0x78, 0x8b, 0x9f, 0xd7, 0xf6, 0xf2, + 0xda, 0x61, 0xea, 0xff, 0xbc, 0x31, 0x86, 0xde, 0x6e, 0x2d, 0x01, 0x84, + 0xb1, 0xc7, 0x44, 0x88, 0x2e, 0xfc, 0x08, 0xf3, 0x5b, 0xe2, 0x3c, 0xff, + 0xbe, 0xa7, 0x50, 0x41, 0x39, 0x83, 0x88, 0xe8, 0x9f, 0x58, 0xde, 0x66, + 0xcb, 0xfa, 0xbe, 0x11, 0xbf, 0xf8, 0x96, 0xdb, 0x83, 0x87, 0x0a, 0x2e, + 0x0c, 0x4e, 0x57, 0xe0, 0x0f, 0x27, 0x3c, 0xb8, 0xb3, 0xbe, 0x02, 0x07, + 0xa6, 0xd3, 0x18, 0x99, 0xac, 0x40, 0xdf, 0x04, 0x96, 0xee, 0x31, 0x46, + 0x6a, 0xca, 0xa0, 0x2d, 0xb4, 0x23, 0x81, 0xab, 0xb4, 0xc3, 0x43, 0xd3, + 0x81, 0x60, 0x66, 0x32, 0x84, 0xc1, 0x59, 0x3f, 0x9f, 0x77, 0xf1, 0xf9, + 0x72, 0x18, 0xab, 0x62, 0x83, 0x21, 0x08, 0x8f, 0x95, 0xd8, 0x3f, 0xed, + 0xc7, 0x03, 0x13, 0x21, 0xec, 0x9b, 0x6c, 0xc6, 0xb8, 0x99, 0xc6, 0x51, + 0xe6, 0x8e, 0x1f, 0x24, 0xb5, 0xee, 0x7d, 0x4a, 0x4b, 0x6f, 0x54, 0x69, + 0x34, 0x24, 0xbd, 0xb8, 0xc4, 0x3c, 0xe4, 0x4d, 0x36, 0xb6, 0x3c, 0xcb, + 0xdc, 0x50, 0x96, 0x0a, 0xf3, 0x6f, 0xed, 0x08, 0x63, 0x36, 0xed, 0x75, + 0xad, 0x06, 0x16, 0x4b, 0xfc, 0x86, 0x83, 0x5b, 0xcc, 0x50, 0x70, 0x4b, + 0xa1, 0x2e, 0xb8, 0xd9, 0x8c, 0x04, 0x37, 0x33, 0xbe, 0x36, 0x8a, 0x3f, + 0x9a, 0x3e, 0x1c, 0x4b, 0x7e, 0x6a, 0xf5, 0xd6, 0xd8, 0xf9, 0x2c, 0xb8, + 0x6d, 0x52, 0xcb, 0x4e, 0x41, 0x33, 0x58, 0x0d, 0x30, 0x36, 0xeb, 0xa1, + 0xfd, 0x14, 0x6a, 0xf4, 0x66, 0xe6, 0xf1, 0x10, 0xf6, 0x33, 0xa7, 0xfc, + 0x15, 0x73, 0x4a, 0xdf, 0xf1, 0x58, 0x68, 0x1c, 0x7e, 0xea, 0x1b, 0xd8, + 0x75, 0x2e, 0x4c, 0x9b, 0x77, 0xe2, 0x51, 0xf2, 0xb5, 0x79, 0x4d, 0x18, + 0xf7, 0x16, 0x42, 0xc1, 0x4e, 0xda, 0xef, 0xbd, 0x7c, 0x24, 0xb8, 0x81, + 0xb6, 0x7c, 0x3b, 0xaf, 0x45, 0xe7, 0xf1, 0x8f, 0xe2, 0x4f, 0x09, 0xb8, + 0x80, 0x3d, 0xc7, 0xbd, 0x98, 0x0f, 0xcb, 0x5a, 0xd4, 0xb9, 0xf9, 0x82, + 0x15, 0xd0, 0xf5, 0xd3, 0xfb, 0xa8, 0xeb, 0x6f, 0x17, 0x02, 0x78, 0xc0, + 0xd4, 0x12, 0x3f, 0x54, 0x01, 0xea, 0xd4, 0x47, 0x3d, 0x30, 0xc1, 0x2c, + 0x91, 0xe7, 0x92, 0x88, 0x2e, 0x71, 0x72, 0xed, 0x81, 0x69, 0xf1, 0x13, + 0xda, 0xde, 0xa4, 0x0f, 0xd0, 0x7f, 0x7e, 0x78, 0x2d, 0x56, 0xb5, 0x50, + 0xd6, 0xce, 0xdd, 0x09, 0xfa, 0x8b, 0xa3, 0xa3, 0x13, 0x93, 0xa2, 0x07, + 0x6d, 0x1c, 0xae, 0x34, 0x56, 0xae, 0xfa, 0x2b, 0xeb, 0xd2, 0x62, 0xd1, + 0x47, 0x08, 0x43, 0xd4, 0xe1, 0x69, 0xd3, 0xb2, 0xae, 0xae, 0xfe, 0xd0, + 0x6a, 0xb9, 0x59, 0xf4, 0x22, 0xb2, 0x3e, 0xaf, 0xa4, 0x8e, 0xd4, 0xe8, + 0xc1, 0xff, 0x0f, 0xbe, 0xf2, 0x1d, 0xab, 0xd7, 0x96, 0x4f, 0xfc, 0xc5, + 0x43, 0x5f, 0x7c, 0x94, 0xb4, 0x5d, 0xe8, 0x25, 0xbd, 0x07, 0x4d, 0xeb, + 0xa3, 0xda, 0xd4, 0x67, 0x56, 0xcb, 0x5a, 0x7d, 0x60, 0x41, 0xfd, 0x0f, + 0x5e, 0x0f, 0x63, 0x7f, 0xa1, 0x85, 0xba, 0x6b, 0xc7, 0x63, 0xd4, 0xe1, + 0x61, 0x53, 0x72, 0x62, 0x84, 0xfe, 0x5c, 0x47, 0xff, 0xf6, 0xa8, 0x8d, + 0x66, 0x1e, 0x9b, 0xc7, 0xb2, 0xd8, 0x44, 0x7f, 0xbf, 0x98, 0x8b, 0xb5, + 0x3c, 0x0d, 0x2d, 0x4b, 0x19, 0x82, 0x9d, 0xd4, 0x71, 0xbb, 0xa9, 0x75, + 0x8a, 0x4d, 0xdb, 0x99, 0x97, 0x5e, 0xcc, 0x45, 0x82, 0x6d, 0x05, 0xd1, + 0x77, 0x5d, 0x70, 0x43, 0xe1, 0xab, 0xb4, 0xbd, 0xc2, 0xba, 0xe5, 0x3e, + 0xe6, 0x99, 0x3b, 0xe1, 0xd8, 0xd5, 0xb1, 0xdd, 0x6b, 0xc9, 0xc6, 0xde, + 0x0f, 0x99, 0x9f, 0xb2, 0x8b, 0x9d, 0x6b, 0x83, 0xbc, 0x56, 0xbd, 0x1a, + 0xc1, 0x3b, 0xe8, 0x07, 0x77, 0xd3, 0x0f, 0xae, 0xae, 0xfe, 0xd4, 0x8a, + 0xde, 0xe4, 0xf8, 0x41, 0xdb, 0xa4, 0x27, 0xd8, 0x41, 0x3d, 0x6d, 0x34, + 0x14, 0xa6, 0x8d, 0x1c, 0x7a, 0xaf, 0x61, 0x87, 0xf4, 0xd4, 0x59, 0x23, + 0xcd, 0x3c, 0xf2, 0xbb, 0xf0, 0xd4, 0x60, 0xea, 0x69, 0xe3, 0x51, 0x44, + 0x1d, 0xdf, 0xc1, 0xbe, 0x09, 0x3f, 0xb2, 0x77, 0x86, 0x30, 0xd3, 0x10, + 0xc2, 0x83, 0xa4, 0x7d, 0x25, 0xd9, 0xd8, 0xff, 0x3a, 0x75, 0x30, 0x55, + 0x23, 0xd7, 0xd2, 0xf8, 0x91, 0xf1, 0x30, 0x70, 0x93, 0xb3, 0xf6, 0xac, + 0xc4, 0xe8, 0x6c, 0x33, 0x0e, 0x17, 0x32, 0xca, 0xc9, 0x9b, 0x5a, 0x67, + 0x1a, 0x3f, 0xb7, 0x24, 0x97, 0xce, 0x9a, 0xcc, 0x71, 0xd4, 0xc7, 0x28, + 0xfd, 0x68, 0x38, 0x5f, 0x17, 0xdc, 0x44, 0x3f, 0x7a, 0x34, 0x2f, 0x32, + 0xc5, 0x0d, 0xc3, 0x5d, 0xcb, 0xda, 0x4c, 0xfd, 0x98, 0x76, 0xcd, 0xaf, + 0x0e, 0xe9, 0x47, 0x31, 0x6e, 0xf3, 0x36, 0xa8, 0x32, 0xc4, 0x18, 0x0c, + 0x99, 0xea, 0x72, 0xfd, 0x00, 0x1e, 0xb5, 0xaf, 0x85, 0x83, 0x3b, 0x26, + 0xd3, 0x2e, 0x97, 0x8e, 0x50, 0x65, 0xaa, 0x5d, 0xed, 0x60, 0xdd, 0xed, + 0x98, 0xec, 0x50, 0x1d, 0xb3, 0x12, 0x03, 0x9d, 0x6a, 0x33, 0x6b, 0x6e, + 0x9a, 0x35, 0x37, 0xcd, 0x9a, 0x9b, 0x26, 0x1f, 0x69, 0xd6, 0xda, 0xb6, + 0xc2, 0xa0, 0xda, 0x2a, 0xfa, 0xa7, 0x7f, 0x3d, 0x6b, 0x3a, 0x38, 0x82, + 0x39, 0x28, 0xb8, 0xa9, 0xb0, 0xc2, 0xe5, 0x60, 0xbb, 0x41, 0x55, 0xc4, + 0x32, 0xbe, 0x0a, 0x9d, 0xb5, 0xcc, 0x1c, 0x54, 0x5b, 0x58, 0x6f, 0x33, + 0xb6, 0x2e, 0x63, 0x03, 0xef, 0xb0, 0xce, 0xbe, 0xc6, 0x3a, 0x9b, 0x4f, + 0x32, 0xae, 0x96, 0x5f, 0xb5, 0x7a, 0x17, 0x3b, 0x35, 0x61, 0x84, 0xfc, + 0x7e, 0x9f, 0x36, 0x9b, 0x67, 0x2d, 0x6d, 0x77, 0x2b, 0xec, 0xd1, 0x51, + 0x5d, 0xcb, 0x9c, 0x7a, 0xb8, 0xc0, 0x3a, 0x60, 0xc4, 0x5a, 0xde, 0xa7, + 0x62, 0x0f, 0xeb, 0x5e, 0x5c, 0xbd, 0x89, 0x60, 0x47, 0x6f, 0xc3, 0xb1, + 0x89, 0x72, 0xf4, 0x27, 0xd3, 0x8b, 0x7c, 0xc4, 0x2a, 0x9d, 0xcd, 0x78, + 0x98, 0x4b, 0xab, 0x48, 0x2a, 0x4e, 0xbf, 0x41, 0xfa, 0x38, 0xeb, 0xc4, + 0x98, 0xf9, 0x55, 0xe4, 0x59, 0x4f, 0x67, 0x0c, 0x0f, 0x5e, 0xcb, 0xaf, + 0x60, 0x9e, 0x8b, 0x1b, 0x01, 0x55, 0xc1, 0xf8, 0x4d, 0x21, 0x67, 0x4a, + 0x7e, 0xb2, 0xac, 0x19, 0xe1, 0x21, 0x1e, 0x4f, 0x0f, 0x43, 0x72, 0x96, + 0xb5, 0xf4, 0x9e, 0x64, 0x19, 0xd6, 0xc5, 0x83, 0x58, 0xaa, 0xf7, 0xaa, + 0xce, 0x42, 0xdc, 0x38, 0x8f, 0x6f, 0xa9, 0xbb, 0x67, 0x53, 0x8c, 0xed, + 0x0c, 0x75, 0x53, 0x81, 0x4b, 0x61, 0xe1, 0x11, 0xd5, 0x5e, 0xdd, 0x85, + 0x77, 0xef, 0x52, 0x08, 0xe9, 0x69, 0x5c, 0x68, 0x0e, 0xd1, 0xaf, 0x3a, + 0x89, 0x31, 0xa2, 0x70, 0xcf, 0x45, 0x82, 0x5b, 0x69, 0x8b, 0xca, 0xb9, + 0x3a, 0xda, 0x87, 0xbe, 0x47, 0x1d, 0xb6, 0x51, 0x87, 0x5b, 0xa6, 0x11, + 0xaa, 0x48, 0xf5, 0xa8, 0x8e, 0x42, 0xbb, 0x6a, 0x2f, 0x68, 0xd4, 0x93, + 0xe8, 0xe4, 0x3b, 0xc4, 0x4a, 0xe2, 0x2b, 0x25, 0x5b, 0x8a, 0xbf, 0xde, + 0x68, 0xcf, 0x8c, 0x4b, 0x62, 0x6e, 0xdd, 0xf2, 0x14, 0xe3, 0xd1, 0x45, + 0xbe, 0x84, 0x07, 0x1f, 0xaa, 0x1b, 0xac, 0xa5, 0x57, 0x92, 0x4c, 0x9e, + 0x15, 0x29, 0x1c, 0x2f, 0x74, 0xd1, 0x2e, 0xab, 0x8b, 0xfe, 0x15, 0x0a, + 0x6e, 0x9c, 0x6c, 0x57, 0x1b, 0x67, 0x17, 0x05, 0xbb, 0x69, 0xc3, 0xee, + 0xd9, 0x88, 0xd0, 0xe5, 0xfa, 0x62, 0xdb, 0x34, 0x5c, 0xfa, 0xbf, 0x64, + 0xcb, 0x6f, 0x93, 0x96, 0xd8, 0xd3, 0x5f, 0xf2, 0xd3, 0xe0, 0xdd, 0x93, + 0x69, 0xbc, 0xbb, 0xda, 0xcb, 0x9a, 0x5a, 0xc2, 0x14, 0x55, 0xc5, 0xef, + 0xd3, 0x2e, 0xe8, 0x83, 0xaa, 0x53, 0xfc, 0xc8, 0xeb, 0xac, 0x79, 0xc7, + 0x24, 0xbc, 0x84, 0x0a, 0x51, 0x37, 0x31, 0xdd, 0x87, 0xc9, 0x78, 0xef, + 0x39, 0xd5, 0xa5, 0xba, 0x0a, 0x52, 0x83, 0x1d, 0x9f, 0x6a, 0xa3, 0x4f, + 0xb5, 0x93, 0x9f, 0x76, 0xfa, 0xd4, 0x16, 0xf2, 0xb3, 0xc5, 0xf6, 0x29, + 0xf1, 0xcd, 0xdf, 0xe6, 0x65, 0x43, 0xe1, 0x6e, 0x5b, 0x2f, 0x5b, 0xf9, + 0x6e, 0x27, 0xe5, 0xe8, 0xe4, 0x7b, 0x77, 0xf3, 0xbd, 0xbb, 0x67, 0xff, + 0x97, 0xf0, 0x47, 0x59, 0x9c, 0xd8, 0xbf, 0x5e, 0xd3, 0x24, 0x07, 0xfc, + 0xac, 0x88, 0x29, 0x90, 0x75, 0xa5, 0x24, 0x47, 0x0c, 0xa0, 0xbb, 0x19, + 0xbe, 0x45, 0xa9, 0x67, 0x5b, 0xb7, 0xd7, 0x33, 0x9f, 0x31, 0x9f, 0xfa, + 0x8e, 0x13, 0x4b, 0x33, 0x47, 0xcf, 0xb4, 0x28, 0x8c, 0x18, 0x37, 0x33, + 0x4e, 0x0d, 0x1c, 0x29, 0x68, 0x9d, 0x51, 0xde, 0x6b, 0x1a, 0x13, 0x8c, + 0xbf, 0x0f, 0x6d, 0xc4, 0x75, 0x91, 0x54, 0x3f, 0x22, 0x66, 0x2c, 0x72, + 0x44, 0x69, 0xfd, 0x1b, 0xa0, 0x5d, 0x64, 0x6d, 0x18, 0x9c, 0x56, 0xda, + 0x40, 0xad, 0x5b, 0x4b, 0xbf, 0x61, 0xe3, 0xeb, 0x7d, 0x58, 0x6e, 0x63, + 0xb8, 0x7e, 0x24, 0x88, 0x65, 0xb7, 0x92, 0xe6, 0xde, 0x75, 0x0a, 0x97, + 0x8d, 0x0f, 0x69, 0x47, 0x2d, 0x9d, 0x55, 0x06, 0x72, 0xcc, 0x13, 0x91, + 0xe3, 0x82, 0xd5, 0xf7, 0x11, 0xab, 0xc3, 0x17, 0xe0, 0xb3, 0xb9, 0xb1, + 0xd8, 0xa0, 0xcf, 0xad, 0x25, 0x88, 0xd3, 0xd3, 0xa4, 0x69, 0x14, 0x88, + 0xdf, 0xb9, 0x46, 0x74, 0x4f, 0x91, 0x66, 0xbc, 0x48, 0x53, 0xcf, 0x83, + 0x71, 0x73, 0x04, 0x9b, 0xe2, 0xac, 0x15, 0xcc, 0x79, 0x47, 0xa5, 0x27, + 0x20, 0xbd, 0xf2, 0xe3, 0x06, 0xff, 0x1e, 0x54, 0x3b, 0x24, 0xa6, 0xca, + 0x1d, 0x2b, 0x54, 0x73, 0x8d, 0xaa, 0xd4, 0x41, 0xcc, 0xd9, 0x6b, 0x0c, + 0xc8, 0x1a, 0x03, 0xbf, 0x50, 0x5a, 0xe2, 0x9c, 0x92, 0x5c, 0xdd, 0x98, + 0x39, 0xc7, 0x18, 0x3a, 0xac, 0xb4, 0x96, 0x63, 0x14, 0xdf, 0xaf, 0x0b, + 0xfd, 0x83, 0xc5, 0x75, 0x06, 0xd0, 0x90, 0x67, 0x7c, 0x16, 0x7c, 0x6a, + 0xc3, 0x44, 0x1b, 0x46, 0xa6, 0xdb, 0x30, 0x3c, 0xa1, 0x70, 0xb7, 0xb1, + 0x18, 0x97, 0x6e, 0xb6, 0xfb, 0x94, 0xaa, 0xa5, 0x7a, 0x2d, 0x86, 0x42, + 0xa8, 0x76, 0xe9, 0x5f, 0xc1, 0xae, 0x22, 0xc6, 0xdf, 0x74, 0xa2, 0x9b, + 0x79, 0xdf, 0xc2, 0xfb, 0x8c, 0xa5, 0x58, 0x0d, 0xd2, 0xde, 0x54, 0x0b, + 0xf1, 0x78, 0x9d, 0xdb, 0x89, 0xf7, 0x0f, 0x7d, 0x8e, 0x0d, 0x44, 0xff, + 0x9f, 0xbf, 0xd7, 0x86, 0xc7, 0x27, 0xca, 0xd0, 0xb2, 0x1a, 0x77, 0x46, + 0x50, 0xe5, 0x62, 0x8d, 0x7b, 0x73, 0xbb, 0x1a, 0xe4, 0x3d, 0xfb, 0x59, + 0xdf, 0x97, 0x53, 0x46, 0xea, 0x4f, 0x1a, 0xe4, 0xba, 0x9d, 0x37, 0x6e, + 0xb8, 0xde, 0xfd, 0x05, 0xd7, 0x15, 0x9e, 0x61, 0x22, 0xfb, 0x01, 0x6b, + 0x4a, 0x3e, 0x67, 0xc1, 0x9d, 0xf2, 0xa0, 0x7f, 0x2c, 0x8a, 0x7d, 0x73, + 0x61, 0xcc, 0xe5, 0xb4, 0xde, 0x4b, 0xec, 0x1f, 0x76, 0x35, 0xeb, 0x78, + 0x60, 0x2e, 0x82, 0xd9, 0x1c, 0x2c, 0x7f, 0x4a, 0x9f, 0xf7, 0xab, 0x04, + 0xf6, 0xce, 0xd5, 0xe1, 0x5c, 0x4e, 0xbf, 0x38, 0xac, 0xe2, 0x83, 0xb5, + 0xc4, 0x1d, 0x0f, 0xce, 0x35, 0x61, 0xff, 0x9c, 0x8f, 0xef, 0x58, 0xd8, + 0x92, 0xac, 0xe3, 0xf3, 0x2e, 0x3c, 0x7d, 0xd2, 0xb2, 0x04, 0x77, 0xf5, + 0xcf, 0x01, 0xb3, 0xe3, 0xac, 0x45, 0x67, 0x58, 0x97, 0x9e, 0x00, 0xf6, + 0x3e, 0xe1, 0xc2, 0xf4, 0xb8, 0x85, 0x5d, 0xc6, 0x70, 0xad, 0x8b, 0x0e, + 0xdf, 0xcb, 0xba, 0xe1, 0x65, 0x0d, 0xbc, 0x27, 0xe4, 0xe4, 0xf3, 0x4b, + 0xcc, 0x53, 0xf7, 0x3d, 0x91, 0xc0, 0x9b, 0xb9, 0x2c, 0xb6, 0x10, 0x9f, + 0x0f, 0x92, 0x97, 0x37, 0x72, 0xac, 0x63, 0x73, 0x06, 0x5e, 0xcf, 0xf9, + 0xb8, 0x4e, 0x13, 0x5e, 0xca, 0xc9, 0x33, 0xf2, 0x6c, 0x00, 0x7d, 0xe4, + 0xe5, 0xb5, 0x5c, 0x84, 0x6b, 0x86, 0xf1, 0x53, 0x3e, 0x77, 0xef, 0x9c, + 0xce, 0xba, 0xe5, 0xe3, 0xba, 0x51, 0xbc, 0x92, 0x0b, 0x90, 0xd7, 0x30, + 0x6b, 0x55, 0x1f, 0x46, 0x72, 0x8d, 0x17, 0x37, 0x30, 0x51, 0x3b, 0xb5, + 0x46, 0xae, 0xbd, 0x63, 0x75, 0xd9, 0xb1, 0x28, 0xeb, 0x94, 0xd6, 0xed, + 0xc3, 0x70, 0xee, 0x75, 0x77, 0xa9, 0x9f, 0x7e, 0x66, 0x7c, 0xc1, 0xc6, + 0x7e, 0x4f, 0x9b, 0xfc, 0x7d, 0x1a, 0x38, 0x67, 0x66, 0xad, 0xea, 0x14, + 0xb1, 0x2e, 0x6b, 0xd4, 0x5b, 0x6b, 0x9a, 0xb8, 0xae, 0xde, 0xfb, 0xa2, + 0x92, 0x7e, 0xc7, 0x83, 0xe8, 0x13, 0xa2, 0x2f, 0x62, 0xe6, 0x59, 0xe0, + 0x47, 0xc4, 0x9f, 0x0d, 0x63, 0x9a, 0xf8, 0x7d, 0x86, 0xb8, 0xa6, 0x7b, + 0x1e, 0xf5, 0x89, 0x07, 0x30, 0x64, 0x95, 0x11, 0x9f, 0x57, 0x13, 0xd7, + 0xce, 0x35, 0xb1, 0x4e, 0xad, 0xb1, 0xac, 0xbf, 0x6d, 0x86, 0xe5, 0x4a, + 0xe9, 0x46, 0xad, 0x7b, 0xfe, 0x2b, 0x55, 0xd0, 0x2f, 0x06, 0x95, 0x3e, + 0xff, 0x16, 0xe2, 0x03, 0xe7, 0x21, 0x7a, 0x05, 0x56, 0xcc, 0x79, 0xb0, + 0x92, 0xf2, 0x6c, 0x1c, 0xe3, 0xda, 0xc4, 0x27, 0x71, 0xca, 0xb4, 0x6d, + 0x8c, 0x98, 0x4b, 0x0f, 0x60, 0x39, 0x75, 0xdc, 0x7f, 0xca, 0xb2, 0xca, + 0xa9, 0xe3, 0x06, 0xda, 0x67, 0xcf, 0x09, 0x0b, 0x2f, 0x1a, 0x2f, 0x52, + 0xa7, 0x8a, 0xb8, 0xb1, 0x99, 0xef, 0x84, 0xf9, 0xbc, 0x0f, 0x7b, 0xc7, + 0xa4, 0x5f, 0xaa, 0xe3, 0x33, 0xaf, 0xe2, 0x58, 0x2e, 0x81, 0x26, 0xea, + 0x2f, 0x4a, 0x9a, 0x8d, 0x7c, 0x27, 0x4a, 0x7a, 0xd1, 0xb9, 0xaf, 0x61, + 0xf3, 0x29, 0x05, 0x3d, 0x2e, 0x3a, 0xf8, 0x1a, 0xda, 0xcf, 0x7c, 0x51, + 0x4e, 0x60, 0x96, 0x1a, 0xd7, 0x8e, 0xcc, 0x13, 0x7f, 0x57, 0xa5, 0x86, + 0xc0, 0xfa, 0x8d, 0x37, 0xa6, 0x14, 0x8e, 0x8f, 0xb3, 0xdf, 0x5b, 0x03, + 0xab, 0x82, 0x32, 0xbd, 0x3e, 0xf5, 0x3b, 0x78, 0xea, 0x24, 0xf5, 0xf0, + 0x64, 0x18, 0x3f, 0xc8, 0x79, 0xb0, 0xec, 0xb8, 0x60, 0x3a, 0x3d, 0xb1, + 0x4f, 0x49, 0x7f, 0x24, 0x7d, 0x4b, 0x3c, 0xea, 0x55, 0x2e, 0xd4, 0x3f, + 0xe5, 0x81, 0x7e, 0x2e, 0x0a, 0x6f, 0xbd, 0x0f, 0x7a, 0xfd, 0x1f, 0x32, + 0xd7, 0xb8, 0x50, 0xc6, 0x5e, 0x76, 0xd3, 0x77, 0x13, 0xbc, 0x16, 0xe6, + 0x35, 0xfc, 0x4e, 0x39, 0xdc, 0x4b, 0xdc, 0xac, 0xe1, 0x65, 0x3a, 0xf1, + 0x98, 0xc7, 0xb2, 0xdc, 0xac, 0x0d, 0x3b, 0xbe, 0x67, 0x59, 0xb1, 0xd5, + 0xf2, 0x7c, 0x08, 0xb1, 0x73, 0x3a, 0x9f, 0x73, 0xea, 0xe5, 0x75, 0x3c, + 0xe6, 0xa6, 0x1f, 0x49, 0xac, 0xb2, 0xde, 0xdb, 0x3d, 0x94, 0x83, 0xdb, + 0x9f, 0x2b, 0x08, 0xb6, 0x89, 0xda, 0x32, 0x9c, 0x1d, 0x57, 0xcc, 0xd9, + 0x29, 0x3e, 0xbb, 0x1e, 0xee, 0xa4, 0x76, 0x24, 0x4b, 0x3f, 0xd8, 0x15, + 0x6a, 0xc1, 0x33, 0xa6, 0x17, 0x95, 0xfa, 0x12, 0xdc, 0xdf, 0x1d, 0xc2, + 0x33, 0xec, 0x0b, 0x68, 0xb3, 0xc4, 0x3c, 0xd8, 0x48, 0x07, 0x49, 0xcf, + 0xf5, 0x63, 0xe8, 0xdf, 0x75, 0x31, 0xcf, 0xb9, 0xed, 0x3c, 0x57, 0x56, + 0x0f, 0xcc, 0xe7, 0x3d, 0xb8, 0xa0, 0x3b, 0x98, 0xf0, 0x39, 0xbb, 0x66, + 0x6b, 0xa1, 0xf9, 0x6b, 0x58, 0x50, 0x6b, 0x49, 0x2b, 0x32, 0x13, 0x14, + 0xdd, 0x65, 0x3c, 0x8e, 0x2f, 0xfd, 0x8d, 0x5b, 0x7a, 0x8e, 0xeb, 0x7f, + 0x57, 0xc0, 0x95, 0xd2, 0x22, 0x6d, 0x6e, 0xf8, 0x3c, 0xa9, 0xce, 0xd6, + 0x51, 0xfd, 0x4b, 0x37, 0xf0, 0xde, 0x84, 0x91, 0xc2, 0xf5, 0x5e, 0xbb, + 0x33, 0x67, 0xfb, 0x50, 0xa7, 0xe8, 0xfe, 0x31, 0x43, 0xf2, 0xec, 0xa0, + 0x6a, 0x67, 0xde, 0xca, 0x7a, 0x90, 0xad, 0xe2, 0x33, 0xd4, 0x3f, 0x0e, + 0x8f, 0x09, 0x9d, 0x83, 0x18, 0xcd, 0xc9, 0x6c, 0x63, 0x00, 0xeb, 0xcc, + 0x58, 0xe2, 0x22, 0x7b, 0xe8, 0x43, 0x90, 0x39, 0x44, 0xe3, 0xfc, 0xcb, + 0x4a, 0x1b, 0xbc, 0xc5, 0xad, 0xf5, 0x2f, 0x28, 0x27, 0x6f, 0xad, 0x28, + 0xe6, 0xad, 0xe5, 0xf9, 0x25, 0xc1, 0x2e, 0xd6, 0x83, 0xae, 0xd9, 0x52, + 0x7d, 0xe8, 0x52, 0x9b, 0xec, 0xda, 0x9a, 0x51, 0x5b, 0x67, 0x7d, 0xaa, + 0x63, 0xc2, 0x87, 0x97, 0x89, 0xc5, 0xa6, 0x7a, 0x10, 0x5a, 0xb6, 0x06, + 0xfe, 0xad, 0x13, 0xdd, 0x28, 0xd7, 0xa5, 0x87, 0x2c, 0xc7, 0x26, 0xbb, + 0xae, 0xd5, 0x05, 0xbb, 0x58, 0x7f, 0xba, 0x0a, 0x3d, 0xcc, 0x7f, 0x08, + 0xf9, 0x53, 0xce, 0xcc, 0x40, 0x72, 0xe1, 0xed, 0x7c, 0xf7, 0x62, 0x72, + 0x11, 0xe0, 0xd4, 0x3f, 0x95, 0x61, 0x2f, 0x51, 0xbd, 0x5a, 0xe1, 0xd2, + 0x9d, 0x3e, 0x90, 0x16, 0x7b, 0xfe, 0x7c, 0xeb, 0x85, 0xf1, 0x6e, 0xd5, + 0x31, 0x3d, 0xe3, 0xdf, 0x68, 0xca, 0x2c, 0x62, 0xca, 0xdf, 0x4e, 0x1e, + 0xda, 0x67, 0x9f, 0xf4, 0x6f, 0x20, 0x4f, 0x1b, 0x66, 0x3f, 0x4f, 0x53, + 0xea, 0x4a, 0x7f, 0x6b, 0x1b, 0x63, 0x7b, 0x87, 0xf1, 0x91, 0x15, 0xfd, + 0xa6, 0xd0, 0x99, 0x2b, 0xea, 0x33, 0x4d, 0xbe, 0xc2, 0xbe, 0x4d, 0x85, + 0x90, 0x2f, 0x5d, 0x68, 0xf7, 0xb7, 0x99, 0xdd, 0xfe, 0x0d, 0x66, 0x8f, + 0xbf, 0xdd, 0xdc, 0x49, 0xda, 0x5d, 0xfe, 0x0e, 0x93, 0x71, 0x5d, 0xe8, + 0xa1, 0x5e, 0xbb, 0x31, 0x5a, 0xd8, 0x49, 0xec, 0x21, 0x34, 0x7b, 0x89, + 0x83, 0xfc, 0x94, 0x71, 0x88, 0x32, 0xce, 0x47, 0xbc, 0x48, 0x6b, 0x5e, + 0xea, 0x6b, 0xc4, 0xb6, 0xe3, 0x11, 0x7b, 0x16, 0x55, 0x91, 0x7a, 0xa0, + 0x75, 0xcb, 0x09, 0xe6, 0xfb, 0xd4, 0x9e, 0xd6, 0x65, 0xa7, 0x50, 0xe3, + 0x4d, 0x49, 0xef, 0xcc, 0x7e, 0x38, 0x1e, 0x37, 0xde, 0x43, 0x3c, 0xf2, + 0x32, 0x9f, 0x1d, 0xa6, 0xef, 0x8e, 0xd8, 0xf3, 0x07, 0x1a, 0x24, 0xdf, + 0x84, 0x2d, 0xa6, 0xcf, 0xbf, 0x8d, 0xbd, 0x59, 0x30, 0xa5, 0xb5, 0xdc, + 0xee, 0x96, 0x79, 0xc8, 0xfc, 0xef, 0x05, 0xd0, 0x84, 0xce, 0x82, 0x8f, + 0x72, 0x7d, 0x09, 0x7f, 0x7f, 0x92, 0x75, 0x0d, 0xe2, 0x87, 0x96, 0x75, + 0x2f, 0xfb, 0x9a, 0xa3, 0xf9, 0x3a, 0x5c, 0xb6, 0x6d, 0xec, 0xc1, 0xe1, + 0x7c, 0x14, 0xef, 0x50, 0x3e, 0xcf, 0x5c, 0x2d, 0xde, 0x1e, 0x77, 0x63, + 0xb7, 0x71, 0x5b, 0xb1, 0x5e, 0xb8, 0x70, 0x4f, 0xe2, 0x00, 0xb1, 0x83, + 0x0b, 0xd5, 0xc4, 0x6f, 0x0f, 0xda, 0xd7, 0xdc, 0xec, 0xff, 0xbe, 0x8e, + 0x41, 0xa7, 0x9e, 0x90, 0xc7, 0x9d, 0xe4, 0xb1, 0xd9, 0xbf, 0x61, 0x42, + 0xf3, 0xdf, 0x31, 0x01, 0x9f, 0x37, 0xb5, 0xab, 0xf5, 0xcc, 0x49, 0x0b, + 0x7d, 0xc6, 0xad, 0xb8, 0x72, 0x72, 0xb8, 0xdf, 0x43, 0xff, 0xf9, 0x65, + 0x32, 0x03, 0x73, 0x12, 0x17, 0x88, 0x3c, 0x5e, 0x0d, 0x30, 0xb7, 0x37, + 0x24, 0xe3, 0x21, 0xd6, 0x62, 0x63, 0x96, 0xb1, 0xd9, 0x01, 0xad, 0x9f, + 0x35, 0x39, 0xed, 0x4e, 0xc5, 0x7b, 0x47, 0x08, 0x1e, 0xab, 0xc8, 0x8f, + 0x9f, 0xb9, 0x3b, 0x30, 0x17, 0xf5, 0xef, 0x60, 0xbd, 0x89, 0xb0, 0xbf, + 0xf3, 0xc7, 0x71, 0x5b, 0x2d, 0xe2, 0x89, 0x05, 0xca, 0xed, 0x9d, 0x6b, + 0xf2, 0xdf, 0xce, 0xfa, 0x71, 0x39, 0x6e, 0x0d, 0xbd, 0x68, 0x04, 0x10, + 0x9c, 0x33, 0xa8, 0xef, 0x0c, 0x86, 0x67, 0xd9, 0x72, 0xc5, 0xd9, 0xf3, + 0xcf, 0xb5, 0xf8, 0xb7, 0x31, 0x36, 0xab, 0x68, 0xa2, 0xc6, 0xb9, 0xb4, + 0x5f, 0x7a, 0xbe, 0xa6, 0xb9, 0xb5, 0xe4, 0x4f, 0x7c, 0x74, 0x5f, 0xeb, + 0x3a, 0xfa, 0x43, 0x74, 0x0e, 0x9b, 0x98, 0xe6, 0x5e, 0x22, 0xcd, 0x4c, + 0x84, 0x18, 0x76, 0xef, 0x9a, 0x00, 0xf3, 0x94, 0xe8, 0x92, 0x7a, 0x2c, + 0x94, 0x64, 0x92, 0xba, 0xbc, 0xa7, 0x75, 0xee, 0x94, 0xd4, 0xe5, 0x4c, + 0x6b, 0xee, 0x94, 0x8e, 0x77, 0x58, 0x5b, 0x56, 0x24, 0x35, 0xe3, 0x9c, + 0x8a, 0x45, 0x5e, 0xa5, 0x2c, 0x1e, 0xfc, 0xca, 0xda, 0xa5, 0xc7, 0xe7, + 0x6f, 0x61, 0x3c, 0x55, 0x33, 0x37, 0x46, 0x98, 0xf3, 0xab, 0xe7, 0xa8, + 0x98, 0x39, 0xb7, 0x17, 0x15, 0x11, 0xf8, 0xe2, 0x3a, 0xde, 0x3d, 0x99, + 0xa0, 0x1e, 0xae, 0xd1, 0xdc, 0x47, 0xa8, 0xd5, 0xc7, 0x52, 0xf8, 0xc8, + 0x53, 0xf4, 0xc5, 0x51, 0xae, 0x5b, 0x36, 0x27, 0x3c, 0xcb, 0xf3, 0x61, + 0x3e, 0x7f, 0x7d, 0xed, 0x6a, 0xae, 0xfd, 0xd1, 0x29, 0xf1, 0xd7, 0x4c, + 0xeb, 0x85, 0x93, 0xce, 0xda, 0xf1, 0x64, 0x02, 0x1f, 0x9e, 0xd4, 0x06, + 0xde, 0x55, 0xb1, 0xde, 0x0b, 0x4a, 0xd6, 0x47, 0x5d, 0x15, 0xae, 0x58, + 0xc3, 0xf1, 0xf8, 0xe0, 0x2e, 0xd2, 0x6c, 0x59, 0x4b, 0xfd, 0xdb, 0x7c, + 0xd0, 0xe7, 0x99, 0x67, 0xbd, 0xe4, 0xc7, 0xe1, 0xa5, 0x8e, 0xb4, 0x4f, + 0x16, 0x7b, 0x35, 0xf6, 0xa9, 0xd7, 0xf9, 0x09, 0x53, 0x0f, 0xbe, 0x1d, + 0xcd, 0x01, 0xd4, 0xda, 0xcf, 0x85, 0xf8, 0x9c, 0xe8, 0xe1, 0xd7, 0xca, + 0xa5, 0xbf, 0xc7, 0x3c, 0x26, 0xb9, 0x24, 0xcc, 0x1c, 0xb6, 0x53, 0x7a, + 0xda, 0x6c, 0x96, 0xfe, 0xee, 0xa5, 0xbf, 0x6f, 0x14, 0x9f, 0x36, 0xe9, + 0xd3, 0x26, 0x7d, 0xda, 0xd4, 0x22, 0x03, 0x88, 0x85, 0xfa, 0x68, 0xb7, + 0x74, 0x44, 0x7c, 0xbd, 0x07, 0xbb, 0xf9, 0xd9, 0xc3, 0xfb, 0x87, 0xd9, + 0xe7, 0x62, 0x91, 0xac, 0x79, 0x10, 0xed, 0xe6, 0x23, 0xe8, 0x9f, 0xc0, + 0x6f, 0xfc, 0xcd, 0xe5, 0x28, 0x5f, 0x2e, 0x3d, 0xbc, 0x16, 0x3a, 0x8a, + 0x47, 0xd8, 0x47, 0xfd, 0x5a, 0x55, 0xea, 0x9e, 0xee, 0x63, 0x4a, 0x0b, + 0xb5, 0xb3, 0x1f, 0xde, 0x55, 0xd8, 0x49, 0xfb, 0xc6, 0xfa, 0x5f, 0x56, + 0xec, 0xa5, 0x6a, 0xb9, 0x36, 0x63, 0xe9, 0x0e, 0xae, 0x63, 0x0a, 0x1f, + 0x76, 0xbe, 0xfd, 0x7d, 0x88, 0x6e, 0x7f, 0xd2, 0xd0, 0xc7, 0xf5, 0x1d, + 0x3e, 0x86, 0xd9, 0x53, 0xf6, 0x31, 0xc6, 0x76, 0xdb, 0xf1, 0xd5, 0x43, + 0x1a, 0xd7, 0xf3, 0xd8, 0x86, 0x9c, 0xd4, 0x52, 0x0b, 0x8f, 0x1a, 0x16, + 0x9e, 0xe6, 0xe7, 0x22, 0x73, 0xd9, 0xc8, 0x0d, 0xb9, 0xcc, 0xc5, 0xe7, + 0x76, 0xf0, 0xb9, 0x16, 0xa6, 0xce, 0xd9, 0x69, 0x99, 0x0d, 0x1e, 0x94, + 0xd9, 0x20, 0xf2, 0xa6, 0xe8, 0x7e, 0x00, 0x17, 0x72, 0xb1, 0x41, 0xb7, + 0xdb, 0x1a, 0x62, 0x5c, 0x5d, 0xfc, 0x88, 0xbe, 0xfb, 0xda, 0x1a, 0xad, + 0x9b, 0x3a, 0x4c, 0x8c, 0x29, 0x2d, 0xf2, 0x33, 0xcc, 0x6f, 0xf2, 0xa1, + 0x31, 0xba, 0xd2, 0x1d, 0x0f, 0x9d, 0x85, 0x36, 0xdf, 0x47, 0x49, 0x9f, + 0x2c, 0x38, 0xb9, 0x6e, 0x5d, 0x31, 0xd7, 0xb5, 0xe4, 0x2b, 0xd4, 0x1d, + 0x13, 0xac, 0xcf, 0xd3, 0x56, 0x36, 0xc8, 0x7a, 0x55, 0x98, 0x16, 0xda, + 0x43, 0x68, 0x4c, 0x0a, 0x2d, 0xbd, 0x73, 0x4c, 0xe1, 0x1b, 0x95, 0x88, + 0xb3, 0x56, 0xc1, 0x28, 0xd7, 0xb3, 0x16, 0x6b, 0x52, 0xc8, 0x9b, 0x92, + 0xda, 0xd9, 0xc5, 0xbe, 0xa5, 0x87, 0x79, 0x51, 0x30, 0xb5, 0xcc, 0x4b, + 0x9d, 0x7c, 0xb4, 0xb1, 0x20, 0x76, 0x11, 0x9b, 0x88, 0x6d, 0x0e, 0xe2, + 0x1e, 0x53, 0x7a, 0x7f, 0x0b, 0xe3, 0x46, 0x3c, 0xfa, 0x14, 0xc4, 0x4e, + 0x07, 0xa9, 0x0b, 0x2f, 0x76, 0x33, 0x0f, 0xee, 0x6a, 0xa6, 0xae, 0x82, + 0x5e, 0xec, 0xb2, 0x67, 0x09, 0x25, 0xfd, 0x79, 0x69, 0x43, 0xc5, 0x1a, + 0x37, 0xeb, 0x75, 0xf4, 0xe8, 0xcc, 0x26, 0xdd, 0x29, 0xa1, 0x57, 0x9a, + 0x4b, 0x3a, 0xba, 0xdb, 0x94, 0x13, 0xba, 0x16, 0xce, 0x1a, 0x0e, 0x6e, + 0x2d, 0xe9, 0x2c, 0x42, 0xb9, 0x6a, 0xd6, 0x02, 0x2b, 0x6f, 0xc0, 0xae, + 0x15, 0xbc, 0xb6, 0xe5, 0x3a, 0x76, 0xcd, 0x08, 0x3e, 0x26, 0x76, 0xed, + 0xdc, 0x4a, 0xec, 0x5a, 0xaf, 0x4a, 0xb8, 0x55, 0xe6, 0x12, 0x25, 0xec, + 0x5a, 0x5d, 0xcc, 0xd1, 0x07, 0xb1, 0x8b, 0xb8, 0xa6, 0xb6, 0x7e, 0x08, + 0xbe, 0x55, 0xae, 0xcf, 0x5c, 0x18, 0x62, 0xbf, 0x52, 0x06, 0x2c, 0xb6, + 0x70, 0xcb, 0xea, 0xac, 0x55, 0xae, 0xd7, 0x47, 0xcb, 0x5d, 0x32, 0x77, + 0x8e, 0x67, 0x47, 0x98, 0x4b, 0x5c, 0xab, 0xb4, 0x6c, 0x1a, 0xbe, 0x50, + 0x8d, 0xbe, 0xb3, 0xd8, 0x2f, 0x44, 0x7c, 0x9b, 0x89, 0x7b, 0xe2, 0xc9, + 0x4f, 0xad, 0xa9, 0xb0, 0xd0, 0x98, 0x9f, 0xf7, 0x21, 0xfd, 0x90, 0x8f, + 0x75, 0x68, 0x41, 0x1d, 0xc1, 0x6b, 0xf1, 0x88, 0x6f, 0x5b, 0x21, 0xeb, + 0xdf, 0xd2, 0x70, 0x0b, 0xba, 0x4e, 0x49, 0xcd, 0x89, 0x62, 0xeb, 0xa9, + 0x76, 0xd6, 0x19, 0x1d, 0x1d, 0x63, 0x9d, 0xec, 0xe3, 0xba, 0x55, 0xf7, + 0xb4, 0xe8, 0x49, 0xf4, 0xac, 0x85, 0xa2, 0xae, 0x1b, 0xe7, 0xa2, 0xa5, + 0x9e, 0xf8, 0x3d, 0xdb, 0x87, 0x46, 0x8d, 0x10, 0xf5, 0xf3, 0x2b, 0x2f, + 0x82, 0x16, 0xce, 0x18, 0xe2, 0x7b, 0xfc, 0xdb, 0x4c, 0x63, 0x63, 0xf3, + 0xb8, 0xe5, 0xd1, 0x65, 0xbe, 0x1d, 0xb1, 0xed, 0xb6, 0x81, 0xb5, 0xac, + 0x7d, 0xba, 0x87, 0xb6, 0x2a, 0xcd, 0xb2, 0x6f, 0xb4, 0xd9, 0x7a, 0xff, + 0x46, 0xe6, 0x35, 0xf6, 0xe9, 0x3e, 0x1f, 0x73, 0xa5, 0xef, 0x94, 0x85, + 0x69, 0xe3, 0x4d, 0xeb, 0x51, 0xdd, 0x43, 0xbb, 0x7c, 0x95, 0x79, 0x57, + 0x70, 0x49, 0xca, 0x7f, 0xfb, 0xa4, 0xc7, 0x55, 0x95, 0x42, 0x73, 0x19, + 0x7d, 0xee, 0xd5, 0xa4, 0x33, 0x73, 0x3c, 0x96, 0xbf, 0xcd, 0xbf, 0x65, + 0x82, 0xbd, 0x04, 0x7b, 0x5d, 0xa7, 0xbf, 0xfb, 0xaa, 0xff, 0xee, 0x09, + 0xb7, 0xaa, 0x4d, 0xc1, 0xdd, 0xb2, 0xd6, 0xc2, 0xc7, 0xab, 0xe3, 0x83, + 0x11, 0x17, 0x73, 0x24, 0x69, 0x99, 0xf9, 0x66, 0x7f, 0x86, 0x39, 0x79, + 0xdb, 0x04, 0xd2, 0x32, 0x9f, 0x0d, 0xae, 0x1e, 0xee, 0x0d, 0x42, 0x66, + 0x69, 0xf8, 0x06, 0xa3, 0x32, 0x4c, 0x9f, 0x8b, 0xb4, 0xa9, 0xf8, 0x42, + 0x3f, 0xe2, 0x17, 0x3f, 0x76, 0xbf, 0x69, 0x3d, 0x9e, 0x5f, 0xcb, 0xe7, + 0x3b, 0x99, 0x2f, 0xd3, 0xcc, 0x9f, 0xc3, 0x83, 0x5e, 0xc8, 0x3b, 0x5a, + 0xe6, 0x0d, 0x15, 0xa3, 0xaf, 0xe3, 0x9b, 0x7c, 0x3e, 0xd4, 0xc1, 0x5c, + 0x39, 0x6d, 0xc4, 0xd3, 0x1b, 0x90, 0xed, 0xac, 0x86, 0x66, 0x34, 0x28, + 0x99, 0x7d, 0x89, 0x1d, 0x12, 0xf8, 0x39, 0xd7, 0xf4, 0xe8, 0xa2, 0xc7, + 0xf5, 0xe8, 0x9b, 0x66, 0xfd, 0xbf, 0xe6, 0x6f, 0xa2, 0x03, 0xd1, 0xcb, + 0x37, 0xcb, 0x50, 0xb1, 0x88, 0xb2, 0xfd, 0xdc, 0xce, 0x2b, 0x7e, 0x5d, + 0xc7, 0x7f, 0x26, 0x3e, 0xfa, 0x4f, 0x05, 0x99, 0x71, 0x96, 0x30, 0x9f, + 0xdd, 0x47, 0xb5, 0x2e, 0x9b, 0x4a, 0x14, 0x67, 0x9e, 0x3e, 0x7f, 0xe7, + 0xa4, 0x85, 0x93, 0x46, 0x10, 0xd2, 0xe3, 0x97, 0x27, 0xe7, 0x89, 0x00, + 0x9a, 0xd0, 0xc1, 0xeb, 0xed, 0x93, 0x95, 0xaa, 0x7d, 0xc2, 0xc2, 0x5f, + 0x18, 0x5a, 0xb6, 0xcd, 0xcd, 0x98, 0x36, 0xb4, 0xb3, 0xc0, 0x3b, 0xc4, + 0x4a, 0xe2, 0x63, 0x1e, 0x04, 0x74, 0x87, 0x56, 0xd3, 0xd4, 0x6d, 0xc4, + 0x0f, 0x12, 0x63, 0xee, 0x15, 0x15, 0x48, 0xaa, 0x29, 0x8f, 0xe8, 0xad, + 0x13, 0xe9, 0x42, 0xa5, 0xda, 0x4e, 0x5d, 0xde, 0xb1, 0xaa, 0x0c, 0x97, + 0x6c, 0x5d, 0xde, 0x46, 0x5d, 0xe2, 0xf5, 0xa5, 0x70, 0x5f, 0xa8, 0x45, + 0xa7, 0x82, 0xdd, 0x9f, 0x55, 0xb2, 0x4e, 0xa7, 0x89, 0x6f, 0x89, 0x07, + 0x43, 0x3d, 0xf8, 0x2e, 0xf3, 0xcd, 0xa3, 0xf4, 0xd5, 0x5f, 0xe9, 0x4d, + 0xa8, 0xf8, 0x5e, 0x33, 0xed, 0xb8, 0xd6, 0xbf, 0x79, 0x22, 0x83, 0xc7, + 0x66, 0x2d, 0x3c, 0xc5, 0x38, 0x69, 0x48, 0x66, 0x43, 0xe5, 0xec, 0xd7, + 0x58, 0xd3, 0x16, 0x4e, 0xd8, 0x7e, 0xbe, 0xab, 0x75, 0xfd, 0x4c, 0x04, + 0xee, 0xef, 0xca, 0xef, 0x3b, 0x5b, 0xa3, 0x33, 0xf2, 0x9d, 0xe1, 0xb7, + 0x85, 0x01, 0x43, 0x4b, 0x7f, 0xec, 0xae, 0x40, 0x65, 0xdc, 0xb2, 0x06, + 0x92, 0x72, 0xbd, 0xaf, 0x35, 0x61, 0xdf, 0xdf, 0xc3, 0xef, 0xd2, 0x4c, + 0xfa, 0x6f, 0x04, 0x0b, 0x46, 0xd3, 0x94, 0x79, 0x2b, 0xeb, 0x7b, 0x86, + 0xf5, 0xbd, 0x36, 0xa5, 0xa5, 0x77, 0xb8, 0x65, 0xfe, 0x32, 0x7f, 0xa0, + 0x9a, 0xd7, 0x6f, 0x2f, 0xd6, 0xf7, 0xaa, 0x53, 0x32, 0xd3, 0x23, 0x06, + 0x84, 0xb3, 0x17, 0xd2, 0xc5, 0xfa, 0x5e, 0x31, 0xe6, 0xc1, 0x16, 0xd6, + 0x76, 0x2f, 0xb1, 0xf8, 0xc6, 0x7c, 0x2d, 0xfc, 0x27, 0xdc, 0x88, 0x25, + 0x7f, 0x82, 0x03, 0xf4, 0xb1, 0x03, 0x09, 0xb7, 0x8a, 0x2e, 0x71, 0x51, + 0x4f, 0xff, 0x88, 0x7d, 0x21, 0x37, 0xaa, 0xf4, 0x9f, 0xe1, 0x81, 0x2f, + 0xa8, 0xe9, 0x99, 0x09, 0x89, 0xed, 0x5d, 0xad, 0x5b, 0x4e, 0x39, 0x35, + 0x3d, 0x70, 0x6a, 0x78, 0x41, 0x6a, 0x7a, 0xed, 0xea, 0x0c, 0x4e, 0x4f, + 0xe2, 0x3b, 0x4b, 0x09, 0x1e, 0x6b, 0xb9, 0x66, 0x7d, 0x32, 0xce, 0xde, + 0x5a, 0xeb, 0xef, 0x50, 0xf1, 0x23, 0x55, 0xcc, 0x01, 0xa7, 0x59, 0xd3, + 0x7d, 0xa9, 0x78, 0x28, 0xe1, 0x42, 0x97, 0x97, 0xf6, 0x78, 0x9f, 0x7d, + 0xf6, 0x5b, 0xf9, 0x28, 0x69, 0x96, 0xc1, 0xc3, 0x9a, 0xfe, 0xbe, 0x8e, + 0xcf, 0xdc, 0xf4, 0xbd, 0x77, 0xdc, 0x3e, 0x5c, 0xcd, 0x3b, 0x35, 0xbd, + 0xba, 0xc1, 0x1a, 0xba, 0x9c, 0x0c, 0xe0, 0x4a, 0xde, 0xa0, 0x0f, 0x66, + 0x70, 0x98, 0x35, 0xfd, 0xb2, 0x1e, 0xc2, 0x87, 0xf9, 0x16, 0xfa, 0x65, + 0x18, 0xbf, 0x24, 0xfe, 0x5d, 0xc5, 0x9a, 0x7e, 0x27, 0x7d, 0x2a, 0xc9, + 0x9a, 0xde, 0x66, 0xe3, 0x8d, 0x7d, 0xad, 0x67, 0xc6, 0xed, 0x9a, 0xde, + 0xe0, 0x62, 0x3d, 0xf4, 0x22, 0xbe, 0xc0, 0x3c, 0x61, 0xfd, 0x6a, 0x6d, + 0x80, 0xcf, 0x52, 0x6f, 0x85, 0xd5, 0x98, 0xb2, 0x6b, 0xd0, 0x7a, 0xff, + 0x76, 0xae, 0xbd, 0xd8, 0x8e, 0x33, 0x0b, 0x5b, 0x57, 0xbd, 0x86, 0x3f, + 0xaa, 0x71, 0xd1, 0x0f, 0x53, 0xfe, 0x3b, 0x18, 0x6b, 0xc1, 0x54, 0x69, + 0xe6, 0x91, 0xe0, 0x3a, 0xb7, 0xf9, 0xef, 0xa4, 0x6f, 0xdc, 0xb2, 0x8a, + 0x99, 0x24, 0xe4, 0xc4, 0x59, 0x3b, 0xe3, 0x2c, 0xc2, 0x38, 0x5b, 0xca, + 0x38, 0x7b, 0xdc, 0x88, 0x27, 0xd6, 0x13, 0x77, 0xbd, 0x9c, 0x97, 0x58, + 0x6b, 0x26, 0x5d, 0x8d, 0x72, 0x0d, 0xf7, 0x4a, 0xcc, 0x6c, 0x5d, 0x35, + 0x7c, 0xb6, 0x12, 0xa2, 0x2b, 0x7c, 0xb6, 0x98, 0x18, 0x83, 0x99, 0xe9, + 0xe2, 0x82, 0x3b, 0x3e, 0x78, 0xab, 0x3b, 0x3e, 0xf0, 0x9e, 0x7a, 0xd3, + 0x7a, 0x9d, 0x71, 0xb6, 0x8d, 0x71, 0xb6, 0x9d, 0x71, 0xd6, 0x66, 0x5a, + 0x78, 0x2e, 0xa9, 0x65, 0x9a, 0x5c, 0x31, 0xa3, 0xcd, 0x85, 0xa5, 0x95, + 0x2c, 0x0d, 0x7e, 0xc4, 0x3b, 0xff, 0x88, 0xfc, 0x5f, 0x34, 0xe2, 0xdd, + 0x09, 0x25, 0xb1, 0x15, 0xc5, 0x07, 0x94, 0xbb, 0xbc, 0x18, 0x5b, 0x7b, + 0xa7, 0xcf, 0x17, 0x7d, 0xa3, 0x24, 0xbb, 0x1b, 0xcf, 0x1a, 0xcc, 0xa5, + 0x8b, 0xb4, 0x68, 0xd6, 0xd5, 0x83, 0x23, 0xd4, 0xa3, 0x3f, 0xde, 0x83, + 0xa3, 0xac, 0x87, 0xf7, 0xb2, 0x0e, 0xdf, 0x67, 0xc6, 0x5a, 0x36, 0xb3, + 0xff, 0xb9, 0x14, 0xd1, 0xa2, 0x51, 0xd5, 0x83, 0x3e, 0xfa, 0x70, 0x1f, + 0xeb, 0x46, 0x9b, 0xf9, 0x6b, 0xd5, 0x41, 0xac, 0xb0, 0xa7, 0x20, 0xef, + 0x69, 0x89, 0x5e, 0x57, 0x3f, 0x7a, 0x67, 0x25, 0xb7, 0x21, 0x74, 0x53, + 0xaa, 0x07, 0xc7, 0xcd, 0x32, 0xf4, 0x34, 0x77, 0xa9, 0xdb, 0x0b, 0x32, + 0x7f, 0x63, 0x3c, 0x9a, 0x8c, 0x57, 0x9b, 0x5f, 0x85, 0x7c, 0xbc, 0x0b, + 0x39, 0x89, 0x4f, 0x73, 0xbb, 0xba, 0x73, 0x5a, 0x62, 0xbc, 0x47, 0xf5, + 0x48, 0x0c, 0x9b, 0x83, 0xea, 0x2e, 0x89, 0x69, 0x7b, 0x66, 0x2d, 0x71, + 0x2f, 0x7b, 0x1a, 0xb7, 0x11, 0xc7, 0x81, 0x31, 0xe5, 0xfe, 0x5e, 0x84, + 0x71, 0xd7, 0x56, 0xe6, 0xa2, 0x9f, 0xc6, 0x68, 0x3b, 0x17, 0xda, 0x8d, + 0xdf, 0xb1, 0xb2, 0xa1, 0x5e, 0xc6, 0x54, 0x0f, 0x0e, 0x9b, 0x5f, 0xb6, + 0x2e, 0xdb, 0xf8, 0xa4, 0x94, 0xd7, 0xd7, 0xe3, 0x9e, 0x89, 0x25, 0xf0, + 0xe9, 0x52, 0xb7, 0x03, 0x48, 0xd4, 0xf8, 0x50, 0xa1, 0x4b, 0xbd, 0xd9, + 0xd7, 0x3a, 0x77, 0x42, 0x49, 0xff, 0x51, 0x8c, 0xef, 0xf5, 0xb8, 0x9f, + 0x79, 0x60, 0x77, 0xf2, 0x1e, 0xdc, 0x17, 0xaa, 0x40, 0x90, 0x7a, 0xda, + 0x1f, 0x0a, 0x30, 0xbf, 0xfe, 0x7e, 0x91, 0xce, 0xb3, 0x65, 0xc5, 0xbe, + 0xfa, 0x1a, 0xb6, 0xaa, 0x65, 0x8c, 0xad, 0x9b, 0x94, 0x39, 0x51, 0xa6, + 0x35, 0x32, 0xa9, 0x23, 0xc8, 0x7e, 0x76, 0x7d, 0x52, 0x1b, 0x5c, 0xef, + 0x8e, 0x49, 0xaf, 0x92, 0x0b, 0x12, 0xd7, 0xe5, 0xe3, 0xf1, 0xee, 0x26, + 0xd1, 0xb1, 0x1e, 0xc1, 0x26, 0xea, 0x69, 0x4b, 0x3e, 0xcc, 0x18, 0x5a, + 0x28, 0x13, 0x8c, 0x94, 0xce, 0x5f, 0xa7, 0x15, 0x21, 0xad, 0xc8, 0xa4, + 0xe0, 0xb5, 0x0c, 0xf1, 0x9a, 0xce, 0x38, 0xb4, 0xac, 0x75, 0xc4, 0x69, + 0x81, 0x53, 0x32, 0x6f, 0x8a, 0x1d, 0x21, 0xb6, 0x6d, 0x22, 0xee, 0xed, + 0xa1, 0x57, 0x5b, 0xb7, 0xd4, 0xc7, 0x8d, 0x36, 0x85, 0x47, 0x66, 0x9a, + 0xe1, 0x73, 0x93, 0xe6, 0x3b, 0xf9, 0x10, 0x2e, 0xe7, 0x23, 0x78, 0x9b, + 0xb4, 0x2f, 0xd9, 0xb4, 0xeb, 0xf0, 0x8b, 0x62, 0xde, 0x4a, 0x32, 0x6f, + 0x6d, 0x98, 0x50, 0xf4, 0xd7, 0x28, 0x86, 0x8c, 0xbf, 0xfe, 0xec, 0xd2, + 0xcd, 0x3e, 0xea, 0x4d, 0x64, 0xf1, 0xf0, 0x7b, 0x14, 0xfb, 0xed, 0x3c, + 0xfd, 0xda, 0x67, 0x53, 0x35, 0xb4, 0x15, 0x75, 0x5f, 0x5d, 0x7c, 0x6f, + 0xe5, 0x54, 0xa1, 0x28, 0xaf, 0x0e, 0xd7, 0xa9, 0x04, 0xca, 0x4e, 0x5d, + 0xe3, 0x55, 0x97, 0xf8, 0x60, 0x65, 0x7d, 0xe4, 0xfb, 0x5c, 0xff, 0x21, + 0x62, 0x3e, 0x8b, 0xeb, 0x5f, 0xb5, 0xd7, 0x0d, 0x73, 0x5d, 0x75, 0x0d, + 0x1f, 0x46, 0xae, 0xbd, 0x13, 0xa2, 0xec, 0x78, 0x38, 0x42, 0xdd, 0x5d, + 0x59, 0x23, 0xcf, 0x05, 0x70, 0x7b, 0x7e, 0x55, 0xb9, 0xe4, 0x71, 0x3f, + 0xfb, 0x01, 0xc7, 0x97, 0x88, 0xf7, 0xcc, 0xe7, 0x79, 0x4f, 0xf0, 0xd7, + 0x7a, 0x62, 0x8d, 0xcf, 0xeb, 0x3d, 0x4c, 0x5b, 0x94, 0xd1, 0x78, 0x72, + 0xef, 0x8b, 0xea, 0xe8, 0x9f, 0x61, 0x90, 0xbd, 0xd0, 0x43, 0x13, 0x59, + 0xec, 0x9f, 0xf8, 0x63, 0x7b, 0x8f, 0x6e, 0xe5, 0x6a, 0xec, 0xe1, 0x9a, + 0xfb, 0xaa, 0x19, 0x47, 0xff, 0x2d, 0x19, 0x17, 0x8c, 0xb4, 0xbd, 0x12, + 0x52, 0x6b, 0xe3, 0x2d, 0xb7, 0x2a, 0x0b, 0x65, 0x49, 0x0c, 0xb4, 0x37, + 0xc7, 0x13, 0x97, 0xf1, 0x88, 0x25, 0xf3, 0x6e, 0x77, 0xb1, 0xee, 0x12, + 0x97, 0xaa, 0x76, 0xd6, 0xde, 0xb6, 0x22, 0x56, 0xda, 0x50, 0x78, 0xf3, + 0x73, 0x33, 0x05, 0xe9, 0xc7, 0xa5, 0xde, 0xf8, 0x55, 0x1b, 0xd7, 0x39, + 0xcc, 0x9c, 0xfd, 0xac, 0xf1, 0x62, 0x84, 0xd5, 0x18, 0x9e, 0x55, 0x0a, + 0x07, 0x0c, 0x2f, 0xb2, 0x61, 0x0b, 0xdb, 0xf9, 0xbd, 0x97, 0xf8, 0xe9, + 0x5d, 0xa3, 0x0a, 0x53, 0xa1, 0x10, 0x31, 0x23, 0x73, 0xb0, 0xeb, 0xff, + 0x78, 0x65, 0x5f, 0x27, 0xea, 0x92, 0x3d, 0xf8, 0x7f, 0x6d, 0x5f, 0x66, + 0x15, 0xf1, 0x8b, 0xc8, 0xee, 0x57, 0xcc, 0xa1, 0x09, 0x10, 0xd3, 0xec, + 0x32, 0xe6, 0xa3, 0x2e, 0xa4, 0xaf, 0xba, 0xa0, 0x9d, 0x7e, 0x87, 0x7d, + 0xde, 0x43, 0xf5, 0xda, 0xe9, 0x56, 0xb7, 0x8e, 0xc1, 0xe3, 0x3e, 0x3c, + 0x78, 0xbc, 0x03, 0xd5, 0xf6, 0x7c, 0x68, 0x94, 0x3a, 0x75, 0xb1, 0xbf, + 0x1a, 0xfe, 0xd4, 0xc3, 0x3e, 0xeb, 0xea, 0xea, 0x87, 0xd1, 0x62, 0x5f, + 0x1f, 0xc1, 0x9e, 0x09, 0xbf, 0xda, 0x32, 0xe1, 0x41, 0xc7, 0x9d, 0x0f, + 0xc3, 0xbb, 0xaa, 0x97, 0x7c, 0xc9, 0x75, 0xf9, 0xfd, 0x2e, 0xf6, 0x67, + 0xc2, 0x5f, 0x19, 0xa2, 0x4b, 0xc8, 0xdb, 0x2a, 0x1d, 0x43, 0xc7, 0x3d, + 0x6a, 0x87, 0xf9, 0x37, 0xd6, 0x55, 0x7b, 0xcf, 0x47, 0xae, 0x55, 0xc8, + 0x59, 0x00, 0x3e, 0x23, 0x39, 0xa7, 0x0f, 0x13, 0x8c, 0xed, 0xbb, 0xec, + 0xf7, 0x8f, 0x97, 0x39, 0x32, 0xa5, 0xd9, 0xb7, 0xb6, 0xd3, 0x7e, 0xf2, + 0x4c, 0x6b, 0xf1, 0xda, 0x7a, 0x9f, 0x73, 0xde, 0x40, 0x7c, 0xa1, 0x0f, + 0xcb, 0x68, 0x84, 0xfa, 0xb8, 0x5d, 0xa7, 0x50, 0x9f, 0x67, 0x42, 0x5d, + 0xe2, 0xf0, 0xfb, 0x80, 0x39, 0xcf, 0x9e, 0x53, 0x67, 0xde, 0xa4, 0xee, + 0x16, 0xcb, 0xfb, 0x55, 0xbe, 0xdf, 0x7e, 0x5f, 0xf2, 0x2d, 0xb1, 0x66, + 0x50, 0x30, 0xe7, 0x17, 0xdd, 0xff, 0x5d, 0xc8, 0x3d, 0x8f, 0xfe, 0xa7, + 0x8c, 0xe3, 0x78, 0x77, 0xa5, 0x4b, 0xfc, 0xe7, 0x4f, 0x71, 0xdf, 0xf4, + 0x30, 0xef, 0x0b, 0xfd, 0x83, 0xec, 0x25, 0x3c, 0xaa, 0x93, 0xf9, 0x67, + 0xef, 0x71, 0xd7, 0xed, 0x65, 0xf8, 0x4b, 0xab, 0x7c, 0xf1, 0x10, 0xea, + 0x93, 0x23, 0x7c, 0x5e, 0xa1, 0x9d, 0xb8, 0xf1, 0x31, 0x63, 0x03, 0x3a, + 0x6a, 0x24, 0x07, 0x3c, 0x6b, 0xf5, 0xf5, 0x88, 0x0e, 0x15, 0x36, 0xf2, + 0xfa, 0x73, 0xb4, 0xef, 0x93, 0x86, 0x07, 0xf5, 0x8b, 0x64, 0xd6, 0xa7, + 0x8d, 0xa7, 0xf1, 0x75, 0x9f, 0xb3, 0xf7, 0x95, 0xb5, 0xaa, 0x75, 0x7d, + 0xe0, 0x0e, 0x57, 0xfd, 0xf8, 0x1b, 0xf4, 0xa7, 0xb6, 0x55, 0x37, 0xde, + 0x2b, 0xe9, 0xc4, 0x40, 0x64, 0xd5, 0x33, 0x16, 0x6e, 0x1a, 0x46, 0x68, + 0xd5, 0x8d, 0xf6, 0x2f, 0xf1, 0x7d, 0x90, 0x31, 0x88, 0x6c, 0x75, 0x4a, + 0xe6, 0x3f, 0x71, 0xd2, 0x39, 0x88, 0x3f, 0x2c, 0x8c, 0xe0, 0xc0, 0x44, + 0x11, 0x5b, 0xd3, 0xb7, 0xf5, 0x55, 0xd7, 0x65, 0x7b, 0x60, 0x22, 0xde, + 0x5b, 0x55, 0x94, 0x6d, 0x1f, 0xfb, 0x8c, 0x4a, 0xe6, 0xd8, 0xfb, 0xa9, + 0xd3, 0x01, 0x5b, 0xa7, 0x3d, 0x30, 0xf2, 0xd7, 0xe9, 0xf6, 0x93, 0xae, + 0x3f, 0x25, 0x7a, 0x93, 0xfd, 0xb6, 0x83, 0xd8, 0x4b, 0xba, 0xbb, 0x6f, + 0xa0, 0xdb, 0x67, 0x5c, 0xa7, 0xbb, 0x6b, 0x22, 0x7e, 0xda, 0x55, 0xa4, + 0xfb, 0xed, 0xe9, 0x12, 0x8d, 0x2c, 0xb6, 0xad, 0xca, 0x22, 0xbf, 0x6e, + 0x9f, 0xb5, 0xcf, 0xd6, 0xc7, 0x59, 0xfb, 0xfa, 0xc6, 0x7a, 0x89, 0x07, + 0xfe, 0x9a, 0xd2, 0xed, 0xbd, 0x7d, 0x07, 0x7b, 0xdd, 0x18, 0x1f, 0xda, + 0x9b, 0x5b, 0xdc, 0x69, 0xc6, 0x76, 0xd8, 0xb7, 0xf9, 0x73, 0x33, 0x8d, + 0x0e, 0xf6, 0x61, 0x9b, 0xcc, 0x2e, 0x7f, 0xa7, 0xe9, 0x23, 0xee, 0xaa, + 0x54, 0x1b, 0x27, 0x64, 0xb6, 0x21, 0xb1, 0x5c, 0xc4, 0xc2, 0x05, 0xe9, + 0xf7, 0x76, 0xb2, 0x4f, 0x58, 0x46, 0xfb, 0xf6, 0xe2, 0x48, 0xa1, 0x57, + 0xa5, 0xc3, 0x5c, 0xc7, 0x94, 0xba, 0x02, 0xd6, 0xbc, 0x6e, 0x54, 0xd2, + 0x97, 0xc2, 0xa9, 0x81, 0xd4, 0xc9, 0x7a, 0x0b, 0xc4, 0x28, 0xbe, 0x45, + 0xa9, 0x6c, 0x6a, 0x7b, 0xbd, 0x1b, 0xc7, 0x6c, 0xfc, 0xa5, 0x4d, 0xf1, + 0x33, 0x2e, 0x31, 0x73, 0xc7, 0x84, 0xd4, 0x31, 0x42, 0x48, 0x7d, 0x08, + 0xff, 0x90, 0x9c, 0x1f, 0xa8, 0x41, 0xfa, 0xde, 0x1a, 0x48, 0x5f, 0x71, + 0x04, 0x3f, 0xd2, 0x23, 0xbe, 0x4c, 0xc1, 0xa3, 0xb6, 0x98, 0x33, 0xfe, + 0xad, 0x66, 0x10, 0x01, 0xf6, 0x65, 0x5d, 0xee, 0x18, 0xfb, 0x0c, 0xd1, + 0x63, 0x67, 0xeb, 0xb2, 0x7c, 0xc6, 0xdf, 0x6e, 0x3a, 0xb9, 0xf0, 0x96, + 0x29, 0x9f, 0xbf, 0x63, 0x32, 0x16, 0x39, 0x62, 0x63, 0xb1, 0xae, 0xd6, + 0x58, 0xde, 0xb2, 0x5e, 0x31, 0xe6, 0xaf, 0x96, 0x3b, 0x3d, 0x48, 0x6b, + 0x22, 0xdf, 0x84, 0xbb, 0x89, 0x9f, 0xda, 0x26, 0x9b, 0x60, 0x4c, 0x02, + 0x27, 0x8e, 0x47, 0xb0, 0x72, 0x42, 0x3b, 0x3d, 0xe8, 0xce, 0x60, 0x7c, + 0xb6, 0x13, 0x13, 0x05, 0xff, 0x42, 0xd4, 0x45, 0x5c, 0x9d, 0x74, 0xe1, + 0x76, 0x63, 0xb5, 0x9a, 0xb7, 0x63, 0x5a, 0xe1, 0x2e, 0x63, 0xbb, 0xea, + 0xb5, 0x31, 0xc5, 0x0c, 0xb1, 0x88, 0xc2, 0x4d, 0xce, 0x5c, 0xbe, 0x35, + 0x49, 0xcc, 0x7d, 0xfb, 0x84, 0xd4, 0x77, 0x0b, 0xaf, 0x26, 0xa9, 0x97, + 0x64, 0x36, 0xe3, 0x65, 0x0f, 0xb4, 0x4f, 0x69, 0xdd, 0x86, 0x72, 0x30, + 0xde, 0xad, 0x33, 0x0e, 0x2e, 0x5c, 0x36, 0xd3, 0xec, 0x97, 0x1c, 0xd4, + 0x6e, 0x68, 0x11, 0x8f, 0x2b, 0x84, 0x01, 0x9b, 0x46, 0x6f, 0xab, 0x31, + 0x53, 0x86, 0xa5, 0x7a, 0x0f, 0x4e, 0xdb, 0x32, 0xf4, 0xb7, 0xae, 0x27, + 0xbe, 0x7e, 0xdc, 0xcc, 0xb0, 0x07, 0x96, 0xfd, 0xd0, 0x58, 0xa2, 0xc5, + 0xdd, 0x46, 0x0c, 0x1b, 0x8b, 0x2e, 0xa8, 0xb4, 0xca, 0x7a, 0x1a, 0xd3, + 0x33, 0x60, 0x45, 0xa9, 0x71, 0xea, 0x9b, 0xc8, 0x18, 0x27, 0xce, 0x6a, + 0x3b, 0xee, 0x5f, 0x48, 0xc3, 0x99, 0xdf, 0x6c, 0x32, 0xfe, 0x37, 0x2e, + 0x85, 0xb5, 0x23, 0x69, 0xf2, 0xdd, 0xc1, 0xbc, 0x3b, 0xdf, 0xe3, 0xe1, + 0x7d, 0x99, 0xdb, 0x75, 0xb7, 0x8e, 0xe6, 0x30, 0xef, 0x4e, 0x49, 0x5f, + 0x85, 0x60, 0x77, 0x01, 0x32, 0x43, 0x62, 0x6f, 0xf1, 0xa9, 0x55, 0xda, + 0x3b, 0xea, 0x9a, 0x74, 0xf6, 0xc5, 0x72, 0xb3, 0x9e, 0xe0, 0x56, 0xb3, + 0x19, 0xc7, 0x0a, 0x9e, 0x1b, 0x68, 0xc7, 0x8f, 0xdc, 0xe2, 0x72, 0x21, + 0xbe, 0xea, 0x2e, 0x55, 0xdc, 0x5b, 0x62, 0x9e, 0xc8, 0xd8, 0x35, 0xb1, + 0x8c, 0x72, 0x5e, 0x38, 0x29, 0x6b, 0x7c, 0xab, 0x75, 0xf4, 0xa4, 0xd4, + 0xc8, 0xee, 0xd6, 0x88, 0xa9, 0x75, 0x4b, 0x1f, 0x58, 0x4d, 0x3d, 0x7d, + 0x34, 0x26, 0x35, 0x78, 0x3f, 0x6b, 0xb0, 0xb6, 0xd0, 0xae, 0xa4, 0x8e, + 0x69, 0x09, 0xbf, 0xdb, 0x85, 0x2b, 0x0d, 0x5a, 0xe6, 0x79, 0x68, 0xbd, + 0xce, 0xbc, 0x70, 0x67, 0x6b, 0x63, 0x11, 0x0f, 0xdf, 0x3a, 0xd3, 0x27, + 0xe7, 0x49, 0x6c, 0x1d, 0x37, 0xe5, 0x05, 0x1b, 0x5b, 0xd6, 0x4b, 0xc9, + 0x2e, 0xe2, 0x06, 0xc1, 0xc6, 0x72, 0xfd, 0x81, 0xd6, 0x86, 0x29, 0x1f, + 0x79, 0x53, 0x78, 0x8f, 0x75, 0xe9, 0x48, 0xa1, 0xc4, 0xa3, 0x83, 0x9b, + 0x37, 0x13, 0x37, 0xbb, 0x53, 0x5a, 0xcb, 0x06, 0xe2, 0x66, 0x9d, 0x3d, + 0x84, 0x07, 0x3d, 0x78, 0xcc, 0x74, 0xfa, 0x08, 0xc1, 0xce, 0xd6, 0x49, + 0x2d, 0x2d, 0xb8, 0xf9, 0xea, 0x6a, 0x60, 0x07, 0x71, 0xf3, 0x42, 0xce, + 0x83, 0x0c, 0x71, 0xf3, 0x47, 0x39, 0x1f, 0xee, 0x20, 0x6e, 0xbe, 0x42, + 0x8c, 0x75, 0x3e, 0xf9, 0x4b, 0x7c, 0xbb, 0x38, 0x13, 0xdb, 0x95, 0xf0, + 0xd1, 0xb7, 0x05, 0x3b, 0xff, 0xa6, 0x88, 0x9d, 0xff, 0xcb, 0x3f, 0xc3, + 0xce, 0x77, 0x13, 0x13, 0x76, 0x4d, 0xc8, 0xfe, 0xd1, 0xae, 0xd6, 0xd7, + 0x4f, 0xc9, 0x99, 0x95, 0x5b, 0xf1, 0xee, 0xc9, 0xe1, 0x7e, 0x62, 0x65, + 0x8c, 0x24, 0x33, 0xc8, 0x4d, 0x62, 0x09, 0x71, 0xc1, 0x4b, 0x6e, 0xae, + 0xbb, 0x32, 0xa9, 0x19, 0x6f, 0xa8, 0x78, 0x67, 0x06, 0x71, 0xf6, 0xca, + 0xda, 0x02, 0x4d, 0x98, 0xf6, 0xa4, 0x88, 0x8d, 0x59, 0x03, 0x97, 0x12, + 0x3b, 0x57, 0xcd, 0x01, 0xb5, 0x73, 0x0e, 0x76, 0x96, 0x79, 0x58, 0x55, + 0x1c, 0x7f, 0x46, 0xec, 0xcc, 0xfe, 0x96, 0xa1, 0x36, 0xd7, 0xc4, 0x18, + 0x55, 0x38, 0x1c, 0x0f, 0xa0, 0xeb, 0x38, 0x71, 0x8f, 0x3d, 0x0f, 0xb3, + 0x86, 0x7e, 0x6a, 0x64, 0x70, 0x74, 0xd6, 0x99, 0x87, 0x6d, 0x22, 0x7e, + 0xf3, 0xc4, 0xc3, 0x28, 0x9f, 0xf3, 0xe0, 0x19, 0xe2, 0xe7, 0x8d, 0xb4, + 0xf3, 0x19, 0xe2, 0xe7, 0xbb, 0x6f, 0x98, 0x89, 0x4d, 0xcd, 0xe1, 0x15, + 0x62, 0xf9, 0xba, 0x5a, 0xc4, 0x65, 0xde, 0x61, 0x5d, 0x59, 0x13, 0xc0, + 0x39, 0x1b, 0x3f, 0xfb, 0x17, 0xb2, 0xca, 0x91, 0xad, 0x8c, 0xb6, 0x10, + 0xbb, 0xba, 0x68, 0xd7, 0xb6, 0x93, 0x5a, 0xe7, 0x8b, 0xd4, 0x45, 0x63, + 0xfc, 0xbc, 0x6d, 0x8f, 0xbe, 0xa4, 0xcc, 0x4e, 0x3a, 0x5b, 0xe5, 0x5c, + 0x55, 0x05, 0xed, 0xbd, 0x65, 0x2c, 0x96, 0xfe, 0x00, 0x4e, 0x4c, 0x26, + 0xf2, 0x65, 0xc5, 0x7a, 0x28, 0xf7, 0xfa, 0x79, 0x2f, 0x8d, 0xce, 0x35, + 0x8e, 0x7f, 0x27, 0xf2, 0xc7, 0x88, 0x5d, 0x65, 0xcf, 0x34, 0x14, 0xdc, + 0x64, 0x76, 0x62, 0xdc, 0x8c, 0xa2, 0xfc, 0x5c, 0x71, 0xef, 0xf5, 0x9c, + 0x9c, 0xc5, 0xdb, 0xd9, 0x1a, 0xfa, 0x5e, 0x09, 0x13, 0xa6, 0x89, 0xef, + 0xc2, 0xbe, 0xdb, 0x0b, 0x82, 0x17, 0xbb, 0x71, 0xd4, 0xd4, 0x22, 0x3f, + 0x67, 0x4c, 0xdc, 0x2b, 0xfb, 0xee, 0x37, 0xcc, 0x9e, 0x1e, 0xe4, 0x3d, + 0xf3, 0x73, 0xb3, 0xa7, 0xc1, 0x09, 0xfc, 0xc6, 0xdd, 0x5c, 0x0e, 0xd7, + 0x4a, 0x2f, 0x31, 0xbd, 0x16, 0x19, 0xc1, 0x23, 0xc4, 0x1c, 0xbf, 0x56, + 0x01, 0xdd, 0xd3, 0xdf, 0xe4, 0xd6, 0x22, 0x33, 0x2a, 0xc0, 0x77, 0x77, + 0x32, 0xbf, 0xed, 0xa4, 0x6f, 0xc4, 0x16, 0x2a, 0x94, 0x1b, 0x97, 0xbe, + 0x6c, 0xe3, 0x51, 0x7f, 0x37, 0xaf, 0x8d, 0x17, 0x4a, 0xb8, 0xa6, 0x47, + 0x78, 0xc5, 0xa6, 0xe3, 0x4e, 0x0e, 0xd1, 0xf3, 0xfe, 0x85, 0x4b, 0x70, + 0x64, 0xab, 0xa4, 0xac, 0xf7, 0x8f, 0x85, 0xac, 0xde, 0xc5, 0x12, 0xc3, + 0x3a, 0xb6, 0x99, 0xe2, 0x5f, 0x7d, 0xe4, 0xb3, 0x07, 0x87, 0xcc, 0xa5, + 0xec, 0xdd, 0x64, 0x0e, 0xda, 0x44, 0x6c, 0xdd, 0xcd, 0x1a, 0x6c, 0x59, + 0x83, 0x46, 0xd6, 0x6a, 0x5a, 0xab, 0x1b, 0x79, 0x35, 0x5f, 0x13, 0x21, + 0xbe, 0x59, 0xc5, 0xda, 0xdd, 0x56, 0x68, 0xc2, 0x1b, 0x67, 0x74, 0xfa, + 0x66, 0x3b, 0xf1, 0x7b, 0x37, 0xee, 0xa1, 0x3c, 0xdf, 0x2e, 0x7c, 0x07, + 0xe9, 0x6f, 0x78, 0x70, 0xe4, 0x78, 0x1a, 0xeb, 0x57, 0x0d, 0xe1, 0xd2, + 0x37, 0x7d, 0xcc, 0x55, 0x01, 0x3c, 0x7e, 0x5c, 0xf2, 0x6b, 0x09, 0x6f, + 0xdf, 0x88, 0x45, 0x7c, 0x88, 0xda, 0x38, 0xe4, 0x8b, 0xef, 0x39, 0x18, + 0xc5, 0xcf, 0xfe, 0xb7, 0xf4, 0x3e, 0xf3, 0xd0, 0xaa, 0x7f, 0x86, 0x67, + 0x88, 0x5b, 0x88, 0x05, 0x2a, 0x12, 0xf6, 0xb9, 0xb7, 0x12, 0xde, 0xf5, + 0xd0, 0x07, 0x24, 0xa6, 0x97, 0x32, 0xd6, 0x2d, 0x62, 0xe7, 0x85, 0xe2, + 0x5c, 0xf2, 0xed, 0x93, 0xda, 0xc5, 0x43, 0x88, 0x11, 0x43, 0xa3, 0x4f, + 0xb0, 0x9b, 0x9b, 0x78, 0xf7, 0x4a, 0x3c, 0x6e, 0x9c, 0x23, 0xde, 0x1d, + 0xa6, 0xad, 0x3d, 0xba, 0xf8, 0x66, 0x08, 0x65, 0x73, 0x11, 0xfa, 0xa4, + 0xcc, 0x25, 0x5f, 0xf1, 0x3b, 0x73, 0x49, 0x99, 0x85, 0xcb, 0xb9, 0x10, + 0x74, 0x94, 0xb1, 0x77, 0x2b, 0x57, 0x59, 0xe6, 0xe4, 0x29, 0xff, 0x0e, + 0xe6, 0xf7, 0x8c, 0x19, 0x0e, 0xee, 0x28, 0x84, 0xf8, 0xa9, 0x0b, 0x66, + 0x0a, 0xbf, 0xc7, 0xe7, 0x23, 0xfc, 0x8e, 0x62, 0x22, 0x5f, 0x5b, 0x21, + 0xcd, 0xc0, 0x44, 0xde, 0xc9, 0x79, 0xd1, 0xfc, 0x5e, 0xbf, 0x60, 0xcd, + 0xb6, 0xe3, 0xce, 0xdf, 0xfa, 0x0d, 0x7f, 0x7f, 0x1e, 0xf3, 0x7b, 0xc9, + 0xf7, 0x99, 0x93, 0x3a, 0x3e, 0x3a, 0x69, 0x63, 0xfe, 0x79, 0x62, 0xfe, + 0x01, 0xaf, 0x5b, 0xb0, 0xe6, 0xaf, 0xac, 0xf3, 0xf1, 0x78, 0xef, 0x34, + 0xfd, 0xa0, 0x8b, 0x74, 0x5d, 0x7a, 0xd8, 0xe6, 0xd7, 0xe1, 0xd3, 0x99, + 0xe5, 0x5e, 0x3e, 0x99, 0xc0, 0x3b, 0xd7, 0x67, 0xa7, 0x9f, 0x94, 0xd9, + 0x33, 0x60, 0x3c, 0xf2, 0xee, 0x5a, 0xf8, 0x5a, 0xd8, 0x6f, 0x7a, 0xf9, + 0x7c, 0xc4, 0x7e, 0x5e, 0x66, 0xb9, 0x9f, 0x7c, 0x56, 0xc2, 0xd3, 0x1f, + 0x5d, 0x7f, 0xe7, 0x20, 0x3b, 0x35, 0xdf, 0x79, 0xc6, 0x96, 0xdb, 0x7e, + 0x4e, 0xe6, 0xad, 0xfe, 0x05, 0xd8, 0xf1, 0xf5, 0xfb, 0x94, 0x49, 0xec, + 0x7b, 0xc0, 0x72, 0xfc, 0x36, 0x1c, 0xdc, 0xc6, 0x78, 0xf8, 0x2e, 0xed, + 0xb3, 0xed, 0x5c, 0x5d, 0xf0, 0x2e, 0xb3, 0xd3, 0x96, 0xf9, 0xae, 0x73, + 0x52, 0x93, 0xe4, 0xfe, 0x1f, 0x54, 0x08, 0x1e, 0x7f, 0x9c, 0x35, 0x6b, + 0xd8, 0x94, 0xd9, 0x3e, 0x94, 0x27, 0x75, 0x08, 0x9b, 0xc6, 0xa3, 0x78, + 0xdb, 0xf0, 0x17, 0xcf, 0xb0, 0x48, 0x4c, 0x0e, 0x30, 0x26, 0xc3, 0x18, + 0x31, 0x63, 0xd1, 0xb7, 0x89, 0x4f, 0xb3, 0x64, 0xf8, 0xe8, 0x84, 0x1b, + 0x6f, 0x13, 0x33, 0x42, 0x39, 0x67, 0x40, 0x9d, 0x77, 0x4b, 0xbf, 0x57, + 0x22, 0x5a, 0x13, 0x6b, 0xd9, 0x8b, 0x3a, 0xe4, 0x98, 0xf3, 0xfd, 0xfa, + 0x8f, 0x71, 0xec, 0x84, 0x0b, 0xf7, 0xb1, 0xef, 0x4b, 0xdf, 0x69, 0xf0, + 0xef, 0xc6, 0xfe, 0xf7, 0xf1, 0x0f, 0xd6, 0x94, 0x9c, 0xb3, 0x52, 0x72, + 0x96, 0xe3, 0x13, 0xab, 0x56, 0xd7, 0xe7, 0x9f, 0x87, 0x3e, 0x78, 0x15, + 0x8d, 0x03, 0x0b, 0xf8, 0xc0, 0x9a, 0xe7, 0xbd, 0xf7, 0x18, 0x3f, 0x2f, + 0x1a, 0xb1, 0x88, 0x8b, 0xc2, 0xcc, 0x87, 0xdd, 0xb8, 0xd7, 0x90, 0x7d, + 0x26, 0x6d, 0xe0, 0x69, 0x68, 0xfd, 0x17, 0x94, 0x9c, 0xcd, 0xb9, 0x64, + 0x65, 0x6b, 0x64, 0x5d, 0x85, 0x95, 0xcb, 0x1b, 0x3b, 0xcb, 0xa0, 0xb5, + 0x78, 0x95, 0x6e, 0xbc, 0xaf, 0xfe, 0xa7, 0x35, 0x1f, 0xfe, 0xc4, 0x7a, + 0x47, 0x2f, 0xd1, 0xd5, 0xa2, 0x3e, 0x77, 0x89, 0xb7, 0x3a, 0x1c, 0x33, + 0x65, 0x7f, 0xee, 0xc7, 0xb8, 0xef, 0x84, 0x07, 0xed, 0xc9, 0x5f, 0x5a, + 0xd9, 0xb0, 0xd0, 0x0c, 0x56, 0xa2, 0x42, 0xe8, 0x3b, 0x33, 0xeb, 0x17, + 0x0a, 0x50, 0x1d, 0xa6, 0xe0, 0x65, 0xf1, 0xd3, 0x71, 0x58, 0xa6, 0xcc, + 0x11, 0x2d, 0xdc, 0x91, 0x1c, 0xc2, 0x7b, 0xc9, 0xf4, 0x1f, 0xf8, 0xa0, + 0x5d, 0xbc, 0xec, 0xd6, 0xe6, 0x9b, 0xdc, 0x51, 0xe5, 0x6f, 0xd0, 0x07, + 0x1a, 0xec, 0x7a, 0x93, 0x67, 0xef, 0x14, 0x60, 0x6e, 0x91, 0x1e, 0x73, + 0x1c, 0x73, 0x63, 0x59, 0x78, 0x88, 0xed, 0x86, 0x9b, 0xb5, 0xcc, 0x53, + 0x4a, 0x8b, 0xec, 0x53, 0x51, 0x75, 0x8f, 0x3e, 0x88, 0x67, 0x8c, 0x78, + 0xba, 0x4d, 0xd5, 0xf9, 0x3a, 0x0b, 0x25, 0xda, 0xed, 0xc4, 0x2a, 0xda, + 0xfc, 0x65, 0x77, 0x39, 0x6a, 0x57, 0xeb, 0x9d, 0xe5, 0x6e, 0x6d, 0xf0, + 0x6b, 0x8c, 0xaf, 0xcd, 0x85, 0x79, 0xff, 0xfb, 0x71, 0x17, 0x56, 0xd8, + 0xfb, 0x08, 0xb9, 0xe2, 0x8c, 0x74, 0x1c, 0x5b, 0xc6, 0xac, 0xf5, 0xaf, + 0x26, 0xb5, 0xc8, 0x53, 0x2a, 0xbb, 0x23, 0x40, 0x4c, 0x73, 0x3f, 0xf4, + 0xe8, 0x2c, 0xeb, 0x54, 0x7b, 0xc1, 0x85, 0x5b, 0x4e, 0x09, 0xcd, 0x1c, + 0x69, 0x1e, 0x42, 0xf9, 0x09, 0x6b, 0xfd, 0x0e, 0x43, 0x1b, 0xbc, 0xec, + 0xce, 0xfe, 0xd7, 0x5a, 0xea, 0xad, 0x43, 0xc9, 0x3e, 0xda, 0x10, 0x71, + 0xc5, 0x90, 0x9c, 0x87, 0x4b, 0xfc, 0x39, 0x31, 0xc5, 0x1f, 0xd3, 0x57, + 0xdd, 0xa9, 0x20, 0xf9, 0xd4, 0x12, 0xd3, 0x90, 0xf9, 0x79, 0x14, 0x97, + 0x8d, 0xac, 0x7f, 0x53, 0x43, 0x82, 0xd8, 0x2c, 0xc2, 0x3a, 0x18, 0xc5, + 0x51, 0x62, 0xbc, 0x43, 0x6c, 0x09, 0xe7, 0x43, 0x3a, 0xb1, 0x59, 0x37, + 0x5c, 0x63, 0x01, 0x35, 0x93, 0x8b, 0x19, 0xed, 0xf8, 0xf7, 0x98, 0x8f, + 0x88, 0x8b, 0x1c, 0x42, 0xe0, 0xc4, 0xdf, 0x59, 0x55, 0xba, 0xde, 0x32, + 0xa6, 0xb8, 0xee, 0x13, 0x11, 0xea, 0x98, 0xef, 0xc9, 0xb9, 0x15, 0xb3, + 0x0b, 0xf7, 0x8c, 0x85, 0xf9, 0x7e, 0x15, 0x56, 0x9e, 0x88, 0xe2, 0x4a, + 0xf2, 0x66, 0xcc, 0xd7, 0x38, 0x18, 0xc8, 0xaf, 0xd3, 0x8f, 0xd8, 0x67, + 0x65, 0x0b, 0xba, 0xbd, 0x77, 0x74, 0xc8, 0x94, 0xfe, 0xdc, 0xc3, 0xbf, + 0x03, 0xfc, 0x88, 0x3e, 0xbf, 0x55, 0xc4, 0x3a, 0xfb, 0x5b, 0xa3, 0x33, + 0x6f, 0x55, 0xd8, 0x7b, 0x9a, 0x88, 0xf2, 0xb9, 0x90, 0x3d, 0x17, 0x1c, + 0x26, 0xcd, 0xb3, 0xe3, 0xd2, 0xb7, 0xb5, 0xad, 0xf3, 0x15, 0xf7, 0xdf, + 0xdf, 0x32, 0x5c, 0x58, 0xcf, 0xde, 0x3e, 0xa2, 0x4b, 0xbd, 0x1c, 0xd6, + 0x6a, 0xb1, 0x0e, 0xa7, 0x43, 0x6c, 0xc2, 0xf5, 0x7f, 0x87, 0x23, 0xa1, + 0x04, 0x73, 0xbe, 0x8e, 0x77, 0x73, 0x5f, 0x66, 0xbf, 0x53, 0x27, 0x67, + 0x77, 0x70, 0xcb, 0x09, 0x2f, 0xd7, 0x5c, 0x4f, 0x5c, 0xb3, 0x09, 0x3f, + 0x0b, 0x39, 0xbd, 0xc6, 0x61, 0x5e, 0x1f, 0x9d, 0x0e, 0x10, 0x8b, 0xfa, + 0xf8, 0xb9, 0x91, 0xb7, 0x2f, 0xe2, 0x49, 0x64, 0xf9, 0xd7, 0x78, 0xf2, + 0x11, 0x0f, 0xe8, 0xb8, 0x9a, 0x7b, 0x09, 0x57, 0x48, 0x3b, 0x3b, 0xed, + 0xd0, 0x3c, 0x5e, 0x10, 0xba, 0xb2, 0x5e, 0x6c, 0xb0, 0xd6, 0x2d, 0xf4, + 0x03, 0x72, 0x8e, 0xf7, 0xdf, 0xb8, 0x06, 0x91, 0xdd, 0x09, 0xf6, 0xc7, + 0x46, 0x03, 0xda, 0x43, 0xb4, 0x97, 0x29, 0x6b, 0x68, 0xec, 0x45, 0xe5, + 0xdd, 0x08, 0x56, 0x8c, 0x59, 0x43, 0x91, 0x94, 0x5c, 0xb7, 0xac, 0xea, + 0xb5, 0x7a, 0xe4, 0x0d, 0xe5, 0x61, 0xad, 0xf3, 0x50, 0x07, 0xa3, 0x38, + 0x9b, 0x6b, 0xbc, 0xf8, 0x1e, 0xb1, 0x53, 0x94, 0xbd, 0xde, 0x25, 0xf7, + 0x28, 0x66, 0x72, 0xff, 0xb1, 0x52, 0x66, 0x04, 0xa3, 0x85, 0x80, 0x9a, + 0xce, 0xfd, 0x49, 0xa5, 0xe4, 0xa2, 0x11, 0xfa, 0x42, 0xd3, 0x98, 0xf0, + 0x6a, 0x0d, 0x55, 0x91, 0xce, 0x51, 0xd2, 0x99, 0x5e, 0xa3, 0x67, 0x46, + 0x94, 0xe8, 0x2c, 0x40, 0x5c, 0xf7, 0xaa, 0xcc, 0xcf, 0xa8, 0xb7, 0xa7, + 0xf9, 0xbc, 0xe8, 0x2d, 0x8c, 0x9f, 0x15, 0xe9, 0x3c, 0x56, 0xb8, 0x88, + 0xe9, 0xdc, 0x25, 0xfb, 0xf7, 0x91, 0x42, 0x82, 0xb5, 0xaf, 0x0f, 0x79, + 0xe6, 0x93, 0xb1, 0x5c, 0x63, 0x66, 0x8c, 0x7c, 0x38, 0x67, 0xee, 0xfa, + 0xf0, 0x64, 0xf1, 0x99, 0x61, 0xbe, 0x3b, 0x7c, 0xed, 0x77, 0xd1, 0x91, + 0xb3, 0xaf, 0xef, 0xec, 0x2b, 0x94, 0xd3, 0x76, 0x4e, 0x1f, 0x7e, 0xd8, + 0xf4, 0xca, 0x0c, 0x1c, 0x2f, 0x8d, 0xaf, 0xc7, 0x88, 0xf1, 0x97, 0xd8, + 0x45, 0xb9, 0x47, 0xa9, 0xcf, 0x13, 0xa6, 0xbd, 0x7f, 0x2f, 0xe7, 0xba, + 0x98, 0xab, 0xbb, 0x5a, 0xcf, 0x10, 0x8b, 0x1d, 0x63, 0xcc, 0xec, 0x49, + 0x36, 0x76, 0xbf, 0x4c, 0xbf, 0x4b, 0x7f, 0x5d, 0xf6, 0xc8, 0x81, 0xb1, + 0x89, 0x6f, 0x63, 0xaa, 0xa6, 0x71, 0xe1, 0x59, 0xe6, 0x84, 0xd3, 0xcc, + 0x53, 0x1e, 0xe6, 0x84, 0xea, 0x09, 0x62, 0x48, 0xe6, 0xa9, 0x79, 0xe6, + 0x29, 0x8f, 0xde, 0x78, 0x71, 0x06, 0xff, 0x9d, 0x7a, 0x11, 0xfe, 0x62, + 0x89, 0x19, 0xc8, 0xb3, 0xce, 0xfc, 0x55, 0x9f, 0xe9, 0xc7, 0xa5, 0x9b, + 0x9d, 0x19, 0x9a, 0x9b, 0x35, 0x7b, 0x77, 0xae, 0x31, 0x34, 0x22, 0xb4, + 0x7b, 0xb4, 0x48, 0x96, 0xb6, 0x3a, 0x62, 0x63, 0xef, 0x6e, 0xf6, 0x0b, + 0x72, 0x8e, 0xab, 0x0a, 0x1e, 0xfa, 0xfe, 0x88, 0x21, 0xe7, 0x1b, 0x22, + 0xc1, 0xcd, 0xb4, 0xe1, 0x88, 0xd9, 0xd8, 0x12, 0x53, 0x3b, 0x70, 0xa9, + 0x98, 0x63, 0x1d, 0x2c, 0xad, 0x65, 0x8e, 0xa2, 0xb1, 0xfb, 0x7e, 0x7c, + 0x03, 0xe9, 0x9a, 0xc6, 0xde, 0x71, 0xc4, 0x8c, 0x7b, 0x21, 0xe7, 0x41, + 0x1d, 0x5a, 0xf5, 0x79, 0x37, 0xf1, 0xc8, 0x27, 0xd6, 0x52, 0xfd, 0x31, + 0x8c, 0x13, 0x33, 0x36, 0xac, 0xd2, 0x2f, 0x7e, 0xbf, 0x78, 0xcf, 0xd9, + 0x2b, 0x12, 0x7f, 0xf1, 0x51, 0x07, 0xe5, 0xf0, 0x2c, 0xaa, 0xe3, 0x1a, + 0xd4, 0x85, 0x7d, 0x56, 0xf8, 0x55, 0x1c, 0xa0, 0xbf, 0x8d, 0x17, 0x14, + 0x8c, 0xfa, 0x57, 0x31, 0x20, 0xb5, 0x89, 0xef, 0xb4, 0xe5, 0x02, 0xc4, + 0x29, 0x11, 0x94, 0xeb, 0xb1, 0xe8, 0x30, 0xe5, 0x6b, 0x63, 0x2e, 0x1f, + 0x65, 0x0e, 0xc9, 0x86, 0x02, 0xf6, 0xf9, 0xd5, 0x72, 0x3d, 0x62, 0xff, + 0xcf, 0x81, 0xf4, 0x41, 0x0d, 0x53, 0xb2, 0x4f, 0x7d, 0x08, 0xaf, 0x8e, + 0xcf, 0xe3, 0x58, 0x32, 0x8d, 0xbd, 0x35, 0x21, 0x8c, 0x99, 0x8b, 0xed, + 0xb9, 0x81, 0xf4, 0x5b, 0x5b, 0x26, 0x0e, 0xda, 0xb3, 0xc8, 0x8d, 0x49, + 0x57, 0xbd, 0x9c, 0xe3, 0x98, 0x66, 0xdf, 0x35, 0x6e, 0x0c, 0xe1, 0x80, + 0xf1, 0xc7, 0x30, 0x16, 0x49, 0xee, 0x1c, 0xc1, 0xf9, 0x29, 0xa9, 0x61, + 0xfd, 0xad, 0xcb, 0xc6, 0x44, 0x3f, 0x2e, 0x62, 0x5e, 0x1f, 0x9a, 0x6c, + 0x0c, 0x37, 0xd7, 0xba, 0x7c, 0xca, 0xc1, 0x72, 0x4d, 0x79, 0x39, 0x73, + 0x5d, 0x85, 0x20, 0xf5, 0x75, 0x21, 0xe9, 0x65, 0xce, 0x11, 0x7d, 0xca, + 0x19, 0x3f, 0x47, 0xce, 0x44, 0x5e, 0x61, 0xa4, 0xf9, 0xc6, 0xfd, 0x15, + 0xf9, 0xff, 0x83, 0x6b, 0xe7, 0x0e, 0x8b, 0xb3, 0xf1, 0x3f, 0xb7, 0x2e, + 0xdd, 0x24, 0x72, 0x27, 0x03, 0xcc, 0xe9, 0xd1, 0xa9, 0x6b, 0xfa, 0x15, + 0x9d, 0x9e, 0x93, 0x9a, 0x61, 0xeb, 0xdc, 0x99, 0xb7, 0x69, 0x03, 0xef, + 0xa8, 0x46, 0xd6, 0x13, 0xfa, 0x55, 0x0d, 0xfd, 0xad, 0x09, 0xbd, 0x4b, + 0x53, 0x9e, 0x9e, 0xab, 0xe6, 0x7a, 0xb4, 0xac, 0x7e, 0xd7, 0xc2, 0xcd, + 0x6d, 0x70, 0xeb, 0x72, 0x7d, 0xca, 0x4a, 0x87, 0xe4, 0x77, 0x33, 0x20, + 0xb5, 0xfc, 0x05, 0x73, 0xde, 0x5a, 0xbe, 0xd8, 0xc1, 0x86, 0x7f, 0x97, + 0x93, 0xbd, 0xaf, 0xac, 0xc5, 0x5e, 0xfb, 0xe2, 0xdb, 0xee, 0x83, 0xf8, + 0xdb, 0xfc, 0x21, 0xbc, 0x39, 0xee, 0x21, 0xce, 0x14, 0x59, 0xd6, 0xa3, + 0x7a, 0x75, 0x3c, 0xfd, 0x2e, 0xf3, 0xe2, 0xc5, 0xa9, 0x92, 0x5f, 0xcc, + 0xb5, 0xae, 0x98, 0x52, 0xa4, 0x55, 0x85, 0x32, 0xca, 0xf9, 0x53, 0xc3, + 0x8d, 0x68, 0x11, 0xdb, 0xba, 0xc9, 0xe7, 0xee, 0x9c, 0x83, 0x79, 0x63, + 0xf9, 0xc3, 0x01, 0x67, 0xfe, 0x15, 0x60, 0x1e, 0x1d, 0xc5, 0x91, 0x5c, + 0x63, 0xe2, 0x3d, 0x39, 0xa7, 0xc3, 0x5e, 0xec, 0x12, 0x46, 0x71, 0x22, + 0x57, 0xca, 0xa1, 0x11, 0x39, 0xdf, 0x9a, 0x88, 0xba, 0x9c, 0x1c, 0x19, + 0x75, 0x69, 0xd9, 0xa8, 0xeb, 0xe6, 0x80, 0x60, 0x83, 0xe1, 0x42, 0x2c, + 0x52, 0x0e, 0x37, 0xf6, 0x18, 0x8e, 0x7f, 0xd4, 0xcf, 0x78, 0x11, 0x5d, + 0x24, 0x75, 0x59, 0x6a, 0xb2, 0x87, 0x35, 0x79, 0x31, 0xd2, 0x8b, 0x3d, + 0x78, 0x4d, 0x17, 0x7d, 0xec, 0x2f, 0xe9, 0xc3, 0x38, 0x87, 0xfd, 0xd6, + 0x7c, 0xb7, 0xf8, 0x92, 0x17, 0x87, 0x9a, 0xa6, 0xad, 0xa9, 0xb0, 0xc8, + 0xee, 0xc6, 0x69, 0xe6, 0x57, 0xdc, 0x1c, 0x8b, 0x9c, 0x66, 0xcd, 0x1e, + 0xd1, 0x4b, 0x3e, 0x7e, 0x57, 0x91, 0x4f, 0x3d, 0x33, 0x8b, 0x3f, 0xe1, + 0xef, 0xf5, 0x91, 0xbd, 0xca, 0x59, 0x6f, 0xf9, 0xcc, 0xdb, 0x81, 0xd2, + 0xec, 0x54, 0x9e, 0x8d, 0xe6, 0x09, 0x3a, 0x2b, 0x84, 0x56, 0x80, 0xfe, + 0x59, 0x8e, 0xde, 0xb0, 0x9c, 0xf3, 0x10, 0xbd, 0xc8, 0x9e, 0x22, 0xa8, + 0x0f, 0x0b, 0x2f, 0x51, 0x1f, 0x87, 0xae, 0x9d, 0xa9, 0x72, 0xf2, 0x57, + 0x05, 0xaf, 0x6f, 0x4e, 0xbe, 0xb8, 0xce, 0x8f, 0xdf, 0x58, 0x97, 0xc2, + 0x11, 0xe6, 0x04, 0xb1, 0x69, 0xc6, 0xc6, 0x91, 0x6e, 0xe2, 0x93, 0xdd, + 0xf6, 0xf9, 0x11, 0xc6, 0x81, 0x79, 0x4d, 0x8e, 0xf9, 0x3e, 0xe2, 0xec, + 0xb9, 0x9c, 0x7d, 0x66, 0xaf, 0xf7, 0x0d, 0x15, 0x63, 0xae, 0xf9, 0x12, + 0x7a, 0x6b, 0x85, 0x5e, 0x28, 0xb8, 0x6d, 0x32, 0x41, 0x1d, 0xd4, 0x09, + 0x5d, 0xeb, 0x29, 0x76, 0x73, 0x87, 0xc6, 0x84, 0x3e, 0x30, 0x32, 0x16, + 0xeb, 0xff, 0x29, 0xb0, 0xae, 0x0a, 0xda, 0xe0, 0x6c, 0xf1, 0xff, 0x38, + 0x7e, 0xa1, 0x84, 0x96, 0xd0, 0xf1, 0xc0, 0x64, 0x8e, 0x3b, 0x3e, 0x57, + 0x41, 0xdd, 0x69, 0xdd, 0x3f, 0x50, 0x15, 0x78, 0xec, 0x89, 0x04, 0x79, + 0x5f, 0x14, 0xdc, 0x3c, 0xe9, 0x83, 0xff, 0x4c, 0x15, 0x6b, 0xae, 0x0f, + 0x97, 0x9b, 0x69, 0xd7, 0x27, 0x4a, 0xbc, 0xdb, 0x7b, 0xa3, 0x78, 0x74, + 0x22, 0x0a, 0x93, 0x3e, 0x3b, 0x67, 0xca, 0x3e, 0xb0, 0xcf, 0xce, 0x9f, + 0x17, 0xd7, 0xd4, 0xd9, 0x7b, 0x54, 0xcf, 0x16, 0xf4, 0xc8, 0x59, 0x55, + 0x85, 0x0f, 0x4e, 0xcc, 0xdf, 0x5c, 0x0e, 0xeb, 0x85, 0xa5, 0xa9, 0x78, + 0x66, 0x17, 0x7d, 0x7e, 0xc5, 0xf2, 0x30, 0x7b, 0x19, 0xf6, 0x94, 0x6b, + 0xa5, 0xff, 0x1d, 0x60, 0xff, 0x5b, 0xda, 0xd3, 0xd7, 0xfb, 0x1f, 0x52, + 0xd9, 0x4d, 0x41, 0x58, 0x1f, 0x95, 0xa7, 0xac, 0x8f, 0xbd, 0xa9, 0x38, + 0xdf, 0x97, 0x3d, 0x3d, 0xcb, 0x7a, 0xab, 0xd9, 0xb2, 0xf2, 0xcd, 0xb1, + 0x4c, 0xc8, 0x1d, 0xc2, 0x99, 0x06, 0xd9, 0x07, 0x74, 0xe1, 0x83, 0xb8, + 0x1e, 0xd9, 0x05, 0xd9, 0x7b, 0x67, 0x8e, 0x5f, 0x2c, 0xe7, 0x0e, 0xeb, + 0x82, 0x9d, 0xe6, 0x22, 0x3c, 0x33, 0xbb, 0x16, 0xbd, 0x5e, 0xd8, 0xe7, + 0x62, 0x2c, 0x03, 0x6f, 0x2c, 0x85, 0xd4, 0xed, 0x78, 0xcb, 0x43, 0x08, + 0x63, 0xb6, 0x70, 0x08, 0x0f, 0x9e, 0x90, 0xfd, 0xc5, 0x07, 0x5a, 0x7d, + 0x27, 0xac, 0xbf, 0x8b, 0xa4, 0xe6, 0x99, 0x17, 0x2d, 0xab, 0x62, 0x6d, + 0x63, 0x84, 0xe5, 0x88, 0x18, 0xa3, 0x57, 0xb0, 0x7b, 0xff, 0x07, 0xa8, + 0xc1, 0xd9, 0xe9, 0xf4, 0xcd, 0xec, 0x25, 0x3b, 0x9f, 0x54, 0x21, 0x3c, + 0x4f, 0x19, 0x9f, 0x2e, 0x08, 0x4e, 0x79, 0xb0, 0x75, 0xcb, 0x89, 0x25, + 0x78, 0x61, 0x36, 0x8c, 0xb3, 0xa6, 0x4e, 0x9c, 0x04, 0x55, 0x99, 0xb2, + 0xaa, 0xab, 0xc9, 0x6b, 0xa5, 0xdb, 0x8d, 0x4d, 0x49, 0xe9, 0x0f, 0xf5, + 0xfe, 0x80, 0xc2, 0x92, 0x72, 0xe8, 0x0b, 0xfb, 0x81, 0x01, 0x3f, 0xfb, + 0xd5, 0x27, 0x55, 0x3c, 0xf3, 0xbe, 0x3b, 0x8c, 0xe7, 0x99, 0x7f, 0x7e, + 0x50, 0x90, 0x33, 0x53, 0xcc, 0x31, 0xd3, 0x51, 0xda, 0xca, 0x07, 0x57, + 0x7d, 0x15, 0x0e, 0x33, 0x5e, 0x5e, 0x32, 0xca, 0x98, 0xa3, 0xe4, 0x0c, + 0x95, 0xe4, 0xf7, 0x9d, 0x72, 0x56, 0xc4, 0x7a, 0x56, 0x77, 0xfa, 0x7d, + 0x63, 0xe6, 0xc6, 0x73, 0xc8, 0x21, 0xe6, 0xf5, 0xc6, 0xee, 0x88, 0x7a, + 0xc5, 0x4a, 0x7f, 0x5d, 0x51, 0xce, 0xdd, 0x55, 0xa8, 0xb0, 0x65, 0xc5, + 0xf0, 0x44, 0xa9, 0xa6, 0x54, 0x4b, 0x2f, 0xd7, 0x9d, 0x2d, 0xfa, 0x60, + 0x25, 0x63, 0xfd, 0x28, 0x6b, 0x74, 0xf9, 0x09, 0xa9, 0x25, 0xec, 0x5f, + 0xd4, 0x7a, 0x62, 0x61, 0xc1, 0x0d, 0x3e, 0xdc, 0x1f, 0xd2, 0x5a, 0xe4, + 0x2c, 0xf6, 0xd3, 0x85, 0x0e, 0x8f, 0x9c, 0x89, 0x7a, 0xa6, 0x20, 0xb5, + 0x5c, 0x72, 0x41, 0x69, 0xbd, 0x08, 0x6a, 0xc7, 0xc4, 0x46, 0xdd, 0xad, + 0x1f, 0x8d, 0x05, 0xe4, 0xdc, 0xfc, 0x90, 0x8b, 0xbd, 0xb6, 0x6f, 0xcc, + 0xb2, 0xee, 0x6e, 0xd6, 0xfb, 0xd7, 0xbb, 0x65, 0x3f, 0x39, 0xd6, 0x7b, + 0x4e, 0x69, 0x2d, 0x47, 0xd4, 0x8d, 0x74, 0x9e, 0xab, 0x92, 0x18, 0xc9, + 0x52, 0xce, 0x47, 0x6d, 0x99, 0xf6, 0x53, 0xa6, 0xd2, 0x99, 0xa1, 0x2a, + 0x5c, 0x1e, 0x87, 0xce, 0xa8, 0xc5, 0x79, 0x83, 0xc9, 0x29, 0x14, 0x4f, + 0xb7, 0x43, 0xfc, 0x5f, 0xeb, 0x15, 0x0c, 0x55, 0xc9, 0x9c, 0x3c, 0x3d, + 0x2e, 0x35, 0x46, 0x09, 0x3e, 0xc9, 0x56, 0xa7, 0x06, 0x70, 0x65, 0x0d, + 0xf0, 0xca, 0x98, 0xb3, 0xdf, 0x5e, 0x3c, 0xe3, 0x6d, 0x9f, 0x65, 0x78, + 0xc8, 0x3e, 0xa3, 0x20, 0xf4, 0x0f, 0xe2, 0x4c, 0x4e, 0x30, 0xe5, 0x00, + 0x31, 0x65, 0x6c, 0x90, 0x78, 0xb3, 0xa5, 0xe0, 0x9c, 0xb7, 0x32, 0x3e, + 0xa2, 0xcf, 0x3f, 0x49, 0xac, 0x7a, 0x18, 0xce, 0x7e, 0x7b, 0x43, 0xf1, + 0x0c, 0x42, 0x2c, 0xdf, 0xa9, 0xb6, 0x16, 0xec, 0x33, 0x5a, 0x8c, 0xb1, + 0x76, 0xb5, 0x79, 0xb6, 0x43, 0x6d, 0x99, 0xed, 0x52, 0x3b, 0x0a, 0xd2, + 0xb3, 0x3e, 0xd0, 0x7a, 0xff, 0x89, 0xed, 0x6a, 0xeb, 0x74, 0x8f, 0x22, + 0xa6, 0x0d, 0xf9, 0x52, 0x19, 0xd5, 0x35, 0xeb, 0xcc, 0xcf, 0x3b, 0xd9, + 0x77, 0x6d, 0x35, 0x4b, 0xfd, 0xbc, 0xfc, 0x1f, 0x57, 0x58, 0xfe, 0x67, + 0xa2, 0x77, 0xa3, 0xb2, 0xac, 0x5b, 0x93, 0x7f, 0x2d, 0xf6, 0xb0, 0x9e, + 0x4e, 0xb2, 0x36, 0x9a, 0x55, 0xe8, 0x63, 0xdf, 0x31, 0x6c, 0x2c, 0x2b, + 0xee, 0x97, 0x89, 0x4c, 0x72, 0x4e, 0x42, 0xfc, 0x15, 0x59, 0xf6, 0x20, + 0xf8, 0x7b, 0xf2, 0xbf, 0xb7, 0x28, 0x57, 0x97, 0x9c, 0x23, 0xf0, 0x5e, + 0x3f, 0x47, 0x76, 0x6c, 0xec, 0xba, 0x5c, 0x1e, 0x5e, 0x1b, 0x25, 0x3e, + 0xdd, 0xab, 0xb4, 0xc1, 0xa7, 0x1c, 0xb9, 0x2e, 0x5e, 0x66, 0x0c, 0x0f, + 0xdb, 0x31, 0xec, 0xc8, 0xb5, 0xb2, 0x28, 0xd7, 0x8a, 0x7c, 0xa7, 0x7d, + 0x3e, 0x8b, 0x74, 0x5a, 0xe7, 0xc6, 0xe4, 0x1c, 0x99, 0xcc, 0x2e, 0x45, + 0x36, 0x91, 0xe3, 0x84, 0x55, 0xa1, 0x77, 0xa9, 0x6d, 0xf6, 0xb9, 0x32, + 0x39, 0xd3, 0x25, 0xfb, 0xfb, 0x25, 0xb9, 0xa4, 0x8e, 0x2f, 0x0a, 0x76, + 0x4c, 0xca, 0x39, 0x6b, 0xcb, 0xfa, 0x99, 0x51, 0x11, 0x14, 0x59, 0xce, + 0x1a, 0x22, 0x8b, 0x9c, 0x17, 0x29, 0xc9, 0xf3, 0xb5, 0xa2, 0x3c, 0x62, + 0xab, 0xeb, 0x76, 0x2a, 0xfd, 0xff, 0xdf, 0xdb, 0x39, 0xe7, 0x2c, 0x49, + 0x49, 0x9e, 0x60, 0x4a, 0xf8, 0xcf, 0xb7, 0x8e, 0x8e, 0x0f, 0xe0, 0x15, + 0xde, 0xff, 0x65, 0xae, 0x24, 0x97, 0x1b, 0x33, 0xd3, 0xa5, 0x33, 0x72, + 0x6c, 0x29, 0xcd, 0x98, 0x31, 0x42, 0x3f, 0x72, 0xe4, 0x93, 0x33, 0x72, + 0x8d, 0xf3, 0x97, 0xed, 0xb9, 0x57, 0x3c, 0xcd, 0x7e, 0x19, 0x67, 0x0b, + 0xbf, 0x6d, 0xbf, 0xa6, 0x7c, 0x05, 0x7b, 0x64, 0xa1, 0x3d, 0x47, 0xda, + 0x72, 0x96, 0x44, 0xe1, 0xa9, 0x69, 0x60, 0xda, 0xe4, 0xb2, 0xa9, 0x21, + 0x3c, 0x6e, 0x58, 0xd6, 0x93, 0xcd, 0xba, 0x9c, 0x01, 0xba, 0x50, 0x6b, + 0xcf, 0x85, 0x60, 0x54, 0xe9, 0xb2, 0x77, 0x27, 0xe7, 0x48, 0x7a, 0xa8, + 0x03, 0x91, 0x5d, 0x7c, 0xa0, 0x64, 0x7b, 0x39, 0xdf, 0x96, 0xa5, 0x7e, + 0x44, 0x37, 0xa5, 0x73, 0x6e, 0x32, 0x73, 0xb9, 0x51, 0x27, 0xb7, 0xd9, + 0x3a, 0x79, 0xda, 0x10, 0x7f, 0x65, 0xf6, 0xa1, 0xaf, 0xce, 0x10, 0x3f, + 0x8c, 0x18, 0x5e, 0x1b, 0xab, 0x1d, 0x26, 0x3e, 0x39, 0xc2, 0xd8, 0x79, + 0xd4, 0xbc, 0x88, 0x8b, 0xf9, 0x97, 0xf0, 0xca, 0xb5, 0xff, 0x85, 0x13, + 0x7f, 0xf1, 0xb5, 0x6c, 0xb1, 0xcf, 0x32, 0xfd, 0x75, 0xcb, 0xb2, 0xb8, + 0xe4, 0xa1, 0x93, 0x4d, 0x72, 0xb6, 0xa9, 0x3c, 0xf5, 0xde, 0x3a, 0xd9, + 0xdf, 0x2a, 0x4b, 0x0d, 0x7e, 0xf5, 0x82, 0x2e, 0xba, 0xf9, 0x64, 0xf5, + 0x19, 0x5d, 0xe4, 0xd2, 0x8d, 0x51, 0xfb, 0x7f, 0x33, 0x43, 0x6b, 0x77, + 0xeb, 0x12, 0x3b, 0xef, 0x34, 0xb7, 0xd9, 0x39, 0x61, 0x30, 0x75, 0xab, + 0xad, 0x83, 0x83, 0xa9, 0x65, 0x8e, 0x2e, 0x52, 0x09, 0xfb, 0xfb, 0xe1, + 0x94, 0xa3, 0x9b, 0x5c, 0xaa, 0xde, 0xfe, 0x1e, 0x4d, 0x39, 0x67, 0xa2, + 0xb3, 0x29, 0xdd, 0xfe, 0x1e, 0x4f, 0xc5, 0xec, 0xef, 0x23, 0xa9, 0x5b, + 0xae, 0xf3, 0xc5, 0x9f, 0xff, 0x07, 0xd8, 0xc4, 0xd3, 0xb4, 0xb4, 0x3a, + 0x00, 0x00, 0x00 }; static const u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static const u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; static struct fw_info bnx2_txp_fw_06 = { - /* Firmware version: 4.0.5 */ + /* Firmware version: 4.4.2 */ .ver_major = 0x4, - .ver_minor = 0x0, - .ver_fix = 0x5, + .ver_minor = 0x4, + .ver_fix = 0x2, .start_addr = 0x08000098, .text_addr = 0x08000000, - .text_len = 0x3ad8, + .text_len = 0x3ab0, .text_index = 0x0, .gz_text = bnx2_TXP_b06FwText, .gz_text_len = sizeof(bnx2_TXP_b06FwText), @@ -4582,11 +4535,11 @@ static struct fw_info bnx2_txp_fw_06 = { .data_index = 0x0, .data = bnx2_TXP_b06FwData, - .sbss_addr = 0x08003b00, + .sbss_addr = 0x08003ae0, .sbss_len = 0x68, .sbss_index = 0x0, - .bss_addr = 0x08003b68, + .bss_addr = 0x08003b48, .bss_len = 0x14c, .bss_index = 0x0, @@ -4611,3 +4564,4 @@ static const struct cpu_reg cpu_reg_txp = { .spad_base = BNX2_TXP_SCRATCH, .mips_view_base = 0x8000000, }; + -- GitLab From a1efb4b686babf38e5e63add8b990f18e38becc4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 9 Oct 2008 12:24:39 -0700 Subject: [PATCH 3566/5416] bnx2: Eliminate TSO header modifications. This is now possible with updated firmware. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 21711c753a0..f147204e1e4 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6008,7 +6008,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } #endif if ((mss = skb_shinfo(skb)->gso_size)) { - u32 tcp_opt_len, ip_tcp_len; + u32 tcp_opt_len; struct iphdr *iph; vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; @@ -6032,21 +6032,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL; } } else { - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); - iph = ip_hdr(skb); - iph->check = 0; - iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); if (tcp_opt_len || (iph->ihl > 5)) { vlan_tag_flags |= ((iph->ihl - 5) + (tcp_opt_len >> 2)) << 8; -- GitLab From 3d16af8665504c89f9ef3aae56f54fb93e48da61 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 9 Oct 2008 12:26:41 -0700 Subject: [PATCH 3567/5416] bnx2: Handle DMA mapping errors. Before, the driver would not care about the return codes from pci_map_* functions. This could be potentially dangerous if a mapping failed. Now, we will check all pci_map_* calls. On the transmit side, we switch to use the new function skb_dma_map(). On the receive side, we add pci_dma_mapping_error(). Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 114 ++++++++++++++++++++++++--------------------- drivers/net/bnx2.h | 8 +++- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index f147204e1e4..a95ca4fa249 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -2476,6 +2476,11 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index) return -ENOMEM; mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(bp->pdev, mapping)) { + __free_page(page); + return -EIO; + } + rx_pg->page = page; pci_unmap_addr_set(rx_pg, mapping, mapping); rxbd->rx_bd_haddr_hi = (u64) mapping >> 32; @@ -2518,6 +2523,10 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index) mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(bp->pdev, mapping)) { + dev_kfree_skb(skb); + return -EIO; + } rx_buf->skb = skb; pci_unmap_addr_set(rx_buf, mapping, mapping); @@ -2592,7 +2601,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) sw_cons = txr->tx_cons; while (sw_cons != hw_cons) { - struct sw_bd *tx_buf; + struct sw_tx_bd *tx_buf; struct sk_buff *skb; int i, last; @@ -2617,21 +2626,13 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) } } - pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping), - skb_headlen(skb), PCI_DMA_TODEVICE); + skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE); tx_buf->skb = NULL; last = skb_shinfo(skb)->nr_frags; for (i = 0; i < last; i++) { sw_cons = NEXT_TX_BD(sw_cons); - - pci_unmap_page(bp->pdev, - pci_unmap_addr( - &txr->tx_buf_ring[TX_RING_IDX(sw_cons)], - mapping), - skb_shinfo(skb)->frags[i].size, - PCI_DMA_TODEVICE); } sw_cons = NEXT_TX_BD(sw_cons); @@ -2672,11 +2673,31 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, { struct sw_pg *cons_rx_pg, *prod_rx_pg; struct rx_bd *cons_bd, *prod_bd; - dma_addr_t mapping; int i; - u16 hw_prod = rxr->rx_pg_prod, prod; + u16 hw_prod, prod; u16 cons = rxr->rx_pg_cons; + cons_rx_pg = &rxr->rx_pg_ring[cons]; + + /* The caller was unable to allocate a new page to replace the + * last one in the frags array, so we need to recycle that page + * and then free the skb. + */ + if (skb) { + struct page *page; + struct skb_shared_info *shinfo; + + shinfo = skb_shinfo(skb); + shinfo->nr_frags--; + page = shinfo->frags[shinfo->nr_frags].page; + shinfo->frags[shinfo->nr_frags].page = NULL; + + cons_rx_pg->page = page; + dev_kfree_skb(skb); + } + + hw_prod = rxr->rx_pg_prod; + for (i = 0; i < count; i++) { prod = RX_PG_RING_IDX(hw_prod); @@ -2685,20 +2706,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)]; prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; - if (i == 0 && skb) { - struct page *page; - struct skb_shared_info *shinfo; - - shinfo = skb_shinfo(skb); - shinfo->nr_frags--; - page = shinfo->frags[shinfo->nr_frags].page; - shinfo->frags[shinfo->nr_frags].page = NULL; - mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - cons_rx_pg->page = page; - pci_unmap_addr_set(cons_rx_pg, mapping, mapping); - dev_kfree_skb(skb); - } if (prod != cons) { prod_rx_pg->page = cons_rx_pg->page; cons_rx_pg->page = NULL; @@ -2784,6 +2791,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb, skb_put(skb, hdr_len); for (i = 0; i < pages; i++) { + dma_addr_t mapping_old; + frag_len = min(frag_size, (unsigned int) PAGE_SIZE); if (unlikely(frag_len <= 4)) { unsigned int tail = 4 - frag_len; @@ -2806,9 +2815,10 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb, } rx_pg = &rxr->rx_pg_ring[pg_cons]; - pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping), - PAGE_SIZE, PCI_DMA_FROMDEVICE); - + /* Don't unmap yet. If we're unable to allocate a new + * page, we need to recycle the page and the DMA addr. + */ + mapping_old = pci_unmap_addr(rx_pg, mapping); if (i == pages - 1) frag_len -= 4; @@ -2825,6 +2835,9 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb, return err; } + pci_unmap_page(bp->pdev, mapping_old, + PAGE_SIZE, PCI_DMA_FROMDEVICE); + frag_size -= frag_len; skb->data_len += frag_len; skb->truesize += frag_len; @@ -4971,31 +4984,20 @@ bnx2_free_tx_skbs(struct bnx2 *bp) continue; for (j = 0; j < TX_DESC_CNT; ) { - struct sw_bd *tx_buf = &txr->tx_buf_ring[j]; + struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; struct sk_buff *skb = tx_buf->skb; - int k, last; if (skb == NULL) { j++; continue; } - pci_unmap_single(bp->pdev, - pci_unmap_addr(tx_buf, mapping), - skb_headlen(skb), PCI_DMA_TODEVICE); + skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE); tx_buf->skb = NULL; - last = skb_shinfo(skb)->nr_frags; - for (k = 0; k < last; k++) { - tx_buf = &txr->tx_buf_ring[j + k + 1]; - pci_unmap_page(bp->pdev, - pci_unmap_addr(tx_buf, mapping), - skb_shinfo(skb)->frags[j].size, - PCI_DMA_TODEVICE); - } + j += skb_shinfo(skb)->nr_frags + 1; dev_kfree_skb(skb); - j += k + 1; } } } @@ -5373,8 +5375,11 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) for (i = 14; i < pkt_size; i++) packet[i] = (unsigned char) (i & 0xff); - map = pci_map_single(bp->pdev, skb->data, pkt_size, - PCI_DMA_TODEVICE); + if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_kfree_skb(skb); + return -EIO; + } + map = skb_shinfo(skb)->dma_maps[0]; REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); @@ -5409,7 +5414,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) udelay(5); - pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE); + skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE); dev_kfree_skb(skb); if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod) @@ -5970,13 +5975,14 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) struct bnx2 *bp = netdev_priv(dev); dma_addr_t mapping; struct tx_bd *txbd; - struct sw_bd *tx_buf; + struct sw_tx_bd *tx_buf; u32 len, vlan_tag_flags, last_frag, mss; u16 prod, ring_prod; int i; struct bnx2_napi *bnapi; struct bnx2_tx_ring_info *txr; struct netdev_queue *txq; + struct skb_shared_info *sp; /* Determine which tx ring we will be placed on */ i = skb_get_queue_mapping(skb); @@ -6041,11 +6047,16 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } else mss = 0; - mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); + if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + sp = skb_shinfo(skb); + mapping = sp->dma_maps[0]; tx_buf = &txr->tx_buf_ring[ring_prod]; tx_buf->skb = skb; - pci_unmap_addr_set(tx_buf, mapping, mapping); txbd = &txr->tx_desc_ring[ring_prod]; @@ -6064,10 +6075,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) txbd = &txr->tx_desc_ring[ring_prod]; len = frag->size; - mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset, - len, PCI_DMA_TODEVICE); - pci_unmap_addr_set(&txr->tx_buf_ring[ring_prod], - mapping, mapping); + mapping = sp->dma_maps[i + 1]; txbd->tx_bd_haddr_hi = (u64) mapping >> 32; txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index edc7774f2f2..617d9534016 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6526,10 +6526,14 @@ struct sw_pg { DECLARE_PCI_UNMAP_ADDR(mapping) }; +struct sw_tx_bd { + struct sk_buff *skb; +}; + #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT) #define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT) #define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT) -#define SW_TXBD_RING_SIZE (sizeof(struct sw_bd) * TX_DESC_CNT) +#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT) #define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT) /* Buffered flash (Atmel: AT45DB011B) specific information */ @@ -6609,7 +6613,7 @@ struct bnx2_tx_ring_info { u32 tx_bseq_addr; struct tx_bd *tx_desc_ring; - struct sw_bd *tx_buf_ring; + struct sw_tx_bd *tx_buf_ring; u16 tx_cons; u16 hw_tx_cons; -- GitLab From ec7e6fabbe72f1fe65eed14c106a0fbc00f6c2f1 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 9 Oct 2008 12:27:06 -0700 Subject: [PATCH 3568/5416] bnx2: Update version to 1.8.1. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a95ca4fa249..430d430bce2 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.8.0" -#define DRV_MODULE_RELDATE "Aug 14, 2008" +#define DRV_MODULE_VERSION "1.8.1" +#define DRV_MODULE_RELDATE "Oct 7, 2008" #define RUN_AT(x) (jiffies + (x)) -- GitLab From 3bca103a1e658d23737d20e1989139d9ca8973bf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 7 Oct 2008 20:14:55 +0100 Subject: [PATCH 3569/5416] [ARM] 5295/1: make ZONE_DMA optional Most ARM machines don't need a special "DMA" memory zone, and when configured out, the kernel becomes a bit smaller: | text data bss dec hex filename |3826182 102384 111700 4040266 3da64a vmlinux |3823593 101616 111700 4036909 3d992d vmlinux.nodmazone This is because the system now has only one zone total which effect is to optimize away many conditionals in page allocation paths. So let's configure this zone only on machines that need split zones. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 4 +++- arch/arm/common/Kconfig | 3 ++- arch/arm/include/asm/memory.h | 2 ++ arch/arm/mach-pxa/Kconfig | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f5bf38b5f38..ea52fae3329 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -148,7 +148,6 @@ config ARCH_MAY_HAVE_PC_FDC config ZONE_DMA bool - default y config GENERIC_ISA_DMA bool @@ -357,6 +356,7 @@ config ARCH_IXP4XX select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS + select ZONE_DMA if PCI help Support for Intel's IXP4XX (XScale) family of processors. @@ -503,6 +503,7 @@ config ARCH_SHARK bool "Shark" select ISA select ISA_DMA + select ZONE_DMA select PCI help Support for the StrongARM based Digital DNARD machine, also known @@ -524,6 +525,7 @@ config ARCH_DAVINCI select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK + select ZONE_DMA help Support for TI's DaVinci platform. diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 3e073467cac..2e32acca02f 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -12,7 +12,8 @@ config ICST307 config SA1111 bool - select DMABOUNCE + select DMABOUNCE if !ARCH_PXA + select ZONE_DMA if !ARCH_PXA config DMABOUNCE bool diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 7834adbe177..809ff9ab853 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -137,6 +137,8 @@ #ifndef arch_adjust_zones #define arch_adjust_zones(node,size,holes) do { } while (0) +#elif !defined(CONFIG_ZONE_DMA) +#error "custom arch_adjust_zones() requires CONFIG_ZONE_DMA" #endif /* diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index e8ee7ec9ff6..e484f609fed 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -210,6 +210,7 @@ config MACH_ARMCORE bool "CompuLab CM-X270 modules" select PXA27x select IWMMXT + select ZONE_DMA if PCI config MACH_MAGICIAN bool "Enable HTC Magician Support" -- GitLab From efc968d450e013049a662d22727cf132618dcb2f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 9 Oct 2008 14:04:54 -0700 Subject: [PATCH 3570/5416] Don't allow splice() to files opened with O_APPEND This is debatable, but while we're debating it, let's disallow the combination of splice and an O_APPEND destination. It's not entirely clear what the semantics of O_APPEND should be, and POSIX apparently expects pwrite() to ignore O_APPEND, for example. So we could make up any semantics we want, including the old ones. But Miklos convinced me that we should at least give it some thought, and that accepting writes at arbitrary offsets is wrong at least for IS_APPEND() files (which always have O_APPEND set, even if the reverse isn't true: you can obviously have O_APPEND set on a regular file). So disallow O_APPEND entirely for now. I doubt anybody cares, and this way we have one less gray area to worry about. Reported-and-argued-for-by: Miklos Szeredi Acked-by: Jens Axboe Signed-off-by: Linus Torvalds --- fs/splice.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/splice.c b/fs/splice.c index 1bbc6f4bb09..a1e701c2715 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -898,6 +898,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, if (unlikely(!(out->f_mode & FMODE_WRITE))) return -EBADF; + if (unlikely(out->f_flags & O_APPEND)) + return -EINVAL; + ret = rw_verify_area(WRITE, out, ppos, len); if (unlikely(ret < 0)) return ret; -- GitLab From af807c82978ec1b8c5120b59b78ef951b3e4603b Mon Sep 17 00:00:00 2001 From: Dave Graham Date: Thu, 9 Oct 2008 14:28:58 -0700 Subject: [PATCH 3571/5416] e1000e: don't generate bad checksums for tcp packets with 0 csum When offloading transmit checksums only, the driver was not correctly configuring the hardware to handle the case of a zero checksum. For UDP the correct behavior is to leave it alone, but for tcp the checksum must be changed from 0x0000 to 0xFFFF. The hardware takes care of this case but only if it is told the packet is tcp. Signed-off-by: Dave Graham Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 62 +++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1b72749979c..abd492b7336 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3749,34 +3749,50 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) struct e1000_buffer *buffer_info; unsigned int i; u8 css; + u32 cmd_len = E1000_TXD_CMD_DEXT; - if (skb->ip_summed == CHECKSUM_PARTIAL) { - css = skb_transport_offset(skb); - - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = - css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + case __constant_htons(ETH_P_IPV6): + /* XXX not handling all IPV6 headers */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + default: + if (unlikely(net_ratelimit())) + e_warn("checksum_partial proto=%x!\n", skb->protocol); + break; + } - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; + css = skb_transport_offset(skb); - return 1; - } + i = tx_ring->next_to_use; + buffer_info = &tx_ring->buffer_info[i]; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + + context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; + context_desc->upper_setup.tcp_fields.tucso = + css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(cmd_len); + + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; - return 0; + return 1; } #define E1000_MAX_PER_TXD 8192 -- GitLab From 3ed30676f5bc9960c67644fa37c5fdc36ae47b5b Mon Sep 17 00:00:00 2001 From: Dave Graham Date: Thu, 9 Oct 2008 14:29:26 -0700 Subject: [PATCH 3572/5416] e1000: don't generate bad checksums for tcp packets with 0 csum When offloading transmit checksums only, the driver was not correctly configuring the hardware to handle the case of a zero checksum. For UDP the correct behavior is to leave it alone, but for tcp the checksum must be changed from 0x0000 to 0xFFFF. The hardware takes care of this case but only if it is told the packet is tcp. same patch as e1000e Signed-off-by: Dave Graham Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 55 ++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 2ab44db29fa..3bafaede791 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2873,32 +2873,49 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int i; u8 css; + u32 cmd_len = E1000_TXD_CMD_DEXT; - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - css = skb_transport_offset(skb); + if (skb->ip_summed != CHECKSUM_PARTIAL) + return false; - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + case __constant_htons(ETH_P_IPV6): + /* XXX not handling all IPV6 headers */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + cmd_len |= E1000_TXD_CMD_TCP; + break; + default: + if (unlikely(net_ratelimit())) + DPRINTK(DRV, WARNING, + "checksum_partial proto=%x!\n", skb->protocol); + break; + } - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = - css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); + css = skb_transport_offset(skb); - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; + i = tx_ring->next_to_use; + buffer_info = &tx_ring->buffer_info[i]; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - if (unlikely(++i == tx_ring->count)) i = 0; - tx_ring->next_to_use = i; + context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; + context_desc->upper_setup.tcp_fields.tucso = + css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(cmd_len); - return true; - } + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; - return false; + if (unlikely(++i == tx_ring->count)) i = 0; + tx_ring->next_to_use = i; + + return true; } #define E1000_MAX_TXD_PWR 12 -- GitLab From 5c714e238e5e0eb74cdc74201bf3d6296b3b3104 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 9 Oct 2008 14:31:42 -0700 Subject: [PATCH 3573/5416] myri10ge: remove over-paranoid queue number modulus No need to modulus the queue number in ->hard_start_xmit() since the core is going to do that for you modulus ->real_num_tx_queues. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ab7755abd20..8cec6f3c2f8 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2643,8 +2643,6 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) u8 flags, odd_flag; queue = skb_get_queue_mapping(skb); - queue &= (mgp->num_slices - 1); - ss = &mgp->ss[queue]; netdev_queue = netdev_get_tx_queue(mgp->dev, queue); tx = &ss->tx; -- GitLab From 3d5a019d5761a40465337711ae7d2beb1e9b43ec Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 9 Oct 2008 14:32:24 -0700 Subject: [PATCH 3574/5416] sctp: Fix the SNMP number of SCTP_MIB_CURRESTAB RFC3873 defined SCTP_MIB_CURRESTAB: sctpCurrEstab OBJECT-TYPE SYNTAX Gauge32 MAX-ACCESS read-only STATUS current DESCRIPTION "The number of associations for which the current state is either ESTABLISHED, SHUTDOWN-RECEIVED or SHUTDOWN-PENDING." REFERENCE "Section 4 in RFC2960 covers the SCTP Association state diagram." If the T4 RTO timer expires many times(timeout), the association will enter CLOSED state, so we should dec the number of SCTP_MIB_CURRESTAB, not inc the number of SCTP_MIB_CURRESTAB. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ea3a34cbe47..1588d063c68 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5436,7 +5436,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire( sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); - SCTP_INC_STATS(SCTP_MIB_CURRESTAB); + SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); return SCTP_DISPOSITION_ABORT; } -- GitLab From 56eb82bb8d2cdd8d9f4838eaa109df41d7164ca5 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 9 Oct 2008 14:33:01 -0700 Subject: [PATCH 3575/5416] sctp: Fix SNMP number of SCTP_MIB_ABORTED during violation handling. If ABORT chunks require authentication and a protocol violation is triggered, we do not tear down the association. Subsequently, we should not increment SCTP_MIB_ABORTED. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 1588d063c68..f5094f1b5af 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4188,11 +4188,10 @@ static sctp_disposition_t sctp_sf_abort_violation( SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); } -discard: - sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); - SCTP_INC_STATS(SCTP_MIB_ABORTEDS); +discard: + sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); return SCTP_DISPOSITION_ABORT; nomem_pkt: @@ -4265,12 +4264,10 @@ static sctp_disposition_t sctp_sf_violation_paramlen( sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); + SCTP_INC_STATS(SCTP_MIB_ABORTEDS); discard: sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); - - SCTP_INC_STATS(SCTP_MIB_ABORTEDS); - return SCTP_DISPOSITION_ABORT; nomem: return SCTP_DISPOSITION_NOMEM; -- GitLab From a1080a8b0bc301c223c4bf0cea4c5e42f43dcf58 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 9 Oct 2008 14:33:26 -0700 Subject: [PATCH 3576/5416] sctp: update SNMP statiscts when T5 timer expired. The T5 timer is the timer for the over-all shutdown procedure. If this timer expires, then shutdown procedure has not completed and we ABORT the association. We should update SCTP_MIB_ABORTED and SCTP_MIB_CURRESTAB when aborting. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f5094f1b5af..d4c3fbc4671 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5489,6 +5489,9 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(SCTP_ERROR_NO_ERROR)); + SCTP_INC_STATS(SCTP_MIB_ABORTEDS); + SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); + return SCTP_DISPOSITION_DELETE_TCB; nomem: return SCTP_DISPOSITION_NOMEM; -- GitLab From 1d74a6bddf647285e7aa4e9ca4ec16eb071dfd95 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 9 Oct 2008 14:34:47 -0700 Subject: [PATCH 3577/5416] smsc95xx: fix usb usage on big endian platforms Fix warnings caught by David Miller on sparc64 Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/usb/smsc95xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 412bde6217c..51e2f5d7d14 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -320,12 +320,12 @@ static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs) usb_free_urb(urb); } -static int smsc95xx_write_reg_async(struct usbnet *dev, u32 index, u32 *data) +static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) { struct usb_context *usb_context; int status; struct urb *urb; - const u32 size = 4; + const u16 size = 4; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { @@ -344,8 +344,8 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u32 index, u32 *data) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER; usb_context->req.wValue = 00; - usb_context->req.wIndex = cpu_to_le32(index); - usb_context->req.wLength = cpu_to_le32(size); + usb_context->req.wIndex = cpu_to_le16(index); + usb_context->req.wLength = cpu_to_le16(size); init_completion(&usb_context->notify); usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), @@ -545,7 +545,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) } memcpy(&intdata, urb->transfer_buffer, 4); - le32_to_cpus(intdata); + le32_to_cpus(&intdata); if (netif_msg_link(dev)) devdbg(dev, "intdata: 0x%08X", intdata); -- GitLab From df58ef51caea073f4b45857c51f445f65267dac7 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 9 Oct 2008 14:35:58 -0700 Subject: [PATCH 3578/5416] r8169: fix early spinlock use rtl8169_init_one -> rtl_init_mac_address -> rtl_rar_set -> spin_lock_irq(&tp->lock); [...] -> spin_lock_init(&tp->lock); Signed-off-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/r8169.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 108aaff0b21..59fbc64d7c4 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1952,7 +1952,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->do_ioctl = rtl8169_ioctl; } - /* Read MAC address from EEPROM */ + spin_lock_init(&tp->lock); + rtl_init_mac_address(tp, ioaddr); /* Get MAC address */ @@ -1995,8 +1996,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->timer.data = (unsigned long) dev; tp->timer.function = rtl8169_phy_timer; - spin_lock_init(&tp->lock); - rc = register_netdev(dev); if (rc < 0) goto err_out_msi_5; -- GitLab From 78e645cb890b0f32ea81a974e29427d9cd2f64f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 9 Oct 2008 14:37:47 -0700 Subject: [PATCH 3579/5416] tcpv[46]: fix md5 pseudoheader address field ordering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maybe it's just me but I guess those md5 people made a mess out of it by having *_md5_hash_* to use daddr, saddr order instead of the one that is natural (and equal to what csum functions use). For the segment were sending, the original addresses are reversed so buff's saddr == skb's daddr and vice-versa. Maybe I can finally proceed with unification of some code after fixing it first... :-) Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv6/tcp_ipv6.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ba46769c6e9..5c8fa7f1e32 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -583,8 +583,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) rep.th.doff = arg.iov[0].iov_len / 4; tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1], - key, ip_hdr(skb)->daddr, - ip_hdr(skb)->saddr, &rep.th); + key, ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, &rep.th); } #endif arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index dd7bdde7bdd..eab10bc7ff8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1007,8 +1007,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key, - &ipv6_hdr(skb)->daddr, - &ipv6_hdr(skb)->saddr, t1); + &ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, t1); } #endif -- GitLab From 77c676da1b717eed7239144fb539dfc4c7b78e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 9 Oct 2008 14:41:38 -0700 Subject: [PATCH 3580/5416] tcpv6: trivial formatting changes to send_(ack|reset) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index eab10bc7ff8..910603cd12d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -949,7 +949,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) struct flowi fl; struct net *net = dev_net(skb->dst->dev); struct sock *ctl_sk = net->ipv6.tcp_sk; - unsigned int tot_len = sizeof(*th); + unsigned int tot_len = sizeof(struct tcphdr); #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *key; #endif @@ -1033,7 +1033,6 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) * namespace */ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { - if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { ip6_xmit(ctl_sk, buff, &fl, NULL, 0); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); @@ -1070,13 +1069,13 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); - t1 = (struct tcphdr *) skb_push(buff,tot_len); + t1 = (struct tcphdr *) skb_push(buff, tot_len); /* Swap the send and the receive. */ memset(t1, 0, sizeof(*t1)); t1->dest = th->source; t1->source = th->dest; - t1->doff = tot_len/4; + t1->doff = tot_len / 4; t1->seq = htonl(seq); t1->ack_seq = htonl(ack); t1->ack = 1; -- GitLab From 81ada62d70060023923f46ab666cdc2970e1e0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 9 Oct 2008 14:42:01 -0700 Subject: [PATCH 3581/5416] tcpv6: convert opt[] -> topt in tcp_v6_send_reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit after this I get: $ diff-funcs tcp_v6_send_reset tcp_ipv6.c tcp_ipv6.c tcp_v6_send_ack --- tcp_ipv6.c:tcp_v6_send_reset() +++ tcp_ipv6.c:tcp_v6_send_ack() @@ -1,4 +1,5 @@ -static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) +static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, + struct tcp_md5sig_key *key) { struct tcphdr *th = tcp_hdr(skb), *t1; struct sk_buff *buff; @@ -7,31 +8,14 @@ struct sock *ctl_sk = net->ipv6.tcp_sk; unsigned int tot_len = sizeof(struct tcphdr); __be32 *topt; -#ifdef CONFIG_TCP_MD5SIG - struct tcp_md5sig_key *key; -#endif - - if (th->rst) - return; - - if (!ipv6_unicast_destination(skb)) - return; + if (ts) + tot_len += TCPOLEN_TSTAMP_ALIGNED; #ifdef CONFIG_TCP_MD5SIG - if (sk) - key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); - else - key = NULL; - if (key) tot_len += TCPOLEN_MD5SIG_ALIGNED; #endif - /* - * We need to grab some memory, and put together an RST, - * and then put it into the queue to be sent. - */ - buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (buff == NULL) @@ -46,18 +30,20 @@ t1->dest = th->source; t1->source = th->dest; t1->doff = tot_len / 4; - t1->rst = 1; - - if(th->ack) { - t1->seq = th->ack_seq; - } else { - t1->ack = 1; - t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin - + skb->len - (th->doff<<2)); - } + t1->seq = htonl(seq); + t1->ack_seq = htonl(ack); + t1->ack = 1; + t1->window = htons(win); topt = (__be32 *)(t1 + 1); + if (ts) { + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); + *topt++ = htonl(tcp_time_stamp); + *topt++ = htonl(ts); + } + #ifdef CONFIG_TCP_MD5SIG if (key) { *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | @@ -84,15 +70,10 @@ fl.fl_ip_sport = t1->source; security_skb_classify_flow(skb, &fl); - /* Pass a socket to ip6_dst_lookup either it is for RST - * Underlying function will use this to retrieve the network - * namespace - */ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { ip6_xmit(ctl_sk, buff, &fl, NULL, 0); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); - TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); return; } } ...which starts to be trivial to combine. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 910603cd12d..1941c5c888d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -950,6 +950,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) struct net *net = dev_net(skb->dst->dev); struct sock *ctl_sk = net->ipv6.tcp_sk; unsigned int tot_len = sizeof(struct tcphdr); + __be32 *topt; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *key; #endif @@ -999,14 +1000,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) + skb->len - (th->doff<<2)); } + topt = (__be32 *)(t1 + 1); + #ifdef CONFIG_TCP_MD5SIG if (key) { - __be32 *opt = (__be32*)(t1 + 1); - opt[0] = htonl((TCPOPT_NOP << 24) | - (TCPOPT_NOP << 16) | - (TCPOPT_MD5SIG << 8) | - TCPOLEN_MD5SIG); - tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key, + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); + tcp_v6_md5_hash_hdr((__u8 *)topt, key, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, t1); } -- GitLab From 626e264dd1989bdc98a5eaf2e059af4dba07ac4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 9 Oct 2008 14:42:40 -0700 Subject: [PATCH 3582/5416] tcpv6: combine tcp_v6_send_(reset|ack) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $ codiff tcp_ipv6.o.old tcp_ipv6.o.new net/ipv6/tcp_ipv6.c: tcp_v6_md5_hash_hdr | -144 tcp_v6_send_ack | -585 tcp_v6_send_reset | -540 3 functions changed, 1269 bytes removed, diff: -1269 net/ipv6/tcp_ipv6.c: tcp_v6_send_response | +791 1 function changed, 791 bytes added, diff: +791 tcp_ipv6.o.new: 4 functions changed, 791 bytes added, 1269 bytes removed, diff: -478 I choose to leave the reset related netns comment in place (not the one that is killed) as I cannot understand its English so it's a bit hard for me to evaluate its usefulness :-). Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 139 +++++++++++++------------------------------- 1 file changed, 40 insertions(+), 99 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1941c5c888d..13c65144a00 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -942,7 +942,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } -static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) +static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, + u32 ts, struct tcp_md5sig_key *key, int rst) { struct tcphdr *th = tcp_hdr(skb), *t1; struct sk_buff *buff; @@ -951,31 +952,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) struct sock *ctl_sk = net->ipv6.tcp_sk; unsigned int tot_len = sizeof(struct tcphdr); __be32 *topt; -#ifdef CONFIG_TCP_MD5SIG - struct tcp_md5sig_key *key; -#endif - - if (th->rst) - return; - - if (!ipv6_unicast_destination(skb)) - return; + if (ts) + tot_len += TCPOLEN_TSTAMP_ALIGNED; #ifdef CONFIG_TCP_MD5SIG - if (sk) - key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); - else - key = NULL; - if (key) tot_len += TCPOLEN_MD5SIG_ALIGNED; #endif - /* - * We need to grab some memory, and put together an RST, - * and then put it into the queue to be sent. - */ - buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (buff == NULL) @@ -990,18 +974,21 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) t1->dest = th->source; t1->source = th->dest; t1->doff = tot_len / 4; - t1->rst = 1; - - if(th->ack) { - t1->seq = th->ack_seq; - } else { - t1->ack = 1; - t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin - + skb->len - (th->doff<<2)); - } + t1->seq = htonl(seq); + t1->ack_seq = htonl(ack); + t1->ack = !rst || !th->ack; + t1->rst = rst; + t1->window = htons(win); topt = (__be32 *)(t1 + 1); + if (ts) { + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); + *topt++ = htonl(tcp_time_stamp); + *topt++ = htonl(ts); + } + #ifdef CONFIG_TCP_MD5SIG if (key) { *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | @@ -1036,7 +1023,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { ip6_xmit(ctl_sk, buff, &fl, NULL, 0); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); - TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); + if (rst) + TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); return; } } @@ -1044,87 +1032,40 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) kfree_skb(buff); } -static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, - struct tcp_md5sig_key *key) +static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) { - struct tcphdr *th = tcp_hdr(skb), *t1; - struct sk_buff *buff; - struct flowi fl; - struct net *net = dev_net(skb->dst->dev); - struct sock *ctl_sk = net->ipv6.tcp_sk; - unsigned int tot_len = sizeof(struct tcphdr); - __be32 *topt; - - if (ts) - tot_len += TCPOLEN_TSTAMP_ALIGNED; + struct tcphdr *th = tcp_hdr(skb); + u32 seq = 0, ack_seq = 0; #ifdef CONFIG_TCP_MD5SIG - if (key) - tot_len += TCPOLEN_MD5SIG_ALIGNED; + struct tcp_md5sig_key *key; #endif - buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, - GFP_ATOMIC); - if (buff == NULL) + if (th->rst) return; - skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); - - t1 = (struct tcphdr *) skb_push(buff, tot_len); - - /* Swap the send and the receive. */ - memset(t1, 0, sizeof(*t1)); - t1->dest = th->source; - t1->source = th->dest; - t1->doff = tot_len / 4; - t1->seq = htonl(seq); - t1->ack_seq = htonl(ack); - t1->ack = 1; - t1->window = htons(win); - - topt = (__be32 *)(t1 + 1); - - if (ts) { - *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); - *topt++ = htonl(tcp_time_stamp); - *topt++ = htonl(ts); - } + if (!ipv6_unicast_destination(skb)) + return; #ifdef CONFIG_TCP_MD5SIG - if (key) { - *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); - tcp_v6_md5_hash_hdr((__u8 *)topt, key, - &ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, t1); - } + if (sk) + key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); + else + key = NULL; #endif - buff->csum = csum_partial((char *)t1, tot_len, 0); - - memset(&fl, 0, sizeof(fl)); - ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); - ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); - - t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, - tot_len, IPPROTO_TCP, - buff->csum); - - fl.proto = IPPROTO_TCP; - fl.oif = inet6_iif(skb); - fl.fl_ip_dport = t1->dest; - fl.fl_ip_sport = t1->source; - security_skb_classify_flow(skb, &fl); + if (th->ack) + seq = ntohl(th->ack_seq); + else + ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - + (th->doff << 2); - if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { - if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { - ip6_xmit(ctl_sk, buff, &fl, NULL, 0); - TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); - return; - } - } + tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1); +} - kfree_skb(buff); +static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, + struct tcp_md5sig_key *key) +{ + tcp_v6_send_response(skb, seq, ack, win, ts, key, 0); } static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) -- GitLab From f24d43c07e208372aa3d3bff419afbf43ba87698 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 9 Oct 2008 14:51:27 -0700 Subject: [PATCH 3583/5416] udp: complete port availability checking While looking at UDP port randomization, I noticed it was litle bit pessimistic, not looking at type of sockets (IPV6/IPV4) and not looking at bound addresses if any. We should perform same tests than when binding to a specific port. This permits a cleanup of udp_lib_get_port() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/udp.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 67d8430b4a2..eacf4cfef14 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -122,14 +122,23 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); atomic_t udp_memory_allocated; EXPORT_SYMBOL(udp_memory_allocated); -static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, - const struct hlist_head udptable[]) +static int udp_lib_lport_inuse(struct net *net, __u16 num, + const struct hlist_head udptable[], + struct sock *sk, + int (*saddr_comp)(const struct sock *sk1, + const struct sock *sk2)) { - struct sock *sk; + struct sock *sk2; struct hlist_node *node; - sk_for_each(sk, node, &udptable[udp_hashfn(net, num)]) - if (net_eq(sock_net(sk), net) && sk->sk_hash == num) + sk_for_each(sk2, node, &udptable[udp_hashfn(net, num)]) + if (net_eq(sock_net(sk2), net) && + sk2 != sk && + sk2->sk_hash == num && + (!sk2->sk_reuse || !sk->sk_reuse) && + (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if + || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && + (*saddr_comp)(sk, sk2)) return 1; return 0; } @@ -146,9 +155,6 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, const struct sock *sk2 ) ) { struct hlist_head *udptable = sk->sk_prot->h.udp_hash; - struct hlist_node *node; - struct hlist_head *head; - struct sock *sk2; int error = 1; struct net *net = sock_net(sk); @@ -165,32 +171,21 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, rand = net_random(); snum = first = rand % remaining + low; rand |= 1; - while (__udp_lib_lport_inuse(net, snum, udptable)) { + while (udp_lib_lport_inuse(net, snum, udptable, sk, + saddr_comp)) { do { snum = snum + rand; } while (snum < low || snum > high); if (snum == first) goto fail; } - } else { - head = &udptable[udp_hashfn(net, snum)]; - - sk_for_each(sk2, node, head) - if (sk2->sk_hash == snum && - sk2 != sk && - net_eq(sock_net(sk2), net) && - (!sk2->sk_reuse || !sk->sk_reuse) && - (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if - || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_comp)(sk, sk2) ) - goto fail; - } + } else if (udp_lib_lport_inuse(net, snum, udptable, sk, saddr_comp)) + goto fail; inet_sk(sk)->num = snum; sk->sk_hash = snum; if (sk_unhashed(sk)) { - head = &udptable[udp_hashfn(net, snum)]; - sk_add_node(sk, head); + sk_add_node(sk, &udptable[udp_hashfn(net, snum)]); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); } error = 0; -- GitLab From 3fa8749e584b55f1180411ab1b51117190bac1e5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 9 Oct 2008 15:13:53 -0700 Subject: [PATCH 3584/5416] Linux 2.6.27 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ce9eceb2538..16e3fbb968a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc9 +EXTRAVERSION = NAME = Rotary Wombat # *DOCUMENTATION* -- GitLab From 13c9821ea49be153ea74e5987cf6955871d7b124 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Oct 2008 16:40:29 -0700 Subject: [PATCH 3585/5416] ppp: Use skb_queue_walk() in ppp_mp_insert(). Instead of open-coded version. Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 5d4d21516a6..0ca0fcbb7c0 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1863,9 +1863,10 @@ ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb) /* N.B. we don't need to lock the list lock because we have the ppp unit receive-side lock. */ - for (p = list->next; p != (struct sk_buff *)list; p = p->next) + skb_queue_walk(list, p) { if (seq_before(seq, p->sequence)) break; + } __skb_queue_before(list, p, skb); } -- GitLab From e2ed6e4daa6f16f088600d98568cb5730b5238a6 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 7 Oct 2008 18:26:55 +1100 Subject: [PATCH 3586/5416] powerpc/spufs: set nlink count for spufs root correctly Currently, an empty spufs root inode has nlink count of 1. However, the directory has two links; / -> spu and /spu/ -> . This change increments the link count of the root inode in spufs. Signed-off-by: Jeremy Kerr --- arch/powerpc/platforms/cell/spufs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 690ca7b0dcf..0d262b9f94a 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -755,6 +755,7 @@ spufs_create_root(struct super_block *sb, void *data) inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; SPUFS_I(inode)->i_ctx = NULL; + inc_nlink(inode); ret = -EINVAL; if (!spufs_parse_options(sb, data, inode)) -- GitLab From ba0b996d01eaca4f3cc1f07dcc238fcad7e0d427 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 9 Oct 2008 10:39:21 +1100 Subject: [PATCH 3587/5416] powerpc/spufs: use inc_nlink Style change: use inc_nlink instead of incrementing i_nlink directly Signed-off-by: Jeremy Kerr --- arch/powerpc/platforms/cell/spufs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 0d262b9f94a..d79ac67c9df 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -298,8 +298,8 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, d_instantiate(dentry, inode); dget(dentry); - dir->i_nlink++; - dentry->d_inode->i_nlink++; + inc_nlink(dir); + inc_nlink(dentry->d_inode); goto out; out_free_ctx: @@ -538,8 +538,8 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) inode->i_fop = &simple_dir_operations; d_instantiate(dentry, inode); - dir->i_nlink++; - dentry->d_inode->i_nlink++; + inc_nlink(dir); + inc_nlink(dentry->d_inode); return ret; out_iput: -- GitLab From 6747c2ee8abf749e63fee8cd01a9ee293e6a4247 Mon Sep 17 00:00:00 2001 From: Kou Ishizaki Date: Thu, 9 Oct 2008 10:45:49 +1100 Subject: [PATCH 3588/5416] powerpc/spufs: add a missing mutex_unlock A mutex_unlock(&gang->aff_mutex) in spufs_create_context() is missing in case spufs_context_open() fails. As a result, spu_create syscall and spu_get_idle() may block. This patch adds the mutex_unlock. Signed-off-by: Kou Ishizaki Signed-off-by: Jeremy Kerr Acked-by: Andre Detsch --- arch/powerpc/platforms/cell/spufs/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d79ac67c9df..6b7c7b13245 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -496,6 +496,8 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, ret = spufs_context_open(dget(dentry), mntget(mnt)); if (ret < 0) { WARN_ON(spufs_rmdir(inode, dentry)); + if (affinity) + mutex_unlock(&gang->aff_mutex); mutex_unlock(&inode->i_mutex); spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); goto out; -- GitLab From 300b994b74e75120dd1a48529552a44977e0a82a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 00:18:52 +0400 Subject: [PATCH 3589/5416] proc: fix return value of proc_reg_open() in "too late" case If ->open() wasn't called, returning 0 is misleading and, theoretically, oopsable: 1) remove_proc_entry clears ->proc_fops, drops lock, 2) ->open "succeeds", 3) ->release oopses, because it assumes ->open was called (single_release()). Signed-off-by: Alexey Dobriyan --- fs/proc/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 8bb03f056c2..c6b4fa7e3b4 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -342,7 +342,7 @@ static int proc_reg_open(struct inode *inode, struct file *file) if (!pde->proc_fops) { spin_unlock(&pde->pde_unload_lock); kfree(pdeo); - return rv; + return -EINVAL; } pde->pde_users++; open = pde->proc_fops->open; -- GitLab From e1675231ceedf83f20943a26e5e346a52163dec8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 00:23:32 +0400 Subject: [PATCH 3590/5416] proc: proc_sys_root tweak Signed-off-by: Alexey Dobriyan --- fs/proc/proc_sysctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index f9a8b892718..daa5f51e534 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -395,10 +395,10 @@ static struct dentry_operations proc_sys_dentry_operations = { .d_compare = proc_sys_compare, }; -static struct proc_dir_entry *proc_sys_root; - int proc_sys_init(void) { + struct proc_dir_entry *proc_sys_root; + proc_sys_root = proc_mkdir("sys", NULL); proc_sys_root->proc_iops = &proc_sys_dir_operations; proc_sys_root->proc_fops = &proc_sys_dir_file_operations; -- GitLab From a04f4de6412a4f0ababf9f665674414f26d4cb6e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 00:26:49 +0400 Subject: [PATCH 3591/5416] proc: remove dummy vmcore_open() Empty ->open is equivalent to always succeeding ->open. Signed-off-by: Alexey Dobriyan --- fs/proc/vmcore.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 9ac0f5e064e..841368b87a2 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -165,14 +165,8 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, return acc; } -static int open_vmcore(struct inode *inode, struct file *filp) -{ - return 0; -} - const struct file_operations proc_vmcore_operations = { .read = read_vmcore, - .open = open_vmcore, }; static struct vmcore* __init get_new_element(void) -- GitLab From a70973c2141f98e2046f7ce9a29774bf254cf70f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 00:31:19 +0400 Subject: [PATCH 3592/5416] proc: remove unused get_dma_list() Signed-off-by: Alexey Dobriyan --- arch/arm/kernel/dma.c | 17 ----------------- arch/sparc/include/asm/dma_32.h | 1 - fs/proc/proc_misc.c | 1 - 3 files changed, 19 deletions(-) diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index ba99a203552..d006085ed7e 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -25,23 +25,6 @@ EXPORT_SYMBOL(dma_spin_lock); static dma_t dma_chan[MAX_DMA_CHANNELS]; -/* - * Get dma list for /proc/dma - */ -int get_dma_list(char *buf) -{ - dma_t *dma; - char *p = buf; - int i; - - for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++) - if (dma->lock) - p += sprintf(p, "%2d: %14s %s\n", i, - dma->d_ops->type, dma->device_id); - - return p - buf; -} - /* * Request DMA channel * diff --git a/arch/sparc/include/asm/dma_32.h b/arch/sparc/include/asm/dma_32.h index cf7189c0079..7fa752959b9 100644 --- a/arch/sparc/include/asm/dma_32.h +++ b/arch/sparc/include/asm/dma_32.h @@ -231,7 +231,6 @@ static inline void sparc_dma_pause(struct sparc_dma_registers *regs, #define for_each_dvma(dma) \ for((dma) = dma_chain; (dma); (dma) = (dma)->next) -extern int get_dma_list(char *); extern int request_dma(unsigned int, __const__ char *); extern void free_dma(unsigned int); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 29e20c6b1f7..66c1ab87656 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -68,7 +68,6 @@ extern int get_hardware_list(char *); extern int get_stram_list(char *); extern int get_exec_domain_list(char *); -extern int get_dma_list(char *); static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) -- GitLab From 81324364b76eba592255d4b712e522f9fd8d25f4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 3 Oct 2008 00:33:54 +0400 Subject: [PATCH 3593/5416] proc: make grab_header() static Signed-off-by: Adrian Bunk Signed-off-by: Alexey Dobriyan --- fs/proc/proc_sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index daa5f51e534..945a81043ba 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -66,7 +66,7 @@ static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name) return NULL; } -struct ctl_table_header *grab_header(struct inode *inode) +static struct ctl_table_header *grab_header(struct inode *inode) { if (PROC_I(inode)->sysctl) return sysctl_head_grab(PROC_I(inode)->sysctl); -- GitLab From 53167a3ef23df561d898dee636f3393e9fba937c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Oct 2008 02:01:51 +0400 Subject: [PATCH 3594/5416] proc: move PROC_PAGE_MONITOR to fs/proc/Kconfig Signed-off-by: Alexey Dobriyan --- fs/proc/Kconfig | 10 ++++++++++ init/Kconfig | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig index 73cd7a418f0..50f8f0600f0 100644 --- a/fs/proc/Kconfig +++ b/fs/proc/Kconfig @@ -57,3 +57,13 @@ config PROC_SYSCTL As it is generally a good thing, you should say Y here unless building a kernel for install/rescue disks or your system is very limited in memory. + +config PROC_PAGE_MONITOR + default y + depends on PROC_FS && MMU + bool "Enable /proc page monitoring" if EMBEDDED + help + Various /proc files exist to monitor process memory utilization: + /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap, + /proc/kpagecount, and /proc/kpageflags. Disabling these + interfaces will reduce the size of the kernel by approximately 4kb. diff --git a/init/Kconfig b/init/Kconfig index c11da38837e..8a8e2d00c40 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -779,16 +779,6 @@ config MARKERS source "arch/Kconfig" -config PROC_PAGE_MONITOR - default y - depends on PROC_FS && MMU - bool "Enable /proc page monitoring" if EMBEDDED - help - Various /proc files exist to monitor process memory utilization: - /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap, - /proc/kpagecount, and /proc/kpageflags. Disabling these - interfaces will reduce the size of the kernel by approximately 4kb. - endmenu # General setup config HAVE_GENERIC_DMA_COHERENT -- GitLab From a6bebbc87a8c16eabb6bd5c6fd2d994be0236fba Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 5 Oct 2008 00:51:15 +0400 Subject: [PATCH 3595/5416] [PATCH] signal, procfs: some lock_task_sighand() users do not need rcu_read_lock() lock_task_sighand() make sure task->sighand is being protected, so we do not need rcu_read_lock(). [ exec() will get task->sighand->siglock before change task->sighand! ] But code using rcu_read_lock() _just_ to protect lock_task_sighand() only appear in procfs. (and some code in procfs use lock_task_sighand() without such redundant protection.) Other subsystem may put lock_task_sighand() into rcu_read_lock() critical region, but these rcu_read_lock() are used for protecting "for_each_process()", "find_task_by_vpid()" etc. , not for protecting lock_task_sighand(). Signed-off-by: Lai Jiangshan [ok from Oleg] Signed-off-by: Alexey Dobriyan --- fs/proc/array.c | 2 -- fs/proc/base.c | 9 +-------- kernel/sched_debug.c | 2 -- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 71c9be59c9c..1c8d7b5d7a1 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -261,7 +261,6 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p) sigemptyset(&ignored); sigemptyset(&caught); - rcu_read_lock(); if (lock_task_sighand(p, &flags)) { pending = p->pending.signal; shpending = p->signal->shared_pending.signal; @@ -272,7 +271,6 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p) qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; unlock_task_sighand(p, &flags); } - rcu_read_unlock(); seq_printf(m, "Threads:\t%d\n", num_threads); seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim); diff --git a/fs/proc/base.c b/fs/proc/base.c index a28840b11b8..bb63fa1d34a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -164,7 +164,6 @@ static struct fs_struct *get_fs_struct(struct task_struct *task) static int get_nr_threads(struct task_struct *tsk) { - /* Must be called with the rcu_read_lock held */ unsigned long flags; int count = 0; @@ -471,14 +470,10 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) struct rlimit rlim[RLIM_NLIMITS]; - rcu_read_lock(); - if (!lock_task_sighand(task,&flags)) { - rcu_read_unlock(); + if (!lock_task_sighand(task, &flags)) return 0; - } memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS); unlock_task_sighand(task, &flags); - rcu_read_unlock(); /* * print the file header @@ -3088,9 +3083,7 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct generic_fillattr(inode, stat); if (p) { - rcu_read_lock(); stat->nlink += get_nr_threads(p); - rcu_read_unlock(); put_task_struct(p); } diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index bbe6b31c3c5..ad958c1ec70 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -333,12 +333,10 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) unsigned long flags; int num_threads = 1; - rcu_read_lock(); if (lock_task_sighand(p, &flags)) { num_threads = atomic_read(&p->signal->count); unlock_task_sighand(p, &flags); } - rcu_read_unlock(); SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads); SEQ_printf(m, -- GitLab From 478307230810d7e2a753ed220db9066dfdf88718 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 6 Oct 2008 03:11:58 +0400 Subject: [PATCH 3596/5416] [PATCH] proc: show personality via /proc/pid/personality Make process personality flags visible in /proc. Since a process's personality is potentially sensitive (e.g. READ_IMPLIES_EXEC), make this file only readable by the process owner. Signed-off-by: Kees Cook Signed-off-by: Alexey Dobriyan --- fs/proc/base.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index bb63fa1d34a..c1332dd2575 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2438,6 +2438,13 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) } #endif /* CONFIG_TASK_IO_ACCOUNTING */ +static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +{ + seq_printf(m, "%08x\n", task->personality); + return 0; +} + /* * Thread groups */ @@ -2454,6 +2461,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), ONE("status", S_IRUGO, pid_status), + ONE("personality", S_IRUSR, pid_personality), INF("limits", S_IRUSR, pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, pid_sched), @@ -2789,6 +2797,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), ONE("status", S_IRUGO, pid_status), + ONE("personality", S_IRUSR, pid_personality), INF("limits", S_IRUSR, pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, pid_sched), -- GitLab From 45acb8db06bad529f0feaf89465ce33152640089 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 7 Oct 2008 01:58:45 +0400 Subject: [PATCH 3597/5416] proc: remove now unneeded ADDBUF macro After local seq_file conversion it was forgotten. Signed-off-by: Alexey Dobriyan --- fs/proc/array.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 1c8d7b5d7a1..f4bc0e78953 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -86,11 +86,6 @@ #include #include "internal.h" -/* Gcc optimizes away "strlen(x)" for constant x */ -#define ADDBUF(buffer, string) \ -do { memcpy(buffer, string, strlen(string)); \ - buffer += strlen(string); } while (0) - static inline void task_name(struct seq_file *m, struct task_struct *p) { int i; -- GitLab From 3bbfe0596746e1590888a6e1e6a07583265238b7 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 10 Oct 2008 03:27:16 +0400 Subject: [PATCH 3598/5416] proc: remove kernel.maps_protect After commit 831830b5a2b5d413407adf380ef62fe17d6fcbf2 aka "restrict reading from /proc//maps to those who share ->mm or can ptrace" sysctl stopped being relevant because commit moved security checks from ->show time to ->start time (mm_for_maps()). Signed-off-by: Alexey Dobriyan Acked-by: Kees Cook --- Documentation/filesystems/proc.txt | 7 ------- fs/proc/base.c | 3 --- fs/proc/internal.h | 2 -- fs/proc/task_mmu.c | 16 +--------------- fs/proc/task_nommu.c | 5 ----- kernel/sysctl.c | 11 ----------- 6 files changed, 1 insertion(+), 43 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index f566ad9bcb7..63ed861d5ca 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1332,13 +1332,6 @@ determine whether or not they are still functioning properly. Because the NMI watchdog shares registers with oprofile, by disabling the NMI watchdog, oprofile may have more registers to utilize. -maps_protect ------------- - -Enables/Disables the protection of the per-process proc entries "maps" and -"smaps". When enabled, the contents of these files are visible only to -readers that are allowed to ptrace() the given process. - msgmni ------ diff --git a/fs/proc/base.c b/fs/proc/base.c index c1332dd2575..b5918ae8ca7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -148,9 +148,6 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries, return count; } -int maps_protect; -EXPORT_SYMBOL(maps_protect); - static struct fs_struct *get_fs_struct(struct task_struct *task) { struct fs_struct *fs; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 442202314d5..3bfb7b8747b 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -45,8 +45,6 @@ do { \ extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *); #endif -extern int maps_protect; - extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 73d1891ee62..4806830ea2a 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -210,9 +210,6 @@ static int show_map(struct seq_file *m, void *v) dev_t dev = 0; int len; - if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) - return -EACCES; - if (file) { struct inode *inode = vma->vm_file->f_path.dentry->d_inode; dev = inode->i_sb->s_dev; @@ -742,22 +739,11 @@ const struct file_operations proc_pagemap_operations = { #ifdef CONFIG_NUMA extern int show_numa_map(struct seq_file *m, void *v); -static int show_numa_map_checked(struct seq_file *m, void *v) -{ - struct proc_maps_private *priv = m->private; - struct task_struct *task = priv->task; - - if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) - return -EACCES; - - return show_numa_map(m, v); -} - static const struct seq_operations proc_pid_numa_maps_op = { .start = m_start, .next = m_next, .stop = m_stop, - .show = show_numa_map_checked + .show = show_numa_map, }; static int numa_maps_open(struct inode *inode, struct file *file) diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 5d84e7121df..219bd79ea89 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -110,11 +110,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, static int show_map(struct seq_file *m, void *_vml) { struct vm_list_struct *vml = _vml; - struct proc_maps_private *priv = m->private; - struct task_struct *task = priv->task; - - if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) - return -EACCES; return nommu_vma_show(m, vml->vma); } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 50ec0886fa3..cc3e0d7a5ac 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -80,7 +80,6 @@ extern int pid_max_min, pid_max_max; extern int sysctl_drop_caches; extern int percpu_pagelist_fraction; extern int compat_log; -extern int maps_protect; extern int latencytop_enabled; extern int sysctl_nr_open_min, sysctl_nr_open_max; #ifdef CONFIG_RCU_TORTURE_TEST @@ -809,16 +808,6 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, -#endif -#ifdef CONFIG_PROC_FS - { - .ctl_name = CTL_UNNUMBERED, - .procname = "maps_protect", - .data = &maps_protect, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, #endif { .ctl_name = CTL_UNNUMBERED, -- GitLab From fbcffcc6a0536544fa53cd5bd5c4913efe1a5982 Mon Sep 17 00:00:00 2001 From: Chien Tung Date: Thu, 9 Oct 2008 17:41:05 -0700 Subject: [PATCH 3599/5416] RDMA/nes: Fix slab corruption Referencing cm_node after it is freed via rem_ref_cm_node() causes a slab corruption. There is no need to set cm_node->cm_id to NULL in mini_cm_close(). Signed-off-by: Chien Tung Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_cm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index d69226d7102..2caf9da81ad 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2029,7 +2029,6 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod ret = rem_ref_cm_node(cm_core, cm_node); break; } - cm_node->cm_id = NULL; return ret; } -- GitLab From bb21c95e2d3325fcb53c591686dbbf4068a165bc Mon Sep 17 00:00:00 2001 From: Guo-Fu Tseng Date: Thu, 9 Oct 2008 21:10:36 -0700 Subject: [PATCH 3600/5416] nf_conntrack_ecache.h: Fix missing braces This patch add missing braces of today's net-next-2.6: include/net/netfilter/nf_conntrack_ecache.h Signed-off-by: Guo-Fu Tseng Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_ecache.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 35f814c1e2c..11480e633a9 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -74,6 +74,7 @@ static inline void nf_ct_event_cache_flush(struct net *net) {} static inline int nf_conntrack_ecache_init(struct net *net) { return 0; +} static inline void nf_conntrack_ecache_fini(struct net *net) { -- GitLab From fa3e5b4eb8261ae6ee27922881093db973e9d640 Mon Sep 17 00:00:00 2001 From: Guo-Fu Tseng Date: Thu, 9 Oct 2008 21:11:56 -0700 Subject: [PATCH 3601/5416] tcpv6: fix error with CONFIG_TCP_MD5SIG disabled This patch fix error with CONFIG_TCP_MD5SIG disabled. Signed-off-by: Guo-Fu Tseng Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 13c65144a00..e5310c9b84d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1036,9 +1036,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = tcp_hdr(skb); u32 seq = 0, ack_seq = 0; -#ifdef CONFIG_TCP_MD5SIG - struct tcp_md5sig_key *key; -#endif + struct tcp_md5sig_key *key = NULL; if (th->rst) return; @@ -1049,8 +1047,6 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_TCP_MD5SIG if (sk) key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); - else - key = NULL; #endif if (th->ack) -- GitLab From 9fd3f88cb67ac51bd5face8441472b91e042be67 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 1 Oct 2008 09:44:02 +0000 Subject: [PATCH 3602/5416] powerpc: Oops in pseries_lmb_remove() Testing hotplug memory remove has revealed that we can oops in pseries_lmb_remove(). The incorrect shift causes a NULL pointer dereference in the page_zone() inline routine. I have only been able to reproduce the oops on kernels with large pages enabled. Tested on Power5 and Power6 with and without large pages enabled. Signed-off-by: Nathan Fontenot Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/hotplug-memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index a1a368dd2d9..140d02a5232 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -21,7 +21,7 @@ static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size) struct zone *zone; int ret; - start_pfn = base >> PFN_SECTION_SHIFT; + start_pfn = base >> PAGE_SHIFT; zone = page_zone(pfn_to_page(start_pfn)); /* -- GitLab From 4538d0ca71b4f8991c4c0f433d7d17805738326e Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 6 Oct 2008 07:26:54 +0000 Subject: [PATCH 3603/5416] powerpc: Fix no interrupt handling in pata_of_platform When no interrupt is specified the pata_of_platform fills the irq_res resource with -1, which is wrong to do for two reasons: 1. By definition, 'no irq' should be IRQ 0, not some negative integer; 2. pata_platform checks for irq_res.start > 0, but since irq_res.start is unsigned type, the check will be true for `-1'. Reported-by: Steven A. Falco Signed-off-by: Anton Vorontsov Signed-off-by: Benjamin Herrenschmidt --- drivers/ata/pata_of_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 408da30594c..1f18ad9e4fe 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev, ret = of_irq_to_resource(dn, 0, &irq_res); if (ret == NO_IRQ) - irq_res.start = irq_res.end = -1; + irq_res.start = irq_res.end = 0; else irq_res.flags = 0; -- GitLab From 99c840668c23fa81ac642598c792926021329747 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Mon, 6 Oct 2008 22:38:33 +0000 Subject: [PATCH 3604/5416] powerpc/cell/oprofile: Fix test on overlay_tbl_offset in vma_map Offset is unsigned and when an address isn't found in the vma map vma_map_lookup() returns the vma physical address + 0x10000000. vma_map_lookup used to return 0xffffffff on a failed lookup, but a change was made to return the vma physical address + 0x10000000 There are two callers of vam_map_lookup: one of them correctly deals with this new return value, but the other (below) did not. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Acked-by: Maynard Johnson Signed-off-by: Arnd Bergmann Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/oprofile/cell/vma_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c index fff66662d02..258fa4411e9 100644 --- a/arch/powerpc/oprofile/cell/vma_map.c +++ b/arch/powerpc/oprofile/cell/vma_map.c @@ -229,7 +229,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu, */ overlay_tbl_offset = vma_map_lookup(map, ovly_table_sym, aSpu, &grd_val); - if (overlay_tbl_offset < 0) { + if (overlay_tbl_offset > 0x10000000) { printk(KERN_ERR "SPU_PROF: " "%s, line %d: Error finding SPU overlay table\n", __func__, __LINE__); -- GitLab From 41c2e949cb7b80c5a6247c7df97759953b0f71b5 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 7 Oct 2008 06:10:03 +0000 Subject: [PATCH 3605/5416] powerpc: Fix error path in kernel_thread function The powerpc 32-bit and 64-bit kernel_thread functions don't properly propagate errors being returned by the clone syscall. (In the case of error, the syscall exit code returns a positive errno in r3 and sets the CR0[SO] bit.) This patch fixes that by negating r3 if CR0[SO] is set after the syscall. Signed-off-by: Josh Poimboeuf Signed-off-by: Josh Boyer Acked-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/misc_32.S | 8 +++++--- arch/powerpc/kernel/misc_64.S | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index e9c8ab6eabf..6a9b4bf0d17 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -900,8 +900,10 @@ _GLOBAL(kernel_thread) li r4,0 /* new sp (unused) */ li r0,__NR_clone sc - cmpwi 0,r3,0 /* parent or child? */ - bne 1f /* return if parent */ + bns+ 1f /* did system call indicate error? */ + neg r3,r3 /* if so, make return code negative */ +1: cmpwi 0,r3,0 /* parent or child? */ + bne 2f /* return if parent */ li r0,0 /* make top-level stack frame */ stwu r0,-16(r1) mtlr r30 /* fn addr in lr */ @@ -911,7 +913,7 @@ _GLOBAL(kernel_thread) li r0,__NR_exit /* exit if function returns */ li r3,0 sc -1: lwz r30,8(r1) +2: lwz r30,8(r1) lwz r31,12(r1) addi r1,r1,16 blr diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 4dd70cf7bb4..3053fe5c62f 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -426,8 +426,10 @@ _GLOBAL(kernel_thread) li r4,0 /* new sp (unused) */ li r0,__NR_clone sc - cmpdi 0,r3,0 /* parent or child? */ - bne 1f /* return if parent */ + bns+ 1f /* did system call indicate error? */ + neg r3,r3 /* if so, make return code negative */ +1: cmpdi 0,r3,0 /* parent or child? */ + bne 2f /* return if parent */ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) ld r2,8(r29) @@ -438,7 +440,7 @@ _GLOBAL(kernel_thread) li r0,__NR_exit /* exit after child exits */ li r3,0 sc -1: addi r1,r1,STACK_FRAME_OVERHEAD +2: addi r1,r1,STACK_FRAME_OVERHEAD ld r29,-24(r1) ld r30,-16(r1) blr -- GitLab From 58f467ce1476f5b2a347cee3a32275b737fbd667 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 8 Oct 2008 05:05:29 +0000 Subject: [PATCH 3606/5416] powerpc/of-bindings: Don't support linux, "compatible" values Compatible property values in the form linux, is not documented anywhere and using it leaks Linux implementation details into the device tree data (which is bad). Remove support for compatible values of this form. If any platforms exist which depended on this code (and I don't know of any), then they can be fixed up by adding legacy translations to the lookup table in this file. Signed-off-by: Grant Likely Signed-off-by: Benjamin Herrenschmidt --- drivers/of/base.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ad8ac1a8af2..cd1ce7ab851 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -420,13 +420,12 @@ static struct of_modalias_table of_modalias_table[] = { * @len: Length of modalias value * * Based on the value of the compatible property, this routine will determine - * an appropriate modalias value for a particular device tree node. Three - * separate methods are used to derive a modalias value. + * an appropriate modalias value for a particular device tree node. Two + * separate methods are attempted to derive a modalias value. * * First method is to lookup the compatible value in of_modalias_table. - * Second is to look for a "linux," entry in the compatible list - * and used that for modalias. Third is to strip off the manufacturer - * prefix from the first compatible entry and use the remainder as modalias + * Second is to strip off the manufacturer prefix from the first + * compatible entry and use the remainder as modalias * * This routine returns 0 on success */ @@ -449,21 +448,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) if (!compatible) return -ENODEV; - /* 2. search for linux, entry */ - p = compatible; - while (cplen > 0) { - if (!strncmp(p, "linux,", 6)) { - p += 6; - strlcpy(modalias, p, len); - return 0; - } - - i = strlen(p) + 1; - p += i; - cplen -= i; - } - - /* 3. take first compatible entry and strip manufacturer */ + /* 2. take first compatible entry and strip manufacturer */ p = strchr(compatible, ','); if (!p) return -ENODEV; -- GitLab From 91a00302959545a9ae423e99732b1e46eb19e877 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 8 Oct 2008 14:03:29 +0000 Subject: [PATCH 3607/5416] powerpc: Sync RPA note in zImage with kernel's RPA note Commit 9b09c6d909dfd8de96b99b9b9c808b94b0a71614 ("powerpc: Change the default link address for pSeries zImage kernels") changed the real-base value in the CHRP note added by the addnote program from 12MB to 32MB to give more space for Open Firmware to load the zImage. (The real-base value says where we want OF to position itself in memory.) However, this change was ineffective on most pSeries machines, because the RPA note added by addnote has the "ignore me" flag set to 1. This was intended to tell OF to ignore just the RPA note, but has the side effect of also making OF ignore the CHRP note (at least on most pSeries machines). To solve this we have to set the "ignore me" flag to 0 in the RPA note. (We can't just omit the RPA note because that is equivalent to having an RPA note with default values, and the default values are not what we want.) However, then we have to make sure the values in the zImage's RPA note match up with the values that the kernel supplies later in prom_init.c with either the ibm,client-architecture-support call or the process-elf-header call in prom_send_capabilities(). So this sets the "ignore me" flag in the RPA note in addnote to 0, and adjusts the RPA note values in addnote.c and in prom_init.c to be consistent with each other and with the values in ibm_architecture_vec. However, since the wrapper is independent of the kernel, this doesn't ensure that the notes will stay consistent. To ensure that, this adds code to addnote.c so that it can extract the kernel's RPA note from the kernel binary and put that in the zImage. To that end, we put the kernel's fake ELF header (which contains the kernel's RPA note) into its own section, and arrange for wrapper to pull out that section with objcopy and pass it to addnote, which then extracts the RPA note from it and transfers it to the zImage. Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/boot/addnote.c | 144 ++++++++++++++++++++++-------- arch/powerpc/boot/wrapper | 4 +- arch/powerpc/kernel/prom_init.c | 10 +-- arch/powerpc/kernel/vmlinux.lds.S | 3 + 4 files changed, 119 insertions(+), 42 deletions(-) diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c index b1e5611b2ab..dcc9ab2ca82 100644 --- a/arch/powerpc/boot/addnote.c +++ b/arch/powerpc/boot/addnote.c @@ -11,7 +11,12 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Usage: addnote zImage + * Usage: addnote zImage [note.elf] + * + * If note.elf is supplied, it is the name of an ELF file that contains + * an RPA note to use instead of the built-in one. Alternatively, the + * note.elf file may be empty, in which case the built-in RPA note is + * used (this is to simplify how this is invoked from the wrapper script). */ #include #include @@ -43,27 +48,29 @@ char rpaname[] = "IBM,RPA-Client-Config"; */ #define N_RPA_DESCR 8 unsigned int rpanote[N_RPA_DESCR] = { - 0, /* lparaffinity */ - 64, /* min_rmo_size */ + 1, /* lparaffinity */ + 128, /* min_rmo_size */ 0, /* min_rmo_percent */ - 40, /* max_pft_size */ + 46, /* max_pft_size */ 1, /* splpar */ -1, /* min_load */ - 0, /* new_mem_def */ - 1, /* ignore_my_client_config */ + 1, /* new_mem_def */ + 0, /* ignore_my_client_config */ }; #define ROUNDUP(len) (((len) + 3) & ~3) unsigned char buf[512]; +unsigned char notebuf[512]; -#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) -#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2)) +#define GET_16BE(b, off) (((b)[off] << 8) + ((b)[(off)+1])) +#define GET_32BE(b, off) ((GET_16BE((b), (off)) << 16) + \ + GET_16BE((b), (off)+2)) -#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \ - buf[(off) + 1] = (v) & 0xff) -#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \ - PUT_16BE((off) + 2, (v))) +#define PUT_16BE(b, off, v) ((b)[off] = ((v) >> 8) & 0xff, \ + (b)[(off) + 1] = (v) & 0xff) +#define PUT_32BE(b, off, v) (PUT_16BE((b), (off), (v) >> 16), \ + PUT_16BE((b), (off) + 2, (v))) /* Structure of an ELF file */ #define E_IDENT 0 /* ELF header */ @@ -88,15 +95,71 @@ unsigned char buf[512]; unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; +unsigned char *read_rpanote(const char *fname, int *nnp) +{ + int notefd, nr, i; + int ph, ps, np; + int note, notesize; + + notefd = open(fname, O_RDONLY); + if (notefd < 0) { + perror(fname); + exit(1); + } + nr = read(notefd, notebuf, sizeof(notebuf)); + if (nr < 0) { + perror("read note"); + exit(1); + } + if (nr == 0) /* empty file */ + return NULL; + if (nr < E_HSIZE || + memcmp(¬ebuf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0 || + notebuf[E_IDENT+EI_CLASS] != ELFCLASS32 || + notebuf[E_IDENT+EI_DATA] != ELFDATA2MSB) + goto notelf; + close(notefd); + + /* now look for the RPA-note */ + ph = GET_32BE(notebuf, E_PHOFF); + ps = GET_16BE(notebuf, E_PHENTSIZE); + np = GET_16BE(notebuf, E_PHNUM); + if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) + goto notelf; + + for (i = 0; i < np; ++i, ph += ps) { + if (GET_32BE(notebuf, ph + PH_TYPE) != PT_NOTE) + continue; + note = GET_32BE(notebuf, ph + PH_OFFSET); + notesize = GET_32BE(notebuf, ph + PH_FILESZ); + if (notesize < 34 || note + notesize > nr) + continue; + if (GET_32BE(notebuf, note) != strlen(rpaname) + 1 || + GET_32BE(notebuf, note + 8) != 0x12759999 || + strcmp((char *)¬ebuf[note + 12], rpaname) != 0) + continue; + /* looks like an RPA note, return it */ + *nnp = notesize; + return ¬ebuf[note]; + } + /* no RPA note found */ + return NULL; + + notelf: + fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", fname); + exit(1); +} + int main(int ac, char **av) { int fd, n, i; int ph, ps, np; int nnote, nnote2, ns; + unsigned char *rpap; - if (ac != 2) { - fprintf(stderr, "Usage: %s elf-file\n", av[0]); + if (ac != 2 && ac != 3) { + fprintf(stderr, "Usage: %s elf-file [rpanote.elf]\n", av[0]); exit(1); } fd = open(av[1], O_RDWR); @@ -107,6 +170,7 @@ main(int ac, char **av) nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr); nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote); + rpap = NULL; n = read(fd, buf, sizeof(buf)); if (n < 0) { @@ -124,16 +188,19 @@ main(int ac, char **av) exit(1); } - ph = GET_32BE(E_PHOFF); - ps = GET_16BE(E_PHENTSIZE); - np = GET_16BE(E_PHNUM); + if (ac == 3) + rpap = read_rpanote(av[2], &nnote2); + + ph = GET_32BE(buf, E_PHOFF); + ps = GET_16BE(buf, E_PHENTSIZE); + np = GET_16BE(buf, E_PHNUM); if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) goto notelf; if (ph + (np + 2) * ps + nnote + nnote2 > n) goto nospace; for (i = 0; i < np; ++i) { - if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { + if (GET_32BE(buf, ph + PH_TYPE) == PT_NOTE) { fprintf(stderr, "%s already has a note entry\n", av[1]); exit(0); @@ -148,37 +215,42 @@ main(int ac, char **av) /* fill in the program header entry */ ns = ph + 2 * ps; - PUT_32BE(ph + PH_TYPE, PT_NOTE); - PUT_32BE(ph + PH_OFFSET, ns); - PUT_32BE(ph + PH_FILESZ, nnote); + PUT_32BE(buf, ph + PH_TYPE, PT_NOTE); + PUT_32BE(buf, ph + PH_OFFSET, ns); + PUT_32BE(buf, ph + PH_FILESZ, nnote); /* fill in the note area we point to */ /* XXX we should probably make this a proper section */ - PUT_32BE(ns, strlen(arch) + 1); - PUT_32BE(ns + 4, N_DESCR * 4); - PUT_32BE(ns + 8, 0x1275); + PUT_32BE(buf, ns, strlen(arch) + 1); + PUT_32BE(buf, ns + 4, N_DESCR * 4); + PUT_32BE(buf, ns + 8, 0x1275); strcpy((char *) &buf[ns + 12], arch); ns += 12 + strlen(arch) + 1; for (i = 0; i < N_DESCR; ++i, ns += 4) - PUT_32BE(ns, descr[i]); + PUT_32BE(buf, ns, descr[i]); /* fill in the second program header entry and the RPA note area */ ph += ps; - PUT_32BE(ph + PH_TYPE, PT_NOTE); - PUT_32BE(ph + PH_OFFSET, ns); - PUT_32BE(ph + PH_FILESZ, nnote2); + PUT_32BE(buf, ph + PH_TYPE, PT_NOTE); + PUT_32BE(buf, ph + PH_OFFSET, ns); + PUT_32BE(buf, ph + PH_FILESZ, nnote2); /* fill in the note area we point to */ - PUT_32BE(ns, strlen(rpaname) + 1); - PUT_32BE(ns + 4, sizeof(rpanote)); - PUT_32BE(ns + 8, 0x12759999); - strcpy((char *) &buf[ns + 12], rpaname); - ns += 12 + ROUNDUP(strlen(rpaname) + 1); - for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) - PUT_32BE(ns, rpanote[i]); + if (rpap) { + /* RPA note supplied in file, just copy the whole thing over */ + memcpy(buf + ns, rpap, nnote2); + } else { + PUT_32BE(buf, ns, strlen(rpaname) + 1); + PUT_32BE(buf, ns + 4, sizeof(rpanote)); + PUT_32BE(buf, ns + 8, 0x12759999); + strcpy((char *) &buf[ns + 12], rpaname); + ns += 12 + ROUNDUP(strlen(rpaname) + 1); + for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) + PUT_32BE(buf, ns, rpanote[i]); + } /* Update the number of program headers */ - PUT_16BE(E_PHNUM, np + 2); + PUT_16BE(buf, E_PHNUM, np + 2); /* write back */ lseek(fd, (long) 0, SEEK_SET); diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 965c237c122..ee0dc41d7c5 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -307,7 +307,9 @@ fi # post-processing needed for some platforms case "$platform" in pseries|chrp) - $objbin/addnote "$ofile" + ${CROSS}objcopy -O binary -j .fakeelf "$kernel" "$ofile".rpanote + $objbin/addnote "$ofile" "$ofile".rpanote + rm -r "$ofile".rpanote ;; coff) ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7cf274a2b33..2fdbc18ae94 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -732,7 +732,7 @@ static struct fake_elf { u32 ignore_me; } rpadesc; } rpanote; -} fake_elf = { +} fake_elf __section(.fakeelf) = { .elfhdr = { .e_ident = { 0x7f, 'E', 'L', 'F', ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, @@ -774,13 +774,13 @@ static struct fake_elf { .type = 0x12759999, .name = "IBM,RPA-Client-Config", .rpadesc = { - .lpar_affinity = 0, - .min_rmo_size = 64, /* in megabytes */ + .lpar_affinity = 1, + .min_rmo_size = 128, /* in megabytes */ .min_rmo_percent = 0, - .max_pft_size = 48, /* 2^48 bytes max PFT size */ + .max_pft_size = 46, /* 2^46 bytes max PFT size */ .splpar = 1, .min_load = ~0U, - .new_mem_def = 0 + .new_mem_def = 1 } } }; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index e6927fb2e65..b39c27ed791 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -203,6 +203,9 @@ SECTIONS *(.rela*) } + /* Fake ELF header containing RPA note; for addnote */ + .fakeelf : AT(ADDR(.fakeelf) - LOAD_OFFSET) { *(.fakeelf) } + /* freed after init ends here */ . = ALIGN(PAGE_SIZE); __init_end = .; -- GitLab From 8f64e1f2d1e09267ac926e15090fd505c1c0cbcb Mon Sep 17 00:00:00 2001 From: Jon Tollefson Date: Thu, 9 Oct 2008 10:18:40 +0000 Subject: [PATCH 3608/5416] powerpc: Reserve in bootmem lmb reserved regions that cross NUMA nodes If there are multiple reserved memory blocks via lmb_reserve() that are contiguous addresses and on different NUMA nodes we are losing track of which address ranges to reserve in bootmem on which node. I discovered this when I recently got to try 16GB huge pages on a system with more then 2 nodes. When scanning the device tree in early boot we call lmb_reserve() with the addresses of the 16G pages that we find so that the memory doesn't get used for something else. For example the addresses for the pages could be 4000000000, 4400000000, 4800000000, 4C00000000, etc - 8 pages, one on each of eight nodes. In the lmb after all the pages have been reserved it will look something like the following: lmb_dump_all: memory.cnt = 0x2 memory.size = 0x3e80000000 memory.region[0x0].base = 0x0 .size = 0x1e80000000 memory.region[0x1].base = 0x4000000000 .size = 0x2000000000 reserved.cnt = 0x5 reserved.size = 0x3e80000000 reserved.region[0x0].base = 0x0 .size = 0x7b5000 reserved.region[0x1].base = 0x2a00000 .size = 0x78c000 reserved.region[0x2].base = 0x328c000 .size = 0x43000 reserved.region[0x3].base = 0xf4e8000 .size = 0xb18000 reserved.region[0x4].base = 0x4000000000 .size = 0x2000000000 The reserved.region[0x4] contains the 16G pages. In arch/powerpc/mm/num.c: do_init_bootmem() we loop through each of the node numbers looking for the reserved regions that belong to the particular node. It is not able to identify region 0x4 as being a part of each of the 8 nodes. It is assuming that a reserved region is only on a single node. This patch takes out the reserved region loop from inside the loop that goes over each node. It looks up the active region containing the start of the reserved region. If it extends past that active region then it adjusts the size and gets the next active region containing it. Signed-off-by: Jon Tollefson Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/numa.c | 108 ++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index be05457631d..6cf5c71c431 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -89,6 +89,46 @@ static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn, return 0; } +/* + * get_active_region_work_fn - A helper function for get_node_active_region + * Returns datax set to the start_pfn and end_pfn if they contain + * the initial value of datax->start_pfn between them + * @start_pfn: start page(inclusive) of region to check + * @end_pfn: end page(exclusive) of region to check + * @datax: comes in with ->start_pfn set to value to search for and + * goes out with active range if it contains it + * Returns 1 if search value is in range else 0 + */ +static int __init get_active_region_work_fn(unsigned long start_pfn, + unsigned long end_pfn, void *datax) +{ + struct node_active_region *data; + data = (struct node_active_region *)datax; + + if (start_pfn <= data->start_pfn && end_pfn > data->start_pfn) { + data->start_pfn = start_pfn; + data->end_pfn = end_pfn; + return 1; + } + return 0; + +} + +/* + * get_node_active_region - Return active region containing start_pfn + * @start_pfn: The page to return the region for. + * @node_ar: Returned set to the active region containing start_pfn + */ +static void __init get_node_active_region(unsigned long start_pfn, + struct node_active_region *node_ar) +{ + int nid = early_pfn_to_nid(start_pfn); + + node_ar->nid = nid; + node_ar->start_pfn = start_pfn; + work_with_active_regions(nid, get_active_region_work_fn, node_ar); +} + static void __cpuinit map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; @@ -882,38 +922,50 @@ void __init do_init_bootmem(void) start_pfn, end_pfn); free_bootmem_with_active_regions(nid, end_pfn); + } - /* Mark reserved regions on this node */ - for (i = 0; i < lmb.reserved.cnt; i++) { - unsigned long physbase = lmb.reserved.region[i].base; - unsigned long size = lmb.reserved.region[i].size; - unsigned long start_paddr = start_pfn << PAGE_SHIFT; - unsigned long end_paddr = end_pfn << PAGE_SHIFT; - - if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid && - early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid) - continue; - - if (physbase < end_paddr && - (physbase+size) > start_paddr) { - /* overlaps */ - if (physbase < start_paddr) { - size -= start_paddr - physbase; - physbase = start_paddr; - } - - if (size > end_paddr - physbase) - size = end_paddr - physbase; - - dbg("reserve_bootmem %lx %lx\n", physbase, - size); - reserve_bootmem_node(NODE_DATA(nid), physbase, - size, BOOTMEM_DEFAULT); - } + /* Mark reserved regions */ + for (i = 0; i < lmb.reserved.cnt; i++) { + unsigned long physbase = lmb.reserved.region[i].base; + unsigned long size = lmb.reserved.region[i].size; + unsigned long start_pfn = physbase >> PAGE_SHIFT; + unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT); + struct node_active_region node_ar; + + get_node_active_region(start_pfn, &node_ar); + while (start_pfn < end_pfn) { + /* + * if reserved region extends past active region + * then trim size to active region + */ + if (end_pfn > node_ar.end_pfn) + size = (node_ar.end_pfn << PAGE_SHIFT) + - (start_pfn << PAGE_SHIFT); + dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, size, + node_ar.nid); + reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, + size, BOOTMEM_DEFAULT); + /* + * if reserved region is contained in the active region + * then done. + */ + if (end_pfn <= node_ar.end_pfn) + break; + + /* + * reserved region extends past the active region + * get next active region that contains this + * reserved region + */ + start_pfn = node_ar.end_pfn; + physbase = start_pfn << PAGE_SHIFT; + get_node_active_region(start_pfn, &node_ar); } - sparse_memory_present_with_active_regions(nid); } + + for_each_online_node(nid) + sparse_memory_present_with_active_regions(nid); } void __init paging_init(void) -- GitLab From 55ed31e62d18094337319b942b38cfc00360444b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Oct 2008 22:13:53 -0700 Subject: [PATCH 3609/5416] enic: Attempt to fix build in 32-bit such as i386. Such platforms lack readq/writeq but this driver want to call them. Noticed by Andrew Morton. Signed-off-by: David S. Miller --- drivers/net/enic/vnic_dev.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index 2dcffd3a24b..b9dc1821c80 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h @@ -27,6 +27,20 @@ #define VNIC_PADDR_TARGET 0x0000000000000000ULL #endif +#ifndef readq +static inline u64 readq(void __iomem *reg) +{ + return (((u64)readl(reg + 0x4UL) << 32) | + (u64)readl(reg)); +} + +static inline void writeq(u64 val, void __iomem *reg) +{ + writel(val & 0xffffffff, reg); + writel(val >> 32, reg + 0x4UL); +} +#endif + enum vnic_dev_intr_mode { VNIC_DEV_INTR_MODE_UNKNOWN, VNIC_DEV_INTR_MODE_INTX, -- GitLab From b911e473d24633c19414b54b82b9ff0b1a2419d7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 10 Oct 2008 08:22:44 +0200 Subject: [PATCH 3610/5416] doc/cdrom: Trvial documentation error, file not present The sbpcd tester program is not included in the kernel source tree, so remove the reference to it. Signed-off-by: Randy Dunlap Reported-by: Nick Warne Signed-off-by: Jens Axboe --- Documentation/cdrom/ide-cd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd index 91c0dcc6fa5..2c558cd6c1e 100644 --- a/Documentation/cdrom/ide-cd +++ b/Documentation/cdrom/ide-cd @@ -145,8 +145,7 @@ useful for reading photocds. To play an audio CD, you should first unmount and remove any data CDROM. Any of the CDROM player programs should then work (workman, -workbone, cdplayer, etc.). Lacking anything else, you could use the -cdtester program in Documentation/cdrom/sbpcd. +workbone, cdplayer, etc.). On a few drives, you can read digital audio directly using a program such as cdda2wav. The only types of drive which I've heard support -- GitLab From f26ed116c0baa8f9cbbe3d5db84034d75f6250f8 Mon Sep 17 00:00:00 2001 From: David John Date: Fri, 10 Oct 2008 11:42:44 +0530 Subject: [PATCH 3611/5416] HPET: Remove spurious HPET busy warning message. On x86 systems with CONFIG_HPET_TIMER enabled, when the HPET driver (drivers/char/hpet.c) is loaded, an incorrect busy message is printed when the driver initializes since the HPET has already been allocated by the core timer code. Remove the warning message. Signed-off-by: David John Acked-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar --- drivers/char/hpet.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 2908a0eb63a..f3cfb4c7612 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -897,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) hdp->hd_address = ioremap(addr.minimum, addr.address_length); if (hpet_is_known(hdp)) { - printk(KERN_DEBUG "%s: 0x%lx is busy\n", - __func__, hdp->hd_phys_address); iounmap(hdp->hd_address); return AE_ALREADY_EXISTS; } @@ -914,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) HPET_RANGE_SIZE); if (hpet_is_known(hdp)) { - printk(KERN_DEBUG "%s: 0x%lx is busy\n", - __func__, hdp->hd_phys_address); iounmap(hdp->hd_address); return AE_ALREADY_EXISTS; } -- GitLab From 778e4875fb9ac8dcef654aaadb53a953cde96026 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Thu, 9 Oct 2008 17:51:43 +0300 Subject: [PATCH 3612/5416] ARM: OMAP3: Defconfig for the Gumstix Overo board (rev 3) Add defconfig for the Gumstix Overo board Signed-off-by: Steve Sakoman Signed-off-by: Tony Lindgren --- arch/arm/configs/overo_defconfig | 1885 ++++++++++++++++++++++++++++++ 1 file changed, 1885 insertions(+) create mode 100644 arch/arm/configs/overo_defconfig diff --git a/arch/arm/configs/overo_defconfig b/arch/arm/configs/overo_defconfig new file mode 100644 index 00000000000..49200967a15 --- /dev/null +++ b/arch/arm/configs/overo_defconfig @@ -0,0 +1,1885 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc8 +# Fri Oct 3 11:50:34 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_OPROFILE_ARMV7=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_LSF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM7X00A is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP3_BEAGLE is not set +CONFIG_MACH_OVERO=y + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_LEDS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE=" debug " +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +# CONFIG_BT_HCIUART_LL is not set +CONFIG_BT_HCIBCM203X=y +CONFIG_BT_HCIBPA10X=y +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +CONFIG_CFG80211=y +CONFIG_NL80211=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_MAC80211=y + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_IEEE80211=y +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=y +CONFIG_IEEE80211_CRYPT_CCMP=y +CONFIG_IEEE80211_CRYPT_TKIP=y +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +CONFIG_EEPROM_93CX6=m +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_DELAY=m +# CONFIG_DM_UEVENT is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +# CONFIG_NET_ETHERNET is not set +CONFIG_MII=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=y +CONFIG_LIBERTAS_USB=y +CONFIG_LIBERTAS_SDIO=y +CONFIG_LIBERTAS_DEBUG=y +CONFIG_USB_ZD1201=m +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_RTL8187=m +# CONFIG_MAC80211_HWSIM is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_IWLWIFI_LEDS is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_ISP1301_OMAP is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=m +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_DVB_CORE=m +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX2341X=m +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_AU0828 is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +# CONFIG_USB_GSPCA is not set +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +# CONFIG_VIDEO_EM28XX is not set +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +# CONFIG_USB_ET61X251 is not set +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +# CONFIG_USB_ZC0301 is not set +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_ZR364XX=m +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_USB_DSBR is not set +# CONFIG_USB_SI470X is not set +CONFIG_DVB_CAPTURE_DRIVERS=y +# CONFIG_TTPCI_EEPROM is not set + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +# CONFIG_DVB_USB_DW2102 is not set +# CONFIG_DVB_USB_ANYSEE is not set +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +# CONFIG_DVB_CINERGYT2_TUNING is not set +# CONFIG_DVB_SIANO_SMS1XXX is not set + +# +# Supported FlexCopII (B2C2) Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +# CONFIG_DVB_DRX397XD is not set +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_S5H1411=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +# CONFIG_DVB_ISL6405 is not set +CONFIG_DVB_ISL6421=m +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +# CONFIG_SND_DEBUG_VERBOSE is not set +# CONFIG_SND_PCM_XRUN_DEBUG is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +CONFIG_USB_MUSB_HOST=y +# CONFIG_USB_MUSB_PERIPHERAL is not set +# CONFIG_USB_MUSB_OTG is not set +CONFIG_USB_MUSB_HDRC_HCD=y +CONFIG_MUSB_PIO_ONLY=y +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +# CONFIG_USB_EZUSB is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP2101 is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_RIO500 is not set +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +# CONFIG_USB_BERRY_CHARGE is not set +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_GADGET is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA955X is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=m +CONFIG_CRYPTO_XCBC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From 492656511b109b5f9ee64d05c90b5bd9043549fa Mon Sep 17 00:00:00 2001 From: Nishant Kamat Date: Fri, 10 Oct 2008 11:28:23 +0300 Subject: [PATCH 3613/5416] ARM: OMAP3: Add basic board support for OMAP LDP This adds minimal board support for the OMAP3430 LDP development platform. Signed-off-by: Nishant Kamat Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 4 + arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/board-ldp.c | 86 +++++++++++++++++++++ arch/arm/plat-omap/include/mach/board-ldp.h | 36 +++++++++ arch/arm/plat-omap/include/mach/hardware.h | 4 + 5 files changed, 131 insertions(+) create mode 100644 arch/arm/mach-omap2/board-ldp.c create mode 100644 arch/arm/plat-omap/include/mach/board-ldp.h diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index aef043b87b4..4832fcc7d04 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -48,6 +48,10 @@ config MACH_OMAP3_BEAGLE bool "OMAP3 BEAGLE board" depends on ARCH_OMAP3 && ARCH_OMAP34XX +config MACH_OMAP_LDP + bool "OMAP3 LDP board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + config MACH_OVERO bool "Gumstix Overo board" depends on ARCH_OMAP3 && ARCH_OMAP34XX diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index feb9caf771d..c69392372c9 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -30,5 +30,6 @@ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o +obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o obj-$(CONFIG_MACH_OVERO) += board-overo.o diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c new file mode 100644 index 00000000000..1ea59986aa7 --- /dev/null +++ b/arch/arm/mach-omap2/board-ldp.c @@ -0,0 +1,86 @@ +/* + * linux/arch/arm/mach-omap2/board-ldp.c + * + * Copyright (C) 2008 Texas Instruments Inc. + * Nishant Kamat + * + * Modified from mach-omap2/board-3430sdp.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static void __init omap_ldp_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); +} + +static struct omap_uart_config ldp_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct omap_board_config_kernel ldp_config[] __initdata = { + { OMAP_TAG_UART, &ldp_uart_config }, +}; + +static int __init omap_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, NULL, 0); + omap_register_i2c_bus(2, 400, NULL, 0); + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + +static void __init omap_ldp_init(void) +{ + omap_i2c_init(); + omap_board_config = ldp_config; + omap_board_config_size = ARRAY_SIZE(ldp_config); + omap_serial_init(); +} + +static void __init omap_ldp_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP_LDP, "OMAP LDP board") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_ldp_map_io, + .init_irq = omap_ldp_init_irq, + .init_machine = omap_ldp_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/plat-omap/include/mach/board-ldp.h b/arch/arm/plat-omap/include/mach/board-ldp.h new file mode 100644 index 00000000000..66e2746c04c --- /dev/null +++ b/arch/arm/plat-omap/include/mach/board-ldp.h @@ -0,0 +1,36 @@ +/* + * arch/arm/plat-omap/include/mach/board-ldp.h + * + * Hardware definitions for TI OMAP3 LDP. + * + * Copyright (C) 2008 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OMAP_LDP_H +#define __ASM_ARCH_OMAP_LDP_H + +extern void twl4030_bci_battery_init(void); + +#define TWL4030_IRQNUM INT_34XX_SYS_NIRQ + +#endif /* __ASM_ARCH_OMAP_LDP_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 80f6d7ec53e..6589ddbb63b 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -326,6 +326,10 @@ #include "board-omap3beagle.h" #endif +#ifdef CONFIG_MACH_OMAP_LDP +#include "board-ldp.h" +#endif + #ifdef CONFIG_MACH_OMAP_APOLLON #include "board-apollon.h" #endif -- GitLab From 99b3075b9095c23acf8d884bdc7fe33c8c3520f0 Mon Sep 17 00:00:00 2001 From: Nishant Kamat Date: Fri, 10 Oct 2008 11:48:56 +0300 Subject: [PATCH 3614/5416] ARM: OMAP3: Add default kernel config for OMAP LDP This patch adds a default config for the OMAP LDP platform. Signed-off-by: Nishant Kamat Signed-off-by: Tony Lindgren --- arch/arm/configs/omap_ldp_defconfig | 1044 +++++++++++++++++++++++++++ 1 file changed, 1044 insertions(+) create mode 100644 arch/arm/configs/omap_ldp_defconfig diff --git a/arch/arm/configs/omap_ldp_defconfig b/arch/arm/configs/omap_ldp_defconfig new file mode 100644 index 00000000000..948a212fb1c --- /dev/null +++ b/arch/arm/configs/omap_ldp_defconfig @@ -0,0 +1,1044 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-rc5 +# Fri Oct 10 11:49:41 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM7X00A is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +CONFIG_OMAP_MUX=y +CONFIG_OMAP_MUX_DEBUG=y +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_OMAP_SERIAL_WAKE=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP3_BEAGLE is not set +CONFIG_MACH_OMAP_LDP=y +# CONFIG_MACH_OVERO is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_ISP1301_OMAP is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +CONFIG_W1=y + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_GPIO is not set + +# +# 1-wire Slaves +# +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2760 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +# CONFIG_SND_SOC is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +# CONFIG_MMC_SPI is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From 2043f3f7312cc7fbbc2acffb9d87265b0ad9a529 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 13 Oct 2008 14:46:30 +0800 Subject: [PATCH 3615/5416] Blackfin arch: Enable framebuffer support for the BF526-EZkit TFT LCD display Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 8482d22321f..ccfa0880184 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -582,6 +582,13 @@ static struct bfin5xx_spi_chip spidev_chip_info = { }; #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +static struct bfin5xx_spi_chip lq035q1_spi_chip_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + #if defined(CONFIG_MTD_DATAFLASH) \ || defined(CONFIG_MTD_DATAFLASH_MODULE) @@ -730,6 +737,16 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .controller_data = &spidev_chip_info, }, #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + { + .modalias = "bfin-lq035q1-spi", + .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, + .controller_data = &lq035q1_spi_chip_info, + .mode = SPI_CPHA | SPI_CPOL, + }, +#endif }; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) @@ -777,6 +794,34 @@ static struct platform_device bfin_fb_adv7393_device = { }; #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) +#include + +static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = { + .mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB, + .use_bl = 1, + .gpio_bl = GPIO_PF7, +}; + +static struct resource bfin_lq035q1_resources[] = { + { + .start = IRQ_PPI_ERROR, + .end = IRQ_PPI_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_lq035q1_device = { + .name = "bfin-lq035q1", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_lq035q1_resources), + .resource = bfin_lq035q1_resources, + .dev = { + .platform_data = &bfin_lq035q1_data, + }, +}; +#endif + #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) static struct resource bfin_uart_resources[] = { #ifdef CONFIG_SERIAL_BFIN_UART0 @@ -997,6 +1042,10 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_fb_device, #endif +#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE) + &bfin_lq035q1_device, +#endif + #if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE) &bfin_fb_adv7393_device, #endif -- GitLab From d207a8c7681f14302e9e80ef5b8202abe39060b5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:26:57 +0800 Subject: [PATCH 3616/5416] Blackfin arch: ptrace - fix off-by-one check on end of memory regions Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 50 +++++++++++++++-------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index e8172eece04..7e1f762b670 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -161,15 +161,15 @@ static inline int is_user_addr_valid(struct task_struct *child, struct sram_list_struct *sraml; for (vml = child->mm->context.vmlist; vml; vml = vml->next) - if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end) + if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end) return 0; for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) if (start >= (unsigned long)sraml->addr - && start + len <= (unsigned long)sraml->addr + sraml->length) + && start + len < (unsigned long)sraml->addr + sraml->length) return 0; - if (start >= FIXED_CODE_START && start + len <= FIXED_CODE_END) + if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) return 0; return -EIO; @@ -216,34 +216,30 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; pr_debug("ptrace: user address is valid\n"); -#if L1_CODE_LENGTH != 0 - if (addr >= L1_CODE_START + if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif -#if L1_DATA_A_LENGTH != 0 - if (addr >= L1_DATA_A_START + + } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif -#if L1_DATA_B_LENGTH != 0 - if (addr >= L1_DATA_B_START + + } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); - } else -#endif - if (addr >= FIXED_CODE_START + + } else if (addr >= FIXED_CODE_START && addr + sizeof(tmp) <= FIXED_CODE_END) { memcpy(&tmp, (const void *)(addr), sizeof(tmp)); copied = sizeof(tmp); + } else copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); if (copied != sizeof(tmp)) break; @@ -300,34 +296,30 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; pr_debug("ptrace: user address is valid\n"); -#if L1_CODE_LENGTH != 0 - if (addr >= L1_CODE_START + if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif -#if L1_DATA_A_LENGTH != 0 - if (addr >= L1_DATA_A_START + + } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif -#if L1_DATA_B_LENGTH != 0 - if (addr >= L1_DATA_B_START + + } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); - } else -#endif - if (addr >= FIXED_CODE_START + + } else if (addr >= FIXED_CODE_START && addr + sizeof(data) <= FIXED_CODE_END) { memcpy((void *)(addr), &data, sizeof(data)); copied = sizeof(data); + } else copied = access_process_vm(child, addr, &data, sizeof(data), 1); + pr_debug("ptrace: copied size %d\n", copied); if (copied != sizeof(data)) break; -- GitLab From 3c08f1d122627c9559fb03a11f52ea37f960b61e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:12:51 +0800 Subject: [PATCH 3617/5416] Blackfin arch: have is_user_addr_valid() check for overflows (like when address is -1) Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/ptrace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 7e1f762b670..140bf00e997 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -160,6 +160,10 @@ static inline int is_user_addr_valid(struct task_struct *child, struct vm_list_struct *vml; struct sram_list_struct *sraml; + /* overflow */ + if (start + len < start) + return -EIO; + for (vml = child->mm->context.vmlist; vml; vml = vml->next) if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end) return 0; -- GitLab From 5b7dba4ff834259a5623e03a565748704a8fe449 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 9 Oct 2008 13:21:30 -0500 Subject: [PATCH 3618/5416] sched_clock: prevent scd->clock from moving backwards When sched_clock_cpu() couples the clocks between two cpus, it may increment scd->clock beyond the GTOD tick window that __update_sched_clock() uses to clamp the clock. A later call to __update_sched_clock() may move the clock back to scd->tick_gtod + TICK_NSEC, violating the clock's monotonic property. This patch ensures that scd->clock will not be set backward. Signed-off-by: Dave Kleikamp Acked-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/sched_clock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c index e8ab096ddfe..81787248b60 100644 --- a/kernel/sched_clock.c +++ b/kernel/sched_clock.c @@ -118,13 +118,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) /* * scd->clock = clamp(scd->tick_gtod + delta, - * max(scd->tick_gtod, scd->clock), - * scd->tick_gtod + TICK_NSEC); + * max(scd->tick_gtod, scd->clock), + * max(scd->clock, scd->tick_gtod + TICK_NSEC)); */ clock = scd->tick_gtod + delta; min_clock = wrap_max(scd->tick_gtod, scd->clock); - max_clock = scd->tick_gtod + TICK_NSEC; + max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC); clock = wrap_max(clock, min_clock); clock = wrap_min(clock, max_clock); -- GitLab From a88c71e4367aada2065c5e247477c891d2ca952f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:37:52 +0800 Subject: [PATCH 3619/5416] Blackfin arch: emulate a TTY over the EMUDAT/JTAG interface Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/early_printk.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 60f67f90fe3..1f4e3d2e090 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -35,6 +35,9 @@ extern struct console *bfin_earlyserial_init(unsigned int port, unsigned int cflag); #endif +#ifdef CONFIG_BFIN_JTAG_COMM +extern struct console *bfin_jc_early_init(void); +#endif static struct console *early_console; @@ -142,6 +145,15 @@ int __init setup_early_printk(char *buf) early_console = earlyserial_init(buf); } #endif + +#ifdef CONFIG_BFIN_JTAG_COMM + /* Check for Blackfin JTAG */ + if (!strncmp(buf, "jtag", 4)) { + buf += 4; + early_console = bfin_jc_early_init(); + } +#endif + #ifdef CONFIG_FB /* TODO: add framebuffer console support */ #endif -- GitLab From 9f06c38fb230720371397a57faa24aa6e31b2c87 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Fri, 10 Oct 2008 18:13:21 +0800 Subject: [PATCH 3620/5416] Blackfin arch: Add optional verbose debug Add optional verbose debug - which when turned off, quiets down userspace errors. Saves ~8k of code/data for production systems Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig.debug | 13 ++ arch/blackfin/kernel/traps.c | 230 ++++++++++++++++++++--------------- 2 files changed, 143 insertions(+), 100 deletions(-) diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index f08aea4fc5e..3ad25983ec9 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -5,6 +5,19 @@ source "lib/Kconfig.debug" config HAVE_ARCH_KGDB def_bool y +config DEBUG_VERBOSE + bool "Verbose fault messages" + default y + select PRINTK + help + When a program crashes due to an exception, or the kernel detects + an internal error, the kernel can print a not so brief message + explaining what the problem was. This debugging information is + useful to developers and kernel hackers when tracking down problems, + but mostly meaningless to other people. This is always helpful for + debugging but serves no purpose on a production system. + Most people should say N here. + config DEBUG_MMRS bool "Generate Blackfin MMR tree" select DEBUG_FS diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 709c247b701..1aa2c788e22 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -58,6 +58,15 @@ # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) #endif + +#ifdef CONFIG_VERBOSE_DEBUG +#define verbose_printk(fmt, arg...) \ + printk(fmt, ##arg) +#else +#define verbose_printk(fmt, arg...) \ + ({ if (0) printk(fmt, ##arg); 0; }) +#endif + /* Initiate the event table handler */ void __init trap_init(void) { @@ -78,6 +87,7 @@ unsigned long saved_retx, saved_seqstat, static void decode_address(char *buf, unsigned long address) { +#ifdef CONFIG_DEBUG_VERBOSE struct vm_list_struct *vml; struct task_struct *p; struct mm_struct *mm; @@ -185,12 +195,16 @@ static void decode_address(char *buf, unsigned long address) done: write_unlock_irqrestore(&tasklist_lock, flags); +#else + sprintf(buf, " "); +#endif } asmlinkage void double_fault_c(struct pt_regs *fp) { console_verbose(); oops_in_progress = 1; +#ifdef CONFIG_DEBUG_VERBOSE printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { @@ -213,6 +227,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) dump_bfin_mem(fp); show_regs(fp); } +#endif panic("Double Fault - unrecoverable event\n"); } @@ -288,7 +303,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x02 - KGDB initial connection and break signal trap */ @@ -317,7 +332,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT04 ... VEC_EXCPT15: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x10 HW Single step, handled here */ @@ -334,7 +349,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x12 - Reserved, Caught by default */ @@ -356,35 +371,35 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_UNDEF_I: info.si_code = ILL_ILLOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -392,7 +407,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ case VEC_CPLB_MHIT: @@ -400,10 +415,10 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (saved_dcplb_fault_addr < FIXED_CODE_START) - printk(KERN_NOTICE "NULL pointer access\n"); + verbose_printk(KERN_NOTICE "NULL pointer access\n"); else #endif - printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x28 - Emulation Watchpoint, handled here */ @@ -422,7 +437,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ info.si_code = BUS_OPFETCH; sig = SIGBUS; - printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); + verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); CHK_DEBUGGER_TRAP_MAYBE(); break; #else @@ -432,21 +447,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ case VEC_CPLB_I_MHIT: @@ -454,17 +469,17 @@ asmlinkage void trap_c(struct pt_regs *fp) sig = SIGSEGV; #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO if (saved_icplb_fault_addr < FIXED_CODE_START) - printk(KERN_NOTICE "Jump to NULL address\n"); + verbose_printk(KERN_NOTICE "Jump to NULL address\n"); else #endif - printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2E - Illegal use of Supervisor Resource, handled here */ case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); + verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); CHK_DEBUGGER_TRAP_MAYBE(); break; /* 0x2F - Reserved, Caught by default */ @@ -492,17 +507,17 @@ asmlinkage void trap_c(struct pt_regs *fp) case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); break; /* External Memory Addressing Error */ case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): info.si_code = BUS_ADRERR; sig = SIGBUS; - printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); break; /* Performance Monitor Overflow */ case (SEQSTAT_HWERRCAUSE_PERF_FLOW): - printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); + verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); break; /* RAISE 5 instruction */ case (SEQSTAT_HWERRCAUSE_RAISE_5): @@ -522,7 +537,7 @@ asmlinkage void trap_c(struct pt_regs *fp) oops_in_progress = 1; info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", + verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", (fp->seqstat & SEQSTAT_EXCAUSE)); CHK_DEBUGGER_TRAP_MAYBE(); break; @@ -531,7 +546,6 @@ asmlinkage void trap_c(struct pt_regs *fp) BUG_ON(sig == 0); if (sig != SIGTRAP) { - unsigned long *stack; dump_bfin_process(fp); dump_bfin_mem(fp); show_regs(fp); @@ -539,7 +553,7 @@ asmlinkage void trap_c(struct pt_regs *fp) /* Print out the trace buffer if it makes sense */ #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) - printk(KERN_NOTICE "No trace since you do not have " + verbose_printk(KERN_NOTICE "No trace since you do not have " "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" KERN_NOTICE "\n"); else @@ -548,20 +562,22 @@ asmlinkage void trap_c(struct pt_regs *fp) if (oops_in_progress) { /* Dump the current kernel stack */ - printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); show_stack(current, NULL); - print_modules(); #ifndef CONFIG_ACCESS_CHECK - printk(KERN_EMERG "Please turn on " + verbose_printk(KERN_EMERG "Please turn on " "CONFIG_ACCESS_CHECK\n"); #endif panic("Kernel exception"); } else { +#ifdef CONFIG_VERBOSE_DEBUG + unsigned long *stack; /* Dump the user space stack */ stack = (unsigned long *)rdusp(); - printk(KERN_NOTICE "Userspace Stack\n"); + verbose_printk(KERN_NOTICE "Userspace Stack\n"); show_stack(NULL, stack); +#endif } } @@ -582,7 +598,7 @@ asmlinkage void trap_c(struct pt_regs *fp) * Similar to get_user, do some address checking, then dereference * Return true on sucess, false on bad address */ -bool get_instruction(unsigned short *val, unsigned short *address) +static bool get_instruction(unsigned short *val, unsigned short *address) { unsigned long addr; @@ -643,45 +659,48 @@ bool get_instruction(unsigned short *val, unsigned short *address) * These are the normal instructions which cause change of flow, which * would be at the source of the trace buffer */ -void decode_instruction(unsigned short *address) +#ifdef CONFIG_DEBUG_VERBOSE +static void decode_instruction(unsigned short *address) { unsigned short opcode; if (get_instruction(&opcode, address)) { if (opcode == 0x0010) - printk("RTS"); + verbose_printk("RTS"); else if (opcode == 0x0011) - printk("RTI"); + verbose_printk("RTI"); else if (opcode == 0x0012) - printk("RTX"); + verbose_printk("RTX"); else if (opcode >= 0x0050 && opcode <= 0x0057) - printk("JUMP (P%i)", opcode & 7); + verbose_printk("JUMP (P%i)", opcode & 7); else if (opcode >= 0x0060 && opcode <= 0x0067) - printk("CALL (P%i)", opcode & 7); + verbose_printk("CALL (P%i)", opcode & 7); else if (opcode >= 0x0070 && opcode <= 0x0077) - printk("CALL (PC+P%i)", opcode & 7); + verbose_printk("CALL (PC+P%i)", opcode & 7); else if (opcode >= 0x0080 && opcode <= 0x0087) - printk("JUMP (PC+P%i)", opcode & 7); + verbose_printk("JUMP (PC+P%i)", opcode & 7); else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) - printk("IF !CC JUMP"); + verbose_printk("IF !CC JUMP"); else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) - printk("IF CC JUMP"); + verbose_printk("IF CC JUMP"); else if (opcode >= 0x2000 && opcode <= 0x2fff) - printk("JUMP.S"); + verbose_printk("JUMP.S"); else if (opcode >= 0xe080 && opcode <= 0xe0ff) - printk("LSETUP"); + verbose_printk("LSETUP"); else if (opcode >= 0xe200 && opcode <= 0xe2ff) - printk("JUMP.L"); + verbose_printk("JUMP.L"); else if (opcode >= 0xe300 && opcode <= 0xe3ff) - printk("CALL pcrel"); + verbose_printk("CALL pcrel"); else - printk("0x%04x", opcode); + verbose_printk("0x%04x", opcode); } } +#endif void dump_bfin_trace_buffer(void) { +#ifdef CONFIG_DEBUG_VERBOSE #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON int tflags, i = 0; char buf[150]; @@ -737,6 +756,7 @@ void dump_bfin_trace_buffer(void) trace_buffer_restore(tflags); #endif +#endif } EXPORT_SYMBOL(dump_bfin_trace_buffer); @@ -744,7 +764,7 @@ EXPORT_SYMBOL(dump_bfin_trace_buffer); * Checks to see if the address pointed to is either a * 16-bit CALL instruction, or a 32-bit CALL instruction */ -bool is_bfin_call(unsigned short *addr) +static bool is_bfin_call(unsigned short *addr) { unsigned short opcode = 0, *ins_addr; ins_addr = (unsigned short *)addr; @@ -766,8 +786,10 @@ bool is_bfin_call(unsigned short *addr) return false; } + void show_stack(struct task_struct *task, unsigned long *stack) { +#ifdef CONFIG_PRINTK unsigned int *addr, *endstack, *fp = 0, *frame; unsigned short *ins_addr; char buf[150]; @@ -792,8 +814,10 @@ void show_stack(struct task_struct *task, unsigned long *stack) } else endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack); + printk(KERN_NOTICE "Stack info:\n"); decode_address(buf, (unsigned int)stack); - printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); + printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); + addr = (unsigned int *)((unsigned int)stack & ~0x3F); /* First thing is to look for a frame pointer */ @@ -884,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) if (!j) printk("\n"); } - +#endif } void dump_stack(void) @@ -902,38 +926,39 @@ EXPORT_SYMBOL(dump_stack); void dump_bfin_process(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE /* We should be able to look at fp->ipend, but we don't push it on the * stack all the time, so do this until we fix that */ unsigned int context = bfin_read_IPEND(); if (oops_in_progress) - printk(KERN_EMERG "Kernel OOPS in progress\n"); + verbose_printk(KERN_EMERG "Kernel OOPS in progress\n"); if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) - printk(KERN_NOTICE "HW Error context\n"); + verbose_printk(KERN_NOTICE "HW Error context\n"); else if (context & 0x0020) - printk(KERN_NOTICE "Deferred Exception context\n"); + verbose_printk(KERN_NOTICE "Deferred Exception context\n"); else if (context & 0x3FC0) - printk(KERN_NOTICE "Interrupt context\n"); + verbose_printk(KERN_NOTICE "Interrupt context\n"); else if (context & 0x4000) - printk(KERN_NOTICE "Deferred Interrupt context\n"); + verbose_printk(KERN_NOTICE "Deferred Interrupt context\n"); else if (context & 0x8000) - printk(KERN_NOTICE "Kernel process context\n"); + verbose_printk(KERN_NOTICE "Kernel process context\n"); /* Because we are crashing, and pointers could be bad, we check things * pretty closely before we use them */ if ((unsigned long)current >= FIXED_CODE_START && !((unsigned long)current & 0x3) && current->pid) { - printk(KERN_NOTICE "CURRENT PROCESS:\n"); + verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n"); if (current->comm >= (char *)FIXED_CODE_START) - printk(KERN_NOTICE "COMM=%s PID=%d\n", + verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n", current->comm, current->pid); else - printk(KERN_NOTICE "COMM= invalid\n"); + verbose_printk(KERN_NOTICE "COMM= invalid\n"); if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) - printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" KERN_NOTICE "\n", (void *)current->mm->start_code, @@ -944,26 +969,28 @@ void dump_bfin_process(struct pt_regs *fp) (void *)current->mm->brk, (void *)current->mm->start_stack); else - printk(KERN_NOTICE "invalid mm\n"); + verbose_printk(KERN_NOTICE "invalid mm\n"); } else - printk(KERN_NOTICE "\n" KERN_NOTICE + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "No Valid process in current context\n"); +#endif } void dump_bfin_mem(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE unsigned short *addr, *erraddr, val = 0, err = 0; char sti = 0, buf[6]; erraddr = (void *)fp->pc; - printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); + verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10; addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; addr++) { if (!((unsigned long)addr & 0xF)) - printk("\n" KERN_NOTICE "0x%p: ", addr); + verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); if (!get_instruction(&val, addr)) { val = 0; @@ -972,10 +999,10 @@ void dump_bfin_mem(struct pt_regs *fp) sprintf(buf, "%04x", val); if (addr == erraddr) { - printk("[%s]", buf); + verbose_printk("[%s]", buf); err = val; } else - printk(" %s ", buf); + verbose_printk(" %s ", buf); /* Do any previous instructions turn on interrupts? */ if (addr <= erraddr && /* in the past */ @@ -984,14 +1011,14 @@ void dump_bfin_mem(struct pt_regs *fp) sti = 1; } - printk("\n"); + verbose_printk("\n"); /* Hardware error interrupts can be deferred */ if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR && oops_in_progress)){ - printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); + verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); #ifndef CONFIG_DEBUG_HWERR - printk(KERN_NOTICE "The remaining message may be meaningless\n" + verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" " better idea where it came from\n"); #else @@ -1005,45 +1032,47 @@ void dump_bfin_mem(struct pt_regs *fp) /* And the last RETI points to the current userspace context */ if ((fp + 1)->pc >= current->mm->start_code && (fp + 1)->pc <= current->mm->end_code) { - printk(KERN_NOTICE "It might be better to look around here : \n"); - printk(KERN_NOTICE "-------------------------------------------\n"); + verbose_printk(KERN_NOTICE "It might be better to look around here : \n"); + verbose_printk(KERN_NOTICE "-------------------------------------------\n"); show_regs(fp + 1); - printk(KERN_NOTICE "-------------------------------------------\n"); + verbose_printk(KERN_NOTICE "-------------------------------------------\n"); } } #endif } +#endif } void show_regs(struct pt_regs *fp) { +#ifdef CONFIG_DEBUG_VERBOSE char buf [150]; struct irqaction *action; unsigned int i; unsigned long flags; - printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); - printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); + verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", (long)fp->seqstat, fp->ipend, fp->syscfg); if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { - printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", + verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); #ifdef EBIU_ERRMST /* If the error was from the EBIU, print it out */ if (bfin_read_EBIU_ERRMST() & CORE_ERROR) { - printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", + verbose_printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", bfin_read_EBIU_ERRMST()); - printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", + verbose_printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", bfin_read_EBIU_ERRADD()); } #endif } - printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", + verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); for (i = 6; i <= 15 ; i++) { if (fp->ipend & (1 << i)) { decode_address(buf, bfin_read32(EVT0 + 4*i)); - printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); } } @@ -1056,64 +1085,65 @@ void show_regs(struct pt_regs *fp) goto unlock; decode_address(buf, (unsigned int)action->handler); - printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); + verbose_printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); for (action = action->next; action; action = action->next) { decode_address(buf, (unsigned int)action->handler); - printk(", %s", buf); + verbose_printk(", %s", buf); } - printk("\n"); + verbose_printk("\n"); unlock: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } } decode_address(buf, fp->rete); - printk(KERN_NOTICE " RETE: %s\n", buf); + verbose_printk(KERN_NOTICE " RETE: %s\n", buf); decode_address(buf, fp->retn); - printk(KERN_NOTICE " RETN: %s\n", buf); + verbose_printk(KERN_NOTICE " RETN: %s\n", buf); decode_address(buf, fp->retx); - printk(KERN_NOTICE " RETX: %s\n", buf); + verbose_printk(KERN_NOTICE " RETX: %s\n", buf); decode_address(buf, fp->rets); - printk(KERN_NOTICE " RETS: %s\n", buf); + verbose_printk(KERN_NOTICE " RETS: %s\n", buf); decode_address(buf, fp->pc); - printk(KERN_NOTICE " PC : %s\n", buf); + verbose_printk(KERN_NOTICE " PC : %s\n", buf); if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { decode_address(buf, saved_dcplb_fault_addr); - printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); + verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); decode_address(buf, saved_icplb_fault_addr); - printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); + verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); } - printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); - printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", + verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); + verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", fp->r0, fp->r1, fp->r2, fp->r3); - printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", + verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", fp->r4, fp->r5, fp->r6, fp->r7); - printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", + verbose_printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", fp->p0, fp->p1, fp->p2, fp->p3); - printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", + verbose_printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", fp->p4, fp->p5, fp->fp, (long)fp); - printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", + verbose_printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0, fp->lc0); - printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", + verbose_printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1, fp->lc1); - printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", + verbose_printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", fp->b0, fp->l0, fp->m0, fp->i0); - printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", + verbose_printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", fp->b1, fp->l1, fp->m1, fp->i1); - printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", + verbose_printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", fp->b2, fp->l2, fp->m2, fp->i2); - printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", + verbose_printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", fp->b3, fp->l3, fp->m3, fp->i3); - printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", + verbose_printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", fp->a0w, fp->a0x, fp->a1w, fp->a1x); - printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", + verbose_printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", rdusp(), fp->astat); - printk(KERN_NOTICE "\n"); + verbose_printk(KERN_NOTICE "\n"); +#endif } #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 -- GitLab From f5623a3cf27284f5121296dec847a8f75e5d0691 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 17:51:15 +0800 Subject: [PATCH 3621/5416] Blackfin arch: update board defconfigs Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/configs/H8606_defconfig | 36 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig index ba0bee90b7e..1fc31f1b762 100644 --- a/arch/blackfin/configs/H8606_defconfig +++ b/arch/blackfin/configs/H8606_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.12 +# Linux kernel version: 2.6.22.14 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -192,7 +192,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=400000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MAX_SCLK_HZ=133333333 CONFIG_MIN_SCLK_HZ=27000000 # @@ -516,7 +516,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y # # CONFIG_MTD_DATAFLASH is not set CONFIG_MTD_M25P80=y -CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set @@ -635,25 +635,25 @@ CONFIG_INPUT=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_ATI_REMOTE is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INPUT_UINPUT is not set -# CONFIG_BF53X_PFBUTTONS is not set +# CONFIG_INPUT_MISC is not set # # Hardware I/O ports @@ -681,7 +681,15 @@ CONFIG_BFIN_TIMER_LATENCY=y # # Serial drivers # -# CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support -- GitLab From 6d0b8c993dc0a26fe7a9ee8b839d1964bd0debd4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 18:05:02 +0800 Subject: [PATCH 3622/5416] Blackfin arch: remove non-bf54x ifdef logic since this file is only compiled on bf54x parts Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/head.S | 49 +++------------------------------ 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 4d5cfeacb12..b0628164e5d 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -73,25 +73,19 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; -#if defined(CONFIG_BF54x) + /* enable self refresh via SRREQ */ P2.H = hi(EBIU_RSTCTL); P2.L = lo(EBIU_RSTCTL); R0 = [P2]; BITSET (R0, 3); -#else - P2.H = hi(EBIU_SDGCTL); - P2.L = lo(EBIU_SDGCTL); - R0 = [P2]; - BITSET (R0, 24); -#endif [P2] = R0; SSYNC; -#if defined(CONFIG_BF54x) + + /* wait for SRACK bit to be set */ .LSRR_MODE: R0 = [P2]; CC = BITTST(R0, 4); if !CC JUMP .LSRR_MODE; -#endif r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */ r0 = r0 << 9; /* Shift it over, */ @@ -123,7 +117,7 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; -#if defined(CONFIG_BF54x) + /* disable self refresh by clearing SRREQ */ P2.H = hi(EBIU_RSTCTL); P2.L = lo(EBIU_RSTCTL); R0 = [P2]; @@ -155,41 +149,6 @@ ENTRY(_start_dma_code) r0.h = hi(mem_DDRCTL2); [p0] = r0; ssync; -#else - p0.l = lo(EBIU_SDRRC); - p0.h = hi(EBIU_SDRRC); - r0 = mem_SDRRC; - w[p0] = r0.l; - ssync; - - p0.l = LO(EBIU_SDBCTL); - p0.h = HI(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */ - r0 = mem_SDBCTL; - w[p0] = r0.l; - ssync; - - P2.H = hi(EBIU_SDGCTL); - P2.L = lo(EBIU_SDGCTL); - R0 = [P2]; - BITCLR (R0, 24); - p0.h = hi(EBIU_SDSTAT); - p0.l = lo(EBIU_SDSTAT); - r2.l = w[p0]; - cc = bittst(r2,3); - if !cc jump .Lskip; - NOP; - BITSET (R0, 23); -.Lskip: - [P2] = R0; - SSYNC; - - R0.L = lo(mem_SDGCTL); - R0.H = hi(mem_SDGCTL); - R1 = [p2]; - R1 = R1 | R0; - [P2] = R1; - SSYNC; -#endif RTS; ENDPROC(_start_dma_code) -- GitLab From e482cad241c0b7108cbc94959307a73d19ba17d5 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Fri, 10 Oct 2008 18:21:45 +0800 Subject: [PATCH 3623/5416] Blackfin arch: print out error/warning if you are running on the incorrect CPU type Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/processor.h | 6 +++ arch/blackfin/kernel/setup.c | 43 ++++++++++++------- arch/blackfin/mach-bf527/include/mach/bf527.h | 19 +++++++- arch/blackfin/mach-bf533/include/mach/bf533.h | 10 ++--- arch/blackfin/mach-bf537/include/mach/bf537.h | 10 ++--- arch/blackfin/mach-bf548/include/mach/bf548.h | 23 +++++----- arch/blackfin/mach-bf561/include/mach/bf561.h | 6 +-- 7 files changed, 76 insertions(+), 41 deletions(-) diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 6f3995b119d..e3e9b41fa8d 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h @@ -134,6 +134,12 @@ static inline uint32_t __pure bfin_revid(void) return revid; } +static inline uint16_t __pure bfin_cpuid(void) +{ + return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; + +} + static inline uint32_t __pure bfin_compiled_revid(void) { #if defined(CONFIG_BF_REV_0_0) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 4267523912b..74370f3707b 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -813,17 +813,23 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU); else printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid()); - if (bfin_revid() != bfin_compiled_revid()) { - if (bfin_compiled_revid() == -1) - printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", - bfin_revid()); - else if (bfin_compiled_revid() != 0xffff) - printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", - bfin_compiled_revid(), bfin_revid()); + + if (unlikely(CPUID != bfin_cpuid())) + printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", + CPU, bfin_cpuid(), bfin_revid()); + else { + if (bfin_revid() != bfin_compiled_revid()) { + if (bfin_compiled_revid() == -1) + printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", + bfin_revid()); + else if (bfin_compiled_revid() != 0xffff) + printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", + bfin_compiled_revid(), bfin_revid()); + } + if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) + printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", + CPU, bfin_revid()); } - if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) - printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", - CPU, bfin_revid()); printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); @@ -997,13 +1003,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) } seq_printf(m, "processor\t: %d\n" - "vendor_id\t: %s\n" - "cpu family\t: 0x%x\n" - "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" - "stepping\t: %d\n", + "vendor_id\t: %s\n", *(unsigned int *)v, - vendor, - (bfin_read_CHIPID() & CHIPID_FAMILY), + vendor); + + if (CPUID == bfin_cpuid()) + seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); + else + seq_printf(m, "cpu family\t: Compiled for:0x%04x, running on:0x%04x\n", + CPUID, bfin_cpuid()); + + seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" + "stepping\t: %d\n", cpu, cclk/1000000, sclk/1000000, #ifdef CONFIG_MPU "mpu on", diff --git a/arch/blackfin/mach-bf527/include/mach/bf527.h b/arch/blackfin/mach-bf527/include/mach/bf527.h index 330041fde54..144f08d3f8e 100644 --- a/arch/blackfin/mach-bf527/include/mach/bf527.h +++ b/arch/blackfin/mach-bf527/include/mach/bf527.h @@ -110,16 +110,31 @@ #ifdef CONFIG_BF527 #define CPU "BF527" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF526 +#define CPU "BF526" +#define CPUID 0x27e4 #endif #ifdef CONFIG_BF525 #define CPU "BF525" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF524 +#define CPU "BF524" +#define CPUID 0x27e4 +#endif +#ifdef CONFIG_BF523 +#define CPU "BF523" +#define CPUID 0x27e4 #endif #ifdef CONFIG_BF522 #define CPU "BF522" +#define CPUID 0x27e4 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF527_H__ */ diff --git a/arch/blackfin/mach-bf533/include/mach/bf533.h b/arch/blackfin/mach-bf533/include/mach/bf533.h index 94980111230..dfc8c1ad2d7 100644 --- a/arch/blackfin/mach-bf533/include/mach/bf533.h +++ b/arch/blackfin/mach-bf533/include/mach/bf533.h @@ -141,19 +141,19 @@ #ifdef CONFIG_BF533 #define CPU "BF533" -#define CPUID 0x027a5000 +#define CPUID 0x27a5 #endif #ifdef CONFIG_BF532 #define CPU "BF532" -#define CPUID 0x0275A000 +#define CPUID 0x275A #endif #ifdef CONFIG_BF531 #define CPU "BF531" -#define CPUID 0x027a5000 +#define CPUID 0x27a5 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF533_H__ */ diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h index 7a047e04e38..24d5c9d4232 100644 --- a/arch/blackfin/mach-bf537/include/mach/bf537.h +++ b/arch/blackfin/mach-bf537/include/mach/bf537.h @@ -121,19 +121,19 @@ #ifdef CONFIG_BF537 #define CPU "BF537" -#define CPUID 0x027c8000 +#define CPUID 0x27c8 #endif #ifdef CONFIG_BF536 #define CPU "BF536" -#define CPUID 0x027c8000 +#define CPUID 0x27c8 #endif #ifdef CONFIG_BF534 #define CPU "BF534" -#define CPUID 0x027c6000 +#define CPUID 0x27c6 #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF537_H__ */ diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index 14f8a7b8454..49f9b403d45 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -106,20 +106,23 @@ #if defined(CONFIG_BF542) # define CPU "BF542" -# define CPUID 0x027c8000 +# define CPUID 0x27de #elif defined(CONFIG_BF544) -# define CPU "BF544" -# define CPUID 0x027c8000 +# define CPU "BF544" +# define CPUID 0x27de #elif defined(CONFIG_BF547) -# define CPU "BF547" +# define CPU "BF547" +# define CPUID 0x27de #elif defined(CONFIG_BF548) -# define CPU "BF548" -# define CPUID 0x027c6000 +# define CPU "BF548" +# define CPUID 0x27de #elif defined(CONFIG_BF549) -# define CPU "BF549" -#else -# define CPU "UNKNOWN" -# define CPUID 0x0 +# define CPU "BF549" +# define CPUID 0x27de +#endif + +#ifndef CPU +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF48_H__ */ diff --git a/arch/blackfin/mach-bf561/include/mach/bf561.h b/arch/blackfin/mach-bf561/include/mach/bf561.h index 7787caad355..18b1b3a223a 100644 --- a/arch/blackfin/mach-bf561/include/mach/bf561.h +++ b/arch/blackfin/mach-bf561/include/mach/bf561.h @@ -211,11 +211,11 @@ #ifdef CONFIG_BF561 #define CPU "BF561" -#define CPUID 0x027bb000 +#define CPUID 0x27bb #endif + #ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#error Unknown CPU type - This kernel doesn't seem to be configured properly #endif #endif /* __MACH_BF561_H__ */ -- GitLab From 9a6f5ae1f1f3c37aad938a1c82db248a3f95a629 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 18:57:21 +0800 Subject: [PATCH 3624/5416] Blackfin arch: bfin_reset() is an internal reboot function ... everyone should go through machine_restart() Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin-global.h | 1 - arch/blackfin/kernel/reboot.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index f842ea3bfc1..56dcb0a2d24 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h @@ -63,7 +63,6 @@ extern void bfin_dcache_init(void); extern void init_exception_vectors(void); extern void program_IAR(void); -extern void bfin_reset(void); extern asmlinkage void lower_to_irq14(void); extern asmlinkage void bfin_return_from_exception(void); extern asmlinkage void evt14_softirq(void); diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index b0a8f89cc9b..d0ead640d99 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -20,7 +20,7 @@ * the core reset. */ __attribute__((l1_text)) -void bfin_reset(void) +static void bfin_reset(void) { /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as -- GitLab From 5dc64a3442b98eaa0e3730c35fcf00cf962a93e7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 10 Oct 2008 11:27:38 +0100 Subject: [PATCH 3625/5416] xen: do not reserve 2 pages of padding between hypervisor and fixmap. When reserving space for the hypervisor the Xen paravirt backend adds an extra two pages (this was carried forward from the 2.6.18-xen tree which had them "for safety"). Depending on various CONFIG options this can cause the boot time fixmaps to span multiple PMDs which is not supported and triggers a WARN in early_ioremap_init(). This was exposed by 2216d199b1430d1c0affb1498a9ebdbd9c0de439 which moved the dmi table parsing earlier. x86: fix CONFIG_X86_RESERVE_LOW_64K=y The bad_bios_dmi_table() quirk never triggered because we do DMI setup too late. Move it a bit earlier. There is no real reason to reserve these two extra pages and the fixmap already incorporates FIX_HOLE which serves the same purpose. None of the other callers of reserve_top_address do this. Signed-off-by: Ian Campbell Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 85692c9f649..977a54255fb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1370,7 +1370,7 @@ static void __init xen_reserve_top(void) if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) top = pp.virt_start; - reserve_top_address(-top + 2 * PAGE_SIZE); + reserve_top_address(-top); #endif /* CONFIG_X86_32 */ } -- GitLab From fedb7569100ac858bea7954d82c74e5561bf2c03 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Tue, 23 Sep 2008 21:46:30 -0400 Subject: [PATCH 3626/5416] ALSA: hda: use last DAC defined for hp_pin Patch allows the last DAC in the dac_nids for the hp_nid if there is an available one this isn't in use by a line_out entry or if hp_nid isn't already defined. This solves the issues with the 'Headphone Playback' mixer controls on the 92hd73xxx branch and possibly others. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bd0d6f8ab43..6e0a18bca23 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2817,6 +2817,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, } } + if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && + cfg->hp_outs && !spec->multiout.hp_nid) + spec->multiout.hp_nid = nid; + if (cfg->hp_outs > 1) { err = stac92xx_add_control(spec, STAC_CTL_WIDGET_HP_SWITCH, @@ -4083,8 +4087,6 @@ again: case STAC_DELL_M6: spec->init = dell_eq_core_init; spec->num_smuxes = 0; - spec->multiout.hp_nid = - spec->multiout.dac_nids[spec->multiout.num_dacs - 1]; spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; spec->num_amps = 1; -- GitLab From a99606d25eb6981e13d332e18774e203ded66709 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 24 Sep 2008 09:44:18 +0200 Subject: [PATCH 3627/5416] ALSA: Remove bitwise from snd_pcm_hw_param_t We have some arithmetic operations against snd_pcm_hw_param_t, thus bitwise isn't correct for it. Better to remove the flag to shut up sparse warnings. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/asound.h | 44 ++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index ca2f3582664..1196e3d5194 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -297,29 +297,39 @@ struct snd_pcm_info { unsigned char reserved[64]; /* reserved for future... */ }; -typedef int __bitwise snd_pcm_hw_param_t; -#define SNDRV_PCM_HW_PARAM_ACCESS ((__force snd_pcm_hw_param_t) 0) /* Access type */ -#define SNDRV_PCM_HW_PARAM_FORMAT ((__force snd_pcm_hw_param_t) 1) /* Format */ -#define SNDRV_PCM_HW_PARAM_SUBFORMAT ((__force snd_pcm_hw_param_t) 2) /* Subformat */ +typedef int snd_pcm_hw_param_t; +#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */ +#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */ +#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */ #define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS #define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT -#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS ((__force snd_pcm_hw_param_t) 8) /* Bits per sample */ -#define SNDRV_PCM_HW_PARAM_FRAME_BITS ((__force snd_pcm_hw_param_t) 9) /* Bits per frame */ -#define SNDRV_PCM_HW_PARAM_CHANNELS ((__force snd_pcm_hw_param_t) 10) /* Channels */ -#define SNDRV_PCM_HW_PARAM_RATE ((__force snd_pcm_hw_param_t) 11) /* Approx rate */ -#define SNDRV_PCM_HW_PARAM_PERIOD_TIME ((__force snd_pcm_hw_param_t) 12) /* Approx distance between interrupts in us */ -#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE ((__force snd_pcm_hw_param_t) 13) /* Approx frames between interrupts */ -#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES ((__force snd_pcm_hw_param_t) 14) /* Approx bytes between interrupts */ -#define SNDRV_PCM_HW_PARAM_PERIODS ((__force snd_pcm_hw_param_t) 15) /* Approx interrupts per buffer */ -#define SNDRV_PCM_HW_PARAM_BUFFER_TIME ((__force snd_pcm_hw_param_t) 16) /* Approx duration of buffer in us */ -#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE ((__force snd_pcm_hw_param_t) 17) /* Size of buffer in frames */ -#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES ((__force snd_pcm_hw_param_t) 18) /* Size of buffer in bytes */ -#define SNDRV_PCM_HW_PARAM_TICK_TIME ((__force snd_pcm_hw_param_t) 19) /* Approx tick duration in us */ +#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */ +#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */ +#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */ +#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */ +#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between + * interrupts in us + */ +#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between + * interrupts + */ +#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between + * interrupts + */ +#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per + * buffer + */ +#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer + * in us + */ +#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */ +#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */ +#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */ #define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS #define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME -#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ +#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ struct snd_interval { unsigned int min, max; -- GitLab From 37c34ffb3a9a6051236a4ee1acb7752bcc3f50fd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 24 Sep 2008 09:59:44 +0200 Subject: [PATCH 3628/5416] ALSA: intel8x0 - Add quirk for Fujitsu Lifebook P7010 Fujitsu Lifebook P7010 requires ac97_quirk=hp_only. http://bugzilla.kernel.org/show_bug.cgi?id=9100 Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index f7b4d0c5d49..c88d1eace1c 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1961,6 +1961,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Fujitsu S6210", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x10cf, + .subdevice = 0x127d, + .name = "Fujitsu Lifebook P7010", + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x10cf, .subdevice = 0x127e, -- GitLab From ddc0f38a62083a552d6acb792d9ce513cf4081df Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Thu, 25 Sep 2008 09:17:11 -0400 Subject: [PATCH 3629/5416] ALSA: hda: slave_dig_outs code block in wrong location Removed invalid references to slave_dig_outs inside the S/PDIF IN capture switch control. Beforehand this was basically a mute switch for the S/PDIF outs as well. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c742e101d91..cb9aae5e9ca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1652,15 +1652,9 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, mutex_lock(&codec->spdif_mutex); change = codec->spdif_in_enable != val; if (change) { - hda_nid_t *d; codec->spdif_in_enable = val; snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); - - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, val); } mutex_unlock(&codec->spdif_mutex); return change; -- GitLab From 2f72853ca1ee1571377996471d05db51eb7c54c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 25 Sep 2008 16:32:41 +0200 Subject: [PATCH 3630/5416] ALSA: hda - Fix / clean-up slave digital out codes The recent slave_dig_out addition has some rooms to clean up. Also it doesn't call snd_hda_cleanup_stream() properly for slaves at closing. The patch fixes both issues. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 115 +++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index cb9aae5e9ca..94ea6543440 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1426,6 +1426,29 @@ static unsigned int convert_to_spdif_status(unsigned short val) return sbits; } +/* set digital convert verbs both for the given NID and its slaves */ +static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, + int verb, int val) +{ + hda_nid_t *d; + + snd_hda_codec_write(codec, nid, 0, verb, val); + d = codec->slave_dig_outs; + if (!d) + return; + for (; *d; d++) + snd_hda_codec_write(codec, *d, 0, verb, val); +} + +static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid, + int dig1, int dig2) +{ + if (dig1 != -1) + set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1); + if (dig2 != -1) + set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2); +} + static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1444,25 +1467,8 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, change = codec->spdif_ctls != val; codec->spdif_ctls = val; - if (change) { - hda_nid_t *d; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_DIGI_CONVERT_2, - val >> 8); - - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) { - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_2, - val >> 8); - } - } + if (change) + set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff); mutex_unlock(&codec->spdif_mutex); return change; @@ -1493,17 +1499,8 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, val |= AC_DIG1_ENABLE; change = codec->spdif_ctls != val; if (change) { - hda_nid_t *d; codec->spdif_ctls = val; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); - - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write_cache(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - val & 0xff); + set_dig_out_convert(codec, nid, val & 0xff, -1); /* unmute amp switch (if any) */ if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && (val & AC_DIG1_ENABLE)) @@ -2598,32 +2595,32 @@ int snd_hda_input_mux_put(struct hda_codec *codec, static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, unsigned int stream_tag, unsigned int format) { - hda_nid_t *d; - /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ - if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); - - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); - } + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) + set_dig_out_convert(codec, nid, + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, + -1); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); + if (codec->slave_dig_outs) { + hda_nid_t *d; + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_setup_stream(codec, *d, stream_tag, 0, + format); + } /* turn on again (if needed) */ - if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & 0xff); + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) + set_dig_out_convert(codec, nid, + codec->spdif_ctls & 0xff, -1); +} - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_write(codec, *d, 0, - AC_VERB_SET_DIGI_CONVERT_1, - codec->spdif_ctls & 0xff); +static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) +{ + snd_hda_codec_cleanup_stream(codec, nid); + if (codec->slave_dig_outs) { + hda_nid_t *d; + for (d = codec->slave_dig_outs; *d; d++) + snd_hda_codec_cleanup_stream(codec, *d); } - } /* @@ -2635,7 +2632,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec, mutex_lock(&codec->spdif_mutex); if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) /* already opened as analog dup; reset it once */ - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); + cleanup_dig_out_stream(codec, mout->dig_out_nid); mout->dig_out_used = HDA_DIG_EXCLUSIVE; mutex_unlock(&codec->spdif_mutex); return 0; @@ -2647,12 +2644,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, unsigned int format, struct snd_pcm_substream *substream) { - hda_nid_t *nid; mutex_lock(&codec->spdif_mutex); setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); - if (codec->slave_dig_outs) - for (nid = codec->slave_dig_outs; *nid; nid++) - setup_dig_out_stream(codec, *nid, stream_tag, format); mutex_unlock(&codec->spdif_mutex); return 0; } @@ -2719,7 +2712,6 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct snd_pcm_substream *substream) { hda_nid_t *nids = mout->dac_nids; - hda_nid_t *d; int chs = substream->runtime->channels; int i; @@ -2733,16 +2725,9 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, mout->dig_out_used = HDA_DIG_ANALOG_DUP; setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - setup_dig_out_stream(codec, *d, - stream_tag, format); } else { mout->dig_out_used = 0; - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); - if (codec->slave_dig_outs) - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_cleanup_stream(codec, *d); + cleanup_dig_out_stream(codec, mout->dig_out_nid); } } mutex_unlock(&codec->spdif_mutex); @@ -2793,7 +2778,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, mout->extra_out_nid[i]); mutex_lock(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid); + cleanup_dig_out_stream(codec, mout->dig_out_nid); mout->dig_out_used = 0; } mutex_unlock(&codec->spdif_mutex); -- GitLab From 9a10eb21e1e1c389a8cea3016157a7f471512645 Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Fri, 26 Sep 2008 13:45:46 +0800 Subject: [PATCH 3631/5416] ALSA: Support NVIDIA MCP78/7A HDMI audio Add NVIDIA HDMI HD-audio codec support in snd-hda-intel driver, include NVIDIA MCP78/7A HDMI. Signed-off-by: Wei Ni Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/Kconfig | 8 ++ sound/pci/hda/Makefile | 1 + sound/pci/hda/hda_codec.c | 3 + sound/pci/hda/hda_patch.h | 2 + sound/pci/hda/patch_nvhdmi.c | 164 +++++++++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 sound/pci/hda/patch_nvhdmi.c diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 1f8b7966a83..7003711f4fc 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -565,6 +565,14 @@ config SND_HDA_CODEC_ATIHDMI Say Y here to include ATI HDMI HD-audio codec support in snd-hda-intel driver, such as ATI RS600 HDMI. +config SND_HDA_CODEC_NVHDMI + bool "Build NVIDIA HDMI HD-audio codec support" + depends on SND_HDA_INTEL + default y + help + Say Y here to include NVIDIA HDMI HD-audio codec support in + snd-hda-intel driver, such as NVIDIA MCP78 HDMI. + config SND_HDA_CODEC_CONEXANT bool "Build Conexant HD-audio codec support" depends on SND_HDA_INTEL diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 6db92fd954d..1980c6d207e 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -15,5 +15,6 @@ snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o +snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 94ea6543440..fdb6d559f5d 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -93,6 +93,9 @@ static const struct hda_codec_preset *hda_preset_tables[] = { #endif #ifdef CONFIG_SND_HDA_CODEC_VIA snd_hda_preset_via, +#endif +#ifdef CONFIG_SND_HDA_CODEC_NVHDMI + snd_hda_preset_nvhdmi, #endif NULL }; diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index 2fdf2358dbc..dfbcfa88da4 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h @@ -18,3 +18,5 @@ extern struct hda_codec_preset snd_hda_preset_atihdmi[]; extern struct hda_codec_preset snd_hda_preset_conexant[]; /* VIA codecs */ extern struct hda_codec_preset snd_hda_preset_via[]; +/* NVIDIA HDMI codecs */ +extern struct hda_codec_preset snd_hda_preset_nvhdmi[]; diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c new file mode 100644 index 00000000000..1a65775d28e --- /dev/null +++ b/sound/pci/hda/patch_nvhdmi.c @@ -0,0 +1,164 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for NVIDIA HDMI codecs + * + * Copyright (c) 2008 NVIDIA Corp. All rights reserved. + * Copyright (c) 2008 Wei Ni + * + * + * This driver 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 driver 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 "hda_codec.h" +#include "hda_local.h" + +struct nvhdmi_spec { + struct hda_multi_out multiout; + + struct hda_pcm pcm_rec; +}; + +static struct hda_verb nvhdmi_basic_init[] = { + /* enable digital output on pin widget */ + { 0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + {} /* terminator */ +}; + +/* + * Controls + */ +static int nvhdmi_build_controls(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec = codec->spec; + int err; + + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; + + return 0; +} + +static int nvhdmi_init(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, nvhdmi_basic_init); + return 0; +} + +/* + * Digital out + */ +static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct nvhdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); +} + +static int nvhdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct nvhdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} + +static int nvhdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct nvhdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + +static struct hda_pcm_stream nvhdmi_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x4, /* NID to query formats and rates and setup streams */ + .rates = SNDRV_PCM_RATE_48000, + .maxbps = 16, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .ops = { + .open = nvhdmi_dig_playback_pcm_open, + .close = nvhdmi_dig_playback_pcm_close, + .prepare = nvhdmi_dig_playback_pcm_prepare + }, +}; + +static int nvhdmi_build_pcms(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = "NVIDIA HDMI"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback; + + return 0; +} + +static void nvhdmi_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} + +static struct hda_codec_ops nvhdmi_patch_ops = { + .build_controls = nvhdmi_build_controls, + .build_pcms = nvhdmi_build_pcms, + .init = nvhdmi_init, + .free = nvhdmi_free, +}; + +static int patch_nvhdmi(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = 0x4; /* NID for copying analog to digital, + * seems to be unused in pure-digital + * case. */ + + codec->patch_ops = nvhdmi_patch_ops; + + return 0; +} + +/* + * patch entries + */ +struct hda_codec_preset snd_hda_preset_nvhdmi[] = { + { .id = 0x10de0002, .name = "NVIDIA MCP78 HDMI", .patch = patch_nvhdmi }, + { .id = 0x10de0007, .name = "NVIDIA MCP7A HDMI", .patch = patch_nvhdmi }, + {} /* terminator */ +}; -- GitLab From dc9c8e218da823008ce1572998902a4bdf46af37 Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Fri, 26 Sep 2008 13:55:56 +0800 Subject: [PATCH 3632/5416] ALSA: Fix for reading RIRB buffer on NVIDIA aza controller with AMD Phenom cpu When read RIRB buffer immediately after RIRB interrupt received, sometimes the data will be "0x0". If we wait for some time, the data in buffer will be correct. This issue only occurred with AMD Phenom cpu. So we set this "needs_damn_long_delay" flag. Signed-off-by: Wei Ni Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 60cc44abf58..9f316c1b279 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1220,6 +1220,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, if (err < 0) return err; + if (chip->driver_type == AZX_DRIVER_NVIDIA) + chip->bus->needs_damn_long_delay = 1; + codecs = audio_codecs = 0; max_slots = azx_max_codecs[chip->driver_type]; if (!max_slots) -- GitLab From 97c889a78b70f0ac0949967bf174d1a6a28bfb5c Mon Sep 17 00:00:00 2001 From: Eran Tromer Date: Fri, 26 Sep 2008 01:07:03 -0400 Subject: [PATCH 3633/5416] ALSA: usb-audio: add support for E-Mu Tracker Pre Add support for the E-Mu "Tracker Pre" USB sound card, following the example of the (very similar) E-Mu 0202 and E-Mu 0404 USB. As with the 0202 and 0404 USB, functionality is very limited: just a couple of sample rates, no volume/mute control, etc. Signed-off-by: Eran Tromer Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/usbaudio.c | 3 ++- sound/usb/usbquirks.h | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c5cf682c352..8af12b680e1 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -484,7 +484,7 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs, } /* - * process after E-Mu 0202/0404 high speed playback sync complete + * process after E-Mu 0202/0404/Tracker Pre high speed playback sync complete * * These devices return the number of samples per packet instead of the number * of samples per microframe. @@ -2264,6 +2264,7 @@ static void init_substream(struct snd_usb_stream *as, int stream, struct audiofo switch (as->chip->usb_id) { case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */ case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */ + case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */ subs->ops.retire_sync = retire_playback_sync_urb_hs_emu; break; } diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 3f68359d494..d96bf8b2b94 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -62,6 +62,13 @@ .idProduct = 0x3f04, .bInterfaceClass = USB_CLASS_AUDIO, }, +{ + /* E-Mu Tracker Pre */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x041e, + .idProduct = 0x3f0a, + .bInterfaceClass = USB_CLASS_AUDIO, +}, /* * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface -- GitLab From b2c4f4d71f7a161630681678cbba84bd695bfd1e Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Fri, 26 Sep 2008 10:06:40 -0400 Subject: [PATCH 3634/5416] ALSA: hda: 92xx S/PDIF In support Add support for S/PDIF IN on reference boards quirks. Also disable the IEC958 capture switch on boards with GPIO0 enabled. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6e0a18bca23..2191735068e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1245,7 +1245,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) return err; spec->multiout.share_spdif = 1; } - if (spec->dig_in_nid) { + if (spec->dig_in_nid && (!spec->gpio_dir & 0x01)) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); if (err < 0) return err; @@ -4079,10 +4079,6 @@ again: memcpy(&spec->private_dimux, &stac92hd73xx_dmux, sizeof(stac92hd73xx_dmux)); - /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; - spec->gpio_data = 0x01; - switch (spec->board_config) { case STAC_DELL_M6: spec->init = dell_eq_core_init; @@ -4120,6 +4116,11 @@ again: spec->num_dmics = STAC92HD73XX_NUM_DMICS; spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); } + if (spec->board_config > STAC_92HD73XX_REF) { + /* GPIO0 High = Enable EAPD */ + spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; + spec->gpio_data = 0x01; + } spec->dinput_mux = &spec->private_dimux; spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); @@ -4356,10 +4357,12 @@ again: spec->aloopback_mask = 0x20; spec->aloopback_shift = 0; - /* GPIO0 High = EAPD */ - spec->gpio_mask = 0x01; - spec->gpio_dir = 0x01; - spec->gpio_data = 0x01; + if (spec->board_config > STAC_92HD71BXX_REF) { + /* GPIO0 = EAPD */ + spec->gpio_mask = 0x01; + spec->gpio_dir = 0x01; + spec->gpio_data = 0x01; + } spec->powerdown_adcs = 1; spec->digbeep_nid = 0x26; @@ -4601,9 +4604,11 @@ static int patch_stac927x(struct hda_codec *codec) spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); break; default: - /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; - spec->gpio_data = 0x01; + if (spec->board_config > STAC_D965_REF) { + /* GPIO0 High = Enable EAPD */ + spec->eapd_mask = spec->gpio_mask = 0x01; + spec->gpio_dir = spec->gpio_data = 0x01; + } spec->num_dmics = 0; spec->init = stac927x_core_init; @@ -4717,6 +4722,9 @@ static int patch_stac9205(struct hda_codec *codec) */ spec->gpio_data = 0x01; break; + case STAC_9205_REF: + /* SPDIF-In enabled */ + break; default: /* GPIO0 High = EAPD */ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; -- GitLab From 9a9e2359f484402c620f9a3748037fea65fa5af4 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Fri, 26 Sep 2008 10:37:03 -0400 Subject: [PATCH 3635/5416] ALSA: hda: HP laptop quirk Added HP laptop SND_PCI_QUIRK for STAC_HP_M4. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 2191735068e..f9b25638892 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1650,6 +1650,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_92HD71BXX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, + "unknown HP", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, "unknown Dell", STAC_DELL_M4_1), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, -- GitLab From 71dc525c5d480397ac7343a0a2808f8a23705d42 Mon Sep 17 00:00:00 2001 From: Julien Brunel Date: Fri, 26 Sep 2008 15:23:46 +0200 Subject: [PATCH 3636/5416] ALSA: sound/soc/at32: Useless NULL test The test (ssc != NULL) can only be reached if the call to the function ssc_request, the result of which ssc is assigned, succeeds. Moreover, two statements assign NULL to ssc just before a return, which is useless since it is a local variable. So, we suggest to delete the test and the two assignments. A simplified version of the semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @bad_null_test@ expression x,E; @@ x = ssc_request(...) ... when != x = E * x != NULL // Signed-off-by: Julien Brunel Signed-off-by: Julia Lawall Acked-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/at32/playpaq_wm8510.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c index 7e6560ba751..98a2d5826a8 100644 --- a/sound/soc/at32/playpaq_wm8510.c +++ b/sound/soc/at32/playpaq_wm8510.c @@ -406,7 +406,6 @@ static int __init playpaq_asoc_init(void) ssc = ssc_request(0); if (IS_ERR(ssc)) { ret = PTR_ERR(ssc); - ssc = NULL; goto err_ssc; } ssc_p->ssc = ssc; @@ -477,10 +476,7 @@ err_pll0: _gclk0 = NULL; } err_gclk0: - if (ssc != NULL) { - ssc_free(ssc); - ssc = NULL; - } + ssc_free(ssc); err_ssc: return ret; } -- GitLab From cb55974cb461ff9c9c0675b2a8361d387212b64f Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Fri, 26 Sep 2008 23:47:45 -0300 Subject: [PATCH 3637/5416] ALSA: hda - Map ALC662 model for Gigabyte 945GCM-S2L Use 3stack-6ch-dig ALC662 model for Gigabyte 945GCM-S2L motherboard. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c2ff85dad50..8f1fe962fb5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15703,6 +15703,8 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", + ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13), -- GitLab From 95fe5f2cec831d73ee93227810ab95d05ced3416 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Fri, 26 Sep 2008 23:48:45 -0300 Subject: [PATCH 3638/5416] ALSA: hda - Map ALC662 model for Foxconn 45CMX/45GMX/45CMX-K Use 3stack-6ch-dig ALC662 model for Foxconn 45CMX/45GMX/45CMX-K motherboard. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8f1fe962fb5..dedd51d5540 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15700,6 +15700,8 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), + SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", + ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), -- GitLab From f3911c5ab93e4295938b2013104d2986ea601454 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sat, 27 Sep 2008 09:13:45 +0200 Subject: [PATCH 3639/5416] ALSA: hda: appletv support The AppleTV needs the same handling as the 24" iMac. Signed-off-by: Peter Korsgaard Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index dedd51d5540..2ff617d066c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6656,6 +6656,7 @@ static int patch_alc882(struct hda_codec *codec) board_config = ALC885_MACPRO; break; case 0x106b1000: /* iMac 24 */ + case 0x106b2800: /* AppleTV */ board_config = ALC885_IMAC24; break; case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ -- GitLab From 00ef50c242f05381cd3fbf56bbda28155cbbb7c8 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Sat, 27 Sep 2008 18:13:47 -0400 Subject: [PATCH 3640/5416] ALSA: hda: SPDIF stream muting support Added support for muting S/DPIF outs using the 'Digital Playback Source' muxs on supporting codecs. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 35 ++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f9b25638892..05661f7f3ce 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -138,6 +138,7 @@ struct sigmatel_spec { unsigned int mic_switch: 1; unsigned int alt_switch: 1; unsigned int hp_detect: 1; + unsigned int spdif_mute: 1; /* gpio lines */ unsigned int eapd_mask; @@ -547,10 +548,32 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct sigmatel_spec *spec = codec->spec; + struct hda_input_mux *smux = &spec->private_smux; unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + int err, val; + hda_nid_t nid; - return snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, + err = snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, spec->smux_nids[smux_idx], &spec->cur_smux[smux_idx]); + if (err < 0) + return err; + + if (spec->spdif_mute) { + if (smux_idx == 0) + nid = spec->multiout.dig_out_nid; + else + nid = codec->slave_dig_outs[smux_idx - 1]; + if (spec->cur_smux[smux_idx] == smux->num_items - 1) + val = AMP_OUT_MUTE; + if (smux_idx == 0) + nid = spec->multiout.dig_out_nid; + else + nid = codec->slave_dig_outs[smux_idx - 1]; + /* un/mute SPDIF out */ + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, val); + } + return 0; } static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -1228,6 +1251,15 @@ static int stac92xx_build_controls(struct hda_codec *codec) return err; } if (spec->num_smuxes > 0) { + int wcaps = get_wcaps(codec, spec->multiout.dig_out_nid); + struct hda_input_mux *smux = &spec->private_smux; + /* check for mute support on SPDIF out */ + if (wcaps & AC_WCAP_OUT_AMP) { + smux->items[smux->num_items].label = "Off"; + smux->items[smux->num_items].index = 0; + smux->num_items++; + spec->spdif_mute = 1; + } stac_smux_mixer.count = spec->num_smuxes; err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&stac_smux_mixer, codec)); @@ -4377,7 +4409,6 @@ again: spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); switch (spec->board_config) { case STAC_HP_M4: -- GitLab From b636a1d947c7f1bb0e0a157663e08ce3e49b2e52 Mon Sep 17 00:00:00 2001 From: Vedran Miletic Date: Mon, 29 Sep 2008 15:08:00 +0200 Subject: [PATCH 3641/5416] ALSA: cs46xx: Add PCI IDs for TerraTec and Hercules cards This patch adds PCI IDs for: * TerraTec DMX XFire 1024 * Hercules Gamesurround Fortissimo II * Hercules Gamesurround Fortissimo III 7.1 All those cards were supported as generic CS46xx device, so they will work as before. I'm pretty sure that first two cards work, as they have same hardware design as reference card. Not sure about Fortissimo III, but this won't break it if it worked. Tested on TerraTec DMX XFire 1024. Signed-off-by: Vedran Miletic Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/cs46xx/cs46xx_lib.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index a10ab8283f9..fb6dc398025 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3501,8 +3501,9 @@ static struct cs_card_type __devinitdata cards[] = { .name = "Mitac MI6020/21", .amp = amp_voyetra, }, + /* Hercules Game Theatre XP */ { - .vendor = 0x14AF, + .vendor = 0x14af, /* Guillemot Corporation */ .id = 0x0050, .name = "Hercules Game Theatre XP", .amp = amp_hercules, @@ -3544,7 +3545,23 @@ static struct cs_card_type __devinitdata cards[] = { .amp = amp_hercules, .mixer_init = hercules_mixer_init, }, + /* Herculess Fortissimo */ + { + .vendor = 0x1681, + .id = 0xa010, + .name = "Hercules Gamesurround Fortissimo II", + }, + { + .vendor = 0x1681, + .id = 0xa011, + .name = "Hercules Gamesurround Fortissimo III 7.1", + }, /* Teratec */ + { + .vendor = 0x153b, + .id = 0x112e, + .name = "Terratec DMX XFire 1024", + }, { .vendor = 0x153b, .id = 0x1136, -- GitLab From d6b52039c95556ade5c4f99592a0dc46473fbf93 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 29 Sep 2008 23:14:11 +0400 Subject: [PATCH 3642/5416] ALSA: Correct Vladimir Barinov's e-mail address Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- arch/arm/plat-omap/include/mach/mtd-xip.h | 2 +- drivers/usb/host/ehci-ixp4xx.c | 2 +- sound/soc/codecs/tlv320aic3x.c | 2 +- sound/soc/codecs/tlv320aic3x.h | 2 +- sound/soc/davinci/davinci-evm.c | 2 +- sound/soc/davinci/davinci-i2s.c | 2 +- sound/soc/davinci/davinci-i2s.h | 2 +- sound/soc/davinci/davinci-pcm.c | 2 +- sound/soc/davinci/davinci-pcm.h | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/plat-omap/include/mach/mtd-xip.h b/arch/arm/plat-omap/include/mach/mtd-xip.h index 5cee7e16a1b..39b591ff54b 100644 --- a/arch/arm/plat-omap/include/mach/mtd-xip.h +++ b/arch/arm/plat-omap/include/mach/mtd-xip.h @@ -3,7 +3,7 @@ * * Do not include this file directly. It's included from linux/mtd/xip.h * - * Author: Vladimir Barinov + * Author: Vladimir Barinov * * (c) 2005 MontaVista Software, Inc. This file is licensed under the * terms of the GNU General Public License version 2. This program is diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index f9575c40912..9c32063a0c2 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -1,7 +1,7 @@ /* * IXP4XX EHCI Host Controller Driver * - * Author: Vladimir Barinov + * Author: Vladimir Barinov * * Based on "ehci-fsl.c" by Randy Vinson * diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 88428e22a4d..566a427c928 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1,7 +1,7 @@ /* * ALSA SoC TLV320AIC3X codec driver * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * Based on sound/soc/codecs/wm8753.c by Liam Girdwood diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index afb238ec0b9..00a195aa02e 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -1,7 +1,7 @@ /* * ALSA SoC TLV320AIC3X codec driver * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 092202302bd..9e6062cd6b5 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -1,7 +1,7 @@ /* * ASoC driver for TI DAVINCI EVM platform * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index e8269d6b788..abb5fedb0b1 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -1,7 +1,7 @@ /* * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h index c5b091807ee..241648ce887 100644 --- a/sound/soc/davinci/davinci-i2s.h +++ b/sound/soc/davinci/davinci-i2s.h @@ -1,7 +1,7 @@ /* * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 6a5e56a782b..76feaa65737 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -1,7 +1,7 @@ /* * ALSA PCM interface for the TI DAVINCI processor * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index 8d6a45e75a6..62cb4eb07e3 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -1,7 +1,7 @@ /* * ALSA PCM interface for the TI DAVINCI processor * - * Author: Vladimir Barinov, + * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * * This program is free software; you can redistribute it and/or modify -- GitLab From 19c009aad0ddeaa6a4ba41577022301f18d43afa Mon Sep 17 00:00:00 2001 From: Vedran Miletic Date: Mon, 29 Sep 2008 20:29:25 +0200 Subject: [PATCH 3643/5416] ALSA: hda: add more board-specific information for Realtek ALC662 rev1 I recently got a chance to play with two boards with ALC662 rev1: * BIOSTAR TA780G M2+ * ASROCK K10N78FullHD-hSLI R3.0 Both use 3 stack, 6ch mode with digital out. Since autodetection isn't able to figure that out from BIOS, we need to specify that manually. Signed-off-by: Vedran Miletic Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2ff617d066c..6322ab76a39 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15708,6 +15708,9 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1849, 0x0774, "ASROCK K10N78FullHD-hSLI R3.0", + ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13), -- GitLab From 669faba27f2f7b04b9228d20e30e7f584f0becd5 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Tue, 30 Sep 2008 15:49:13 +0200 Subject: [PATCH 3644/5416] ALSA: hda - Fix another ALC889A (rev 0x100101) ALC889A hardware (id 0x10ec0885 rev 0x100101) to use patch_alc883 Signed-off-by: Clive Messer Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6322ab76a39..e72b4eac0c6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6667,7 +6667,8 @@ static int patch_alc882(struct hda_codec *codec) break; default: /* ALC889A is handled better as ALC888-compatible */ - if (codec->revision_id == 0x100103) { + if (codec->revision_id == 0x100101 || + codec->revision_id == 0x100103) { alc_free(codec); return patch_alc883(codec); } @@ -16317,6 +16318,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, + { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A", + .patch = patch_alc882 }, /* should be patch_alc883() in future */ { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", .patch = patch_alc882 }, /* should be patch_alc883() in future */ { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, -- GitLab From 7a17daae8ed71bf3259d905a4fc48a5b424fa935 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 2 Oct 2008 14:50:22 +0200 Subject: [PATCH 3645/5416] ALSA: usb - Fix possible Oops at USB-MIDI disconnection The endpoints should be released immediately at disconnection rather than the delayed release. This could be a reason of Oops at USB-audio device disconnection being used. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/usbmidi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index c0c7770198a..5962e4b8442 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -1112,6 +1112,15 @@ void snd_usbmidi_disconnect(struct list_head* p) } if (ep->in) usb_kill_urb(ep->in->urb); + /* free endpoints here; later call can result in Oops */ + if (ep->out) { + snd_usbmidi_out_endpoint_delete(ep->out); + ep->out = NULL; + } + if (ep->in) { + snd_usbmidi_in_endpoint_delete(ep->in); + ep->in = NULL; + } } del_timer_sync(&umidi->error_timer); } -- GitLab From 310e0dc01d15f6e792a54f971dc7b1e13d1c6e95 Mon Sep 17 00:00:00 2001 From: Pedro Lopez-Cabanillas Date: Sat, 4 Oct 2008 16:27:36 +0200 Subject: [PATCH 3646/5416] ALSA: snd-usb-audio: support for Edirol UA-4FX device Renamed the old quirk function for ua-700/ua-25 to become more generic, moving the MIDI interfaces to the quirk data header. Added a new quirk for the Edirol UA-4FX. Signed-off-by: Pedro Lopez-Cabanillas Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/usbaudio.c | 41 +++++++------------------------- sound/usb/usbaudio.h | 2 +- sound/usb/usbquirks.h | 54 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8af12b680e1..6e70ba4ee21 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2997,12 +2997,12 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip, } /* - * Create a stream for an Edirol UA-700/UA-25 interface. The only way - * to detect the sample rate is by looking at wMaxPacketSize. + * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. + * The only way to detect the sample rate is by looking at wMaxPacketSize. */ -static int create_ua700_ua25_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - const struct snd_usb_audio_quirk *quirk) +static int create_uaxx_quirk(struct snd_usb_audio *chip, + struct usb_interface *iface, + const struct snd_usb_audio_quirk *quirk) { static const struct audioformat ua_format = { .format = SNDRV_PCM_FORMAT_S24_3LE, @@ -3017,37 +3017,12 @@ static int create_ua700_ua25_quirk(struct snd_usb_audio *chip, struct audioformat *fp; int stream, err; - /* both PCM and MIDI interfaces have 2 altsettings */ - if (iface->num_altsetting != 2) + /* both PCM and MIDI interfaces have 2 or more altsettings */ + if (iface->num_altsetting < 2) return -ENXIO; alts = &iface->altsetting[1]; altsd = get_iface_desc(alts); - if (altsd->bNumEndpoints == 2) { - static const struct snd_usb_midi_endpoint_info ua700_ep = { - .out_cables = 0x0003, - .in_cables = 0x0003 - }; - static const struct snd_usb_audio_quirk ua700_quirk = { - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &ua700_ep - }; - static const struct snd_usb_midi_endpoint_info ua25_ep = { - .out_cables = 0x0001, - .in_cables = 0x0001 - }; - static const struct snd_usb_audio_quirk ua25_quirk = { - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &ua25_ep - }; - if (chip->usb_id == USB_ID(0x0582, 0x002b)) - return snd_usb_create_midi_interface(chip, iface, - &ua700_quirk); - else - return snd_usb_create_midi_interface(chip, iface, - &ua25_quirk); - } - if (altsd->bNumEndpoints != 1) return -ENXIO; @@ -3377,9 +3352,9 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_CME] = snd_usb_create_midi_interface, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, - [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk, + [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk }; if (quirk->type < QUIRK_TYPE_COUNT) { diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index f3ca77f08ea..36e4f7a29ad 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -159,9 +159,9 @@ enum quirk_type { QUIRK_MIDI_US122L, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, - QUIRK_AUDIO_EDIROL_UA700_UA25, QUIRK_AUDIO_EDIROL_UA1000, QUIRK_AUDIO_EDIROL_UA101, + QUIRK_AUDIO_EDIROL_UAXX, QUIRK_TYPE_COUNT }; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index d96bf8b2b94..85532cf9dbf 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -862,15 +862,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = (const struct snd_usb_audio_quirk[]) { { .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = 3, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0003, + .in_cables = 0x0003 + } }, { .ifnum = -1 @@ -1204,15 +1208,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UA700_UA25 + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } }, { .ifnum = -1 @@ -1344,6 +1352,40 @@ YAMAHA_DEVICE(0x7010, "UB99"), .in_cables = 0x000f } } +}, +{ + /* + * This quirk is for the "Advanced Driver" mode. If off, the UA-4FX + * is standard compliant, but has only 16-bit PCM and no MIDI. + */ + USB_DEVICE(0x0582, 0x00a3), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .vendor_name = "EDIROL", + .product_name = "UA-4FX", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_EDIROL_UAXX + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_EDIROL_UAXX + }, + { + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } }, /* TODO: add Edirol MD-P1 support */ { -- GitLab From 238713d4891468f7942f7670d22ab44af0943a4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 5 Oct 2008 10:57:39 +0200 Subject: [PATCH 3647/5416] ALSA: hda - Fix PCI SSID for ASROCK K18N78FullHD-hSLI The PCI SSID for ASROCK mobo in commit ac56445dd6a38a36c2fa91989f5f6220a9bdf97c is wrong. This patch fixes to the correct one, 1849:3662. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e72b4eac0c6..0b6e682c46d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15710,7 +15710,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), - SND_PCI_QUIRK(0x1849, 0x0774, "ASROCK K10N78FullHD-hSLI R3.0", + SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), -- GitLab From 5c1d1a98c5e20ba517369d15995464a10add9132 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Tue, 7 Oct 2008 14:17:53 +0800 Subject: [PATCH 3648/5416] ALSA: hda: comment typo fix fix a typo in comment for process_unsol_events(). Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fdb6d559f5d..1c0b33b6ce1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -317,7 +317,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) } /* - * process queueud unsolicited events + * process queued unsolicited events */ static void process_unsol_events(struct work_struct *work) { -- GitLab From 6b34500c1ce9707b77ba1631bb21c8a1dea060bd Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Tue, 7 Oct 2008 14:21:41 +0800 Subject: [PATCH 3649/5416] ALSA: hda: comment typo fix fix a typo in comment for is_in_nid_list(). Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1c0b33b6ce1..6447754ae56 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2789,7 +2789,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, } /* - * Helper for automatic ping configuration + * Helper for automatic pin configuration */ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) -- GitLab From 8ae23ec3ab305b58140462234bddf2257af57bae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 Oct 2008 11:33:21 +0100 Subject: [PATCH 3650/5416] ALSA: ASoC: Correct inverted Mic PGA Switch control in wm8510 driver Mic PGA Switch should be inverted in the WM8510 driver but isn't. Reported-by: ext-jukka.hynninen@vaisala.com Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/codecs/wm8510.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 75ed0413ce4..9a37c8d95ed 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -199,7 +199,7 @@ SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0), }; static const struct snd_kcontrol_new wm8510_boost_controls[] = { -SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 0), +SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 1), SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0), SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0), }; -- GitLab From ff33f2303b0ea8e5ac15af91de8d8538a5d58db1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Oct 2008 11:38:09 +0200 Subject: [PATCH 3651/5416] ALSA: Increase components array size Increase the card components[] (and thus snd_card_info.components[], too) array size from 80 to 128 chars so that more strings can be stored. The 80 chars aren't enough for more than 2 HD-audio codecs, and this hits an ugly snd_BUG() as reported by Wu Fegguang for HP 2230s. The control protocol number is increased to 2.0.6 as well, in case it matters. Reported-by: Wu Fengguang Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- include/sound/asound.h | 5 ++--- include/sound/core.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index 1196e3d5194..2c4dc908a54 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -707,7 +707,7 @@ struct snd_timer_tread { * * ****************************************************************************/ -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5) +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) struct snd_ctl_card_info { int card; /* card number */ @@ -718,8 +718,7 @@ struct snd_ctl_card_info { unsigned char longname[80]; /* name + info text about soundcard */ unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ unsigned char mixername[80]; /* visual mixer identification */ - unsigned char components[80]; /* card components / fine identification, delimited with one space (AC97 etc..) */ - unsigned char reserved[48]; /* reserved for future */ + unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ }; typedef int __bitwise snd_ctl_elem_type_t; diff --git a/include/sound/core.h b/include/sound/core.h index f52ab6f3ca6..e5eec5f7350 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -116,7 +116,7 @@ struct snd_card { char shortname[32]; /* short name of this soundcard */ char longname[80]; /* name of this soundcard */ char mixername[80]; /* mixer name */ - char components[80]; /* card components delimited with + char components[128]; /* card components delimited with space */ struct module *module; /* top-level module */ -- GitLab From cb01e2b99264d579085c63966744d91b87c6b35d Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 7 Oct 2008 08:05:20 +0800 Subject: [PATCH 3652/5416] ALSA: ASoC: add new param mux to dapm_mux_update_power Function dapm_mux_update_power needs enum index mux and register mask value val as parameters, but it only has a parameter val, and uses it as both val and mux. snd_soc_test_bits(widget->codec, e->reg, mask, val) val is register mask here, e->texts[val] but val should be enum index mux here. This patch adds a new param mux to fix it. Signed-off-by: Richard Zhao Signed-off-by: Mark Brown Signed-off-by: Jaroslav Kysela --- sound/soc/soc-dapm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c016426fb89..9ca9c08610f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -693,7 +693,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) /* test and update the power status of a mux widget */ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, struct snd_kcontrol *kcontrol, int mask, - int val, struct soc_enum* e) + int mux, int val, struct soc_enum *e) { struct snd_soc_dapm_path *path; int found = 0; @@ -709,12 +709,12 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, if (path->kcontrol != kcontrol) continue; - if (!path->name || ! e->texts[val]) + if (!path->name || !e->texts[mux]) continue; found = 1; /* we now need to match the string in the enum to the path */ - if (!(strcmp(path->name, e->texts[val]))) + if (!(strcmp(path->name, e->texts[mux]))) path->connect = 1; /* new connection */ else path->connect = 0; /* old connection must be powered down */ @@ -1291,7 +1291,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mutex_lock(&widget->codec->mutex); widget->value = val; - dapm_mux_update_power(widget, kcontrol, mask, mux, e); + dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); if (widget->event) { if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { ret = widget->event(widget, -- GitLab From 52948b3f7c481be2cd3a68d1db42dd6906bf853a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Oct 2008 16:13:59 +0200 Subject: [PATCH 3653/5416] ALSA: Add a note on dependency of RTC stuff Added a note on the dependency of old RTC stuff, which is exclusive with the new RTC class drivers. http://bugme.linux-foundation.org/show_bug.cgi?id=11430 Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 91f91c5cdb4..66348c92f88 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -108,6 +108,9 @@ config SND_RTCTIMER To compile this driver as a module, choose M here: the module will be called snd-rtctimer. + Note that this option is exclusive with the new RTC drivers + (CONFIG_RTC_CLASS) since this requires the old API. + config SND_SEQ_RTCTIMER_DEFAULT bool "Use RTC as default sequencer timer" depends on SND_RTCTIMER && SND_SEQUENCER -- GitLab From 59b3db6c69ae9eeed1d8fc3aee6b88272ba38ba8 Mon Sep 17 00:00:00 2001 From: Pedro Lopez-Cabanillas Date: Tue, 7 Oct 2008 20:54:18 +0200 Subject: [PATCH 3654/5416] ALSA: usb-audio: dynamic detection of MIDI interfaces in uaxx-quirk The MIDI interfaces have to be detected dynamically for Edirol devices ua-700, ua-25 and ua4-fx. This patch reverses the wrong changes made by my other patch in uaxx-quirk. Signed-off-by: Pedro Lopez-Cabanillas Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/usb/usbaudio.c | 25 +++++++++++++++++++++++++ sound/usb/usbquirks.h | 18 +++--------------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 6e70ba4ee21..bbd70d5814a 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3023,6 +3023,31 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, alts = &iface->altsetting[1]; altsd = get_iface_desc(alts); + if (altsd->bNumEndpoints == 2) { + static const struct snd_usb_midi_endpoint_info ua700_ep = { + .out_cables = 0x0003, + .in_cables = 0x0003 + }; + static const struct snd_usb_audio_quirk ua700_quirk = { + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &ua700_ep + }; + static const struct snd_usb_midi_endpoint_info uaxx_ep = { + .out_cables = 0x0001, + .in_cables = 0x0001 + }; + static const struct snd_usb_audio_quirk uaxx_quirk = { + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &uaxx_ep + }; + if (chip->usb_id == USB_ID(0x0582, 0x002b)) + return snd_usb_create_midi_interface(chip, iface, + &ua700_quirk); + else + return snd_usb_create_midi_interface(chip, iface, + &uaxx_quirk); + } + if (altsd->bNumEndpoints != 1) return -ENXIO; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 85532cf9dbf..69689e79bf7 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -870,11 +870,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = -1 @@ -1216,11 +1212,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = -1 @@ -1375,11 +1367,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } + .type = QUIRK_AUDIO_EDIROL_UAXX }, { .ifnum = -1 -- GitLab From 32fe61426373d85e797bf4f4dcbe4510487c3e00 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Oct 2008 10:28:25 +0200 Subject: [PATCH 3655/5416] ALSA: mtpav - Fix race in probe Ingo reported Oops at probing mtpav driver. It's a race between the irq handler and the rawmidi instance registration. This patch fixes the order of registration to avoid the race. Signed-off-by: Takashi Iwai Tested-by: Ingo Molnar Signed-off-by: Jaroslav Kysela --- sound/drivers/mtpav.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index b5e1a71bb64..5b89c0883d6 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -715,6 +715,10 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev) card->private_free = snd_mtpav_free; + err = snd_mtpav_get_RAWMIDI(mtp_card); + if (err < 0) + goto __error; + err = snd_mtpav_get_ISA(mtp_card); if (err < 0) goto __error; @@ -724,10 +728,6 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev) snprintf(card->longname, sizeof(card->longname), "MTPAV on parallel port at 0x%lx", port); - err = snd_mtpav_get_RAWMIDI(mtp_card); - if (err < 0) - goto __error; - snd_mtpav_portscan(mtp_card); snd_card_set_dev(card, &dev->dev); -- GitLab From fb2aa074d4eac4957f5717d261bc336f4a5f31c4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Oct 2008 13:02:20 +0100 Subject: [PATCH 3656/5416] ALSA: ASoC: Check for machine type in GTA01 machine driver Since there are now multiple OpenMoko platforms it is more important to check that the machine driver is running on the correct system. This was orgininally generated as part of the initial GTA02 machine port. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/soc/s3c24xx/neo1973_wm8753.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 47ddcdedc3a..73a50e93a9a 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -716,6 +717,12 @@ static int __init neo1973_init(void) DBG("Entered %s\n", __func__); + if (!machine_is_neo1973_gta01()) { + printk(KERN_INFO + "Only GTA01 hardware supported by ASoC driver\n"); + return -ENODEV; + } + neo1973_snd_device = platform_device_alloc("soc-audio", -1); if (!neo1973_snd_device) return -ENOMEM; -- GitLab From b9aea7150a84d037b6ca3c2506b0058cee4eb1d2 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Thu, 9 Oct 2008 08:37:28 -0400 Subject: [PATCH 3657/5416] ALSA: hda: STAC_HP_M4 Set the third microphone to a default config of a 'Line In' to be added the Input Source Mux's. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 05661f7f3ce..5c65f7d4606 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -3643,7 +3643,12 @@ static int stac92xx_init(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = cfg->input_pins[i]; if (nid) { - unsigned int pinctl = AC_PINCTL_IN_EN; + unsigned int pinctl = snd_hda_codec_read(codec, nid, + 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + /* if PINCTL already set then skip */ + if (pinctl & AC_PINCAP_IN) + continue; + pinctl = AC_PINCTL_IN_EN; if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) pinctl |= stac92xx_get_vref(codec, nid); stac92xx_auto_set_pinctl(codec, nid, pinctl); @@ -4413,12 +4418,13 @@ again: switch (spec->board_config) { case STAC_HP_M4: spec->num_dmics = 0; - spec->num_smuxes = 1; + spec->num_smuxes = 0; spec->num_dmuxes = 0; /* enable internal microphone */ - snd_hda_codec_write_cache(codec, 0x0e, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80); + stac92xx_set_config_reg(codec, 0x0e, 0x01813040); + stac92xx_auto_set_pinctl(codec, 0x0e, + AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); break; default: spec->num_dmics = STAC92HD71BXX_NUM_DMICS; -- GitLab From 72474be62d6ec2e0337ff01ecbd737f9c5c242c7 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Thu, 9 Oct 2008 09:32:17 -0400 Subject: [PATCH 3658/5416] ALSA: hda: VREF powerdown for headphones Add support for powering down VREF on standard headphone insertion, also powers up the VREF on a headset insertion. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_sigmatel.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 5c65f7d4606..c461baa83c2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -38,6 +38,7 @@ #define NUM_CONTROL_ALLOC 32 #define STAC_PWR_EVENT 0x20 #define STAC_HP_EVENT 0x30 +#define STAC_VREF_EVENT 0x40 enum { STAC_REF, @@ -3854,13 +3855,22 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) struct sigmatel_spec *spec = codec->spec; int idx = res >> 26 & 0x0f; - switch ((res >> 26) & 0x30) { + switch ((res >> 26) & 0x70) { case STAC_HP_EVENT: stac92xx_hp_detect(codec, res); /* fallthru */ case STAC_PWR_EVENT: if (spec->num_pwrs > 0) stac92xx_pin_sense(codec, idx); + break; + case STAC_VREF_EVENT: { + int data = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_DATA, 0); + /* toggle VREF state based on GPIOx status */ + snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, + !!(data & (1 << idx))); + break; + } } } @@ -4360,6 +4370,17 @@ again: codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; break; case 0x111d7608: /* 5 Port with Analog Mixer */ + switch (codec->subsystem_id) { + case 0x103c361a: + /* Enable VREF power saving on GPIO1 detect */ + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); + snd_hda_codec_write_cache(codec, codec->afg, 0, + AC_VERB_SET_UNSOLICITED_ENABLE, + (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); + spec->gpio_mask |= 0x02; + break; + } if ((codec->revision_id & 0xf) == 0 || (codec->revision_id & 0xf) == 1) { #ifdef SND_HDA_NEEDS_RESUME -- GitLab From 01460f3520c100010aacc8f8500cafcb17ce4665 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 10 Oct 2008 13:36:57 +0100 Subject: [PATCH 3659/5416] dm mpath: use more error codes This patch allows path errors from the multipath ctr function to propagate up to userspace as errno values from the ioctl() call. This is in response to https://www.redhat.com/archives/dm-devel/2008-May/msg00000.html and https://bugzilla.redhat.com/show_bug.cgi?id=444421 The patch only lets through the errors that it needs to in order to get the path errors from parse_path(). Signed-off-by: Benjamin Marzinski Signed-off-by: Alasdair G Kergon --- drivers/md/dm-mpath.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index c2fcf28b4c7..c2ff77d77a5 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -563,12 +563,12 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, /* we need at least a path arg */ if (as->argc < 1) { ti->error = "no device given"; - return NULL; + return ERR_PTR(-EINVAL); } p = alloc_pgpath(); if (!p) - return NULL; + return ERR_PTR(-ENOMEM); r = dm_get_device(ti, shift(as), ti->begin, ti->len, dm_table_get_mode(ti->table), &p->path.dev); @@ -596,7 +596,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, bad: free_pgpath(p); - return NULL; + return ERR_PTR(r); } static struct priority_group *parse_priority_group(struct arg_set *as, @@ -614,14 +614,14 @@ static struct priority_group *parse_priority_group(struct arg_set *as, if (as->argc < 2) { as->argc = 0; - ti->error = "not enough priority group aruments"; - return NULL; + ti->error = "not enough priority group arguments"; + return ERR_PTR(-EINVAL); } pg = alloc_priority_group(); if (!pg) { ti->error = "couldn't allocate priority group"; - return NULL; + return ERR_PTR(-ENOMEM); } pg->m = m; @@ -654,8 +654,10 @@ static struct priority_group *parse_priority_group(struct arg_set *as, path_args.argv = as->argv; pgpath = parse_path(&path_args, &pg->ps, ti); - if (!pgpath) + if (IS_ERR(pgpath)) { + r = PTR_ERR(pgpath); goto bad; + } pgpath->pg = pg; list_add_tail(&pgpath->list, &pg->pgpaths); @@ -666,7 +668,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, bad: free_priority_group(pg, ti); - return NULL; + return ERR_PTR(r); } static int parse_hw_handler(struct arg_set *as, struct multipath *m) @@ -785,8 +787,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, struct priority_group *pg; pg = parse_priority_group(&as, m); - if (!pg) { - r = -EINVAL; + if (IS_ERR(pg)) { + r = PTR_ERR(pg); goto bad; } -- GitLab From 6680073d3ec7c6dbdbf77870bf1fea869767d779 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Fri, 10 Oct 2008 13:36:58 +0100 Subject: [PATCH 3660/5416] dm mpath: remove is_active from struct dm_path This patch moves 'is_active' from struct dm_path to struct pgpath as it does not need exporting. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon --- drivers/md/dm-mpath.c | 13 +++++++------ drivers/md/dm-mpath.h | 2 -- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index c2ff77d77a5..b2ab8489d0e 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -30,6 +30,7 @@ struct pgpath { struct list_head list; struct priority_group *pg; /* Owning PG */ + unsigned is_active; /* Path status */ unsigned fail_count; /* Cumulative failure count */ struct dm_path path; @@ -123,7 +124,7 @@ static struct pgpath *alloc_pgpath(void) struct pgpath *pgpath = kzalloc(sizeof(*pgpath), GFP_KERNEL); if (pgpath) - pgpath->path.is_active = 1; + pgpath->is_active = 1; return pgpath; } @@ -854,13 +855,13 @@ static int fail_path(struct pgpath *pgpath) spin_lock_irqsave(&m->lock, flags); - if (!pgpath->path.is_active) + if (!pgpath->is_active) goto out; DMWARN("Failing path %s.", pgpath->path.dev->name); pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path); - pgpath->path.is_active = 0; + pgpath->is_active = 0; pgpath->fail_count++; m->nr_valid_paths--; @@ -890,7 +891,7 @@ static int reinstate_path(struct pgpath *pgpath) spin_lock_irqsave(&m->lock, flags); - if (pgpath->path.is_active) + if (pgpath->is_active) goto out; if (!pgpath->pg->ps.type->reinstate_path) { @@ -904,7 +905,7 @@ static int reinstate_path(struct pgpath *pgpath) if (r) goto out; - pgpath->path.is_active = 1; + pgpath->is_active = 1; m->current_pgpath = NULL; if (!m->nr_valid_paths++ && m->queue_size) @@ -1292,7 +1293,7 @@ static int multipath_status(struct dm_target *ti, status_type_t type, list_for_each_entry(p, &pg->pgpaths, list) { DMEMIT("%s %s %u ", p->path.dev->name, - p->path.is_active ? "A" : "F", + p->is_active ? "A" : "F", p->fail_count); if (pg->ps.type->status) sz += pg->ps.type->status(&pg->ps, diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h index c198b856a45..e230f719625 100644 --- a/drivers/md/dm-mpath.h +++ b/drivers/md/dm-mpath.h @@ -13,8 +13,6 @@ struct dm_dev; struct dm_path { struct dm_dev *dev; /* Read-only */ - unsigned is_active; /* Read-only */ - void *pscontext; /* For path-selector use */ }; -- GitLab From f7c83e2e4783c4f7abe6f3a85a8c5e210f98bc7b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Fri, 10 Oct 2008 13:36:59 +0100 Subject: [PATCH 3661/5416] dm raid1: kcopyd should stop on error if errors handled dm-raid1 is setting the 'DM_KCOPYD_IGNORE_ERROR' flag unconditionally when assigning kcopyd work. kcopyd is responsible for copying an assigned section of disk to one or more other disks. The 'DM_KCOPYD_IGNORE_ERROR' flag affects kcopyd in the following way: When not set: kcopyd will immediately stop the copy operation when an error is encountered. When set: kcopyd will try to proceed regardless of errors and try to continue copying any remaining amount. Since dm-raid1 tracks regions of the address space that are (or are not) in sync and it now has the ability to handle these errors, we can safely enable this optimization. This optimization is conditional on whether mirror error handling has been enabled. Signed-off-by: Jonathan Brassow Signed-off-by: Alasdair G Kergon --- drivers/md/dm-raid1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ff05fe89308..29913e42c4a 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -842,7 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg) } /* hand to kcopyd */ - set_bit(DM_KCOPYD_IGNORE_ERROR, &flags); + if (!errors_handled(ms)) + set_bit(DM_KCOPYD_IGNORE_ERROR, &flags); + r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags, recovery_complete, reg); -- GitLab From a481db784682b33d078c7bf8a1d0581dc09946c1 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:00 +0100 Subject: [PATCH 3662/5416] dm exception store: introduce area_location function Move this logic to a function, because it will be reused later. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-exception-store.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 41f408068a7..824cf31967c 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -208,6 +208,14 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata) return req.result; } +/* + * Convert a metadata area index to a chunk index. + */ +static chunk_t area_location(struct pstore *ps, chunk_t area) +{ + return 1 + ((ps->exceptions_per_area + 1) * area); +} + /* * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. @@ -217,8 +225,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw) int r; uint32_t chunk; - /* convert a metadata area index to a chunk index */ - chunk = 1 + ((ps->exceptions_per_area + 1) * area); + chunk = area_location(ps, area); r = chunk_io(ps, chunk, rw, 0); if (r) -- GitLab From fd14acf6fc9f4635be201960004d847b14236a20 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:01 +0100 Subject: [PATCH 3663/5416] dm exception store: use chunk_t for_areas Change uint32_t into chunk_t to remove 32-bit limitation on the number of chunks on systems with 64-bit sector numbers. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-exception-store.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 824cf31967c..769ab677f8e 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -108,12 +108,12 @@ struct pstore { * Used to keep track of which metadata area the data in * 'chunk' refers to. */ - uint32_t current_area; + chunk_t current_area; /* * The next free chunk for an exception. */ - uint32_t next_free; + chunk_t next_free; /* * The index of next free exception in the current @@ -175,7 +175,7 @@ static void do_metadata(struct work_struct *work) /* * Read or write a chunk aligned and sized block of data from a device. */ -static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata) +static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) { struct dm_io_region where = { .bdev = ps->snap->cow->bdev, @@ -220,10 +220,10 @@ static chunk_t area_location(struct pstore *ps, chunk_t area) * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. */ -static int area_io(struct pstore *ps, uint32_t area, int rw) +static int area_io(struct pstore *ps, chunk_t area, int rw) { int r; - uint32_t chunk; + chunk_t chunk; chunk = area_location(ps, area); @@ -235,7 +235,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw) return 0; } -static int zero_area(struct pstore *ps, uint32_t area) +static int zero_area(struct pstore *ps, chunk_t area) { memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); return area_io(ps, area, WRITE); @@ -411,7 +411,7 @@ static int insert_exceptions(struct pstore *ps, int *full) static int read_exceptions(struct pstore *ps) { - uint32_t area; + chunk_t area; int r, full = 1; /* @@ -524,6 +524,7 @@ static int persistent_prepare(struct exception_store *store, { struct pstore *ps = get_info(store); uint32_t stride; + chunk_t next_free; sector_t size = get_dev_size(store->snap->cow->bdev); /* Is there enough room ? */ @@ -537,7 +538,8 @@ static int persistent_prepare(struct exception_store *store, * into account the location of the metadata chunks. */ stride = (ps->exceptions_per_area + 1); - if ((++ps->next_free % stride) == 1) + next_free = ++ps->next_free; + if (sector_div(next_free, stride) == 1) ps->next_free++; atomic_inc(&ps->pending_count); -- GitLab From 3e1a8bdd05d6b1734a8ccf7af28042d72c447780 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:02 +0100 Subject: [PATCH 3664/5416] dm crypt: tidy inc pending Move io pending to one place. No functional change, usefull to simplify debugging. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 13956437bc8..6b9be99eff5 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -517,6 +517,11 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) } } +static void crypt_inc_pending(struct dm_crypt_io *io) +{ + atomic_inc(&io->pending); +} + /* * One of the bios was finished. Check for completion of * the whole request and correctly clean up the buffer. @@ -591,7 +596,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io) struct bio *base_bio = io->base_bio; struct bio *clone; - atomic_inc(&io->pending); + crypt_inc_pending(io); /* * The block layer might modify the bvec array, so always @@ -665,7 +670,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, if (async) kcryptd_queue_io(io); else { - atomic_inc(&io->pending); + crypt_inc_pending(io); generic_make_request(clone); } } @@ -701,7 +706,7 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) if (unlikely(r < 0)) return; } else - atomic_inc(&io->pending); + crypt_inc_pending(io); /* out of memory -> run queues */ if (unlikely(remaining)) { @@ -720,7 +725,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) /* * Prevent io from disappearing until this function completes. */ - atomic_inc(&io->pending); + crypt_inc_pending(io); crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector); kcryptd_crypt_write_convert_loop(io); @@ -741,7 +746,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) struct crypt_config *cc = io->target->private; int r = 0; - atomic_inc(&io->pending); + crypt_inc_pending(io); crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, io->sector); -- GitLab From dc440d1e56c481f80d5350daadc7d078a04ca729 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:03 +0100 Subject: [PATCH 3665/5416] dm crypt: tidy crypt alloc Factor out crypt io allocation code. Later patches will call it from another place. No functional change. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 6b9be99eff5..cac064d4aa7 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -517,6 +517,22 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) } } +static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti, + struct bio *bio, sector_t sector) +{ + struct crypt_config *cc = ti->private; + struct dm_crypt_io *io; + + io = mempool_alloc(cc->io_pool, GFP_NOIO); + io->target = ti; + io->base_bio = bio; + io->sector = sector; + io->error = 0; + atomic_set(&io->pending, 0); + + return io; +} + static void crypt_inc_pending(struct dm_crypt_io *io) { atomic_inc(&io->pending); @@ -1113,15 +1129,9 @@ static void crypt_dtr(struct dm_target *ti) static int crypt_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) { - struct crypt_config *cc = ti->private; struct dm_crypt_io *io; - io = mempool_alloc(cc->io_pool, GFP_NOIO); - io->target = ti; - io->base_bio = bio; - io->sector = bio->bi_sector - ti->begin; - io->error = 0; - atomic_set(&io->pending, 0); + io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); if (bio_data_dir(io->base_bio) == READ) kcryptd_queue_io(io); -- GitLab From fc5a5e9aa878f86642c962b309f793fb2db0727e Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:04 +0100 Subject: [PATCH 3666/5416] dm crypt: tidy write loop pending Move kcryptd_crypt_write_convert_loop inside kcryptd_crypt_write_convert. This change is needed for a later patch. No functional change. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index cac064d4aa7..97b407582c0 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -691,13 +691,19 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, } } -static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) +static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; struct bio *clone; unsigned remaining = io->base_bio->bi_size; int r; + /* + * Prevent io from disappearing until this function completes. + */ + crypt_inc_pending(io); + crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector); + /* * The allocated buffers can be smaller than the whole bio, * so repeat the whole process until all the data can be handled. @@ -706,7 +712,7 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) clone = crypt_alloc_buffer(io, remaining); if (unlikely(!clone)) { io->error = -ENOMEM; - return; + break; } io->ctx.bio_out = clone; @@ -720,7 +726,7 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) /* processed, no running async crypto */ kcryptd_crypt_write_io_submit(io, r, 0); if (unlikely(r < 0)) - return; + break; } else crypt_inc_pending(io); @@ -732,19 +738,6 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) congestion_wait(WRITE, HZ/100); } } -} - -static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) -{ - struct crypt_config *cc = io->target->private; - - /* - * Prevent io from disappearing until this function completes. - */ - crypt_inc_pending(io); - - crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector); - kcryptd_crypt_write_convert_loop(io); crypt_dec_pending(io); } -- GitLab From 1e37bb8e557a186d327eb4d1387953880ffc2cdd Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Fri, 10 Oct 2008 13:37:05 +0100 Subject: [PATCH 3667/5416] dm crypt: remove inc_pending from write_io_submit Make the caller reponsible for incrementing the pending count before calling kcryptd_crypt_write_io_submit() in the non-async case to bring it into line with the async case. Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 97b407582c0..0042636ad37 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -685,10 +685,8 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, if (async) kcryptd_queue_io(io); - else { - crypt_inc_pending(io); + else generic_make_request(clone); - } } static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) @@ -724,9 +722,12 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) if (atomic_dec_and_test(&io->ctx.pending)) { /* processed, no running async crypto */ + crypt_inc_pending(io); kcryptd_crypt_write_io_submit(io, r, 0); - if (unlikely(r < 0)) + if (unlikely(r < 0)) { + crypt_dec_pending(io); break; + } } else crypt_inc_pending(io); -- GitLab From 6c031f41db15b6cb0cd33545cec28ca706cd3c7e Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:06 +0100 Subject: [PATCH 3668/5416] dm crypt: move dec_pending on error into write_io_submit Make kcryptd_crypt_write_io_submit() responsible for decrementing the pending count after an error. Also fixes a bug in the async path that forgot to decrement it. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 0042636ad37..d8126ac8296 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -674,6 +674,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, crypt_free_buffer_pages(cc, clone); bio_put(clone); io->error = -EIO; + crypt_dec_pending(io); return; } @@ -724,10 +725,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) /* processed, no running async crypto */ crypt_inc_pending(io); kcryptd_crypt_write_io_submit(io, r, 0); - if (unlikely(r < 0)) { - crypt_dec_pending(io); + if (unlikely(r < 0)) break; - } } else crypt_inc_pending(io); -- GitLab From 4e59409891c9cc30cb4d5d73250b0c968af8e39b Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:07 +0100 Subject: [PATCH 3669/5416] dm crypt: fix async inc_pending The pending reference count must be incremented *before* the async work is queued to another thread, not after. Otherwise there's a race if the work completes and decrements the reference count before it gets incremented. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index d8126ac8296..262ed181669 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -719,16 +719,15 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) remaining -= clone->bi_size; + crypt_inc_pending(io); r = crypt_convert(cc, &io->ctx); if (atomic_dec_and_test(&io->ctx.pending)) { /* processed, no running async crypto */ - crypt_inc_pending(io); kcryptd_crypt_write_io_submit(io, r, 0); if (unlikely(r < 0)) break; - } else - crypt_inc_pending(io); + } /* out of memory -> run queues */ if (unlikely(remaining)) { -- GitLab From c8081618a9f832fdf7ca81eb087f9f61f2bf07d5 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:08 +0100 Subject: [PATCH 3670/5416] dm crypt: tidy ctx pending Move the initialisation of ctx->pending into one place, at the start of crypt_convert(). Introduce crypt_finished to indicate whether or not the encryption is finished, for use in a later patch. No functional change. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 262ed181669..f6018f5961d 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -333,7 +333,6 @@ static void crypt_convert_init(struct crypt_config *cc, ctx->idx_out = bio_out ? bio_out->bi_idx : 0; ctx->sector = sector + cc->iv_offset; init_completion(&ctx->restart); - atomic_set(&ctx->pending, 1); } static int crypt_convert_block(struct crypt_config *cc, @@ -408,6 +407,8 @@ static int crypt_convert(struct crypt_config *cc, { int r; + atomic_set(&ctx->pending, 1); + while(ctx->idx_in < ctx->bio_in->bi_vcnt && ctx->idx_out < ctx->bio_out->bi_vcnt) { @@ -694,6 +695,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; struct bio *clone; + int crypt_finished; unsigned remaining = io->base_bio->bi_size; int r; @@ -721,19 +723,23 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) crypt_inc_pending(io); r = crypt_convert(cc, &io->ctx); + crypt_finished = atomic_dec_and_test(&io->ctx.pending); - if (atomic_dec_and_test(&io->ctx.pending)) { - /* processed, no running async crypto */ + /* Encryption was already finished, submit io now */ + if (crypt_finished) { kcryptd_crypt_write_io_submit(io, r, 0); + + /* + * If there was an error, do not try next fragments. + * For async, error is processed in async handler. + */ if (unlikely(r < 0)) break; } /* out of memory -> run queues */ if (unlikely(remaining)) { - /* wait for async crypto then reinitialize pending */ wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); - atomic_set(&io->ctx.pending, 1); congestion_wait(WRITE, HZ/100); } } -- GitLab From 933f01d43326fb12a978a8e0bb062c28a2de4d5a Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 10 Oct 2008 13:37:08 +0100 Subject: [PATCH 3671/5416] dm crypt: avoid unnecessary wait when splitting bio Don't wait between submitting crypt requests for a bio unless we are short of memory. There are two situations when we must split an encrypted bio: 1) there are no free pages; 2) the new bio would violate underlying device restrictions (e.g. max hw segments). In case (2) we do not need to wait. Add output variable to crypt_alloc_buffer() to distinguish between these cases. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index f6018f5961d..682ef9e6acd 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -457,9 +457,11 @@ static void dm_crypt_bio_destructor(struct bio *bio) /* * Generate a new unfragmented bio with the given size * This should never violate the device limitations - * May return a smaller bio when running out of pages + * May return a smaller bio when running out of pages, indicated by + * *out_of_pages set to 1. */ -static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) +static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, + unsigned *out_of_pages) { struct crypt_config *cc = io->target->private; struct bio *clone; @@ -473,11 +475,14 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) return NULL; clone_init(io, clone); + *out_of_pages = 0; for (i = 0; i < nr_iovecs; i++) { page = mempool_alloc(cc->page_pool, gfp_mask); - if (!page) + if (!page) { + *out_of_pages = 1; break; + } /* * if additional pages cannot be allocated without waiting, @@ -696,6 +701,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) struct crypt_config *cc = io->target->private; struct bio *clone; int crypt_finished; + unsigned out_of_pages = 0; unsigned remaining = io->base_bio->bi_size; int r; @@ -710,7 +716,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) * so repeat the whole process until all the data can be handled. */ while (remaining) { - clone = crypt_alloc_buffer(io, remaining); + clone = crypt_alloc_buffer(io, remaining, &out_of_pages); if (unlikely(!clone)) { io->error = -ENOMEM; break; @@ -737,11 +743,15 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) break; } - /* out of memory -> run queues */ - if (unlikely(remaining)) { - wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); + /* + * Out of memory -> run queues + * But don't wait if split was due to the io size restriction + */ + if (unlikely(out_of_pages)) congestion_wait(WRITE, HZ/100); - } + + if (unlikely(remaining)) + wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); } crypt_dec_pending(io); -- GitLab From 82b1519b345d61dcfae526e3fcb08128f39f9bcc Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:09 +0100 Subject: [PATCH 3672/5416] dm: export struct dm_dev Split struct dm_dev in two and publish the part that other targets need in include/linux/device-mapper.h. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 4 +- drivers/md/dm-table.c | 71 +++++++++++++++++++---------------- drivers/md/dm.h | 7 +--- include/linux/device-mapper.h | 7 +++- 4 files changed, 49 insertions(+), 40 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index b262c0042de..90e19f13f26 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1131,7 +1131,7 @@ static void retrieve_deps(struct dm_table *table, unsigned int count = 0; struct list_head *tmp; size_t len, needed; - struct dm_dev *dd; + struct dm_dev_internal *dd; struct dm_target_deps *deps; deps = get_result_buffer(param, param_size, &len); @@ -1157,7 +1157,7 @@ static void retrieve_deps(struct dm_table *table, deps->count = count; count = 0; list_for_each_entry (dd, dm_table_get_devices(table), list) - deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); + deps->dev[count++] = huge_encode_dev(dd->dm_dev.bdev->bd_dev); param->data_size = param->data_start + needed; } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 61f44140923..5dd32b8a57a 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -250,7 +250,8 @@ static void free_devices(struct list_head *devices) struct list_head *tmp, *next; list_for_each_safe(tmp, next, devices) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + struct dm_dev_internal *dd = + list_entry(tmp, struct dm_dev_internal, list); kfree(dd); } } @@ -327,12 +328,12 @@ static int lookup_device(const char *path, dev_t *dev) /* * See if we've already got a device in the list. */ -static struct dm_dev *find_device(struct list_head *l, dev_t dev) +static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev) { - struct dm_dev *dd; + struct dm_dev_internal *dd; list_for_each_entry (dd, l, list) - if (dd->bdev->bd_dev == dev) + if (dd->dm_dev.bdev->bd_dev == dev) return dd; return NULL; @@ -341,45 +342,47 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev) /* * Open a device so we can use it as a map destination. */ -static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md) +static int open_dev(struct dm_dev_internal *d, dev_t dev, + struct mapped_device *md) { static char *_claim_ptr = "I belong to device-mapper"; struct block_device *bdev; int r; - BUG_ON(d->bdev); + BUG_ON(d->dm_dev.bdev); - bdev = open_by_devnum(dev, d->mode); + bdev = open_by_devnum(dev, d->dm_dev.mode); if (IS_ERR(bdev)) return PTR_ERR(bdev); r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md)); if (r) blkdev_put(bdev); else - d->bdev = bdev; + d->dm_dev.bdev = bdev; return r; } /* * Close a device that we've been using. */ -static void close_dev(struct dm_dev *d, struct mapped_device *md) +static void close_dev(struct dm_dev_internal *d, struct mapped_device *md) { - if (!d->bdev) + if (!d->dm_dev.bdev) return; - bd_release_from_disk(d->bdev, dm_disk(md)); - blkdev_put(d->bdev); - d->bdev = NULL; + bd_release_from_disk(d->dm_dev.bdev, dm_disk(md)); + blkdev_put(d->dm_dev.bdev); + d->dm_dev.bdev = NULL; } /* * If possible, this checks an area of a destination device is valid. */ -static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) +static int check_device_area(struct dm_dev_internal *dd, sector_t start, + sector_t len) { - sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; + sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT; if (!dev_size) return 1; @@ -392,16 +395,17 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) * careful to leave things as they were if we fail to reopen the * device. */ -static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md) +static int upgrade_mode(struct dm_dev_internal *dd, int new_mode, + struct mapped_device *md) { int r; - struct dm_dev dd_copy; - dev_t dev = dd->bdev->bd_dev; + struct dm_dev_internal dd_copy; + dev_t dev = dd->dm_dev.bdev->bd_dev; dd_copy = *dd; - dd->mode |= new_mode; - dd->bdev = NULL; + dd->dm_dev.mode |= new_mode; + dd->dm_dev.bdev = NULL; r = open_dev(dd, dev, md); if (!r) close_dev(&dd_copy, md); @@ -421,7 +425,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, { int r; dev_t uninitialized_var(dev); - struct dm_dev *dd; + struct dm_dev_internal *dd; unsigned int major, minor; BUG_ON(!t); @@ -443,20 +447,20 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, if (!dd) return -ENOMEM; - dd->mode = mode; - dd->bdev = NULL; + dd->dm_dev.mode = mode; + dd->dm_dev.bdev = NULL; if ((r = open_dev(dd, dev, t->md))) { kfree(dd); return r; } - format_dev_t(dd->name, dev); + format_dev_t(dd->dm_dev.name, dev); atomic_set(&dd->count, 0); list_add(&dd->list, &t->devices); - } else if (dd->mode != (mode | dd->mode)) { + } else if (dd->dm_dev.mode != (mode | dd->dm_dev.mode)) { r = upgrade_mode(dd, mode, t->md); if (r) return r; @@ -465,11 +469,11 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, if (!check_device_area(dd, start, len)) { DMWARN("device %s too small for target", path); - dm_put_device(ti, dd); + dm_put_device(ti, &dd->dm_dev); return -EINVAL; } - *result = dd; + *result = &dd->dm_dev; return 0; } @@ -540,8 +544,11 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, /* * Decrement a devices use count and remove it if necessary. */ -void dm_put_device(struct dm_target *ti, struct dm_dev *dd) +void dm_put_device(struct dm_target *ti, struct dm_dev *d) { + struct dm_dev_internal *dd = container_of(d, struct dm_dev_internal, + dm_dev); + if (atomic_dec_and_test(&dd->count)) { close_dev(dd, ti->table->md); list_del(&dd->list); @@ -937,12 +944,12 @@ int dm_table_resume_targets(struct dm_table *t) int dm_table_any_congested(struct dm_table *t, int bdi_bits) { - struct dm_dev *dd; + struct dm_dev_internal *dd; struct list_head *devices = dm_table_get_devices(t); int r = 0; list_for_each_entry(dd, devices, list) { - struct request_queue *q = bdev_get_queue(dd->bdev); + struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); r |= bdi_congested(&q->backing_dev_info, bdi_bits); } @@ -951,11 +958,11 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits) void dm_table_unplug_all(struct dm_table *t) { - struct dm_dev *dd; + struct dm_dev_internal *dd; struct list_head *devices = dm_table_get_devices(t); list_for_each_entry(dd, devices, list) { - struct request_queue *q = bdev_get_queue(dd->bdev); + struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); blk_unplug(q); } diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 1e59a0b0a78..65f2f562220 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -25,13 +25,10 @@ /* * List of devices that a metadevice uses and should open/close. */ -struct dm_dev { +struct dm_dev_internal { struct list_head list; - atomic_t count; - int mode; - struct block_device *bdev; - char name[16]; + struct dm_dev dm_dev; }; struct dm_table; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index a90222e3297..178390de195 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -13,7 +13,6 @@ struct dm_target; struct dm_table; -struct dm_dev; struct mapped_device; struct bio_vec; @@ -84,6 +83,12 @@ void dm_error(const char *message); */ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev); +struct dm_dev { + struct block_device *bdev; + int mode; + char name[16]; +}; + /* * Constructors should call these functions to ensure destination devices * are opened/closed correctly. -- GitLab From 89343da077ad564ed130c46e5ea6a79388410fa5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:10 +0100 Subject: [PATCH 3673/5416] dm: publish dm_get_mapinfo Publish dm_get_mapinfo in include/linux/device-mapper.h because this function is used by targets. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.h | 1 - include/linux/device-mapper.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 65f2f562220..911d434361d 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -91,7 +91,6 @@ int dm_stripe_init(void); void dm_stripe_exit(void); void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); -union map_info *dm_get_mapinfo(struct bio *bio); int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md); diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 178390de195..6b80961650f 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -207,6 +207,7 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); int dm_noflush_suspending(struct dm_target *ti); +union map_info *dm_get_mapinfo(struct bio *bio); /* * Geometry functions. -- GitLab From ea0ec640940c2ae3a8d71af3249fccf06a9997a3 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:11 +0100 Subject: [PATCH 3674/5416] dm: publish dm_table_unplug_all Publish dm_table_unplug_all in include/linux/device-mapper.h because this function is used by targets. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.h | 1 - include/linux/device-mapper.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 911d434361d..8812208978e 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -46,7 +46,6 @@ void dm_table_presuspend_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t); int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); -void dm_table_unplug_all(struct dm_table *t); /* * To check the return value from dm_table_find_target(). diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 6b80961650f..e462c7f3b39 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -237,6 +237,11 @@ int dm_table_add_target(struct dm_table *t, const char *type, */ int dm_table_complete(struct dm_table *t); +/* + * Unplug all devices in a table. + */ +void dm_table_unplug_all(struct dm_table *t); + /* * Table reference counting. */ -- GitLab From 54160904260fa764ba6e2dc738770be30fdf9553 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 10 Oct 2008 13:37:12 +0100 Subject: [PATCH 3675/5416] dm: publish dm_vcalloc Publish dm_vcalloc in include/linux/device-mapper.h because this function is used by targets. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.h | 1 - include/linux/device-mapper.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 8812208978e..cd189da2b2f 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -89,7 +89,6 @@ void dm_linear_exit(void); int dm_stripe_init(void); void dm_stripe_exit(void); -void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md); diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index e462c7f3b39..08d783592b7 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -267,6 +267,11 @@ void dm_table_event(struct dm_table *t); */ int dm_swap_table(struct mapped_device *md, struct dm_table *t); +/* + * A wrapper around vmalloc. + */ +void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); + /*----------------------------------------------------------------- * Macros. *---------------------------------------------------------------*/ -- GitLab From 0c2322e4ce144e130c03d813fe92de3798662c5e Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Fri, 10 Oct 2008 13:37:13 +0100 Subject: [PATCH 3676/5416] dm: detect lost queue Detect and report buggy drivers that destroy their request_queue. Signed-off-by: Alasdair G Kergon Cc: Stefan Raspl Cc: Jens Axboe Cc: Andrew Morton --- drivers/md/dm-table.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5dd32b8a57a..a740a6950f5 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -482,6 +482,13 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) { struct request_queue *q = bdev_get_queue(bdev); struct io_restrictions *rs = &ti->limits; + char b[BDEVNAME_SIZE]; + + if (unlikely(!q)) { + DMWARN("%s: Cannot set limits for nonexistent device %s", + dm_device_name(ti->table->md), bdevname(bdev, b)); + return; + } /* * Combine the device limits low. @@ -950,7 +957,14 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits) list_for_each_entry(dd, devices, list) { struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); - r |= bdi_congested(&q->backing_dev_info, bdi_bits); + char b[BDEVNAME_SIZE]; + + if (likely(q)) + r |= bdi_congested(&q->backing_dev_info, bdi_bits); + else + DMWARN_LIMIT("%s: any_congested: nonexistent device %s", + dm_device_name(t->md), + bdevname(dd->dm_dev.bdev, b)); } return r; @@ -963,8 +977,14 @@ void dm_table_unplug_all(struct dm_table *t) list_for_each_entry(dd, devices, list) { struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); - - blk_unplug(q); + char b[BDEVNAME_SIZE]; + + if (likely(q)) + blk_unplug(q); + else + DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s", + dm_device_name(t->md), + bdevname(dd->dm_dev.bdev, b)); } } -- GitLab From 4e8086d65bd0a606434a4b16611653387f8c9698 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 21:07:55 +0800 Subject: [PATCH 3677/5416] Blackfin arch: update anomaly headers to match the latest sheet Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- .../mach-bf527/include/mach/anomaly.h | 158 +++++++++++++----- .../mach-bf533/include/mach/anomaly.h | 49 +++--- .../mach-bf537/include/mach/anomaly.h | 2 + .../mach-bf548/include/mach/anomaly.h | 91 +++++++++- .../mach-bf561/include/mach/anomaly.h | 2 + 5 files changed, 227 insertions(+), 75 deletions(-) diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h index dc26912430e..62373e61c58 100644 --- a/arch/blackfin/mach-bf527/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h @@ -7,12 +7,24 @@ */ /* This file shoule be up to date with: - * - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List + * - Revision B, 08/12/2008; ADSP-BF526 Blackfin Processor Anomaly List + * - Revision E, 08/18/2008; ADSP-BF527 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ #define _MACH_ANOMALY_H_ +#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) +# define ANOMALY_BF526 1 +#else +# define ANOMALY_BF526 0 +#endif +#if defined(__ADSPBF523__) || defined(__ADSPBF525__) || defined(__ADSPBF527__) +# define ANOMALY_BF527 1 +#else +# define ANOMALY_BF527 0 +#endif + /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */ #define ANOMALY_05000074 (1) /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */ @@ -23,70 +35,124 @@ #define ANOMALY_05000245 (1) /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */ #define ANOMALY_05000265 (1) -/* New Feature: EMAC TX DMA Word Alignment */ -#define ANOMALY_05000285 (1) +/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ +#define ANOMALY_05000310 (1) /* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */ -#define ANOMALY_05000312 (1) +#define ANOMALY_05000312 (ANOMALY_BF527) +/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */ +#define ANOMALY_05000313 (__SILICON_REVISION__ < 2) /* Incorrect Access of OTP_STATUS During otp_write() Function */ -#define ANOMALY_05000328 (1) +#define ANOMALY_05000328 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */ -#define ANOMALY_05000337 (1) +#define ANOMALY_05000337 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */ -#define ANOMALY_05000341 (1) +#define ANOMALY_05000341 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */ -#define ANOMALY_05000342 (1) +#define ANOMALY_05000342 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* USB Calibration Value Is Not Initialized */ -#define ANOMALY_05000346 (1) +#define ANOMALY_05000346 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* USB Calibration Value to use */ #define ANOMALY_05000346_value 0xE510 /* Preboot Routine Incorrectly Alters Reset Value of USB Register */ -#define ANOMALY_05000347 (1) +#define ANOMALY_05000347 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Security Features Are Not Functional */ -#define ANOMALY_05000348 (__SILICON_REVISION__ < 1) +#define ANOMALY_05000348 (ANOMALY_BF527 && __SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Function Performs Improper System Reset */ +#define ANOMALY_05000353 (ANOMALY_BF526) /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */ -#define ANOMALY_05000355 (1) +#define ANOMALY_05000355 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ -#define ANOMALY_05000357 (1) +#define ANOMALY_05000357 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Incorrect Revision Number in DSPID Register */ -#define ANOMALY_05000364 (__SILICON_REVISION__ > 0) +#define ANOMALY_05000364 (ANOMALY_BF527 && __SILICON_REVISION__ == 1) /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ #define ANOMALY_05000366 (1) -/* New Feature: Higher Default CCLK Rate */ -#define ANOMALY_05000368 (1) +/* Incorrect Default CSEL Value in PLL_DIV */ +#define ANOMALY_05000368 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Authentication Fails To Initiate */ -#define ANOMALY_05000376 (__SILICON_REVISION__ > 0) +#define ANOMALY_05000376 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* Data Read From L3 Memory by USB DMA May be Corrupted */ -#define ANOMALY_05000380 (1) -/* USB Full-speed Mode not Fully Tested */ -#define ANOMALY_05000381 (1) -/* New Feature: Boot from OTP Memory */ -#define ANOMALY_05000385 (1) -/* New Feature: bfrom_SysControl() Routine */ -#define ANOMALY_05000386 (1) -/* New Feature: Programmable Preboot Settings */ -#define ANOMALY_05000387 (1) +#define ANOMALY_05000380 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* 8-Bit NAND Flash Boot Mode Not Functional */ +#define ANOMALY_05000382 (__SILICON_REVISION__ < 2) +/* Host Must Not Read Back During Host DMA Boot */ +#define ANOMALY_05000384 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Boot from OTP Memory Not Functional */ +#define ANOMALY_05000385 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Routine Not Functional */ +#define ANOMALY_05000386 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Programmable Preboot Settings Not Functional */ +#define ANOMALY_05000387 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* CRC32 Checksum Support Not Functional */ +#define ANOMALY_05000388 (__SILICON_REVISION__ < 2) /* Reset Vector Must Not Be in SDRAM Memory Space */ -#define ANOMALY_05000389 (1) -/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */ -#define ANOMALY_05000392 (1) -/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */ -#define ANOMALY_05000393 (1) -/* New Feature: Log Buffer Functionality */ -#define ANOMALY_05000394 (1) -/* New Feature: Hook Routine Functionality */ -#define ANOMALY_05000395 (1) -/* New Feature: Header Indirect Bit */ -#define ANOMALY_05000396 (1) -/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */ -#define ANOMALY_05000397 (1) -/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */ -#define ANOMALY_05000398 (1) -/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */ -#define ANOMALY_05000399 (1) +#define ANOMALY_05000389 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000392 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000393 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Log Buffer Not Functional */ +#define ANOMALY_05000394 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Hook Routine Not Functional */ +#define ANOMALY_05000395 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Header Indirect Bit Not Functional */ +#define ANOMALY_05000396 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */ +#define ANOMALY_05000397 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* SWRESET, DFRESET and WDRESET Bits in the SYSCR Register Not Functional */ +#define ANOMALY_05000398 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* BCODE_NOBOOT in BCODE Field of SYSCR Register Not Functional */ +#define ANOMALY_05000399 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) /* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */ -#define ANOMALY_05000401 (1) +#define ANOMALY_05000401 (__SILICON_REVISION__ < 2) +/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */ +#define ANOMALY_05000403 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Disallows Certain User Interrupts */ +#define ANOMALY_05000404 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Does Not Save/Restore Full Context */ +#define ANOMALY_05000405 (1) +/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */ +#define ANOMALY_05000407 (__SILICON_REVISION__ < 2) +/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */ +#define ANOMALY_05000408 (1) +/* Lockbox firmware leaves MDMA0 channel enabled */ +#define ANOMALY_05000409 (__SILICON_REVISION__ < 2) +/* Incorrect Default Internal Voltage Regulator Setting */ +#define ANOMALY_05000410 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */ +#define ANOMALY_05000411 (__SILICON_REVISION__ < 2) +/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */ +#define ANOMALY_05000414 (__SILICON_REVISION__ < 2) +/* DEB2_URGENT Bit Not Functional */ +#define ANOMALY_05000415 (__SILICON_REVISION__ < 2) +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) +/* SPORT0 Ignores External TSCLK0 on PG14 When TMR6 is an Output */ +#define ANOMALY_05000417 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* tSFSPE and tHFSPE Do Not Meet Data Sheet Specifications */ +#define ANOMALY_05000418 (__SILICON_REVISION__ < 2) +/* USB PLL_STABLE Bit May Not Accurately Reflect the USB PLL's Status */ +#define ANOMALY_05000420 (__SILICON_REVISION__ < 2) +/* TWI Fall Time (Tof) May Violate the Minimum I2C Specification */ +#define ANOMALY_05000421 (1) +/* TWI Input Capacitance (Ci) May Violate the Maximum I2C Specification */ +#define ANOMALY_05000422 (ANOMALY_BF527 && __SILICON_REVISION__ > 1) +/* Certain Ethernet Frames With Errors are Misclassified in RMII Mode */ +#define ANOMALY_05000423 (__SILICON_REVISION__ < 2) +/* Internal Voltage Regulator Not Trimmed */ +#define ANOMALY_05000424 (ANOMALY_BF527 && __SILICON_REVISION__ < 2) +/* Multichannel SPORT Channel Misalignment Under Specific Configuration */ +#define ANOMALY_05000425 (__SILICON_REVISION__ < 2) +/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */ +#define ANOMALY_05000426 (1) +/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Reflects Buffer Status Instead of IRQ Status */ +#define ANOMALY_05000429 (__SILICON_REVISION__ < 2) +/* Software System Reset Corrupts PLL_LOCKCNT Register */ +#define ANOMALY_05000430 (ANOMALY_BF527 && __SILICON_REVISION__ > 1) +/* bfrom_SysControl() Does Not Clear SIC_IWR1 Before Executing PLL Programming Sequence */ +#define ANOMALY_05000432 (ANOMALY_BF526) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) @@ -99,6 +165,8 @@ #define ANOMALY_05000263 (0) #define ANOMALY_05000266 (0) #define ANOMALY_05000273 (0) +#define ANOMALY_05000285 (0) +#define ANOMALY_05000307 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h index 8f7ea112fd3..f544fc56959 100644 --- a/arch/blackfin/mach-bf533/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h @@ -7,7 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List + * - Revision D, 06/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -97,11 +97,11 @@ /* UART STB Bit Incorrectly Affects Receiver Setting */ #define ANOMALY_05000231 (__SILICON_REVISION__ < 5) /* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */ -#define ANOMALY_05000233 (__SILICON_REVISION__ < 4) +#define ANOMALY_05000233 (__SILICON_REVISION__ < 6) /* Incorrect Revision Number in DSPID Register */ #define ANOMALY_05000234 (__SILICON_REVISION__ == 4) /* DF Bit in PLL_CTL Register Does Not Respond to Hardware Reset */ -#define ANOMALY_05000242 (__SILICON_REVISION__ < 4) +#define ANOMALY_05000242 (__SILICON_REVISION__ < 5) /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */ #define ANOMALY_05000244 (__SILICON_REVISION__ < 5) /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */ @@ -131,7 +131,7 @@ /* CSYNC/SSYNC/IDLE Causes Infinite Stall in Penultimate Instruction in Hardware Loop */ #define ANOMALY_05000264 (__SILICON_REVISION__ < 5) /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */ -#define ANOMALY_05000265 (__SILICON_REVISION__ < 5) +#define ANOMALY_05000265 (1) /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Increase */ #define ANOMALY_05000269 (__SILICON_REVISION__ < 5) /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */ @@ -141,56 +141,59 @@ /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */ #define ANOMALY_05000272 (1) /* Writes to Synchronous SDRAM Memory May Be Lost */ -#define ANOMALY_05000273 (1) +#define ANOMALY_05000273 (__SILICON_REVISION__ < 6) /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */ #define ANOMALY_05000276 (1) /* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */ -#define ANOMALY_05000277 (1) +#define ANOMALY_05000277 (__SILICON_REVISION__ < 6) /* Disabling Peripherals with DMA Running May Cause DMA System Instability */ -#define ANOMALY_05000278 (1) +#define ANOMALY_05000278 (__SILICON_REVISION__ < 6) /* False Hardware Error Exception When ISR Context Is Not Restored */ -#define ANOMALY_05000281 (1) +#define ANOMALY_05000281 (__SILICON_REVISION__ < 6) /* Memory DMA Corruption with 32-Bit Data and Traffic Control */ -#define ANOMALY_05000282 (1) +#define ANOMALY_05000282 (__SILICON_REVISION__ < 6) /* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */ -#define ANOMALY_05000283 (1) +#define ANOMALY_05000283 (__SILICON_REVISION__ < 6) /* SPORTs May Receive Bad Data If FIFOs Fill Up */ -#define ANOMALY_05000288 (1) +#define ANOMALY_05000288 (__SILICON_REVISION__ < 6) /* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */ -#define ANOMALY_05000301 (1) +#define ANOMALY_05000301 (__SILICON_REVISION__ < 6) /* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */ #define ANOMALY_05000302 (__SILICON_REVISION__ < 5) /* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */ #define ANOMALY_05000305 (__SILICON_REVISION__ < 5) /* New Feature: Additional PPI Frame Sync Sampling Options (Not Available On Older Silicon) */ #define ANOMALY_05000306 (__SILICON_REVISION__ < 5) +/* SCKELOW Bit Does Not Maintain State Through Hibernate */ +#define ANOMALY_05000307 (1) /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ #define ANOMALY_05000310 (1) /* Erroneous Flag (GPIO) Pin Operations under Specific Sequences */ -#define ANOMALY_05000311 (1) +#define ANOMALY_05000311 (__SILICON_REVISION__ < 6) /* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */ -#define ANOMALY_05000312 (1) +#define ANOMALY_05000312 (__SILICON_REVISION__ < 6) /* PPI Is Level-Sensitive on First Transfer */ -#define ANOMALY_05000313 (1) +#define ANOMALY_05000313 (__SILICON_REVISION__ < 6) /* Killed System MMR Write Completes Erroneously On Next System MMR Access */ -#define ANOMALY_05000315 (1) +#define ANOMALY_05000315 (__SILICON_REVISION__ < 6) /* Internal Voltage Regulator Values of 1.05V, 1.10V and 1.15V Not Allowed for LQFP Packages */ -#define ANOMALY_05000319 (ANOMALY_BF531 || ANOMALY_BF532) +#define ANOMALY_05000319 ((ANOMALY_BF531 || ANOMALY_BF532) && __SILICON_REVISION__ < 6) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ -#define ANOMALY_05000357 (1) +#define ANOMALY_05000357 (__SILICON_REVISION__ < 6) /* UART Break Signal Issues */ #define ANOMALY_05000363 (__SILICON_REVISION__ < 5) /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ #define ANOMALY_05000366 (1) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (__SILICON_REVISION__ < 6) /* PPI Does Not Start Properly In Specific Mode */ -#define ANOMALY_05000400 (__SILICON_REVISION__ >= 5) +#define ANOMALY_05000400 (__SILICON_REVISION__ == 5) /* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */ -#define ANOMALY_05000402 (__SILICON_REVISION__ >= 5) +#define ANOMALY_05000402 (__SILICON_REVISION__ == 5) /* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */ #define ANOMALY_05000403 (1) - +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) /* These anomalies have been "phased" out of analog.com anomaly sheets and are * here to show running on older silicon just isn't feasible. @@ -268,5 +271,7 @@ /* Anomalies that don't exist on this proc */ #define ANOMALY_05000266 (0) #define ANOMALY_05000323 (0) +#define ANOMALY_05000353 (1) +#define ANOMALY_05000386 (1) #endif diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h index 8460ab9c324..c68992494f9 100644 --- a/arch/blackfin/mach-bf537/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h @@ -158,6 +158,8 @@ #define ANOMALY_05000266 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) +#define ANOMALY_05000353 (1) #define ANOMALY_05000363 (0) +#define ANOMALY_05000386 (1) #endif diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index d02cd803828..816b09278f6 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -2,18 +2,18 @@ * File: include/asm-blackfin/mach-bf548/anomaly.h * Bugs: Enter bugs at http://blackfin.uclinux.org/ * - * Copyright (C) 2004-2007 Analog Devices Inc. + * Copyright (C) 2004-2008 Analog Devices Inc. * Licensed under the GPL-2 or later. */ /* This file shoule be up to date with: - * - Revision E, 11/28/2007; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List + * - Revision G, 08/07/2008; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ #define _MACH_ANOMALY_H_ -/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */ +/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */ #define ANOMALY_05000074 (1) /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */ #define ANOMALY_05000119 (1) @@ -36,14 +36,14 @@ /* TWI Slave Boot Mode Is Not Functional */ #define ANOMALY_05000324 (__SILICON_REVISION__ < 1) /* External FIFO Boot Mode Is Not Functional */ -#define ANOMALY_05000325 (__SILICON_REVISION__ < 1) +#define ANOMALY_05000325 (__SILICON_REVISION__ < 2) /* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */ #define ANOMALY_05000327 (__SILICON_REVISION__ < 1) /* Incorrect Access of OTP_STATUS During otp_write() Function */ #define ANOMALY_05000328 (__SILICON_REVISION__ < 1) /* Synchronous Burst Flash Boot Mode Is Not Functional */ #define ANOMALY_05000329 (__SILICON_REVISION__ < 1) -/* Host DMA Boot Mode Is Not Functional */ +/* Host DMA Boot Modes Are Not Functional */ #define ANOMALY_05000330 (__SILICON_REVISION__ < 1) /* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */ #define ANOMALY_05000334 (__SILICON_REVISION__ < 1) @@ -63,26 +63,100 @@ #define ANOMALY_05000346 (__SILICON_REVISION__ < 1) /* USB Calibration Value to use */ #define ANOMALY_05000346_value 0x5411 -/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */ +/* Preboot Routine Incorrectly Alters Reset Value of USB Register */ #define ANOMALY_05000347 (__SILICON_REVISION__ < 1) /* Data Lost when Core Reads SDH Data FIFO */ #define ANOMALY_05000349 (__SILICON_REVISION__ < 1) /* PLL Status Register Is Inaccurate */ #define ANOMALY_05000351 (__SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Function Performs Improper System Reset */ +#define ANOMALY_05000353 (__SILICON_REVISION__ < 2) +/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */ +#define ANOMALY_05000355 (__SILICON_REVISION__ < 1) +/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */ +#define ANOMALY_05000356 (__SILICON_REVISION__ < 1) /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ #define ANOMALY_05000357 (1) /* External Memory Read Access Hangs Core With PLL Bypass */ #define ANOMALY_05000360 (1) /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */ #define ANOMALY_05000365 (1) +/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */ +#define ANOMALY_05000367 (__SILICON_REVISION__ < 1) /* Addressing Conflict between Boot ROM and Asynchronous Memory */ #define ANOMALY_05000369 (1) +/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */ +#define ANOMALY_05000370 (__SILICON_REVISION__ < 1) /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ -#define ANOMALY_05000371 (1) +#define ANOMALY_05000371 (__SILICON_REVISION__ < 2) +/* USB DP/DM Data Pins May Lose State When Entering Hibernate */ +#define ANOMALY_05000372 (__SILICON_REVISION__ < 1) /* Mobile DDR Operation Not Functional */ #define ANOMALY_05000377 (1) /* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */ -#define ANOMALY_05000378 (1) +#define ANOMALY_05000378 (__SILICON_REVISION__ < 2) +/* 16-Bit NAND FLASH Boot Mode Is Not Functional */ +#define ANOMALY_05000379 (1) +/* 8-Bit NAND Flash Boot Mode Not Functional */ +#define ANOMALY_05000382 (__SILICON_REVISION__ < 1) +/* Some ATAPI Modes Are Not Functional */ +#define ANOMALY_05000383 (1) +/* Boot from OTP Memory Not Functional */ +#define ANOMALY_05000385 (__SILICON_REVISION__ < 1) +/* bfrom_SysControl() Firmware Routine Not Functional */ +#define ANOMALY_05000386 (__SILICON_REVISION__ < 1) +/* Programmable Preboot Settings Not Functional */ +#define ANOMALY_05000387 (__SILICON_REVISION__ < 1) +/* CRC32 Checksum Support Not Functional */ +#define ANOMALY_05000388 (__SILICON_REVISION__ < 1) +/* Reset Vector Must Not Be in SDRAM Memory Space */ +#define ANOMALY_05000389 (__SILICON_REVISION__ < 1) +/* Changed Meaning of BCODE Field in SYSCR Register */ +#define ANOMALY_05000390 (__SILICON_REVISION__ < 1) +/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */ +#define ANOMALY_05000391 (__SILICON_REVISION__ < 1) +/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000392 (__SILICON_REVISION__ < 1) +/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */ +#define ANOMALY_05000393 (__SILICON_REVISION__ < 1) +/* Log Buffer Not Functional */ +#define ANOMALY_05000394 (__SILICON_REVISION__ < 1) +/* Hook Routine Not Functional */ +#define ANOMALY_05000395 (__SILICON_REVISION__ < 1) +/* Header Indirect Bit Not Functional */ +#define ANOMALY_05000396 (__SILICON_REVISION__ < 1) +/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */ +#define ANOMALY_05000397 (__SILICON_REVISION__ < 1) +/* Lockbox SESR Disallows Certain User Interrupts */ +#define ANOMALY_05000404 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Does Not Save/Restore Full Context */ +#define ANOMALY_05000405 (1) +/* Lockbox SESR Argument Checking Does Not Check L2 Memory Protection Range */ +#define ANOMALY_05000406 (__SILICON_REVISION__ < 2) +/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */ +#define ANOMALY_05000407 (__SILICON_REVISION__ < 2) +/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */ +#define ANOMALY_05000408 (1) +/* Lockbox firmware leaves MDMA0 channel enabled */ +#define ANOMALY_05000409 (__SILICON_REVISION__ < 2) +/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */ +#define ANOMALY_05000411 (__SILICON_REVISION__ < 2) +/* NAND Boot Mode Not Compatible With Some NAND Flash Devices */ +#define ANOMALY_05000413 (__SILICON_REVISION__ < 2) +/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */ +#define ANOMALY_05000414 (__SILICON_REVISION__ < 2) +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_05000416 (1) +/* Multichannel SPORT Channel Misalignment Under Specific Configuration */ +#define ANOMALY_05000425 (1) +/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */ +#define ANOMALY_05000426 (1) +/* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */ +#define ANOMALY_05000427 (__SILICON_REVISION__ < 2) +/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Behaves as a Buffer Status Bit Instead of an IRQ Status Bit */ +#define ANOMALY_05000429 (__SILICON_REVISION__ < 2) +/* Software System Reset Corrupts PLL_LOCKCNT Register */ +#define ANOMALY_05000430 (__SILICON_REVISION__ >= 2) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) @@ -95,6 +169,7 @@ #define ANOMALY_05000263 (0) #define ANOMALY_05000266 (0) #define ANOMALY_05000273 (0) +#define ANOMALY_05000307 (0) #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h index 5c5d7d7d695..22990df04ae 100644 --- a/arch/blackfin/mach-bf561/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h @@ -270,5 +270,7 @@ #define ANOMALY_05000183 (0) #define ANOMALY_05000273 (0) #define ANOMALY_05000311 (0) +#define ANOMALY_05000353 (1) +#define ANOMALY_05000386 (1) #endif -- GitLab From e1fee94f346387739e683b31815ab54dc0a30bd6 Mon Sep 17 00:00:00 2001 From: Oliver Schuster Date: Wed, 5 Mar 2008 16:48:45 +0100 Subject: [PATCH 3678/5416] [WATCHDOG] add watchdog driver IT8716 IT8726 IT8712J/K Add it87xx watchdog driver IT8716 IT8718 IT8726 IT8712-J IT8712-K Signed-off-by: Oliver Schuster Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 12 + drivers/watchdog/Makefile | 1 + drivers/watchdog/it87_wdt.c | 725 ++++++++++++++++++++++++++++++++++++ 3 files changed, 738 insertions(+) create mode 100644 drivers/watchdog/it87_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c5103671670..82e65154e75 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -416,6 +416,18 @@ config IT8712F_WDT To compile this driver as a module, choose M here: the module will be called it8712f_wdt. +config IT87_WDT + tristate "IT87 Watchdog Timer" + depends on X86 && EXPERIMENTAL + ---help--- + This is the driver for the hardware watchdog on the ITE IT8716, + IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog + simply watches your kernel to make sure it doesn't freeze, and if + it does, it reboots your computer after a certain amount of time. + + To compile this driver as a module, choose M here: the module will + be called it87_wdt. + config HP_WATCHDOG tristate "HP Proliant iLO 2 Hardware Watchdog Timer" depends on X86 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e0ef123fbde..e2e4bcf0a56 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -71,6 +71,7 @@ ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o endif obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o +obj-$(CONFIG_IT87_WDT) += it87_wdt.o obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c new file mode 100644 index 00000000000..afb8af397a9 --- /dev/null +++ b/drivers/watchdog/it87_wdt.c @@ -0,0 +1,725 @@ +/* + * Watchdog Timer Driver + * for ITE IT87xx Environment Control - Low Pin Count Input / Output + * + * (c) Copyright 2007 Oliver Schuster + * + * Based on softdog.c by Alan Cox, + * 83977f_wdt.c by Jose Goncalves, + * it87.c by Chris Gauthron, Jean Delvare + * + * Data-sheets: Publicly available at the ITE website + * http://www.ite.com.tw/ + * + * Support of the watchdog timers, which are available on + * IT8716, IT8718, IT8726 and IT8712 (J,K version). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 + +#define WATCHDOG_VERSION "1.12" +#define WATCHDOG_NAME "IT87 WDT" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" +#define WD_MAGIC 'V' + +/* Defaults for Module Parameter */ +#define DEFAULT_NOGAMEPORT 0 +#define DEFAULT_EXCLUSIVE 1 +#define DEFAULT_TIMEOUT 60 +#define DEFAULT_TESTMODE 0 +#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT + +/* IO Ports */ +#define REG 0x2e +#define VAL 0x2f + +/* Logical device Numbers LDN */ +#define GPIO 0x07 +#define GAMEPORT 0x09 +#define CIR 0x0a + +/* Configuration Registers and Functions */ +#define LDNREG 0x07 +#define CHIPID 0x20 +#define CHIPREV 0x22 +#define ACTREG 0x30 +#define BASEREG 0x60 + +/* Chip Id numbers */ +#define NO_DEV_ID 0xffff +#define IT8705_ID 0x8705 +#define IT8712_ID 0x8712 +#define IT8716_ID 0x8716 +#define IT8718_ID 0x8718 +#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ + +/* GPIO Configuration Registers LDN=0x07 */ +#define WDTCTRL 0x71 +#define WDTCFG 0x72 +#define WDTVALLSB 0x73 +#define WDTVALMSB 0x74 + +/* GPIO Bits WDTCTRL */ +#define WDT_CIRINT 0x80 +#define WDT_MOUSEINT 0x40 +#define WDT_KYBINT 0x20 +#define WDT_GAMEPORT 0x10 /* not it8718 */ +#define WDT_FORCE 0x02 +#define WDT_ZERO 0x01 + +/* GPIO Bits WDTCFG */ +#define WDT_TOV1 0x80 +#define WDT_KRST 0x40 +#define WDT_TOVE 0x20 +#define WDT_PWROK 0x10 +#define WDT_INT_MASK 0x0f + +/* CIR Configuration Register LDN=0x0a */ +#define CIR_ILS 0x70 + +/* The default Base address is not always available, we use this */ +#define CIR_BASE 0x0208 + +/* CIR Controller */ +#define CIR_DR(b) (b) +#define CIR_IER(b) (b + 1) +#define CIR_RCR(b) (b + 2) +#define CIR_TCR1(b) (b + 3) +#define CIR_TCR2(b) (b + 4) +#define CIR_TSR(b) (b + 5) +#define CIR_RSR(b) (b + 6) +#define CIR_BDLR(b) (b + 5) +#define CIR_BDHR(b) (b + 6) +#define CIR_IIR(b) (b + 7) + +/* Default Base address of Game port */ +#define GP_BASE_DEFAULT 0x0201 + +/* wdt_status */ +#define WDTS_TIMER_RUN 0 +#define WDTS_DEV_OPEN 1 +#define WDTS_KEEPALIVE 2 +#define WDTS_LOCKED 3 +#define WDTS_USE_GP 4 +#define WDTS_EXPECTED 5 + +static unsigned int base, gpact, ciract; +static unsigned long wdt_status; +static DEFINE_SPINLOCK(spinlock); + +static int nogameport = DEFAULT_NOGAMEPORT; +static int exclusive = DEFAULT_EXCLUSIVE; +static int timeout = DEFAULT_TIMEOUT; +static int testmode = DEFAULT_TESTMODE; +static int nowayout = DEFAULT_NOWAYOUT; + +module_param(nogameport, int, 0); +MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default=" + __MODULE_STRING(DEFAULT_NOGAMEPORT)); +module_param(exclusive, int, 0); +MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default=" + __MODULE_STRING(DEFAULT_EXCLUSIVE)); +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default=" + __MODULE_STRING(DEFAULT_TIMEOUT)); +module_param(testmode, int, 0); +MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default=" + __MODULE_STRING(DEFAULT_TESTMODE)); +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT)); + +/* Superio Chip */ + +static inline void superio_enter(void) +{ + outb(0x87, REG); + outb(0x01, REG); + outb(0x55, REG); + outb(0x55, REG); +} + +static inline void superio_exit(void) +{ + outb(0x02, REG); + outb(0x02, VAL); +} + +static inline void superio_select(int ldn) +{ + outb(LDNREG, REG); + outb(ldn, VAL); +} + +static inline int superio_inb(int reg) +{ + outb(reg, REG); + return inb(VAL); +} + +static inline void superio_outb(int val, int reg) +{ + outb(reg, REG); + outb(val, VAL); +} + +static inline int superio_inw(int reg) +{ + int val; + outb(reg++, REG); + val = inb(VAL) << 8; + outb(reg, REG); + val |= inb(VAL); + return val; +} + +static inline void superio_outw(int val, int reg) +{ + outb(reg++, REG); + outb(val >> 8, VAL); + outb(reg, REG); + outb(val, VAL); +} + +/* watchdog timer handling */ + +static void wdt_keepalive(void) +{ + if (test_bit(WDTS_USE_GP, &wdt_status)) + inb(base); + else + /* The timer reloads with around 5 msec delay */ + outb(0x55, CIR_DR(base)); + set_bit(WDTS_KEEPALIVE, &wdt_status); +} + +static void wdt_start(void) +{ + unsigned long flags; + + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + + superio_select(GPIO); + if (test_bit(WDTS_USE_GP, &wdt_status)) + superio_outb(WDT_GAMEPORT, WDTCTRL); + else + superio_outb(WDT_CIRINT, WDTCTRL); + if (!testmode) + superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG); + else + superio_outb(WDT_TOV1, WDTCFG); + superio_outb(timeout>>8, WDTVALMSB); + superio_outb(timeout, WDTVALLSB); + + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); +} + +static void wdt_stop(void) +{ + unsigned long flags; + + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + + superio_select(GPIO); + superio_outb(0x00, WDTCTRL); + superio_outb(WDT_TOV1, WDTCFG); + superio_outb(0x00, WDTVALMSB); + superio_outb(0x00, WDTVALLSB); + + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); +} + +/** + * wdt_set_timeout - set a new timeout value with watchdog ioctl + * @t: timeout value in seconds + * + * The hardware device has a 16 bit watchdog timer, thus the + * timeout time ranges between 1 and 65535 seconds. + * + * Used within WDIOC_SETTIMEOUT watchdog device ioctl. + */ + +static int wdt_set_timeout(int t) +{ + unsigned long flags; + + if (t < 1 || t > 65535) + return -EINVAL; + + timeout = t; + + spin_lock_irqsave(&spinlock, flags); + if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { + superio_enter(); + + superio_select(GPIO); + superio_outb(t>>8, WDTVALMSB); + superio_outb(t, WDTVALLSB); + + superio_exit(); + } + spin_unlock_irqrestore(&spinlock, flags); + return 0; +} + +/** + * wdt_get_status - determines the status supported by watchdog ioctl + * @status: status returned to user space + * + * The status bit of the device does not allow to distinguish + * between a regular system reset and a watchdog forced reset. + * But, in test mode it is useful, so it is supported through + * WDIOC_GETSTATUS watchdog ioctl. Additionally the driver + * reports the keepalive signal and the acception of the magic. + * + * Used within WDIOC_GETSTATUS watchdog device ioctl. + */ + +static int wdt_get_status(int *status) +{ + unsigned long flags; + + *status = 0; + if (testmode) { + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + superio_select(GPIO); + if (superio_inb(WDTCTRL) & WDT_ZERO) { + superio_outb(0x00, WDTCTRL); + clear_bit(WDTS_TIMER_RUN, &wdt_status); + *status |= WDIOF_CARDRESET; + } + + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + } + if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status)) + *status |= WDIOF_KEEPALIVEPING; + if (test_bit(WDTS_EXPECTED, &wdt_status)) + *status |= WDIOF_MAGICCLOSE; + return 0; +} + +/* /dev/watchdog handling */ + +/** + * wdt_open - watchdog file_operations .open + * @inode: inode of the device + * @file: file handle to the device + * + * The watchdog timer starts by opening the device. + * + * Used within the file operation of the watchdog device. + */ + +static int wdt_open(struct inode *inode, struct file *file) +{ + if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status)) + return -EBUSY; + if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { + if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status)) + __module_get(THIS_MODULE); + wdt_start(); + } + return nonseekable_open(inode, file); +} + +/** + * wdt_release - watchdog file_operations .release + * @inode: inode of the device + * @file: file handle to the device + * + * Closing the watchdog device either stops the watchdog timer + * or in the case, that nowayout is set or the magic character + * wasn't written, a critical warning about an running watchdog + * timer is given. + * + * Used within the file operation of the watchdog device. + */ + +static int wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { + if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) { + wdt_stop(); + clear_bit(WDTS_TIMER_RUN, &wdt_status); + } else { + wdt_keepalive(); + printk(KERN_CRIT PFX + "unexpected close, not stopping watchdog!\n"); + } + } + clear_bit(WDTS_DEV_OPEN, &wdt_status); + return 0; +} + +/** + * wdt_write - watchdog file_operations .write + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we don't define content meaning. + * + * Used within the file operation of the watchdog device. + */ + +static ssize_t wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + clear_bit(WDTS_EXPECTED, &wdt_status); + wdt_keepalive(); + } + if (!nowayout) { + size_t ofs; + + /* note: just in case someone wrote the magic character long ago */ + for (ofs = 0; ofs != count; ofs++) { + char c; + if (get_user(c, buf + ofs)) + return -EFAULT; + if (c == WD_MAGIC) + set_bit(WDTS_EXPECTED, &wdt_status); + } + } + return count; +} + +static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = WATCHDOG_NAME, +}; + +/** + * wdt_ioctl - watchdog file_operations .unlocked_ioctl + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + * + * Used within the file operation of the watchdog device. + */ + +static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int rc = 0, status, new_options, new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, + &ident, sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + wdt_get_status(&status); + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_KEEPALIVE: + wdt_keepalive(); + return 0; + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + switch (new_options) { + case WDIOS_DISABLECARD: + if (test_bit(WDTS_TIMER_RUN, &wdt_status)) + wdt_stop(); + clear_bit(WDTS_TIMER_RUN, &wdt_status); + return 0; + + case WDIOS_ENABLECARD: + if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) + wdt_start(); + return 0; + + default: + return -EFAULT; + } + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + rc = wdt_set_timeout(new_timeout); + case WDIOC_GETTIMEOUT: + if (put_user(timeout, uarg.i)) + return -EFAULT; + return rc; + + default: + return -ENOTTY; + } +} + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + wdt_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .unlocked_ioctl = wdt_ioctl, + .open = wdt_open, + .release = wdt_release, +}; + +static struct miscdevice wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + +static int __init it87_wdt_init(void) +{ + int rc = 0; + u16 chip_type; + u8 chip_rev; + unsigned long flags; + + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + chip_type = superio_inw(CHIPID); + chip_rev = superio_inb(CHIPREV) & 0x0f; + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + + switch (chip_type) { + case IT8716_ID: + case IT8718_ID: + case IT8726_ID: + break; + case IT8712_ID: + if (chip_rev > 7) + break; + case IT8705_ID: + printk(KERN_ERR PFX + "Unsupported Chip found, Chip %04x Revision %02x\n", + chip_type, chip_rev); + return -ENODEV; + case NO_DEV_ID: + printk(KERN_ERR PFX "no device\n"); + return -ENODEV; + default: + printk(KERN_ERR PFX + "Unknown Chip found, Chip %04x Revision %04x\n", + chip_type, chip_rev); + return -ENODEV; + } + + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + + superio_select(GPIO); + superio_outb(WDT_TOV1, WDTCFG); + superio_outb(0x00, WDTCTRL); + + /* First try to get Gameport support */ + if (chip_type != IT8718_ID && !nogameport) { + superio_select(GAMEPORT); + base = superio_inw(BASEREG); + if (!base) { + base = GP_BASE_DEFAULT; + superio_outw(base, BASEREG); + } + gpact = superio_inb(ACTREG); + superio_outb(0x01, ACTREG); + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + if (request_region(base, 1, WATCHDOG_NAME)) + set_bit(WDTS_USE_GP, &wdt_status); + else + rc = -EIO; + } else { + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + } + + /* If we haven't Gameport support, try to get CIR support */ + if (!test_bit(WDTS_USE_GP, &wdt_status)) { + if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) { + if (rc == -EIO) + printk(KERN_ERR PFX + "I/O Address 0x%04x and 0x%04x" + " already in use\n", base, CIR_BASE); + else + printk(KERN_ERR PFX + "I/O Address 0x%04x already in use\n", + CIR_BASE); + rc = -EIO; + goto err_out; + } + base = CIR_BASE; + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + + superio_select(CIR); + superio_outw(base, BASEREG); + superio_outb(0x00, CIR_ILS); + ciract = superio_inb(ACTREG); + superio_outb(0x01, ACTREG); + if (rc == -EIO) { + superio_select(GAMEPORT); + superio_outb(gpact, ACTREG); + } + + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + } + + if (timeout < 1 || timeout > 65535) { + timeout = DEFAULT_TIMEOUT; + printk(KERN_WARNING PFX + "Timeout value out of range, use default %d sec\n", + DEFAULT_TIMEOUT); + } + + rc = register_reboot_notifier(&wdt_notifier); + if (rc) { + printk(KERN_ERR PFX + "Cannot register reboot notifier (err=%d)\n", rc); + goto err_out_region; + } + + rc = misc_register(&wdt_miscdev); + if (rc) { + printk(KERN_ERR PFX + "Cannot register miscdev on minor=%d (err=%d)\n", + wdt_miscdev.minor, rc); + goto err_out_reboot; + } + + /* Initialize CIR to use it as keepalive source */ + if (!test_bit(WDTS_USE_GP, &wdt_status)) { + outb(0x00, CIR_RCR(base)); + outb(0xc0, CIR_TCR1(base)); + outb(0x5c, CIR_TCR2(base)); + outb(0x10, CIR_IER(base)); + outb(0x00, CIR_BDHR(base)); + outb(0x01, CIR_BDLR(base)); + outb(0x09, CIR_IER(base)); + } + + printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " + "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " + "nogameport=%d)\n", chip_type, chip_rev, timeout, + nowayout, testmode, exclusive, nogameport); + + return 0; + +err_out_reboot: + unregister_reboot_notifier(&wdt_notifier); +err_out_region: + release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); + if (!test_bit(WDTS_USE_GP, &wdt_status)) { + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + superio_select(CIR); + superio_outb(ciract, ACTREG); + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + } +err_out: + if (chip_type != IT8718_ID && !nogameport) { + spin_lock_irqsave(&spinlock, flags); + superio_enter(); + superio_select(GAMEPORT); + superio_outb(gpact, ACTREG); + superio_exit(); + spin_unlock_irqrestore(&spinlock, flags); + } + + return rc; +} + +static void __exit it87_wdt_exit(void) +{ + unsigned long flags; + int nolock; + + nolock = !spin_trylock_irqsave(&spinlock, flags); + superio_enter(); + superio_select(GPIO); + superio_outb(0x00, WDTCTRL); + superio_outb(0x00, WDTCFG); + superio_outb(0x00, WDTVALMSB); + superio_outb(0x00, WDTVALLSB); + if (test_bit(WDTS_USE_GP, &wdt_status)) { + superio_select(GAMEPORT); + superio_outb(gpact, ACTREG); + } else { + superio_select(CIR); + superio_outb(ciract, ACTREG); + } + superio_exit(); + if (!nolock) + spin_unlock_irqrestore(&spinlock, flags); + + misc_deregister(&wdt_miscdev); + unregister_reboot_notifier(&wdt_notifier); + release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); +} + +module_init(it87_wdt_init); +module_exit(it87_wdt_exit); + +MODULE_AUTHOR("Oliver Schuster"); +MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From 7d8b09066117e3023e55964ae4626c107f437b60 Mon Sep 17 00:00:00 2001 From: Flemming Frandsen Date: Thu, 17 Apr 2008 11:29:54 +0200 Subject: [PATCH 3679/5416] [WATCHDOG] Add driver for winbond w83697ug/uf watchdog feature Adapted the w83627hf_wdt.c driver to work with the w83697ug/uf chip, found on MSI Fuzzy CX700 boards. The method used is taken directly from the winbond datasheet and surprisingly it differs slightly from all the other winbond watchdogs. So far it has only been tested on the CX700 board that I have, but it seems to work nicely. Signed-off-by: Flemming Frandsen Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 15 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/w83697ug_wdt.c | 392 ++++++++++++++++++++++++++++++++ 3 files changed, 408 insertions(+) create mode 100644 drivers/watchdog/w83697ug_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 82e65154e75..37dc27c4ecd 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -585,6 +585,21 @@ config W83697HF_WDT Most people will say N. +config W83697UG_WDT + tristate "W83697UG/W83697UF Watchdog Timer" + depends on X86 + ---help--- + This is the driver for the hardware watchdog on the W83697UG/UF + chipset as used in MSI Fuzzy CX700 VIA motherboards (and likely others). + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. + + To compile this driver as a module, choose M here: the + module will be called w83697ug_wdt. + + Most people will say N. + config W83877F_WDT tristate "W83877F (EMACS) Watchdog Timer" depends on X86 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e2e4bcf0a56..6f018e5b3dd 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o +obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c new file mode 100644 index 00000000000..c73b5e2919c --- /dev/null +++ b/drivers/watchdog/w83697ug_wdt.c @@ -0,0 +1,392 @@ +/* + * w83697ug/uf WDT driver + * + * (c) Copyright 2008 Flemming Fransen + * reused original code to supoprt w83697ug/uf. + * + * Based on w83627hf_wdt.c which is based on advantechwdt.c + * which is based on wdt.c. + * Original copyright messages: + * + * (c) Copyright 2007 Vlad Drukker + * added support for W83627THF. + * + * (c) Copyright 2003 Pádraig Brady + * + * (c) Copyright 2000-2001 Marek Michalkiewicz + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define WATCHDOG_NAME "w83697ug/uf WDT" +#define PFX WATCHDOG_NAME ": " +#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ + +static unsigned long wdt_is_open; +static char expect_close; +static DEFINE_SPINLOCK(io_lock); + +static int wdt_io = 0x2e; +module_param(wdt_io, int, 0); +MODULE_PARM_DESC(wdt_io, "w83697ug/uf WDT io port (default 0x2e)"); + +static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=255 (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* + * Kernel methods. + */ + +#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ +#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register + (same as EFER) */ +#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ + +static void w83697ug_select_wd_register(void) +{ + unsigned char c; + unsigned char version; + + outb_p(0x87, WDT_EFER); /* Enter extended function mode */ + outb_p(0x87, WDT_EFER); /* Again according to manual */ + + outb(0x20, WDT_EFER); /* check chip version */ + version = inb(WDT_EFDR); + + if (version == 0x68) { /* W83697UG */ + printk(KERN_INFO PFX "Watchdog chip version 0x%02x = " + "W83697UG/UF found at 0x%04x\n", version, wdt_io); + + outb_p(0x2b, WDT_EFER); + c = inb_p(WDT_EFDR); /* select WDT0 */ + c &= ~0x04; + outb_p(0x2b, WDT_EFER); + outb_p(c, WDT_EFDR); /* set pin118 to WDT0 */ + + } else { + printk(KERN_ERR PFX "No W83697UG/UF could be found\n"); + return -EIO; + } + + outb_p(0x07, WDT_EFER); /* point to logical device number reg */ + outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ + outb_p(0x30, WDT_EFER); /* select CR30 */ + c = inb_p(WDT_EFDR); + outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ +} + +static void w83697ug_unselect_wd_register(void) +{ + outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ +} + +static void w83697ug_init(void) +{ + unsigned char t; + + w83697ug_select_wd_register(); + + outb_p(0xF6, WDT_EFER); /* Select CRF6 */ + t = inb_p(WDT_EFDR); /* read CRF6 */ + if (t != 0) { + printk(KERN_INFO PFX "Watchdog already running." + " Resetting timeout to %d sec\n", timeout); + outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ + } + outb_p(0xF5, WDT_EFER); /* Select CRF5 */ + t = inb_p(WDT_EFDR); /* read CRF5 */ + t &= ~0x0C; /* set second mode & + disable keyboard turning off watchdog */ + outb_p(t, WDT_EFDR); /* Write back to CRF5 */ + + w83697ug_unselect_wd_register(); +} + +static void wdt_ctrl(int timeout) +{ + spin_lock(&io_lock); + + w83697ug_select_wd_register(); + + outb_p(0xF4, WDT_EFER); /* Select CRF4 */ + outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ + + w83697ug_unselect_wd_register(); + + spin_unlock(&io_lock); +} + +static int wdt_ping(void) +{ + wdt_ctrl(timeout); + return 0; +} + +static int wdt_disable(void) +{ + wdt_ctrl(0); + return 0; +} + +static int wdt_set_heartbeat(int t) +{ + if (t < 1 || t > 255) + return -EINVAL; + + timeout = t; + return 0; +} + +static ssize_t wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + expect_close = 0; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + wdt_ping(); + } + return count; +} + +static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_timeout; + static const struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "W83697UG WDT", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + wdt_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + wdt_ping(); + retval = 0; + } + + return retval; + } + + case WDIOC_KEEPALIVE: + wdt_ping(); + break; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, p)) + return -EFAULT; + if (wdt_set_heartbeat(new_timeout)) + return -EINVAL; + wdt_ping(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + default: + return -ENOTTY; + } + return 0; +} + +static int wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &wdt_is_open)) + return -EBUSY; + /* + * Activate + */ + + wdt_ping(); + return nonseekable_open(inode, file); +} + +static int wdt_close(struct inode *inode, struct file *file) +{ + if (expect_close == 42) + wdt_disable(); + else { + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); + wdt_ping(); + } + expect_close = 0; + clear_bit(0, &wdt_is_open); + return 0; +} + +/* + * Notifier for system down + */ + +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + wdt_disable(); /* Turn the WDT off */ + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .unlocked_ioctl = wdt_ioctl, + .open = wdt_open, + .release = wdt_close, +}; + +static struct miscdevice wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + +static int __init wdt_init(void) +{ + int ret; + + printk(KERN_INFO "WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising.\n"); + + if (wdt_set_heartbeat(timeout)) { + wdt_set_heartbeat(WATCHDOG_TIMEOUT); + printk(KERN_INFO PFX + "timeout value must be 1<=timeout<=255, using %d\n", + WATCHDOG_TIMEOUT); + } + + if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + wdt_io); + ret = -EIO; + goto out; + } + + w83697ug_init(); + + ret = register_reboot_notifier(&wdt_notifier); + if (ret != 0) { + printk(KERN_ERR PFX + "cannot register reboot notifier (err=%d)\n", ret); + goto unreg_regions; + } + + ret = misc_register(&wdt_miscdev); + if (ret != 0) { + printk(KERN_ERR PFX + "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto unreg_reboot; + } + + printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", + timeout, nowayout); + +out: + return ret; +unreg_reboot: + unregister_reboot_notifier(&wdt_notifier); +unreg_regions: + release_region(wdt_io, 1); + goto out; +} + +static void __exit wdt_exit(void) +{ + misc_deregister(&wdt_miscdev); + unregister_reboot_notifier(&wdt_notifier); + release_region(wdt_io, 1); +} + +module_init(wdt_init); +module_exit(wdt_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Flemming Frandsen "); +MODULE_DESCRIPTION("w83697ug/uf WDT driver"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From e6bb42e3d669afbeb4c971994614bcf241687666 Mon Sep 17 00:00:00 2001 From: Renaud CERRATO Date: Mon, 23 Jun 2008 17:05:49 +0200 Subject: [PATCH 3680/5416] [WATCHDOG] Add AT91SAM9X watchdog Add a driver for the watchdog timer embedded into AT91SAM9X chips. Signed-off-by: Renaud Cerrato Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 7 + drivers/watchdog/Makefile | 1 + drivers/watchdog/at91sam9_wdt.c | 328 ++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/watchdog/at91sam9_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37dc27c4ecd..6a711eb6998 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -66,6 +66,13 @@ config AT91RM9200_WATCHDOG Watchdog timer embedded into AT91RM9200 chips. This will reboot your system when the timeout is reached. +config AT91SAM9X_WATCHDOG + tristate "AT91SAM9X watchdog" + depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261) + help + Watchdog timer embedded into AT91SAM9X chips. This will reboot your + system when the timeout is reached. + config 21285_WATCHDOG tristate "DC21285 watchdog" depends on FOOTBRIDGE diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 6f018e5b3dd..f896d6f666b 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o # ARM Architecture obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o +obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c new file mode 100644 index 00000000000..b4babfc3158 --- /dev/null +++ b/drivers/watchdog/at91sam9_wdt.c @@ -0,0 +1,328 @@ +/* + * Watchdog driver for Atmel AT91SAM9x processors. + * + * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr + * + * 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. + */ + +/* + * The Watchdog Timer Mode Register can be only written to once. If the + * timeout need to be set from Linux, be sure that the bootstrap or the + * bootloader doesn't write to this register. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "AT91SAM9 Watchdog" + +/* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, + * use this to convert a watchdog + * value from/to milliseconds. + */ +#define ms_to_ticks(t) (((t << 8) / 1000) - 1) +#define ticks_to_ms(t) (((t + 1) * 1000) >> 8) + +/* Hardware timeout in seconds */ +#define WDT_HW_TIMEOUT 2 + +/* Timer heartbeat (500ms) */ +#define WDT_TIMEOUT (HZ/2) + +/* User land timeout */ +#define WDT_HEARTBEAT 15 +static int heartbeat = WDT_HEARTBEAT; +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. " + "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static void at91_ping(unsigned long data); + +static struct { + unsigned long next_heartbeat; /* the next_heartbeat for the timer */ + unsigned long open; + char expect_close; + struct timer_list timer; /* The timer that pings the watchdog */ +} at91wdt_private; + +/* ......................................................................... */ + + +/* + * Reload the watchdog timer. (ie, pat the watchdog) + */ +static inline void at91_wdt_reset(void) +{ + at91_sys_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); +} + +/* + * Timer tick + */ +static void at91_ping(unsigned long data) +{ + if (time_before(jiffies, at91wdt_private.next_heartbeat) || + (!nowayout && !at91wdt_private.open)) { + at91_wdt_reset(); + mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); + } else + printk(KERN_CRIT DRV_NAME": I will reset your machine !\n"); +} + +/* + * Watchdog device is opened, and watchdog starts running. + */ +static int at91_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &at91wdt_private.open)) + return -EBUSY; + + at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; + mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); + + return nonseekable_open(inode, file); +} + +/* + * Close the watchdog device. + */ +static int at91_wdt_close(struct inode *inode, struct file *file) +{ + clear_bit(0, &at91wdt_private.open); + + /* stop internal ping */ + if (!at91wdt_private.expect_close) + del_timer(&at91wdt_private.timer); + + at91wdt_private.expect_close = 0; + return 0; +} + +/* + * Set the watchdog time interval in 1/256Hz (write-once) + * Counter is 12 bit. + */ +static int at91_wdt_settimeout(unsigned int timeout) +{ + unsigned int reg; + unsigned int mr; + + /* Check if disabled */ + mr = at91_sys_read(AT91_WDT_MR); + if (mr & AT91_WDT_WDDIS) { + printk(KERN_ERR DRV_NAME": sorry, watchdog is disabled\n"); + return -EIO; + } + + /* + * All counting occurs at SLOW_CLOCK / 128 = 256 Hz + * + * Since WDV is a 12-bit counter, the maximum period is + * 4096 / 256 = 16 seconds. + */ + reg = AT91_WDT_WDRSTEN /* causes watchdog reset */ + /* | AT91_WDT_WDRPROC causes processor reset only */ + | AT91_WDT_WDDBGHLT /* disabled in debug mode */ + | AT91_WDT_WDD /* restart at any time */ + | (timeout & AT91_WDT_WDV); /* timer value */ + at91_sys_write(AT91_WDT_MR, reg); + + return 0; +} + +static const struct watchdog_info at91_wdt_info = { + .identity = DRV_NAME, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +}; + +/* + * Handle commands from user-space. + */ +static long at91_wdt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_value; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &at91_wdt_info, + sizeof(at91_wdt_info)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_KEEPALIVE: + at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_value, p)) + return -EFAULT; + + heartbeat = new_value; + at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; + + return put_user(new_value, p); /* return current value */ + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + } + return -ENOTTY; +} + +/* + * Pat the watchdog whenever device is written to. + */ +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, + loff_t *ppos) +{ + if (!len) + return 0; + + /* Scan for magic character */ + if (!nowayout) { + size_t i; + + at91wdt_private.expect_close = 0; + + for (i = 0; i < len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') { + at91wdt_private.expect_close = 42; + break; + } + } + } + + at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; + + return len; +} + +/* ......................................................................... */ + +static const struct file_operations at91wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .unlocked_ioctl = at91_wdt_ioctl, + .open = at91_wdt_open, + .release = at91_wdt_close, + .write = at91_wdt_write, +}; + +static struct miscdevice at91wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &at91wdt_fops, +}; + +static int __init at91wdt_probe(struct platform_device *pdev) +{ + int res; + + if (at91wdt_miscdev.parent) + return -EBUSY; + at91wdt_miscdev.parent = &pdev->dev; + + /* Set watchdog */ + res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); + if (res) + return res; + + res = misc_register(&at91wdt_miscdev); + if (res) + return res; + + at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; + setup_timer(&at91wdt_private.timer, at91_ping, 0); + mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); + + printk(KERN_INFO DRV_NAME " enabled (heartbeat=%d sec, nowayout=%d)\n", + heartbeat, nowayout); + + return 0; +} + +static int __exit at91wdt_remove(struct platform_device *pdev) +{ + int res; + + res = misc_deregister(&at91wdt_miscdev); + if (!res) + at91wdt_miscdev.parent = NULL; + + return res; +} + +#ifdef CONFIG_PM + +static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) +{ + return 0; +} + +static int at91wdt_resume(struct platform_device *pdev) +{ + return 0; +} + +#else +#define at91wdt_suspend NULL +#define at91wdt_resume NULL +#endif + +static struct platform_driver at91wdt_driver = { + .remove = __exit_p(at91wdt_remove), + .suspend = at91wdt_suspend, + .resume = at91wdt_resume, + .driver = { + .name = "at91_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init at91sam_wdt_init(void) +{ + return platform_driver_probe(&at91wdt_driver, at91wdt_probe); +} + +static void __exit at91sam_wdt_exit(void) +{ + platform_driver_unregister(&at91wdt_driver); +} + +module_init(at91sam_wdt_init); +module_exit(at91sam_wdt_exit); + +MODULE_AUTHOR("Renaud CERRATO "); +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From 2817142f31bfbf26c216bf4f9192540c81b2d071 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 20 Sep 2008 04:14:01 +0300 Subject: [PATCH 3681/5416] [WATCHDOG] omap_wdt.c: sync linux-omap changes These are changes that have been sitting in linux-omap and were never sent upstream. Hopefully, it'll never happen again at least for this driver. Signed-off-by: Felipe Balbi Signed-off-by: Wim Van Sebroeck --- arch/arm/plat-omap/devices.c | 21 ++- drivers/watchdog/omap_wdt.c | 283 ++++++++++++++++++++++------------- drivers/watchdog/omap_wdt.h | 28 ++-- 3 files changed, 203 insertions(+), 129 deletions(-) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 01da719a745..cc62cec1b75 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -441,16 +441,8 @@ static inline void omap_init_uwire(void) {} #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) -#ifdef CONFIG_ARCH_OMAP24XX -#define OMAP_WDT_BASE 0x48022000 -#else -#define OMAP_WDT_BASE 0xfffeb000 -#endif - static struct resource wdt_resources[] = { { - .start = OMAP_WDT_BASE, - .end = OMAP_WDT_BASE + 0x4f, .flags = IORESOURCE_MEM, }, }; @@ -464,6 +456,19 @@ static struct platform_device omap_wdt_device = { static void omap_init_wdt(void) { + if (cpu_is_omap16xx()) + wdt_resources[0].start = 0xfffeb000; + else if (cpu_is_omap2420()) + wdt_resources[0].start = 0x48022000; /* WDT2 */ + else if (cpu_is_omap2430()) + wdt_resources[0].start = 0x49016000; /* WDT2 */ + else if (cpu_is_omap343x()) + wdt_resources[0].start = 0x48314000; /* WDT2 */ + else + return; + + wdt_resources[0].end = wdt_resources[0].start + 0x4f; + (void) platform_device_register(&omap_wdt_device); } #else diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3a11dadfd8e..7de16a3f684 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -1,7 +1,7 @@ /* - * linux/drivers/char/watchdog/omap_wdt.c + * omap_wdt.c * - * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog + * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog * * Author: MontaVista Software, Inc. * or @@ -47,50 +47,63 @@ #include "omap_wdt.h" +static struct platform_device *omap_wdt_dev; + static unsigned timer_margin; module_param(timer_margin, uint, 0); MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); -static int omap_wdt_users; -static struct clk *armwdt_ck; -static struct clk *mpu_wdt_ick; -static struct clk *mpu_wdt_fck; - static unsigned int wdt_trgr_pattern = 0x1234; static spinlock_t wdt_lock; -static void omap_wdt_ping(void) +struct omap_wdt_dev { + void __iomem *base; /* physical */ + struct device *dev; + int omap_wdt_users; + struct clk *armwdt_ck; + struct clk *mpu_wdt_ick; + struct clk *mpu_wdt_fck; + struct resource *mem; + struct miscdevice omap_wdt_miscdev; +}; + +static void omap_wdt_ping(struct omap_wdt_dev *wdev) { + void __iomem *base = wdev->base; /* wait for posted write to complete */ - while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) + while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); wdt_trgr_pattern = ~wdt_trgr_pattern; - omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR)); + omap_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); /* wait for posted write to complete */ - while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) + while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); /* reloaded WCRR from WLDR */ } -static void omap_wdt_enable(void) +static void omap_wdt_enable(struct omap_wdt_dev *wdev) { + void __iomem *base; + base = wdev->base; /* Sequence to enable the watchdog */ - omap_writel(0xBBBB, OMAP_WATCHDOG_SPR); - while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) + omap_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); + while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); - omap_writel(0x4444, OMAP_WATCHDOG_SPR); - while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) + omap_writel(0x4444, base + OMAP_WATCHDOG_SPR); + while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); } -static void omap_wdt_disable(void) +static void omap_wdt_disable(struct omap_wdt_dev *wdev) { + void __iomem *base; + base = wdev->base; /* sequence required to disable watchdog */ - omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) + omap_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); - omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) + omap_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); } @@ -103,15 +116,17 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout) timer_margin = new_timeout; } -static void omap_wdt_set_timeout(void) +static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) { u32 pre_margin = GET_WLDR_VAL(timer_margin); + void __iomem *base; + base = wdev->base; /* just count up at 32 KHz */ - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); - omap_writel(pre_margin, OMAP_WATCHDOG_LDR); - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) + omap_writel(pre_margin, base + OMAP_WATCHDOG_LDR); + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); } @@ -121,65 +136,69 @@ static void omap_wdt_set_timeout(void) static int omap_wdt_open(struct inode *inode, struct file *file) { - if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users)) + struct omap_wdt_dev *wdev; + void __iomem *base; + wdev = platform_get_drvdata(omap_wdt_dev); + base = wdev->base; + if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) return -EBUSY; if (cpu_is_omap16xx()) - clk_enable(armwdt_ck); /* Enable the clock */ + clk_enable(wdev->armwdt_ck); /* Enable the clock */ - if (cpu_is_omap24xx()) { - clk_enable(mpu_wdt_ick); /* Enable the interface clock */ - clk_enable(mpu_wdt_fck); /* Enable the functional clock */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + clk_enable(wdev->mpu_wdt_ick); /* Enable the interface clock */ + clk_enable(wdev->mpu_wdt_fck); /* Enable the functional clock */ } /* initialize prescaler */ - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); - omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL); - while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) + omap_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); + while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); - omap_wdt_set_timeout(); - omap_wdt_enable(); + file->private_data = (void *) wdev; + + omap_wdt_set_timeout(wdev); + omap_wdt_enable(wdev); return nonseekable_open(inode, file); } static int omap_wdt_release(struct inode *inode, struct file *file) { + struct omap_wdt_dev *wdev; + wdev = file->private_data; /* * Shut off the timer unless NOWAYOUT is defined. */ #ifndef CONFIG_WATCHDOG_NOWAYOUT - omap_wdt_disable(); - if (cpu_is_omap16xx()) { - clk_disable(armwdt_ck); /* Disable the clock */ - clk_put(armwdt_ck); - armwdt_ck = NULL; - } + omap_wdt_disable(wdev); - if (cpu_is_omap24xx()) { - clk_disable(mpu_wdt_ick); /* Disable the clock */ - clk_disable(mpu_wdt_fck); /* Disable the clock */ - clk_put(mpu_wdt_ick); - clk_put(mpu_wdt_fck); - mpu_wdt_ick = NULL; - mpu_wdt_fck = NULL; + if (cpu_is_omap16xx()) + clk_disable(wdev->armwdt_ck); /* Disable the clock */ + + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + clk_disable(wdev->mpu_wdt_ick); /* Disable the clock */ + clk_disable(wdev->mpu_wdt_fck); /* Disable the clock */ } #else printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); #endif - omap_wdt_users = 0; + wdev->omap_wdt_users = 0; return 0; } static ssize_t omap_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { + struct omap_wdt_dev *wdev; + wdev = file->private_data; /* Refresh LOAD_TIME. */ if (len) { spin_lock(&wdt_lock); - omap_wdt_ping(); + omap_wdt_ping(wdev); spin_unlock(&wdt_lock); } return len; @@ -188,12 +207,14 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, static long omap_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct omap_wdt_dev *wdev; int new_margin; static const struct watchdog_info ident = { .identity = "OMAP Watchdog", .options = WDIOF_SETTIMEOUT, .firmware_version = 0, }; + wdev = file->private_data; switch (cmd) { case WDIOC_GETSUPPORT: @@ -210,7 +231,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, (int __user *)arg); case WDIOC_KEEPALIVE: spin_lock(&wdt_lock); - omap_wdt_ping(); + omap_wdt_ping(wdev); spin_unlock(&wdt_lock); return 0; case WDIOC_SETTIMEOUT: @@ -219,11 +240,11 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_adjust_timeout(new_margin); spin_lock(&wdt_lock); - omap_wdt_disable(); - omap_wdt_set_timeout(); - omap_wdt_enable(); + omap_wdt_disable(wdev); + omap_wdt_set_timeout(wdev); + omap_wdt_enable(wdev); - omap_wdt_ping(); + omap_wdt_ping(wdev); spin_unlock(&wdt_lock); /* Fall */ case WDIOC_GETTIMEOUT: @@ -241,96 +262,150 @@ static const struct file_operations omap_wdt_fops = { .release = omap_wdt_release, }; -static struct miscdevice omap_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &omap_wdt_fops, -}; static int __init omap_wdt_probe(struct platform_device *pdev) { struct resource *res, *mem; int ret; + struct omap_wdt_dev *wdev; /* reserve static register mappings */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENOENT; + if (omap_wdt_dev) + return -EBUSY; + mem = request_mem_region(res->start, res->end - res->start + 1, pdev->name); if (mem == NULL) return -EBUSY; - platform_set_drvdata(pdev, mem); - - omap_wdt_users = 0; + wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); + if (!wdev) { + ret = -ENOMEM; + goto fail; + } + wdev->omap_wdt_users = 0; + wdev->mem = mem; if (cpu_is_omap16xx()) { - armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); - if (IS_ERR(armwdt_ck)) { - ret = PTR_ERR(armwdt_ck); - armwdt_ck = NULL; + wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); + if (IS_ERR(wdev->armwdt_ck)) { + ret = PTR_ERR(wdev->armwdt_ck); + wdev->armwdt_ck = NULL; goto fail; } } if (cpu_is_omap24xx()) { - mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); - if (IS_ERR(mpu_wdt_ick)) { - ret = PTR_ERR(mpu_wdt_ick); - mpu_wdt_ick = NULL; + wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); + if (IS_ERR(wdev->mpu_wdt_ick)) { + ret = PTR_ERR(wdev->mpu_wdt_ick); + wdev->mpu_wdt_ick = NULL; + goto fail; + } + wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); + if (IS_ERR(wdev->mpu_wdt_fck)) { + ret = PTR_ERR(wdev->mpu_wdt_fck); + wdev->mpu_wdt_fck = NULL; + goto fail; + } + } + + if (cpu_is_omap34xx()) { + wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick"); + if (IS_ERR(wdev->mpu_wdt_ick)) { + ret = PTR_ERR(wdev->mpu_wdt_ick); + wdev->mpu_wdt_ick = NULL; goto fail; } - mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); - if (IS_ERR(mpu_wdt_fck)) { - ret = PTR_ERR(mpu_wdt_fck); - mpu_wdt_fck = NULL; + wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); + if (IS_ERR(wdev->mpu_wdt_fck)) { + ret = PTR_ERR(wdev->mpu_wdt_fck); + wdev->mpu_wdt_fck = NULL; goto fail; } } + wdev->base = (void __iomem *) (mem->start); + platform_set_drvdata(pdev, wdev); - omap_wdt_disable(); + omap_wdt_disable(wdev); omap_wdt_adjust_timeout(timer_margin); - omap_wdt_miscdev.parent = &pdev->dev; - ret = misc_register(&omap_wdt_miscdev); + wdev->omap_wdt_miscdev.parent = &pdev->dev; + wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; + wdev->omap_wdt_miscdev.name = "watchdog"; + wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; + + ret = misc_register(&(wdev->omap_wdt_miscdev)); if (ret) goto fail; - pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin); + pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", + omap_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, + timer_margin); /* autogate OCP interface clock */ - omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG); + omap_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); + + omap_wdt_dev = pdev; + return 0; fail: - if (armwdt_ck) - clk_put(armwdt_ck); - if (mpu_wdt_ick) - clk_put(mpu_wdt_ick); - if (mpu_wdt_fck) - clk_put(mpu_wdt_fck); - release_resource(mem); + if (wdev) { + platform_set_drvdata(pdev, NULL); + if (wdev->armwdt_ck) + clk_put(wdev->armwdt_ck); + if (wdev->mpu_wdt_ick) + clk_put(wdev->mpu_wdt_ick); + if (wdev->mpu_wdt_fck) + clk_put(wdev->mpu_wdt_fck); + kfree(wdev); + } + if (mem) { + release_mem_region(res->start, res->end - res->start + 1); + } return ret; } static void omap_wdt_shutdown(struct platform_device *pdev) { - omap_wdt_disable(); + struct omap_wdt_dev *wdev; + wdev = platform_get_drvdata(pdev); + + if (wdev->omap_wdt_users) + omap_wdt_disable(wdev); } static int omap_wdt_remove(struct platform_device *pdev) { - struct resource *mem = platform_get_drvdata(pdev); - misc_deregister(&omap_wdt_miscdev); - release_resource(mem); - if (armwdt_ck) - clk_put(armwdt_ck); - if (mpu_wdt_ick) - clk_put(mpu_wdt_ick); - if (mpu_wdt_fck) - clk_put(mpu_wdt_fck); + struct omap_wdt_dev *wdev; + wdev = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) + return -ENOENT; + + misc_deregister(&(wdev->omap_wdt_miscdev)); + release_mem_region(res->start, res->end - res->start + 1); + platform_set_drvdata(pdev, NULL); + if (wdev->armwdt_ck) { + clk_put(wdev->armwdt_ck); + wdev->armwdt_ck = NULL; + } + if (wdev->mpu_wdt_ick) { + clk_put(wdev->mpu_wdt_ick); + wdev->mpu_wdt_ick = NULL; + } + if (wdev->mpu_wdt_fck) { + clk_put(wdev->mpu_wdt_fck); + wdev->mpu_wdt_fck = NULL; + } + kfree(wdev); + omap_wdt_dev = NULL; return 0; } @@ -344,16 +419,20 @@ static int omap_wdt_remove(struct platform_device *pdev) static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { - if (omap_wdt_users) - omap_wdt_disable(); + struct omap_wdt_dev *wdev; + wdev = platform_get_drvdata(pdev); + if (wdev->omap_wdt_users) + omap_wdt_disable(wdev); return 0; } static int omap_wdt_resume(struct platform_device *pdev) { - if (omap_wdt_users) { - omap_wdt_enable(); - omap_wdt_ping(); + struct omap_wdt_dev *wdev; + wdev = platform_get_drvdata(pdev); + if (wdev->omap_wdt_users) { + omap_wdt_enable(wdev); + omap_wdt_ping(wdev); } return 0; } diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h index 52a532a5114..fc02ec6a038 100644 --- a/drivers/watchdog/omap_wdt.h +++ b/drivers/watchdog/omap_wdt.h @@ -30,25 +30,15 @@ #ifndef _OMAP_WATCHDOG_H #define _OMAP_WATCHDOG_H -#define OMAP1610_WATCHDOG_BASE 0xfffeb000 -#define OMAP2420_WATCHDOG_BASE 0x48022000 /*WDT Timer 2 */ - -#ifdef CONFIG_ARCH_OMAP24XX -#define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE -#else -#define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE -#define RM_RSTST_WKUP 0 -#endif - -#define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00) -#define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10) -#define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14) -#define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24) -#define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28) -#define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c) -#define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30) -#define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34) -#define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48) +#define OMAP_WATCHDOG_REV (0x00) +#define OMAP_WATCHDOG_SYS_CONFIG (0x10) +#define OMAP_WATCHDOG_STATUS (0x14) +#define OMAP_WATCHDOG_CNTRL (0x24) +#define OMAP_WATCHDOG_CRR (0x28) +#define OMAP_WATCHDOG_LDR (0x2c) +#define OMAP_WATCHDOG_TGR (0x30) +#define OMAP_WATCHDOG_WPS (0x34) +#define OMAP_WATCHDOG_SPR (0x48) /* Using the prescaler, the OMAP watchdog could go for many * months before firing. These limits work without scaling, -- GitLab From 9f69e3b0c22200998caa73b23a39c03950b2752d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 20 Sep 2008 04:14:02 +0300 Subject: [PATCH 3682/5416] [WATCHDOG] omap_wdt.c: another ioremap() fix convert to use ioremap() and __raw_{read/write} friends. Signed-off-by: Felipe Balbi Signed-off-by: George G. Davis Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/omap_wdt.c | 50 +++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 7de16a3f684..9c389b16497 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -71,12 +71,12 @@ static void omap_wdt_ping(struct omap_wdt_dev *wdev) { void __iomem *base = wdev->base; /* wait for posted write to complete */ - while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) + while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); wdt_trgr_pattern = ~wdt_trgr_pattern; - omap_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); + __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); /* wait for posted write to complete */ - while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) + while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); /* reloaded WCRR from WLDR */ } @@ -86,11 +86,11 @@ static void omap_wdt_enable(struct omap_wdt_dev *wdev) void __iomem *base; base = wdev->base; /* Sequence to enable the watchdog */ - omap_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); - while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) + __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); + while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); - omap_writel(0x4444, base + OMAP_WATCHDOG_SPR); - while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) + __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); + while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); } @@ -99,11 +99,11 @@ static void omap_wdt_disable(struct omap_wdt_dev *wdev) void __iomem *base; base = wdev->base; /* sequence required to disable watchdog */ - omap_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) + __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); - omap_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) + __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); } @@ -123,10 +123,10 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) base = wdev->base; /* just count up at 32 KHz */ - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); - omap_writel(pre_margin, base + OMAP_WATCHDOG_LDR); - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) + __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); } @@ -152,10 +152,10 @@ static int omap_wdt_open(struct inode *inode, struct file *file) } /* initialize prescaler */ - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); - omap_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); - while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) + __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); file->private_data = (void *) wdev; @@ -224,7 +224,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(0, (int __user *)arg); case WDIOC_GETBOOTSTATUS: if (cpu_is_omap16xx()) - return put_user(omap_readw(ARM_SYSST), + return put_user(__raw_readw(ARM_SYSST), (int __user *)arg); if (cpu_is_omap24xx()) return put_user(omap_prcm_get_reset_sources(), @@ -328,7 +328,12 @@ static int __init omap_wdt_probe(struct platform_device *pdev) goto fail; } } - wdev->base = (void __iomem *) (mem->start); + wdev->base = ioremap(res->start, res->end - res->start + 1); + if (!wdev->base) { + ret = -ENOMEM; + goto fail; + } + platform_set_drvdata(pdev, wdev); omap_wdt_disable(wdev); @@ -344,11 +349,11 @@ static int __init omap_wdt_probe(struct platform_device *pdev) goto fail; pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", - omap_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, + __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, timer_margin); /* autogate OCP interface clock */ - omap_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); + __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); omap_wdt_dev = pdev; @@ -363,6 +368,7 @@ fail: clk_put(wdev->mpu_wdt_ick); if (wdev->mpu_wdt_fck) clk_put(wdev->mpu_wdt_fck); + iounmap(wdev->base); kfree(wdev); } if (mem) { @@ -404,6 +410,8 @@ static int omap_wdt_remove(struct platform_device *pdev) clk_put(wdev->mpu_wdt_fck); wdev->mpu_wdt_fck = NULL; } + iounmap(wdev->base); + kfree(wdev); omap_wdt_dev = NULL; return 0; -- GitLab From b3112180fe0b8dd80053d1d83e6fc421a266e47a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 20 Sep 2008 04:14:03 +0300 Subject: [PATCH 3683/5416] [WATCHDOG] omap_wdt.c: cleanup a bit omap_wdt.c Trivial cleanup patch. Signed-off-by: Felipe Balbi Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/omap_wdt.c | 132 +++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 54 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 9c389b16497..7bcbb7f4745 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -70,11 +70,14 @@ struct omap_wdt_dev { static void omap_wdt_ping(struct omap_wdt_dev *wdev) { void __iomem *base = wdev->base; + /* wait for posted write to complete */ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); + wdt_trgr_pattern = ~wdt_trgr_pattern; __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); + /* wait for posted write to complete */ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) cpu_relax(); @@ -83,12 +86,13 @@ static void omap_wdt_ping(struct omap_wdt_dev *wdev) static void omap_wdt_enable(struct omap_wdt_dev *wdev) { - void __iomem *base; - base = wdev->base; + void __iomem *base = wdev->base; + /* Sequence to enable the watchdog */ __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); + __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) cpu_relax(); @@ -96,12 +100,13 @@ static void omap_wdt_enable(struct omap_wdt_dev *wdev) static void omap_wdt_disable(struct omap_wdt_dev *wdev) { - void __iomem *base; - base = wdev->base; + void __iomem *base = wdev->base; + /* sequence required to disable watchdog */ __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); + __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) cpu_relax(); @@ -119,12 +124,12 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout) static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) { u32 pre_margin = GET_WLDR_VAL(timer_margin); - void __iomem *base; - base = wdev->base; + void __iomem *base = wdev->base; /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); + __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); @@ -133,13 +138,11 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) /* * Allow only one task to hold it open */ - static int omap_wdt_open(struct inode *inode, struct file *file) { - struct omap_wdt_dev *wdev; - void __iomem *base; - wdev = platform_get_drvdata(omap_wdt_dev); - base = wdev->base; + struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); + void __iomem *base = wdev->base; + if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) return -EBUSY; @@ -154,6 +157,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) /* initialize prescaler */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); + __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) cpu_relax(); @@ -162,13 +166,14 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_set_timeout(wdev); omap_wdt_enable(wdev); + return nonseekable_open(inode, file); } static int omap_wdt_release(struct inode *inode, struct file *file) { - struct omap_wdt_dev *wdev; - wdev = file->private_data; + struct omap_wdt_dev *wdev = file->private_data; + /* * Shut off the timer unless NOWAYOUT is defined. */ @@ -187,14 +192,15 @@ static int omap_wdt_release(struct inode *inode, struct file *file) printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); #endif wdev->omap_wdt_users = 0; + return 0; } static ssize_t omap_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - struct omap_wdt_dev *wdev; - wdev = file->private_data; + struct omap_wdt_dev *wdev = file->private_data; + /* Refresh LOAD_TIME. */ if (len) { spin_lock(&wdt_lock); @@ -214,6 +220,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, .options = WDIOF_SETTIMEOUT, .firmware_version = 0, }; + wdev = file->private_data; switch (cmd) { @@ -262,31 +269,37 @@ static const struct file_operations omap_wdt_fops = { .release = omap_wdt_release, }; - static int __init omap_wdt_probe(struct platform_device *pdev) { struct resource *res, *mem; - int ret; struct omap_wdt_dev *wdev; + int ret; /* reserve static register mappings */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; + if (!res) { + ret = -ENOENT; + goto err_get_resource; + } - if (omap_wdt_dev) - return -EBUSY; + if (omap_wdt_dev) { + ret = -EBUSY; + goto err_busy; + } mem = request_mem_region(res->start, res->end - res->start + 1, pdev->name); - if (mem == NULL) - return -EBUSY; + if (!mem) { + ret = -EBUSY; + goto err_busy; + } wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); if (!wdev) { ret = -ENOMEM; - goto fail; + goto err_kzalloc; } + wdev->omap_wdt_users = 0; wdev->mem = mem; @@ -295,7 +308,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdev->armwdt_ck)) { ret = PTR_ERR(wdev->armwdt_ck); wdev->armwdt_ck = NULL; - goto fail; + goto err_clk; } } @@ -304,13 +317,13 @@ static int __init omap_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdev->mpu_wdt_ick)) { ret = PTR_ERR(wdev->mpu_wdt_ick); wdev->mpu_wdt_ick = NULL; - goto fail; + goto err_clk; } wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); if (IS_ERR(wdev->mpu_wdt_fck)) { ret = PTR_ERR(wdev->mpu_wdt_fck); wdev->mpu_wdt_fck = NULL; - goto fail; + goto err_clk; } } @@ -319,19 +332,19 @@ static int __init omap_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdev->mpu_wdt_ick)) { ret = PTR_ERR(wdev->mpu_wdt_ick); wdev->mpu_wdt_ick = NULL; - goto fail; + goto err_clk; } wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); if (IS_ERR(wdev->mpu_wdt_fck)) { ret = PTR_ERR(wdev->mpu_wdt_fck); wdev->mpu_wdt_fck = NULL; - goto fail; + goto err_clk; } } wdev->base = ioremap(res->start, res->end - res->start + 1); if (!wdev->base) { ret = -ENOMEM; - goto fail; + goto err_ioremap; } platform_set_drvdata(pdev, wdev); @@ -346,7 +359,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev) ret = misc_register(&(wdev->omap_wdt_miscdev)); if (ret) - goto fail; + goto err_misc; pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, @@ -359,28 +372,34 @@ static int __init omap_wdt_probe(struct platform_device *pdev) return 0; -fail: - if (wdev) { - platform_set_drvdata(pdev, NULL); - if (wdev->armwdt_ck) - clk_put(wdev->armwdt_ck); - if (wdev->mpu_wdt_ick) - clk_put(wdev->mpu_wdt_ick); - if (wdev->mpu_wdt_fck) - clk_put(wdev->mpu_wdt_fck); - iounmap(wdev->base); - kfree(wdev); - } - if (mem) { - release_mem_region(res->start, res->end - res->start + 1); - } +err_misc: + platform_set_drvdata(pdev, NULL); + iounmap(wdev->base); + +err_ioremap: + wdev->base = NULL; + +err_clk: + if (wdev->armwdt_ck) + clk_put(wdev->armwdt_ck); + if (wdev->mpu_wdt_ick) + clk_put(wdev->mpu_wdt_ick); + if (wdev->mpu_wdt_fck) + clk_put(wdev->mpu_wdt_fck); + kfree(wdev); + +err_kzalloc: + release_mem_region(res->start, res->end - res->start + 1); + +err_busy: +err_get_resource: + return ret; } static void omap_wdt_shutdown(struct platform_device *pdev) { - struct omap_wdt_dev *wdev; - wdev = platform_get_drvdata(pdev); + struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev->omap_wdt_users) omap_wdt_disable(wdev); @@ -388,8 +407,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev) static int omap_wdt_remove(struct platform_device *pdev) { - struct omap_wdt_dev *wdev; - wdev = platform_get_drvdata(pdev); + struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -398,14 +416,17 @@ static int omap_wdt_remove(struct platform_device *pdev) misc_deregister(&(wdev->omap_wdt_miscdev)); release_mem_region(res->start, res->end - res->start + 1); platform_set_drvdata(pdev, NULL); + if (wdev->armwdt_ck) { clk_put(wdev->armwdt_ck); wdev->armwdt_ck = NULL; } + if (wdev->mpu_wdt_ick) { clk_put(wdev->mpu_wdt_ick); wdev->mpu_wdt_ick = NULL; } + if (wdev->mpu_wdt_fck) { clk_put(wdev->mpu_wdt_fck); wdev->mpu_wdt_fck = NULL; @@ -414,6 +435,7 @@ static int omap_wdt_remove(struct platform_device *pdev) kfree(wdev); omap_wdt_dev = NULL; + return 0; } @@ -427,21 +449,23 @@ static int omap_wdt_remove(struct platform_device *pdev) static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { - struct omap_wdt_dev *wdev; - wdev = platform_get_drvdata(pdev); + struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); + if (wdev->omap_wdt_users) omap_wdt_disable(wdev); + return 0; } static int omap_wdt_resume(struct platform_device *pdev) { - struct omap_wdt_dev *wdev; - wdev = platform_get_drvdata(pdev); + struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); + if (wdev->omap_wdt_users) { omap_wdt_enable(wdev); omap_wdt_ping(wdev); } + return 0; } -- GitLab From 22ac92322c83334b562024414b770e48927ae963 Mon Sep 17 00:00:00 2001 From: Sylver Bruneau Date: Thu, 26 Jun 2008 10:47:45 +0200 Subject: [PATCH 3684/5416] [WATCHDOG] Orion: add hardware watchdog support This patch allows the use of the hardware watchdog in the Marvell Orion series of ARM SoCs. Signed-off-by: Sylver Bruneau Signed-off-by: Lennert Buytenhek Signed-off-by: Wim Van Sebroeck --- arch/arm/mach-orion5x/include/mach/orion5x.h | 2 + drivers/watchdog/Kconfig | 9 + drivers/watchdog/Makefile | 1 + drivers/watchdog/orion5x_wdt.c | 231 +++++++++++++++++++ 4 files changed, 243 insertions(+) create mode 100644 drivers/watchdog/orion5x_wdt.c diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 61eb74a8886..615cc1d0818 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -153,9 +153,11 @@ #define CPU_CONF ORION5X_BRIDGE_REG(0x100) #define CPU_CTRL ORION5X_BRIDGE_REG(0x104) #define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108) +#define WDT_RESET 0x0002 #define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c) #define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C) #define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110) +#define WDT_INT_REQ 0x0008 #define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114) #define BRIDGE_INT_TIMER0 0x0002 #define BRIDGE_INT_TIMER1 0x0004 diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6a711eb6998..1a22fe782a2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -224,6 +224,15 @@ config DAVINCI_WATCHDOG NOTE: once enabled, this timer cannot be disabled. Say N if you are unsure. +config ORION5X_WATCHDOG + tristate "Orion5x watchdog" + depends on ARCH_ORION5X + help + Say Y here if to include support for the watchdog timer + in the Orion5x ARM SoCs. + To compile this driver as a module, choose M here: the + module will be called orion5x_wdt. + # ARM26 Architecture # AVR32 Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f896d6f666b..d604430ffeb 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o +obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o # ARM26 Architecture diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c new file mode 100644 index 00000000000..14477631498 --- /dev/null +++ b/drivers/watchdog/orion5x_wdt.c @@ -0,0 +1,231 @@ +/* + * drivers/watchdog/orion5x_wdt.c + * + * Watchdog driver for Orion5x processors + * + * Author: Sylver Bruneau + * + * 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 + +/* + * Watchdog timer block registers. + */ +#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000) +#define WDT_EN 0x0010 +#define WDT_VAL (TIMER_VIRT_BASE + 0x0024) + +#define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK) +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 + +static int nowayout = WATCHDOG_NOWAYOUT; +static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ +static unsigned long wdt_status; + +static void wdt_enable(void) +{ + u32 reg; + + /* Set watchdog duration */ + writel(ORION5X_TCLK * heartbeat, WDT_VAL); + + /* Clear watchdog timer interrupt */ + reg = readl(BRIDGE_CAUSE); + reg &= ~WDT_INT_REQ; + writel(reg, BRIDGE_CAUSE); + + /* Enable watchdog timer */ + reg = readl(TIMER_CTRL); + reg |= WDT_EN; + writel(reg, TIMER_CTRL); + + /* Enable reset on watchdog */ + reg = readl(CPU_RESET_MASK); + reg |= WDT_RESET; + writel(reg, CPU_RESET_MASK); +} + +static void wdt_disable(void) +{ + u32 reg; + + /* Disable reset on watchdog */ + reg = readl(CPU_RESET_MASK); + reg &= ~WDT_RESET; + writel(reg, CPU_RESET_MASK); + + /* Disable watchdog timer */ + reg = readl(TIMER_CTRL); + reg &= ~WDT_EN; + writel(reg, TIMER_CTRL); +} + +static int orion5x_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) + return -EBUSY; + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + wdt_enable(); + return nonseekable_open(inode, file); +} + +static int orion5x_wdt_get_timeleft(int *time_left) +{ + *time_left = readl(WDT_VAL) / ORION5X_TCLK; + return 0; +} + +static ssize_t orion5x_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + set_bit(WDT_OK_TO_CLOSE, &wdt_status); + } + } + wdt_enable(); + } + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING, + .identity = "Orion5x Watchdog", +}; + + +static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + int time; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + wdt_enable(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, (int *)arg); + if (ret) + break; + + if (time <= 0 || time > WDT_MAX_DURATION) { + ret = -EINVAL; + break; + } + heartbeat = time; + wdt_enable(); + /* Fall through */ + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + + case WDIOC_GETTIMELEFT: + if (orion5x_wdt_get_timeleft(&time)) { + ret = -EINVAL; + break; + } + ret = put_user(time, (int *)arg); + break; + } + return ret; +} + +static int orion5x_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + wdt_disable(); + else + printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " + "timer will not stop\n"); + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + + +static const struct file_operations orion5x_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = orion5x_wdt_write, + .unlocked_ioctl = orion5x_wdt_ioctl, + .open = orion5x_wdt_open, + .release = orion5x_wdt_release, +}; + +static struct miscdevice orion5x_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &orion5x_wdt_fops, +}; + +static int __init orion5x_wdt_init(void) +{ + int ret; + + ret = misc_register(&orion5x_wdt_miscdev); + if (ret == 0) + printk("Orion5x Watchdog Timer: heartbeat %d sec\n", + heartbeat); + + return ret; +} + +static void __exit orion5x_wdt_exit(void) +{ + misc_deregister(&orion5x_wdt_miscdev); +} + +module_init(orion5x_wdt_init); +module_exit(orion5x_wdt_exit); + +MODULE_AUTHOR("Sylver Bruneau "); +MODULE_DESCRIPTION("Orion5x Processor Watchdog"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default is " + __MODULE_STRING(WDT_MAX_DURATION) ")"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From cdbf4c3c5f4909767c21f47f68f2ee57a8b36b3b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 13 Oct 2008 11:33:43 +0800 Subject: [PATCH 3685/5416] Blackfin arch: use the Blackfin on-chip ROM to do software reset when possible Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfrom.h | 85 +++++++++++++++++++++++++++++++ arch/blackfin/kernel/reboot.c | 10 +++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 arch/blackfin/include/asm/bfrom.h diff --git a/arch/blackfin/include/asm/bfrom.h b/arch/blackfin/include/asm/bfrom.h new file mode 100644 index 00000000000..cfe8024c3b2 --- /dev/null +++ b/arch/blackfin/include/asm/bfrom.h @@ -0,0 +1,85 @@ +/* Blackfin on-chip ROM API + * + * Copyright 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFROM_H__ +#define __BFROM_H__ + +#include + +/* Possible syscontrol action flags */ +#define SYSCTRL_READ 0x00000000 /* read registers */ +#define SYSCTRL_WRITE 0x00000001 /* write registers */ +#define SYSCTRL_SYSRESET 0x00000002 /* perform system reset */ +#define SYSCTRL_CORERESET 0x00000004 /* perform core reset */ +#define SYSCTRL_SOFTRESET 0x00000006 /* perform core and system reset */ +#define SYSCTRL_VRCTL 0x00000010 /* read/write VR_CTL register */ +#define SYSCTRL_EXTVOLTAGE 0x00000020 /* VDDINT supplied externally */ +#define SYSCTRL_INTVOLTAGE 0x00000000 /* VDDINT generated by on-chip regulator */ +#define SYSCTRL_OTPVOLTAGE 0x00000040 /* For Factory Purposes Only */ +#define SYSCTRL_PLLCTL 0x00000100 /* read/write PLL_CTL register */ +#define SYSCTRL_PLLDIV 0x00000200 /* read/write PLL_DIV register */ +#define SYSCTRL_LOCKCNT 0x00000400 /* read/write PLL_LOCKCNT register */ +#define SYSCTRL_PLLSTAT 0x00000800 /* read/write PLL_STAT register */ + +typedef struct ADI_SYSCTRL_VALUES { + uint16_t uwVrCtl; + uint16_t uwPllCtl; + uint16_t uwPllDiv; + uint16_t uwPllLockCnt; + uint16_t uwPllStat; +} ADI_SYSCTRL_VALUES; + +static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, ADI_SYSCTRL_VALUES *power_settings, void *reserved) = (void *)0xEF000038; + +/* We need a dedicated function since we need to screw with the stack pointer + * when resetting. The on-chip ROM will save/restore registers on the stack + * when doing a system reset, so the stack cannot be outside of the chip. + */ +__attribute__((__noreturn__)) +static inline void bfrom_SoftReset(void *new_stack) +{ + while (1) + __asm__ __volatile__( + "sp = %[stack];" + "jump (%[bfrom_syscontrol]);" + : : [bfrom_syscontrol] "p"(bfrom_SysControl), + "q0"(SYSCTRL_SOFTRESET), + "q1"(0), + "q2"(NULL), + [stack] "p"(new_stack) + ); +} + +/* OTP Functions */ +static uint32_t (* const bfrom_OtpCommand)(uint32_t command, uint32_t value) = (void *)0xEF000018; +static uint32_t (* const bfrom_OtpRead)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001A; +static uint32_t (* const bfrom_OtpWrite)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001C; + +/* otp command: defines for "command" */ +#define OTP_INIT 0x00000001 +#define OTP_CLOSE 0x00000002 + +/* otp read/write: defines for "flags" */ +#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */ +#define OTP_UPPER_HALF 0x00000001 +#define OTP_NO_ECC 0x00000010 /* do not use ECC */ +#define OTP_LOCK 0x00000020 /* sets page protection bit for page */ +#define OTP_CHECK_FOR_PREV_WRITE 0x00000080 + +/* Return values for all functions */ +#define OTP_SUCCESS 0x00000000 +#define OTP_MASTER_ERROR 0x001 +#define OTP_WRITE_ERROR 0x003 +#define OTP_READ_ERROR 0x005 +#define OTP_ACC_VIO_ERROR 0x009 +#define OTP_DATA_MULT_ERROR 0x011 +#define OTP_ECC_MULT_ERROR 0x021 +#define OTP_PREV_WR_ERROR 0x041 +#define OTP_DATA_SB_WARN 0x100 +#define OTP_ECC_SB_WARN 0x200 + +#endif diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index d0ead640d99..ae97ca407b0 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -10,6 +10,7 @@ #include #include #include +#include /* A system soft reset makes external memory unusable so force * this function into L1. We use the compiler ssync here rather @@ -74,7 +75,14 @@ void machine_restart(char *cmd) { native_machine_restart(cmd); local_irq_disable(); - bfin_reset(); + if (ANOMALY_05000353 || ANOMALY_05000386) + bfin_reset(); + else + /* the bootrom checks to see how it was reset and will + * automatically perform a software reset for us when + * it starts executing boot + */ + asm("raise 1;"); } __attribute__((weak)) -- GitLab From ad5dd977430216059d8344ccc516f11be4a37082 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 10 Oct 2008 21:17:11 +0800 Subject: [PATCH 3686/5416] Blackfin arch: make sure L2 start and length are always defined (fixes building on BF542) Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/include/mach/mem_map.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/blackfin/mach-bf548/include/mach/mem_map.h b/arch/blackfin/mach-bf548/include/mach/mem_map.h index f99f47bc3a0..a2228428dc0 100644 --- a/arch/blackfin/mach-bf548/include/mach/mem_map.h +++ b/arch/blackfin/mach-bf548/include/mach/mem_map.h @@ -94,13 +94,13 @@ #endif /*CONFIG_BFIN_DCACHE*/ /* Level 2 Memory */ -#if !defined(CONFIG_BF542) -# define L2_START 0xFEB00000 -# if defined(CONFIG_BF544) -# define L2_LENGTH 0x10000 -# else -# define L2_LENGTH 0x20000 -# endif +#define L2_START 0xFEB00000 +#if defined(CONFIG_BF542) +# define L2_LENGTH 0 +#elif defined(CONFIG_BF544) +# define L2_LENGTH 0x10000 +#else +# define L2_LENGTH 0x20000 #endif /* Scratch Pad Memory */ -- GitLab From 6d0f0dfdbc8bdb0c52759224b0d423c35f828397 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 2 Oct 2008 09:32:45 +0000 Subject: [PATCH 3687/5416] [WATCHDOG] orion5x_wdt.c: add spinlocking Add spin_locking to orion5x_wdt.c to prevent races. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/orion5x_wdt.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index 14477631498..14a339f58b6 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c @@ -20,6 +20,7 @@ #include #include #include +#include /* * Watchdog timer block registers. @@ -35,11 +36,14 @@ static int nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ static unsigned long wdt_status; +static spinlock_t wdt_lock; static void wdt_enable(void) { u32 reg; + spin_lock(&wdt_lock); + /* Set watchdog duration */ writel(ORION5X_TCLK * heartbeat, WDT_VAL); @@ -57,12 +61,16 @@ static void wdt_enable(void) reg = readl(CPU_RESET_MASK); reg |= WDT_RESET; writel(reg, CPU_RESET_MASK); + + spin_unlock(&wdt_lock); } static void wdt_disable(void) { u32 reg; + spin_lock(&wdt_lock); + /* Disable reset on watchdog */ reg = readl(CPU_RESET_MASK); reg &= ~WDT_RESET; @@ -72,6 +80,16 @@ static void wdt_disable(void) reg = readl(TIMER_CTRL); reg &= ~WDT_EN; writel(reg, TIMER_CTRL); + + spin_unlock(&wdt_lock); +} + +static int orion5x_wdt_get_timeleft(int *time_left) +{ + spin_lock(&wdt_lock); + *time_left = readl(WDT_VAL) / ORION5X_TCLK; + spin_unlock(&wdt_lock); + return 0; } static int orion5x_wdt_open(struct inode *inode, struct file *file) @@ -83,12 +101,6 @@ static int orion5x_wdt_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -static int orion5x_wdt_get_timeleft(int *time_left) -{ - *time_left = readl(WDT_VAL) / ORION5X_TCLK; - return 0; -} - static ssize_t orion5x_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { @@ -201,6 +213,8 @@ static int __init orion5x_wdt_init(void) { int ret; + spin_lock_init(&wdt_lock); + ret = misc_register(&orion5x_wdt_miscdev); if (ret == 0) printk("Orion5x Watchdog Timer: heartbeat %d sec\n", -- GitLab From fecc8d6d5611a6b1dce4a6cff4713f390056aa1c Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Fri, 10 Oct 2008 21:23:29 +0800 Subject: [PATCH 3688/5416] Blackfin arch: Remove useless head file Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/cpumask.h | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 arch/blackfin/include/asm/cpumask.h diff --git a/arch/blackfin/include/asm/cpumask.h b/arch/blackfin/include/asm/cpumask.h deleted file mode 100644 index b20a8e9012c..00000000000 --- a/arch/blackfin/include/asm/cpumask.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_BLACKFIN_CPUMASK_H -#define _ASM_BLACKFIN_CPUMASK_H - -#include - -#endif /* _ASM_BLACKFIN_CPUMASK_H */ -- GitLab From 3094c981f2d567f0a442687ced24a5340aa10b6c Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Fri, 10 Oct 2008 21:22:01 +0800 Subject: [PATCH 3689/5416] Blackfin arch: fix a typo in comments Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 74370f3707b..7054594831c 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -411,7 +411,7 @@ static __init void parse_cmdline_early(char *cmdline_p) * [_rambase, _ramstart]: kernel image * [memory_start, memory_end]: dynamic memory managed by kernel * [memory_end, _ramend]: reserved memory - * [meory_mtd_start(memory_end), + * [memory_mtd_start(memory_end), * memory_mtd_start + mtd_size]: rootfs (if any) * [_ramend - DMA_UNCACHED_REGION, * _ramend]: uncached DMA region -- GitLab From 561967010edef40f539dacf2aa125e20773ab40b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:29 -0400 Subject: [PATCH 3690/5416] netlabel: Fix some sparse warnings Fix a few sparse warnings. One dealt with a RCU lock being held on error, another dealt with an improper type caused by a signed/unsigned mixup while the rest appeared to be caused by using rcu_dereference() in a list_for_each_entry_rcu() call. The latter probably isn't a big deal, but I derive a certain pleasure from knowing that the net/netlabel is nice and clean. Thanks to James Morris for pointing out the issues and demonstrating how to run sparse. Signed-off-by: Paul Moore --- net/netlabel/netlabel_cipso_v4.c | 4 ++-- net/netlabel/netlabel_domainhash.c | 12 ++++++------ net/netlabel/netlabel_unlabeled.c | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 0aec318bf0e..aaf50032b3a 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -491,7 +491,7 @@ list_start: doi_def = cipso_v4_doi_getdef(doi); if (doi_def == NULL) { ret_val = -EINVAL; - goto list_failure; + goto list_failure_lock; } ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type); @@ -655,7 +655,7 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb, struct netlink_callback *cb) { struct netlbl_cipsov4_doiwalk_arg cb_arg; - int doi_skip = cb->args[0]; + u32 doi_skip = cb->args[0]; cb_arg.nl_cb = cb; cb_arg.skb = skb; diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 643c032a3a5..dc42206c431 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -115,13 +115,13 @@ static u32 netlbl_domhsh_hash(const char *key) static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) { u32 bkt; + struct list_head *bkt_list; struct netlbl_dom_map *iter; if (domain != NULL) { bkt = netlbl_domhsh_hash(domain); - list_for_each_entry_rcu(iter, - &rcu_dereference(netlbl_domhsh)->tbl[bkt], - list) + bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt]; + list_for_each_entry_rcu(iter, bkt_list, list) if (iter->valid && strcmp(iter->domain, domain) == 0) return iter; } @@ -410,6 +410,7 @@ int netlbl_domhsh_walk(u32 *skip_bkt, { int ret_val = -ENOENT; u32 iter_bkt; + struct list_head *iter_list; struct netlbl_dom_map *iter_entry; u32 chain_cnt = 0; @@ -417,9 +418,8 @@ int netlbl_domhsh_walk(u32 *skip_bkt, for (iter_bkt = *skip_bkt; iter_bkt < rcu_dereference(netlbl_domhsh)->size; iter_bkt++, chain_cnt = 0) { - list_for_each_entry_rcu(iter_entry, - &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt], - list) + iter_list = &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt]; + list_for_each_entry_rcu(iter_entry, iter_list, list) if (iter_entry->valid) { if (chain_cnt++ < *skip_chain) continue; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 921c118ead8..cc105a10e3f 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -381,12 +381,12 @@ static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6( static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) { u32 bkt; + struct list_head *bkt_list; struct netlbl_unlhsh_iface *iter; bkt = netlbl_unlhsh_hash(ifindex); - list_for_each_entry_rcu(iter, - &rcu_dereference(netlbl_unlhsh)->tbl[bkt], - list) + bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; + list_for_each_entry_rcu(iter, bkt_list, list) if (iter->valid && iter->ifindex == ifindex) return iter; @@ -1427,6 +1427,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, struct netlbl_unlhsh_iface *iface; struct netlbl_unlhsh_addr4 *addr4; struct netlbl_unlhsh_addr6 *addr6; + struct list_head *iter_list; cb_arg.nl_cb = cb; cb_arg.skb = skb; @@ -1436,9 +1437,8 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, for (iter_bkt = skip_bkt; iter_bkt < rcu_dereference(netlbl_unlhsh)->size; iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { - list_for_each_entry_rcu(iface, - &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt], - list) { + iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; + list_for_each_entry_rcu(iface, iter_list, list) { if (!iface->valid || iter_chain++ < skip_chain) continue; -- GitLab From accc609322ef5ed44cba6d2d70c741afc76385fb Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:29 -0400 Subject: [PATCH 3691/5416] selinux: Cleanup the NetLabel glue code We were doing a lot of extra work in selinux_netlbl_sock_graft() what wasn't necessary so this patch removes that code. It also removes the redundant second argument to selinux_netlbl_sock_setsid() which allows us to simplify a few other functions. Signed-off-by: Paul Moore Acked-by: James Morris --- security/selinux/netlabel.c | 38 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 89b418392f1..b9ce5fcf343 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -66,22 +66,24 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, /** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label - * @sid: the SID to use * * Description: - * Attempt to label a socket using the NetLabel mechanism using the given - * SID. Returns zero values on success, negative values on failure. + * Attempt to label a socket using the NetLabel mechanism. Returns zero values + * on success, negative values on failure. * */ -static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) +static int selinux_netlbl_sock_setsid(struct sock *sk) { int rc; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; + if (sksec->nlbl_state != NLBL_REQUIRE) + return 0; + netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(sid, &secattr); + rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); if (rc != 0) goto sock_setsid_return; rc = netlbl_sock_setattr(sk, &secattr); @@ -174,24 +176,10 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, */ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) { - struct sk_security_struct *sksec = sk->sk_security; - struct netlbl_lsm_secattr secattr; - u32 nlbl_peer_sid; - - if (sksec->nlbl_state != NLBL_REQUIRE) - return; - - netlbl_secattr_init(&secattr); - if (netlbl_sock_getattr(sk, &secattr) == 0 && - secattr.flags != NETLBL_SECATTR_NONE && - security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0) - sksec->peer_sid = nlbl_peer_sid; - netlbl_secattr_destroy(&secattr); - /* Try to set the NetLabel on the socket to save time later, if we fail * here we will pick up the pieces in later calls to * selinux_netlbl_inode_permission(). */ - selinux_netlbl_sock_setsid(sk, sksec->sid); + selinux_netlbl_sock_setsid(sk); } /** @@ -205,13 +193,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) */ int selinux_netlbl_socket_post_create(struct socket *sock) { - struct sock *sk = sock->sk; - struct sk_security_struct *sksec = sk->sk_security; - - if (sksec->nlbl_state != NLBL_REQUIRE) - return 0; - - return selinux_netlbl_sock_setsid(sk, sksec->sid); + return selinux_netlbl_sock_setsid(sock->sk); } /** @@ -246,7 +228,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) local_bh_disable(); bh_lock_sock_nested(sk); if (likely(sksec->nlbl_state == NLBL_REQUIRE)) - rc = selinux_netlbl_sock_setsid(sk, sksec->sid); + rc = selinux_netlbl_sock_setsid(sk); else rc = 0; bh_unlock_sock(sk); -- GitLab From aa86290089a1e57b4bdbbb4720072233f66bd5b2 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:29 -0400 Subject: [PATCH 3692/5416] selinux: Correctly handle IPv4 packets on IPv6 sockets in all cases We did the right thing in a few cases but there were several areas where we determined a packet's address family based on the socket's address family which is not the right thing to do since we can get IPv4 packets on IPv6 sockets. This patch fixes these problems by either taking the address family directly from the packet. Signed-off-by: Paul Moore Acked-by: James Morris --- security/selinux/hooks.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 03fc6a81ae3..223f474bee8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4207,10 +4207,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * u32 peer_secid = SECSID_NULL; u16 family; - if (sock) + if (skb && skb->protocol == htons(ETH_P_IP)) + family = PF_INET; + else if (skb && skb->protocol == htons(ETH_P_IPV6)) + family = PF_INET6; + else if (sock) family = sock->sk->sk_family; - else if (skb && skb->sk) - family = skb->sk->sk_family; else goto out; @@ -4277,10 +4279,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, { struct sk_security_struct *sksec = sk->sk_security; int err; + u16 family = sk->sk_family; u32 newsid; u32 peersid; - err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); + /* handle mapped IPv4 packets arriving via IPv6 sockets */ + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) + family = PF_INET; + + err = selinux_skb_peerlbl_sid(skb, family, &peersid); if (err) return err; if (peersid == SECSID_NULL) { @@ -4318,9 +4325,14 @@ static void selinux_inet_csk_clone(struct sock *newsk, static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) { + u16 family = sk->sk_family; struct sk_security_struct *sksec = sk->sk_security; - selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); + /* handle mapped IPv4 packets arriving via IPv6 sockets */ + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) + family = PF_INET; + + selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); } static void selinux_req_classify_flow(const struct request_sock *req, -- GitLab From 948a72438d4178d0728c4b0a38836d280b846939 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:30 -0400 Subject: [PATCH 3693/5416] netlabel: Remove unneeded in-kernel API functions After some discussions with the Smack folks, well just Casey, I now have a better idea of what Smack wants out of NetLabel in the future so I think it is now safe to do some API "pruning". If another LSM comes along that needs this functionality we can always add it back in, but I don't see any LSMs on the horizon which might make use of these functions. Thanks to Rami Rosen who suggested removing netlbl_cfg_cipsov4_del() back in February 2008. Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/netlabel.h | 13 ------ net/netlabel/netlabel_kapi.c | 84 ++++++++++-------------------------- 2 files changed, 23 insertions(+), 74 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index e4d2d6baa98..5303749b709 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -352,12 +352,9 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr) int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info); int netlbl_cfg_unlbl_add_map(const char *domain, struct netlbl_audit *audit_info); -int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def, - struct netlbl_audit *audit_info); int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, const char *domain, struct netlbl_audit *audit_info); -int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info); /* * LSM security attribute operations @@ -404,22 +401,12 @@ static inline int netlbl_cfg_unlbl_add_map(const char *domain, { return -ENOSYS; } -static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def, - struct netlbl_audit *audit_info) -{ - return -ENOSYS; -} static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, const char *domain, struct netlbl_audit *audit_info) { return -ENOSYS; } -static inline int netlbl_cfg_cipsov4_del(u32 doi, - struct netlbl_audit *audit_info) -{ - return -ENOSYS; -} static inline int netlbl_secattr_catmap_walk( struct netlbl_lsm_secattr_catmap *catmap, u32 offset) diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 39793a1a93a..6c211fe9778 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -82,7 +82,7 @@ int netlbl_cfg_unlbl_add_map(const char *domain, entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) - goto cfg_unlbl_add_map_failure; + return -ENOMEM; if (domain != NULL) { entry->domain = kstrdup(domain, GFP_ATOMIC); if (entry->domain == NULL) @@ -103,49 +103,6 @@ cfg_unlbl_add_map_failure: return ret_val; } -/** - * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition - * @doi_def: the DOI definition - * @audit_info: NetLabel audit information - * - * Description: - * Add a new CIPSOv4 DOI definition to the NetLabel subsystem. Returns zero on - * success, negative values on failure. - * - */ -int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def, - struct netlbl_audit *audit_info) -{ - int ret_val; - const char *type_str; - struct audit_buffer *audit_buf; - - ret_val = cipso_v4_doi_add(doi_def); - - audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, - audit_info); - if (audit_buf != NULL) { - switch (doi_def->type) { - case CIPSO_V4_MAP_STD: - type_str = "std"; - break; - case CIPSO_V4_MAP_PASS: - type_str = "pass"; - break; - default: - type_str = "(unknown)"; - } - audit_log_format(audit_buf, - " cipso_doi=%u cipso_type=%s res=%u", - doi_def->doi, - type_str, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); - } - - return ret_val; -} - /** * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping * @doi_def: the DOI definition @@ -165,10 +122,12 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, { int ret_val = -ENOMEM; struct netlbl_dom_map *entry; + const char *type_str; + struct audit_buffer *audit_buf; entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) - goto cfg_cipsov4_add_map_failure; + return -ENOMEM; if (domain != NULL) { entry->domain = kstrdup(domain, GFP_ATOMIC); if (entry->domain == NULL) @@ -182,7 +141,7 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, * domain mapping for it. */ rcu_read_lock(); - ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info); + ret_val = cipso_v4_doi_add(doi_def); if (ret_val != 0) goto cfg_cipsov4_add_map_failure_unlock; ret_val = netlbl_domhsh_add(entry, audit_info); @@ -196,6 +155,24 @@ cfg_cipsov4_add_map_failure_remove_doi: cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free); cfg_cipsov4_add_map_failure_unlock: rcu_read_unlock(); + audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, + audit_info); + if (audit_buf != NULL) { + switch (doi_def->type) { + case CIPSO_V4_MAP_STD: + type_str = "std"; + break; + case CIPSO_V4_MAP_PASS: + type_str = "pass"; + break; + default: + type_str = "(unknown)"; + } + audit_log_format(audit_buf, + " cipso_doi=%u cipso_type=%s res=%u", + doi_def->doi, type_str, ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } cfg_cipsov4_add_map_failure: if (entry != NULL) kfree(entry->domain); @@ -203,21 +180,6 @@ cfg_cipsov4_add_map_failure: return ret_val; } -/** - * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition - * @doi: the CIPSO DOI value - * @audit_info: NetLabel audit information - * - * Description: - * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem. - * Returns zero on success, negative values on failure. - * - */ -int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info) -{ - return cipso_v4_doi_remove(doi, audit_info, netlbl_cipsov4_doi_free); -} - /* * Security Attribute Functions */ -- GitLab From d8395c876bb8a560c8a032887e191b95499a25d6 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:30 -0400 Subject: [PATCH 3694/5416] selinux: Better local/forward check in selinux_ip_postroute() It turns out that checking to see if skb->sk is NULL is not a very good indicator of a forwarded packet as some locally generated packets also have skb->sk set to NULL. Fix this by not only checking the skb->sk field but also the IP[6]CB(skb)->flags field for the IP[6]SKB_FORWARDED flag. While we are at it, we are calling selinux_parse_skb() much earlier than we really should resulting in potentially wasted cycles parsing packets for information we might no use; so shuffle the code around a bit to fix this. Signed-off-by: Paul Moore Acked-by: James Morris --- security/selinux/hooks.c | 126 +++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 223f474bee8..b520667a24b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4070,20 +4070,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, - u16 family, char *addrp) + u16 family) { int err; struct sk_security_struct *sksec = sk->sk_security; u32 peer_sid; u32 sk_sid = sksec->sid; + struct avc_audit_data ad; + char *addrp; + + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = skb->iif; + ad.u.net.family = family; + err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); + if (err) + return err; if (selinux_compat_net) - err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, + err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad, family, addrp); else err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, ad); + PACKET__RECV, &ad); if (err) return err; @@ -4092,12 +4100,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (err) return err; err = avc_has_perm(sk_sid, peer_sid, - SECCLASS_PEER, PEER__RECV, ad); + SECCLASS_PEER, PEER__RECV, &ad); } else { - err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) return err; - err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); + err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); } return err; @@ -4111,6 +4119,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) u32 sk_sid = sksec->sid; struct avc_audit_data ad; char *addrp; + u8 secmark_active; + u8 peerlbl_active; if (family != PF_INET && family != PF_INET6) return 0; @@ -4119,6 +4129,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) family = PF_INET; + /* If any sort of compatibility mode is enabled then handoff processing + * to the selinux_sock_rcv_skb_compat() function to deal with the + * special handling. We do this in an attempt to keep this function + * as fast and as clean as possible. */ + if (selinux_compat_net || !selinux_policycap_netpeer) + return selinux_sock_rcv_skb_compat(sk, skb, family); + + secmark_active = selinux_secmark_enabled(); + peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); + if (!secmark_active && !peerlbl_active) + return 0; + AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = skb->iif; ad.u.net.family = family; @@ -4126,15 +4148,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) return err; - /* If any sort of compatibility mode is enabled then handoff processing - * to the selinux_sock_rcv_skb_compat() function to deal with the - * special handling. We do this in an attempt to keep this function - * as fast and as clean as possible. */ - if (selinux_compat_net || !selinux_policycap_netpeer) - return selinux_sock_rcv_skb_compat(sk, skb, &ad, - family, addrp); - - if (netlbl_enabled() || selinux_xfrm_enabled()) { + if (peerlbl_active) { u32 peer_sid; err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); @@ -4148,7 +4162,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) PEER__RECV, &ad); } - if (selinux_secmark_enabled()) { + if (secmark_active) { err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) @@ -4396,15 +4410,15 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, if (!secmark_active && !peerlbl_active) return NF_ACCEPT; + if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) + return NF_DROP; + AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) return NF_DROP; - if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) - return NF_DROP; - if (peerlbl_active) if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, peer_sid, &ad) != 0) @@ -4505,30 +4519,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk, static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, int ifindex, - struct avc_audit_data *ad, - u16 family, - char *addrp, - u8 proto) + u16 family) { struct sock *sk = skb->sk; struct sk_security_struct *sksec; + struct avc_audit_data ad; + char *addrp; + u8 proto; if (sk == NULL) return NF_ACCEPT; sksec = sk->sk_security; + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = ifindex; + ad.u.net.family = family; + if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) + return NF_DROP; + if (selinux_compat_net) { if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, - ad, family, addrp)) + &ad, family, addrp)) return NF_DROP; } else { if (avc_has_perm(sksec->sid, skb->secmark, - SECCLASS_PACKET, PACKET__SEND, ad)) + SECCLASS_PACKET, PACKET__SEND, &ad)) return NF_DROP; } if (selinux_policycap_netpeer) - if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) + if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) return NF_DROP; return NF_ACCEPT; @@ -4542,23 +4562,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, struct sock *sk; struct avc_audit_data ad; char *addrp; - u8 proto; u8 secmark_active; u8 peerlbl_active; - AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = ifindex; - ad.u.net.family = family; - if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) - return NF_DROP; - /* If any sort of compatibility mode is enabled then handoff processing * to the selinux_ip_postroute_compat() function to deal with the * special handling. We do this in an attempt to keep this function * as fast and as clean as possible. */ if (selinux_compat_net || !selinux_policycap_netpeer) - return selinux_ip_postroute_compat(skb, ifindex, &ad, - family, addrp, proto); + return selinux_ip_postroute_compat(skb, ifindex, family); /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec * packet transformation so allow the packet to pass without any checks @@ -4574,21 +4586,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, if (!secmark_active && !peerlbl_active) return NF_ACCEPT; - /* if the packet is locally generated (skb->sk != NULL) then use the - * socket's label as the peer label, otherwise the packet is being - * forwarded through this system and we need to fetch the peer label - * directly from the packet */ + /* if the packet is being forwarded then get the peer label from the + * packet itself; otherwise check to see if it is from a local + * application or the kernel, if from an application get the peer label + * from the sending socket, otherwise use the kernel's sid */ sk = skb->sk; - if (sk) { + if (sk == NULL) { + switch (family) { + case PF_INET: + if (IPCB(skb)->flags & IPSKB_FORWARDED) + secmark_perm = PACKET__FORWARD_OUT; + else + secmark_perm = PACKET__SEND; + break; + case PF_INET6: + if (IP6CB(skb)->flags & IP6SKB_FORWARDED) + secmark_perm = PACKET__FORWARD_OUT; + else + secmark_perm = PACKET__SEND; + break; + default: + return NF_DROP; + } + if (secmark_perm == PACKET__FORWARD_OUT) { + if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) + return NF_DROP; + } else + peer_sid = SECINITSID_KERNEL; + } else { struct sk_security_struct *sksec = sk->sk_security; peer_sid = sksec->sid; secmark_perm = PACKET__SEND; - } else { - if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) - return NF_DROP; - secmark_perm = PACKET__FORWARD_OUT; } + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = ifindex; + ad.u.net.family = family; + if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) + return NF_DROP; + if (secmark_active) if (avc_has_perm(peer_sid, skb->secmark, SECCLASS_PACKET, secmark_perm, &ad)) -- GitLab From 99d854d231ce141850b988bdc7e2e7c78f49b03a Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:30 -0400 Subject: [PATCH 3695/5416] selinux: Fix a problem in security_netlbl_sid_to_secattr() Currently when SELinux fails to allocate memory in security_netlbl_sid_to_secattr() the NetLabel LSM domain field is set to NULL which triggers the default NetLabel LSM domain mapping which may not always be the desired mapping. This patch fixes this by returning an error when the kernel is unable to allocate memory. This could result in more failures on a system with heavy memory pressure but it is the "correct" thing to do. Signed-off-by: Paul Moore Acked-by: James Morris --- security/selinux/ss/services.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8551952ef32..c8f688a1004 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2785,7 +2785,7 @@ netlbl_secattr_to_sid_return_cleanup: */ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) { - int rc = -ENOENT; + int rc; struct context *ctx; if (!ss_initialized) @@ -2793,10 +2793,16 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) read_lock(&policy_rwlock); ctx = sidtab_search(&sidtab, sid); - if (ctx == NULL) + if (ctx == NULL) { + rc = -ENOENT; goto netlbl_sid_to_secattr_failure; + } secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], GFP_ATOMIC); + if (secattr->domain == NULL) { + rc = -ENOMEM; + goto netlbl_sid_to_secattr_failure; + } secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; mls_export_netlbl_lvl(ctx, secattr); rc = mls_export_netlbl_cat(ctx, secattr); -- GitLab From dfaebe9825ff34983778f287101bc5f3bce00640 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:31 -0400 Subject: [PATCH 3696/5416] selinux: Fix missing calls to netlbl_skbuff_err() At some point I think I messed up and dropped the calls to netlbl_skbuff_err() which are necessary for CIPSO to send error notifications to remote systems. This patch re-introduces the error handling calls into the SELinux code. Signed-off-by: Paul Moore Acked-by: James Morris --- include/net/netlabel.h | 6 ++++-- net/netlabel/netlabel_kapi.c | 5 +++-- security/selinux/hooks.c | 19 +++++++++++++++---- security/selinux/include/netlabel.h | 9 +++++++++ security/selinux/netlabel.c | 20 +++++++++++++++++++- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 5303749b709..e16db096126 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -382,7 +382,7 @@ int netlbl_sock_getattr(struct sock *sk, int netlbl_skbuff_getattr(const struct sk_buff *skb, u16 family, struct netlbl_lsm_secattr *secattr); -void netlbl_skbuff_err(struct sk_buff *skb, int error); +void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway); /* * LSM label mapping cache operations @@ -454,7 +454,9 @@ static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, { return -ENOSYS; } -static inline void netlbl_skbuff_err(struct sk_buff *skb, int error) +static inline void netlbl_skbuff_err(struct sk_buff *skb, + int error, + int gateway) { return; } diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 6c211fe9778..22faba620e4 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -490,6 +490,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, * netlbl_skbuff_err - Handle a LSM error on a sk_buff * @skb: the packet * @error: the error code + * @gateway: true if host is acting as a gateway, false otherwise * * Description: * Deal with a LSM problem when handling the packet in @skb, typically this is @@ -497,10 +498,10 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, * according to the packet's labeling protocol. * */ -void netlbl_skbuff_err(struct sk_buff *skb, int error) +void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) { if (CIPSO_V4_OPTEXIST(skb)) - cipso_v4_error(skb, error, 0); + cipso_v4_error(skb, error, gateway); } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b520667a24b..a91146a6b37 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4101,6 +4101,8 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); + if (err) + selinux_netlbl_err(skb, err, 0); } else { err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) @@ -4156,10 +4158,14 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return err; err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, peer_sid, &ad); - if (err) + if (err) { + selinux_netlbl_err(skb, err, 0); return err; + } err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); + if (err) + selinux_netlbl_err(skb, err, 0); } if (secmark_active) { @@ -4396,6 +4402,7 @@ out: static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, u16 family) { + int err; char *addrp; u32 peer_sid; struct avc_audit_data ad; @@ -4419,10 +4426,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) return NF_DROP; - if (peerlbl_active) - if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, - peer_sid, &ad) != 0) + if (peerlbl_active) { + err = selinux_inet_sys_rcv_skb(ifindex, addrp, family, + peer_sid, &ad); + if (err) { + selinux_netlbl_err(skb, err, 1); return NF_DROP; + } + } if (secmark_active) if (avc_has_perm(peer_sid, skb->secmark, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 487a7d81fe2..d4e3ac8a7fb 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -39,6 +39,8 @@ #ifdef CONFIG_NETLABEL void selinux_netlbl_cache_invalidate(void); +void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); + void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, int family); @@ -63,6 +65,13 @@ static inline void selinux_netlbl_cache_invalidate(void) return; } +static inline void selinux_netlbl_err(struct sk_buff *skb, + int error, + int gateway) +{ + return; +} + static inline void selinux_netlbl_sk_security_reset( struct sk_security_struct *ssec, int family) diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index b9ce5fcf343..4053f7fc95f 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -107,6 +107,24 @@ void selinux_netlbl_cache_invalidate(void) netlbl_cache_invalidate(); } +/** + * selinux_netlbl_err - Handle a NetLabel packet error + * @skb: the packet + * @error: the error code + * @gateway: true if host is acting as a gateway, false otherwise + * + * Description: + * When a packet is dropped due to a call to avc_has_perm() pass the error + * code to the NetLabel subsystem so any protocol specific processing can be + * done. This is safe to call even if you are unsure if NetLabel labeling is + * present on the packet, NetLabel is smart enough to only act when it should. + * + */ +void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) +{ + netlbl_skbuff_err(skb, error, gateway); +} + /** * selinux_netlbl_sk_security_reset - Reset the NetLabel fields * @ssec: the sk_security_struct @@ -289,7 +307,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, return 0; if (nlbl_sid != SECINITSID_UNLABELED) - netlbl_skbuff_err(skb, rc); + netlbl_skbuff_err(skb, rc, 0); return rc; } -- GitLab From a8134296ba9940b5b271d908666e532d34430a3c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:31 -0400 Subject: [PATCH 3697/5416] smack: Fix missing calls to netlbl_skbuff_err() Smack needs to call netlbl_skbuff_err() to let NetLabel do the necessary protocol specific error handling. Signed-off-by: Paul Moore Acked-by: Casey Schaufler --- security/smack/smack_lsm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 87d75417ea9..6e2dc0bab70 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2179,7 +2179,10 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) * This is the simplist possible security model * for networking. */ - return smk_access(smack, ssp->smk_in, MAY_WRITE); + rc = smk_access(smack, ssp->smk_in, MAY_WRITE); + if (rc != 0) + netlbl_skbuff_err(skb, rc, 0); + return rc; } /** -- GitLab From b1edeb102397546438ab4624489c6ccd7b410d97 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:31 -0400 Subject: [PATCH 3698/5416] netlabel: Replace protocol/NetLabel linking with refrerence counts NetLabel has always had a list of backpointers in the CIPSO DOI definition structure which pointed to the NetLabel LSM domain mapping structures which referenced the CIPSO DOI struct. The rationale for this was that when an administrator removed a CIPSO DOI from the system all of the associated NetLabel LSM domain mappings should be removed as well; a list of backpointers made this a simple operation. Unfortunately, while the backpointers did make the removal easier they were a bit of a mess from an implementation point of view which was making further development difficult. Since the removal of a CIPSO DOI is a realtively rare event it seems to make sense to remove this backpointer list as the optimization was hurting us more then it was helping. However, we still need to be able to track when a CIPSO DOI definition is being used so replace the backpointer list with a reference count. In order to preserve the current functionality of removing the associated LSM domain mappings when a CIPSO DOI is removed we walk the LSM domain mapping table, removing the relevant entries. Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/cipso_ipv4.h | 21 +-- net/ipv4/cipso_ipv4.c | 235 ++++++++++++----------------- net/netlabel/netlabel_cipso_v4.c | 77 ++++++---- net/netlabel/netlabel_domainhash.c | 95 ++++++------ net/netlabel/netlabel_domainhash.h | 2 + net/netlabel/netlabel_kapi.c | 43 +++--- net/netlabel/netlabel_mgmt.c | 24 +-- security/smack/smackfs.c | 4 +- 8 files changed, 235 insertions(+), 266 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index a6bb94530cf..5fe6556fb3c 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -40,6 +40,7 @@ #include #include #include +#include /* known doi values */ #define CIPSO_V4_DOI_UNKNOWN 0x00000000 @@ -79,10 +80,9 @@ struct cipso_v4_doi { } map; u8 tags[CIPSO_V4_TAG_MAXCNT]; - u32 valid; + atomic_t refcount; struct list_head list; struct rcu_head rcu; - struct list_head dom_list; }; /* Standard CIPSO mapping table */ @@ -128,25 +128,26 @@ extern int cipso_v4_rbm_strictvalid; #ifdef CONFIG_NETLABEL int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); -int cipso_v4_doi_remove(u32 doi, - struct netlbl_audit *audit_info, - void (*callback) (struct rcu_head * head)); +void cipso_v4_doi_free(struct cipso_v4_doi *doi_def); +int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info); struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); +void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def); int cipso_v4_doi_walk(u32 *skip_cnt, int (*callback) (struct cipso_v4_doi *doi_def, void *arg), void *cb_arg); -int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); -int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, - const char *domain); #else static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) { return -ENOSYS; } +static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def) +{ + return; +} + static inline int cipso_v4_doi_remove(u32 doi, - struct netlbl_audit *audit_info, - void (*callback) (struct rcu_head * head)) + struct netlbl_audit *audit_info) { return 0; } diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 2c0e4572cc9..bf87eddfec3 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -47,17 +47,7 @@ #include #include -struct cipso_v4_domhsh_entry { - char *domain; - u32 valid; - struct list_head list; - struct rcu_head rcu; -}; - /* List of available DOI definitions */ -/* XXX - Updates should be minimal so having a single lock for the - * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be - * okay. */ /* XXX - This currently assumes a minimal number of different DOIs in use, * if in practice there are a lot of different DOIs this list should * probably be turned into a hash table or something similar so we @@ -193,25 +183,6 @@ static void cipso_v4_bitmap_setbit(unsigned char *bitmap, bitmap[byte_spot] &= ~bitmask; } -/** - * cipso_v4_doi_domhsh_free - Frees a domain list entry - * @entry: the entry's RCU field - * - * Description: - * This function is designed to be used as a callback to the call_rcu() - * function so that the memory allocated to a domain list entry can be released - * safely. - * - */ -static void cipso_v4_doi_domhsh_free(struct rcu_head *entry) -{ - struct cipso_v4_domhsh_entry *ptr; - - ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu); - kfree(ptr->domain); - kfree(ptr); -} - /** * cipso_v4_cache_entry_free - Frees a cache entry * @entry: the entry to free @@ -457,7 +428,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) struct cipso_v4_doi *iter; list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) - if (iter->doi == doi && iter->valid) + if (iter->doi == doi && atomic_read(&iter->refcount)) return iter; return NULL; } @@ -501,9 +472,8 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) } } - doi_def->valid = 1; + atomic_set(&doi_def->refcount, 1); INIT_RCU_HEAD(&doi_def->rcu); - INIT_LIST_HEAD(&doi_def->dom_list); spin_lock(&cipso_v4_doi_list_lock); if (cipso_v4_doi_search(doi_def->doi) != NULL) @@ -518,60 +488,130 @@ doi_add_failure: return -EEXIST; } +/** + * cipso_v4_doi_free - Frees a DOI definition + * @entry: the entry's RCU field + * + * Description: + * This function frees all of the memory associated with a DOI definition. + * + */ +void cipso_v4_doi_free(struct cipso_v4_doi *doi_def) +{ + if (doi_def == NULL) + return; + + switch (doi_def->type) { + case CIPSO_V4_MAP_STD: + kfree(doi_def->map.std->lvl.cipso); + kfree(doi_def->map.std->lvl.local); + kfree(doi_def->map.std->cat.cipso); + kfree(doi_def->map.std->cat.local); + break; + } + kfree(doi_def); +} + +/** + * cipso_v4_doi_free_rcu - Frees a DOI definition via the RCU pointer + * @entry: the entry's RCU field + * + * Description: + * This function is designed to be used as a callback to the call_rcu() + * function so that the memory allocated to the DOI definition can be released + * safely. + * + */ +static void cipso_v4_doi_free_rcu(struct rcu_head *entry) +{ + struct cipso_v4_doi *doi_def; + + doi_def = container_of(entry, struct cipso_v4_doi, rcu); + cipso_v4_doi_free(doi_def); +} + /** * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine * @doi: the DOI value * @audit_secid: the LSM secid to use in the audit message - * @callback: the DOI cleanup/free callback * * Description: - * Removes a DOI definition from the CIPSO engine, @callback is called to - * free any memory. The NetLabel routines will be called to release their own - * LSM domain mappings as well as our own domain list. Returns zero on - * success and negative values on failure. + * Removes a DOI definition from the CIPSO engine. The NetLabel routines will + * be called to release their own LSM domain mappings as well as our own + * domain list. Returns zero on success and negative values on failure. * */ -int cipso_v4_doi_remove(u32 doi, - struct netlbl_audit *audit_info, - void (*callback) (struct rcu_head * head)) +int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info) { struct cipso_v4_doi *doi_def; - struct cipso_v4_domhsh_entry *dom_iter; spin_lock(&cipso_v4_doi_list_lock); doi_def = cipso_v4_doi_search(doi); - if (doi_def != NULL) { - doi_def->valid = 0; - list_del_rcu(&doi_def->list); + if (doi_def == NULL) { spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_lock(); - list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) - if (dom_iter->valid) - netlbl_cfg_map_del(dom_iter->domain, - audit_info); - rcu_read_unlock(); - cipso_v4_cache_invalidate(); - call_rcu(&doi_def->rcu, callback); - return 0; + return -ENOENT; + } + if (!atomic_dec_and_test(&doi_def->refcount)) { + spin_unlock(&cipso_v4_doi_list_lock); + return -EBUSY; } + list_del_rcu(&doi_def->list); spin_unlock(&cipso_v4_doi_list_lock); - return -ENOENT; + cipso_v4_cache_invalidate(); + call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu); + + return 0; } /** - * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition + * cipso_v4_doi_getdef - Returns a reference to a valid DOI definition * @doi: the DOI value * * Description: * Searches for a valid DOI definition and if one is found it is returned to * the caller. Otherwise NULL is returned. The caller must ensure that - * rcu_read_lock() is held while accessing the returned definition. + * rcu_read_lock() is held while accessing the returned definition and the DOI + * definition reference count is decremented when the caller is done. * */ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) { - return cipso_v4_doi_search(doi); + struct cipso_v4_doi *doi_def; + + rcu_read_lock(); + doi_def = cipso_v4_doi_search(doi); + if (doi_def == NULL) + goto doi_getdef_return; + if (!atomic_inc_not_zero(&doi_def->refcount)) + doi_def = NULL; + +doi_getdef_return: + rcu_read_unlock(); + return doi_def; +} + +/** + * cipso_v4_doi_putdef - Releases a reference for the given DOI definition + * @doi_def: the DOI definition + * + * Description: + * Releases a DOI definition reference obtained from cipso_v4_doi_getdef(). + * + */ +void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def) +{ + if (doi_def == NULL) + return; + + if (!atomic_dec_and_test(&doi_def->refcount)) + return; + spin_lock(&cipso_v4_doi_list_lock); + list_del_rcu(&doi_def->list); + spin_unlock(&cipso_v4_doi_list_lock); + + cipso_v4_cache_invalidate(); + call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu); } /** @@ -597,7 +637,7 @@ int cipso_v4_doi_walk(u32 *skip_cnt, rcu_read_lock(); list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) - if (iter_doi->valid) { + if (atomic_read(&iter_doi->refcount) > 0) { if (doi_cnt++ < *skip_cnt) continue; ret_val = callback(iter_doi, cb_arg); @@ -613,85 +653,6 @@ doi_walk_return: return ret_val; } -/** - * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition - * @doi_def: the DOI definition - * @domain: the domain to add - * - * Description: - * Adds the @domain to the DOI specified by @doi_def, this function - * should only be called by external functions (i.e. NetLabel). This function - * does allocate memory. Returns zero on success, negative values on failure. - * - */ -int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) -{ - struct cipso_v4_domhsh_entry *iter; - struct cipso_v4_domhsh_entry *new_dom; - - new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL); - if (new_dom == NULL) - return -ENOMEM; - if (domain) { - new_dom->domain = kstrdup(domain, GFP_KERNEL); - if (new_dom->domain == NULL) { - kfree(new_dom); - return -ENOMEM; - } - } - new_dom->valid = 1; - INIT_RCU_HEAD(&new_dom->rcu); - - spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry(iter, &doi_def->dom_list, list) - if (iter->valid && - ((domain != NULL && iter->domain != NULL && - strcmp(iter->domain, domain) == 0) || - (domain == NULL && iter->domain == NULL))) { - spin_unlock(&cipso_v4_doi_list_lock); - kfree(new_dom->domain); - kfree(new_dom); - return -EEXIST; - } - list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); - spin_unlock(&cipso_v4_doi_list_lock); - - return 0; -} - -/** - * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition - * @doi_def: the DOI definition - * @domain: the domain to remove - * - * Description: - * Removes the @domain from the DOI specified by @doi_def, this function - * should only be called by external functions (i.e. NetLabel). Returns zero - * on success and negative values on error. - * - */ -int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, - const char *domain) -{ - struct cipso_v4_domhsh_entry *iter; - - spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry(iter, &doi_def->dom_list, list) - if (iter->valid && - ((domain != NULL && iter->domain != NULL && - strcmp(iter->domain, domain) == 0) || - (domain == NULL && iter->domain == NULL))) { - iter->valid = 0; - list_del_rcu(&iter->list); - spin_unlock(&cipso_v4_doi_list_lock); - call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); - return 0; - } - spin_unlock(&cipso_v4_doi_list_lock); - - return -ENOENT; -} - /* * Label Mapping Functions */ diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index aaf50032b3a..5c4f60bbc82 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -43,6 +43,7 @@ #include "netlabel_user.h" #include "netlabel_cipso_v4.h" #include "netlabel_mgmt.h" +#include "netlabel_domainhash.h" /* Argument struct for cipso_v4_doi_walk() */ struct netlbl_cipsov4_doiwalk_arg { @@ -51,6 +52,12 @@ struct netlbl_cipsov4_doiwalk_arg { u32 seq; }; +/* Argument struct for netlbl_domhsh_walk() */ +struct netlbl_domhsh_walk_arg { + struct netlbl_audit *audit_info; + u32 doi; +}; + /* NetLabel Generic NETLINK CIPSOv4 family */ static struct genl_family netlbl_cipsov4_gnl_family = { .id = GENL_ID_GENERATE, @@ -80,32 +87,6 @@ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1 * Helper Functions */ -/** - * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition - * @entry: the entry's RCU field - * - * Description: - * This function is designed to be used as a callback to the call_rcu() - * function so that the memory allocated to the DOI definition can be released - * safely. - * - */ -void netlbl_cipsov4_doi_free(struct rcu_head *entry) -{ - struct cipso_v4_doi *ptr; - - ptr = container_of(entry, struct cipso_v4_doi, rcu); - switch (ptr->type) { - case CIPSO_V4_MAP_STD: - kfree(ptr->map.std->lvl.cipso); - kfree(ptr->map.std->lvl.local); - kfree(ptr->map.std->cat.cipso); - kfree(ptr->map.std->cat.local); - break; - } - kfree(ptr); -} - /** * netlbl_cipsov4_add_common - Parse the common sections of a ADD message * @info: the Generic NETLINK info block @@ -342,7 +323,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) add_std_failure: if (doi_def) - netlbl_cipsov4_doi_free(&doi_def->rcu); + cipso_v4_doi_free(doi_def); return ret_val; } @@ -379,7 +360,7 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info) return 0; add_pass_failure: - netlbl_cipsov4_doi_free(&doi_def->rcu); + cipso_v4_doi_free(doi_def); return ret_val; } @@ -667,6 +648,29 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb, return skb->len; } +/** + * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE + * @entry: LSM domain mapping entry + * @arg: the netlbl_domhsh_walk_arg structure + * + * Description: + * This function is intended for use by netlbl_cipsov4_remove() as the callback + * for the netlbl_domhsh_walk() function; it removes LSM domain map entries + * which are associated with the CIPSO DOI specified in @arg. Returns zero on + * success, negative values on failure. + * + */ +static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg) +{ + struct netlbl_domhsh_walk_arg *cb_arg = arg; + + if (entry->type == NETLBL_NLTYPE_CIPSOV4 && + entry->type_def.cipsov4->doi == cb_arg->doi) + return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info); + + return 0; +} + /** * netlbl_cipsov4_remove - Handle a REMOVE message * @skb: the NETLINK buffer @@ -681,8 +685,11 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) { int ret_val = -EINVAL; u32 doi = 0; + struct netlbl_domhsh_walk_arg cb_arg; struct audit_buffer *audit_buf; struct netlbl_audit audit_info; + u32 skip_bkt = 0; + u32 skip_chain = 0; if (!info->attrs[NLBL_CIPSOV4_A_DOI]) return -EINVAL; @@ -690,11 +697,15 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); netlbl_netlink_auditinfo(skb, &audit_info); - ret_val = cipso_v4_doi_remove(doi, - &audit_info, - netlbl_cipsov4_doi_free); - if (ret_val == 0) - atomic_dec(&netlabel_mgmt_protocount); + cb_arg.doi = doi; + cb_arg.audit_info = &audit_info; + ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain, + netlbl_cipsov4_remove_cb, &cb_arg); + if (ret_val == 0 || ret_val == -ENOENT) { + ret_val = cipso_v4_doi_remove(doi, &audit_info); + if (ret_val == 0) + atomic_dec(&netlabel_mgmt_protocount); + } audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index dc42206c431..0243f0c57b4 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -217,20 +217,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, u32 bkt; struct audit_buffer *audit_buf; - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - ret_val = 0; - break; - case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4, - entry->domain); - break; - default: - return -EINVAL; - } - if (ret_val != 0) - return ret_val; - entry->valid = 1; INIT_RCU_HEAD(&entry->rcu); @@ -271,16 +257,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, } rcu_read_unlock(); - if (ret_val != 0) { - switch (entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, - entry->domain) != 0) - BUG(); - break; - } - } - return ret_val; } @@ -302,35 +278,26 @@ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry, } /** - * netlbl_domhsh_remove - Removes an entry from the domain hash table - * @domain: the domain to remove + * netlbl_domhsh_remove_entry - Removes a given entry from the domain table + * @entry: the entry to remove * @audit_info: NetLabel audit information * * Description: * Removes an entry from the domain hash table and handles any updates to the - * lower level protocol handler (i.e. CIPSO). Returns zero on success, - * negative on failure. + * lower level protocol handler (i.e. CIPSO). Caller is responsible for + * ensuring that the RCU read lock is held. Returns zero on success, negative + * on failure. * */ -int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) +int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, + struct netlbl_audit *audit_info) { - int ret_val = -ENOENT; - struct netlbl_dom_map *entry; + int ret_val = 0; struct audit_buffer *audit_buf; - rcu_read_lock(); - if (domain) - entry = netlbl_domhsh_search(domain); - else - entry = netlbl_domhsh_search_def(domain); if (entry == NULL) - goto remove_return; - switch (entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, - entry->domain); - break; - } + return -ENOENT; + spin_lock(&netlbl_domhsh_lock); if (entry->valid) { entry->valid = 0; @@ -338,8 +305,8 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) list_del_rcu(&entry->list); else rcu_assign_pointer(netlbl_domhsh_def, NULL); - ret_val = 0; - } + } else + ret_val = -ENOENT; spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); @@ -351,10 +318,42 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) audit_log_end(audit_buf); } -remove_return: - rcu_read_unlock(); - if (ret_val == 0) + if (ret_val == 0) { + switch (entry->type) { + case NETLBL_NLTYPE_CIPSOV4: + cipso_v4_doi_putdef(entry->type_def.cipsov4); + break; + } call_rcu(&entry->rcu, netlbl_domhsh_free_entry); + } + + return ret_val; +} + +/** + * netlbl_domhsh_remove - Removes an entry from the domain hash table + * @domain: the domain to remove + * @audit_info: NetLabel audit information + * + * Description: + * Removes an entry from the domain hash table and handles any updates to the + * lower level protocol handler (i.e. CIPSO). Returns zero on success, + * negative on failure. + * + */ +int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) +{ + int ret_val; + struct netlbl_dom_map *entry; + + rcu_read_lock(); + if (domain) + entry = netlbl_domhsh_search(domain); + else + entry = netlbl_domhsh_search_def(domain); + ret_val = netlbl_domhsh_remove_entry(entry, audit_info); + rcu_read_unlock(); + return ret_val; } diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h index 8220990ceb9..afcc41a7432 100644 --- a/net/netlabel/netlabel_domainhash.h +++ b/net/netlabel/netlabel_domainhash.h @@ -61,6 +61,8 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, struct netlbl_audit *audit_info); int netlbl_domhsh_add_default(struct netlbl_dom_map *entry, struct netlbl_audit *audit_info); +int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, + struct netlbl_audit *audit_info); int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info); struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 22faba620e4..7d8ecea9391 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -121,10 +121,15 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, struct netlbl_audit *audit_info) { int ret_val = -ENOMEM; + u32 doi; + u32 doi_type; struct netlbl_dom_map *entry; const char *type_str; struct audit_buffer *audit_buf; + doi = doi_def->doi; + doi_type = doi_def->type; + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return -ENOMEM; @@ -133,32 +138,25 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, if (entry->domain == NULL) goto cfg_cipsov4_add_map_failure; } - entry->type = NETLBL_NLTYPE_CIPSOV4; - entry->type_def.cipsov4 = doi_def; - - /* Grab a RCU read lock here so nothing happens to the doi_def variable - * between adding it to the CIPSOv4 protocol engine and adding a - * domain mapping for it. */ - rcu_read_lock(); ret_val = cipso_v4_doi_add(doi_def); if (ret_val != 0) - goto cfg_cipsov4_add_map_failure_unlock; + goto cfg_cipsov4_add_map_failure_remove_doi; + entry->type = NETLBL_NLTYPE_CIPSOV4; + entry->type_def.cipsov4 = cipso_v4_doi_getdef(doi); + if (entry->type_def.cipsov4 == NULL) { + ret_val = -ENOENT; + goto cfg_cipsov4_add_map_failure_remove_doi; + } ret_val = netlbl_domhsh_add(entry, audit_info); if (ret_val != 0) - goto cfg_cipsov4_add_map_failure_remove_doi; - rcu_read_unlock(); - - return 0; + goto cfg_cipsov4_add_map_failure_release_doi; -cfg_cipsov4_add_map_failure_remove_doi: - cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free); -cfg_cipsov4_add_map_failure_unlock: - rcu_read_unlock(); +cfg_cipsov4_add_map_return: audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, audit_info); if (audit_buf != NULL) { - switch (doi_def->type) { + switch (doi_type) { case CIPSO_V4_MAP_STD: type_str = "std"; break; @@ -170,14 +168,21 @@ cfg_cipsov4_add_map_failure_unlock: } audit_log_format(audit_buf, " cipso_doi=%u cipso_type=%s res=%u", - doi_def->doi, type_str, ret_val == 0 ? 1 : 0); + doi, type_str, ret_val == 0 ? 1 : 0); audit_log_end(audit_buf); } + + return ret_val; + +cfg_cipsov4_add_map_failure_release_doi: + cipso_v4_doi_putdef(doi_def); +cfg_cipsov4_add_map_failure_remove_doi: + cipso_v4_doi_remove(doi, audit_info); cfg_cipsov4_add_map_failure: if (entry != NULL) kfree(entry->domain); kfree(entry); - return ret_val; + goto cfg_cipsov4_add_map_return; } /* diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 44be5d5261f..c4e18c7bc0c 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -122,18 +122,12 @@ static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) goto add_failure; tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); - /* We should be holding a rcu_read_lock() here while we hold - * the result but since the entry will always be deleted when - * the CIPSO DOI is deleted we aren't going to keep the - * lock. */ - rcu_read_lock(); entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) { - rcu_read_unlock(); + if (entry->type_def.cipsov4 == NULL) goto add_failure; - } ret_val = netlbl_domhsh_add(entry, &audit_info); - rcu_read_unlock(); + if (ret_val != 0) + cipso_v4_doi_putdef(entry->type_def.cipsov4); break; default: goto add_failure; @@ -294,18 +288,12 @@ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) goto adddef_failure; tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); - /* We should be holding a rcu_read_lock() here while we hold - * the result but since the entry will always be deleted when - * the CIPSO DOI is deleted we aren't going to keep the - * lock. */ - rcu_read_lock(); entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) { - rcu_read_unlock(); + if (entry->type_def.cipsov4 == NULL) goto adddef_failure; - } ret_val = netlbl_domhsh_add_default(entry, &audit_info); - rcu_read_unlock(); + if (ret_val != 0) + cipso_v4_doi_putdef(entry->type_def.cipsov4); break; default: goto adddef_failure; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 271a835fbbe..9733f8eb1a2 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -343,9 +343,11 @@ static void smk_cipso_doi(void) doip->tags[rc] = CIPSO_V4_TAG_INVALID; rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); - if (rc != 0) + if (rc != 0) { printk(KERN_WARNING "%s:%d add rc = %d\n", __func__, __LINE__, rc); + kfree(doip); + } } /** -- GitLab From 61e1068219950c672ce979719ad2be3aadb00d7d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:32 -0400 Subject: [PATCH 3699/5416] netlabel: Add a generic way to create ordered linked lists of network addrs Create an ordered IP address linked list mechanism similar to the core kernel's linked list construct. The idea behind this list functionality is to create an extensibile linked list ordered by IP address mask to ease the matching of network addresses. The linked list is ordered with larger address masks at the front of the list and shorter address masks at the end to facilitate overriding network entries with individual host or subnet entries. Signed-off-by: Paul Moore Reviewed-by: James Morris --- net/netlabel/Makefile | 3 +- net/netlabel/netlabel_addrlist.c | 258 ++++++++++++++++++++++ net/netlabel/netlabel_addrlist.h | 174 +++++++++++++++ net/netlabel/netlabel_unlabeled.c | 350 ++++++++++++------------------ 4 files changed, 569 insertions(+), 216 deletions(-) create mode 100644 net/netlabel/netlabel_addrlist.c create mode 100644 net/netlabel/netlabel_addrlist.h diff --git a/net/netlabel/Makefile b/net/netlabel/Makefile index 8af18c0a47d..ea750e9df65 100644 --- a/net/netlabel/Makefile +++ b/net/netlabel/Makefile @@ -5,7 +5,8 @@ # # base objects -obj-y := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o +obj-y := netlabel_user.o netlabel_kapi.o +obj-y += netlabel_domainhash.o netlabel_addrlist.o # management objects obj-y += netlabel_mgmt.o diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c new file mode 100644 index 00000000000..dd928aa52db --- /dev/null +++ b/net/netlabel/netlabel_addrlist.c @@ -0,0 +1,258 @@ +/* + * NetLabel Network Address Lists + * + * This file contains network address list functions used to manage ordered + * lists of network addresses for use by the NetLabel subsystem. The NetLabel + * system manages static and dynamic label mappings for network protocols such + * as CIPSO and RIPSO. + * + * Author: Paul Moore + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2008 + * + * 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 "netlabel_addrlist.h" + +/* + * Address List Functions + */ + +/** + * netlbl_af4list_search - Search for a matching IPv4 address entry + * @addr: IPv4 address + * @head: the list head + * + * Description: + * Searches the IPv4 address list given by @head. If a matching address entry + * is found it is returned, otherwise NULL is returned. The caller is + * responsible for calling the rcu_read_[un]lock() functions. + * + */ +struct netlbl_af4list *netlbl_af4list_search(__be32 addr, + struct list_head *head) +{ + struct netlbl_af4list *iter; + + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && (addr & iter->mask) == iter->addr) + return iter; + + return NULL; +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +/** + * netlbl_af6list_search - Search for a matching IPv6 address entry + * @addr: IPv6 address + * @head: the list head + * + * Description: + * Searches the IPv6 address list given by @head. If a matching address entry + * is found it is returned, otherwise NULL is returned. The caller is + * responsible for calling the rcu_read_[un]lock() functions. + * + */ +struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, + struct list_head *head) +{ + struct netlbl_af6list *iter; + + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && + ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0) + return iter; + + return NULL; +} +#endif /* IPv6 */ + +/** + * netlbl_af4list_add - Add a new IPv4 address entry to a list + * @entry: address entry + * @head: the list head + * + * Description: + * Add a new address entry to the list pointed to by @head. On success zero is + * returned, otherwise a negative value is returned. The caller is responsible + * for calling the necessary locking functions. + * + */ +int netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head) +{ + struct netlbl_af4list *iter; + + iter = netlbl_af4list_search(entry->addr, head); + if (iter != NULL && + iter->addr == entry->addr && iter->mask == entry->mask) + return -EEXIST; + + /* in order to speed up address searches through the list (the common + * case) we need to keep the list in order based on the size of the + * address mask such that the entry with the widest mask (smallest + * numerical value) appears first in the list */ + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && + ntohl(entry->mask) > ntohl(iter->mask)) { + __list_add_rcu(&entry->list, + iter->list.prev, + &iter->list); + return 0; + } + list_add_tail_rcu(&entry->list, head); + return 0; +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +/** + * netlbl_af6list_add - Add a new IPv6 address entry to a list + * @entry: address entry + * @head: the list head + * + * Description: + * Add a new address entry to the list pointed to by @head. On success zero is + * returned, otherwise a negative value is returned. The caller is responsible + * for calling the necessary locking functions. + * + */ +int netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head) +{ + struct netlbl_af6list *iter; + + iter = netlbl_af6list_search(&entry->addr, head); + if (iter != NULL && + ipv6_addr_equal(&iter->addr, &entry->addr) && + ipv6_addr_equal(&iter->mask, &entry->mask)) + return -EEXIST; + + /* in order to speed up address searches through the list (the common + * case) we need to keep the list in order based on the size of the + * address mask such that the entry with the widest mask (smallest + * numerical value) appears first in the list */ + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && + ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) { + __list_add_rcu(&entry->list, + iter->list.prev, + &iter->list); + return 0; + } + list_add_tail_rcu(&entry->list, head); + return 0; +} +#endif /* IPv6 */ + +/** + * netlbl_af4list_remove_entry - Remove an IPv4 address entry + * @entry: address entry + * + * Description: + * Remove the specified IP address entry. The caller is responsible for + * calling the necessary locking functions. + * + */ +void netlbl_af4list_remove_entry(struct netlbl_af4list *entry) +{ + entry->valid = 0; + list_del_rcu(&entry->list); +} + +/** + * netlbl_af4list_remove - Remove an IPv4 address entry + * @addr: IP address + * @mask: IP address mask + * @head: the list head + * + * Description: + * Remove an IP address entry from the list pointed to by @head. Returns the + * entry on success, NULL on failure. The caller is responsible for calling + * the necessary locking functions. + * + */ +struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, + struct list_head *head) +{ + struct netlbl_af4list *entry; + + entry = netlbl_af4list_search(addr, head); + if (entry != NULL && entry->addr == addr && entry->mask == mask) { + netlbl_af4list_remove_entry(entry); + return entry; + } + + return NULL; +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +/** + * netlbl_af6list_remove_entry - Remove an IPv6 address entry + * @entry: address entry + * + * Description: + * Remove the specified IP address entry. The caller is responsible for + * calling the necessary locking functions. + * + */ +void netlbl_af6list_remove_entry(struct netlbl_af6list *entry) +{ + entry->valid = 0; + list_del_rcu(&entry->list); +} + +/** + * netlbl_af6list_remove - Remove an IPv6 address entry + * @addr: IP address + * @mask: IP address mask + * @head: the list head + * + * Description: + * Remove an IP address entry from the list pointed to by @head. Returns the + * entry on success, NULL on failure. The caller is responsible for calling + * the necessary locking functions. + * + */ +struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, + const struct in6_addr *mask, + struct list_head *head) +{ + struct netlbl_af6list *entry; + + entry = netlbl_af6list_search(addr, head); + if (entry != NULL && + ipv6_addr_equal(&entry->addr, addr) && + ipv6_addr_equal(&entry->mask, mask)) { + netlbl_af6list_remove_entry(entry); + return entry; + } + + return NULL; +} +#endif /* IPv6 */ diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h new file mode 100644 index 00000000000..0c41df057fa --- /dev/null +++ b/net/netlabel/netlabel_addrlist.h @@ -0,0 +1,174 @@ +/* + * NetLabel Network Address Lists + * + * This file contains network address list functions used to manage ordered + * lists of network addresses for use by the NetLabel subsystem. The NetLabel + * system manages static and dynamic label mappings for network protocols such + * as CIPSO and RIPSO. + * + * Author: Paul Moore + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2008 + * + * 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 + * + */ + +#ifndef _NETLABEL_ADDRLIST_H +#define _NETLABEL_ADDRLIST_H + +#include +#include +#include +#include + +/** + * struct netlbl_af4list - NetLabel IPv4 address list + * @addr: IPv4 address + * @mask: IPv4 address mask + * @valid: valid flag + * @list: list structure, used internally + */ +struct netlbl_af4list { + __be32 addr; + __be32 mask; + + u32 valid; + struct list_head list; +}; + +/** + * struct netlbl_af6list - NetLabel IPv6 address list + * @addr: IPv6 address + * @mask: IPv6 address mask + * @valid: valid flag + * @list: list structure, used internally + */ +struct netlbl_af6list { + struct in6_addr addr; + struct in6_addr mask; + + u32 valid; + struct list_head list; +}; + +#define __af4list_entry(ptr) container_of(ptr, struct netlbl_af4list, list) + +static inline struct netlbl_af4list *__af4list_valid(struct list_head *s, + struct list_head *h) +{ + struct list_head *i = s; + struct netlbl_af4list *n = __af4list_entry(s); + while (i != h && !n->valid) { + i = i->next; + n = __af4list_entry(i); + } + return n; +} + +static inline struct netlbl_af4list *__af4list_valid_rcu(struct list_head *s, + struct list_head *h) +{ + struct list_head *i = s; + struct netlbl_af4list *n = __af4list_entry(s); + while (i != h && !n->valid) { + i = rcu_dereference(i->next); + n = __af4list_entry(i); + } + return n; +} + +#define netlbl_af4list_foreach(iter, head) \ + for (iter = __af4list_valid((head)->next, head); \ + prefetch(iter->list.next), &iter->list != (head); \ + iter = __af4list_valid(iter->list.next, head)) + +#define netlbl_af4list_foreach_rcu(iter, head) \ + for (iter = __af4list_valid_rcu((head)->next, head); \ + prefetch(iter->list.next), &iter->list != (head); \ + iter = __af4list_valid_rcu(iter->list.next, head)) + +#define netlbl_af4list_foreach_safe(iter, tmp, head) \ + for (iter = __af4list_valid((head)->next, head), \ + tmp = __af4list_valid(iter->list.next, head); \ + &iter->list != (head); \ + iter = tmp, tmp = __af4list_valid(iter->list.next, head)) + +int netlbl_af4list_add(struct netlbl_af4list *entry, + struct list_head *head); +struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, + struct list_head *head); +void netlbl_af4list_remove_entry(struct netlbl_af4list *entry); +struct netlbl_af4list *netlbl_af4list_search(__be32 addr, + struct list_head *head); + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + +#define __af6list_entry(ptr) container_of(ptr, struct netlbl_af6list, list) + +static inline struct netlbl_af6list *__af6list_valid(struct list_head *s, + struct list_head *h) +{ + struct list_head *i = s; + struct netlbl_af6list *n = __af6list_entry(s); + while (i != h && !n->valid) { + i = i->next; + n = __af6list_entry(i); + } + return n; +} + +static inline struct netlbl_af6list *__af6list_valid_rcu(struct list_head *s, + struct list_head *h) +{ + struct list_head *i = s; + struct netlbl_af6list *n = __af6list_entry(s); + while (i != h && !n->valid) { + i = rcu_dereference(i->next); + n = __af6list_entry(i); + } + return n; +} + +#define netlbl_af6list_foreach(iter, head) \ + for (iter = __af6list_valid((head)->next, head); \ + prefetch(iter->list.next), &iter->list != (head); \ + iter = __af6list_valid(iter->list.next, head)) + +#define netlbl_af6list_foreach_rcu(iter, head) \ + for (iter = __af6list_valid_rcu((head)->next, head); \ + prefetch(iter->list.next), &iter->list != (head); \ + iter = __af6list_valid_rcu(iter->list.next, head)) + +#define netlbl_af6list_foreach_safe(iter, tmp, head) \ + for (iter = __af6list_valid((head)->next, head), \ + tmp = __af6list_valid(iter->list.next, head); \ + &iter->list != (head); \ + iter = tmp, tmp = __af6list_valid(iter->list.next, head)) + +int netlbl_af6list_add(struct netlbl_af6list *entry, + struct list_head *head); +struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, + const struct in6_addr *mask, + struct list_head *head); +void netlbl_af6list_remove_entry(struct netlbl_af6list *entry); +struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, + struct list_head *head); +#endif /* IPV6 */ + +#endif diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index cc105a10e3f..ab8131a8e48 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008 * * 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 @@ -54,6 +54,7 @@ #include #include "netlabel_user.h" +#include "netlabel_addrlist.h" #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" #include "netlabel_mgmt.h" @@ -76,22 +77,20 @@ struct netlbl_unlhsh_tbl { struct list_head *tbl; u32 size; }; +#define netlbl_unlhsh_addr4_entry(iter) \ + container_of(iter, struct netlbl_unlhsh_addr4, list) struct netlbl_unlhsh_addr4 { - __be32 addr; - __be32 mask; u32 secid; - u32 valid; - struct list_head list; + struct netlbl_af4list list; struct rcu_head rcu; }; +#define netlbl_unlhsh_addr6_entry(iter) \ + container_of(iter, struct netlbl_unlhsh_addr6, list) struct netlbl_unlhsh_addr6 { - struct in6_addr addr; - struct in6_addr mask; u32 secid; - u32 valid; - struct list_head list; + struct netlbl_af6list list; struct rcu_head rcu; }; struct netlbl_unlhsh_iface { @@ -274,26 +273,28 @@ static void netlbl_unlhsh_free_addr6(struct rcu_head *entry) static void netlbl_unlhsh_free_iface(struct rcu_head *entry) { struct netlbl_unlhsh_iface *iface; - struct netlbl_unlhsh_addr4 *iter4; - struct netlbl_unlhsh_addr4 *tmp4; - struct netlbl_unlhsh_addr6 *iter6; - struct netlbl_unlhsh_addr6 *tmp6; + struct netlbl_af4list *iter4; + struct netlbl_af4list *tmp4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *iter6; + struct netlbl_af6list *tmp6; +#endif /* IPv6 */ iface = container_of(entry, struct netlbl_unlhsh_iface, rcu); /* no need for locks here since we are the only one with access to this * structure */ - list_for_each_entry_safe(iter4, tmp4, &iface->addr4_list, list) - if (iter4->valid) { - list_del_rcu(&iter4->list); - kfree(iter4); - } - list_for_each_entry_safe(iter6, tmp6, &iface->addr6_list, list) - if (iter6->valid) { - list_del_rcu(&iter6->list); - kfree(iter6); - } + netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) { + netlbl_af4list_remove_entry(iter4); + kfree(netlbl_unlhsh_addr4_entry(iter4)); + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) { + netlbl_af6list_remove_entry(iter6); + kfree(netlbl_unlhsh_addr6_entry(iter6)); + } +#endif /* IPv6 */ kfree(iface); } @@ -315,59 +316,6 @@ static u32 netlbl_unlhsh_hash(int ifindex) return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1); } -/** - * netlbl_unlhsh_search_addr4 - Search for a matching IPv4 address entry - * @addr: IPv4 address - * @iface: the network interface entry - * - * Description: - * Searches the IPv4 address list of the network interface specified by @iface. - * If a matching address entry is found it is returned, otherwise NULL is - * returned. The caller is responsible for calling the rcu_read_[un]lock() - * functions. - * - */ -static struct netlbl_unlhsh_addr4 *netlbl_unlhsh_search_addr4( - __be32 addr, - const struct netlbl_unlhsh_iface *iface) -{ - struct netlbl_unlhsh_addr4 *iter; - - list_for_each_entry_rcu(iter, &iface->addr4_list, list) - if (iter->valid && (addr & iter->mask) == iter->addr) - return iter; - - return NULL; -} - -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -/** - * netlbl_unlhsh_search_addr6 - Search for a matching IPv6 address entry - * @addr: IPv6 address - * @iface: the network interface entry - * - * Description: - * Searches the IPv6 address list of the network interface specified by @iface. - * If a matching address entry is found it is returned, otherwise NULL is - * returned. The caller is responsible for calling the rcu_read_[un]lock() - * functions. - * - */ -static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6( - const struct in6_addr *addr, - const struct netlbl_unlhsh_iface *iface) -{ - struct netlbl_unlhsh_addr6 *iter; - - list_for_each_entry_rcu(iter, &iface->addr6_list, list) - if (iter->valid && - ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0) - return iter; - - return NULL; -} -#endif /* IPv6 */ - /** * netlbl_unlhsh_search_iface - Search for a matching interface entry * @ifindex: the network interface @@ -439,43 +387,26 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, const struct in_addr *mask, u32 secid) { + int ret_val; struct netlbl_unlhsh_addr4 *entry; - struct netlbl_unlhsh_addr4 *iter; entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return -ENOMEM; - entry->addr = addr->s_addr & mask->s_addr; - entry->mask = mask->s_addr; - entry->secid = secid; - entry->valid = 1; + entry->list.addr = addr->s_addr & mask->s_addr; + entry->list.mask = mask->s_addr; + entry->list.valid = 1; INIT_RCU_HEAD(&entry->rcu); + entry->secid = secid; spin_lock(&netlbl_unlhsh_lock); - iter = netlbl_unlhsh_search_addr4(entry->addr, iface); - if (iter != NULL && - iter->addr == addr->s_addr && iter->mask == mask->s_addr) { - spin_unlock(&netlbl_unlhsh_lock); - kfree(entry); - return -EEXIST; - } - /* in order to speed up address searches through the list (the common - * case) we need to keep the list in order based on the size of the - * address mask such that the entry with the widest mask (smallest - * numerical value) appears first in the list */ - list_for_each_entry_rcu(iter, &iface->addr4_list, list) - if (iter->valid && - ntohl(entry->mask) > ntohl(iter->mask)) { - __list_add_rcu(&entry->list, - iter->list.prev, - &iter->list); - spin_unlock(&netlbl_unlhsh_lock); - return 0; - } - list_add_tail_rcu(&entry->list, &iface->addr4_list); + ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list); spin_unlock(&netlbl_unlhsh_lock); - return 0; + + if (ret_val != 0) + kfree(entry); + return ret_val; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -498,47 +429,29 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, const struct in6_addr *mask, u32 secid) { + int ret_val; struct netlbl_unlhsh_addr6 *entry; - struct netlbl_unlhsh_addr6 *iter; entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return -ENOMEM; - ipv6_addr_copy(&entry->addr, addr); - entry->addr.s6_addr32[0] &= mask->s6_addr32[0]; - entry->addr.s6_addr32[1] &= mask->s6_addr32[1]; - entry->addr.s6_addr32[2] &= mask->s6_addr32[2]; - entry->addr.s6_addr32[3] &= mask->s6_addr32[3]; - ipv6_addr_copy(&entry->mask, mask); - entry->secid = secid; - entry->valid = 1; + ipv6_addr_copy(&entry->list.addr, addr); + entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; + entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; + entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; + entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; + ipv6_addr_copy(&entry->list.mask, mask); + entry->list.valid = 1; INIT_RCU_HEAD(&entry->rcu); + entry->secid = secid; spin_lock(&netlbl_unlhsh_lock); - iter = netlbl_unlhsh_search_addr6(&entry->addr, iface); - if (iter != NULL && - (ipv6_addr_equal(&iter->addr, addr) && - ipv6_addr_equal(&iter->mask, mask))) { - spin_unlock(&netlbl_unlhsh_lock); - kfree(entry); - return -EEXIST; - } - /* in order to speed up address searches through the list (the common - * case) we need to keep the list in order based on the size of the - * address mask such that the entry with the widest mask (smallest - * numerical value) appears first in the list */ - list_for_each_entry_rcu(iter, &iface->addr6_list, list) - if (iter->valid && - ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) { - __list_add_rcu(&entry->list, - iter->list.prev, - &iter->list); - spin_unlock(&netlbl_unlhsh_lock); - return 0; - } - list_add_tail_rcu(&entry->list, &iface->addr6_list); + ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list); spin_unlock(&netlbl_unlhsh_lock); + + if (ret_val != 0) + kfree(entry); return 0; } #endif /* IPv6 */ @@ -719,22 +632,21 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, const struct in_addr *mask, struct netlbl_audit *audit_info) { - int ret_val = -ENOENT; + int ret_val = 0; + struct netlbl_af4list *list_entry; struct netlbl_unlhsh_addr4 *entry; - struct audit_buffer *audit_buf = NULL; + struct audit_buffer *audit_buf; struct net_device *dev; - char *secctx = NULL; + char *secctx; u32 secctx_len; spin_lock(&netlbl_unlhsh_lock); - entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface); - if (entry != NULL && - entry->addr == addr->s_addr && entry->mask == mask->s_addr) { - entry->valid = 0; - list_del_rcu(&entry->list); - ret_val = 0; - } + list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr, + &iface->addr4_list); spin_unlock(&netlbl_unlhsh_lock); + if (list_entry == NULL) + ret_val = -ENOENT; + entry = netlbl_unlhsh_addr4_entry(list_entry); audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, audit_info); @@ -742,12 +654,12 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, dev = dev_get_by_index(net, iface->ifindex); netlbl_unlabel_audit_addr4(audit_buf, (dev != NULL ? dev->name : NULL), - entry->addr, entry->mask); + addr->s_addr, mask->s_addr); if (dev != NULL) dev_put(dev); - if (security_secid_to_secctx(entry->secid, - &secctx, - &secctx_len) == 0) { + if (entry && security_secid_to_secctx(entry->secid, + &secctx, + &secctx_len) == 0) { audit_log_format(audit_buf, " sec_obj=%s", secctx); security_release_secctx(secctx, secctx_len); } @@ -781,23 +693,20 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, const struct in6_addr *mask, struct netlbl_audit *audit_info) { - int ret_val = -ENOENT; + int ret_val = 0; + struct netlbl_af6list *list_entry; struct netlbl_unlhsh_addr6 *entry; - struct audit_buffer *audit_buf = NULL; + struct audit_buffer *audit_buf; struct net_device *dev; - char *secctx = NULL; + char *secctx; u32 secctx_len; spin_lock(&netlbl_unlhsh_lock); - entry = netlbl_unlhsh_search_addr6(addr, iface); - if (entry != NULL && - (ipv6_addr_equal(&entry->addr, addr) && - ipv6_addr_equal(&entry->mask, mask))) { - entry->valid = 0; - list_del_rcu(&entry->list); - ret_val = 0; - } + list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list); spin_unlock(&netlbl_unlhsh_lock); + if (list_entry == NULL) + ret_val = -ENOENT; + entry = netlbl_unlhsh_addr6_entry(list_entry); audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, audit_info); @@ -808,9 +717,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, addr, mask); if (dev != NULL) dev_put(dev); - if (security_secid_to_secctx(entry->secid, - &secctx, - &secctx_len) == 0) { + if (entry && security_secid_to_secctx(entry->secid, + &secctx, + &secctx_len) == 0) { audit_log_format(audit_buf, " sec_obj=%s", secctx); security_release_secctx(secctx, secctx_len); } @@ -836,16 +745,18 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, */ static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) { - struct netlbl_unlhsh_addr4 *iter4; - struct netlbl_unlhsh_addr6 *iter6; + struct netlbl_af4list *iter4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *iter6; +#endif /* IPv6 */ spin_lock(&netlbl_unlhsh_lock); - list_for_each_entry_rcu(iter4, &iface->addr4_list, list) - if (iter4->valid) - goto unlhsh_condremove_failure; - list_for_each_entry_rcu(iter6, &iface->addr6_list, list) - if (iter6->valid) - goto unlhsh_condremove_failure; + netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list) + goto unlhsh_condremove_failure; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list) + goto unlhsh_condremove_failure; +#endif /* IPv6 */ iface->valid = 0; if (iface->ifindex > 0) list_del_rcu(&iface->list); @@ -1349,7 +1260,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, if (addr4) { struct in_addr addr_struct; - addr_struct.s_addr = addr4->addr; + addr_struct.s_addr = addr4->list.addr; ret_val = nla_put(cb_arg->skb, NLBL_UNLABEL_A_IPV4ADDR, sizeof(struct in_addr), @@ -1357,7 +1268,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, if (ret_val != 0) goto list_cb_failure; - addr_struct.s_addr = addr4->mask; + addr_struct.s_addr = addr4->list.mask; ret_val = nla_put(cb_arg->skb, NLBL_UNLABEL_A_IPV4MASK, sizeof(struct in_addr), @@ -1370,14 +1281,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, ret_val = nla_put(cb_arg->skb, NLBL_UNLABEL_A_IPV6ADDR, sizeof(struct in6_addr), - &addr6->addr); + &addr6->list.addr); if (ret_val != 0) goto list_cb_failure; ret_val = nla_put(cb_arg->skb, NLBL_UNLABEL_A_IPV6MASK, sizeof(struct in6_addr), - &addr6->mask); + &addr6->list.mask); if (ret_val != 0) goto list_cb_failure; @@ -1425,9 +1336,11 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, u32 iter_bkt; u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; struct netlbl_unlhsh_iface *iface; - struct netlbl_unlhsh_addr4 *addr4; - struct netlbl_unlhsh_addr6 *addr6; struct list_head *iter_list; + struct netlbl_af4list *addr4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *addr6; +#endif cb_arg.nl_cb = cb; cb_arg.skb = skb; @@ -1442,38 +1355,38 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, if (!iface->valid || iter_chain++ < skip_chain) continue; - list_for_each_entry_rcu(addr4, - &iface->addr4_list, - list) { - if (!addr4->valid || iter_addr4++ < skip_addr4) + netlbl_af4list_foreach_rcu(addr4, + &iface->addr4_list) { + if (iter_addr4++ < skip_addr4) continue; if (netlbl_unlabel_staticlist_gen( - NLBL_UNLABEL_C_STATICLIST, - iface, - addr4, - NULL, - &cb_arg) < 0) { + NLBL_UNLABEL_C_STATICLIST, + iface, + netlbl_unlhsh_addr4_entry(addr4), + NULL, + &cb_arg) < 0) { iter_addr4--; iter_chain--; goto unlabel_staticlist_return; } } - list_for_each_entry_rcu(addr6, - &iface->addr6_list, - list) { - if (!addr6->valid || iter_addr6++ < skip_addr6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(addr6, + &iface->addr6_list) { + if (iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen( - NLBL_UNLABEL_C_STATICLIST, - iface, - NULL, - addr6, - &cb_arg) < 0) { + NLBL_UNLABEL_C_STATICLIST, + iface, + NULL, + netlbl_unlhsh_addr6_entry(addr6), + &cb_arg) < 0) { iter_addr6--; iter_chain--; goto unlabel_staticlist_return; } } +#endif /* IPv6 */ } } @@ -1504,9 +1417,12 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, struct netlbl_unlhsh_iface *iface; u32 skip_addr4 = cb->args[0]; u32 skip_addr6 = cb->args[1]; - u32 iter_addr4 = 0, iter_addr6 = 0; - struct netlbl_unlhsh_addr4 *addr4; - struct netlbl_unlhsh_addr6 *addr6; + u32 iter_addr4 = 0; + struct netlbl_af4list *addr4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + u32 iter_addr6 = 0; + struct netlbl_af6list *addr6; +#endif cb_arg.nl_cb = cb; cb_arg.skb = skb; @@ -1517,30 +1433,32 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, if (iface == NULL || !iface->valid) goto unlabel_staticlistdef_return; - list_for_each_entry_rcu(addr4, &iface->addr4_list, list) { - if (!addr4->valid || iter_addr4++ < skip_addr4) + netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { + if (iter_addr4++ < skip_addr4) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, - iface, - addr4, - NULL, - &cb_arg) < 0) { + iface, + netlbl_unlhsh_addr4_entry(addr4), + NULL, + &cb_arg) < 0) { iter_addr4--; goto unlabel_staticlistdef_return; } } - list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { - if (!addr6->valid || iter_addr6++ < skip_addr6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { + if (iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, - iface, - NULL, - addr6, - &cb_arg) < 0) { + iface, + NULL, + netlbl_unlhsh_addr6_entry(addr6), + &cb_arg) < 0) { iter_addr6--; goto unlabel_staticlistdef_return; } } +#endif /* IPv6 */ unlabel_staticlistdef_return: rcu_read_unlock(); @@ -1718,25 +1636,27 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, switch (family) { case PF_INET: { struct iphdr *hdr4; - struct netlbl_unlhsh_addr4 *addr4; + struct netlbl_af4list *addr4; hdr4 = ip_hdr(skb); - addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface); + addr4 = netlbl_af4list_search(hdr4->saddr, + &iface->addr4_list); if (addr4 == NULL) goto unlabel_getattr_nolabel; - secattr->attr.secid = addr4->secid; + secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; break; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: { struct ipv6hdr *hdr6; - struct netlbl_unlhsh_addr6 *addr6; + struct netlbl_af6list *addr6; hdr6 = ipv6_hdr(skb); - addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface); + addr6 = netlbl_af6list_search(&hdr6->saddr, + &iface->addr6_list); if (addr6 == NULL) goto unlabel_getattr_nolabel; - secattr->attr.secid = addr6->secid; + secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid; break; } #endif /* IPv6 */ -- GitLab From 63c41688743760631188cf0f4ae986a6793ccb0a Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:32 -0400 Subject: [PATCH 3700/5416] netlabel: Add network address selectors to the NetLabel/LSM domain mapping This patch extends the NetLabel traffic labeling capabilities to individual packets based not only on the LSM domain but the by the destination address as well. The changes here only affect the core NetLabel infrastructre, changes to the NetLabel KAPI and individial protocol engines are also required but are split out into a different patch to ease review. Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/netlabel.h | 7 +- net/netlabel/netlabel_addrlist.c | 130 ++++++++++ net/netlabel/netlabel_addrlist.h | 15 ++ net/netlabel/netlabel_domainhash.c | 290 ++++++++++++++++++--- net/netlabel/netlabel_domainhash.h | 38 ++- net/netlabel/netlabel_kapi.c | 7 +- net/netlabel/netlabel_mgmt.c | 398 ++++++++++++++++++++++------- net/netlabel/netlabel_mgmt.h | 59 ++++- net/netlabel/netlabel_unlabeled.c | 96 +------ 9 files changed, 816 insertions(+), 224 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index e16db096126..0729f8ce504 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -9,7 +9,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * 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 @@ -72,8 +72,9 @@ struct cipso_v4_doi; /* NetLabel NETLINK protocol version * 1: initial version * 2: added static labels for unlabeled connections + * 3: network selectors added to the NetLabel/LSM domain mapping */ -#define NETLBL_PROTO_VERSION 2 +#define NETLBL_PROTO_VERSION 3 /* NetLabel NETLINK types/families */ #define NETLBL_NLTYPE_NONE 0 @@ -87,6 +88,8 @@ struct cipso_v4_doi; #define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6" #define NETLBL_NLTYPE_UNLABELED 5 #define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" +#define NETLBL_NLTYPE_ADDRSELECT 6 +#define NETLBL_NLTYPE_ADDRSELECT_NAME "NLBL_ADRSEL" /* * NetLabel - Kernel API for accessing the network packet label mappings. diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c index dd928aa52db..b0925a30335 100644 --- a/net/netlabel/netlabel_addrlist.c +++ b/net/netlabel/netlabel_addrlist.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "netlabel_addrlist.h" @@ -69,6 +70,32 @@ struct netlbl_af4list *netlbl_af4list_search(__be32 addr, return NULL; } +/** + * netlbl_af4list_search_exact - Search for an exact IPv4 address entry + * @addr: IPv4 address + * @mask: IPv4 address mask + * @head: the list head + * + * Description: + * Searches the IPv4 address list given by @head. If an exact match if found + * it is returned, otherwise NULL is returned. The caller is responsible for + * calling the rcu_read_[un]lock() functions. + * + */ +struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, + __be32 mask, + struct list_head *head) +{ + struct netlbl_af4list *iter; + + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && iter->addr == addr && iter->mask == mask) + return iter; + + return NULL; +} + + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_af6list_search - Search for a matching IPv6 address entry @@ -93,6 +120,33 @@ struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, return NULL; } + +/** + * netlbl_af6list_search_exact - Search for an exact IPv6 address entry + * @addr: IPv6 address + * @mask: IPv6 address mask + * @head: the list head + * + * Description: + * Searches the IPv6 address list given by @head. If an exact match if found + * it is returned, otherwise NULL is returned. The caller is responsible for + * calling the rcu_read_[un]lock() functions. + * + */ +struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, + const struct in6_addr *mask, + struct list_head *head) +{ + struct netlbl_af6list *iter; + + list_for_each_entry_rcu(iter, head, list) + if (iter->valid && + ipv6_addr_equal(&iter->addr, addr) && + ipv6_addr_equal(&iter->mask, mask)) + return iter; + + return NULL; +} #endif /* IPv6 */ /** @@ -256,3 +310,79 @@ struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, return NULL; } #endif /* IPv6 */ + +/* + * Audit Helper Functions + */ + +/** + * netlbl_af4list_audit_addr - Audit an IPv4 address + * @audit_buf: audit buffer + * @src: true if source address, false if destination + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv4 address and address mask, if necessary, to @audit_buf. + * + */ +void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, + int src, const char *dev, + __be32 addr, __be32 mask) +{ + u32 mask_val = ntohl(mask); + char *dir = (src ? "src" : "dst"); + + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " %s=" NIPQUAD_FMT, dir, NIPQUAD(addr)); + if (mask_val != 0xffffffff) { + u32 mask_len = 0; + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); + } +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +/** + * netlbl_af6list_audit_addr - Audit an IPv6 address + * @audit_buf: audit buffer + * @src: true if source address, false if destination + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv6 address and address mask, if necessary, to @audit_buf. + * + */ +void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, + int src, + const char *dev, + const struct in6_addr *addr, + const struct in6_addr *mask) +{ + char *dir = (src ? "src" : "dst"); + + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " %s=" NIP6_FMT, dir, NIP6(*addr)); + if (ntohl(mask->s6_addr32[3]) != 0xffffffff) { + u32 mask_len = 0; + u32 mask_val; + int iter = -1; + while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff) + mask_len += 32; + mask_val = ntohl(mask->s6_addr32[iter]); + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); + } +} +#endif /* IPv6 */ diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h index 0c41df057fa..0242bead405 100644 --- a/net/netlabel/netlabel_addrlist.h +++ b/net/netlabel/netlabel_addrlist.h @@ -36,6 +36,7 @@ #include #include #include +#include /** * struct netlbl_af4list - NetLabel IPv4 address list @@ -116,6 +117,12 @@ struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, void netlbl_af4list_remove_entry(struct netlbl_af4list *entry); struct netlbl_af4list *netlbl_af4list_search(__be32 addr, struct list_head *head); +struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, + __be32 mask, + struct list_head *head); +void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, + int src, const char *dev, + __be32 addr, __be32 mask); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -169,6 +176,14 @@ struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, void netlbl_af6list_remove_entry(struct netlbl_af6list *entry); struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, struct list_head *head); +struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, + const struct in6_addr *mask, + struct list_head *head); +void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, + int src, + const char *dev, + const struct in6_addr *addr, + const struct in6_addr *mask); #endif /* IPV6 */ #endif diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0243f0c57b4..5fadf10e5dd 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -11,7 +11,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * 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 @@ -40,6 +40,7 @@ #include #include "netlabel_mgmt.h" +#include "netlabel_addrlist.h" #include "netlabel_domainhash.h" #include "netlabel_user.h" @@ -72,8 +73,28 @@ static struct netlbl_dom_map *netlbl_domhsh_def = NULL; static void netlbl_domhsh_free_entry(struct rcu_head *entry) { struct netlbl_dom_map *ptr; + struct netlbl_af4list *iter4; + struct netlbl_af4list *tmp4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *iter6; + struct netlbl_af6list *tmp6; +#endif /* IPv6 */ ptr = container_of(entry, struct netlbl_dom_map, rcu); + if (ptr->type == NETLBL_NLTYPE_ADDRSELECT) { + netlbl_af4list_foreach_safe(iter4, tmp4, + &ptr->type_def.addrsel->list4) { + netlbl_af4list_remove_entry(iter4); + kfree(netlbl_domhsh_addr4_entry(iter4)); + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_safe(iter6, tmp6, + &ptr->type_def.addrsel->list6) { + netlbl_af6list_remove_entry(iter6); + kfree(netlbl_domhsh_addr6_entry(iter6)); + } +#endif /* IPv6 */ + } kfree(ptr->domain); kfree(ptr); } @@ -156,6 +177,69 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) return entry; } +/** + * netlbl_domhsh_audit_add - Generate an audit entry for an add event + * @entry: the entry being added + * @addr4: the IPv4 address information + * @addr6: the IPv6 address information + * @result: the result code + * @audit_info: NetLabel audit information + * + * Description: + * Generate an audit record for adding a new NetLabel/LSM mapping entry with + * the given information. Caller is responsibile for holding the necessary + * locks. + * + */ +static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, + struct netlbl_af4list *addr4, + struct netlbl_af6list *addr6, + int result, + struct netlbl_audit *audit_info) +{ + struct audit_buffer *audit_buf; + struct cipso_v4_doi *cipsov4 = NULL; + u32 type; + + audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); + if (audit_buf != NULL) { + audit_log_format(audit_buf, " nlbl_domain=%s", + entry->domain ? entry->domain : "(default)"); + if (addr4 != NULL) { + struct netlbl_domaddr4_map *map4; + map4 = netlbl_domhsh_addr4_entry(addr4); + type = map4->type; + cipsov4 = map4->type_def.cipsov4; + netlbl_af4list_audit_addr(audit_buf, 0, NULL, + addr4->addr, addr4->mask); +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + } else if (addr6 != NULL) { + struct netlbl_domaddr6_map *map6; + map6 = netlbl_domhsh_addr6_entry(addr6); + type = map6->type; + netlbl_af6list_audit_addr(audit_buf, 0, NULL, + &addr6->addr, &addr6->mask); +#endif /* IPv6 */ + } else { + type = entry->type; + cipsov4 = entry->type_def.cipsov4; + } + switch (type) { + case NETLBL_NLTYPE_UNLABELED: + audit_log_format(audit_buf, " nlbl_protocol=unlbl"); + break; + case NETLBL_NLTYPE_CIPSOV4: + BUG_ON(cipsov4 == NULL); + audit_log_format(audit_buf, + " nlbl_protocol=cipsov4 cipso_doi=%u", + cipsov4->doi); + break; + } + audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0); + audit_log_end(audit_buf); + } +} + /* * Domain Hash Table Functions */ @@ -213,50 +297,106 @@ int __init netlbl_domhsh_init(u32 size) int netlbl_domhsh_add(struct netlbl_dom_map *entry, struct netlbl_audit *audit_info) { - int ret_val; - u32 bkt; - struct audit_buffer *audit_buf; - - entry->valid = 1; - INIT_RCU_HEAD(&entry->rcu); + int ret_val = 0; + struct netlbl_dom_map *entry_old; + struct netlbl_af4list *iter4; + struct netlbl_af4list *tmp4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *iter6; + struct netlbl_af6list *tmp6; +#endif /* IPv6 */ rcu_read_lock(); + spin_lock(&netlbl_domhsh_lock); - if (entry->domain != NULL) { - bkt = netlbl_domhsh_hash(entry->domain); - if (netlbl_domhsh_search(entry->domain) == NULL) + if (entry->domain != NULL) + entry_old = netlbl_domhsh_search(entry->domain); + else + entry_old = netlbl_domhsh_search_def(entry->domain); + if (entry_old == NULL) { + entry->valid = 1; + INIT_RCU_HEAD(&entry->rcu); + + if (entry->domain != NULL) { + u32 bkt = netlbl_domhsh_hash(entry->domain); list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); - else - ret_val = -EEXIST; - } else { - INIT_LIST_HEAD(&entry->list); - if (rcu_dereference(netlbl_domhsh_def) == NULL) + } else { + INIT_LIST_HEAD(&entry->list); rcu_assign_pointer(netlbl_domhsh_def, entry); - else - ret_val = -EEXIST; - } - spin_unlock(&netlbl_domhsh_lock); - audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); - if (audit_buf != NULL) { - audit_log_format(audit_buf, - " nlbl_domain=%s", - entry->domain ? entry->domain : "(default)"); - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - audit_log_format(audit_buf, " nlbl_protocol=unlbl"); - break; - case NETLBL_NLTYPE_CIPSOV4: - audit_log_format(audit_buf, - " nlbl_protocol=cipsov4 cipso_doi=%u", - entry->type_def.cipsov4->doi); - break; } - audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); - } - rcu_read_unlock(); + if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { + netlbl_af4list_foreach_rcu(iter4, + &entry->type_def.addrsel->list4) + netlbl_domhsh_audit_add(entry, iter4, NULL, + ret_val, audit_info); +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(iter6, + &entry->type_def.addrsel->list6) + netlbl_domhsh_audit_add(entry, NULL, iter6, + ret_val, audit_info); +#endif /* IPv6 */ + } else + netlbl_domhsh_audit_add(entry, NULL, NULL, + ret_val, audit_info); + } else if (entry_old->type == NETLBL_NLTYPE_ADDRSELECT && + entry->type == NETLBL_NLTYPE_ADDRSELECT) { + struct list_head *old_list4; + struct list_head *old_list6; + + old_list4 = &entry_old->type_def.addrsel->list4; + old_list6 = &entry_old->type_def.addrsel->list6; + + /* we only allow the addition of address selectors if all of + * the selectors do not exist in the existing domain map */ + netlbl_af4list_foreach_rcu(iter4, + &entry->type_def.addrsel->list4) + if (netlbl_af4list_search_exact(iter4->addr, + iter4->mask, + old_list4)) { + ret_val = -EEXIST; + goto add_return; + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(iter6, + &entry->type_def.addrsel->list6) + if (netlbl_af6list_search_exact(&iter6->addr, + &iter6->mask, + old_list6)) { + ret_val = -EEXIST; + goto add_return; + } +#endif /* IPv6 */ + + netlbl_af4list_foreach_safe(iter4, tmp4, + &entry->type_def.addrsel->list4) { + netlbl_af4list_remove_entry(iter4); + iter4->valid = 1; + ret_val = netlbl_af4list_add(iter4, old_list4); + netlbl_domhsh_audit_add(entry_old, iter4, NULL, + ret_val, audit_info); + if (ret_val != 0) + goto add_return; + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_safe(iter6, tmp6, + &entry->type_def.addrsel->list6) { + netlbl_af6list_remove_entry(iter6); + iter6->valid = 1; + ret_val = netlbl_af6list_add(iter6, old_list6); + netlbl_domhsh_audit_add(entry_old, NULL, iter6, + ret_val, audit_info); + if (ret_val != 0) + goto add_return; + } +#endif /* IPv6 */ + } else + ret_val = -EINVAL; + +add_return: + spin_unlock(&netlbl_domhsh_lock); + rcu_read_unlock(); return ret_val; } @@ -319,7 +459,19 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, } if (ret_val == 0) { + struct netlbl_af4list *iter4; + struct netlbl_domaddr4_map *map4; + switch (entry->type) { + case NETLBL_NLTYPE_ADDRSELECT: + netlbl_af4list_foreach_rcu(iter4, + &entry->type_def.addrsel->list4) { + map4 = netlbl_domhsh_addr4_entry(iter4); + cipso_v4_doi_putdef(map4->type_def.cipsov4); + } + /* no need to check the IPv6 list since we currently + * support only unlabeled protocols for IPv6 */ + break; case NETLBL_NLTYPE_CIPSOV4: cipso_v4_doi_putdef(entry->type_def.cipsov4); break; @@ -387,6 +539,70 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) return netlbl_domhsh_search_def(domain); } +/** + * netlbl_domhsh_getentry_af4 - Get an entry from the domain hash table + * @domain: the domain name to search for + * @addr: the IP address to search for + * + * Description: + * Look through the domain hash table searching for an entry to match @domain + * and @addr, return a pointer to a copy of the entry or NULL. The caller is + * responsible for ensuring that rcu_read_[un]lock() is called. + * + */ +struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain, + __be32 addr) +{ + struct netlbl_dom_map *dom_iter; + struct netlbl_af4list *addr_iter; + + dom_iter = netlbl_domhsh_search_def(domain); + if (dom_iter == NULL) + return NULL; + if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT) + return NULL; + + addr_iter = netlbl_af4list_search(addr, + &dom_iter->type_def.addrsel->list4); + if (addr_iter == NULL) + return NULL; + + return netlbl_domhsh_addr4_entry(addr_iter); +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +/** + * netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table + * @domain: the domain name to search for + * @addr: the IP address to search for + * + * Description: + * Look through the domain hash table searching for an entry to match @domain + * and @addr, return a pointer to a copy of the entry or NULL. The caller is + * responsible for ensuring that rcu_read_[un]lock() is called. + * + */ +struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain, + const struct in6_addr *addr) +{ + struct netlbl_dom_map *dom_iter; + struct netlbl_af6list *addr_iter; + + dom_iter = netlbl_domhsh_search_def(domain); + if (dom_iter == NULL) + return NULL; + if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT) + return NULL; + + addr_iter = netlbl_af6list_search(addr, + &dom_iter->type_def.addrsel->list6); + if (addr_iter == NULL) + return NULL; + + return netlbl_domhsh_addr6_entry(addr_iter); +} +#endif /* IPv6 */ + /** * netlbl_domhsh_walk - Iterate through the domain mapping hash table * @skip_bkt: the number of buckets to skip at the start diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h index afcc41a7432..bfcb6763a1a 100644 --- a/net/netlabel/netlabel_domainhash.h +++ b/net/netlabel/netlabel_domainhash.h @@ -11,7 +11,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,16 +36,43 @@ #include #include +#include "netlabel_addrlist.h" + /* Domain hash table size */ /* XXX - currently this number is an uneducated guess */ #define NETLBL_DOMHSH_BITSIZE 7 -/* Domain mapping definition struct */ +/* Domain mapping definition structures */ +#define netlbl_domhsh_addr4_entry(iter) \ + container_of(iter, struct netlbl_domaddr4_map, list) +struct netlbl_domaddr4_map { + u32 type; + union { + struct cipso_v4_doi *cipsov4; + } type_def; + + struct netlbl_af4list list; +}; +#define netlbl_domhsh_addr6_entry(iter) \ + container_of(iter, struct netlbl_domaddr6_map, list) +struct netlbl_domaddr6_map { + u32 type; + + /* NOTE: no 'type_def' union needed at present since we don't currently + * support any IPv6 labeling protocols */ + + struct netlbl_af6list list; +}; +struct netlbl_domaddr_map { + struct list_head list4; + struct list_head list6; +}; struct netlbl_dom_map { char *domain; u32 type; union { struct cipso_v4_doi *cipsov4; + struct netlbl_domaddr_map *addrsel; } type_def; u32 valid; @@ -66,9 +93,16 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info); struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); +struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain, + __be32 addr); int netlbl_domhsh_walk(u32 *skip_bkt, u32 *skip_chain, int (*callback) (struct netlbl_dom_map *entry, void *arg), void *cb_arg); +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain, + const struct in6_addr *addr); +#endif /* IPv6 */ + #endif diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 7d8ecea9391..8b820dc9806 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -419,7 +419,9 @@ int netlbl_enabled(void) * Attach the correct label to the given socket using the security attributes * specified in @secattr. This function requires exclusive access to @sk, * which means it either needs to be in the process of being created or locked. - * Returns zero on success, negative values on failure. + * Returns zero on success, -EDESTADDRREQ if the domain is configured to use + * network address selectors (can't blindly label the socket), and negative + * values on all other failures. * */ int netlbl_sock_setattr(struct sock *sk, @@ -433,6 +435,9 @@ int netlbl_sock_setattr(struct sock *sk, if (dom_entry == NULL) goto socket_setattr_return; switch (dom_entry->type) { + case NETLBL_NLTYPE_ADDRSELECT: + ret_val = -EDESTADDRREQ; + break; case NETLBL_NLTYPE_CIPSOV4: ret_val = cipso_v4_sock_setattr(sk, dom_entry->type_def.cipsov4, diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index c4e18c7bc0c..ee769ecaa13 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * 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 @@ -32,9 +32,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -71,79 +75,336 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { }; /* - * NetLabel Command Handlers + * Helper Functions */ /** * netlbl_mgmt_add - Handle an ADD message - * @skb: the NETLINK buffer * @info: the Generic NETLINK info block + * @audit_info: NetLabel audit information * * Description: - * Process a user generated ADD message and add the domains from the message - * to the hash table. See netlabel.h for a description of the message format. - * Returns zero on success, negative values on failure. + * Helper function for the ADD and ADDDEF messages to add the domain mappings + * from the message to the hash table. See netlabel.h for a description of the + * message format. Returns zero on success, negative values on failure. * */ -static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) +static int netlbl_mgmt_add_common(struct genl_info *info, + struct netlbl_audit *audit_info) { int ret_val = -EINVAL; struct netlbl_dom_map *entry = NULL; - size_t tmp_size; + struct netlbl_domaddr_map *addrmap = NULL; + struct cipso_v4_doi *cipsov4 = NULL; u32 tmp_val; - struct netlbl_audit audit_info; - - if (!info->attrs[NLBL_MGMT_A_DOMAIN] || - !info->attrs[NLBL_MGMT_A_PROTOCOL]) - goto add_failure; - - netlbl_netlink_auditinfo(skb, &audit_info); entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (entry == NULL) { ret_val = -ENOMEM; goto add_failure; } - tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); - entry->domain = kmalloc(tmp_size, GFP_KERNEL); - if (entry->domain == NULL) { - ret_val = -ENOMEM; - goto add_failure; - } entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); - nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); + if (info->attrs[NLBL_MGMT_A_DOMAIN]) { + size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); + entry->domain = kmalloc(tmp_size, GFP_KERNEL); + if (entry->domain == NULL) { + ret_val = -ENOMEM; + goto add_failure; + } + nla_strlcpy(entry->domain, + info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); + } + + /* NOTE: internally we allow/use a entry->type value of + * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users + * to pass that as a protocol value because we need to know the + * "real" protocol */ switch (entry->type) { case NETLBL_NLTYPE_UNLABELED: - ret_val = netlbl_domhsh_add(entry, &audit_info); break; case NETLBL_NLTYPE_CIPSOV4: if (!info->attrs[NLBL_MGMT_A_CV4DOI]) goto add_failure; tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); - entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) + cipsov4 = cipso_v4_doi_getdef(tmp_val); + if (cipsov4 == NULL) goto add_failure; - ret_val = netlbl_domhsh_add(entry, &audit_info); - if (ret_val != 0) - cipso_v4_doi_putdef(entry->type_def.cipsov4); + entry->type_def.cipsov4 = cipsov4; break; default: goto add_failure; } + + if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) { + struct in_addr *addr; + struct in_addr *mask; + struct netlbl_domaddr4_map *map; + + addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); + if (addrmap == NULL) { + ret_val = -ENOMEM; + goto add_failure; + } + INIT_LIST_HEAD(&addrmap->list4); + INIT_LIST_HEAD(&addrmap->list6); + + if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) != + sizeof(struct in_addr)) { + ret_val = -EINVAL; + goto add_failure; + } + if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) != + sizeof(struct in_addr)) { + ret_val = -EINVAL; + goto add_failure; + } + addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]); + mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]); + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) { + ret_val = -ENOMEM; + goto add_failure; + } + map->list.addr = addr->s_addr & mask->s_addr; + map->list.mask = mask->s_addr; + map->list.valid = 1; + map->type = entry->type; + if (cipsov4) + map->type_def.cipsov4 = cipsov4; + + ret_val = netlbl_af4list_add(&map->list, &addrmap->list4); + if (ret_val != 0) { + kfree(map); + goto add_failure; + } + + entry->type = NETLBL_NLTYPE_ADDRSELECT; + entry->type_def.addrsel = addrmap; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) { + struct in6_addr *addr; + struct in6_addr *mask; + struct netlbl_domaddr6_map *map; + + addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); + if (addrmap == NULL) { + ret_val = -ENOMEM; + goto add_failure; + } + INIT_LIST_HEAD(&addrmap->list4); + INIT_LIST_HEAD(&addrmap->list6); + + if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) != + sizeof(struct in6_addr)) { + ret_val = -EINVAL; + goto add_failure; + } + if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) != + sizeof(struct in6_addr)) { + ret_val = -EINVAL; + goto add_failure; + } + addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]); + mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]); + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) { + ret_val = -ENOMEM; + goto add_failure; + } + ipv6_addr_copy(&map->list.addr, addr); + map->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; + map->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; + map->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; + map->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; + ipv6_addr_copy(&map->list.mask, mask); + map->list.valid = 1; + map->type = entry->type; + + ret_val = netlbl_af6list_add(&map->list, &addrmap->list6); + if (ret_val != 0) { + kfree(map); + goto add_failure; + } + + entry->type = NETLBL_NLTYPE_ADDRSELECT; + entry->type_def.addrsel = addrmap; +#endif /* IPv6 */ + } + + ret_val = netlbl_domhsh_add(entry, audit_info); if (ret_val != 0) goto add_failure; return 0; add_failure: + if (cipsov4) + cipso_v4_doi_putdef(cipsov4); if (entry) kfree(entry->domain); + kfree(addrmap); kfree(entry); return ret_val; } +/** + * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry + * @skb: the NETLINK buffer + * @entry: the map entry + * + * Description: + * This function is a helper function used by the LISTALL and LISTDEF command + * handlers. The caller is responsibile for ensuring that the RCU read lock + * is held. Returns zero on success, negative values on failure. + * + */ +static int netlbl_mgmt_listentry(struct sk_buff *skb, + struct netlbl_dom_map *entry) +{ + int ret_val; + struct nlattr *nla_a; + struct nlattr *nla_b; + struct netlbl_af4list *iter4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct netlbl_af6list *iter6; +#endif + + if (entry->domain != NULL) { + ret_val = nla_put_string(skb, + NLBL_MGMT_A_DOMAIN, entry->domain); + if (ret_val != 0) + return ret_val; + } + + switch (entry->type) { + case NETLBL_NLTYPE_ADDRSELECT: + nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST); + if (nla_a == NULL) + return -ENOMEM; + + netlbl_af4list_foreach_rcu(iter4, + &entry->type_def.addrsel->list4) { + struct netlbl_domaddr4_map *map4; + struct in_addr addr_struct; + + nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); + if (nla_b == NULL) + return -ENOMEM; + + addr_struct.s_addr = iter4->addr; + ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR, + sizeof(struct in_addr), + &addr_struct); + if (ret_val != 0) + return ret_val; + addr_struct.s_addr = iter4->mask; + ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK, + sizeof(struct in_addr), + &addr_struct); + if (ret_val != 0) + return ret_val; + map4 = netlbl_domhsh_addr4_entry(iter4); + ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, + map4->type); + if (ret_val != 0) + return ret_val; + switch (map4->type) { + case NETLBL_NLTYPE_CIPSOV4: + ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, + map4->type_def.cipsov4->doi); + if (ret_val != 0) + return ret_val; + break; + } + + nla_nest_end(skb, nla_b); + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + netlbl_af6list_foreach_rcu(iter6, + &entry->type_def.addrsel->list6) { + struct netlbl_domaddr6_map *map6; + + nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); + if (nla_b == NULL) + return -ENOMEM; + + ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR, + sizeof(struct in6_addr), + &iter6->addr); + if (ret_val != 0) + return ret_val; + ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK, + sizeof(struct in6_addr), + &iter6->mask); + if (ret_val != 0) + return ret_val; + map6 = netlbl_domhsh_addr6_entry(iter6); + ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, + map6->type); + if (ret_val != 0) + return ret_val; + + nla_nest_end(skb, nla_b); + } +#endif /* IPv6 */ + + nla_nest_end(skb, nla_a); + break; + case NETLBL_NLTYPE_UNLABELED: + ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); + break; + case NETLBL_NLTYPE_CIPSOV4: + ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); + if (ret_val != 0) + return ret_val; + ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, + entry->type_def.cipsov4->doi); + break; + } + + return ret_val; +} + +/* + * NetLabel Command Handlers + */ + +/** + * netlbl_mgmt_add - Handle an ADD message + * @skb: the NETLINK buffer + * @info: the Generic NETLINK info block + * + * Description: + * Process a user generated ADD message and add the domains from the message + * to the hash table. See netlabel.h for a description of the message format. + * Returns zero on success, negative values on failure. + * + */ +static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) +{ + struct netlbl_audit audit_info; + + if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) || + (!info->attrs[NLBL_MGMT_A_PROTOCOL]) || + (info->attrs[NLBL_MGMT_A_IPV4ADDR] && + info->attrs[NLBL_MGMT_A_IPV6ADDR]) || + (info->attrs[NLBL_MGMT_A_IPV4MASK] && + info->attrs[NLBL_MGMT_A_IPV6MASK]) || + ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ + (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || + ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ + (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) + return -EINVAL; + + netlbl_netlink_auditinfo(skb, &audit_info); + + return netlbl_mgmt_add_common(info, &audit_info); +} + /** * netlbl_mgmt_remove - Handle a REMOVE message * @skb: the NETLINK buffer @@ -192,23 +453,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) if (data == NULL) goto listall_cb_failure; - ret_val = nla_put_string(cb_arg->skb, - NLBL_MGMT_A_DOMAIN, - entry->domain); + ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry); if (ret_val != 0) goto listall_cb_failure; - ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type); - if (ret_val != 0) - goto listall_cb_failure; - switch (entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - ret_val = nla_put_u32(cb_arg->skb, - NLBL_MGMT_A_CV4DOI, - entry->type_def.cipsov4->doi); - if (ret_val != 0) - goto listall_cb_failure; - break; - } cb_arg->seq++; return genlmsg_end(cb_arg->skb, data); @@ -262,50 +509,22 @@ static int netlbl_mgmt_listall(struct sk_buff *skb, */ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) { - int ret_val = -EINVAL; - struct netlbl_dom_map *entry = NULL; - u32 tmp_val; struct netlbl_audit audit_info; - if (!info->attrs[NLBL_MGMT_A_PROTOCOL]) - goto adddef_failure; + if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) || + (info->attrs[NLBL_MGMT_A_IPV4ADDR] && + info->attrs[NLBL_MGMT_A_IPV6ADDR]) || + (info->attrs[NLBL_MGMT_A_IPV4MASK] && + info->attrs[NLBL_MGMT_A_IPV6MASK]) || + ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ + (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || + ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ + (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) + return -EINVAL; netlbl_netlink_auditinfo(skb, &audit_info); - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) { - ret_val = -ENOMEM; - goto adddef_failure; - } - entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); - - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - ret_val = netlbl_domhsh_add_default(entry, &audit_info); - break; - case NETLBL_NLTYPE_CIPSOV4: - if (!info->attrs[NLBL_MGMT_A_CV4DOI]) - goto adddef_failure; - - tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); - entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) - goto adddef_failure; - ret_val = netlbl_domhsh_add_default(entry, &audit_info); - if (ret_val != 0) - cipso_v4_doi_putdef(entry->type_def.cipsov4); - break; - default: - goto adddef_failure; - } - if (ret_val != 0) - goto adddef_failure; - - return 0; - -adddef_failure: - kfree(entry); - return ret_val; + return netlbl_mgmt_add_common(info, &audit_info); } /** @@ -359,19 +578,10 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) ret_val = -ENOENT; goto listdef_failure_lock; } - ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type); - if (ret_val != 0) - goto listdef_failure_lock; - switch (entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - ret_val = nla_put_u32(ans_skb, - NLBL_MGMT_A_CV4DOI, - entry->type_def.cipsov4->doi); - if (ret_val != 0) - goto listdef_failure_lock; - break; - } + ret_val = netlbl_mgmt_listentry(ans_skb, entry); rcu_read_unlock(); + if (ret_val != 0) + goto listdef_failure; genlmsg_end(ans_skb, data); return genlmsg_reply(ans_skb, info); diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index a43bff169d6..05d96431f81 100644 --- a/net/netlabel/netlabel_mgmt.h +++ b/net/netlabel/netlabel_mgmt.h @@ -45,6 +45,16 @@ * NLBL_MGMT_A_DOMAIN * NLBL_MGMT_A_PROTOCOL * + * If IPv4 is specified the following attributes are required: + * + * NLBL_MGMT_A_IPV4ADDR + * NLBL_MGMT_A_IPV4MASK + * + * If IPv6 is specified the following attributes are required: + * + * NLBL_MGMT_A_IPV6ADDR + * NLBL_MGMT_A_IPV6MASK + * * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: * * NLBL_MGMT_A_CV4DOI @@ -68,13 +78,24 @@ * Required attributes: * * NLBL_MGMT_A_DOMAIN + * + * If the IP address selectors are not used the following attribute is + * required: + * * NLBL_MGMT_A_PROTOCOL * - * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: + * If the IP address selectors are used then the following attritbute is + * required: + * + * NLBL_MGMT_A_SELECTORLIST + * + * If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following + * attributes are required: * * NLBL_MGMT_A_CV4DOI * - * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. + * If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other + * attributes are required. * * o ADDDEF: * Sent by an application to set the default domain mapping for the NetLabel @@ -100,15 +121,23 @@ * application there is no payload. On success the kernel should send a * response using the following format. * - * Required attributes: + * If the IP address selectors are not used the following attribute is + * required: * * NLBL_MGMT_A_PROTOCOL * - * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: + * If the IP address selectors are used then the following attritbute is + * required: + * + * NLBL_MGMT_A_SELECTORLIST + * + * If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following + * attributes are required: * * NLBL_MGMT_A_CV4DOI * - * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. + * If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other + * attributes are required. * * o PROTOCOLS: * Sent by an application to request a list of configured NetLabel protocols @@ -162,6 +191,26 @@ enum { NLBL_MGMT_A_CV4DOI, /* (NLA_U32) * the CIPSOv4 DOI value */ + NLBL_MGMT_A_IPV6ADDR, + /* (NLA_BINARY, struct in6_addr) + * an IPv6 address */ + NLBL_MGMT_A_IPV6MASK, + /* (NLA_BINARY, struct in6_addr) + * an IPv6 address mask */ + NLBL_MGMT_A_IPV4ADDR, + /* (NLA_BINARY, struct in_addr) + * an IPv4 address */ + NLBL_MGMT_A_IPV4MASK, + /* (NLA_BINARY, struct in_addr) + * and IPv4 address mask */ + NLBL_MGMT_A_ADDRSELECTOR, + /* (NLA_NESTED) + * an IP address selector, must contain an address, mask, and protocol + * attribute plus any protocol specific attributes */ + NLBL_MGMT_A_SELECTORLIST, + /* (NLA_NESTED) + * the selector list, there must be at least one + * NLBL_MGMT_A_ADDRSELECTOR attribute */ __NLBL_MGMT_A_MAX, }; #define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1) diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index ab8131a8e48..e8a5c32b0f1 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -145,76 +145,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1 [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY } }; -/* - * Audit Helper Functions - */ - -/** - * netlbl_unlabel_audit_addr4 - Audit an IPv4 address - * @audit_buf: audit buffer - * @dev: network interface - * @addr: IP address - * @mask: IP address mask - * - * Description: - * Write the IPv4 address and address mask, if necessary, to @audit_buf. - * - */ -static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf, - const char *dev, - __be32 addr, __be32 mask) -{ - u32 mask_val = ntohl(mask); - - if (dev != NULL) - audit_log_format(audit_buf, " netif=%s", dev); - audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr)); - if (mask_val != 0xffffffff) { - u32 mask_len = 0; - while (mask_val > 0) { - mask_val <<= 1; - mask_len++; - } - audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); - } -} - -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -/** - * netlbl_unlabel_audit_addr6 - Audit an IPv6 address - * @audit_buf: audit buffer - * @dev: network interface - * @addr: IP address - * @mask: IP address mask - * - * Description: - * Write the IPv6 address and address mask, if necessary, to @audit_buf. - * - */ -static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf, - const char *dev, - const struct in6_addr *addr, - const struct in6_addr *mask) -{ - if (dev != NULL) - audit_log_format(audit_buf, " netif=%s", dev); - audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr)); - if (ntohl(mask->s6_addr32[3]) != 0xffffffff) { - u32 mask_len = 0; - u32 mask_val; - int iter = -1; - while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff) - mask_len += 32; - mask_val = ntohl(mask->s6_addr32[iter]); - while (mask_val > 0) { - mask_val <<= 1; - mask_len++; - } - audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); - } -} -#endif /* IPv6 */ - /* * Unlabeled Connection Hash Table Functions */ @@ -571,10 +501,10 @@ static int netlbl_unlhsh_add(struct net *net, mask4 = (struct in_addr *)mask; ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); if (audit_buf != NULL) - netlbl_unlabel_audit_addr4(audit_buf, - dev_name, - addr4->s_addr, - mask4->s_addr); + netlbl_af4list_audit_addr(audit_buf, 1, + dev_name, + addr4->s_addr, + mask4->s_addr); break; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -585,9 +515,9 @@ static int netlbl_unlhsh_add(struct net *net, mask6 = (struct in6_addr *)mask; ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); if (audit_buf != NULL) - netlbl_unlabel_audit_addr6(audit_buf, - dev_name, - addr6, mask6); + netlbl_af6list_audit_addr(audit_buf, 1, + dev_name, + addr6, mask6); break; } #endif /* IPv6 */ @@ -652,9 +582,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, audit_info); if (audit_buf != NULL) { dev = dev_get_by_index(net, iface->ifindex); - netlbl_unlabel_audit_addr4(audit_buf, - (dev != NULL ? dev->name : NULL), - addr->s_addr, mask->s_addr); + netlbl_af4list_audit_addr(audit_buf, 1, + (dev != NULL ? dev->name : NULL), + addr->s_addr, mask->s_addr); if (dev != NULL) dev_put(dev); if (entry && security_secid_to_secctx(entry->secid, @@ -712,9 +642,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, audit_info); if (audit_buf != NULL) { dev = dev_get_by_index(net, iface->ifindex); - netlbl_unlabel_audit_addr6(audit_buf, - (dev != NULL ? dev->name : NULL), - addr, mask); + netlbl_af6list_audit_addr(audit_buf, 1, + (dev != NULL ? dev->name : NULL), + addr, mask); if (dev != NULL) dev_put(dev); if (entry && security_secid_to_secctx(entry->secid, -- GitLab From 948bf85c1bc9a84754786a9d5dd99b7ecc46451e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:32 -0400 Subject: [PATCH 3701/5416] netlabel: Add functionality to set the security attributes of a packet This patch builds upon the new NetLabel address selector functionality by providing the NetLabel KAPI and CIPSO engine support needed to enable the new packet-based labeling. The only new addition to the NetLabel KAPI at this point is shown below: * int netlbl_skbuff_setattr(skb, family, secattr) ... and is designed to be called from a Netfilter hook after the packet's IP header has been populated such as in the FORWARD or LOCAL_OUT hooks. This patch also provides the necessary SELinux hooks to support this new functionality. Smack support is not currently included due to uncertainty regarding the permissions needed to expand the Smack network access controls. Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/cipso_ipv4.h | 16 ++ include/net/netlabel.h | 9 ++ net/ipv4/cipso_ipv4.c | 222 +++++++++++++++++++++++----- net/netlabel/netlabel_kapi.c | 60 ++++++++ security/selinux/hooks.c | 50 ++++++- security/selinux/include/netlabel.h | 9 ++ security/selinux/include/objsec.h | 1 + security/selinux/netlabel.c | 68 ++++++++- 8 files changed, 393 insertions(+), 42 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 5fe6556fb3c..2ce093ba553 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -208,6 +208,10 @@ int cipso_v4_sock_setattr(struct sock *sk, const struct cipso_v4_doi *doi_def, const struct netlbl_lsm_secattr *secattr); int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); +int cipso_v4_skbuff_setattr(struct sk_buff *skb, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr); +int cipso_v4_skbuff_delattr(struct sk_buff *skb); int cipso_v4_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr); int cipso_v4_validate(unsigned char **option); @@ -232,6 +236,18 @@ static inline int cipso_v4_sock_getattr(struct sock *sk, return -ENOSYS; } +static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) +{ + return -ENOSYS; +} + +static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb) +{ + return -ENOSYS; +} + static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr) { diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 0729f8ce504..3f67e6d49e4 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -382,6 +382,9 @@ int netlbl_sock_setattr(struct sock *sk, const struct netlbl_lsm_secattr *secattr); int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); +int netlbl_skbuff_setattr(struct sk_buff *skb, + u16 family, + const struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, u16 family, struct netlbl_lsm_secattr *secattr); @@ -451,6 +454,12 @@ static inline int netlbl_sock_getattr(struct sock *sk, { return -ENOSYS; } +static inline int netlbl_skbuff_setattr(struct sk_buff *skb, + u16 family, + const struct netlbl_lsm_secattr *secattr) +{ + return -ENOSYS; +} static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, u16 family, struct netlbl_lsm_secattr *secattr) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index bf87eddfec3..e13d6dbb66a 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -13,7 +13,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * 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 @@ -1665,48 +1665,27 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) } /** - * cipso_v4_sock_setattr - Add a CIPSO option to a socket - * @sk: the socket + * cipso_v4_genopt - Generate a CIPSO option + * @buf: the option buffer + * @buf_len: the size of opt_buf * @doi_def: the CIPSO DOI to use - * @secattr: the specific security attributes of the socket + * @secattr: the security attributes * * Description: - * Set the CIPSO option on the given socket using the DOI definition and - * security attributes passed to the function. This function requires - * exclusive access to @sk, which means it either needs to be in the - * process of being created or locked. Returns zero on success and negative - * values on failure. + * Generate a CIPSO option using the DOI definition and security attributes + * passed to the function. Returns the length of the option on success and + * negative values on failure. * */ -int cipso_v4_sock_setattr(struct sock *sk, - const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr) +static int cipso_v4_genopt(unsigned char *buf, u32 buf_len, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) { - int ret_val = -EPERM; + int ret_val; u32 iter; - unsigned char *buf; - u32 buf_len = 0; - u32 opt_len; - struct ip_options *opt = NULL; - struct inet_sock *sk_inet; - struct inet_connection_sock *sk_conn; - - /* In the case of sock_create_lite(), the sock->sk field is not - * defined yet but it is not a problem as the only users of these - * "lite" PF_INET sockets are functions which do an accept() call - * afterwards so we will label the socket as part of the accept(). */ - if (sk == NULL) - return 0; - /* We allocate the maximum CIPSO option size here so we are probably - * being a little wasteful, but it makes our life _much_ easier later - * on and after all we are only talking about 40 bytes. */ - buf_len = CIPSO_V4_OPT_LEN_MAX; - buf = kmalloc(buf_len, GFP_ATOMIC); - if (buf == NULL) { - ret_val = -ENOMEM; - goto socket_setattr_failure; - } + if (buf_len <= CIPSO_V4_HDR_LEN) + return -ENOSPC; /* XXX - This code assumes only one tag per CIPSO option which isn't * really a good assumption to make but since we only support the MAC @@ -1734,8 +1713,7 @@ int cipso_v4_sock_setattr(struct sock *sk, buf_len - CIPSO_V4_HDR_LEN); break; default: - ret_val = -EPERM; - goto socket_setattr_failure; + return -EPERM; } iter++; @@ -1743,9 +1721,58 @@ int cipso_v4_sock_setattr(struct sock *sk, iter < CIPSO_V4_TAG_MAXCNT && doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); if (ret_val < 0) - goto socket_setattr_failure; + return ret_val; cipso_v4_gentag_hdr(doi_def, buf, ret_val); - buf_len = CIPSO_V4_HDR_LEN + ret_val; + return CIPSO_V4_HDR_LEN + ret_val; +} + +/** + * cipso_v4_sock_setattr - Add a CIPSO option to a socket + * @sk: the socket + * @doi_def: the CIPSO DOI to use + * @secattr: the specific security attributes of the socket + * + * Description: + * Set the CIPSO option on the given socket using the DOI definition and + * security attributes passed to the function. This function requires + * exclusive access to @sk, which means it either needs to be in the + * process of being created or locked. Returns zero on success and negative + * values on failure. + * + */ +int cipso_v4_sock_setattr(struct sock *sk, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) +{ + int ret_val = -EPERM; + unsigned char *buf = NULL; + u32 buf_len; + u32 opt_len; + struct ip_options *opt = NULL; + struct inet_sock *sk_inet; + struct inet_connection_sock *sk_conn; + + /* In the case of sock_create_lite(), the sock->sk field is not + * defined yet but it is not a problem as the only users of these + * "lite" PF_INET sockets are functions which do an accept() call + * afterwards so we will label the socket as part of the accept(). */ + if (sk == NULL) + return 0; + + /* We allocate the maximum CIPSO option size here so we are probably + * being a little wasteful, but it makes our life _much_ easier later + * on and after all we are only talking about 40 bytes. */ + buf_len = CIPSO_V4_OPT_LEN_MAX; + buf = kmalloc(buf_len, GFP_ATOMIC); + if (buf == NULL) { + ret_val = -ENOMEM; + goto socket_setattr_failure; + } + + ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr); + if (ret_val < 0) + goto socket_setattr_failure; + buf_len = ret_val; /* We can't use ip_options_get() directly because it makes a call to * ip_options_get_alloc() which allocates memory with GFP_KERNEL and @@ -1853,6 +1880,123 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) secattr); } +/** + * cipso_v4_skbuff_setattr - Set the CIPSO option on a packet + * @skb: the packet + * @secattr: the security attributes + * + * Description: + * Set the CIPSO option on the given packet based on the security attributes. + * Returns a pointer to the IP header on success and NULL on failure. + * + */ +int cipso_v4_skbuff_setattr(struct sk_buff *skb, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + struct iphdr *iph; + struct ip_options *opt = &IPCB(skb)->opt; + unsigned char buf[CIPSO_V4_OPT_LEN_MAX]; + u32 buf_len = CIPSO_V4_OPT_LEN_MAX; + u32 opt_len; + int len_delta; + + buf_len = cipso_v4_genopt(buf, buf_len, doi_def, secattr); + if (buf_len < 0) + return buf_len; + opt_len = (buf_len + 3) & ~3; + + /* we overwrite any existing options to ensure that we have enough + * room for the CIPSO option, the reason is that we _need_ to guarantee + * that the security label is applied to the packet - we do the same + * thing when using the socket options and it hasn't caused a problem, + * if we need to we can always revisit this choice later */ + + len_delta = opt_len - opt->optlen; + /* if we don't ensure enough headroom we could panic on the skb_push() + * call below so make sure we have enough, we are also "mangling" the + * packet so we should probably do a copy-on-write call anyway */ + ret_val = skb_cow(skb, skb_headroom(skb) + len_delta); + if (ret_val < 0) + return ret_val; + + if (len_delta > 0) { + /* we assume that the header + opt->optlen have already been + * "pushed" in ip_options_build() or similar */ + iph = ip_hdr(skb); + skb_push(skb, len_delta); + memmove((char *)iph - len_delta, iph, iph->ihl << 2); + skb_reset_network_header(skb); + iph = ip_hdr(skb); + } else if (len_delta < 0) { + iph = ip_hdr(skb); + memset(iph + 1, IPOPT_NOP, opt->optlen); + } else + iph = ip_hdr(skb); + + if (opt->optlen > 0) + memset(opt, 0, sizeof(*opt)); + opt->optlen = opt_len; + opt->cipso = sizeof(struct iphdr); + opt->is_changed = 1; + + /* we have to do the following because we are being called from a + * netfilter hook which means the packet already has had the header + * fields populated and the checksum calculated - yes this means we + * are doing more work than needed but we do it to keep the core + * stack clean and tidy */ + memcpy(iph + 1, buf, buf_len); + if (opt_len > buf_len) + memset((char *)(iph + 1) + buf_len, 0, opt_len - buf_len); + if (len_delta != 0) { + iph->ihl = 5 + (opt_len >> 2); + iph->tot_len = htons(skb->len); + } + ip_send_check(iph); + + return 0; +} + +/** + * cipso_v4_skbuff_delattr - Delete any CIPSO options from a packet + * @skb: the packet + * + * Description: + * Removes any and all CIPSO options from the given packet. Returns zero on + * success, negative values on failure. + * + */ +int cipso_v4_skbuff_delattr(struct sk_buff *skb) +{ + int ret_val; + struct iphdr *iph; + struct ip_options *opt = &IPCB(skb)->opt; + unsigned char *cipso_ptr; + + if (opt->cipso == 0) + return 0; + + /* since we are changing the packet we should make a copy */ + ret_val = skb_cow(skb, skb_headroom(skb)); + if (ret_val < 0) + return ret_val; + + /* the easiest thing to do is just replace the cipso option with noop + * options since we don't change the size of the packet, although we + * still need to recalculate the checksum */ + + iph = ip_hdr(skb); + cipso_ptr = (unsigned char *)iph + opt->cipso; + memset(cipso_ptr, IPOPT_NOOP, cipso_ptr[1]); + opt->cipso = 0; + opt->is_changed = 1; + + ip_send_check(iph); + + return 0; +} + /** * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option * @skb: the packet diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 8b820dc9806..cc8047d1f50 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -472,6 +472,66 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) return cipso_v4_sock_getattr(sk, secattr); } +/** + * netlbl_skbuff_setattr - Label a packet using the correct protocol + * @skb: the packet + * @family: protocol family + * @secattr: the security attributes + * + * Description: + * Attach the correct label to the given packet using the security attributes + * specified in @secattr. Returns zero on success, negative values on failure. + * + */ +int netlbl_skbuff_setattr(struct sk_buff *skb, + u16 family, + const struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + struct iphdr *hdr4; + struct netlbl_domaddr4_map *af4_entry; + + rcu_read_lock(); + switch (family) { + case AF_INET: + hdr4 = ip_hdr(skb); + af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, + hdr4->daddr); + if (af4_entry == NULL) { + ret_val = -ENOENT; + goto skbuff_setattr_return; + } + switch (af4_entry->type) { + case NETLBL_NLTYPE_CIPSOV4: + ret_val = cipso_v4_skbuff_setattr(skb, + af4_entry->type_def.cipsov4, + secattr); + break; + case NETLBL_NLTYPE_UNLABELED: + /* just delete the protocols we support for right now + * but we could remove other protocols if needed */ + ret_val = cipso_v4_skbuff_delattr(skb); + break; + default: + ret_val = -ENOENT; + } + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + /* since we don't support any IPv6 labeling protocols right + * now we can optimize everything away until we do */ + ret_val = 0; + break; +#endif /* IPv6 */ + default: + ret_val = 0; + } + +skbuff_setattr_return: + rcu_read_unlock(); + return ret_val; +} + /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a91146a6b37..7432bdd5d36 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4407,13 +4407,15 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, u32 peer_sid; struct avc_audit_data ad; u8 secmark_active; + u8 netlbl_active; u8 peerlbl_active; if (!selinux_policycap_netpeer) return NF_ACCEPT; secmark_active = selinux_secmark_enabled(); - peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); + netlbl_active = netlbl_enabled(); + peerlbl_active = netlbl_active || selinux_xfrm_enabled(); if (!secmark_active && !peerlbl_active) return NF_ACCEPT; @@ -4440,6 +4442,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) return NF_DROP; + if (netlbl_active) + /* we do this in the FORWARD path and not the POST_ROUTING + * path because we want to make sure we apply the necessary + * labeling before IPsec is applied so we can leverage AH + * protection */ + if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0) + return NF_DROP; + return NF_ACCEPT; } @@ -4463,6 +4473,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum, } #endif /* IPV6 */ +static unsigned int selinux_ip_output(struct sk_buff *skb, + u16 family) +{ + u32 sid; + + if (!netlbl_enabled()) + return NF_ACCEPT; + + /* we do this in the LOCAL_OUT path and not the POST_ROUTING path + * because we want to make sure we apply the necessary labeling + * before IPsec is applied so we can leverage AH protection */ + if (skb->sk) { + struct sk_security_struct *sksec = skb->sk->sk_security; + sid = sksec->sid; + } else + sid = SECINITSID_KERNEL; + if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0) + return NF_DROP; + + return NF_ACCEPT; +} + +static unsigned int selinux_ipv4_output(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + return selinux_ip_output(skb, PF_INET); +} + static int selinux_ip_postroute_iptables_compat(struct sock *sk, int ifindex, struct avc_audit_data *ad, @@ -5700,6 +5741,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = { .pf = PF_INET, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_SELINUX_FIRST, + }, + { + .hook = selinux_ipv4_output, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_SELINUX_FIRST, } }; diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index d4e3ac8a7fb..b3e6ae071fc 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,6 +48,9 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, u32 *type, u32 *sid); +int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, + u16 family, + u32 sid); void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); int selinux_netlbl_socket_post_create(struct socket *sock); @@ -88,6 +91,12 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, *sid = SECSID_NULL; return 0; } +static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, + u16 family, + u32 sid) +{ + return 0; +} static inline void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 91070ab874c..f46dd1c3d01 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -117,6 +117,7 @@ struct sk_security_struct { NLBL_UNSET = 0, NLBL_REQUIRE, NLBL_LABELED, + NLBL_REQSKB, } nlbl_state; #endif }; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 4053f7fc95f..090404d6e51 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -9,7 +9,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008 * * 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 @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include "objsec.h" #include "security.h" @@ -77,6 +79,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) int rc; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; + struct inet_sock *sk_inet; + struct inet_connection_sock *sk_conn; if (sksec->nlbl_state != NLBL_REQUIRE) return 0; @@ -87,8 +91,29 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) if (rc != 0) goto sock_setsid_return; rc = netlbl_sock_setattr(sk, &secattr); - if (rc == 0) + switch (rc) { + case 0: sksec->nlbl_state = NLBL_LABELED; + break; + case -EDESTADDRREQ: + /* we are going to possibly end up labeling the individual + * packets later which is problematic for stream sockets + * because of the additional IP header size, our solution is to + * allow for the maximum IP header length (40 bytes for IPv4, + * we don't have to worry about IPv6 yet) just in case */ + sk_inet = inet_sk(sk); + if (sk_inet->is_icsk) { + sk_conn = inet_csk(sk); + if (sk_inet->opt) + sk_conn->icsk_ext_hdr_len -= + sk_inet->opt->optlen; + sk_conn->icsk_ext_hdr_len += 40; + sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); + } + sksec->nlbl_state = NLBL_REQSKB; + rc = 0; + break; + } sock_setsid_return: netlbl_secattr_destroy(&secattr); @@ -182,6 +207,45 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, return rc; } +/** + * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid + * @skb: the packet + * @family: protocol family + * @sid: the SID + * + * Description + * Call the NetLabel mechanism to set the label of a packet using @sid. + * Returns zero on auccess, negative values on failure. + * + */ +int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, + u16 family, + u32 sid) +{ + int rc; + struct netlbl_lsm_secattr secattr; + struct sock *sk; + + /* if this is a locally generated packet check to see if it is already + * being labeled by it's parent socket, if it is just exit */ + sk = skb->sk; + if (sk != NULL) { + struct sk_security_struct *sksec = sk->sk_security; + if (sksec->nlbl_state != NLBL_REQSKB) + return 0; + } + + netlbl_secattr_init(&secattr); + rc = security_netlbl_sid_to_secattr(sid, &secattr); + if (rc != 0) + goto skbuff_setsid_return; + rc = netlbl_skbuff_setattr(skb, family, &secattr); + +skbuff_setsid_return: + netlbl_secattr_destroy(&secattr); + return rc; +} + /** * selinux_netlbl_sock_graft - Netlabel the new socket * @sk: the new connection -- GitLab From 014ab19a69c325f52d7bae54ceeda73d6307ae0c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:33 -0400 Subject: [PATCH 3702/5416] selinux: Set socket NetLabel based on connection endpoint Previous work enabled the use of address based NetLabel selectors, which while highly useful, brought the potential for additional per-packet overhead when used. This patch attempts to solve that by applying NetLabel socket labels when sockets are connect()'d. This should alleviate the per-packet NetLabel labeling for all connected sockets (yes, it even works for connected DGRAM sockets). Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/cipso_ipv4.h | 5 + include/net/netlabel.h | 13 +++ net/ipv4/cipso_ipv4.c | 74 ++++++++++++++ net/netlabel/netlabel_kapi.c | 78 ++++++++++++++- security/selinux/hooks.c | 11 ++- security/selinux/include/netlabel.h | 19 +++- security/selinux/include/objsec.h | 1 + security/selinux/netlabel.c | 147 ++++++++++++++++++++++------ 8 files changed, 311 insertions(+), 37 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 2ce093ba553..811febf97ca 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -207,6 +207,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); int cipso_v4_sock_setattr(struct sock *sk, const struct cipso_v4_doi *doi_def, const struct netlbl_lsm_secattr *secattr); +void cipso_v4_sock_delattr(struct sock *sk); int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int cipso_v4_skbuff_setattr(struct sk_buff *skb, const struct cipso_v4_doi *doi_def, @@ -230,6 +231,10 @@ static inline int cipso_v4_sock_setattr(struct sock *sk, return -ENOSYS; } +static inline void cipso_v4_sock_delattr(struct sock *sk) +{ +} + static inline int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 3f67e6d49e4..074cad40ac6 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -380,8 +380,12 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, int netlbl_enabled(void); int netlbl_sock_setattr(struct sock *sk, const struct netlbl_lsm_secattr *secattr); +void netlbl_sock_delattr(struct sock *sk); int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); +int netlbl_conn_setattr(struct sock *sk, + struct sockaddr *addr, + const struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_setattr(struct sk_buff *skb, u16 family, const struct netlbl_lsm_secattr *secattr); @@ -449,11 +453,20 @@ static inline int netlbl_sock_setattr(struct sock *sk, { return -ENOSYS; } +static inline void netlbl_sock_delattr(struct sock *sk) +{ +} static inline int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; } +static inline int netlbl_conn_setattr(struct sock *sk, + struct sockaddr *addr, + const struct netlbl_lsm_secattr *secattr) +{ + return -ENOSYS; +} static inline int netlbl_skbuff_setattr(struct sk_buff *skb, u16 family, const struct netlbl_lsm_secattr *secattr) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index e13d6dbb66a..23768b9d6b6 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1809,6 +1809,80 @@ socket_setattr_failure: return ret_val; } +/** + * cipso_v4_sock_delattr - Delete the CIPSO option from a socket + * @sk: the socket + * + * Description: + * Removes the CIPSO option from a socket, if present. + * + */ +void cipso_v4_sock_delattr(struct sock *sk) +{ + u8 hdr_delta; + struct ip_options *opt; + struct inet_sock *sk_inet; + + sk_inet = inet_sk(sk); + opt = sk_inet->opt; + if (opt == NULL || opt->cipso == 0) + return; + + if (opt->srr || opt->rr || opt->ts || opt->router_alert) { + u8 cipso_len; + u8 cipso_off; + unsigned char *cipso_ptr; + int iter; + int optlen_new; + + cipso_off = opt->cipso - sizeof(struct iphdr); + cipso_ptr = &opt->__data[cipso_off]; + cipso_len = cipso_ptr[1]; + + if (opt->srr > opt->cipso) + opt->srr -= cipso_len; + if (opt->rr > opt->cipso) + opt->rr -= cipso_len; + if (opt->ts > opt->cipso) + opt->ts -= cipso_len; + if (opt->router_alert > opt->cipso) + opt->router_alert -= cipso_len; + opt->cipso = 0; + + memmove(cipso_ptr, cipso_ptr + cipso_len, + opt->optlen - cipso_off - cipso_len); + + /* determining the new total option length is tricky because of + * the padding necessary, the only thing i can think to do at + * this point is walk the options one-by-one, skipping the + * padding at the end to determine the actual option size and + * from there we can determine the new total option length */ + iter = 0; + optlen_new = 0; + while (iter < opt->optlen) + if (opt->__data[iter] != IPOPT_NOP) { + iter += opt->__data[iter + 1]; + optlen_new = iter; + } else + iter++; + hdr_delta = opt->optlen; + opt->optlen = (optlen_new + 3) & ~3; + hdr_delta -= opt->optlen; + } else { + /* only the cipso option was present on the socket so we can + * remove the entire option struct */ + sk_inet->opt = NULL; + hdr_delta = opt->optlen; + kfree(opt); + } + + if (sk_inet->is_icsk && hdr_delta > 0) { + struct inet_connection_sock *sk_conn = inet_csk(sk); + sk_conn->icsk_ext_hdr_len -= hdr_delta; + sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); + } +} + /** * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions * @cipso: the CIPSO v4 option diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index cc8047d1f50..78fc557689b 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 * * 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 @@ -455,6 +455,20 @@ socket_setattr_return: return ret_val; } +/** + * netlbl_sock_delattr - Delete all the NetLabel labels on a socket + * @sk: the socket + * + * Description: + * Remove all the NetLabel labeling from @sk. The caller is responsible for + * ensuring that @sk is locked. + * + */ +void netlbl_sock_delattr(struct sock *sk) +{ + cipso_v4_sock_delattr(sk); +} + /** * netlbl_sock_getattr - Determine the security attributes of a sock * @sk: the sock @@ -472,6 +486,68 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) return cipso_v4_sock_getattr(sk, secattr); } +/** + * netlbl_conn_setattr - Label a connected socket using the correct protocol + * @sk: the socket to label + * @addr: the destination address + * @secattr: the security attributes + * + * Description: + * Attach the correct label to the given connected socket using the security + * attributes specified in @secattr. The caller is responsible for ensuring + * that @sk is locked. Returns zero on success, negative values on failure. + * + */ +int netlbl_conn_setattr(struct sock *sk, + struct sockaddr *addr, + const struct netlbl_lsm_secattr *secattr) +{ + int ret_val; + struct sockaddr_in *addr4; + struct netlbl_domaddr4_map *af4_entry; + + rcu_read_lock(); + switch (addr->sa_family) { + case AF_INET: + addr4 = (struct sockaddr_in *)addr; + af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, + addr4->sin_addr.s_addr); + if (af4_entry == NULL) { + ret_val = -ENOENT; + goto conn_setattr_return; + } + switch (af4_entry->type) { + case NETLBL_NLTYPE_CIPSOV4: + ret_val = cipso_v4_sock_setattr(sk, + af4_entry->type_def.cipsov4, + secattr); + break; + case NETLBL_NLTYPE_UNLABELED: + /* just delete the protocols we support for right now + * but we could remove other protocols if needed */ + cipso_v4_sock_delattr(sk); + ret_val = 0; + break; + default: + ret_val = -ENOENT; + } + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + /* since we don't support any IPv6 labeling protocols right + * now we can optimize everything away until we do */ + ret_val = 0; + break; +#endif /* IPv6 */ + default: + ret_val = 0; + } + +conn_setattr_return: + rcu_read_unlock(); + return ret_val; +} + /** * netlbl_skbuff_setattr - Label a packet using the correct protocol * @skb: the packet diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7432bdd5d36..632ac3e80a6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3794,6 +3794,7 @@ out: static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { + struct sock *sk = sock->sk; struct inode_security_struct *isec; int err; @@ -3807,7 +3808,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, isec = SOCK_INODE(sock)->i_security; if (isec->sclass == SECCLASS_TCP_SOCKET || isec->sclass == SECCLASS_DCCP_SOCKET) { - struct sock *sk = sock->sk; struct avc_audit_data ad; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; @@ -3841,6 +3841,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, goto out; } + err = selinux_netlbl_socket_connect(sk, address); + out: return err; } @@ -4290,8 +4292,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) sk->sk_family == PF_UNIX) isec->sid = sksec->sid; sksec->sclass = isec->sclass; - - selinux_netlbl_sock_graft(sk, parent); } static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, @@ -4342,8 +4342,7 @@ static void selinux_inet_csk_clone(struct sock *newsk, selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); } -static void selinux_inet_conn_established(struct sock *sk, - struct sk_buff *skb) +static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) { u16 family = sk->sk_family; struct sk_security_struct *sksec = sk->sk_security; @@ -4353,6 +4352,8 @@ static void selinux_inet_conn_established(struct sock *sk, family = PF_INET; selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); + + selinux_netlbl_inet_conn_established(sk, family); } static void selinux_req_classify_flow(const struct request_sock *req, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b3e6ae071fc..982bac0ac32 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -52,7 +52,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, u32 sid); -void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); +void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family); int selinux_netlbl_socket_post_create(struct socket *sock); int selinux_netlbl_inode_permission(struct inode *inode, int mask); int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, @@ -62,6 +62,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, int selinux_netlbl_socket_setsockopt(struct socket *sock, int level, int optname); +int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr); + #else static inline void selinux_netlbl_cache_invalidate(void) { @@ -98,8 +100,14 @@ static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, return 0; } -static inline void selinux_netlbl_sock_graft(struct sock *sk, - struct socket *sock) +static inline int selinux_netlbl_conn_setsid(struct sock *sk, + struct sockaddr *addr) +{ + return 0; +} + +static inline void selinux_netlbl_inet_conn_established(struct sock *sk, + u16 family) { return; } @@ -125,6 +133,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock, { return 0; } +static inline int selinux_netlbl_socket_connect(struct sock *sk, + struct sockaddr *addr) +{ + return 0; +} #endif /* CONFIG_NETLABEL */ #endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index f46dd1c3d01..ad34787c6c0 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -118,6 +118,7 @@ struct sk_security_struct { NLBL_REQUIRE, NLBL_LABELED, NLBL_REQSKB, + NLBL_CONNLABELED, } nlbl_state; #endif }; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 090404d6e51..b22b7dafa0e 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -29,10 +29,12 @@ #include #include +#include +#include #include #include -#include -#include +#include +#include #include "objsec.h" #include "security.h" @@ -79,8 +81,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) int rc; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; - struct inet_sock *sk_inet; - struct inet_connection_sock *sk_conn; if (sksec->nlbl_state != NLBL_REQUIRE) return 0; @@ -96,20 +96,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) sksec->nlbl_state = NLBL_LABELED; break; case -EDESTADDRREQ: - /* we are going to possibly end up labeling the individual - * packets later which is problematic for stream sockets - * because of the additional IP header size, our solution is to - * allow for the maximum IP header length (40 bytes for IPv4, - * we don't have to worry about IPv6 yet) just in case */ - sk_inet = inet_sk(sk); - if (sk_inet->is_icsk) { - sk_conn = inet_csk(sk); - if (sk_inet->opt) - sk_conn->icsk_ext_hdr_len -= - sk_inet->opt->optlen; - sk_conn->icsk_ext_hdr_len += 40; - sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); - } sksec->nlbl_state = NLBL_REQSKB; rc = 0; break; @@ -247,21 +233,77 @@ skbuff_setsid_return: } /** - * selinux_netlbl_sock_graft - Netlabel the new socket + * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection * @sk: the new connection - * @sock: the new socket * * Description: - * The connection represented by @sk is being grafted onto @sock so set the - * socket's NetLabel to match the SID of @sk. + * A new connection has been established on @sk so make sure it is labeled + * correctly with the NetLabel susbsystem. * */ -void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) +void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) { - /* Try to set the NetLabel on the socket to save time later, if we fail - * here we will pick up the pieces in later calls to - * selinux_netlbl_inode_permission(). */ - selinux_netlbl_sock_setsid(sk); + int rc; + struct sk_security_struct *sksec = sk->sk_security; + struct netlbl_lsm_secattr secattr; + struct inet_sock *sk_inet = inet_sk(sk); + struct sockaddr_in addr; + + if (sksec->nlbl_state != NLBL_REQUIRE) + return; + + netlbl_secattr_init(&secattr); + if (security_netlbl_sid_to_secattr(sksec->sid, &secattr) != 0) + goto inet_conn_established_return; + + rc = netlbl_sock_setattr(sk, &secattr); + switch (rc) { + case 0: + sksec->nlbl_state = NLBL_LABELED; + break; + case -EDESTADDRREQ: + /* no PF_INET6 support yet because we don't support any IPv6 + * labeling protocols */ + if (family != PF_INET) { + sksec->nlbl_state = NLBL_UNSET; + goto inet_conn_established_return; + } + + addr.sin_family = family; + addr.sin_addr.s_addr = sk_inet->daddr; + if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, + &secattr) != 0) { + /* we failed to label the connected socket (could be + * for a variety of reasons, the actual "why" isn't + * important here) so we have to go to our backup plan, + * labeling the packets individually in the netfilter + * local output hook. this is okay but we need to + * adjust the MSS of the connection to take into + * account any labeling overhead, since we don't know + * the exact overhead at this point we'll use the worst + * case value which is 40 bytes for IPv4 */ + struct inet_connection_sock *sk_conn = inet_csk(sk); + sk_conn->icsk_ext_hdr_len += 40 - + (sk_inet->opt ? sk_inet->opt->optlen : 0); + sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); + + sksec->nlbl_state = NLBL_REQSKB; + } else + sksec->nlbl_state = NLBL_CONNLABELED; + break; + default: + /* note that we are failing to label the socket which could be + * a bad thing since it means traffic could leave the system + * without the desired labeling, however, all is not lost as + * we have a check in selinux_netlbl_inode_permission() to + * pick up the pieces that we might drop here because we can't + * return an error code */ + break; + } + +inet_conn_established_return: + netlbl_secattr_destroy(&secattr); + return; } /** @@ -398,7 +440,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, struct netlbl_lsm_secattr secattr; if (level == IPPROTO_IP && optname == IP_OPTIONS && - sksec->nlbl_state == NLBL_LABELED) { + (sksec->nlbl_state == NLBL_LABELED || + sksec->nlbl_state == NLBL_CONNLABELED)) { netlbl_secattr_init(&secattr); lock_sock(sk); rc = netlbl_sock_getattr(sk, &secattr); @@ -410,3 +453,51 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, return rc; } + +/** + * selinux_netlbl_socket_connect - Label a client-side socket on connect + * @sk: the socket to label + * @addr: the destination address + * + * Description: + * Attempt to label a connected socket with NetLabel using the given address. + * Returns zero values on success, negative values on failure. + * + */ +int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) +{ + int rc; + struct sk_security_struct *sksec = sk->sk_security; + struct netlbl_lsm_secattr secattr; + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) + return 0; + + netlbl_secattr_init(&secattr); + local_bh_disable(); + bh_lock_sock_nested(sk); + + /* connected sockets are allowed to disconnect when the address family + * is set to AF_UNSPEC, if that is what is happening we want to reset + * the socket */ + if (addr->sa_family == AF_UNSPEC) { + netlbl_sock_delattr(sk); + sksec->nlbl_state = NLBL_REQSKB; + rc = 0; + goto socket_connect_return; + } + rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); + if (rc != 0) + goto socket_connect_return; + rc = netlbl_conn_setattr(sk, addr, &secattr); + if (rc != 0) + goto socket_connect_return; + sksec->nlbl_state = NLBL_CONNLABELED; + +socket_connect_return: + bh_unlock_sock(sk); + local_bh_enable(); + netlbl_secattr_destroy(&secattr); + return rc; +} -- GitLab From 6c5b3fc0147f79d714d2fe748b5869d7892ef2e7 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:33 -0400 Subject: [PATCH 3703/5416] selinux: Cache NetLabel secattrs in the socket's security struct Previous work enabled the use of address based NetLabel selectors, which while highly useful, brought the potential for additional per-packet overhead when used. This patch attempts to mitigate some of that overhead by caching the NetLabel security attribute struct within the SELinux socket security structure. This should help eliminate the need to recreate the NetLabel secattr structure for each packet resulting in less overhead. Signed-off-by: Paul Moore Acked-by: James Morris --- security/selinux/hooks.c | 1 + security/selinux/include/netlabel.h | 7 ++ security/selinux/include/objsec.h | 7 +- security/selinux/netlabel.c | 115 +++++++++++++++++++--------- 4 files changed, 91 insertions(+), 39 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 632ac3e80a6..3aa811eba25 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -291,6 +291,7 @@ static void sk_free_security(struct sock *sk) struct sk_security_struct *ssec = sk->sk_security; sk->sk_security = NULL; + selinux_netlbl_sk_security_free(ssec); kfree(ssec); } diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 982bac0ac32..b913c8d0603 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -41,6 +41,7 @@ void selinux_netlbl_cache_invalidate(void); void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); +void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, int family); @@ -77,6 +78,12 @@ static inline void selinux_netlbl_err(struct sk_buff *skb, return; } +static inline void selinux_netlbl_sk_security_free( + struct sk_security_struct *ssec) +{ + return; +} + static inline void selinux_netlbl_sk_security_reset( struct sk_security_struct *ssec, int family) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index ad34787c6c0..f8be8d7fa26 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -109,9 +109,6 @@ struct netport_security_struct { }; struct sk_security_struct { - u32 sid; /* SID of this object */ - u32 peer_sid; /* SID of peer */ - u16 sclass; /* sock security class */ #ifdef CONFIG_NETLABEL enum { /* NetLabel state */ NLBL_UNSET = 0, @@ -120,7 +117,11 @@ struct sk_security_struct { NLBL_REQSKB, NLBL_CONNLABELED, } nlbl_state; + struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */ #endif + u32 sid; /* SID of this object */ + u32 peer_sid; /* SID of peer */ + u16 sclass; /* sock security class */ }; struct key_security_struct { diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index b22b7dafa0e..f58701a7b72 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -67,6 +67,38 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, return rc; } +/** + * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr + * @sk: the socket + * + * Description: + * Generate the NetLabel security attributes for a socket, making full use of + * the socket's attribute cache. Returns a pointer to the security attributes + * on success, NULL on failure. + * + */ +static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) +{ + int rc; + struct sk_security_struct *sksec = sk->sk_security; + struct netlbl_lsm_secattr *secattr; + + if (sksec->nlbl_secattr != NULL) + return sksec->nlbl_secattr; + + secattr = netlbl_secattr_alloc(GFP_ATOMIC); + if (secattr == NULL) + return NULL; + rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); + if (rc != 0) { + netlbl_secattr_free(secattr); + return NULL; + } + sksec->nlbl_secattr = secattr; + + return secattr; +} + /** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label @@ -80,17 +112,15 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) { int rc; struct sk_security_struct *sksec = sk->sk_security; - struct netlbl_lsm_secattr secattr; + struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_state != NLBL_REQUIRE) return 0; - netlbl_secattr_init(&secattr); - - rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); - if (rc != 0) - goto sock_setsid_return; - rc = netlbl_sock_setattr(sk, &secattr); + secattr = selinux_netlbl_sock_genattr(sk); + if (secattr == NULL) + return -ENOMEM; + rc = netlbl_sock_setattr(sk, secattr); switch (rc) { case 0: sksec->nlbl_state = NLBL_LABELED; @@ -101,8 +131,6 @@ static int selinux_netlbl_sock_setsid(struct sock *sk) break; } -sock_setsid_return: - netlbl_secattr_destroy(&secattr); return rc; } @@ -136,6 +164,20 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) netlbl_skbuff_err(skb, error, gateway); } +/** + * selinux_netlbl_sk_security_free - Free the NetLabel fields + * @sssec: the sk_security_struct + * + * Description: + * Free all of the memory in the NetLabel fields of a sk_security_struct. + * + */ +void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) +{ + if (ssec->nlbl_secattr != NULL) + netlbl_secattr_free(ssec->nlbl_secattr); +} + /** * selinux_netlbl_sk_security_reset - Reset the NetLabel fields * @ssec: the sk_security_struct @@ -209,7 +251,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u32 sid) { int rc; - struct netlbl_lsm_secattr secattr; + struct netlbl_lsm_secattr secattr_storage; + struct netlbl_lsm_secattr *secattr = NULL; struct sock *sk; /* if this is a locally generated packet check to see if it is already @@ -219,16 +262,21 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, struct sk_security_struct *sksec = sk->sk_security; if (sksec->nlbl_state != NLBL_REQSKB) return 0; + secattr = sksec->nlbl_secattr; + } + if (secattr == NULL) { + secattr = &secattr_storage; + netlbl_secattr_init(secattr); + rc = security_netlbl_sid_to_secattr(sid, secattr); + if (rc != 0) + goto skbuff_setsid_return; } - netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(sid, &secattr); - if (rc != 0) - goto skbuff_setsid_return; - rc = netlbl_skbuff_setattr(skb, family, &secattr); + rc = netlbl_skbuff_setattr(skb, family, secattr); skbuff_setsid_return: - netlbl_secattr_destroy(&secattr); + if (secattr == &secattr_storage) + netlbl_secattr_destroy(secattr); return rc; } @@ -245,18 +293,18 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) { int rc; struct sk_security_struct *sksec = sk->sk_security; - struct netlbl_lsm_secattr secattr; + struct netlbl_lsm_secattr *secattr; struct inet_sock *sk_inet = inet_sk(sk); struct sockaddr_in addr; if (sksec->nlbl_state != NLBL_REQUIRE) return; - netlbl_secattr_init(&secattr); - if (security_netlbl_sid_to_secattr(sksec->sid, &secattr) != 0) - goto inet_conn_established_return; + secattr = selinux_netlbl_sock_genattr(sk); + if (secattr == NULL) + return; - rc = netlbl_sock_setattr(sk, &secattr); + rc = netlbl_sock_setattr(sk, secattr); switch (rc) { case 0: sksec->nlbl_state = NLBL_LABELED; @@ -266,13 +314,13 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) * labeling protocols */ if (family != PF_INET) { sksec->nlbl_state = NLBL_UNSET; - goto inet_conn_established_return; + return; } addr.sin_family = family; addr.sin_addr.s_addr = sk_inet->daddr; if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, - &secattr) != 0) { + secattr) != 0) { /* we failed to label the connected socket (could be * for a variety of reasons, the actual "why" isn't * important here) so we have to go to our backup plan, @@ -300,10 +348,6 @@ void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) * return an error code */ break; } - -inet_conn_established_return: - netlbl_secattr_destroy(&secattr); - return; } /** @@ -468,13 +512,12 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) { int rc; struct sk_security_struct *sksec = sk->sk_security; - struct netlbl_lsm_secattr secattr; + struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_state != NLBL_REQSKB && sksec->nlbl_state != NLBL_CONNLABELED) return 0; - netlbl_secattr_init(&secattr); local_bh_disable(); bh_lock_sock_nested(sk); @@ -487,17 +530,17 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) rc = 0; goto socket_connect_return; } - rc = security_netlbl_sid_to_secattr(sksec->sid, &secattr); - if (rc != 0) + secattr = selinux_netlbl_sock_genattr(sk); + if (secattr == NULL) { + rc = -ENOMEM; goto socket_connect_return; - rc = netlbl_conn_setattr(sk, addr, &secattr); - if (rc != 0) - goto socket_connect_return; - sksec->nlbl_state = NLBL_CONNLABELED; + } + rc = netlbl_conn_setattr(sk, addr, secattr); + if (rc == 0) + sksec->nlbl_state = NLBL_CONNLABELED; socket_connect_return: bh_unlock_sock(sk); local_bh_enable(); - netlbl_secattr_destroy(&secattr); return rc; } -- GitLab From 8d75899d033617316e06296b7c0729612f56aba0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:33 -0400 Subject: [PATCH 3704/5416] netlabel: Changes to the NetLabel security attributes to allow LSMs to pass full contexts This patch provides support for including the LSM's secid in addition to the LSM's MLS information in the NetLabel security attributes structure. Signed-off-by: Paul Moore Acked-by: James Morris --- include/net/netlabel.h | 2 +- security/selinux/ss/services.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 074cad40ac6..d56517ac3ba 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -203,7 +203,7 @@ struct netlbl_lsm_secattr { u32 type; char *domain; struct netlbl_lsm_cache *cache; - union { + struct { struct { struct netlbl_lsm_secattr_catmap *cat; u32 lvl; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index c8f688a1004..ed0ca649d7d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2803,7 +2803,8 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) rc = -ENOMEM; goto netlbl_sid_to_secattr_failure; } - secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; + secattr->attr.secid = sid; + secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; mls_export_netlbl_lvl(ctx, secattr); rc = mls_export_netlbl_cat(ctx, secattr); if (rc != 0) -- GitLab From 15c45f7b2e81655f6eb500ec949c8bd70a04325a Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:34 -0400 Subject: [PATCH 3705/5416] cipso: Add support for native local labeling and fixup mapping names This patch accomplishes three minor tasks: add a new tag type for local labeling, rename the CIPSO_V4_MAP_STD define to CIPSO_V4_MAP_TRANS and replace some of the CIPSO "magic numbers" with constants from the header file. The first change allows CIPSO to support full LSM labels/contexts, not just MLS attributes. The second change brings the mapping names inline with what userspace is using, compatibility is preserved since we don't actually change the value. The last change is to aid readability and help prevent mistakes. Signed-off-by: Paul Moore --- include/net/cipso_ipv4.h | 13 +++- net/ipv4/cipso_ipv4.c | 127 ++++++++++++++++++++++++++----- net/ipv4/ip_options.c | 2 +- net/netlabel/netlabel_cipso_v4.c | 14 ++-- net/netlabel/netlabel_cipso_v4.h | 4 +- net/netlabel/netlabel_kapi.c | 4 +- 6 files changed, 128 insertions(+), 36 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 811febf97ca..9909774eb99 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -45,7 +45,7 @@ /* known doi values */ #define CIPSO_V4_DOI_UNKNOWN 0x00000000 -/* tag types */ +/* standard tag types */ #define CIPSO_V4_TAG_INVALID 0 #define CIPSO_V4_TAG_RBITMAP 1 #define CIPSO_V4_TAG_ENUM 2 @@ -53,10 +53,14 @@ #define CIPSO_V4_TAG_PBITMAP 6 #define CIPSO_V4_TAG_FREEFORM 7 +/* non-standard tag types (tags > 127) */ +#define CIPSO_V4_TAG_LOCAL 128 + /* doi mapping types */ #define CIPSO_V4_MAP_UNKNOWN 0 -#define CIPSO_V4_MAP_STD 1 +#define CIPSO_V4_MAP_TRANS 1 #define CIPSO_V4_MAP_PASS 2 +#define CIPSO_V4_MAP_LOCAL 3 /* limits */ #define CIPSO_V4_MAX_REM_LVLS 255 @@ -215,7 +219,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb, int cipso_v4_skbuff_delattr(struct sk_buff *skb); int cipso_v4_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr); -int cipso_v4_validate(unsigned char **option); +int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option); #else static inline void cipso_v4_error(struct sk_buff *skb, int error, @@ -259,7 +263,8 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, return -ENOSYS; } -static inline int cipso_v4_validate(unsigned char **option) +static inline int cipso_v4_validate(const struct sk_buff *skb, + unsigned char **option) { return -ENOSYS; } diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 23768b9d6b6..490e035c6d9 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -109,6 +109,19 @@ int cipso_v4_rbm_strictvalid = 1; * be omitted. */ #define CIPSO_V4_TAG_RNG_CAT_MAX 8 +/* Base length of the local tag (non-standard tag). + * Tag definition (may change between kernel versions) + * + * 0 8 16 24 32 + * +----------+----------+----------+----------+ + * | 10000000 | 00000110 | 32-bit secid value | + * +----------+----------+----------+----------+ + * | in (host byte order)| + * +----------+----------+ + * + */ +#define CIPSO_V4_TAG_LOC_BLEN 6 + /* * Helper Functions */ @@ -467,6 +480,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) if (doi_def->type != CIPSO_V4_MAP_PASS) return -EINVAL; break; + case CIPSO_V4_TAG_LOCAL: + if (doi_def->type != CIPSO_V4_MAP_LOCAL) + return -EINVAL; + break; default: return -EINVAL; } @@ -502,7 +519,7 @@ void cipso_v4_doi_free(struct cipso_v4_doi *doi_def) return; switch (doi_def->type) { - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: kfree(doi_def->map.std->lvl.cipso); kfree(doi_def->map.std->lvl.local); kfree(doi_def->map.std->cat.cipso); @@ -673,7 +690,7 @@ static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level) switch (doi_def->type) { case CIPSO_V4_MAP_PASS: return 0; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) return 0; break; @@ -702,7 +719,7 @@ static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, case CIPSO_V4_MAP_PASS: *net_lvl = host_lvl; return 0; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: if (host_lvl < doi_def->map.std->lvl.local_size && doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) { *net_lvl = doi_def->map.std->lvl.local[host_lvl]; @@ -736,7 +753,7 @@ static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, case CIPSO_V4_MAP_PASS: *host_lvl = net_lvl; return 0; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: map_tbl = doi_def->map.std; if (net_lvl < map_tbl->lvl.cipso_size && map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { @@ -773,7 +790,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, switch (doi_def->type) { case CIPSO_V4_MAP_PASS: return 0; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: cipso_cat_size = doi_def->map.std->cat.cipso_size; cipso_array = doi_def->map.std->cat.cipso; for (;;) { @@ -821,7 +838,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, u32 host_cat_size = 0; u32 *host_cat_array = NULL; - if (doi_def->type == CIPSO_V4_MAP_STD) { + if (doi_def->type == CIPSO_V4_MAP_TRANS) { host_cat_size = doi_def->map.std->cat.local_size; host_cat_array = doi_def->map.std->cat.local; } @@ -836,7 +853,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, case CIPSO_V4_MAP_PASS: net_spot = host_spot; break; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: if (host_spot >= host_cat_size) return -EPERM; net_spot = host_cat_array[host_spot]; @@ -882,7 +899,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, u32 net_cat_size = 0; u32 *net_cat_array = NULL; - if (doi_def->type == CIPSO_V4_MAP_STD) { + if (doi_def->type == CIPSO_V4_MAP_TRANS) { net_cat_size = doi_def->map.std->cat.cipso_size; net_cat_array = doi_def->map.std->cat.cipso; } @@ -902,7 +919,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, case CIPSO_V4_MAP_PASS: host_spot = net_spot; break; - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: if (net_spot >= net_cat_size) return -EPERM; host_spot = net_cat_array[net_spot]; @@ -1238,7 +1255,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, } else tag_len = 4; - buffer[0] = 0x01; + buffer[0] = CIPSO_V4_TAG_RBITMAP; buffer[1] = tag_len; buffer[3] = level; @@ -1334,7 +1351,7 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def, } else tag_len = 4; - buffer[0] = 0x02; + buffer[0] = CIPSO_V4_TAG_ENUM; buffer[1] = tag_len; buffer[3] = level; @@ -1430,7 +1447,7 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def, } else tag_len = 4; - buffer[0] = 0x05; + buffer[0] = CIPSO_V4_TAG_RANGE; buffer[1] = tag_len; buffer[3] = level; @@ -1483,6 +1500,54 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, return 0; } +/** + * cipso_v4_gentag_loc - Generate a CIPSO local tag (non-standard) + * @doi_def: the DOI definition + * @secattr: the security attributes + * @buffer: the option buffer + * @buffer_len: length of buffer in bytes + * + * Description: + * Generate a CIPSO option using the local tag. Returns the size of the tag + * on success, negative values on failure. + * + */ +static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr, + unsigned char *buffer, + u32 buffer_len) +{ + if (!(secattr->flags & NETLBL_SECATTR_SECID)) + return -EPERM; + + buffer[0] = CIPSO_V4_TAG_LOCAL; + buffer[1] = CIPSO_V4_TAG_LOC_BLEN; + *(u32 *)&buffer[2] = secattr->attr.secid; + + return CIPSO_V4_TAG_LOC_BLEN; +} + +/** + * cipso_v4_parsetag_loc - Parse a CIPSO local tag + * @doi_def: the DOI definition + * @tag: the CIPSO tag + * @secattr: the security attributes + * + * Description: + * Parse a CIPSO local tag and return the security attributes in @secattr. + * Return zero on success, negatives values on failure. + * + */ +static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, + const unsigned char *tag, + struct netlbl_lsm_secattr *secattr) +{ + secattr->attr.secid = *(u32 *)&tag[2]; + secattr->flags |= NETLBL_SECATTR_SECID; + + return 0; +} + /** * cipso_v4_validate - Validate a CIPSO option * @option: the start of the option, on error it is set to point to the error @@ -1502,7 +1567,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, * that is unrecognized." * */ -int cipso_v4_validate(unsigned char **option) +int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) { unsigned char *opt = *option; unsigned char *tag; @@ -1527,7 +1592,7 @@ int cipso_v4_validate(unsigned char **option) goto validate_return_locked; } - opt_iter = 6; + opt_iter = CIPSO_V4_HDR_LEN; tag = opt + opt_iter; while (opt_iter < opt_len) { for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) @@ -1545,7 +1610,7 @@ int cipso_v4_validate(unsigned char **option) switch (tag[0]) { case CIPSO_V4_TAG_RBITMAP: - if (tag_len < 4) { + if (tag_len < CIPSO_V4_TAG_RBM_BLEN) { err_offset = opt_iter + 1; goto validate_return_locked; } @@ -1563,7 +1628,7 @@ int cipso_v4_validate(unsigned char **option) err_offset = opt_iter + 3; goto validate_return_locked; } - if (tag_len > 4 && + if (tag_len > CIPSO_V4_TAG_RBM_BLEN && cipso_v4_map_cat_rbm_valid(doi_def, &tag[4], tag_len - 4) < 0) { @@ -1573,7 +1638,7 @@ int cipso_v4_validate(unsigned char **option) } break; case CIPSO_V4_TAG_ENUM: - if (tag_len < 4) { + if (tag_len < CIPSO_V4_TAG_ENUM_BLEN) { err_offset = opt_iter + 1; goto validate_return_locked; } @@ -1583,7 +1648,7 @@ int cipso_v4_validate(unsigned char **option) err_offset = opt_iter + 3; goto validate_return_locked; } - if (tag_len > 4 && + if (tag_len > CIPSO_V4_TAG_ENUM_BLEN && cipso_v4_map_cat_enum_valid(doi_def, &tag[4], tag_len - 4) < 0) { @@ -1592,7 +1657,7 @@ int cipso_v4_validate(unsigned char **option) } break; case CIPSO_V4_TAG_RANGE: - if (tag_len < 4) { + if (tag_len < CIPSO_V4_TAG_RNG_BLEN) { err_offset = opt_iter + 1; goto validate_return_locked; } @@ -1602,7 +1667,7 @@ int cipso_v4_validate(unsigned char **option) err_offset = opt_iter + 3; goto validate_return_locked; } - if (tag_len > 4 && + if (tag_len > CIPSO_V4_TAG_RNG_BLEN && cipso_v4_map_cat_rng_valid(doi_def, &tag[4], tag_len - 4) < 0) { @@ -1610,6 +1675,19 @@ int cipso_v4_validate(unsigned char **option) goto validate_return_locked; } break; + case CIPSO_V4_TAG_LOCAL: + /* This is a non-standard tag that we only allow for + * local connections, so if the incoming interface is + * not the loopback device drop the packet. */ + if (!(skb->dev->flags & IFF_LOOPBACK)) { + err_offset = opt_iter; + goto validate_return_locked; + } + if (tag_len != CIPSO_V4_TAG_LOC_BLEN) { + err_offset = opt_iter + 1; + goto validate_return_locked; + } + break; default: err_offset = opt_iter; goto validate_return_locked; @@ -1712,6 +1790,12 @@ static int cipso_v4_genopt(unsigned char *buf, u32 buf_len, &buf[CIPSO_V4_HDR_LEN], buf_len - CIPSO_V4_HDR_LEN); break; + case CIPSO_V4_TAG_LOCAL: + ret_val = cipso_v4_gentag_loc(doi_def, + secattr, + &buf[CIPSO_V4_HDR_LEN], + buf_len - CIPSO_V4_HDR_LEN); + break; default: return -EPERM; } @@ -1921,6 +2005,9 @@ static int cipso_v4_getattr(const unsigned char *cipso, case CIPSO_V4_TAG_RANGE: ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr); break; + case CIPSO_V4_TAG_LOCAL: + ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr); + break; } if (ret_val == 0) secattr->type = NETLBL_NLTYPE_CIPSOV4; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index be3f18a7a40..2c88da6e786 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -438,7 +438,7 @@ int ip_options_compile(struct net *net, goto error; } opt->cipso = optptr - iph; - if (cipso_v4_validate(&optptr)) { + if (cipso_v4_validate(skb, &optptr)) { pp_ptr = optptr; goto error; } diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 5c4f60bbc82..db83a67cbc7 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -132,9 +132,9 @@ static int netlbl_cipsov4_add_common(struct genl_info *info, * @info: the Generic NETLINK info block * * Description: - * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message - * and add it to the CIPSO V4 engine. Return zero on success and non-zero on - * error. + * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD + * message and add it to the CIPSO V4 engine. Return zero on success and + * non-zero on error. * */ static int netlbl_cipsov4_add_std(struct genl_info *info) @@ -164,7 +164,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) ret_val = -ENOMEM; goto add_std_failure; } - doi_def->type = CIPSO_V4_MAP_STD; + doi_def->type = CIPSO_V4_MAP_TRANS; ret_val = netlbl_cipsov4_add_common(info, doi_def); if (ret_val != 0) @@ -393,8 +393,8 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); switch (type) { - case CIPSO_V4_MAP_STD: - type_str = "std"; + case CIPSO_V4_MAP_TRANS: + type_str = "trans"; ret_val = netlbl_cipsov4_add_std(info); break; case CIPSO_V4_MAP_PASS: @@ -497,7 +497,7 @@ list_start: nla_nest_end(ans_skb, nla_a); switch (doi_def->type) { - case CIPSO_V4_MAP_STD: + case CIPSO_V4_MAP_TRANS: nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST); if (nla_a == NULL) { ret_val = -ENOMEM; diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h index 220cb9d06b4..fb3957f1d69 100644 --- a/net/netlabel/netlabel_cipso_v4.h +++ b/net/netlabel/netlabel_cipso_v4.h @@ -45,7 +45,7 @@ * NLBL_CIPSOV4_A_MTYPE * NLBL_CIPSOV4_A_TAGLST * - * If using CIPSO_V4_MAP_STD the following attributes are required: + * If using CIPSO_V4_MAP_TRANS the following attributes are required: * * NLBL_CIPSOV4_A_MLSLVLLST * NLBL_CIPSOV4_A_MLSCATLST @@ -76,7 +76,7 @@ * NLBL_CIPSOV4_A_MTYPE * NLBL_CIPSOV4_A_TAGLST * - * If using CIPSO_V4_MAP_STD the following attributes are required: + * If using CIPSO_V4_MAP_TRANS the following attributes are required: * * NLBL_CIPSOV4_A_MLSLVLLST * NLBL_CIPSOV4_A_MLSCATLST diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 78fc557689b..8435b15c3f7 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -157,8 +157,8 @@ cfg_cipsov4_add_map_return: audit_info); if (audit_buf != NULL) { switch (doi_type) { - case CIPSO_V4_MAP_STD: - type_str = "std"; + case CIPSO_V4_MAP_TRANS: + type_str = "trans"; break; case CIPSO_V4_MAP_PASS: type_str = "pass"; -- GitLab From d91d40799165b0c84c97e7c71fb8039494ff07dc Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Oct 2008 10:16:34 -0400 Subject: [PATCH 3706/5416] netlabel: Add configuration support for local labeling Add the necessary NetLabel support for the new CIPSO mapping, CIPSO_V4_MAP_LOCAL, which allows full LSM label/context support. Signed-off-by: Paul Moore Reviewed-by: James Morris --- include/net/netlabel.h | 3 ++- net/netlabel/netlabel_cipso_v4.c | 41 ++++++++++++++++++++++++++++++++ net/netlabel/netlabel_cipso_v4.h | 6 +++-- net/netlabel/netlabel_kapi.c | 3 +++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index d56517ac3ba..17c442a4514 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -72,7 +72,8 @@ struct cipso_v4_doi; /* NetLabel NETLINK protocol version * 1: initial version * 2: added static labels for unlabeled connections - * 3: network selectors added to the NetLabel/LSM domain mapping + * 3: network selectors added to the NetLabel/LSM domain mapping and the + * CIPSO_V4_MAP_LOCAL CIPSO mapping was added */ #define NETLBL_PROTO_VERSION 3 diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index db83a67cbc7..fff32b70efa 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -364,6 +364,43 @@ add_pass_failure: return ret_val; } +/** + * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition + * @info: the Generic NETLINK info block + * + * Description: + * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD + * message and add it to the CIPSO V4 engine. Return zero on success and + * non-zero on error. + * + */ +static int netlbl_cipsov4_add_local(struct genl_info *info) +{ + int ret_val; + struct cipso_v4_doi *doi_def = NULL; + + if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) + return -EINVAL; + + doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); + if (doi_def == NULL) + return -ENOMEM; + doi_def->type = CIPSO_V4_MAP_LOCAL; + + ret_val = netlbl_cipsov4_add_common(info, doi_def); + if (ret_val != 0) + goto add_local_failure; + + ret_val = cipso_v4_doi_add(doi_def); + if (ret_val != 0) + goto add_local_failure; + return 0; + +add_local_failure: + cipso_v4_doi_free(doi_def); + return ret_val; +} + /** * netlbl_cipsov4_add - Handle an ADD message * @skb: the NETLINK buffer @@ -401,6 +438,10 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) type_str = "pass"; ret_val = netlbl_cipsov4_add_pass(info); break; + case CIPSO_V4_MAP_LOCAL: + type_str = "local"; + ret_val = netlbl_cipsov4_add_local(info); + break; } if (ret_val == 0) atomic_inc(&netlabel_mgmt_protocount); diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h index fb3957f1d69..c8a4079261f 100644 --- a/net/netlabel/netlabel_cipso_v4.h +++ b/net/netlabel/netlabel_cipso_v4.h @@ -50,7 +50,8 @@ * NLBL_CIPSOV4_A_MLSLVLLST * NLBL_CIPSOV4_A_MLSCATLST * - * If using CIPSO_V4_MAP_PASS no additional attributes are required. + * If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes + * are required. * * o REMOVE: * Sent by an application to remove a specific DOI mapping table from the @@ -81,7 +82,8 @@ * NLBL_CIPSOV4_A_MLSLVLLST * NLBL_CIPSOV4_A_MLSCATLST * - * If using CIPSO_V4_MAP_PASS no additional attributes are required. + * If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes + * are required. * * o LISTALL: * This message is sent by an application to list the valid DOIs on the diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 8435b15c3f7..b32eceb3ab0 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -163,6 +163,9 @@ cfg_cipsov4_add_map_return: case CIPSO_V4_MAP_PASS: type_str = "pass"; break; + case CIPSO_V4_MAP_LOCAL: + type_str = "local"; + break; default: type_str = "(unknown)"; } -- GitLab From ed458df4d2470adc02762a87a9ad665d0b1a2bd4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 10 Oct 2008 08:00:17 -0700 Subject: [PATCH 3707/5416] PnP: move pnpacpi/pnpbios_init to after PCI init We already did that a long time ago for pnp_system_init, but pnpacpi_init and pnpbios_init remained as subsys_initcalls, and get linked into the kernel before the arch-specific routines that finalize the PCI resources (pci_subsys_init). This means that the PnP routines would either register their resources before the PCI layer could, or would be unable to check whether a PCI resource had already been registered. Both are problematic. I wanted to do this before 2.6.27, but every time we change something like this, something breaks. That said, _every_ single time we trust some firmware (like PnP tables) more than we trust the hardware itself (like PCI probing), the problems have been worse. Signed-off-by: Linus Torvalds --- drivers/pnp/Makefile | 5 ++++- drivers/pnp/pnpacpi/core.c | 2 +- drivers/pnp/pnpbios/core.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile index 26f5abc9c3f..e83f34f1b5b 100644 --- a/drivers/pnp/Makefile +++ b/drivers/pnp/Makefile @@ -2,12 +2,15 @@ # Makefile for the Linux Plug-and-Play Support. # -obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o system.o +obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o obj-$(CONFIG_PNPACPI) += pnpacpi/ obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ +# pnp_system_init goes after pnpacpi/pnpbios init +obj-y += system.o + ifeq ($(CONFIG_PNP_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index c1b9ea34977..53561d72b4e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -268,7 +268,7 @@ static int __init pnpacpi_init(void) return 0; } -subsys_initcall(pnpacpi_init); +fs_initcall(pnpacpi_init); static int __init pnpacpi_setup(char *str) { diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 19a4be1a9a3..662dfcddedc 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -571,7 +571,7 @@ static int __init pnpbios_init(void) return 0; } -subsys_initcall(pnpbios_init); +fs_initcall(pnpbios_init); static int __init pnpbios_thread_init(void) { -- GitLab From 43603c8df97f246e8be7b9cc92a8f968a85108bd Mon Sep 17 00:00:00 2001 From: Hans Schou Date: Thu, 9 Oct 2008 20:47:24 +0200 Subject: [PATCH 3708/5416] x86, debug: print more information about unknown CPUs Write the name of the unknown vendor_id to output instead of just "unknown". Tag changed to 'vendor_id' as used in /proc/cpuinfo Signed-off-by: Hans Schou Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cef3519b3bb..84c4040efa8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -406,7 +406,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) if (!printed) { printed++; - printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); + printk(KERN_ERR "CPU: vendor_id '%s' unknown, using generic init.\n", v); printk(KERN_ERR "CPU: Your system may be unstable.\n"); } -- GitLab From b2bc27314664c4d1a2f02e6f4cd0c32e4681d61e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:36 -0700 Subject: [PATCH 3709/5416] x86, cpa: rename PTE attribute macros for kernel direct mapping in early boot Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 34 +++++++++++++++------------------- arch/x86/kernel/head_64.S | 4 ++-- include/asm-x86/pgtable.h | 11 +++++++++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index a7010c3a377..e835b4eea70 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -172,10 +172,6 @@ num_subarch_entries = (. - subarch_entries) / 4 * * Note that the stack is not yet set up! */ -#define PTE_ATTR 0x007 /* PRESENT+RW+USER */ -#define PDE_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ -#define PGD_ATTR 0x001 /* PRESENT (no other attributes) */ - default_entry: #ifdef CONFIG_X86_PAE @@ -196,9 +192,9 @@ default_entry: movl $pa(pg0), %edi movl %edi, pa(init_pg_tables_start) movl $pa(swapper_pg_pmd), %edx - movl $PTE_ATTR, %eax + movl $PTE_IDENT_ATTR, %eax 10: - leal PDE_ATTR(%edi),%ecx /* Create PMD entry */ + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ movl %ecx,(%edx) /* Store PMD entry */ /* Upper half already zero */ addl $8,%edx @@ -215,7 +211,7 @@ default_entry: * End condition: we must map up to and including INIT_MAP_BEYOND_END * bytes beyond the end of our own page tables. */ - leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp + leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp cmpl %ebp,%eax jb 10b 1: @@ -224,7 +220,7 @@ default_entry: movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax + movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8) #else /* Not PAE */ @@ -233,9 +229,9 @@ page_pde_offset = (__PAGE_OFFSET >> 20); movl $pa(pg0), %edi movl %edi, pa(init_pg_tables_start) movl $pa(swapper_pg_dir), %edx - movl $PTE_ATTR, %eax + movl $PTE_IDENT_ATTR, %eax 10: - leal PDE_ATTR(%edi),%ecx /* Create PDE entry */ + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ movl %ecx,(%edx) /* Store identity PDE entry */ movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ addl $4,%edx @@ -249,7 +245,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); * bytes beyond the end of our own page tables; the +0x007 is * the attribute bits */ - leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp + leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp cmpl %ebp,%eax jb 10b movl %edi,pa(init_pg_tables_end) @@ -257,7 +253,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax + movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax movl %eax,pa(swapper_pg_dir+0xffc) #endif jmp 3f @@ -634,19 +630,19 @@ ENTRY(empty_zero_page) /* Page-aligned for the benefit of paravirt? */ .align PAGE_SIZE_asm ENTRY(swapper_pg_dir) - .long pa(swapper_pg_pmd+PGD_ATTR),0 /* low identity map */ + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ # if KPMDS == 3 - .long pa(swapper_pg_pmd+PGD_ATTR),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x2000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0 # elif KPMDS == 2 .long 0,0 - .long pa(swapper_pg_pmd+PGD_ATTR),0 - .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0 # elif KPMDS == 1 .long 0,0 .long 0,0 - .long pa(swapper_pg_pmd+PGD_ATTR),0 + .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 # else # error "Kernel PMDs should be 1, 2 or 3" # endif diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index db3280afe88..26cfdc1d7c7 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -110,7 +110,7 @@ startup_64: movq %rdi, %rax shrq $PMD_SHIFT, %rax andq $(PTRS_PER_PMD - 1), %rax - leaq __PAGE_KERNEL_LARGE_EXEC(%rdi), %rdx + leaq __PAGE_KERNEL_IDENT_LARGE_EXEC(%rdi), %rdx leaq level2_spare_pgt(%rip), %rbx movq %rdx, 0(%rbx, %rax, 8) ident_complete: @@ -374,7 +374,7 @@ NEXT_PAGE(level2_ident_pgt) /* Since I easily can, map the first 1G. * Don't set NX because code runs from these pages. */ - PMDS(0, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD) + PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) NEXT_PAGE(level2_kernel_pgt) /* diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index eccd52406ab..0ff73e7737a 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -132,6 +132,17 @@ #define __S110 PAGE_SHARED_EXEC #define __S111 PAGE_SHARED_EXEC +/* + * early identity mapping pte attrib macros. + */ +#ifdef CONFIG_X86_64 +#define __PAGE_KERNEL_IDENT_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC +#else +#define PTE_IDENT_ATTR 0x007 /* PRESENT+RW+USER */ +#define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ +#define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */ +#endif + #ifndef __ASSEMBLY__ /* -- GitLab From 3a85e770aa77e4f1a4096275c97b64c10cd7323e Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:37 -0700 Subject: [PATCH 3710/5416] x86, cpa: remove USER permission from the very early identity mapping attribute remove USER from the PTE/PDE attributes for the very early identity mapping. We overwrite these mappings with KERNEL attribute later in the boot. Just being paranoid here as there is no need for USER bit to be set. If this breaks something(don't know the history), then we can simply drop this change. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- include/asm-x86/pgtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 0ff73e7737a..bbf0f591d1b 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -138,8 +138,8 @@ #ifdef CONFIG_X86_64 #define __PAGE_KERNEL_IDENT_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC #else -#define PTE_IDENT_ATTR 0x007 /* PRESENT+RW+USER */ -#define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ +#define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */ +#define PDE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */ #define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */ #endif -- GitLab From a2699e477b8e6b17d4da64916f766dd5a2576c9c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:38 -0700 Subject: [PATCH 3711/5416] x86, cpa: make the kernel physical mapping initialization a two pass sequence In the first pass, kernel physical mapping will be setup using large or small pages but uses the same PTE attributes as that of the early PTE attributes setup by early boot code in head_[32|64].S After flushing TLB's, we go through the second pass, which setups the direct mapped PTE's with the appropriate attributes (like NX, GLOBAL etc) which are runtime detectable. This two pass mechanism conforms to the TLB app note which says: "Software should not write to a paging-structure entry in a way that would change, for any linear address, both the page size and either the page frame or attributes." Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 65 +++++++++++++++++++++++++--- arch/x86/mm/init_64.c | 99 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..9b5f7d7049d 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -194,11 +194,30 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - unsigned pages_2m = 0, pages_4k = 0; + unsigned pages_2m, pages_4k; + int mapping_iter; + + /* + * First iteration will setup identity mapping using large/small pages + * based on use_pse, with other attributes same as set by + * the early code in head_32.S + * + * Second iteration will setup the appropriate attributes (NX, GLOBAL..) + * as desired for the kernel identity mapping. + * + * This two pass mechanism conforms to the TLB app note which says: + * + * "Software should not write to a paging-structure entry in a way + * that would change, for any linear address, both the page size + * and either the page frame or attributes." + */ + mapping_iter = 1; if (!cpu_has_pse) use_pse = 0; +repeat: + pages_2m = pages_4k = 0; pfn = start_pfn; pgd_idx = pgd_index((pfn<> PAGE_SHIFT, PAGE_KERNEL).pte); + pages++; +repeat_set_pte: set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE; - pages++; } - update_page_count(PG_LEVEL_4K, pages); + + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_4K, pages); return last_map_addr; } @@ -318,7 +323,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, { unsigned long pages = 0; unsigned long last_map_addr = end; - unsigned long start = address; int i = pmd_index(address); @@ -341,15 +345,14 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, last_map_addr = phys_pte_update(pmd, address, end); spin_unlock(&init_mm.page_table_lock); + continue; } - /* Count entries we're using from level2_ident_pgt */ - if (start == 0) - pages++; - continue; + goto repeat_set_pte; } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -366,7 +369,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); spin_unlock(&init_mm.page_table_lock); } - update_page_count(PG_LEVEL_2M, pages); + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_2M, pages); return last_map_addr; } @@ -405,14 +409,18 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, } if (pud_val(*pud)) { - if (!pud_large(*pud)) + if (!pud_large(*pud)) { last_map_addr = phys_pmd_update(pud, addr, end, page_size_mask); - continue; + continue; + } + + goto repeat_set_pte; } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -430,7 +438,9 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, spin_unlock(&init_mm.page_table_lock); } __flush_tlb_all(); - update_page_count(PG_LEVEL_1G, pages); + + if (physical_mapping_iter == 1) + update_page_count(PG_LEVEL_1G, pages); return last_map_addr; } @@ -494,15 +504,54 @@ static void __init init_gbpages(void) direct_gbpages = 0; } +static int is_kernel(unsigned long pfn) +{ + unsigned long pg_addresss = pfn << PAGE_SHIFT; + + if (pg_addresss >= (unsigned long) __pa(_text) && + pg_addresss <= (unsigned long) __pa(_end)) + return 1; + + return 0; +} + static unsigned long __init kernel_physical_mapping_init(unsigned long start, unsigned long end, unsigned long page_size_mask) { - unsigned long next, last_map_addr = end; + unsigned long next, last_map_addr; + u64 cached_supported_pte_mask = __supported_pte_mask; + unsigned long cache_start = start; + unsigned long cache_end = end; + + /* + * First iteration will setup identity mapping using large/small pages + * based on page_size_mask, with other attributes same as set by + * the early code in head_64.S + * + * Second iteration will setup the appropriate attributes + * as desired for the kernel identity mapping. + * + * This two pass mechanism conforms to the TLB app note which says: + * + * "Software should not write to a paging-structure entry in a way + * that would change, for any linear address, both the page size + * and either the page frame or attributes." + * + * For now, only difference between very early PTE attributes used in + * head_64.S and here is _PAGE_NX. + */ + BUILD_BUG_ON((__PAGE_KERNEL_LARGE & ~__PAGE_KERNEL_IDENT_LARGE_EXEC) + != _PAGE_NX); + __supported_pte_mask &= ~(_PAGE_NX); + physical_mapping_iter = 1; - start = (unsigned long)__va(start); - end = (unsigned long)__va(end); +repeat: + last_map_addr = cache_end; + + start = (unsigned long)__va(cache_start); + end = (unsigned long)__va(cache_end); for (; start < end; start = next) { pgd_t *pgd = pgd_offset_k(start); @@ -514,11 +563,21 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start, next = end; if (pgd_val(*pgd)) { + /* + * Static identity mappings will be overwritten + * with run-time mappings. For example, this allows + * the static 0-1GB identity mapping to be mapped + * non-executable with this. + */ + if (is_kernel(pte_pfn(*((pte_t *) pgd)))) + goto realloc; + last_map_addr = phys_pud_update(pgd, __pa(start), __pa(end), page_size_mask); continue; } +realloc: pud = alloc_low_page(&pud_phys); last_map_addr = phys_pud_init(pud, __pa(start), __pa(next), page_size_mask); @@ -528,6 +587,16 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start, pgd_populate(&init_mm, pgd, __va(pud_phys)); spin_unlock(&init_mm.page_table_lock); } + __flush_tlb_all(); + + if (physical_mapping_iter == 1) { + physical_mapping_iter = 2; + /* + * Second iteration will set the actual desired PTE attributes. + */ + __supported_pte_mask = cached_supported_pte_mask; + goto repeat; + } return last_map_addr; } -- GitLab From 0b8fdcbcd287a1fbe66817491e6149841ae25705 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:39 -0700 Subject: [PATCH 3712/5416] x86, cpa: dont use large pages for kernel identity mapping with DEBUG_PAGEALLOC Don't use large pages for kernel identity mapping with DEBUG_PAGEALLOC. This will remove the need to split the large page for the allocated kernel page in the interrupt context. This will simplify cpa code(as we don't do the split any more from the interrupt context). cpa code simplication in the subsequent patches. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 18 ++++++++++++++---- arch/x86/mm/init_64.c | 26 ++++++++++++++++++++------ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 9b5f7d7049d..44ccb028c35 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -777,7 +777,7 @@ void __init setup_bootmem_allocator(void) after_init_bootmem = 1; } -static void __init find_early_table_space(unsigned long end) +static void __init find_early_table_space(unsigned long end, int use_pse) { unsigned long puds, pmds, ptes, tables, start; @@ -787,7 +787,7 @@ static void __init find_early_table_space(unsigned long end) pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); - if (cpu_has_pse) { + if (use_pse) { unsigned long extra; extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); @@ -827,12 +827,22 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, pgd_t *pgd_base = swapper_pg_dir; unsigned long start_pfn, end_pfn; unsigned long big_page_start; +#ifdef CONFIG_DEBUG_PAGEALLOC + /* + * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. + * This will simplify cpa(), which otherwise needs to support splitting + * large pages into small in interrupt context, etc. + */ + int use_pse = 0; +#else + int use_pse = cpu_has_pse; +#endif /* * Find space for the kernel direct mapping tables. */ if (!after_init_bootmem) - find_early_table_space(end); + find_early_table_space(end, use_pse); #ifdef CONFIG_X86_PAE set_nx(); @@ -878,7 +888,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); if (start_pfn < end_pfn) kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, - cpu_has_pse); + use_pse); /* tail is not big page alignment ? */ start_pfn = end_pfn; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 1ba945eb628..9d7587ac1eb 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -456,13 +456,14 @@ phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, return phys_pud_init(pud, addr, end, page_size_mask); } -static void __init find_early_table_space(unsigned long end) +static void __init find_early_table_space(unsigned long end, int use_pse, + int use_gbpages) { unsigned long puds, pmds, ptes, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); - if (direct_gbpages) { + if (use_gbpages) { unsigned long extra; extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; @@ -470,7 +471,7 @@ static void __init find_early_table_space(unsigned long end) pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); - if (cpu_has_pse) { + if (use_pse) { unsigned long extra; extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; @@ -640,6 +641,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, struct map_range mr[NR_RANGE_MR]; int nr_range, i; + int use_pse, use_gbpages; printk(KERN_INFO "init_memory_mapping\n"); @@ -653,9 +655,21 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, if (!after_bootmem) init_gbpages(); - if (direct_gbpages) +#ifdef CONFIG_DEBUG_PAGEALLOC + /* + * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. + * This will simplify cpa(), which otherwise needs to support splitting + * large pages into small in interrupt context, etc. + */ + use_pse = use_gbpages = 0; +#else + use_pse = cpu_has_pse; + use_gbpages = direct_gbpages; +#endif + + if (use_gbpages) page_size_mask |= 1 << PG_LEVEL_1G; - if (cpu_has_pse) + if (use_pse) page_size_mask |= 1 << PG_LEVEL_2M; memset(mr, 0, sizeof(mr)); @@ -716,7 +730,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, (mr[i].page_size_mask & (1< Date: Tue, 23 Sep 2008 14:00:40 -0700 Subject: [PATCH 3713/5416] x86, cpa: no need to check alias for __set_pages_p/__set_pages_np No alias checking needed for setting present/not-present mapping. Otherwise, we may need to break large pages for 64-bit kernel text mappings (this adds to complexity if we want to do this from atomic context especially, for ex: with CONFIG_DEBUG_PAGEALLOC). Let's keep it simple! Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 4b6968ba086..162812b05d2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1121,7 +1121,13 @@ static int __set_pages_p(struct page *page, int numpages) .mask_clr = __pgprot(0), .flags = 0}; - return __change_page_attr_set_clr(&cpa, 1); + /* + * No alias checking needed for setting present flag. otherwise, + * we may need to break large pages for 64-bit kernel text + * mappings (this adds to complexity if we want to do this from + * atomic context especially). Let's keep it simple! + */ + return __change_page_attr_set_clr(&cpa, 0); } static int __set_pages_np(struct page *page, int numpages) @@ -1133,7 +1139,13 @@ static int __set_pages_np(struct page *page, int numpages) .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), .flags = 0}; - return __change_page_attr_set_clr(&cpa, 1); + /* + * No alias checking needed for setting not present flag. otherwise, + * we may need to break large pages for 64-bit kernel text + * mappings (this adds to complexity if we want to do this from + * atomic context especially). Let's keep it simple! + */ + return __change_page_attr_set_clr(&cpa, 0); } void kernel_map_pages(struct page *page, int numpages, int enable) @@ -1153,11 +1165,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) /* * The return value is ignored as the calls cannot fail. - * Large pages are kept enabled at boot time, and are - * split up quickly with DEBUG_PAGEALLOC. If a splitup - * fails here (due to temporary memory shortage) no damage - * is done because we just keep the largepage intact up - * to the next attempt when it will likely be split up: + * Large pages for identity mappings are not used at boot time + * and hence no memory allocations during large page split. */ if (enable) __set_pages_p(page, numpages); -- GitLab From 8311eb84bf842d345f543f4c62ca2b6ea26f638c Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:41 -0700 Subject: [PATCH 3714/5416] x86, cpa: remove cpa pool code Interrupt context no longer splits large page in cpa(). So we can do away with cpa memory pool code. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 1 - arch/x86/mm/init_64.c | 2 - arch/x86/mm/pageattr.c | 157 ++--------------------------------- include/asm-x86/cacheflush.h | 2 - 4 files changed, 5 insertions(+), 157 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 44ccb028c35..74780800e7e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -1051,7 +1051,6 @@ void __init mem_init(void) if (boot_cpu_data.wp_works_ok < 0) test_wp_bit(); - cpa_init(); save_pg_dir(); zap_low_mappings(); } diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 9d7587ac1eb..f54a4d97530 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -889,8 +889,6 @@ void __init mem_init(void) reservedpages << (PAGE_SHIFT-10), datasize >> 10, initsize >> 10); - - cpa_init(); } void free_init_pages(char *what, unsigned long begin, unsigned long end) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 162812b05d2..f5e8663c0f7 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -447,114 +447,17 @@ out_unlock: return do_split; } -static LIST_HEAD(page_pool); -static unsigned long pool_size, pool_pages, pool_low; -static unsigned long pool_used, pool_failed; - -static void cpa_fill_pool(struct page **ret) -{ - gfp_t gfp = GFP_KERNEL; - unsigned long flags; - struct page *p; - - /* - * Avoid recursion (on debug-pagealloc) and also signal - * our priority to get to these pagetables: - */ - if (current->flags & PF_MEMALLOC) - return; - current->flags |= PF_MEMALLOC; - - /* - * Allocate atomically from atomic contexts: - */ - if (in_atomic() || irqs_disabled() || debug_pagealloc) - gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN; - - while (pool_pages < pool_size || (ret && !*ret)) { - p = alloc_pages(gfp, 0); - if (!p) { - pool_failed++; - break; - } - /* - * If the call site needs a page right now, provide it: - */ - if (ret && !*ret) { - *ret = p; - continue; - } - spin_lock_irqsave(&pgd_lock, flags); - list_add(&p->lru, &page_pool); - pool_pages++; - spin_unlock_irqrestore(&pgd_lock, flags); - } - - current->flags &= ~PF_MEMALLOC; -} - -#define SHIFT_MB (20 - PAGE_SHIFT) -#define ROUND_MB_GB ((1 << 10) - 1) -#define SHIFT_MB_GB 10 -#define POOL_PAGES_PER_GB 16 - -void __init cpa_init(void) -{ - struct sysinfo si; - unsigned long gb; - - si_meminfo(&si); - /* - * Calculate the number of pool pages: - * - * Convert totalram (nr of pages) to MiB and round to the next - * GiB. Shift MiB to Gib and multiply the result by - * POOL_PAGES_PER_GB: - */ - if (debug_pagealloc) { - gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB; - pool_size = POOL_PAGES_PER_GB * gb; - } else { - pool_size = 1; - } - pool_low = pool_size; - - cpa_fill_pool(NULL); - printk(KERN_DEBUG - "CPA: page pool initialized %lu of %lu pages preallocated\n", - pool_pages, pool_size); -} - static int split_large_page(pte_t *kpte, unsigned long address) { unsigned long flags, pfn, pfninc = 1; unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; - struct page *base; + struct page *base = alloc_pages(GFP_KERNEL, 0); + if (!base) + return -ENOMEM; - /* - * Get a page from the pool. The pool list is protected by the - * pgd_lock, which we have to take anyway for the split - * operation: - */ spin_lock_irqsave(&pgd_lock, flags); - if (list_empty(&page_pool)) { - spin_unlock_irqrestore(&pgd_lock, flags); - base = NULL; - cpa_fill_pool(&base); - if (!base) - return -ENOMEM; - spin_lock_irqsave(&pgd_lock, flags); - } else { - base = list_first_entry(&page_pool, struct page, lru); - list_del(&base->lru); - pool_pages--; - - if (pool_pages < pool_low) - pool_low = pool_pages; - } - /* * Check for races, another CPU might have split this page * up for us already: @@ -611,11 +514,8 @@ out_unlock: * If we dropped out via the lookup_address check under * pgd_lock then stick the page back into the pool: */ - if (base) { - list_add(&base->lru, &page_pool); - pool_pages++; - } else - pool_used++; + if (base) + __free_page(base); spin_unlock_irqrestore(&pgd_lock, flags); return 0; @@ -899,8 +799,6 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, cpa_flush_all(cache); out: - cpa_fill_pool(NULL); - return ret; } @@ -1178,53 +1076,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) * but that can deadlock->flush only current cpu: */ __flush_tlb_all(); - - /* - * Try to refill the page pool here. We can do this only after - * the tlb flush. - */ - cpa_fill_pool(NULL); -} - -#ifdef CONFIG_DEBUG_FS -static int dpa_show(struct seq_file *m, void *v) -{ - seq_puts(m, "DEBUG_PAGEALLOC\n"); - seq_printf(m, "pool_size : %lu\n", pool_size); - seq_printf(m, "pool_pages : %lu\n", pool_pages); - seq_printf(m, "pool_low : %lu\n", pool_low); - seq_printf(m, "pool_used : %lu\n", pool_used); - seq_printf(m, "pool_failed : %lu\n", pool_failed); - - return 0; -} - -static int dpa_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, dpa_show, NULL); } -static const struct file_operations dpa_fops = { - .open = dpa_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init debug_pagealloc_proc_init(void) -{ - struct dentry *de; - - de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL, - &dpa_fops); - if (!de) - return -ENOMEM; - - return 0; -} -__initcall(debug_pagealloc_proc_init); -#endif - #ifdef CONFIG_HIBERNATION bool kernel_page_present(struct page *page) diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index 0a5f71817b3..8e205a13125 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -99,8 +99,6 @@ int set_pages_rw(struct page *page, int numpages); void clflush_cache_range(void *addr, unsigned int size); -void cpa_init(void); - #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); extern const int rodata_test_data; -- GitLab From ad5ca55f6bdb47c957b681c7358bb3719ba4ee82 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Sep 2008 14:00:42 -0700 Subject: [PATCH 3715/5416] x86, cpa: srlz cpa(), global flush tlb after splitting big page and before doing cpa Do a global flush tlb after splitting the large page and before we do the actual change page attribute in the PTE. With out this, we violate the TLB application note, which says "The TLBs may contain both ordinary and large-page translations for a 4-KByte range of linear addresses. This may occur if software modifies the paging structures so that the page size used for the address range changes. If the two translations differ with respect to page frame or attributes (e.g., permissions), processor behavior is undefined and may be implementation-specific." And also serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings) using cpa_lock. So that we don't allow any other cpu, with stale large tlb entries change the page attribute in parallel to some other cpu splitting a large page entry along with changing the attribute. Signed-off-by: Suresh Siddha Cc: Suresh Siddha Cc: arjan@linux.intel.com Cc: venkatesh.pallipadi@intel.com Cc: jeremy@goop.org Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index f5e8663c0f7..b6374d653d0 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -35,6 +35,14 @@ struct cpa_data { int curpage; }; +/* + * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings) + * using cpa_lock. So that we don't allow any other cpu, with stale large tlb + * entries change the page attribute in parallel to some other cpu + * splitting a large page entry along with changing the attribute. + */ +static DEFINE_SPINLOCK(cpa_lock); + #define CPA_FLUSHTLB 1 #define CPA_ARRAY 2 @@ -453,7 +461,13 @@ static int split_large_page(pte_t *kpte, unsigned long address) unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; - struct page *base = alloc_pages(GFP_KERNEL, 0); + struct page *base; + + if (!debug_pagealloc) + spin_unlock(&cpa_lock); + base = alloc_pages(GFP_KERNEL, 0); + if (!debug_pagealloc) + spin_lock(&cpa_lock); if (!base) return -ENOMEM; @@ -594,7 +608,25 @@ repeat: */ err = split_large_page(kpte, address); if (!err) { - cpa->flags |= CPA_FLUSHTLB; + /* + * Do a global flush tlb after splitting the large page + * and before we do the actual change page attribute in the PTE. + * + * With out this, we violate the TLB application note, that says + * "The TLBs may contain both ordinary and large-page + * translations for a 4-KByte range of linear addresses. This + * may occur if software modifies the paging structures so that + * the page size used for the address range changes. If the two + * translations differ with respect to page frame or attributes + * (e.g., permissions), processor behavior is undefined and may + * be implementation-specific." + * + * We do this global tlb flush inside the cpa_lock, so that we + * don't allow any other cpu, with stale tlb entries change the + * page attribute in parallel, that also falls into the + * just split large page entry. + */ + flush_tlb_all(); goto repeat; } @@ -686,7 +718,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) if (cpa->flags & CPA_ARRAY) cpa->numpages = 1; + if (!debug_pagealloc) + spin_lock(&cpa_lock); ret = __change_page_attr(cpa, checkalias); + if (!debug_pagealloc) + spin_unlock(&cpa_lock); if (ret) return ret; -- GitLab From 9542ada803198e6eba29d3289abb39ea82047b92 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 24 Sep 2008 08:53:33 -0700 Subject: [PATCH 3716/5416] x86: track memtype for RAM in page struct Track the memtype for RAM pages in page struct instead of using the memtype list. This avoids the explosion in the number of entries in memtype list (of the order of 20,000 with AGP) and makes the PAT tracking simpler. We are using PG_arch_1 bit in page->flags. We still use the memtype list for non RAM pages. Signed-off-by: Suresh Siddha Signed-off-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 19 +++++++++ arch/x86/mm/pat.c | 83 ++++++++++++++++++++++++++++++++++++ include/asm-x86/cacheflush.h | 2 + include/asm-x86/page.h | 1 + 4 files changed, 105 insertions(+) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index d4b6e6a29ae..d03c461e045 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -83,6 +83,25 @@ int page_is_ram(unsigned long pagenr) return 0; } +int pagerange_is_ram(unsigned long start, unsigned long end) +{ + int ram_page = 0, not_rampage = 0; + unsigned long page_nr; + + for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT); + ++page_nr) { + if (page_is_ram(page_nr)) + ram_page = 1; + else + not_rampage = 1; + + if (ram_page == not_rampage) + return -1; + } + + return ram_page; +} + /* * Fix up the linear direct mapping of the kernel to avoid cache attribute * conflicts. diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index f049b1d6ebd..aceb6c7c6db 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -210,6 +210,75 @@ static int chk_conflict(struct memtype *new, struct memtype *entry, static struct memtype *cached_entry; static u64 cached_start; +/* + * RED-PEN: TODO: Add PageReserved() check as well here, + * once we add SetPageReserved() to all the drivers using + * set_memory_* or set_pages_*. + * + * This will help prevent accidentally freeing pages + * before setting the attribute back to WB. + */ + +/* + * For RAM pages, mark the pages as non WB memory type using + * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or + * set_memory_wc() on a RAM page at a time before marking it as WB again. + * This is ok, because only one driver will be owning the page and + * doing set_memory_*() calls. + * + * For now, we use PageNonWB to track that the RAM page is being mapped + * as non WB. In future, we will have to use one more flag + * (or some other mechanism in page_struct) to distinguish between + * UC and WC mapping. + */ +static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type, + unsigned long *new_type) +{ + struct page *page; + u64 pfn, end_pfn; + + for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) { + page = pfn_to_page(pfn); + if (page_mapped(page) || PageNonWB(page)) + goto out; + + SetPageNonWB(page); + } + return 0; + +out: + end_pfn = pfn; + for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) { + page = pfn_to_page(pfn); + ClearPageNonWB(page); + } + + return -EINVAL; +} + +static int free_ram_pages_type(u64 start, u64 end) +{ + struct page *page; + u64 pfn, end_pfn; + + for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) { + page = pfn_to_page(pfn); + if (page_mapped(page) || !PageNonWB(page)) + goto out; + + ClearPageNonWB(page); + } + return 0; + +out: + end_pfn = pfn; + for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) { + page = pfn_to_page(pfn); + SetPageNonWB(page); + } + return -EINVAL; +} + /* * req_type typically has one of the: * - _PAGE_CACHE_WB @@ -232,6 +301,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, unsigned long actual_type; struct list_head *where; int err = 0; + int is_range_ram; BUG_ON(start >= end); /* end is exclusive */ @@ -270,6 +340,12 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK); + is_range_ram = pagerange_is_ram(start, end); + if (is_range_ram == 1) + return reserve_ram_pages_type(start, end, req_type, new_type); + else if (is_range_ram < 0) + return -EINVAL; + new = kmalloc(sizeof(struct memtype), GFP_KERNEL); if (!new) return -ENOMEM; @@ -358,6 +434,7 @@ int free_memtype(u64 start, u64 end) { struct memtype *entry; int err = -EINVAL; + int is_range_ram; if (!pat_enabled) return 0; @@ -366,6 +443,12 @@ int free_memtype(u64 start, u64 end) if (is_ISA_range(start, end - 1)) return 0; + is_range_ram = pagerange_is_ram(start, end); + if (is_range_ram == 1) + return free_ram_pages_type(start, end); + else if (is_range_ram < 0) + return -EINVAL; + spin_lock(&memtype_lock); list_for_each_entry(entry, &memtype_list, nd) { if (entry->start == start && entry->end == end) { diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index 8e205a13125..092b9b4eb00 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -24,6 +24,8 @@ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ memcpy((dst), (src), (len)) +#define PG_non_WB PG_arch_1 +PAGEFLAG(NonWB, non_WB) /* * The set_memory_* API can be used to change various attributes of a virtual diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h index 49982110e4d..3407ac12ba3 100644 --- a/include/asm-x86/page.h +++ b/include/asm-x86/page.h @@ -57,6 +57,7 @@ typedef struct { pgdval_t pgd; } pgd_t; typedef struct { pgprotval_t pgprot; } pgprot_t; extern int page_is_ram(unsigned long pagenr); +extern int pagerange_is_ram(unsigned long start, unsigned long end); extern int devmem_is_allowed(unsigned long pagenr); extern void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot); -- GitLab From 28dd033f43ca957cd751e02652b36c6fa364ca18 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 29 Sep 2008 12:13:26 -0700 Subject: [PATCH 3717/5416] x86: fix pagetable init 64-bit breakage Fix _end alignment check - can trigger a crash if _end happens to be on a page boundary. Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index f54a4d97530..6116ff0d741 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -510,7 +510,7 @@ static int is_kernel(unsigned long pfn) unsigned long pg_addresss = pfn << PAGE_SHIFT; if (pg_addresss >= (unsigned long) __pa(_text) && - pg_addresss <= (unsigned long) __pa(_end)) + pg_addresss < (unsigned long) __pa(_end)) return 1; return 0; -- GitLab From ad2cde16a21985cdc4302e4a4b0fc373d666fdf7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 30 Sep 2008 13:20:45 +0200 Subject: [PATCH 3718/5416] x86, pat: cleanups clean up recently added code to be more consistent with other x86 code. Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 67 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index aceb6c7c6db..738fd0f2495 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -7,24 +7,24 @@ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen. */ -#include +#include +#include +#include #include #include +#include #include -#include -#include -#include -#include -#include +#include #include -#include +#include #include -#include -#include -#include #include +#include #include +#include +#include +#include #include #ifdef CONFIG_X86_PAT @@ -46,6 +46,7 @@ early_param("nopat", nopat); static int debug_enable; + static int __init pat_debug_setup(char *str) { debug_enable = 1; @@ -145,14 +146,14 @@ static char *cattr_name(unsigned long flags) */ struct memtype { - u64 start; - u64 end; - unsigned long type; - struct list_head nd; + u64 start; + u64 end; + unsigned long type; + struct list_head nd; }; static LIST_HEAD(memtype_list); -static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ +static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ /* * Does intersection of PAT memory type and MTRR memory type and returns @@ -180,8 +181,8 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type) return req_type; } -static int chk_conflict(struct memtype *new, struct memtype *entry, - unsigned long *type) +static int +chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type) { if (new->type != entry->type) { if (type) { @@ -210,15 +211,6 @@ static int chk_conflict(struct memtype *new, struct memtype *entry, static struct memtype *cached_entry; static u64 cached_start; -/* - * RED-PEN: TODO: Add PageReserved() check as well here, - * once we add SetPageReserved() to all the drivers using - * set_memory_* or set_pages_*. - * - * This will help prevent accidentally freeing pages - * before setting the attribute back to WB. - */ - /* * For RAM pages, mark the pages as non WB memory type using * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or @@ -232,7 +224,7 @@ static u64 cached_start; * UC and WC mapping. */ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type, - unsigned long *new_type) + unsigned long *new_type) { struct page *page; u64 pfn, end_pfn; @@ -295,15 +287,15 @@ out: * it will return a negative return value. */ int reserve_memtype(u64 start, u64 end, unsigned long req_type, - unsigned long *new_type) + unsigned long *new_type) { struct memtype *new, *entry; unsigned long actual_type; struct list_head *where; - int err = 0; int is_range_ram; + int err = 0; - BUG_ON(start >= end); /* end is exclusive */ + BUG_ON(start >= end); /* end is exclusive */ if (!pat_enabled) { /* This is identical to page table setting without PAT */ @@ -336,9 +328,10 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, actual_type = _PAGE_CACHE_WB; else actual_type = _PAGE_CACHE_UC_MINUS; - } else + } else { actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK); + } is_range_ram = pagerange_is_ram(start, end); if (is_range_ram == 1) @@ -350,9 +343,9 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, if (!new) return -ENOMEM; - new->start = start; - new->end = end; - new->type = actual_type; + new->start = start; + new->end = end; + new->type = actual_type; if (new_type) *new_type = actual_type; @@ -411,6 +404,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, start, end, cattr_name(new->type), cattr_name(req_type)); kfree(new); spin_unlock(&memtype_lock); + return err; } @@ -469,6 +463,7 @@ int free_memtype(u64 start, u64 end) } dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end); + return err; } @@ -575,9 +570,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) { + unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK); u64 addr = (u64)pfn << PAGE_SHIFT; unsigned long flags; - unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK); reserve_memtype(addr, addr + size, want_flags, &flags); if (flags != want_flags) { @@ -620,6 +615,7 @@ static struct memtype *memtype_get_idx(loff_t pos) } spin_unlock(&memtype_lock); kfree(print_entry); + return NULL; } @@ -650,6 +646,7 @@ static int memtype_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type), print_entry->start, print_entry->end); kfree(print_entry); + return 0; } -- GitLab From b27a43c1e90582facad44de67d02bc9e9f900289 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 7 Oct 2008 13:58:46 -0700 Subject: [PATCH 3719/5416] x86, cpa: make the kernel physical mapping initialization a two pass sequence, fix Jeremy Fitzhardinge wrote: > I'd noticed that current tip/master hasn't been booting under Xen, and I > just got around to bisecting it down to this change. > > commit 065ae73c5462d42e9761afb76f2b52965ff45bd6 > Author: Suresh Siddha > > x86, cpa: make the kernel physical mapping initialization a two pass sequence > > This patch is causing Xen to fail various pagetable updates because it > ends up remapping pagetables to RW, which Xen explicitly prohibits (as > that would allow guests to make arbitrary changes to pagetables, rather > than have them mediated by the hypervisor). Instead of making init a two pass sequence, to satisfy the Intel's TLB Application note (developer.intel.com/design/processor/applnots/317080.pdf Section 6 page 26), we preserve the original page permissions when fragmenting the large mappings and don't touch the existing memory mapping (which satisfies Xen's requirements). Only open issue is: on a native linux kernel, we will go back to mapping the first 0-1GB kernel identity mapping as executable (because of the static mapping setup in head_64.S). We can fix this in a different patch if needed. Signed-off-by: Suresh Siddha Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 149 +++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 88 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 6116ff0d741..8c7eae490a2 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -270,10 +270,9 @@ static __ref void unmap_low_page(void *adr) early_iounmap(adr, PAGE_SIZE); } -static int physical_mapping_iter; - static unsigned long __meminit -phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end) +phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, + pgprot_t prot) { unsigned pages = 0; unsigned long last_map_addr = end; @@ -291,35 +290,40 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end) break; } + /* + * We will re-use the existing mapping. + * Xen for example has some special requirements, like mapping + * pagetable pages as RO. So assume someone who pre-setup + * these mappings are more intelligent. + */ if (pte_val(*pte)) - goto repeat_set_pte; + continue; if (0) printk(" pte=%p addr=%lx pte=%016lx\n", pte, addr, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL).pte); pages++; -repeat_set_pte: - set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); + set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, prot)); last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE; } - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_4K, pages); + update_page_count(PG_LEVEL_4K, pages); return last_map_addr; } static unsigned long __meminit -phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end) +phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end, + pgprot_t prot) { pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); - return phys_pte_init(pte, address, end); + return phys_pte_init(pte, address, end, prot); } static unsigned long __meminit phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, - unsigned long page_size_mask) + unsigned long page_size_mask, pgprot_t prot) { unsigned long pages = 0; unsigned long last_map_addr = end; @@ -330,6 +334,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, unsigned long pte_phys; pmd_t *pmd = pmd_page + pmd_index(address); pte_t *pte; + pgprot_t new_prot = prot; if (address >= end) { if (!after_bootmem) { @@ -343,45 +348,58 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, if (!pmd_large(*pmd)) { spin_lock(&init_mm.page_table_lock); last_map_addr = phys_pte_update(pmd, address, - end); + end, prot); spin_unlock(&init_mm.page_table_lock); continue; } - goto repeat_set_pte; + /* + * If we are ok with PG_LEVEL_2M mapping, then we will + * use the existing mapping, + * + * Otherwise, we will split the large page mapping but + * use the same existing protection bits except for + * large page, so that we don't violate Intel's TLB + * Application note (317080) which says, while changing + * the page sizes, new and old translations should + * not differ with respect to page frame and + * attributes. + */ + if (page_size_mask & (1 << PG_LEVEL_2M)) + continue; + new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd)); } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); + pfn_pte(address >> PAGE_SHIFT, + __pgprot(pgprot_val(prot) | _PAGE_PSE))); spin_unlock(&init_mm.page_table_lock); last_map_addr = (address & PMD_MASK) + PMD_SIZE; continue; } pte = alloc_low_page(&pte_phys); - last_map_addr = phys_pte_init(pte, address, end); + last_map_addr = phys_pte_init(pte, address, end, new_prot); unmap_low_page(pte); spin_lock(&init_mm.page_table_lock); pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); spin_unlock(&init_mm.page_table_lock); } - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_2M, pages); + update_page_count(PG_LEVEL_2M, pages); return last_map_addr; } static unsigned long __meminit phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end, - unsigned long page_size_mask) + unsigned long page_size_mask, pgprot_t prot) { pmd_t *pmd = pmd_offset(pud, 0); unsigned long last_map_addr; - last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask); + last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot); __flush_tlb_all(); return last_map_addr; } @@ -398,6 +416,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, unsigned long pmd_phys; pud_t *pud = pud_page + pud_index(addr); pmd_t *pmd; + pgprot_t prot = PAGE_KERNEL; if (addr >= end) break; @@ -411,16 +430,28 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, if (pud_val(*pud)) { if (!pud_large(*pud)) { last_map_addr = phys_pmd_update(pud, addr, end, - page_size_mask); + page_size_mask, prot); continue; } - - goto repeat_set_pte; + /* + * If we are ok with PG_LEVEL_1G mapping, then we will + * use the existing mapping. + * + * Otherwise, we will split the gbpage mapping but use + * the same existing protection bits except for large + * page, so that we don't violate Intel's TLB + * Application note (317080) which says, while changing + * the page sizes, new and old translations should + * not differ with respect to page frame and + * attributes. + */ + if (page_size_mask & (1 << PG_LEVEL_1G)) + continue; + prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud)); } if (page_size_mask & (1<> PAGE_SHIFT, PAGE_KERNEL_LARGE)); @@ -430,7 +461,8 @@ repeat_set_pte: } pmd = alloc_low_page(&pmd_phys); - last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask); + last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask, + prot); unmap_low_page(pmd); spin_lock(&init_mm.page_table_lock); @@ -439,8 +471,7 @@ repeat_set_pte: } __flush_tlb_all(); - if (physical_mapping_iter == 1) - update_page_count(PG_LEVEL_1G, pages); + update_page_count(PG_LEVEL_1G, pages); return last_map_addr; } @@ -505,54 +536,15 @@ static void __init init_gbpages(void) direct_gbpages = 0; } -static int is_kernel(unsigned long pfn) -{ - unsigned long pg_addresss = pfn << PAGE_SHIFT; - - if (pg_addresss >= (unsigned long) __pa(_text) && - pg_addresss < (unsigned long) __pa(_end)) - return 1; - - return 0; -} - static unsigned long __init kernel_physical_mapping_init(unsigned long start, unsigned long end, unsigned long page_size_mask) { - unsigned long next, last_map_addr; - u64 cached_supported_pte_mask = __supported_pte_mask; - unsigned long cache_start = start; - unsigned long cache_end = end; - - /* - * First iteration will setup identity mapping using large/small pages - * based on page_size_mask, with other attributes same as set by - * the early code in head_64.S - * - * Second iteration will setup the appropriate attributes - * as desired for the kernel identity mapping. - * - * This two pass mechanism conforms to the TLB app note which says: - * - * "Software should not write to a paging-structure entry in a way - * that would change, for any linear address, both the page size - * and either the page frame or attributes." - * - * For now, only difference between very early PTE attributes used in - * head_64.S and here is _PAGE_NX. - */ - BUILD_BUG_ON((__PAGE_KERNEL_LARGE & ~__PAGE_KERNEL_IDENT_LARGE_EXEC) - != _PAGE_NX); - __supported_pte_mask &= ~(_PAGE_NX); - physical_mapping_iter = 1; + unsigned long next, last_map_addr = end; -repeat: - last_map_addr = cache_end; - - start = (unsigned long)__va(cache_start); - end = (unsigned long)__va(cache_end); + start = (unsigned long)__va(start); + end = (unsigned long)__va(end); for (; start < end; start = next) { pgd_t *pgd = pgd_offset_k(start); @@ -564,21 +556,11 @@ repeat: next = end; if (pgd_val(*pgd)) { - /* - * Static identity mappings will be overwritten - * with run-time mappings. For example, this allows - * the static 0-1GB identity mapping to be mapped - * non-executable with this. - */ - if (is_kernel(pte_pfn(*((pte_t *) pgd)))) - goto realloc; - last_map_addr = phys_pud_update(pgd, __pa(start), __pa(end), page_size_mask); continue; } -realloc: pud = alloc_low_page(&pud_phys); last_map_addr = phys_pud_init(pud, __pa(start), __pa(next), page_size_mask); @@ -590,15 +572,6 @@ realloc: } __flush_tlb_all(); - if (physical_mapping_iter == 1) { - physical_mapping_iter = 2; - /* - * Second iteration will set the actual desired PTE attributes. - */ - __supported_pte_mask = cached_supported_pte_mask; - goto repeat; - } - return last_map_addr; } -- GitLab From 73f6aa4d44ab6157badc456ddfa05b31e58de5f0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 10 Oct 2008 17:28:29 +1100 Subject: [PATCH 3720/5416] Fix barrier fail detection in XFS Currently we disable barriers as soon as we get a buffer in xlog_iodone that has the XBF_ORDERED flag cleared. But this can be the case not only for buffers where the barrier failed, but also the first buffer of a split log write in case of a log wraparound. Due to the disabled barriers we can easily get directory corruption on unclean shutdowns. So instead of using this check add a new buffer flag for failed barrier writes. This is a regression vs 2.6.26 caused by patch to use the right macro to check for the ORDERED flag, as we previously got true returned for every buffer. Thanks to Toei Rei for reporting the bug. Signed-off-by: Christoph Hellwig Reviewed-by: Eric Sandeen Reviewed-by: David Chinner Signed-off-by: Tim Shimmin Signed-off-by: Linus Torvalds --- fs/xfs/linux-2.6/xfs_buf.c | 3 ++- fs/xfs/linux-2.6/xfs_buf.h | 8 ++++++++ fs/xfs/xfs_log.c | 7 ++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 986061ae1b9..36d5fcd3f59 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1001,12 +1001,13 @@ xfs_buf_iodone_work( * We can get an EOPNOTSUPP to ordered writes. Here we clear the * ordered flag and reissue them. Because we can't tell the higher * layers directly that they should not issue ordered I/O anymore, they - * need to check if the ordered flag was cleared during I/O completion. + * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion. */ if ((bp->b_error == EOPNOTSUPP) && (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { XB_TRACE(bp, "ordered_retry", bp->b_iodone); bp->b_flags &= ~XBF_ORDERED; + bp->b_flags |= _XFS_BARRIER_FAILED; xfs_buf_iorequest(bp); } else if (bp->b_iodone) (*(bp->b_iodone))(bp); diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index fe010995665..456519a088c 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -85,6 +85,14 @@ typedef enum { * modifications being lost. */ _XBF_PAGE_LOCKED = (1 << 22), + + /* + * If we try a barrier write, but it fails we have to communicate + * this to the upper layers. Unfortunately b_error gets overwritten + * when the buffer is re-issued so we have to add another flag to + * keep this information. + */ + _XFS_BARRIER_FAILED = (1 << 23), } xfs_buf_flags_t; typedef enum { diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 503ea89e8b9..0b02c644355 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1033,11 +1033,12 @@ xlog_iodone(xfs_buf_t *bp) l = iclog->ic_log; /* - * If the ordered flag has been removed by a lower - * layer, it means the underlyin device no longer supports + * If the _XFS_BARRIER_FAILED flag was set by a lower + * layer, it means the underlying device no longer supports * barrier I/O. Warn loudly and turn off barriers. */ - if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { + if (bp->b_flags & _XFS_BARRIER_FAILED) { + bp->b_flags &= ~_XFS_BARRIER_FAILED; l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; xfs_fs_cmn_err(CE_WARN, l->l_mp, "xlog_iodone: Barriers are no longer supported" -- GitLab From 456018d791ff4ef03d610f72486c637056bcd749 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 8 Oct 2008 15:31:14 -0400 Subject: [PATCH 3721/5416] NFS: Cleanup nfs_set_port Signed-off-by: "J. Bruce Fields" Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 5d2a5d3c424..d212ee41caf 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -285,16 +285,15 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len) */ static inline void nfs_set_port(struct sockaddr *sap, unsigned short port) { + struct sockaddr_in *ap = (struct sockaddr_in *)sap; + struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap; + switch (sap->sa_family) { - case AF_INET: { - struct sockaddr_in *ap = (struct sockaddr_in *)sap; - ap->sin_port = htons(port); - break; - } - case AF_INET6: { - struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; - ap->sin6_port = htons(port); - break; - } + case AF_INET: + ap->sin_port = htons(port); + break; + case AF_INET6: + ap6->sin6_port = htons(port); + break; } } -- GitLab From 5e2e7721f04c11e6dc4a74b33f05a0e1c0381e2e Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 8 Oct 2008 15:38:10 -0400 Subject: [PATCH 3722/5416] NFS: fix nfs_parse_ip_address() corner case Bruce observed that nfs_parse_ip_address() will successfully parse an IPv6 address that looks like this: "::1%" A scope delimiter is present, but there is no scope ID following it. This is harmless, as it would simply set the scope ID to zero. However, in some cases we would like to flag this as an improperly formed address. We are now also careful to reject addresses where garbage follows the address (up to the length of the string), instead of ignoring the non-address characters; and where the scope ID is nonsense (not a valid device name, but also not numeric). Before, both of these cases would result in a harmless zero scope ID. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/nfs/super.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 20dc4ccdff5..d496e401622 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -717,17 +717,21 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, - const char *delim, - struct sockaddr_in6 *sin6) +static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, + const char *delim, + struct sockaddr_in6 *sin6) { char *p; size_t len; - if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) - return ; + if ((string + str_len) == delim) + return 1; + if (*delim != IPV6_SCOPE_DELIMITER) - return; + return 0; + + if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) + return 0; len = (string + str_len) - delim - 1; p = kstrndup(delim + 1, len, GFP_KERNEL); @@ -740,14 +744,20 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, scope_id = dev->ifindex; dev_put(dev); } else { - /* scope_id is set to zero on error */ - strict_strtoul(p, 10, &scope_id); + if (strict_strtoul(p, 10, &scope_id) == 0) { + kfree(p); + return 0; + } } kfree(p); + sin6->sin6_scope_id = scope_id; dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id); + return 1; } + + return 0; } static void nfs_parse_ipv6_address(char *string, size_t str_len, @@ -763,9 +773,11 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len, sin6->sin6_family = AF_INET6; *addr_len = sizeof(*sin6); - if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) { - nfs_parse_ipv6_scope_id(string, str_len, delim, sin6); - return; + if (in6_pton(string, str_len, addr, + IPV6_SCOPE_DELIMITER, &delim) != 0) { + if (nfs_parse_ipv6_scope_id(string, str_len, + delim, sin6) != 0) + return; } } -- GitLab From 8d4ba0347ccfea4f12e56e2484954b891411b74d Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 14:59:49 -0400 Subject: [PATCH 3723/5416] RPC/RDMA: refactor the inline memory registration code. Refactor the memory registration and deregistration routines. This saves stack space, makes the code more readable and prepares to add the new FRMR registration methods. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 365 ++++++++++++++++++++---------------- 1 file changed, 207 insertions(+), 158 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 8ea283ecc52..d04208a02f6 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -863,6 +863,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, char *p; size_t len; int i, rc; + struct rpcrdma_mw *r; buf->rb_max_requests = cdata->max_requests; spin_lock_init(&buf->rb_lock); @@ -873,7 +874,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, * 2. arrays of struct rpcrdma_req to fill in pointers * 3. array of struct rpcrdma_rep for replies * 4. padding, if any - * 5. mw's, if any + * 5. mw's or fmr's, if any * Send/recv buffers in req/rep need to be registered */ @@ -927,15 +928,13 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, * and also reduce unbind-to-bind collision. */ INIT_LIST_HEAD(&buf->rb_mws); + r = (struct rpcrdma_mw *)p; switch (ia->ri_memreg_strategy) { case RPCRDMA_MTHCAFMR: - { - struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; - struct ib_fmr_attr fa = { - RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT - }; /* TBD we are perhaps overallocating here */ for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { + static struct ib_fmr_attr fa = + { RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT }; r->r.fmr = ib_alloc_fmr(ia->ri_pd, IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ, &fa); @@ -948,12 +947,9 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, list_add(&r->mw_list, &buf->rb_mws); ++r; } - } break; case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS: - { - struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; /* Allocate one extra request's worth, for full cycling */ for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { r->r.mw = ib_alloc_mw(ia->ri_pd); @@ -966,7 +962,6 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, list_add(&r->mw_list, &buf->rb_mws); ++r; } - } break; default: break; @@ -1046,6 +1041,7 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) { int rc, i; struct rpcrdma_ia *ia = rdmab_to_ia(buf); + struct rpcrdma_mw *r; /* clean up in reverse order from create * 1. recv mr memory (mr free, then kfree) @@ -1065,7 +1061,6 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) } if (buf->rb_send_bufs && buf->rb_send_bufs[i]) { while (!list_empty(&buf->rb_mws)) { - struct rpcrdma_mw *r; r = list_entry(buf->rb_mws.next, struct rpcrdma_mw, mw_list); list_del(&r->mw_list); @@ -1115,6 +1110,8 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) { struct rpcrdma_req *req; unsigned long flags; + int i; + struct rpcrdma_mw *r; spin_lock_irqsave(&buffers->rb_lock, flags); if (buffers->rb_send_index == buffers->rb_max_requests) { @@ -1135,9 +1132,8 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) } buffers->rb_send_bufs[buffers->rb_send_index++] = NULL; if (!list_empty(&buffers->rb_mws)) { - int i = RPCRDMA_MAX_SEGS - 1; + i = RPCRDMA_MAX_SEGS - 1; do { - struct rpcrdma_mw *r; r = list_entry(buffers->rb_mws.next, struct rpcrdma_mw, mw_list); list_del(&r->mw_list); @@ -1329,15 +1325,202 @@ rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg) seg->mr_dma, seg->mr_dmalen, seg->mr_dir); } +static int +rpcrdma_register_fmr_external(struct rpcrdma_mr_seg *seg, + int *nsegs, int writing, struct rpcrdma_ia *ia) +{ + struct rpcrdma_mr_seg *seg1 = seg; + u64 physaddrs[RPCRDMA_MAX_DATA_SEGS]; + int len, pageoff, i, rc; + + pageoff = offset_in_page(seg1->mr_offset); + seg1->mr_offset -= pageoff; /* start of page */ + seg1->mr_len += pageoff; + len = -pageoff; + if (*nsegs > RPCRDMA_MAX_DATA_SEGS) + *nsegs = RPCRDMA_MAX_DATA_SEGS; + for (i = 0; i < *nsegs;) { + rpcrdma_map_one(ia, seg, writing); + physaddrs[i] = seg->mr_dma; + len += seg->mr_len; + ++seg; + ++i; + /* Check for holes */ + if ((i < *nsegs && offset_in_page(seg->mr_offset)) || + offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) + break; + } + rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr, + physaddrs, i, seg1->mr_dma); + if (rc) { + dprintk("RPC: %s: failed ib_map_phys_fmr " + "%u@0x%llx+%i (%d)... status %i\n", __func__, + len, (unsigned long long)seg1->mr_dma, + pageoff, i, rc); + while (i--) + rpcrdma_unmap_one(ia, --seg); + } else { + seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey; + seg1->mr_base = seg1->mr_dma + pageoff; + seg1->mr_nsegs = i; + seg1->mr_len = len; + } + *nsegs = i; + return rc; +} + +static int +rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg, + struct rpcrdma_ia *ia) +{ + struct rpcrdma_mr_seg *seg1 = seg; + LIST_HEAD(l); + int rc; + + list_add(&seg1->mr_chunk.rl_mw->r.fmr->list, &l); + rc = ib_unmap_fmr(&l); + while (seg1->mr_nsegs--) + rpcrdma_unmap_one(ia, seg++); + if (rc) + dprintk("RPC: %s: failed ib_unmap_fmr," + " status %i\n", __func__, rc); + return rc; +} + +static int +rpcrdma_register_memwin_external(struct rpcrdma_mr_seg *seg, + int *nsegs, int writing, struct rpcrdma_ia *ia, + struct rpcrdma_xprt *r_xprt) +{ + int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE : + IB_ACCESS_REMOTE_READ); + struct ib_mw_bind param; + int rc; + + *nsegs = 1; + rpcrdma_map_one(ia, seg, writing); + param.mr = ia->ri_bind_mem; + param.wr_id = 0ULL; /* no send cookie */ + param.addr = seg->mr_dma; + param.length = seg->mr_len; + param.send_flags = 0; + param.mw_access_flags = mem_priv; + + DECR_CQCOUNT(&r_xprt->rx_ep); + rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, ¶m); + if (rc) { + dprintk("RPC: %s: failed ib_bind_mw " + "%u@0x%llx status %i\n", + __func__, seg->mr_len, + (unsigned long long)seg->mr_dma, rc); + rpcrdma_unmap_one(ia, seg); + } else { + seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; + seg->mr_base = param.addr; + seg->mr_nsegs = 1; + } + return rc; +} + +static int +rpcrdma_deregister_memwin_external(struct rpcrdma_mr_seg *seg, + struct rpcrdma_ia *ia, + struct rpcrdma_xprt *r_xprt, void **r) +{ + struct ib_mw_bind param; + LIST_HEAD(l); + int rc; + + BUG_ON(seg->mr_nsegs != 1); + param.mr = ia->ri_bind_mem; + param.addr = 0ULL; /* unbind */ + param.length = 0; + param.mw_access_flags = 0; + if (*r) { + param.wr_id = (u64) (unsigned long) *r; + param.send_flags = IB_SEND_SIGNALED; + INIT_CQCOUNT(&r_xprt->rx_ep); + } else { + param.wr_id = 0ULL; + param.send_flags = 0; + DECR_CQCOUNT(&r_xprt->rx_ep); + } + rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, ¶m); + rpcrdma_unmap_one(ia, seg); + if (rc) + dprintk("RPC: %s: failed ib_(un)bind_mw," + " status %i\n", __func__, rc); + else + *r = NULL; /* will upcall on completion */ + return rc; +} + +static int +rpcrdma_register_default_external(struct rpcrdma_mr_seg *seg, + int *nsegs, int writing, struct rpcrdma_ia *ia) +{ + int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE : + IB_ACCESS_REMOTE_READ); + struct rpcrdma_mr_seg *seg1 = seg; + struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS]; + int len, i, rc = 0; + + if (*nsegs > RPCRDMA_MAX_DATA_SEGS) + *nsegs = RPCRDMA_MAX_DATA_SEGS; + for (len = 0, i = 0; i < *nsegs;) { + rpcrdma_map_one(ia, seg, writing); + ipb[i].addr = seg->mr_dma; + ipb[i].size = seg->mr_len; + len += seg->mr_len; + ++seg; + ++i; + /* Check for holes */ + if ((i < *nsegs && offset_in_page(seg->mr_offset)) || + offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) + break; + } + seg1->mr_base = seg1->mr_dma; + seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd, + ipb, i, mem_priv, &seg1->mr_base); + if (IS_ERR(seg1->mr_chunk.rl_mr)) { + rc = PTR_ERR(seg1->mr_chunk.rl_mr); + dprintk("RPC: %s: failed ib_reg_phys_mr " + "%u@0x%llx (%d)... status %i\n", + __func__, len, + (unsigned long long)seg1->mr_dma, i, rc); + while (i--) + rpcrdma_unmap_one(ia, --seg); + } else { + seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey; + seg1->mr_nsegs = i; + seg1->mr_len = len; + } + *nsegs = i; + return rc; +} + +static int +rpcrdma_deregister_default_external(struct rpcrdma_mr_seg *seg, + struct rpcrdma_ia *ia) +{ + struct rpcrdma_mr_seg *seg1 = seg; + int rc; + + rc = ib_dereg_mr(seg1->mr_chunk.rl_mr); + seg1->mr_chunk.rl_mr = NULL; + while (seg1->mr_nsegs--) + rpcrdma_unmap_one(ia, seg++); + if (rc) + dprintk("RPC: %s: failed ib_dereg_mr," + " status %i\n", __func__, rc); + return rc; +} + int rpcrdma_register_external(struct rpcrdma_mr_seg *seg, int nsegs, int writing, struct rpcrdma_xprt *r_xprt) { struct rpcrdma_ia *ia = &r_xprt->rx_ia; - int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE : - IB_ACCESS_REMOTE_READ); - struct rpcrdma_mr_seg *seg1 = seg; - int i; int rc = 0; switch (ia->ri_memreg_strategy) { @@ -1352,114 +1535,20 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg, break; #endif - /* Registration using fast memory registration */ + /* Registration using fmr memory registration */ case RPCRDMA_MTHCAFMR: - { - u64 physaddrs[RPCRDMA_MAX_DATA_SEGS]; - int len, pageoff = offset_in_page(seg->mr_offset); - seg1->mr_offset -= pageoff; /* start of page */ - seg1->mr_len += pageoff; - len = -pageoff; - if (nsegs > RPCRDMA_MAX_DATA_SEGS) - nsegs = RPCRDMA_MAX_DATA_SEGS; - for (i = 0; i < nsegs;) { - rpcrdma_map_one(ia, seg, writing); - physaddrs[i] = seg->mr_dma; - len += seg->mr_len; - ++seg; - ++i; - /* Check for holes */ - if ((i < nsegs && offset_in_page(seg->mr_offset)) || - offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) - break; - } - nsegs = i; - rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr, - physaddrs, nsegs, seg1->mr_dma); - if (rc) { - dprintk("RPC: %s: failed ib_map_phys_fmr " - "%u@0x%llx+%i (%d)... status %i\n", __func__, - len, (unsigned long long)seg1->mr_dma, - pageoff, nsegs, rc); - while (nsegs--) - rpcrdma_unmap_one(ia, --seg); - } else { - seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey; - seg1->mr_base = seg1->mr_dma + pageoff; - seg1->mr_nsegs = nsegs; - seg1->mr_len = len; - } - } + rc = rpcrdma_register_fmr_external(seg, &nsegs, writing, ia); break; /* Registration using memory windows */ case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS: - { - struct ib_mw_bind param; - rpcrdma_map_one(ia, seg, writing); - param.mr = ia->ri_bind_mem; - param.wr_id = 0ULL; /* no send cookie */ - param.addr = seg->mr_dma; - param.length = seg->mr_len; - param.send_flags = 0; - param.mw_access_flags = mem_priv; - - DECR_CQCOUNT(&r_xprt->rx_ep); - rc = ib_bind_mw(ia->ri_id->qp, - seg->mr_chunk.rl_mw->r.mw, ¶m); - if (rc) { - dprintk("RPC: %s: failed ib_bind_mw " - "%u@0x%llx status %i\n", - __func__, seg->mr_len, - (unsigned long long)seg->mr_dma, rc); - rpcrdma_unmap_one(ia, seg); - } else { - seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; - seg->mr_base = param.addr; - seg->mr_nsegs = 1; - nsegs = 1; - } - } + rc = rpcrdma_register_memwin_external(seg, &nsegs, writing, ia, r_xprt); break; /* Default registration each time */ default: - { - struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS]; - int len = 0; - if (nsegs > RPCRDMA_MAX_DATA_SEGS) - nsegs = RPCRDMA_MAX_DATA_SEGS; - for (i = 0; i < nsegs;) { - rpcrdma_map_one(ia, seg, writing); - ipb[i].addr = seg->mr_dma; - ipb[i].size = seg->mr_len; - len += seg->mr_len; - ++seg; - ++i; - /* Check for holes */ - if ((i < nsegs && offset_in_page(seg->mr_offset)) || - offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) - break; - } - nsegs = i; - seg1->mr_base = seg1->mr_dma; - seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd, - ipb, nsegs, mem_priv, &seg1->mr_base); - if (IS_ERR(seg1->mr_chunk.rl_mr)) { - rc = PTR_ERR(seg1->mr_chunk.rl_mr); - dprintk("RPC: %s: failed ib_reg_phys_mr " - "%u@0x%llx (%d)... status %i\n", - __func__, len, - (unsigned long long)seg1->mr_dma, nsegs, rc); - while (nsegs--) - rpcrdma_unmap_one(ia, --seg); - } else { - seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey; - seg1->mr_nsegs = nsegs; - seg1->mr_len = len; - } - } + rc = rpcrdma_register_default_external(seg, &nsegs, writing, ia); break; } if (rc) @@ -1473,7 +1562,6 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, struct rpcrdma_xprt *r_xprt, void *r) { struct rpcrdma_ia *ia = &r_xprt->rx_ia; - struct rpcrdma_mr_seg *seg1 = seg; int nsegs = seg->mr_nsegs, rc; switch (ia->ri_memreg_strategy) { @@ -1487,55 +1575,16 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, #endif case RPCRDMA_MTHCAFMR: - { - LIST_HEAD(l); - list_add(&seg->mr_chunk.rl_mw->r.fmr->list, &l); - rc = ib_unmap_fmr(&l); - while (seg1->mr_nsegs--) - rpcrdma_unmap_one(ia, seg++); - } - if (rc) - dprintk("RPC: %s: failed ib_unmap_fmr," - " status %i\n", __func__, rc); + rc = rpcrdma_deregister_fmr_external(seg, ia); break; case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS: - { - struct ib_mw_bind param; - BUG_ON(nsegs != 1); - param.mr = ia->ri_bind_mem; - param.addr = 0ULL; /* unbind */ - param.length = 0; - param.mw_access_flags = 0; - if (r) { - param.wr_id = (u64) (unsigned long) r; - param.send_flags = IB_SEND_SIGNALED; - INIT_CQCOUNT(&r_xprt->rx_ep); - } else { - param.wr_id = 0ULL; - param.send_flags = 0; - DECR_CQCOUNT(&r_xprt->rx_ep); - } - rc = ib_bind_mw(ia->ri_id->qp, - seg->mr_chunk.rl_mw->r.mw, ¶m); - rpcrdma_unmap_one(ia, seg); - } - if (rc) - dprintk("RPC: %s: failed ib_(un)bind_mw," - " status %i\n", __func__, rc); - else - r = NULL; /* will upcall on completion */ + rc = rpcrdma_deregister_memwin_external(seg, ia, r_xprt, &r); break; default: - rc = ib_dereg_mr(seg1->mr_chunk.rl_mr); - seg1->mr_chunk.rl_mr = NULL; - while (seg1->mr_nsegs--) - rpcrdma_unmap_one(ia, seg++); - if (rc) - dprintk("RPC: %s: failed ib_dereg_mr," - " status %i\n", __func__, rc); + rc = rpcrdma_deregister_default_external(seg, ia); break; } if (r) { -- GitLab From fe9053b30bb48b99f7b45541249f5cfe96bdf7f7 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 14:59:59 -0400 Subject: [PATCH 3724/5416] RPC/RDMA: add data types and new FRMR memory registration enum. Internal RPC/RDMA structure updates in preparation for FRMR support. Signed-off-by: Tom Talpey Acked-by: Tom Tucker Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprtrdma.h | 1 + net/sunrpc/xprtrdma/xprt_rdma.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/sunrpc/xprtrdma.h b/include/linux/sunrpc/xprtrdma.h index 4de56b1d372..55a5d92ca1e 100644 --- a/include/linux/sunrpc/xprtrdma.h +++ b/include/linux/sunrpc/xprtrdma.h @@ -78,6 +78,7 @@ enum rpcrdma_memreg { RPCRDMA_MEMWINDOWS, RPCRDMA_MEMWINDOWS_ASYNC, RPCRDMA_MTHCAFMR, + RPCRDMA_FRMR, RPCRDMA_ALLPHYSICAL, RPCRDMA_LAST }; diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 2427822f8bd..05b7898e1f4 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -58,6 +58,8 @@ struct rpcrdma_ia { struct rdma_cm_id *ri_id; struct ib_pd *ri_pd; struct ib_mr *ri_bind_mem; + u32 ri_dma_lkey; + int ri_have_dma_lkey; struct completion ri_done; int ri_async_rc; enum rpcrdma_memreg ri_memreg_strategy; @@ -156,6 +158,10 @@ struct rpcrdma_mr_seg { /* chunk descriptors */ union { struct ib_mw *mw; struct ib_fmr *fmr; + struct { + struct ib_fast_reg_page_list *fr_pgl; + struct ib_mr *fr_mr; + } frmr; } r; struct list_head mw_list; } *rl_mw; @@ -198,7 +204,7 @@ struct rpcrdma_buffer { atomic_t rb_credits; /* most recent server credits */ unsigned long rb_cwndscale; /* cached framework rpc_cwndscale */ int rb_max_requests;/* client max requests */ - struct list_head rb_mws; /* optional memory windows/fmrs */ + struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ int rb_send_index; struct rpcrdma_req **rb_send_bufs; int rb_recv_index; -- GitLab From bd7ed1d13304d914648dacec4dbb9145aaae614e Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:00:09 -0400 Subject: [PATCH 3725/5416] RPC/RDMA: check selected memory registration mode at runtime. At transport creation, check for, and use, any local dma lkey. Then, check that the selected memory registration mode is in fact supported by the RDMA adapter selected for the mount. Fall back to best alternative if not. Signed-off-by: Tom Talpey Acked-by: Tom Tucker Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 95 +++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index d04208a02f6..0f3b43148b7 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -423,7 +423,8 @@ rpcrdma_clean_cq(struct ib_cq *cq) int rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) { - int rc; + int rc, mem_priv; + struct ib_device_attr devattr; struct rpcrdma_ia *ia = &xprt->rx_ia; init_completion(&ia->ri_done); @@ -442,6 +443,53 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) goto out2; } + /* + * Query the device to determine if the requested memory + * registration strategy is supported. If it isn't, set the + * strategy to a globally supported model. + */ + rc = ib_query_device(ia->ri_id->device, &devattr); + if (rc) { + dprintk("RPC: %s: ib_query_device failed %d\n", + __func__, rc); + goto out2; + } + + if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) { + ia->ri_have_dma_lkey = 1; + ia->ri_dma_lkey = ia->ri_id->device->local_dma_lkey; + } + + switch (memreg) { + case RPCRDMA_MEMWINDOWS: + case RPCRDMA_MEMWINDOWS_ASYNC: + if (!(devattr.device_cap_flags & IB_DEVICE_MEM_WINDOW)) { + dprintk("RPC: %s: MEMWINDOWS registration " + "specified but not supported by adapter, " + "using slower RPCRDMA_REGISTER\n", + __func__); + memreg = RPCRDMA_REGISTER; + } + break; + case RPCRDMA_MTHCAFMR: + if (!ia->ri_id->device->alloc_fmr) { +#if RPCRDMA_PERSISTENT_REGISTRATION + dprintk("RPC: %s: MTHCAFMR registration " + "specified but not supported by adapter, " + "using riskier RPCRDMA_ALLPHYSICAL\n", + __func__); + memreg = RPCRDMA_ALLPHYSICAL; +#else + dprintk("RPC: %s: MTHCAFMR registration " + "specified but not supported by adapter, " + "using slower RPCRDMA_REGISTER\n", + __func__); + memreg = RPCRDMA_REGISTER; +#endif + } + break; + } + /* * Optionally obtain an underlying physical identity mapping in * order to do a memory window-based bind. This base registration @@ -450,22 +498,27 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) * revoked after the corresponding completion similar to a storage * adapter. */ - if (memreg > RPCRDMA_REGISTER) { - int mem_priv = IB_ACCESS_LOCAL_WRITE; - switch (memreg) { + switch (memreg) { + case RPCRDMA_BOUNCEBUFFERS: + case RPCRDMA_REGISTER: + break; #if RPCRDMA_PERSISTENT_REGISTRATION - case RPCRDMA_ALLPHYSICAL: - mem_priv |= IB_ACCESS_REMOTE_WRITE; - mem_priv |= IB_ACCESS_REMOTE_READ; - break; + case RPCRDMA_ALLPHYSICAL: + mem_priv = IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_READ; + goto register_setup; #endif - case RPCRDMA_MEMWINDOWS_ASYNC: - case RPCRDMA_MEMWINDOWS: - mem_priv |= IB_ACCESS_MW_BIND; - break; - default: + case RPCRDMA_MEMWINDOWS_ASYNC: + case RPCRDMA_MEMWINDOWS: + mem_priv = IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_MW_BIND; + goto register_setup; + case RPCRDMA_MTHCAFMR: + if (ia->ri_have_dma_lkey) break; - } + mem_priv = IB_ACCESS_LOCAL_WRITE; + register_setup: ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); if (IS_ERR(ia->ri_bind_mem)) { printk(KERN_ALERT "%s: ib_get_dma_mr for " @@ -475,7 +528,15 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) memreg = RPCRDMA_REGISTER; ia->ri_bind_mem = NULL; } + break; + default: + printk(KERN_ERR "%s: invalid memory registration mode %d\n", + __func__, memreg); + rc = -EINVAL; + goto out2; } + dprintk("RPC: %s: memory registration strategy is %d\n", + __func__, memreg); /* Else will do memory reg/dereg for each chunk */ ia->ri_memreg_strategy = memreg; @@ -1248,7 +1309,11 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len, va, len, DMA_BIDIRECTIONAL); iov->length = len; - if (ia->ri_bind_mem != NULL) { + if (ia->ri_have_dma_lkey) { + *mrp = NULL; + iov->lkey = ia->ri_dma_lkey; + return 0; + } else if (ia->ri_bind_mem != NULL) { *mrp = NULL; iov->lkey = ia->ri_bind_mem->lkey; return 0; -- GitLab From 3197d309f5fb042499b2c4c8f2fcb67372df5201 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:00:20 -0400 Subject: [PATCH 3726/5416] RPC/RDMA: support FRMR client memory registration. Configure, detect and use "fastreg" support from IB/iWARP verbs layer to perform RPC/RDMA memory registration. Make FRMR the default memreg mode (will fall back if not supported by the selected RDMA adapter). This allows full and optimal operation over the cxgb3 adapter, and others. Signed-off-by: Tom Talpey Acked-by: Tom Tucker Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/transport.c | 6 +- net/sunrpc/xprtrdma/verbs.c | 167 +++++++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 6 deletions(-) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index a564c1a39ec..89970b0a4cc 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -70,11 +70,7 @@ static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; static unsigned int xprt_rdma_inline_write_padding; -#if !RPCRDMA_PERSISTENT_REGISTRATION -static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_REGISTER; /* FMR? */ -#else -static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_ALLPHYSICAL; -#endif +static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR; #ifdef RPC_DEBUG diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 0f3b43148b7..39a165202d8 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -485,6 +485,26 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) "using slower RPCRDMA_REGISTER\n", __func__); memreg = RPCRDMA_REGISTER; +#endif + } + break; + case RPCRDMA_FRMR: + /* Requires both frmr reg and local dma lkey */ + if ((devattr.device_cap_flags & + (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) != + (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) { +#if RPCRDMA_PERSISTENT_REGISTRATION + dprintk("RPC: %s: FRMR registration " + "specified but not supported by adapter, " + "using riskier RPCRDMA_ALLPHYSICAL\n", + __func__); + memreg = RPCRDMA_ALLPHYSICAL; +#else + dprintk("RPC: %s: FRMR registration " + "specified but not supported by adapter, " + "using slower RPCRDMA_REGISTER\n", + __func__); + memreg = RPCRDMA_REGISTER; #endif } break; @@ -501,6 +521,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) switch (memreg) { case RPCRDMA_BOUNCEBUFFERS: case RPCRDMA_REGISTER: + case RPCRDMA_FRMR: break; #if RPCRDMA_PERSISTENT_REGISTRATION case RPCRDMA_ALLPHYSICAL: @@ -602,6 +623,12 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, ep->rep_attr.srq = NULL; ep->rep_attr.cap.max_send_wr = cdata->max_requests; switch (ia->ri_memreg_strategy) { + case RPCRDMA_FRMR: + /* Add room for frmr register and invalidate WRs */ + ep->rep_attr.cap.max_send_wr *= 3; + if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) + return -EINVAL; + break; case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS: /* Add room for mw_binds+unbinds - overkill! */ @@ -684,6 +711,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, break; case RPCRDMA_MTHCAFMR: case RPCRDMA_REGISTER: + case RPCRDMA_FRMR: ep->rep_remote_cma.responder_resources = cdata->max_requests * (RPCRDMA_MAX_DATA_SEGS / 8); break; @@ -935,7 +963,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, * 2. arrays of struct rpcrdma_req to fill in pointers * 3. array of struct rpcrdma_rep for replies * 4. padding, if any - * 5. mw's or fmr's, if any + * 5. mw's, fmr's or frmr's, if any * Send/recv buffers in req/rep need to be registered */ @@ -943,6 +971,10 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *)); len += cdata->padding; switch (ia->ri_memreg_strategy) { + case RPCRDMA_FRMR: + len += buf->rb_max_requests * RPCRDMA_MAX_SEGS * + sizeof(struct rpcrdma_mw); + break; case RPCRDMA_MTHCAFMR: /* TBD we are perhaps overallocating here */ len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * @@ -991,6 +1023,30 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, INIT_LIST_HEAD(&buf->rb_mws); r = (struct rpcrdma_mw *)p; switch (ia->ri_memreg_strategy) { + case RPCRDMA_FRMR: + for (i = buf->rb_max_requests * RPCRDMA_MAX_SEGS; i; i--) { + r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd, + RPCRDMA_MAX_SEGS); + if (IS_ERR(r->r.frmr.fr_mr)) { + rc = PTR_ERR(r->r.frmr.fr_mr); + dprintk("RPC: %s: ib_alloc_fast_reg_mr" + " failed %i\n", __func__, rc); + goto out; + } + r->r.frmr.fr_pgl = + ib_alloc_fast_reg_page_list(ia->ri_id->device, + RPCRDMA_MAX_SEGS); + if (IS_ERR(r->r.frmr.fr_pgl)) { + rc = PTR_ERR(r->r.frmr.fr_pgl); + dprintk("RPC: %s: " + "ib_alloc_fast_reg_page_list " + "failed %i\n", __func__, rc); + goto out; + } + list_add(&r->mw_list, &buf->rb_mws); + ++r; + } + break; case RPCRDMA_MTHCAFMR: /* TBD we are perhaps overallocating here */ for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { @@ -1126,6 +1182,15 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) struct rpcrdma_mw, mw_list); list_del(&r->mw_list); switch (ia->ri_memreg_strategy) { + case RPCRDMA_FRMR: + rc = ib_dereg_mr(r->r.frmr.fr_mr); + if (rc) + dprintk("RPC: %s:" + " ib_dereg_mr" + " failed %i\n", + __func__, rc); + ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); + break; case RPCRDMA_MTHCAFMR: rc = ib_dealloc_fmr(r->r.fmr); if (rc) @@ -1228,6 +1293,7 @@ rpcrdma_buffer_put(struct rpcrdma_req *req) req->rl_reply = NULL; } switch (ia->ri_memreg_strategy) { + case RPCRDMA_FRMR: case RPCRDMA_MTHCAFMR: case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS: @@ -1390,6 +1456,96 @@ rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg) seg->mr_dma, seg->mr_dmalen, seg->mr_dir); } +static int +rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, + int *nsegs, int writing, struct rpcrdma_ia *ia, + struct rpcrdma_xprt *r_xprt) +{ + struct rpcrdma_mr_seg *seg1 = seg; + struct ib_send_wr frmr_wr, *bad_wr; + u8 key; + int len, pageoff; + int i, rc; + + pageoff = offset_in_page(seg1->mr_offset); + seg1->mr_offset -= pageoff; /* start of page */ + seg1->mr_len += pageoff; + len = -pageoff; + if (*nsegs > RPCRDMA_MAX_DATA_SEGS) + *nsegs = RPCRDMA_MAX_DATA_SEGS; + for (i = 0; i < *nsegs;) { + rpcrdma_map_one(ia, seg, writing); + seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; + len += seg->mr_len; + ++seg; + ++i; + /* Check for holes */ + if ((i < *nsegs && offset_in_page(seg->mr_offset)) || + offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) + break; + } + dprintk("RPC: %s: Using frmr %p to map %d segments\n", + __func__, seg1->mr_chunk.rl_mw, i); + + /* Bump the key */ + key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF); + ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key); + + /* Prepare FRMR WR */ + memset(&frmr_wr, 0, sizeof frmr_wr); + frmr_wr.opcode = IB_WR_FAST_REG_MR; + frmr_wr.send_flags = 0; /* unsignaled */ + frmr_wr.wr.fast_reg.iova_start = (unsigned long)seg1->mr_dma; + frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; + frmr_wr.wr.fast_reg.page_list_len = i; + frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; + frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; + frmr_wr.wr.fast_reg.access_flags = (writing ? + IB_ACCESS_REMOTE_WRITE : IB_ACCESS_REMOTE_READ); + frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; + DECR_CQCOUNT(&r_xprt->rx_ep); + + rc = ib_post_send(ia->ri_id->qp, &frmr_wr, &bad_wr); + + if (rc) { + dprintk("RPC: %s: failed ib_post_send for register," + " status %i\n", __func__, rc); + while (i--) + rpcrdma_unmap_one(ia, --seg); + } else { + seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; + seg1->mr_base = seg1->mr_dma + pageoff; + seg1->mr_nsegs = i; + seg1->mr_len = len; + } + *nsegs = i; + return rc; +} + +static int +rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg, + struct rpcrdma_ia *ia, struct rpcrdma_xprt *r_xprt) +{ + struct rpcrdma_mr_seg *seg1 = seg; + struct ib_send_wr invalidate_wr, *bad_wr; + int rc; + + while (seg1->mr_nsegs--) + rpcrdma_unmap_one(ia, seg++); + + memset(&invalidate_wr, 0, sizeof invalidate_wr); + invalidate_wr.opcode = IB_WR_LOCAL_INV; + invalidate_wr.send_flags = 0; /* unsignaled */ + invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; + DECR_CQCOUNT(&r_xprt->rx_ep); + + rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); + if (rc) + dprintk("RPC: %s: failed ib_post_send for invalidate," + " status %i\n", __func__, rc); + return rc; +} + static int rpcrdma_register_fmr_external(struct rpcrdma_mr_seg *seg, int *nsegs, int writing, struct rpcrdma_ia *ia) @@ -1600,6 +1756,11 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg, break; #endif + /* Registration using frmr registration */ + case RPCRDMA_FRMR: + rc = rpcrdma_register_frmr_external(seg, &nsegs, writing, ia, r_xprt); + break; + /* Registration using fmr memory registration */ case RPCRDMA_MTHCAFMR: rc = rpcrdma_register_fmr_external(seg, &nsegs, writing, ia); @@ -1639,6 +1800,10 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, break; #endif + case RPCRDMA_FRMR: + rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt); + break; + case RPCRDMA_MTHCAFMR: rc = rpcrdma_deregister_fmr_external(seg, ia); break; -- GitLab From b334eaabf4f92226d2df13c613888a507f03da99 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Thu, 9 Oct 2008 15:00:30 -0400 Subject: [PATCH 3727/5416] RPC/RDMA: fix connection IRD/ORD setting This logic sets the connection parameter that configures the local device and informs the remote peer how many concurrent incoming RDMA_READ requests are supported. The original logic didn't really do what was intended for two reasons: - The max number supported by the device is typically smaller than any one factor in the calculation used, and - The field in the connection parameter structure where the value is stored is a u8 and always overflows for the default settings. So what really happens is the value requested for responder resources is the left over 8 bits from the "desired value". If the desired value happened to be a multiple of 256, the result was zero and it wouldn't connect at all. Given the above and the fact that max_requests is almost always larger than the max responder resources supported by the adapter, this patch simplifies this logic and simply requests the max supported by the device, subject to a reasonable limit. This bug was found by Jim Schutt at Sandia. Signed-off-by: Tom Tucker Acked-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 51 ++++++++++--------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 39a165202d8..e3fe9054fef 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -705,30 +705,13 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, ep->rep_remote_cma.private_data_len = 0; /* Client offers RDMA Read but does not initiate */ - switch (ia->ri_memreg_strategy) { - case RPCRDMA_BOUNCEBUFFERS: + ep->rep_remote_cma.initiator_depth = 0; + if (ia->ri_memreg_strategy == RPCRDMA_BOUNCEBUFFERS) ep->rep_remote_cma.responder_resources = 0; - break; - case RPCRDMA_MTHCAFMR: - case RPCRDMA_REGISTER: - case RPCRDMA_FRMR: - ep->rep_remote_cma.responder_resources = cdata->max_requests * - (RPCRDMA_MAX_DATA_SEGS / 8); - break; - case RPCRDMA_MEMWINDOWS: - case RPCRDMA_MEMWINDOWS_ASYNC: -#if RPCRDMA_PERSISTENT_REGISTRATION - case RPCRDMA_ALLPHYSICAL: -#endif - ep->rep_remote_cma.responder_resources = cdata->max_requests * - (RPCRDMA_MAX_DATA_SEGS / 2); - break; - default: - break; - } - if (ep->rep_remote_cma.responder_resources > devattr.max_qp_rd_atom) + else if (devattr.max_qp_rd_atom > 32) /* arbitrary but <= 255 */ + ep->rep_remote_cma.responder_resources = 32; + else ep->rep_remote_cma.responder_resources = devattr.max_qp_rd_atom; - ep->rep_remote_cma.initiator_depth = 0; ep->rep_remote_cma.retry_count = 7; ep->rep_remote_cma.flow_control = 0; @@ -858,14 +841,6 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) { } } - /* Theoretically a client initiator_depth > 0 is not needed, - * but many peers fail to complete the connection unless they - * == responder_resources! */ - if (ep->rep_remote_cma.initiator_depth != - ep->rep_remote_cma.responder_resources) - ep->rep_remote_cma.initiator_depth = - ep->rep_remote_cma.responder_resources; - ep->rep_connected = 0; rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma); @@ -894,14 +869,16 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) { if (ep->rep_connected <= 0) { /* Sometimes, the only way to reliably connect to remote * CMs is to use same nonzero values for ORD and IRD. */ - ep->rep_remote_cma.initiator_depth = - ep->rep_remote_cma.responder_resources; - if (ep->rep_remote_cma.initiator_depth == 0) - ++ep->rep_remote_cma.initiator_depth; - if (ep->rep_remote_cma.responder_resources == 0) - ++ep->rep_remote_cma.responder_resources; - if (retry_count++ == 0) + if (retry_count++ <= RDMA_CONNECT_RETRY_MAX + 1 && + (ep->rep_remote_cma.responder_resources == 0 || + ep->rep_remote_cma.initiator_depth != + ep->rep_remote_cma.responder_resources)) { + if (ep->rep_remote_cma.responder_resources == 0) + ep->rep_remote_cma.responder_resources = 1; + ep->rep_remote_cma.initiator_depth = + ep->rep_remote_cma.responder_resources; goto retry; + } rc = ep->rep_connected; } else { dprintk("RPC: %s: connected\n", __func__); -- GitLab From ba9e64b1c23f1dd22fea14c310f739d84ac8b748 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 10 Oct 2008 12:10:30 -0700 Subject: [PATCH 3728/5416] gre: fix copy and paste error The flags are dumped twice, the keys not at all. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0d5e35b0ed5..c0755e98b81 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1539,8 +1539,8 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) NLA_PUT_U32(skb, IFLA_GRE_LINK, p->link); NLA_PUT_BE16(skb, IFLA_GRE_IFLAGS, p->i_flags); NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags); - NLA_PUT_BE32(skb, IFLA_GRE_IFLAGS, p->i_flags); - NLA_PUT_BE32(skb, IFLA_GRE_OFLAGS, p->o_flags); + NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key); + NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key); NLA_PUT(skb, IFLA_GRE_LOCAL, 4, &p->iph.saddr); NLA_PUT(skb, IFLA_GRE_REMOTE, 4, &p->iph.daddr); NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl); -- GitLab From 575448bd36208f99fe0dd554a43518d798966740 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:00:40 -0400 Subject: [PATCH 3729/5416] RPC/RDMA: suppress retransmit on RPC/RDMA clients. An RPC/RDMA client cannot retransmit on an unbroken connection, doing so violates its flow control with the server. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/rpc_rdma.c | 2 ++ net/sunrpc/xprtrdma/transport.c | 16 ++++++++++++---- net/sunrpc/xprtrdma/xprt_rdma.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index e55427f73df..721dae795d6 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -681,6 +681,8 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep) struct rpc_xprt *xprt = ep->rep_xprt; spin_lock_bh(&xprt->transport_lock); + if (++xprt->connect_cookie == 0) /* maintain a reserved value */ + ++xprt->connect_cookie; if (ep->rep_connected > 0) { if (!xprt_test_and_set_connected(xprt)) xprt_wake_pending_tasks(xprt, 0); diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 89970b0a4cc..0aefc648538 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -587,6 +587,7 @@ xprt_rdma_allocate(struct rpc_task *task, size_t size) } dprintk("RPC: %s: size %zd, request 0x%p\n", __func__, size, req); out: + req->rl_connect_cookie = 0; /* our reserved value */ return req->rl_xdr_buf; outfail: @@ -690,13 +691,20 @@ xprt_rdma_send_request(struct rpc_task *task) req->rl_reply->rr_xprt = xprt; } - if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { - xprt_disconnect_done(xprt); - return -ENOTCONN; /* implies disconnect */ - } + /* Must suppress retransmit to maintain credits */ + if (req->rl_connect_cookie == xprt->connect_cookie) + goto drop_connection; + req->rl_connect_cookie = xprt->connect_cookie; + + if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) + goto drop_connection; rqst->rq_bytes_sent = 0; return 0; + +drop_connection: + xprt_disconnect_done(xprt); + return -ENOTCONN; /* implies disconnect */ } static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 05b7898e1f4..2db2344d487 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -181,6 +181,7 @@ struct rpcrdma_req { size_t rl_size; /* actual length of buffer */ unsigned int rl_niovs; /* 0, 2 or 4 */ unsigned int rl_nchunks; /* non-zero if chunks */ + unsigned int rl_connect_cookie; /* retry detection */ struct rpcrdma_buffer *rl_buffer; /* home base for this structure */ struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */ -- GitLab From ad0e9e01da4ece70ff524b49c77c5e850d5dd53e Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:00:50 -0400 Subject: [PATCH 3730/5416] RPC/RDMA: maintain the RPC task bytes-sent statistic. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/transport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 0aefc648538..ec6d1e7a194 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -699,6 +699,7 @@ xprt_rdma_send_request(struct rpc_task *task) if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) goto drop_connection; + task->tk_bytes_sent += rqst->rq_snd_buf.len; rqst->rq_bytes_sent = 0; return 0; -- GitLab From 4d74f8ba1fb152ae07eb858abb713e094e77b7d5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 10 Oct 2008 12:11:06 -0700 Subject: [PATCH 3731/5416] gre: minor cleanups in netlink interface - use typeful helpers for IFLA_GRE_LOCAL/IFLA_GRE_REMOTE - replace magic value by FIELD_SIZEOF - use MODULE_ALIAS_RTNL_LINK macro Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c0755e98b81..05ebce2881e 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1368,10 +1368,10 @@ static void ipgre_netlink_parms(struct nlattr *data[], parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); if (data[IFLA_GRE_LOCAL]) - memcpy(&parms->iph.saddr, nla_data(data[IFLA_GRE_LOCAL]), 4); + parms->iph.saddr = nla_get_be32(data[IFLA_GRE_LOCAL]); if (data[IFLA_GRE_REMOTE]) - memcpy(&parms->iph.daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); + parms->iph.daddr = nla_get_be32(data[IFLA_GRE_REMOTE]); if (data[IFLA_GRE_TTL]) parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); @@ -1541,8 +1541,8 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) NLA_PUT_BE16(skb, IFLA_GRE_OFLAGS, p->o_flags); NLA_PUT_BE32(skb, IFLA_GRE_IKEY, p->i_key); NLA_PUT_BE32(skb, IFLA_GRE_OKEY, p->o_key); - NLA_PUT(skb, IFLA_GRE_LOCAL, 4, &p->iph.saddr); - NLA_PUT(skb, IFLA_GRE_REMOTE, 4, &p->iph.daddr); + NLA_PUT_BE32(skb, IFLA_GRE_LOCAL, p->iph.saddr); + NLA_PUT_BE32(skb, IFLA_GRE_REMOTE, p->iph.daddr); NLA_PUT_U8(skb, IFLA_GRE_TTL, p->iph.ttl); NLA_PUT_U8(skb, IFLA_GRE_TOS, p->iph.tos); NLA_PUT_U8(skb, IFLA_GRE_PMTUDISC, !!(p->iph.frag_off & htons(IP_DF))); @@ -1559,8 +1559,8 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, [IFLA_GRE_IKEY] = { .type = NLA_U32 }, [IFLA_GRE_OKEY] = { .type = NLA_U32 }, - [IFLA_GRE_LOCAL] = { .len = 4 }, - [IFLA_GRE_REMOTE] = { .len = 4 }, + [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, + [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, [IFLA_GRE_TTL] = { .type = NLA_U8 }, [IFLA_GRE_TOS] = { .type = NLA_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, @@ -1643,5 +1643,5 @@ static void __exit ipgre_fini(void) module_init(ipgre_init); module_exit(ipgre_fini); MODULE_LICENSE("GPL"); -MODULE_ALIAS("rtnl-link-gre"); -MODULE_ALIAS("rtnl-link-gretap"); +MODULE_ALIAS_RTNL_LINK("gre"); +MODULE_ALIAS_RTNL_LINK("gretap"); -- GitLab From fee08caf943e8ed3446ce42fa085b5e7e5f08d92 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:00 -0400 Subject: [PATCH 3732/5416] RPC/RDMA: avoid an oops due to disconnect racing with async upcalls. RDMA disconnects yield an upcall from the RDMA connection manager, which can race with rpc transport close, e.g. on ^C of a mount. Ensure any rdma cm_id and qp are fully destroyed before continuing. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index e3fe9054fef..d94f379f36d 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -565,6 +565,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) return 0; out2: rdma_destroy_id(ia->ri_id); + ia->ri_id = NULL; out1: return rc; } @@ -585,15 +586,17 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia) dprintk("RPC: %s: ib_dereg_mr returned %i\n", __func__, rc); } - if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp) - rdma_destroy_qp(ia->ri_id); + if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) { + if (ia->ri_id->qp) + rdma_destroy_qp(ia->ri_id); + rdma_destroy_id(ia->ri_id); + ia->ri_id = NULL; + } if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) { rc = ib_dealloc_pd(ia->ri_pd); dprintk("RPC: %s: ib_dealloc_pd returned %i\n", __func__, rc); } - if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) - rdma_destroy_id(ia->ri_id); } /* @@ -751,21 +754,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) if (rc) dprintk("RPC: %s: rpcrdma_ep_disconnect" " returned %i\n", __func__, rc); + rdma_destroy_qp(ia->ri_id); + ia->ri_id->qp = NULL; } - ep->rep_func = NULL; - /* padding - could be done in rpcrdma_buffer_destroy... */ if (ep->rep_pad_mr) { rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad); ep->rep_pad_mr = NULL; } - if (ia->ri_id->qp) { - rdma_destroy_qp(ia->ri_id); - ia->ri_id->qp = NULL; - } - rpcrdma_clean_cq(ep->rep_cq); rc = ib_destroy_cq(ep->rep_cq); if (rc) -- GitLab From 9191ca3b381b15b9a88785a8ae2fa4db8e553b0c Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:11 -0400 Subject: [PATCH 3733/5416] RPC/RDMA: adhere to protocol for unpadded client trailing write chunks. The RPC/RDMA protocol allows clients and servers to avoid RDMA operations for data which is purely the result of XDR padding. On the client, automatically insert the necessary padding for such server replies, and optionally don't marshal such chunks. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/rpc_rdma.c | 21 +++++++++++++++++++-- net/sunrpc/xprtrdma/transport.c | 9 +++++++++ net/sunrpc/xprtrdma/xprt_rdma.h | 5 +++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 721dae795d6..d245c0bf787 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -118,6 +118,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos, } if (xdrbuf->tail[0].iov_len) { + /* the rpcrdma protocol allows us to omit any trailing + * xdr pad bytes, saving the server an RDMA operation. */ + if (xdrbuf->tail[0].iov_len < 4 && xprt_rdma_pad_optimize) + return n; if (n == nsegs) return 0; seg[n].mr_page = NULL; @@ -594,7 +598,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b * Scatter inline received data back into provided iov's. */ static void -rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) +rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) { int i, npages, curlen, olen; char *destp; @@ -660,6 +664,13 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) } else rqst->rq_rcv_buf.tail[0].iov_len = 0; + if (pad) { + /* implicit padding on terminal chunk */ + unsigned char *p = rqst->rq_rcv_buf.tail[0].iov_base; + while (pad--) + p[rqst->rq_rcv_buf.tail[0].iov_len++] = 0; + } + if (copy_len) dprintk("RPC: %s: %d bytes in" " %d extra segments (%d lost)\n", @@ -794,14 +805,20 @@ repost: ((unsigned char *)iptr - (unsigned char *)headerp); status = rep->rr_len + rdmalen; r_xprt->rx_stats.total_rdma_reply += rdmalen; + /* special case - last chunk may omit padding */ + if (rdmalen &= 3) { + rdmalen = 4 - rdmalen; + status += rdmalen; + } } else { /* else ordinary inline */ + rdmalen = 0; iptr = (__be32 *)((unsigned char *)headerp + 28); rep->rr_len -= 28; /*sizeof *headerp;*/ status = rep->rr_len; } /* Fix up the rpc results for upper layer */ - rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); + rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len, rdmalen); break; case __constant_htonl(RDMA_NOMSG): diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index ec6d1e7a194..c7d2380bb5e 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -71,6 +71,7 @@ static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; static unsigned int xprt_rdma_inline_write_padding; static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR; + int xprt_rdma_pad_optimize = 0; #ifdef RPC_DEBUG @@ -135,6 +136,14 @@ static ctl_table xr_tunables_table[] = { .extra1 = &min_memreg, .extra2 = &max_memreg, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "rdma_pad_optimize", + .data = &xprt_rdma_pad_optimize, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0, }, diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 2db2344d487..fde6499a53b 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -280,6 +280,11 @@ struct rpcrdma_xprt { #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt) #define rpcx_to_rdmad(x) (rpcx_to_rdmax(x)->rx_data) +/* Setting this to 0 ensures interoperability with early servers. + * Setting this to 1 enhances certain unaligned read/write performance. + * Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */ +extern int xprt_rdma_pad_optimize; + /* * Interface Adapter calls - xprtrdma/verbs.c */ -- GitLab From 291d5f30399c258344c71069552b82b694bb2b34 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 10 Oct 2008 12:12:41 -0700 Subject: [PATCH 3734/5416] cg6: disable cursor when leaving graphics mode On sparc32 debian etch, the cursor is not disabled when leaving X windows. This patch disables the cursor when leaving graphics mode just like the ffb driver. Signed-off-by: Robert Reif Signed-off-by: David S. Miller --- drivers/video/cg6.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 9eaa63ab08f..940ec04f0f1 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *); static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); +static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); static int cg6_sync(struct fb_info *); static int cg6_mmap(struct fb_info *, struct vm_area_struct *); static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); -static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); +static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* * Frame buffer operations @@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = { .owner = THIS_MODULE, .fb_setcolreg = cg6_setcolreg, .fb_blank = cg6_blank, + .fb_pan_display = cg6_pan_display, .fb_fillrect = cg6_fillrect, .fb_copyarea = cg6_copyarea, .fb_imageblit = cg6_imageblit, @@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = { #define CG6_THC_MISC_INT_ENAB (1 << 5) #define CG6_THC_MISC_INT (1 << 4) #define CG6_THC_MISC_INIT 0x9f +#define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16)) /* The contents are unknown */ struct cg6_tec { @@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info) return 0; } +static void cg6_switch_from_graph(struct cg6_par *par) +{ + struct cg6_thc __iomem *thc = par->thc; + unsigned long flags; + + spin_lock_irqsave(&par->lock, flags); + + /* Hide the cursor. */ + sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); + + spin_unlock_irqrestore(&par->lock, flags); +} + +static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct cg6_par *par = (struct cg6_par *)info->par; + + /* We just use this to catch switches out of + * graphics mode. + */ + cg6_switch_from_graph(par); + + if (var->xoffset || var->yoffset || var->vmode) + return -EINVAL; + return 0; +} + /** * cg6_fillrect - Draws a rectangle on the screen. * @@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info) struct cg6_par *par = (struct cg6_par *)info->par; struct cg6_tec __iomem *tec = par->tec; struct cg6_fbc __iomem *fbc = par->fbc; + struct cg6_thc __iomem *thc = par->thc; u32 rev, conf, mode; int i; + /* Hide the cursor. */ + sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); + /* Turn off stuff in the Transform Engine. */ sbus_writel(0, &tec->tec_matrix); sbus_writel(0, &tec->tec_clip); -- GitLab From 926449ba66ce2a45c619bbe755b00d6bdbf0d83e Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:21 -0400 Subject: [PATCH 3735/5416] RPC/RDMA: return a consistent error, when connect fails. The xprt_connect call path does not expect such errors as ECONNREFUSED to be returned from failed transport connection attempts, otherwise it translates them to EIO and signals fatal errors. For example, mount.nfs prints simply "internal error". Translate all such errors to ENOTCONN from RPC/RDMA to match sockets behavior. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/rpc_rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index d245c0bf787..94ecf1b65ff 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -699,7 +699,7 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep) xprt_wake_pending_tasks(xprt, 0); } else { if (xprt_test_and_clear_connected(xprt)) - xprt_wake_pending_tasks(xprt, ep->rep_connected); + xprt_wake_pending_tasks(xprt, -ENOTCONN); } spin_unlock_bh(&xprt->transport_lock); } -- GitLab From 1a954051b0cf79bd67e5f9db40333e3a9b1d05d2 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:31 -0400 Subject: [PATCH 3736/5416] RPC/RDMA: fix connect/reconnect resource leak. The RPC/RDMA code can leak RDMA connection manager endpoints in certain error cases on connect. Don't signal unwanted events, and be certain to destroy any allocated qp. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index d94f379f36d..a63d0c0ec01 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -338,10 +338,8 @@ connected: wake_up_all(&ep->rep_connect_wait); break; default: - ia->ri_async_rc = -EINVAL; - dprintk("RPC: %s: unexpected CM event %X\n", + dprintk("RPC: %s: unexpected CM event %d\n", __func__, event->event); - complete(&ia->ri_done); break; } @@ -355,6 +353,8 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rdma_cm_id *id; int rc; + init_completion(&ia->ri_done); + id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP); if (IS_ERR(id)) { rc = PTR_ERR(id); @@ -427,8 +427,6 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) struct ib_device_attr devattr; struct rpcrdma_ia *ia = &xprt->rx_ia; - init_completion(&ia->ri_done); - ia->ri_id = rpcrdma_create_id(xprt, ia, addr); if (IS_ERR(ia->ri_id)) { rc = PTR_ERR(ia->ri_id); @@ -815,6 +813,7 @@ retry: goto out; } /* END TEMP */ + rdma_destroy_qp(ia->ri_id); rdma_destroy_id(ia->ri_id); ia->ri_id = id; } -- GitLab From 4dd95b63ae25c5cad6986829b5e8788e9faa0330 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 10 Oct 2008 12:13:22 -0700 Subject: [PATCH 3737/5416] leo: disable cursor when leaving graphics mode On sparc32 debian etch, the cursor is not disabled when leaving X windows. This patch disables the cursor when leaving graphics mode just like the ffb driver. Signed-off-by: Robert Reif Signed-off-by: David S. Miller --- drivers/video/leo.c | 94 +++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 465459e5eae..7c7e8c2da9d 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *); static int leo_mmap(struct fb_info *, struct vm_area_struct *); static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); +static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* * Frame buffer operations @@ -42,6 +43,7 @@ static struct fb_ops leo_ops = { .owner = THIS_MODULE, .fb_setcolreg = leo_setcolreg, .fb_blank = leo_blank, + .fb_pan_display = leo_pan_display, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, @@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn) return; } +static void leo_switch_from_graph(struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_ld_ss0 __iomem *ss = par->ld_ss0; + struct leo_cursor __iomem *cursor = par->cursor; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&par->lock, flags); + + par->extent = ((info->var.xres - 1) | + ((info->var.yres - 1) << 16)); + + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xffff, &ss->wmask); + sbus_writel(0, &ss->vclipmin); + sbus_writel(par->extent, &ss->vclipmax); + sbus_writel(0, &ss->fg); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(0, &ss->widclip); + sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), + &par->lc_ss0_usr->extent); + sbus_writel(4, &par->lc_ss0_usr->addrspace); + sbus_writel(0x80000000, &par->lc_ss0_usr->fill); + sbus_writel(0, &par->lc_ss0_usr->fontt); + do { + val = sbus_readl(&par->lc_ss0_usr->csr); + } while (val & 0x20000000); + + /* setup screen buffer for cfb_* functions */ + sbus_writel(1, &ss->wid); + sbus_writel(0x00ffffff, &ss->planemask); + sbus_writel(0x310b90, &ss->rop); + sbus_writel(0, &par->lc_ss0_usr->addrspace); + + /* hide cursor */ + sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc); + + spin_unlock_irqrestore(&par->lock, flags); +} + +static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + /* We just use this to catch switches out of + * graphics mode. + */ + leo_switch_from_graph(info); + + if (var->xoffset || var->yoffset || var->vmode) + return -EINVAL; + return 0; +} + /** * leo_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function @@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info) leo_wid_put(info, &wl); } -static void leo_switch_from_graph(struct fb_info *info) -{ - struct leo_par *par = (struct leo_par *) info->par; - struct leo_ld_ss0 __iomem *ss = par->ld_ss0; - unsigned long flags; - u32 val; - - spin_lock_irqsave(&par->lock, flags); - - par->extent = ((info->var.xres - 1) | - ((info->var.yres - 1) << 16)); - - sbus_writel(0xffffffff, &ss->wid); - sbus_writel(0xffff, &ss->wmask); - sbus_writel(0, &ss->vclipmin); - sbus_writel(par->extent, &ss->vclipmax); - sbus_writel(0, &ss->fg); - sbus_writel(0xff000000, &ss->planemask); - sbus_writel(0x310850, &ss->rop); - sbus_writel(0, &ss->widclip); - sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), - &par->lc_ss0_usr->extent); - sbus_writel(4, &par->lc_ss0_usr->addrspace); - sbus_writel(0x80000000, &par->lc_ss0_usr->fill); - sbus_writel(0, &par->lc_ss0_usr->fontt); - do { - val = sbus_readl(&par->lc_ss0_usr->csr); - } while (val & 0x20000000); - - /* setup screen buffer for cfb_* functions */ - sbus_writel(1, &ss->wid); - sbus_writel(0x00ffffff, &ss->planemask); - sbus_writel(0x310b90, &ss->rop); - sbus_writel(0, &par->lc_ss0_usr->addrspace); - - spin_unlock_irqrestore(&par->lock, flags); -} - static void leo_init_hw(struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; -- GitLab From 5675add36e76b9487e7f9e689f854cb8d6afd9b4 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:41 -0400 Subject: [PATCH 3738/5416] RPC/RDMA: harden connection logic against missing/late rdma_cm upcalls. Add defensive timeouts to wait_for_completion() calls in RDMA address resolution, and make them interruptible. Fix the timeout units to milliseconds (formerly jiffies) and move to private header. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprtrdma.h | 3 --- net/sunrpc/xprtrdma/verbs.c | 11 +++++++---- net/sunrpc/xprtrdma/xprt_rdma.h | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/sunrpc/xprtrdma.h b/include/linux/sunrpc/xprtrdma.h index 55a5d92ca1e..54a379c9e8e 100644 --- a/include/linux/sunrpc/xprtrdma.h +++ b/include/linux/sunrpc/xprtrdma.h @@ -66,9 +66,6 @@ #define RPCRDMA_INLINE_PAD_THRESH (512)/* payload threshold to pad (bytes) */ -#define RDMA_RESOLVE_TIMEOUT (5*HZ) /* TBD 5 seconds */ -#define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ - /* memory registration strategies */ #define RPCRDMA_PERSISTENT_REGISTRATION (1) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index a63d0c0ec01..f46fb93f421 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -284,6 +284,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) switch (event->event) { case RDMA_CM_EVENT_ADDR_RESOLVED: case RDMA_CM_EVENT_ROUTE_RESOLVED: + ia->ri_async_rc = 0; complete(&ia->ri_done); break; case RDMA_CM_EVENT_ADDR_ERROR: @@ -363,26 +364,28 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, return id; } - ia->ri_async_rc = 0; + ia->ri_async_rc = -ETIMEDOUT; rc = rdma_resolve_addr(id, NULL, addr, RDMA_RESOLVE_TIMEOUT); if (rc) { dprintk("RPC: %s: rdma_resolve_addr() failed %i\n", __func__, rc); goto out; } - wait_for_completion(&ia->ri_done); + wait_for_completion_interruptible_timeout(&ia->ri_done, + msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT) + 1); rc = ia->ri_async_rc; if (rc) goto out; - ia->ri_async_rc = 0; + ia->ri_async_rc = -ETIMEDOUT; rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT); if (rc) { dprintk("RPC: %s: rdma_resolve_route() failed %i\n", __func__, rc); goto out; } - wait_for_completion(&ia->ri_done); + wait_for_completion_interruptible_timeout(&ia->ri_done, + msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT) + 1); rc = ia->ri_async_rc; if (rc) goto out; diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index fde6499a53b..c7a7eba991b 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -51,6 +51,9 @@ #include /* RPC/RDMA protocol */ #include /* xprt parameters */ +#define RDMA_RESOLVE_TIMEOUT (5000) /* 5 seconds */ +#define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ + /* * Interface Adapter -- one per transport instance */ -- GitLab From 5f37d561e0f0cd98017c389cbc22080290f11c3c Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:01:52 -0400 Subject: [PATCH 3739/5416] RPC/RDMA: reformat a debug printk to keep lines together. The send marshaling code split a particular dprintk across two lines, which makes it hard to extract from logfiles. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 94ecf1b65ff..15101f294e0 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -512,8 +512,8 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) if (hdrlen == 0) return -1; - dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd\n" - " headerp 0x%p base 0x%p lkey 0x%x\n", + dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd" + " headerp 0x%p base 0x%p lkey 0x%x\n", __func__, transfertypes[wtype], hdrlen, rpclen, padlen, headerp, base, req->rl_iov.lkey); -- GitLab From b3cd8d45a764e6edb06e7bd386faf99a879569b8 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Thu, 9 Oct 2008 15:02:02 -0400 Subject: [PATCH 3740/5416] RPC/RDMA: optionally emit useful transport info upon connect/disconnect. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/transport.c | 2 +- net/sunrpc/xprtrdma/verbs.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index c7d2380bb5e..c2da680273c 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -784,7 +784,7 @@ static void __exit xprt_rdma_cleanup(void) { int rc; - dprintk("RPCRDMA Module Removed, deregister RPC RDMA transport\n"); + dprintk(KERN_INFO "RPCRDMA Module Removed, deregister RPC RDMA transport\n"); #ifdef RPC_DEBUG if (sunrpc_table_header) { unregister_sysctl_table(sunrpc_table_header); diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index f46fb93f421..170e69cba6c 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -344,6 +344,27 @@ connected: break; } +#ifdef RPC_DEBUG + if (connstate == 1) { + int ird = attr.max_dest_rd_atomic; + int tird = ep->rep_remote_cma.responder_resources; + printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u " + "on %s, memreg %d slots %d ird %d%s\n", + NIPQUAD(addr->sin_addr.s_addr), + ntohs(addr->sin_port), + ia->ri_id->device->name, + ia->ri_memreg_strategy, + xprt->rx_buf.rb_max_requests, + ird, ird < 4 && ird < tird / 2 ? " (low!)" : ""); + } else if (connstate < 0) { + printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u " + "closed (%d)\n", + NIPQUAD(addr->sin_addr.s_addr), + ntohs(addr->sin_port), + connstate); + } +#endif + return 0; } -- GitLab From 08ca0dce1eafa419059ac4cad9ed522af7052526 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Fri, 10 Oct 2008 11:32:34 -0400 Subject: [PATCH 3741/5416] RPC/RDMA: correct the reconnect timer backoff The RPC/RDMA code had a constant 5-second reconnect backoff, and always performed it, even when re-establishing a connection to a server after the RPC layer closed it due to being idle. Make it an geometric backoff (up to 30 seconds), and don't delay idle reconnect. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/transport.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index c2da680273c..9839c3d9414 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -463,6 +463,8 @@ xprt_rdma_close(struct rpc_xprt *xprt) struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); dprintk("RPC: %s: closing\n", __func__); + if (r_xprt->rx_ep.rep_connected > 0) + xprt->reestablish_timeout = 0; xprt_disconnect_done(xprt); (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); } @@ -490,6 +492,11 @@ xprt_rdma_connect(struct rpc_task *task) /* Reconnect */ schedule_delayed_work(&r_xprt->rdma_connect, xprt->reestablish_timeout); + xprt->reestablish_timeout <<= 1; + if (xprt->reestablish_timeout > (30 * HZ)) + xprt->reestablish_timeout = (30 * HZ); + else if (xprt->reestablish_timeout < (5 * HZ)) + xprt->reestablish_timeout = (5 * HZ); } else { schedule_delayed_work(&r_xprt->rdma_connect, 0); if (!RPC_IS_ASYNC(task)) -- GitLab From c055551e97e1ca00781bc41523f829e05a8afed7 Mon Sep 17 00:00:00 2001 From: Tom Talpey Date: Fri, 10 Oct 2008 11:32:45 -0400 Subject: [PATCH 3742/5416] RPC/RDMA: ensure connection attempt is complete before signalling. The RPC/RDMA connection logic could return early from reconnection attempts, leading to additional spurious retries. Signed-off-by: Tom Talpey Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/verbs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 170e69cba6c..a5fef5e6c32 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -804,9 +804,8 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) struct rdma_cm_id *id; int rc = 0; int retry_count = 0; - int reconnect = (ep->rep_connected != 0); - if (reconnect) { + if (ep->rep_connected != 0) { struct rpcrdma_xprt *xprt; retry: rc = rpcrdma_ep_disconnect(ep, ia); @@ -871,9 +870,6 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) { goto out; } - if (reconnect) - return 0; - wait_event_interruptible(ep->rep_connect_wait, ep->rep_connected != 0); /* -- GitLab From 1cf69cfbe117d645640a9230d6deb07c9db46c5f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 10 Oct 2008 12:25:45 -0700 Subject: [PATCH 3743/5416] ath9k: remove nasty FAIL macro from ath9k_hw_reset() This is fucking horribe crap code so nuke it. There I cursed too in a commit log. Signed-off-by: Luis R. Rodriguez Signed-off-by: David S. Miller --- drivers/net/wireless/ath9k/hw.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 62e44a0ef99..372ae61c7b1 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -5867,7 +5867,6 @@ bool ath9k_hw_reset(struct ath_hal *ah, bool bChannelChange, int *status) { -#define FAIL(_code) do { ecode = _code; goto bad; } while (0) u32 saveLedState; struct ath_hal_5416 *ahp = AH5416(ah); struct ath9k_channel *curchan = ah->ah_curchan; @@ -5889,7 +5888,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->channel, chan->channelFlags); - FAIL(-EINVAL); + ecode = -EINVAL; + goto bad; } if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) @@ -5930,7 +5930,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, if (!ath9k_hw_chip_reset(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n", __func__); - FAIL(-EIO); + ecode = -EINVAL; + goto bad; } if (AR_SREV_9280(ah)) { @@ -5947,8 +5948,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, } ecode = ath9k_hw_process_ini(ah, chan, macmode); - if (ecode != 0) + if (ecode != 0) { + ecode = -EINVAL; goto bad; + } if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); @@ -5961,7 +5964,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, if (!ath9k_hw_eeprom_set_board_values(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: error setting board options\n", __func__); - FAIL(-EIO); + ecode = -EIO; + goto bad; } ath9k_hw_decrease_chain_power(ah, chan); @@ -5989,11 +5993,15 @@ bool ath9k_hw_reset(struct ath_hal *ah, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) - FAIL(-EIO); + if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { + ecode = -EIO; + goto bad; + } } else { - if (!(ath9k_hw_set_channel(ah, chan))) - FAIL(-EIO); + if (!(ath9k_hw_set_channel(ah, chan))) { + ecode = -EIO; + goto bad; + } } for (i = 0; i < AR_NUM_DCU; i++) @@ -6027,8 +6035,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, ath9k_hw_init_bb(ah, chan); - if (!ath9k_hw_init_cal(ah, chan)) - FAIL(-ENODEV); + if (!ath9k_hw_init_cal(ah, chan)){ + ecode = -EIO;; + goto bad; + } rx_chainmask = ahp->ah_rxchainmask; if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { @@ -6064,7 +6074,6 @@ bad: if (status) *status = ecode; return false; -#undef FAIL } bool ath9k_hw_phy_disable(struct ath_hal *ah) -- GitLab From d2a3b222cf976bc44bb9aed13f7b17feea28f633 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 10 Oct 2008 12:26:24 -0700 Subject: [PATCH 3744/5416] ath9k: Fix return code when ath9k_hw_setpower() fails on reset We were not reporting a status code back ath9k_hw_setpower() failed during reset so lets correct this. Reported-by: Jiri Slaby Signed-off-by: Luis R. Rodriguez Signed-off-by: David S. Miller --- drivers/net/wireless/ath9k/hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 372ae61c7b1..98bc25c9b3c 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -5892,8 +5892,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, goto bad; } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { + ecode = -EIO; + goto bad; + } if (curchan) ath9k_hw_getnf(ah, curchan); -- GitLab From 4bcb3a37180ee4dffaef8298f373b334a7bedabb Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 10 Oct 2008 21:33:04 +0200 Subject: [PATCH 3745/5416] [S390] qdio: speed up multicast traffic on full HiperSocket queue If an asynchronous HiperSockets queue runs full, no further packet can be sent. In this case the next initiative to give transmitted skbs back to the stack is triggered only by a 10-seconds qdio timer. This timer has been introduced for low multicast traffic scenarios to guarantee freeing of skbs in a limited amount of time. For high HiperSocket multicast traffic scenarios progress checking on the outbound queue should be enforced by tasklet rescheduling. Signed-off-by: Ursula Braun Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio.h | 8 ++++++++ drivers/s390/cio/qdio_main.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index c1a70985abf..af867731a5f 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -16,6 +16,14 @@ #define QDIO_BUSY_BIT_GIVE_UP 2000000 /* 2 seconds = eternity */ #define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ +/* + * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait + * till next initiative to give transmitted skbs back to the stack is too long. + * Therefore polling is started in case of multicast queue is filled more + * than 50 percent. + */ +#define QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */ + enum qdio_irq_states { QDIO_IRQ_STATE_INACTIVE, QDIO_IRQ_STATE_ESTABLISHED, diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index e6eabc85342..9307512132f 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -851,6 +851,12 @@ static void __qdio_outbound_processing(struct qdio_q *q) if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) return; + if ((queue_type(q) == QDIO_IQDIO_QFMT) && + (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) { + tasklet_schedule(&q->tasklet); + return; + } + if (q->u.out.pci_out_enabled) return; -- GitLab From 46fbe4e46ddb88805245a24f684400b50ead68a7 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 10 Oct 2008 21:33:05 +0200 Subject: [PATCH 3746/5416] [S390] cio: move device unregistration to dedicated work queue Use dedicated slow path work queue when unregistering a device due to a user action. This ensures serialialization of other register/ unregister requests. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 56 +++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 28221030b88..38a79ecfc74 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -296,36 +296,33 @@ static void ccw_device_unregister(struct ccw_device *cdev) device_del(&cdev->dev); } -static void ccw_device_remove_orphan_cb(struct device *dev) +static void ccw_device_remove_orphan_cb(struct work_struct *work) { - struct ccw_device *cdev = to_ccwdev(dev); + struct ccw_device_private *priv; + struct ccw_device *cdev; + priv = container_of(work, struct ccw_device_private, kick_work); + cdev = priv->cdev; ccw_device_unregister(cdev); put_device(&cdev->dev); + /* Release cdev reference for workqueue processing. */ + put_device(&cdev->dev); } -static void ccw_device_remove_sch_cb(struct device *dev) -{ - struct subchannel *sch; - - sch = to_subchannel(dev); - css_sch_device_unregister(sch); - /* Reset intparm to zeroes. */ - sch->schib.pmcw.intparm = 0; - cio_modify(sch); - put_device(&sch->dev); -} +static void ccw_device_call_sch_unregister(struct work_struct *work); static void ccw_device_remove_disconnected(struct ccw_device *cdev) { unsigned long flags; - int rc; /* * Forced offline in disconnected state means * 'throw away device'. */ + /* Get cdev reference for workqueue processing. */ + if (!get_device(&cdev->dev)) + return; if (ccw_device_is_orphan(cdev)) { /* * Deregister ccw device. @@ -335,23 +332,13 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) spin_lock_irqsave(cdev->ccwlock, flags); cdev->private->state = DEV_STATE_NOT_OPER; spin_unlock_irqrestore(cdev->ccwlock, flags); - rc = device_schedule_callback(&cdev->dev, - ccw_device_remove_orphan_cb); - if (rc) - CIO_MSG_EVENT(0, "Couldn't unregister orphan " - "0.%x.%04x\n", - cdev->private->dev_id.ssid, - cdev->private->dev_id.devno); - return; - } - /* Deregister subchannel, which will kill the ccw device. */ - rc = device_schedule_callback(cdev->dev.parent, - ccw_device_remove_sch_cb); - if (rc) - CIO_MSG_EVENT(0, "Couldn't unregister disconnected device " - "0.%x.%04x\n", - cdev->private->dev_id.ssid, - cdev->private->dev_id.devno); + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_remove_orphan_cb); + } else + /* Deregister subchannel, which will kill the ccw device. */ + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_call_sch_unregister); + queue_work(slow_path_wq, &cdev->private->kick_work); } /** @@ -970,12 +957,17 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; + /* Get subchannel reference for local processing. */ + if (!get_device(cdev->dev.parent)) + return; sch = to_subchannel(cdev->dev.parent); css_sch_device_unregister(sch); /* Reset intparm to zeroes. */ sch->schib.pmcw.intparm = 0; cio_modify(sch); + /* Release cdev reference for workqueue processing.*/ put_device(&cdev->dev); + /* Release subchannel reference for local processing. */ put_device(&sch->dev); } @@ -1001,6 +993,8 @@ io_subchannel_recog_done(struct ccw_device *cdev) PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister); queue_work(slow_path_wq, &cdev->private->kick_work); + /* Release subchannel reference for asynchronous recognition. */ + put_device(&sch->dev); if (atomic_dec_and_test(&ccw_device_init_count)) wake_up(&ccw_device_init_wq); break; -- GitLab From ecf5d9ef68b868b293b40b89615a92de7310d065 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 10 Oct 2008 21:33:06 +0200 Subject: [PATCH 3747/5416] [S390] cio: introduce purge function for /proc/cio_ignore Allow users to remove blacklisted ccw devices by using the /proc/cio_ignore interface: echo purge > /proc/cio_ignore will remove all devices which are offline and blacklisted. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 11 ++++++---- drivers/s390/cio/device.c | 40 ++++++++++++++++++++++++++++++++++++ drivers/s390/cio/device.h | 1 + 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 0bfcbbe375c..2f547b840ef 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -24,6 +24,7 @@ #include "cio.h" #include "cio_debug.h" #include "css.h" +#include "device.h" /* * "Blacklisting" of certain devices: @@ -191,9 +192,9 @@ static int blacklist_parse_parameters(char *str, range_action action, rc = blacklist_range(ra, from_ssid, to_ssid, from, to, msgtrigger); if (rc) - totalrc = 1; + totalrc = -EINVAL; } else - totalrc = 1; + totalrc = -EINVAL; } return totalrc; @@ -240,8 +241,10 @@ static int blacklist_parse_proc_parameters(char *buf) rc = blacklist_parse_parameters(buf, free, 0); else if (strcmp("add", parm) == 0) rc = blacklist_parse_parameters(buf, add, 0); + else if (strcmp("purge", parm) == 0) + return ccw_purge_blacklisted(); else - return 1; + return -EINVAL; css_schedule_reprobe(); @@ -353,7 +356,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf, } ret = blacklist_parse_proc_parameters(buf); if (ret) - rc = -EINVAL; + rc = ret; else rc = user_len; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 38a79ecfc74..8575d263b13 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -31,6 +31,7 @@ #include "device.h" #include "ioasm.h" #include "io_sch.h" +#include "blacklist.h" static struct timer_list recovery_timer; static DEFINE_SPINLOCK(recovery_lock); @@ -1470,6 +1471,45 @@ static void ccw_device_schedule_recovery(void) spin_unlock_irqrestore(&recovery_lock, flags); } +static int purge_fn(struct device *dev, void *data) +{ + struct ccw_device *cdev = to_ccwdev(dev); + struct ccw_device_private *priv = cdev->private; + int unreg; + + spin_lock_irq(cdev->ccwlock); + unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) && + (priv->state == DEV_STATE_OFFLINE); + spin_unlock_irq(cdev->ccwlock); + if (!unreg) + goto out; + if (!get_device(&cdev->dev)) + goto out; + CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, + priv->dev_id.devno); + PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister); + queue_work(slow_path_wq, &cdev->private->kick_work); + +out: + /* Abort loop in case of pending signal. */ + if (signal_pending(current)) + return -EINTR; + + return 0; +} + +/** + * ccw_purge_blacklisted - purge unused, blacklisted devices + * + * Unregister all ccw devices that are offline and on the blacklist. + */ +int ccw_purge_blacklisted(void) +{ + CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n"); + bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn); + return 0; +} + static void device_set_disconnected(struct ccw_device *cdev) { if (!cdev) diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 6f5c3f2b358..104ed669db4 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -86,6 +86,7 @@ int ccw_device_is_orphan(struct ccw_device *); int ccw_device_recognition(struct ccw_device *); int ccw_device_online(struct ccw_device *); int ccw_device_offline(struct ccw_device *); +int ccw_purge_blacklisted(void); /* Function prototypes for device status and basic sense stuff. */ void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); -- GitLab From d45387d8bce2674fd21369a394933a02b8125878 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:07 +0200 Subject: [PATCH 3748/5416] [S390] cio: Update cio_ignore documentation. Add documentation for the new "purge" cio_ignore parameter. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- Documentation/s390/CommonIO | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO index bf0baa19ec2..428e5c859b6 100644 --- a/Documentation/s390/CommonIO +++ b/Documentation/s390/CommonIO @@ -70,13 +70,19 @@ Command line parameters Note: While already known devices can be added to the list of devices to be ignored, there will be no effect on then. However, if such a device - disappears and then reappears, it will then be ignored. + disappears and then reappears, it will then be ignored. To make + known devices go away, you need the "purge" command (see below). For example, "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore" will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored devices. + You can remove already known but now ignored devices via + "echo purge > /proc/cio_ignore" + All devices ignored but still registered and not online (= not in use) + will be deregistered and thus removed from the system. + The devices can be specified either by bus id (0.x.abcd) or, for 2.4 backward compatibility, by the device number in hexadecimal (0xabcd or abcd). Device numbers given as 0xabcd will be interpreted as 0.0.abcd. -- GitLab From e4a1afaeb1d9ebc09f46d8b229ac96116974b1b8 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:08 +0200 Subject: [PATCH 3749/5416] [S390] cio: Exorcise cio_msg= from documentation. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- Documentation/s390/CommonIO | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO index 428e5c859b6..339207d11d9 100644 --- a/Documentation/s390/CommonIO +++ b/Documentation/s390/CommonIO @@ -104,8 +104,7 @@ debugfs entries handling). - /sys/kernel/debug/s390dbf/cio_msg/sprintf - Various debug messages from the common I/O-layer, including messages - printed when cio_msg=yes. + Various debug messages from the common I/O-layer. - /sys/kernel/debug/s390dbf/cio_trace/hex_ascii Logs the calling of functions in the common I/O-layer and, if applicable, -- GitLab From 2a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 10 Oct 2008 21:33:09 +0200 Subject: [PATCH 3750/5416] [S390] bus_id -> dev_name conversions bus_id -> dev_name() conversions in s390 code. [cornelia.huck@de.ibm.com: minor adaptions] Signed-off-by: Kay Sievers Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 32 +++---- drivers/s390/block/dasd_3990_erp.c | 2 +- drivers/s390/block/dasd_devmap.c | 28 +++--- drivers/s390/block/dasd_eckd.c | 6 +- drivers/s390/block/dasd_eer.c | 6 +- drivers/s390/block/dasd_fba.c | 4 +- drivers/s390/block/dasd_int.h | 4 +- drivers/s390/block/dasd_proc.c | 2 +- drivers/s390/block/dcssblk.c | 5 +- drivers/s390/char/tape_3590.c | 132 +++++++++++++++-------------- drivers/s390/char/tape_block.c | 2 +- drivers/s390/char/tape_core.c | 21 ++--- drivers/s390/char/tape_proc.c | 2 +- drivers/s390/char/tape_std.c | 13 +-- drivers/s390/char/vmlogrdr.c | 2 +- drivers/s390/char/vmur.c | 6 +- drivers/s390/cio/ccwgroup.c | 2 +- drivers/s390/cio/cio.c | 16 ++-- drivers/s390/cio/device.c | 4 +- drivers/s390/cio/device_fsm.c | 6 +- drivers/s390/cio/device_ops.c | 2 +- drivers/s390/net/claw.c | 23 ++--- drivers/s390/net/claw.h | 2 +- drivers/s390/net/ctcm_main.c | 18 ++-- drivers/s390/net/ctcm_main.h | 2 +- drivers/s390/net/lcs.c | 34 ++++---- drivers/s390/net/qeth_core.h | 10 +-- drivers/s390/net/qeth_core_main.c | 10 +-- drivers/s390/scsi/zfcp_def.h | 2 +- 29 files changed, 207 insertions(+), 191 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index acb78017e7d..0a225ccda02 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -215,7 +215,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device) return rc; } /* register 'device' debug area, used for all DBF_DEV_XXX calls */ - device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 1, + device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1, 8 * sizeof(long)); debug_register_view(device->debug_area, &debug_sprintf_view); debug_set_level(device->debug_area, DBF_WARNING); @@ -933,7 +933,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, MESSAGE(KERN_DEBUG, "invalid status in handle_killed_request: " "bus_id %s, status %02x", - cdev->dev.bus_id, cqr->status); + dev_name(&cdev->dev), cqr->status); return; } @@ -942,7 +942,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, device != dasd_device_from_cdev_locked(cdev) || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", - cdev->dev.bus_id); + dev_name(&cdev->dev)); return; } @@ -982,11 +982,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, break; case -ETIMEDOUT: printk(KERN_WARNING"%s(%s): request timed out\n", - __func__, cdev->dev.bus_id); + __func__, dev_name(&cdev->dev)); break; default: printk(KERN_WARNING"%s(%s): unknown error %ld\n", - __func__, cdev->dev.bus_id, PTR_ERR(irb)); + __func__, dev_name(&cdev->dev), PTR_ERR(irb)); } dasd_handle_killed_request(cdev, intparm); return; @@ -995,7 +995,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, now = get_clock(); DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x", - cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) | + dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), (unsigned int) intparm); /* check for unsolicited interrupts */ @@ -1019,7 +1019,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, if (!device || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", - cdev->dev.bus_id); + dev_name(&cdev->dev)); return; } @@ -1037,7 +1037,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, if (cqr->status != DASD_CQR_IN_IO) { MESSAGE(KERN_DEBUG, "invalid status: bus_id %s, status %02x", - cdev->dev.bus_id, cqr->status); + dev_name(&cdev->dev), cqr->status); return; } DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p", @@ -2134,14 +2134,14 @@ int dasd_generic_probe(struct ccw_device *cdev, if (ret) { printk(KERN_WARNING "dasd_generic_probe: could not set ccw-device options " - "for %s\n", cdev->dev.bus_id); + "for %s\n", dev_name(&cdev->dev)); return ret; } ret = dasd_add_sysfs_files(cdev); if (ret) { printk(KERN_WARNING "dasd_generic_probe: could not add sysfs entries " - "for %s\n", cdev->dev.bus_id); + "for %s\n", dev_name(&cdev->dev)); return ret; } cdev->handler = &dasd_int_handler; @@ -2152,13 +2152,13 @@ int dasd_generic_probe(struct ccw_device *cdev, * initial probe. */ if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || - (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0)) + (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) ret = ccw_device_set_online(cdev); if (ret) printk(KERN_WARNING "dasd_generic_probe: could not initially " "online ccw-device %s; return code: %d\n", - cdev->dev.bus_id, ret); + dev_name(&cdev->dev), ret); return 0; } @@ -2224,7 +2224,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, printk (KERN_WARNING "dasd_generic couldn't online device %s " "- discipline DIAG not available\n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); dasd_delete_device(device); return -ENODEV; } @@ -2248,7 +2248,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, printk (KERN_WARNING "dasd_generic couldn't online device %s " "with discipline %s rc=%i\n", - cdev->dev.bus_id, discipline->name, rc); + dev_name(&cdev->dev), discipline->name, rc); module_put(discipline->owner); module_put(base_discipline->owner); dasd_delete_device(device); @@ -2259,7 +2259,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, if (device->state <= DASD_STATE_KNOWN) { printk (KERN_WARNING "dasd_generic discipline not found for %s\n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); rc = -ENODEV; dasd_set_target_state(device, DASD_STATE_NEW); if (device->block) @@ -2267,7 +2267,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, dasd_delete_device(device); } else pr_debug("dasd_generic device %s found\n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); /* FIXME: we have to wait for the root device but we don't want * to wait for each single device but for all at once. */ diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 5c6e6f331cb..b8f9c00633f 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1397,7 +1397,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( DEV_MESSAGE(KERN_ERR, cqr->startdev, "ERP on alias device for request %p," " recover on base device %s", cqr, - cqr->block->base->cdev->dev.bus_id); + dev_name(&cqr->block->base->cdev->dev)); } dasd_eckd_reset_ccw_to_base_io(cqr); erp->startdev = cqr->block->base; diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index cd3335c1c30..921443b01d1 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -515,9 +515,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&cdev->dev)); if (IS_ERR(devmap)) - devmap = dasd_add_busid(cdev->dev.bus_id, + devmap = dasd_add_busid(dev_name(&cdev->dev), DASD_FEATURE_DEFAULT); return devmap; } @@ -584,7 +584,7 @@ dasd_delete_device(struct dasd_device *device) unsigned long flags; /* First remove device pointer from devmap. */ - devmap = dasd_find_busid(device->cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&device->cdev->dev)); BUG_ON(IS_ERR(devmap)); spin_lock(&dasd_devmap_lock); if (devmap->device != device) { @@ -674,7 +674,7 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; int ro_flag; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); if (!IS_ERR(devmap)) ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0; else @@ -723,7 +723,7 @@ dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; int erplog; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); if (!IS_ERR(devmap)) erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0; else @@ -770,7 +770,7 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; int use_diag; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); if (!IS_ERR(devmap)) use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0; else @@ -876,7 +876,7 @@ dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; int alias; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); spin_lock(&dasd_devmap_lock); if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { spin_unlock(&dasd_devmap_lock); @@ -899,7 +899,7 @@ dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; char *vendor; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); spin_lock(&dasd_devmap_lock); if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) vendor = devmap->uid.vendor; @@ -924,7 +924,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) char ua_string[3]; struct dasd_uid *uid; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); spin_lock(&dasd_devmap_lock); if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { spin_unlock(&dasd_devmap_lock); @@ -972,7 +972,7 @@ dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf) struct dasd_devmap *devmap; int eer_flag; - devmap = dasd_find_busid(dev->bus_id); + devmap = dasd_find_busid(dev_name(dev)); if (!IS_ERR(devmap) && devmap->device) eer_flag = dasd_eer_enabled(devmap->device); else @@ -1034,7 +1034,7 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&cdev->dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); spin_lock(&dasd_devmap_lock); @@ -1057,7 +1057,7 @@ dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&cdev->dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); @@ -1077,7 +1077,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&cdev->dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); @@ -1093,7 +1093,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) { struct dasd_devmap *devmap; - devmap = dasd_find_busid(cdev->dev.bus_id); + devmap = dasd_find_busid(dev_name(&cdev->dev)); if (IS_ERR(devmap)) return PTR_ERR(devmap); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 773b3fe275b..72d3970f11a 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -84,7 +84,7 @@ dasd_eckd_probe (struct ccw_device *cdev) if (ret) { printk(KERN_WARNING "dasd_eckd_probe: could not set ccw-device options " - "for %s\n", cdev->dev.bus_id); + "for %s\n", dev_name(&cdev->dev)); return ret; } ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); @@ -2145,13 +2145,13 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, /* dump the sense data */ len = sprintf(page, KERN_ERR PRINTK_HEADER " I/O status report for device %s:\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " in req: %p CS: 0x%02X DS: 0x%02X\n", req, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " device %s: Failing CCW: %p\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), (void *) (addr_t) irb->scsw.cmd.cpa); if (irb->esw.esw0.erw.cons) { for (sl = 0; sl < 4; sl++) { diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index bf512ac75b9..892e2878d61 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -309,7 +309,8 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, do_gettimeofday(&tv); header.tv_sec = tv.tv_sec; header.tv_usec = tv.tv_usec; - strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + strncpy(header.busid, dev_name(&device->cdev->dev), + DASD_EER_BUSID_SIZE); spin_lock_irqsave(&bufferlock, flags); list_for_each_entry(eerb, &bufferlist, list) { @@ -349,7 +350,8 @@ static void dasd_eer_write_snss_trigger(struct dasd_device *device, do_gettimeofday(&tv); header.tv_sec = tv.tv_sec; header.tv_usec = tv.tv_usec; - strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + strncpy(header.busid, dev_name(&device->cdev->dev), + DASD_EER_BUSID_SIZE); spin_lock_irqsave(&bufferlock, flags); list_for_each_entry(eerb, &bufferlist, list) { diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index aa0c533423a..93d9b6452a9 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -451,13 +451,13 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, } len = sprintf(page, KERN_ERR PRINTK_HEADER " I/O status report for device %s:\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " in req: %p CS: 0x%02X DS: 0x%02X\n", req, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " device %s: Failing CCW: %p\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), (void *) (addr_t) irb->scsw.cmd.cpa); if (irb->esw.esw0.erw.cons) { for (sl = 0; sl < 4; sl++) { diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 31ecaa4a40e..489d5fe488f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -126,7 +126,7 @@ do { \ #define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\ do { \ printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \ - d_device->cdev->dev.bus_id, d_args); \ + dev_name(&d_device->cdev->dev), d_args); \ DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \ } while(0) @@ -140,7 +140,7 @@ do { \ #define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\ do { \ printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \ - d_device->cdev->dev.bus_id, d_args); \ + dev_name(&d_device->cdev->dev), d_args); \ } while(0) #define MESSAGE_LOG(d_loglevel,d_string,d_args...)\ diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index e3b5c4d3036..9088de84b45 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -67,7 +67,7 @@ dasd_devices_show(struct seq_file *m, void *v) return 0; } /* Print device number. */ - seq_printf(m, "%s", device->cdev->dev.bus_id); + seq_printf(m, "%s", dev_name(&device->cdev->dev)); /* Print discipline string. */ if (device != NULL && device->discipline != NULL) seq_printf(m, "(%s)", device->discipline->name); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 9481e4a3f76..2aca79e952b 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -91,7 +91,7 @@ static struct rw_semaphore dcssblk_devices_sem; static void dcssblk_release_segment(struct device *dev) { - PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id); + PRINT_DEBUG("segment release fn called for %s\n", dev_name(dev)); kfree(container_of(dev, struct dcssblk_dev_info, dev)); module_put(THIS_MODULE); } @@ -602,7 +602,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) case SEG_TYPE_SC: /* cannot write to these segments */ if (bio_data_dir(bio) == WRITE) { - PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id); + PRINT_WARN("rejecting write to ro segment %s\n", + dev_name(&dev_info->dev)); goto fail; } } diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 839987618ff..4005c44a404 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -910,7 +910,7 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request, * should proceed with the new tape... this * should probably be done in user space! */ - PRINT_WARN("(%s): Swap Tape Device!\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EIO); } @@ -1003,40 +1003,43 @@ tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb) /* Exception Message */ switch (sense->fmt.f70.emc) { case 0x02: - PRINT_WARN("(%s): Data degraded\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): Data degraded\n", + dev_name(&device->cdev->dev)); break; case 0x03: PRINT_WARN("(%s): Data degraded in partion %i\n", - device->cdev->dev.bus_id, sense->fmt.f70.mp); + dev_name(&device->cdev->dev), sense->fmt.f70.mp); break; case 0x04: - PRINT_WARN("(%s): Medium degraded\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): Medium degraded\n", + dev_name(&device->cdev->dev)); break; case 0x05: PRINT_WARN("(%s): Medium degraded in partition %i\n", - device->cdev->dev.bus_id, sense->fmt.f70.mp); + dev_name(&device->cdev->dev), sense->fmt.f70.mp); break; case 0x06: - PRINT_WARN("(%s): Block 0 Error\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): Block 0 Error\n", + dev_name(&device->cdev->dev)); break; case 0x07: PRINT_WARN("(%s): Medium Exception 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f70.md); + dev_name(&device->cdev->dev), sense->fmt.f70.md); break; default: PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f70.emc); + dev_name(&device->cdev->dev), sense->fmt.f70.emc); break; } /* Service Message */ switch (sense->fmt.f70.smc) { case 0x02: PRINT_WARN("(%s): Reference Media maintenance procedure %i\n", - device->cdev->dev.bus_id, sense->fmt.f70.md); + dev_name(&device->cdev->dev), sense->fmt.f70.md); break; default: PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f70.smc); + dev_name(&device->cdev->dev), sense->fmt.f70.smc); break; } } @@ -1054,101 +1057,101 @@ tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb) switch (sense->fmt.f71.emc) { case 0x01: PRINT_WARN("(%s): Effect of failure is unknown\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x02: PRINT_WARN("(%s): CU Exception - no performance impact\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x03: PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x04: PRINT_WARN("(%s): CU Exception on device path 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x05: PRINT_WARN("(%s): CU Exception on library path 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x06: PRINT_WARN("(%s): CU Exception on node 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x07: PRINT_WARN("(%s): CU Exception on partition 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; default: PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.emc); + dev_name(&device->cdev->dev), sense->fmt.f71.emc); } /* Service Message */ switch (sense->fmt.f71.smc) { case 0x01: PRINT_WARN("(%s): Repair impact is unknown\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x02: PRINT_WARN("(%s): Repair will not impact cu performance\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x03: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable node " "0x%x on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable nodes " "(0x%x-0x%x) on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x04: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable cannel path " "0x%x on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable cannel paths " "(0x%x-0x%x) on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x05: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable device path " "0x%x on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable device paths " "(0x%x-0x%x) on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x06: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable library path " "0x%x on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable library paths " "(0x%x-0x%x) on CU\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x07: PRINT_WARN("(%s): Repair will disable access to CU\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; default: PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.smc); + dev_name(&device->cdev->dev), sense->fmt.f71.smc); } } @@ -1165,104 +1168,104 @@ tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb) switch (sense->fmt.f71.emc) { case 0x01: PRINT_WARN("(%s): Effect of failure is unknown\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x02: PRINT_WARN("(%s): DV Exception - no performance impact\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x03: PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x04: PRINT_WARN("(%s): DV Exception on loader 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x05: PRINT_WARN("(%s): DV Exception on message display 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); break; case 0x06: PRINT_WARN("(%s): DV Exception in tape path\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x07: PRINT_WARN("(%s): DV Exception in drive\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; default: PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.emc); + dev_name(&device->cdev->dev), sense->fmt.f71.emc); } /* Service Message */ switch (sense->fmt.f71.smc) { case 0x01: PRINT_WARN("(%s): Repair impact is unknown\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x02: PRINT_WARN("(%s): Repair will not impact device performance\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x03: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable channel path " "0x%x on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable channel path " "(0x%x-0x%x) on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x04: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable interface 0x%x " "on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable interfaces " "(0x%x-0x%x) on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x05: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable loader 0x%x " "on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable loader " "(0x%x-0x%x) on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x07: PRINT_WARN("(%s): Repair will disable access to DV\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case 0x08: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable message " "display 0x%x on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable message " "displays (0x%x-0x%x) on DV\n", - device->cdev->dev.bus_id, + dev_name(&device->cdev->dev), sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x09: - PRINT_WARN("(%s): Clean DV\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev)); break; default: PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n", - device->cdev->dev.bus_id, sense->fmt.f71.smc); + dev_name(&device->cdev->dev), sense->fmt.f71.smc); } } @@ -1279,18 +1282,18 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) return; if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { if (tape_3590_msg[sense->mc] != NULL) - PRINT_WARN("(%s): %s\n", device->cdev->dev.bus_id, + PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev), tape_3590_msg[sense->mc]); else { PRINT_WARN("(%s): Message Code 0x%x\n", - device->cdev->dev.bus_id, sense->mc); + dev_name(&device->cdev->dev), sense->mc); } return; } if (sense->mc == 0xf0) { /* Standard Media Information Message */ PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, " - "RC=%02x-%04x-%02x\n", device->cdev->dev.bus_id, + "RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev), sense->fmt.f70.sev, sense->mc, sense->fmt.f70.emc, sense->fmt.f70.smc, sense->fmt.f70.refcode, sense->fmt.f70.mid, @@ -1302,7 +1305,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) /* Standard I/O Subsystem Service Information Message */ PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, " "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", - device->cdev->dev.bus_id, sense->fmt.f71.sev, + dev_name(&device->cdev->dev), sense->fmt.f71.sev, device->cdev->id.dev_model, sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, sense->fmt.f71.refcode1, @@ -1314,7 +1317,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) /* Standard Device Service Information Message */ PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, " "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", - device->cdev->dev.bus_id, sense->fmt.f71.sev, + dev_name(&device->cdev->dev), sense->fmt.f71.sev, device->cdev->id.dev_model, sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, sense->fmt.f71.refcode1, @@ -1327,7 +1330,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) return; } PRINT_WARN("(%s): Device Message(%x)\n", - device->cdev->dev.bus_id, sense->mc); + dev_name(&device->cdev->dev), sense->mc); } static int tape_3590_crypt_error(struct tape_device *device, @@ -1336,10 +1339,11 @@ static int tape_3590_crypt_error(struct tape_device *device, u8 cu_rc, ekm_rc1; u16 ekm_rc2; u32 drv_rc; - char *bus_id, *sense; + const char *bus_id; + char *sense; sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data; - bus_id = device->cdev->dev.bus_id; + bus_id = dev_name(&device->cdev->dev); cu_rc = sense[0]; drv_rc = *((u32*) &sense[5]) & 0xffffff; ekm_rc1 = sense[9]; @@ -1440,7 +1444,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, * "device intervention" is not very meaningfull */ PRINT_WARN("(%s): Tape operation when medium not loaded\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); tape_med_state_set(device, MS_UNLOADED); tape_3590_schedule_work(device, TO_CRYPT_OFF); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); @@ -1487,18 +1491,18 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, case 0x6020: PRINT_WARN("(%s): Cartridge of wrong type ?\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); case 0x8011: PRINT_WARN("(%s): Another host has reserved the tape device\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EPERM); case 0x8013: PRINT_WARN("(%s): Another host has privileged access to the " - "tape device\n", device->cdev->dev.bus_id); + "tape device\n", dev_name(&device->cdev->dev)); PRINT_WARN("(%s): To solve the problem unload the current " - "cartridge!\n", device->cdev->dev.bus_id); + "cartridge!\n", dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EPERM); default: return tape_3590_erp_basic(device, request, irb, -EIO); diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 95da72bc17e..a25b8bf54f4 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -278,7 +278,7 @@ tapeblock_cleanup_device(struct tape_device *device) if (!device->blk_data.disk) { PRINT_ERR("(%s): No gendisk to clean up!\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); goto cleanup_queue; } diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 181a5441af1..d7073dbf825 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -215,12 +215,12 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) case MS_UNLOADED: device->tape_generic_status |= GMT_DR_OPEN(~0); PRINT_INFO("(%s): Tape is unloaded\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; case MS_LOADED: device->tape_generic_status &= ~GMT_DR_OPEN(~0); PRINT_INFO("(%s): Tape has been mounted\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); break; default: // print nothing @@ -415,7 +415,7 @@ tape_generic_offline(struct tape_device *device) device->cdev_id); PRINT_WARN("(%s): Set offline failed " "- drive in use.\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); spin_unlock_irq(get_ccwdev_lock(device->cdev)); return -EBUSY; } @@ -538,7 +538,8 @@ tape_generic_probe(struct ccw_device *cdev) ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); if (ret) { tape_put_device(device); - PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id); + PRINT_ERR("probe failed for tape device %s\n", + dev_name(&cdev->dev)); return ret; } cdev->dev.driver_data = device; @@ -546,7 +547,7 @@ tape_generic_probe(struct ccw_device *cdev) device->cdev = cdev; ccw_device_get_id(cdev, &dev_id); device->cdev_id = devid_to_int(&dev_id); - PRINT_INFO("tape device %s found\n", cdev->dev.bus_id); + PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev)); return ret; } @@ -616,7 +617,7 @@ tape_generic_remove(struct ccw_device *cdev) device->cdev_id); PRINT_WARN("(%s): Drive in use vanished - " "expect trouble!\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); PRINT_WARN("State was %i\n", device->tape_state); tape_state_set(device, TS_NOT_OPER); __tape_discard_requests(device); @@ -840,7 +841,7 @@ tape_dump_sense(struct tape_device* device, struct tape_request *request, PRINT_INFO("-------------------------------------------------\n"); PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n", irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa); - PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id); + PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev)); if (request != NULL) PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]); @@ -1051,7 +1052,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) device = (struct tape_device *) cdev->dev.driver_data; if (device == NULL) { PRINT_ERR("could not get device structure for %s " - "in interrupt\n", cdev->dev.bus_id); + "in interrupt\n", dev_name(&cdev->dev)); return; } request = (struct tape_request *) intparm; @@ -1064,13 +1065,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) switch (PTR_ERR(irb)) { case -ETIMEDOUT: PRINT_WARN("(%s): Request timed out\n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); case -EIO: __tape_end_request(device, request, -EIO); break; default: PRINT_ERR("(%s): Unexpected i/o error %li\n", - cdev->dev.bus_id, + dev_name(&cdev->dev), PTR_ERR(irb)); } return; diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index e7c888c14e7..8a376af926a 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -52,7 +52,7 @@ static int tape_proc_show(struct seq_file *m, void *v) return 0; spin_lock_irq(get_ccwdev_lock(device->cdev)); seq_printf(m, "%d\t", (int) n); - seq_printf(m, "%-10.10s ", device->cdev->dev.bus_id); + seq_printf(m, "%-10.10s ", dev_name(&device->cdev->dev)); seq_printf(m, "%04X/", device->cdev->id.cu_type); seq_printf(m, "%02X\t", device->cdev->id.cu_model); seq_printf(m, "%04X/", device->cdev->id.dev_type); diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index cc8fd781ee2..5bd573d144d 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -47,7 +47,7 @@ tape_std_assign_timeout(unsigned long data) rc = tape_cancel_io(device, request); if(rc) PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n", - device->cdev->dev.bus_id, rc); + dev_name(&device->cdev->dev), rc); } @@ -83,7 +83,7 @@ tape_std_assign(struct tape_device *device) if (rc != 0) { PRINT_WARN("%s: assign failed - device might be busy\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); DBF_EVENT(3, "%08x: assign failed - device might be busy\n", device->cdev_id); } else { @@ -106,7 +106,7 @@ tape_std_unassign (struct tape_device *device) DBF_EVENT(3, "(%08x): Can't unassign device\n", device->cdev_id); PRINT_WARN("(%s): Can't unassign device - device gone\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); return -EIO; } @@ -120,7 +120,8 @@ tape_std_unassign (struct tape_device *device) if ((rc = tape_do_io(device, request)) != 0) { DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); - PRINT_WARN("%s: Unassign failed\n", device->cdev->dev.bus_id); + PRINT_WARN("%s: Unassign failed\n", + dev_name(&device->cdev->dev)); } else { DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); } @@ -634,10 +635,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count) DBF_EXCEPTION(6, "xcom parm\n"); if (*device->modeset_byte & 0x08) PRINT_INFO("(%s) Compression is currently on\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); else PRINT_INFO("(%s) Compression is currently off\n", - device->cdev->dev.bus_id); + dev_name(&device->cdev->dev)); PRINT_INFO("Use 1 to switch compression on, 0 to " "switch it off\n"); return -EINVAL; diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index c31faefa2b3..036e650e8b9 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -751,7 +751,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) priv->class_device = device_create_drvdata(vmlogrdr_class, dev, MKDEV(vmlogrdr_major, priv->minor_num), - priv, "%s", dev->bus_id); + priv, "%s", dev_name(dev)); if (IS_ERR(priv->class_device)) { ret = PTR_ERR(priv->class_device); priv->class_device=NULL; diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index c1f352b8486..6fdfa5ddeca 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -886,11 +886,11 @@ static int ur_set_online(struct ccw_device *cdev) goto fail_free_cdev; if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) { if (urd->class == DEV_CLASS_UR_I) - sprintf(node_id, "vmrdr-%s", cdev->dev.bus_id); + sprintf(node_id, "vmrdr-%s", dev_name(&cdev->dev)); if (urd->class == DEV_CLASS_UR_O) - sprintf(node_id, "vmpun-%s", cdev->dev.bus_id); + sprintf(node_id, "vmpun-%s", dev_name(&cdev->dev)); } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) { - sprintf(node_id, "vmprt-%s", cdev->dev.bus_id); + sprintf(node_id, "vmprt-%s", dev_name(&cdev->dev)); } else { rc = -EOPNOTSUPP; goto fail_free_cdev; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 9a50f245774..e17b462ace0 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -270,7 +270,7 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, } snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", - gdev->cdev[0]->dev.bus_id); + dev_name(&gdev->cdev[0]->dev)); rc = device_add(&gdev->dev); if (rc) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 326f4cc7f92..8759912734e 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -153,7 +153,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " "subchannel 0.%x.%04x!\n", sch->schid.ssid, sch->schid.sch_no); - sprintf(dbf_text, "no%s", sch->dev.bus_id); + sprintf(dbf_text, "no%s", dev_name(&sch->dev)); CIO_TRACE_EVENT(0, dbf_text); CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); @@ -171,7 +171,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ union orb *orb; CIO_TRACE_EVENT(4, "stIO"); - CIO_TRACE_EVENT(4, sch->dev.bus_id); + CIO_TRACE_EVENT(4, dev_name(&sch->dev)); orb = &to_io_private(sch)->orb; memset(orb, 0, sizeof(union orb)); @@ -232,7 +232,7 @@ cio_resume (struct subchannel *sch) int ccode; CIO_TRACE_EVENT (4, "resIO"); - CIO_TRACE_EVENT (4, sch->dev.bus_id); + CIO_TRACE_EVENT(4, dev_name(&sch->dev)); ccode = rsch (sch->schid); @@ -269,7 +269,7 @@ cio_halt(struct subchannel *sch) return -ENODEV; CIO_TRACE_EVENT (2, "haltIO"); - CIO_TRACE_EVENT (2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); /* * Issue "Halt subchannel" and process condition code @@ -304,7 +304,7 @@ cio_clear(struct subchannel *sch) return -ENODEV; CIO_TRACE_EVENT (2, "clearIO"); - CIO_TRACE_EVENT (2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); /* * Issue "Clear subchannel" and process condition code @@ -340,7 +340,7 @@ cio_cancel (struct subchannel *sch) return -ENODEV; CIO_TRACE_EVENT (2, "cancelIO"); - CIO_TRACE_EVENT (2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); ccode = xsch (sch->schid); @@ -404,7 +404,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) int ret; CIO_TRACE_EVENT (2, "ensch"); - CIO_TRACE_EVENT (2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); if (sch_is_pseudo_sch(sch)) return -EINVAL; @@ -454,7 +454,7 @@ int cio_disable_subchannel(struct subchannel *sch) int ret; CIO_TRACE_EVENT (2, "dissch"); - CIO_TRACE_EVENT (2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); if (sch_is_pseudo_sch(sch)) return 0; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 8575d263b13..95b92dfec5a 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1101,7 +1101,7 @@ static void io_subchannel_irq(struct subchannel *sch) cdev = sch_get_cdev(sch); CIO_TRACE_EVENT(3, "IRQ"); - CIO_TRACE_EVENT(3, sch->dev.bus_id); + CIO_TRACE_EVENT(3, dev_name(&sch->dev)); if (cdev) dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); } @@ -1707,7 +1707,7 @@ __ccwdev_check_busid(struct device *dev, void *id) bus_id = id; - return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0); + return (strncmp(bus_id, dev_name(dev), BUS_ID_SIZE) == 0); } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 84cc9ea346d..10bc03940fb 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -52,8 +52,10 @@ static void ccw_timeout_log(struct ccw_device *cdev) printk(KERN_WARNING "cio: orb:\n"); print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, orb, sizeof(*orb), 0); - printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id); - printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id); + printk(KERN_WARNING "cio: ccw device bus id: %s\n", + dev_name(&cdev->dev)); + printk(KERN_WARNING "cio: subchannel bus id: %s\n", + dev_name(&sch->dev)); printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, " "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm); diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index ee1a28310fb..eabcc42d63d 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -498,7 +498,7 @@ ccw_device_stlck(struct ccw_device *cdev) sch = to_subchannel(cdev->dev.parent); CIO_TRACE_EVENT(2, "stl lock"); - CIO_TRACE_EVENT(2, cdev->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&cdev->dev)); buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL); if (!buf) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index e10ac9ab2d4..26e95858a8f 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -299,7 +299,7 @@ claw_probe(struct ccwgroup_device *cgdev) probe_error(cgdev); put_device(&cgdev->dev); printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n", - cgdev->cdev[0]->dev.bus_id,__func__,__LINE__); + dev_name(&cgdev->cdev[0]->dev), __func__, __LINE__); CLAW_DBF_TEXT_(2, setup, "probex%d", rc); return rc; } @@ -584,7 +584,7 @@ claw_irq_handler(struct ccw_device *cdev, if (!cdev->dev.driver_data) { printk(KERN_WARNING "claw: unsolicited interrupt for device:" "%s received c-%02x d-%02x\n", - cdev->dev.bus_id, irb->scsw.cmd.cstat, + dev_name(&cdev->dev), irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); CLAW_DBF_TEXT(2, trace, "badirq"); return; @@ -598,7 +598,7 @@ claw_irq_handler(struct ccw_device *cdev, p_ch = &privptr->channel[WRITE]; else { printk(KERN_WARNING "claw: Can't determine channel for " - "interrupt, device %s\n", cdev->dev.bus_id); + "interrupt, device %s\n", dev_name(&cdev->dev)); CLAW_DBF_TEXT(2, trace, "badchan"); return; } @@ -662,7 +662,7 @@ claw_irq_handler(struct ccw_device *cdev, printk(KERN_WARNING "claw: unsolicited " "interrupt for device:" "%s received c-%02x d-%02x\n", - cdev->dev.bus_id, + dev_name(&cdev->dev), irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); return; @@ -1136,19 +1136,20 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code) break; case -ENODEV: printk(KERN_EMERG "%s: Missing device called " - "for IO ENODEV\n", cdev->dev.bus_id); + "for IO ENODEV\n", dev_name(&cdev->dev)); break; case -EIO: printk(KERN_EMERG "%s: Status pending... EIO \n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); break; case -EINVAL: printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n", - cdev->dev.bus_id); + dev_name(&cdev->dev)); break; default: printk(KERN_EMERG "%s: Unknown error in " - "Do_IO %d\n",cdev->dev.bus_id, return_code); + "Do_IO %d\n", dev_name(&cdev->dev), + return_code); } } CLAW_DBF_TEXT(4, trace, "ccwret"); @@ -2848,11 +2849,11 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr) struct chbk *p_ch; struct ccw_dev_id dev_id; - CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id); + CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cdev->dev)); privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */ p_ch = &privptr->channel[i]; p_ch->cdev = cdev; - snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id); + snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", dev_name(&cdev->dev)); ccw_device_get_id(cdev, &dev_id); p_ch->devno = dev_id.devno; if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) { @@ -3020,7 +3021,7 @@ claw_remove_device(struct ccwgroup_device *cgdev) priv = cgdev->dev.driver_data; BUG_ON(!priv); printk(KERN_INFO "claw: %s() called %s will be removed.\n", - __func__,cgdev->cdev[0]->dev.bus_id); + __func__, dev_name(&cgdev->cdev[0]->dev)); if (cgdev->state == CCWGROUP_ONLINE) claw_shutdown_device(cgdev); claw_remove_files(&cgdev->dev); diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 1a89d989f34..005072c420d 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -85,7 +85,7 @@ #define CLAW_MAX_DEV 256 /* max claw devices */ #define MAX_NAME_LEN 8 /* host name, adapter name length */ #define CLAW_FRAME_SIZE 4096 -#define CLAW_ID_SIZE BUS_ID_SIZE+3 +#define CLAW_ID_SIZE 20+3 /* state machine codes used in claw_irq_handler */ diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index b11fec24c7d..d2374cf4c4b 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -277,18 +277,18 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb) CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n", - PTR_ERR(irb), cdev->dev.bus_id); + PTR_ERR(irb), dev_name(&cdev->dev)); switch (PTR_ERR(irb)) { case -EIO: - ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id); + ctcm_pr_warn("i/o-error on device %s\n", dev_name(&cdev->dev)); break; case -ETIMEDOUT: - ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id); + ctcm_pr_warn("timeout on device %s\n", dev_name(&cdev->dev)); break; default: ctcm_pr_warn("unknown error %ld on device %s\n", - PTR_ERR(irb), cdev->dev.bus_id); + PTR_ERR(irb), dev_name(&cdev->dev)); } return PTR_ERR(irb); } @@ -1182,7 +1182,7 @@ static void ctcm_irq_handler(struct ccw_device *cdev, int dstat; CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, - "Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id); + "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev)); if (ctcm_check_irb_error(cdev, irb)) return; @@ -1208,14 +1208,14 @@ static void ctcm_irq_handler(struct ccw_device *cdev, ch = priv->channel[WRITE]; else { ctcm_pr_err("ctcm: Can't determine channel for interrupt, " - "device %s\n", cdev->dev.bus_id); + "device %s\n", dev_name(&cdev->dev)); return; } dev = ch->netdev; if (dev == NULL) { ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n", - __func__, cdev->dev.bus_id, ch); + __func__, dev_name(&cdev->dev), ch); return; } @@ -1329,7 +1329,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type, CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s), type %d, proto %d", - __func__, cdev->dev.bus_id, type, priv->protocol); + __func__, dev_name(&cdev->dev), type, priv->protocol); ch = kzalloc(sizeof(struct channel), GFP_KERNEL); if (ch == NULL) @@ -1358,7 +1358,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type, goto nomem_return; ch->cdev = cdev; - snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id); + snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev)); ch->type = type; /** diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index 8e10ee86a5e..d77cce3fe4d 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h @@ -104,7 +104,7 @@ #define READ 0 #define WRITE 1 -#define CTCM_ID_SIZE BUS_ID_SIZE+3 +#define CTCM_ID_SIZE 20+3 struct ctcm_profile { unsigned long maxmulti; diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 9bcfa04d863..0825be87e5a 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -492,7 +492,7 @@ lcs_start_channel(struct lcs_channel *channel) unsigned long flags; int rc; - LCS_DBF_TEXT_(4,trace,"ssch%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace,"ssch%s", dev_name(&channel->ccwdev->dev)); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_start(channel->ccwdev, channel->ccws + channel->io_idx, 0, 0, @@ -501,7 +501,8 @@ lcs_start_channel(struct lcs_channel *channel) channel->state = LCS_CH_STATE_RUNNING; spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4,trace,"essh%s", + dev_name(&channel->ccwdev->dev)); PRINT_ERR("Error in starting channel, rc=%d!\n", rc); } return rc; @@ -514,12 +515,13 @@ lcs_clear_channel(struct lcs_channel *channel) int rc; LCS_DBF_TEXT(4,trace,"clearch"); - LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev)); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_clear(channel->ccwdev, (addr_t) channel); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace, "ecsc%s", + dev_name(&channel->ccwdev->dev)); return rc; } wait_event(channel->wait_q, (channel->state == LCS_CH_STATE_CLEARED)); @@ -540,13 +542,14 @@ lcs_stop_channel(struct lcs_channel *channel) if (channel->state == LCS_CH_STATE_STOPPED) return 0; LCS_DBF_TEXT(4,trace,"haltsch"); - LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev)); channel->state = LCS_CH_STATE_INIT; spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_halt(channel->ccwdev, (addr_t) channel); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - LCS_DBF_TEXT_(4,trace,"ehsc%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace, "ehsc%s", + dev_name(&channel->ccwdev->dev)); return rc; } /* Asynchronous halt initialted. Wait for its completion. */ @@ -632,10 +635,11 @@ __lcs_resume_channel(struct lcs_channel *channel) return 0; if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND) return 0; - LCS_DBF_TEXT_(5, trace, "rsch%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(5, trace, "rsch%s", dev_name(&channel->ccwdev->dev)); rc = ccw_device_resume(channel->ccwdev); if (rc) { - LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(4, trace, "ersc%s", + dev_name(&channel->ccwdev->dev)); PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc); } else channel->state = LCS_CH_STATE_RUNNING; @@ -1302,18 +1306,18 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb) switch (PTR_ERR(irb)) { case -EIO: - PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id); + PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev)); LCS_DBF_TEXT(2, trace, "ckirberr"); LCS_DBF_TEXT_(2, trace, " rc%d", -EIO); break; case -ETIMEDOUT: - PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); + PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev)); LCS_DBF_TEXT(2, trace, "ckirberr"); LCS_DBF_TEXT_(2, trace, " rc%d", -ETIMEDOUT); break; default: PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb), - cdev->dev.bus_id); + dev_name(&cdev->dev)); LCS_DBF_TEXT(2, trace, "ckirberr"); LCS_DBF_TEXT(2, trace, " rc???"); } @@ -1390,7 +1394,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) cstat = irb->scsw.cmd.cstat; dstat = irb->scsw.cmd.dstat; - LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id); + LCS_DBF_TEXT_(5, trace, "Rint%s", dev_name(&cdev->dev)); LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.fctl, @@ -1400,7 +1404,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) rc = lcs_get_problem(cdev, irb); if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) { PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n", - cdev->dev.bus_id, dstat, cstat); + dev_name(&cdev->dev), dstat, cstat); if (rc) { channel->state = LCS_CH_STATE_ERROR; } @@ -1463,7 +1467,7 @@ lcs_tasklet(unsigned long data) int rc; channel = (struct lcs_channel *) data; - LCS_DBF_TEXT_(5, trace, "tlet%s",channel->ccwdev->dev.bus_id); + LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev)); /* Check for processed buffers. */ iob = channel->iob; @@ -2244,7 +2248,7 @@ lcs_recovery(void *ptr) return 0; LCS_DBF_TEXT(4, trace, "recover2"); gdev = card->gdev; - PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id); + PRINT_WARN("Recovery of device %s started...\n", dev_name(&gdev->dev)); rc = __lcs_shutdown_device(gdev, 1); rc = lcs_new_device(gdev); if (!rc) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index bf8a75c92f2..af6d6045851 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -90,11 +90,11 @@ struct qeth_dbf_info { #define CARD_RDEV(card) card->read.ccwdev #define CARD_WDEV(card) card->write.ccwdev #define CARD_DDEV(card) card->data.ccwdev -#define CARD_BUS_ID(card) card->gdev->dev.bus_id -#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id -#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id -#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id -#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id +#define CARD_BUS_ID(card) dev_name(&card->gdev->dev) +#define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev) +#define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev) +#define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev) +#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev) /** * card stuff diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c7ab1b86451..141b2bb7b3c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -745,7 +745,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb) SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) { QETH_DBF_TEXT(TRACE, 2, "CGENCHK"); PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ", - cdev->dev.bus_id, dstat, cstat); + dev_name(&cdev->dev), dstat, cstat); print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET, 16, 1, irb, 64, 1); return 1; @@ -784,12 +784,12 @@ static long __qeth_check_irb_error(struct ccw_device *cdev, switch (PTR_ERR(irb)) { case -EIO: - PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id); + PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev)); QETH_DBF_TEXT(TRACE, 2, "ckirberr"); QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO); break; case -ETIMEDOUT: - PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); + PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev)); QETH_DBF_TEXT(TRACE, 2, "ckirberr"); QETH_DBF_TEXT_(TRACE, 2, " rc%d", -ETIMEDOUT); if (intparm == QETH_RCD_PARM) { @@ -803,7 +803,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev, break; default: PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb), - cdev->dev.bus_id); + dev_name(&cdev->dev)); QETH_DBF_TEXT(TRACE, 2, "ckirberr"); QETH_DBF_TEXT(TRACE, 2, " rc???"); } @@ -4081,7 +4081,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) if (!get_device(dev)) return -ENODEV; - QETH_DBF_TEXT_(SETUP, 2, "%s", gdev->dev.bus_id); + QETH_DBF_TEXT_(SETUP, 2, "%s", dev_name(&gdev->dev)); card = qeth_alloc_card(); if (!card) { diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 73eb41580f2..c69345f1f73 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -596,7 +596,7 @@ struct zfcp_data { struct semaphore config_sema; /* serialises configuration changes */ atomic_t loglevel; /* current loglevel */ - char init_busid[BUS_ID_SIZE]; + char init_busid[20]; u64 init_wwpn; u64 init_fcp_lun; struct kmem_cache *fsf_req_qtcb_cache; -- GitLab From 1bf5b2853925cf92bfc5f0eddb68a8ed18782845 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:10 +0200 Subject: [PATCH 3751/5416] [S390] bus_id -> dev_set_name() changes Convert most s390 users setting bus_id to dev_set_name(). css and ccw busses are deferred since they need some special treatment. Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dcssblk.c | 2 +- drivers/s390/char/vmlogrdr.c | 3 +-- drivers/s390/cio/ccwgroup.c | 3 +-- drivers/s390/cio/chp.c | 3 +-- drivers/s390/cio/css.c | 4 ++-- drivers/s390/crypto/ap_bus.c | 4 ++-- drivers/s390/net/netiucv.c | 2 +- drivers/s390/s390_rdev.c | 2 +- drivers/s390/scsi/zfcp_aux.c | 7 +++---- 9 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 2aca79e952b..ea4272c8c67 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -343,7 +343,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char } strcpy(dev_info->segment_name, local_buf); - strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE); + dev_set_name(&dev_info->dev, local_buf); dev_info->dev.release = dcssblk_release_segment; INIT_LIST_HEAD(&dev_info->lh); diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 036e650e8b9..42173cc3461 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -724,8 +724,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (dev) { - snprintf(dev->bus_id, BUS_ID_SIZE, "%s", - priv->internal_name); + dev_set_name(dev, priv->internal_name); dev->bus = &iucv_bus; dev->parent = iucv_root; dev->driver = &vmlogrdr_driver; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e17b462ace0..3ac2c2019f5 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -269,8 +269,7 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, goto error; } - snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", - dev_name(&gdev->cdev[0]->dev)); + dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); rc = device_add(&gdev->dev); if (rc) diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index f1216cf6fa8..1246f61a533 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -393,8 +393,7 @@ int chp_new(struct chp_id chpid) chp->state = 1; chp->dev.parent = &channel_subsystems[chpid.cssid]->device; chp->dev.release = chp_release; - snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, - chpid.id); + dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id); /* Obtain channel path description and fill it in. */ ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 1261e1a9e8c..76bbb1e74c2 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -698,7 +698,7 @@ static int __init setup_css(int nr) return -ENOMEM; css->pseudo_subchannel->dev.parent = &css->device; css->pseudo_subchannel->dev.release = css_subchannel_release; - sprintf(css->pseudo_subchannel->dev.bus_id, "defunct"); + dev_set_name(&css->pseudo_subchannel->dev, "defunct"); ret = cio_create_sch_lock(css->pseudo_subchannel); if (ret) { kfree(css->pseudo_subchannel); @@ -707,7 +707,7 @@ static int __init setup_css(int nr) mutex_init(&css->mutex); css->valid = 1; css->cssid = nr; - sprintf(css->device.bus_id, "css%x", nr); + dev_set_name(&css->device, "css%x", nr); css->device.release = channel_subsystem_release; tod_high = (u32) (get_clock() >> 32); css_generate_pgid(css, tod_high); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 62b6b55230d..326db1e827c 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -892,8 +892,8 @@ static void ap_scan_bus(struct work_struct *unused) ap_dev->device.bus = &ap_bus_type; ap_dev->device.parent = ap_root_device; - snprintf(ap_dev->device.bus_id, BUS_ID_SIZE, "card%02x", - AP_QID_DEVICE(ap_dev->qid)); + dev_set_name(&ap_dev->device, "card%02x", + AP_QID_DEVICE(ap_dev->qid)); ap_dev->device.release = ap_device_release; rc = device_register(&ap_dev->device); if (rc) { diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 9242b5acc66..0fea51e34b5 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1724,7 +1724,7 @@ static int netiucv_register_device(struct net_device *ndev) IUCV_DBF_TEXT(trace, 3, __func__); if (dev) { - snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name); + dev_set_name(dev, "net%s", ndev->name); dev->bus = &iucv_bus; dev->parent = iucv_root; /* diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index 3c7145d9f9a..64371c05a3b 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c @@ -30,7 +30,7 @@ s390_root_dev_register(const char *name) dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); - strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE)); + dev_set_name(dev, name); dev->release = s390_root_dev_release; ret = device_register(dev); if (ret) { diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 24255e42dc3..3b56220fb90 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -283,8 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) unit->port = port; unit->fcp_lun = fcp_lun; - snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", - (unsigned long long) fcp_lun); + dev_set_name(&unit->sysfs_device, "0x%016llx", + (unsigned long long) fcp_lun); unit->sysfs_device.parent = &port->sysfs_device; unit->sysfs_device.release = zfcp_sysfs_unit_release; dev_set_drvdata(&unit->sysfs_device, unit); @@ -610,8 +610,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set(&port->refcount, 0); - snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", - (unsigned long long) wwpn); + dev_set_name(&port->sysfs_device, "0x%016llx", wwpn); port->sysfs_device.parent = &adapter->ccw_device->dev; port->sysfs_device.release = zfcp_sysfs_port_release; -- GitLab From b9d3aed7e1e50183085fcd2af643bf42d6b4bd95 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:11 +0200 Subject: [PATCH 3752/5416] [S390] more bus_id -> dev_name conversions Some further bus_id -> dev_name() conversions in s390 code. Cc: Kay Sievers Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin Schwidefsky --- drivers/s390/char/raw3270.c | 4 ++-- drivers/s390/cio/device.c | 2 +- drivers/s390/net/claw.c | 13 ++++++++----- drivers/s390/net/ctcm_main.c | 4 ++-- drivers/s390/scsi/zfcp_def.h | 2 +- drivers/s390/scsi/zfcp_erp.c | 2 +- drivers/s390/scsi/zfcp_sysfs.c | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index c3dee900a5c..1792b2c0130 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -1171,7 +1171,7 @@ static int raw3270_create_attributes(struct raw3270 *rp) rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev, MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL, - "tty%s", rp->cdev->dev.bus_id); + "tty%s", dev_name(&rp->cdev->dev)); if (IS_ERR(rp->clttydev)) { rc = PTR_ERR(rp->clttydev); goto out_ttydev; @@ -1180,7 +1180,7 @@ static int raw3270_create_attributes(struct raw3270 *rp) rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev, MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL, - "tub%s", rp->cdev->dev.bus_id); + "tub%s", dev_name(&rp->cdev->dev)); if (!IS_ERR(rp->cltubdev)) goto out; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 95b92dfec5a..a8e755a88b0 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1526,7 +1526,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev) struct subchannel *sch = to_subchannel(cdev->dev.parent); CIO_TRACE_EVENT(2, "notoper"); - CIO_TRACE_EVENT(2, sch->dev.bus_id); + CIO_TRACE_EVENT(2, dev_name(&sch->dev)); ccw_device_set_timeout(cdev, 0); cio_disable_subchannel(sch); cdev->private->state = DEV_STATE_NOT_OPER; diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 26e95858a8f..8f83fc994f5 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2880,7 +2880,8 @@ claw_new_device(struct ccwgroup_device *cgdev) int ret; struct ccw_dev_id dev_id; - printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id); + printk(KERN_INFO "claw: add for %s\n", + dev_name(&cgdev->cdev[READ]->dev)); CLAW_DBF_TEXT(2, setup, "new_dev"); privptr = cgdev->dev.driver_data; cgdev->cdev[READ]->dev.driver_data = privptr; @@ -2904,14 +2905,16 @@ claw_new_device(struct ccwgroup_device *cgdev) if (ret != 0) { printk(KERN_WARNING "claw: ccw_device_set_online %s READ failed " - "with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret); + "with ret = %d\n", dev_name(&cgdev->cdev[READ]->dev), + ret); goto out; } ret = ccw_device_set_online(cgdev->cdev[WRITE]); if (ret != 0) { printk(KERN_WARNING "claw: ccw_device_set_online %s WRITE failed " - "with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret); + "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev) + ret); goto out; } dev = alloc_netdev(0,"claw%d",claw_init_netdevice); @@ -2987,7 +2990,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) struct net_device *ndev; int ret; - CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id); + CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); priv = cgdev->dev.driver_data; if (!priv) return -ENODEV; @@ -3017,7 +3020,7 @@ claw_remove_device(struct ccwgroup_device *cgdev) struct claw_privbk *priv; BUG_ON(!cgdev); - CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id); + CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); priv = cgdev->dev.driver_data; BUG_ON(!priv); printk(KERN_INFO "claw: %s() called %s will be removed.\n", diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index d2374cf4c4b..a4e29836a2a 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1518,8 +1518,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) type = get_channel_type(&cdev0->id); - snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id); - snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id); + snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev)); + snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev)); ret = add_channel(cdev0, type, priv); if (ret) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index c69345f1f73..8a13071c444 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -619,7 +619,7 @@ struct zfcp_fsf_req_qtcb { #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 -#define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id) +#define zfcp_get_busid_by_adapter(adapter) (dev_name(&adapter->ccw_device->dev)) /* * Helper functions for request ID management. diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 78231313187..9040f738ff3 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1376,7 +1376,7 @@ static int zfcp_erp_thread(void *data) struct zfcp_erp_action *act; unsigned long flags; - daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id); + daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev)); /* Block all signals */ siginitsetinv(¤t->blocked, 0); atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 2809d789b55..ca9293ba176 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -381,7 +381,7 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL); ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", - unit->port->adapter->ccw_device->dev.bus_id); + dev_name(&unit->port->adapter->ccw_device->dev)); ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", (unsigned long long) unit->port->wwpn); ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", -- GitLab From 37f1c012f0f23b52df3a0d7850212b336fc9e595 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:12 +0200 Subject: [PATCH 3753/5416] [S390] Use s390_root_dev_* in kvm_virtio. No need to define a static device for the kvm_s390 root device, just use s390_root_dev_register(). This is needed for the bus_id rework Acked-by: Carsten Otte Cc: Kay Sievers Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin Schwidefsky --- drivers/s390/kvm/kvm_virtio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 292b60da6dc..ff4a6931bb8 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -24,6 +24,7 @@ #include #include #include +#include #define VIRTIO_SUBCODE_64 0x0D00 @@ -241,10 +242,7 @@ static struct virtio_config_ops kvm_vq_configspace_ops = { * The root device for the kvm virtio devices. * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2. */ -static struct device kvm_root = { - .parent = NULL, - .bus_id = "kvm_s390", -}; +static struct device *kvm_root; /* * adds a new device and register it with virtio @@ -261,7 +259,7 @@ static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) return; } - kdev->vdev.dev.parent = &kvm_root; + kdev->vdev.dev.parent = kvm_root; kdev->vdev.id.device = d->type; kdev->vdev.config = &kvm_vq_configspace_ops; kdev->desc = d; @@ -317,15 +315,16 @@ static int __init kvm_devices_init(void) if (!MACHINE_IS_KVM) return -ENODEV; - rc = device_register(&kvm_root); - if (rc) { + kvm_root = s390_root_dev_register("kvm_s390"); + if (IS_ERR(kvm_root)) { + rc = PTR_ERR(kvm_root); printk(KERN_ERR "Could not register kvm_s390 root device"); return rc; } rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE); if (rc) { - device_unregister(&kvm_root); + s390_root_dev_unregister(kvm_root); return rc; } -- GitLab From 9286b7ed682615c1508210f85d26e4c9a5cbf126 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:13 +0200 Subject: [PATCH 3754/5416] [S390] bus_id ->dev_name() conversions in qdio Use dev_name() in the new qdio driver. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_debug.c | 2 +- drivers/s390/cio/qdio_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 337aa3087a7..b5390821434 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -155,7 +155,7 @@ static int qstat_seq_open(struct inode *inode, struct file *filp) static void get_queue_name(struct qdio_q *q, struct ccw_device *cdev, char *name) { memset(name, 0, sizeof(name)); - sprintf(name, "%s", cdev->dev.bus_id); + sprintf(name, "%s", dev_name(&cdev->dev)); if (q->is_input_q) sprintf(name + strlen(name), "_input"); else diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 9307512132f..719066ec0c0 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -962,7 +962,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev, char dbf_text[15]; QDIO_DBF_TEXT2(1, trace, "ick2"); - sprintf(dbf_text, "%s", cdev->dev.bus_id); + sprintf(dbf_text, "%s", dev_name(&cdev->dev)); QDIO_DBF_TEXT2(1, trace, dbf_text); QDIO_DBF_HEX2(0, trace, &intparm, sizeof(int)); QDIO_DBF_HEX2(0, trace, &dstat, sizeof(int)); -- GitLab From 1f4e7edabc4071cdff0133e7e04db2d7287d0e36 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 10 Oct 2008 21:33:14 +0200 Subject: [PATCH 3755/5416] [S390] bus_id -> dev_set_name() for css and ccw busses Convert remaining s390 users setting bus_id to dev_set_name() or init_name. Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 13 +++++++++++-- drivers/s390/cio/cio.h | 4 ++++ drivers/s390/cio/device.c | 16 ++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 8759912734e..719d6c406e9 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -571,8 +571,10 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) } mutex_init(&sch->reg_mutex); /* Set a name for the subchannel */ - snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, - schid.sch_no); + if (cio_is_console(schid)) + sch->dev.init_name = cio_get_console_sch_name(schid); + else + dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no); /* * The first subchannel that is not-operational (ccode==3) @@ -677,6 +679,7 @@ do_IRQ (struct pt_regs *regs) #ifdef CONFIG_CCW_CONSOLE static struct subchannel console_subchannel; +static char console_sch_name[10] = "0.x.xxxx"; static struct io_subchannel_private console_priv; static int console_subchannel_in_use; @@ -827,6 +830,12 @@ cio_get_console_subchannel(void) return &console_subchannel; } +const char *cio_get_console_sch_name(struct subchannel_id schid) +{ + snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no); + return (const char *)console_sch_name; +} + #endif static int __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 3b236d20e83..0fb24784e92 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -117,11 +117,15 @@ extern int cio_is_console(struct subchannel_id); extern struct subchannel *cio_get_console_subchannel(void); extern spinlock_t * cio_get_console_lock(void); extern void *cio_get_console_priv(void); +extern const char *cio_get_console_sch_name(struct subchannel_id schid); +extern const char *cio_get_console_cdev_name(struct subchannel *sch); #else #define cio_is_console(schid) 0 #define cio_get_console_subchannel() NULL #define cio_get_console_lock() NULL #define cio_get_console_priv() NULL +#define cio_get_console_sch_name(schid) NULL +#define cio_get_console_cdev_name(sch) NULL #endif #endif diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a8e755a88b0..4e78c82194b 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1035,8 +1035,11 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) init_timer(&priv->timer); /* Set an initial name for the device. */ - snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", - sch->schid.ssid, sch->schib.pmcw.dev); + if (cio_is_console(sch->schid)) + cdev->dev.init_name = cio_get_console_cdev_name(sch); + else + dev_set_name(&cdev->dev, "0.%x.%04x", + sch->schid.ssid, sch->schib.pmcw.dev); /* Increase counter of devices currently in recognition. */ atomic_inc(&ccw_device_init_count); @@ -1625,6 +1628,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) #ifdef CONFIG_CCW_CONSOLE static struct ccw_device console_cdev; +static char console_cdev_name[10] = "0.x.xxxx"; static struct ccw_device_private console_private; static int console_cdev_in_use; @@ -1695,6 +1699,14 @@ ccw_device_probe_console(void) console_cdev.online = 1; return &console_cdev; } + + +const char *cio_get_console_cdev_name(struct subchannel *sch) +{ + snprintf(console_cdev_name, 10, "0.%x.%04x", + sch->schid.ssid, sch->schib.pmcw.dev); + return (const char *)console_cdev_name; +} #endif /* -- GitLab From f9c9fe3ecfc0c5ff17728d0c5ee95a4e269ec190 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 10 Oct 2008 21:33:15 +0200 Subject: [PATCH 3756/5416] [S390] cio: inline assembly cleanup Fix incorrect in- and output constraints, remove volatile declaration of inline assembly parameters and reformat constraint declarations to be more consistent. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 2 +- drivers/s390/cio/io_sch.h | 22 +++++++++++++----- drivers/s390/cio/ioasm.h | 49 ++++++++++++++++++++++----------------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 719d6c406e9..030083f9c6f 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -901,7 +901,7 @@ static void cio_reset_pgm_check_handler(void) pgm_check_occured = 1; } -static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) +static int stsch_reset(struct subchannel_id schid, struct schib *addr) { int rc; diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index 3f8f1cf69c7..c4f3e7c9a85 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -123,7 +123,7 @@ struct ccw_device_private { void *cmb_wait; /* deferred cmb enable/disable */ }; -static inline int ssch(struct subchannel_id schid, volatile union orb *addr) +static inline int ssch(struct subchannel_id schid, union orb *addr) { register struct subchannel_id reg1 asm("1") = schid; int ccode = -EIO; @@ -134,7 +134,9 @@ static inline int ssch(struct subchannel_id schid, volatile union orb *addr) " srl %0,28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "+d" (ccode) + : "d" (reg1), "a" (addr), "m" (*addr) + : "cc", "memory"); return ccode; } @@ -147,7 +149,9 @@ static inline int rsch(struct subchannel_id schid) " rsch\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); + : "=d" (ccode) + : "d" (reg1) + : "cc", "memory"); return ccode; } @@ -160,7 +164,9 @@ static inline int csch(struct subchannel_id schid) " csch\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); + : "=d" (ccode) + : "d" (reg1) + : "cc"); return ccode; } @@ -173,7 +179,9 @@ static inline int hsch(struct subchannel_id schid) " hsch\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); + : "=d" (ccode) + : "d" (reg1) + : "cc"); return ccode; } @@ -186,7 +194,9 @@ static inline int xsch(struct subchannel_id schid) " .insn rre,0xb2760000,%1,0\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); + : "=d" (ccode) + : "d" (reg1) + : "cc"); return ccode; } diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 9fa2ac13ac8..75926279263 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -23,38 +23,39 @@ struct tpi_info { * Some S390 specific IO instructions as inline */ -static inline int stsch(struct subchannel_id schid, - volatile struct schib *addr) +static inline int stsch(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode; asm volatile( - " stsch 0(%2)\n" + " stsch 0(%3)\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "=d" (ccode), "=m" (*addr) + : "d" (reg1), "a" (addr) + : "cc"); return ccode; } -static inline int stsch_err(struct subchannel_id schid, - volatile struct schib *addr) +static inline int stsch_err(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode = -EIO; asm volatile( - " stsch 0(%2)\n" + " stsch 0(%3)\n" "0: ipm %0\n" " srl %0,28\n" "1:\n" EX_TABLE(0b,1b) - : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "+d" (ccode), "=m" (*addr) + : "d" (reg1), "a" (addr) + : "cc"); return ccode; } -static inline int msch(struct subchannel_id schid, - volatile struct schib *addr) +static inline int msch(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode; @@ -63,12 +64,13 @@ static inline int msch(struct subchannel_id schid, " msch 0(%2)\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "=d" (ccode) + : "d" (reg1), "a" (addr), "m" (*addr) + : "cc"); return ccode; } -static inline int msch_err(struct subchannel_id schid, - volatile struct schib *addr) +static inline int msch_err(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode = -EIO; @@ -79,33 +81,38 @@ static inline int msch_err(struct subchannel_id schid, " srl %0,28\n" "1:\n" EX_TABLE(0b,1b) - : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "+d" (ccode) + : "d" (reg1), "a" (addr), "m" (*addr) + : "cc"); return ccode; } -static inline int tsch(struct subchannel_id schid, - volatile struct irb *addr) +static inline int tsch(struct subchannel_id schid, struct irb *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode; asm volatile( - " tsch 0(%2)\n" + " tsch 0(%3)\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + : "=d" (ccode), "=m" (*addr) + : "d" (reg1), "a" (addr) + : "cc"); return ccode; } -static inline int tpi( volatile struct tpi_info *addr) +static inline int tpi(struct tpi_info *addr) { int ccode; asm volatile( - " tpi 0(%1)\n" + " tpi 0(%2)\n" " ipm %0\n" " srl %0,28" - : "=d" (ccode) : "a" (addr), "m" (*addr) : "cc"); + : "=d" (ccode), "=m" (*addr) + : "a" (addr) + : "cc"); return ccode; } -- GitLab From b2bbb642ac2829006a81ae164e2f06ebc22f81dd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 10 Oct 2008 21:33:16 +0200 Subject: [PATCH 3757/5416] [S390] cio: Correct use of ! and & In commit e6bafba5b4765a5a252f1b8d31cbf6d2459da337, a bug was fixed that involved converting !x & y to !(x & y). The code below shows the same pattern, and thus should perhaps be fixed in the same way. In particular, the result of !scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND is always just !scsw_stctl(&request->irb.scsw). The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ expression E; constant C; @@ ( !E & !C | - !E & C + !(E & C) ) // Signed-off-by: Julia Lawall Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc_sch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 91ca87aa9f9..f49f0e502b8 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -261,7 +261,7 @@ static int chsc_examine_irb(struct chsc_request *request) { int backed_up; - if (!scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND) + if (!(scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND)) return -EIO; backed_up = scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHAIN_CHECK; request->irb.scsw.cmd.cstat &= ~SCHN_STAT_CHAIN_CHECK; -- GitLab From b1e766137fe2462fd110e2930f74ef5636adb436 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 10 Oct 2008 21:33:17 +0200 Subject: [PATCH 3758/5416] [S390] cio: fix cio_tpi. In cio_tpi only disable bottom halves when not in interrupt context. Otherwise a WARN_ON gets triggered. Besides that, when we are in interrupt context bottom halves are disabled anyway. Fixes this one: Badness at kernel/softirq.c:77 Modules linked in: CPU: 2 Not tainted 2.6.26 #4 Process swapper (pid: 0, task: 000000003fe83db0, ksp: 000000003fea7d28) Krnl PSW : 0404c00180000000 0000000000053f4e (__local_bh_disable+0xbe/0xcc) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 EA:3 Krnl GPRS: 0000000000008ee0 00000000005f95e0 0000000000000000 0000000000000001 000000000020be92 0000000000000000 0000000000000210 00000000005d36c0 000000003fb5f4d8 0000000000000000 000000000020bed0 000000003fb5f3c8 00000000009be920 0000000000364898 000000003fb5f408 000000003fb5f3c8 Krnl Code: 0000000000053f42: bf2f1000 icm %r2,15,0(%r1) 0000000000053f46: a774ffc5 brc 7,53ed0 0000000000053f4a: a7f40001 brc 15,53f4c >0000000000053f4e: a7280001 lhi %r2,1 0000000000053f52: 50201000 st %r2,0(%r1) 0000000000053f56: a7f4ffbd brc 15,53ed0 0000000000053f5a: 0707 bcr 0,%r7 0000000000053f5c: a7f13fc0 tmll %r15,16320 Call Trace: ([<0000000000000210>] 0x210) [<0000000000053f86>] local_bh_disable+0x2a/0x38 [<000000000020bed0>] wait_cons_dev+0xd4/0x154 [<0000000000247cb2>] raw3215_make_room+0x6a/0x1a8 [<000000000024861a>] raw3215_write+0x86/0x28c [<00000000002488a0>] con3215_write+0x80/0x110 [<000000000004c3e0>] __call_console_drivers+0xc8/0xe4 [<000000000004c47e>] _call_console_drivers+0x82/0xc4 [<000000000004c744>] release_console_sem+0x218/0x2c0 [<000000000004cf64>] vprintk+0x3c0/0x504 [<0000000000354a4a>] printk+0x52/0x64 [<0000000000088004>] __print_symbol+0x40/0x50 [<0000000000071dbc>] print_stack_trace+0x78/0xac [<0000000000079e78>] print_lock_dependencies+0x148/0x208 [<000000000007a050>] print_irq_inversion_bug+0x118/0x15c [<000000000007a106>] check_usage_forwards+0x72/0x84 [<000000000007a36e>] mark_lock+0x1d2/0x594 [<000000000007baca>] __lock_acquire+0x886/0xf48 [<000000000007c234>] lock_acquire+0xa8/0xe0 [<0000000000350316>] _write_lock+0x56/0x98 [<000000000026cd92>] zfcp_erp_adapter_reopen+0x4e/0x8c [<000000000026f1e8>] zfcp_qdio_int_resp+0x2e4/0x2f4 [<00000000002210f4>] qdio_int_handler+0x274/0x888 [<00000000002177b6>] ccw_device_call_handler+0x6e/0xd8 [<0000000000215336>] ccw_device_irq+0xd6/0x160 [<0000000000212f88>] io_subchannel_irq+0x8c/0x118 [<000000000020c120>] do_IRQ+0x1d0/0x1fc [<00000000000270b2>] io_return+0x0/0x8 [<000000000001c8a4>] cpu_idle+0x178/0x21c ([<000000000001c884>] cpu_idle+0x158/0x21c) [<00000000003483a2>] start_secondary+0xb6/0xc8 INFO: lockdep is turned off. Last Breaking-Event-Address: [<0000000000053f4a>] __local_bh_disable+0xba/0xcc Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 030083f9c6f..c0cb7254725 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -114,6 +114,7 @@ cio_tpi(void) struct tpi_info *tpi_info; struct subchannel *sch; struct irb *irb; + int irq_context; tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; if (tpi (NULL) != 1) @@ -126,7 +127,9 @@ cio_tpi(void) sch = (struct subchannel *)(unsigned long)tpi_info->intparm; if (!sch) return 1; - local_bh_disable(); + irq_context = in_interrupt(); + if (!irq_context) + local_bh_disable(); irq_enter (); spin_lock(sch->lock); memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); @@ -134,7 +137,8 @@ cio_tpi(void) sch->driver->irq(sch); spin_unlock(sch->lock); irq_exit (); - _local_bh_enable(); + if (!irq_context) + _local_bh_enable(); return 1; } -- GitLab From 7a0f475513fa573bc8e072021960313da32f0ee3 Mon Sep 17 00:00:00 2001 From: Klaus-Dieter Wacker Date: Fri, 10 Oct 2008 21:33:18 +0200 Subject: [PATCH 3759/5416] [S390] qdio enhanced SIGA (iqdio) support. Add support for z10 HiperSockets multiwrite SBALs on output queues. This is used on LPAR with EDDP enabled devices. Signed-off-by: Klaus-Dieter Wacker Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/qdio.h | 8 +++++++- drivers/s390/cio/qdio.h | 3 +++ drivers/s390/cio/qdio_main.c | 24 +++++++++++++++++++----- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 6813772171f..4734c3f0535 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -299,7 +299,13 @@ struct qdio_ssqd_desc { u8 mbccnt; u16 qdioac2; u64 sch_token; - u64:64; + u8 mro; + u8 mri; + u8:8; + u8 sbalic; + u16:16; + u8:8; + u8 mmwc; } __attribute__ ((packed)); /* params are: ccw_device, qdio_error, queue_number, diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index af867731a5f..e3ea1d5f281 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -203,6 +203,9 @@ struct qdio_output_q { /* PCIs are enabled for the queue */ int pci_out_enabled; + /* IQDIO: output multiple buffers (enhanced SIGA) */ + int use_enh_siga; + /* timer to check for more outbound work */ struct timer_list timer; }; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 719066ec0c0..a50682d2a0f 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -316,6 +316,9 @@ static inline int qdio_do_siga_output(struct qdio_q *q, unsigned int *busy_bit) unsigned int fc = 0; unsigned long schid; + if (q->u.out.use_enh_siga) { + fc = 3; + } if (!is_qebsm(q)) schid = *((u32 *)&q->irq_ptr->schid); else { @@ -1449,6 +1452,8 @@ int qdio_establish(struct qdio_initialize *init_data) } qdio_setup_ssqd_info(irq_ptr); + sprintf(dbf_text, "qDmmwc%2x", irq_ptr->ssqd_desc.mmwc); + QDIO_DBF_TEXT2(0, setup, dbf_text); sprintf(dbf_text, "qib ac%2x", irq_ptr->qib.ac); QDIO_DBF_TEXT2(0, setup, dbf_text); @@ -1621,12 +1626,21 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, if (multicast_outbound(q)) qdio_kick_outbound_q(q); else - /* - * One siga-w per buffer required for unicast - * HiperSockets. - */ - while (count--) + if ((q->irq_ptr->ssqd_desc.mmwc > 1) && + (count > 1) && + (count <= q->irq_ptr->ssqd_desc.mmwc)) { + /* exploit enhanced SIGA */ + q->u.out.use_enh_siga = 1; qdio_kick_outbound_q(q); + } else { + /* + * One siga-w per buffer required for unicast + * HiperSockets. + */ + q->u.out.use_enh_siga = 0; + while (count--) + qdio_kick_outbound_q(q); + } goto out; } -- GitLab From d86730bb9597b02bff59a3a5a01c0094d71a265f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 10 Oct 2008 21:33:19 +0200 Subject: [PATCH 3760/5416] [S390] s390: use sys_pause for 31bit pause entry point sys32_pause is a useless copy of the generic sys_pause. (and it's certainly not there for old sparc32 binaries..) Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_linux.c | 8 -------- arch/s390/kernel/compat_linux.h | 1 - arch/s390/kernel/compat_wrapper.S | 2 -- arch/s390/kernel/syscalls.S | 2 +- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index d7f22226fc4..98e246dc023 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -608,14 +608,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct time return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -/* These are here just in case some old sparc32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo) { diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 20723a06201..05f8516366a 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -206,7 +206,6 @@ long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); -long sys32_pause(void); long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo); long sys32_pwrite64(unsigned int fd, const char __user *ubuf, diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 328a20e880b..ee51ca9e23b 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -128,8 +128,6 @@ sys32_alarm_wrapper: llgfr %r2,%r2 # unsigned int jg sys_alarm # branch to system call -#sys32_pause_wrapper # void - .globl compat_sys_utime_wrapper compat_sys_utime_wrapper: llgtr %r2,%r2 # char * diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index c66d35e5514..3ae303914b4 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -37,7 +37,7 @@ SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper) /* 25 old stime syscall * SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper) SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper) NI_SYSCALL /* old fstat syscall */ -SYSCALL(sys_pause,sys_pause,sys32_pause) +SYSCALL(sys_pause,sys_pause,sys_pause) SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */ NI_SYSCALL /* old stty syscall */ NI_SYSCALL /* old gtty syscall */ -- GitLab From 753c4dd6a2fa2af81f5d809d610d29f2d9dd9bc1 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:20 +0200 Subject: [PATCH 3761/5416] [S390] ptrace changes * System call parameter and result access functions * Add tracehook calls * Split syscall_trace into two functions do_syscall_trace_enter and do_syscall_trace_exit Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/include/asm/ptrace.h | 1 + arch/s390/include/asm/syscall.h | 80 +++++++++++++++++++++++++++++ arch/s390/include/asm/thread_info.h | 2 + arch/s390/kernel/entry.S | 50 ++++++++++++++---- arch/s390/kernel/entry64.S | 42 +++++++++++---- arch/s390/kernel/ptrace.c | 61 ++++++++++++---------- arch/s390/kernel/signal.c | 13 +++++ 8 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 arch/s390/include/asm/syscall.h diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8d41908e251..4c03049e7db 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -74,6 +74,7 @@ config S390 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_KVM if 64BIT + select HAVE_ARCH_TRACEHOOK source "init/Kconfig" diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index af2c9ac28a0..a7226f8143f 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *); #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) +#define user_stack_pointer(regs)((regs)->gprs[15]) #define regs_return_value(regs)((regs)->gprs[2]) #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs * regs); diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h new file mode 100644 index 00000000000..6e623971fbb --- /dev/null +++ b/arch/s390/include/asm/syscall.h @@ -0,0 +1,80 @@ +/* + * Access to user system call parameters and results + * + * Copyright IBM Corp. 2008 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * 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. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H 1 + +#include + +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + if (regs->trap != __LC_SVC_OLD_PSW) + return -1; + return regs->gprs[2]; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->gprs[2] = regs->orig_gpr2; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->gprs[2]; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->gprs[2] = error ? -error : val; +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(task, TIF_31BIT)) { + if (i + n == 6) + args[--n] = (u32) regs->args[0]; + while (n-- > 0) + args[n] = (u32) regs->gprs[2 + i + n]; + } +#endif + if (i + n == 6) + args[--n] = regs->args[0]; + memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + if (i + n == 6) + regs->args[0] = args[--n]; + memcpy(®s->gprs[2 + i], args, n * sizeof(args[0])); +} + +#endif /* _ASM_SYSCALL_H */ diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 91a8f93ad35..ea40a9d690f 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void) * thread information flags bit numbers */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ @@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ #define _TIF_SYSCALL_TRACE (1< #include #include +#include #include #include @@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, } #endif -asmlinkage void -syscall_trace(struct pt_regs *regs, int entryexit) +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { - if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; - if (!(current->ptrace & PT_PTRACED)) - goto out; - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + long ret; /* - * If the debuffer has set an invalid system call number, - * we prepare to skip the system call restart handling. + * The sysc_tracesys code in entry.S stored the system + * call number to gprs[2]. */ - if (!entryexit && regs->gprs[2] >= NR_syscalls) + ret = regs->gprs[2]; + if (test_thread_flag(TIF_SYSCALL_TRACE) && + (tracehook_report_syscall_entry(regs) || + regs->gprs[2] >= NR_syscalls)) { + /* + * Tracing decided this syscall should not happen or the + * debugger stored an invalid system call number. Skip + * the system call and the system call restart handling. + */ regs->trap = -1; - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; + ret = -1; } - out: - if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, - regs->gprs[2], regs->orig_gpr2, regs->gprs[3], - regs->gprs[4], regs->gprs[5]); + + if (unlikely(current->audit_context)) + audit_syscall_entry(test_thread_flag(TIF_31BIT) ? + AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, + regs->gprs[2], regs->orig_gpr2, + regs->gprs[3], regs->gprs[4], + regs->gprs[5]); + return ret; +} + +asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) + audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), + regs->gprs[2]); + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); } /* diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index b9768204021..4f7fc3059a8 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs) */ if (current->thread.per_info.single_step) set_thread_flag(TIF_SINGLE_STEP); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLE_STEP)); } return; } @@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs) set_thread_flag(TIF_RESTART_SVC); } } + +void do_notify_resume(struct pt_regs *regs) +{ + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); +} -- GitLab From b2300b9efe1b8174833e17f37e975c9da00c388a Mon Sep 17 00:00:00 2001 From: Hongjie Yang Date: Fri, 10 Oct 2008 21:33:21 +0200 Subject: [PATCH 3762/5416] [S390] dcssblk: add >2G DCSSs support and stacked contiguous DCSSs support. The DCSS block device driver is modified to add >2G DCSSs support and allow a DCSS block device to map to a set of contiguous DCSSs. The extmem code is also modified to use new Diagnose x'64' subcodes for >2G DCSSs. Signed-off-by: Hongjie Yang Signed-off-by: Martin Schwidefsky --- arch/s390/mm/extmem.c | 251 ++++++++++++++--- drivers/s390/block/dcssblk.c | 515 ++++++++++++++++++++++++++--------- 2 files changed, 596 insertions(+), 170 deletions(-) diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index f231f5ec74b..580fc64cc73 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -43,20 +43,40 @@ #define DCSS_FINDSEG 0x0c #define DCSS_LOADNOLY 0x10 #define DCSS_SEGEXT 0x18 +#define DCSS_LOADSHRX 0x20 +#define DCSS_LOADNSRX 0x24 +#define DCSS_FINDSEGX 0x2c +#define DCSS_SEGEXTX 0x38 #define DCSS_FINDSEGA 0x0c struct qrange { - unsigned int start; // 3byte start address, 1 byte type - unsigned int end; // 3byte end address, 1 byte reserved + unsigned long start; /* last byte type */ + unsigned long end; /* last byte reserved */ }; struct qout64 { + unsigned long segstart; + unsigned long segend; + int segcnt; + int segrcnt; + struct qrange range[6]; +}; + +#ifdef CONFIG_64BIT +struct qrange_old { + unsigned int start; /* last byte type */ + unsigned int end; /* last byte reserved */ +}; + +/* output area format for the Diag x'64' old subcode x'18' */ +struct qout64_old { int segstart; int segend; int segcnt; int segrcnt; - struct qrange range[6]; + struct qrange_old range[6]; }; +#endif struct qin64 { char qopcode; @@ -86,6 +106,55 @@ static DEFINE_MUTEX(dcss_lock); static LIST_HEAD(dcss_list); static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", "EW/EN-MIXED" }; +static int loadshr_scode, loadnsr_scode, findseg_scode; +static int segext_scode, purgeseg_scode; +static int scode_set; + +/* set correct Diag x'64' subcodes. */ +static int +dcss_set_subcodes(void) +{ +#ifdef CONFIG_64BIT + char *name = kmalloc(8 * sizeof(char), GFP_DMA); + unsigned long rx, ry; + int rc; + + if (name == NULL) + return -ENOMEM; + + rx = (unsigned long) name; + ry = DCSS_FINDSEGX; + + strcpy(name, "dummy"); + asm volatile( + " diag %0,%1,0x64\n" + "0: ipm %2\n" + " srl %2,28\n" + " j 2f\n" + "1: la %2,3\n" + "2:\n" + EX_TABLE(0b, 1b) + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); + + kfree(name); + /* Diag x'64' new subcodes are supported, set to new subcodes */ + if (rc != 3) { + loadshr_scode = DCSS_LOADSHRX; + loadnsr_scode = DCSS_LOADNSRX; + purgeseg_scode = DCSS_PURGESEG; + findseg_scode = DCSS_FINDSEGX; + segext_scode = DCSS_SEGEXTX; + return 0; + } +#endif + /* Diag x'64' new subcodes are not supported, set to old subcodes */ + loadshr_scode = DCSS_LOADNOLY; + loadnsr_scode = DCSS_LOADNSR; + purgeseg_scode = DCSS_PURGESEG; + findseg_scode = DCSS_FINDSEG; + segext_scode = DCSS_SEGEXT; + return 0; +} /* * Create the 8 bytes, ebcdic VM segment name from @@ -135,25 +204,45 @@ segment_by_name (char *name) * Perform a function on a dcss segment. */ static inline int -dcss_diag (__u8 func, void *parameter, +dcss_diag(int *func, void *parameter, unsigned long *ret1, unsigned long *ret2) { unsigned long rx, ry; int rc; + if (scode_set == 0) { + rc = dcss_set_subcodes(); + if (rc < 0) + return rc; + scode_set = 1; + } rx = (unsigned long) parameter; - ry = (unsigned long) func; - asm volatile( + ry = (unsigned long) *func; + #ifdef CONFIG_64BIT - " sam31\n" - " diag %0,%1,0x64\n" - " sam64\n" + /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */ + if (*func > DCSS_SEGEXT) + asm volatile( + " diag %0,%1,0x64\n" + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); + /* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */ + else + asm volatile( + " sam31\n" + " diag %0,%1,0x64\n" + " sam64\n" + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); #else + asm volatile( " diag %0,%1,0x64\n" -#endif " ipm %2\n" " srl %2,28\n" : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); +#endif *ret1 = rx; *ret2 = ry; return rc; @@ -190,14 +279,45 @@ query_segment_type (struct dcss_segment *seg) qin->qoutlen = sizeof(struct qout64); memcpy (qin->qname, seg->dcss_name, 8); - diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc); + diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc); + if (diag_cc < 0) { + rc = diag_cc; + goto out_free; + } if (diag_cc > 1) { PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc); rc = dcss_diag_translate_rc (vmrc); goto out_free; } +#ifdef CONFIG_64BIT + /* Only old format of output area of Diagnose x'64' is supported, + copy data for the new format. */ + if (segext_scode == DCSS_SEGEXT) { + struct qout64_old *qout_old; + qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA); + if (qout_old == NULL) { + rc = -ENOMEM; + goto out_free; + } + memcpy(qout_old, qout, sizeof(struct qout64_old)); + qout->segstart = (unsigned long) qout_old->segstart; + qout->segend = (unsigned long) qout_old->segend; + qout->segcnt = qout_old->segcnt; + qout->segrcnt = qout_old->segrcnt; + + if (qout->segcnt > 6) + qout->segrcnt = 6; + for (i = 0; i < qout->segrcnt; i++) { + qout->range[i].start = + (unsigned long) qout_old->range[i].start; + qout->range[i].end = + (unsigned long) qout_old->range[i].end; + } + kfree(qout_old); + } +#endif if (qout->segcnt > 6) { rc = -ENOTSUPP; goto out_free; @@ -268,6 +388,30 @@ segment_type (char* name) return seg.vm_segtype; } +/* + * check if segment collides with other segments that are currently loaded + * returns 1 if this is the case, 0 if no collision was found + */ +static int +segment_overlaps_others (struct dcss_segment *seg) +{ + struct list_head *l; + struct dcss_segment *tmp; + + BUG_ON(!mutex_is_locked(&dcss_lock)); + list_for_each(l, &dcss_list) { + tmp = list_entry(l, struct dcss_segment, list); + if ((tmp->start_addr >> 20) > (seg->end >> 20)) + continue; + if ((tmp->end >> 20) < (seg->start_addr >> 20)) + continue; + if (seg == tmp) + continue; + return 1; + } + return 0; +} + /* * real segment loading function, called from segment_load */ @@ -276,7 +420,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long { struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA); - int dcss_command, rc, diag_cc; + int rc, diag_cc; + unsigned long start_addr, end_addr, dummy; if (seg == NULL) { rc = -ENOMEM; @@ -287,6 +432,13 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long if (rc < 0) goto out_free; + if (loadshr_scode == DCSS_LOADSHRX) { + if (segment_overlaps_others(seg)) { + rc = -EBUSY; + goto out_free; + } + } + rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1); if (rc) @@ -316,20 +468,28 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long } if (do_nonshared) - dcss_command = DCSS_LOADNSR; + diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, + &start_addr, &end_addr); else - dcss_command = DCSS_LOADNOLY; - - diag_cc = dcss_diag(dcss_command, seg->dcss_name, - &seg->start_addr, &seg->end); + diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name, + &start_addr, &end_addr); + if (diag_cc < 0) { + dcss_diag(&purgeseg_scode, seg->dcss_name, + &dummy, &dummy); + rc = diag_cc; + goto out_resource; + } if (diag_cc > 1) { PRINT_WARN ("segment_load: could not load segment %s - " - "diag returned error (%ld)\n",name,seg->end); - rc = dcss_diag_translate_rc (seg->end); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, - &seg->start_addr, &seg->end); + "diag returned error (%ld)\n", + name, end_addr); + rc = dcss_diag_translate_rc(end_addr); + dcss_diag(&purgeseg_scode, seg->dcss_name, + &dummy, &dummy); goto out_resource; } + seg->start_addr = start_addr; + seg->end = end_addr; seg->do_nonshared = do_nonshared; atomic_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); @@ -423,8 +583,8 @@ int segment_modify_shared (char *name, int do_nonshared) { struct dcss_segment *seg; - unsigned long dummy; - int dcss_command, rc, diag_cc; + unsigned long start_addr, end_addr, dummy; + int rc, diag_cc; mutex_lock(&dcss_lock); seg = segment_by_name (name); @@ -445,38 +605,51 @@ segment_modify_shared (char *name, int do_nonshared) goto out_unlock; } release_resource(seg->res); - if (do_nonshared) { - dcss_command = DCSS_LOADNSR; + if (do_nonshared) seg->res->flags &= ~IORESOURCE_READONLY; - } else { - dcss_command = DCSS_LOADNOLY; + else if (seg->vm_segtype == SEG_TYPE_SR || seg->vm_segtype == SEG_TYPE_ER) seg->res->flags |= IORESOURCE_READONLY; - } + if (request_resource(&iomem_resource, seg->res)) { PRINT_WARN("segment_modify_shared: could not reload segment %s" " - overlapping resources\n", name); rc = -EBUSY; kfree(seg->res); - goto out_del; + goto out_del_mem; + } + + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); + if (do_nonshared) + diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, + &start_addr, &end_addr); + else + diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name, + &start_addr, &end_addr); + if (diag_cc < 0) { + rc = diag_cc; + goto out_del_res; } - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - diag_cc = dcss_diag(dcss_command, seg->dcss_name, - &seg->start_addr, &seg->end); if (diag_cc > 1) { PRINT_WARN ("segment_modify_shared: could not reload segment %s" - " - diag returned error (%ld)\n",name,seg->end); - rc = dcss_diag_translate_rc (seg->end); - goto out_del; + " - diag returned error (%ld)\n", + name, end_addr); + rc = dcss_diag_translate_rc(end_addr); + goto out_del_res; } + seg->start_addr = start_addr; + seg->end = end_addr; seg->do_nonshared = do_nonshared; rc = 0; goto out_unlock; - out_del: + out_del_res: + release_resource(seg->res); + kfree(seg->res); + out_del_mem: vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); kfree(seg); out_unlock: mutex_unlock(&dcss_lock); @@ -510,7 +683,7 @@ segment_unload(char *name) kfree(seg->res); vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy); kfree(seg); out_unlock: mutex_unlock(&dcss_lock); @@ -545,7 +718,7 @@ segment_save(char *name) endpfn = (seg->end) >> PAGE_SHIFT; sprintf(cmd1, "DEFSEG %s", name); for (i=0; isegcnt; i++) { - sprintf(cmd1+strlen(cmd1), " %X-%X %s", + sprintf(cmd1+strlen(cmd1), " %lX-%lX %s", seg->range[i].start >> PAGE_SHIFT, seg->range[i].end >> PAGE_SHIFT, segtype_string[seg->range[i].start & 0xff]); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index ea4272c8c67..a7ff167d5b8 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -31,7 +31,6 @@ #define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x) #define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x) - static int dcssblk_open(struct inode *inode, struct file *filp); static int dcssblk_release(struct inode *inode, struct file *filp); static int dcssblk_make_request(struct request_queue *q, struct bio *bio); @@ -48,6 +47,30 @@ static struct block_device_operations dcssblk_devops = { .direct_access = dcssblk_direct_access, }; +struct dcssblk_dev_info { + struct list_head lh; + struct device dev; + char segment_name[BUS_ID_SIZE]; + atomic_t use_count; + struct gendisk *gd; + unsigned long start; + unsigned long end; + int segment_type; + unsigned char save_pending; + unsigned char is_shared; + struct request_queue *dcssblk_queue; + int num_of_segments; + struct list_head seg_list; +}; + +struct segment_info { + struct list_head lh; + char segment_name[BUS_ID_SIZE]; + unsigned long start; + unsigned long end; + int segment_type; +}; + static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count); static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf, @@ -58,30 +81,20 @@ static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *at static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count); static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t dcssblk_seglist_show(struct device *dev, + struct device_attribute *attr, + char *buf); static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store); static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store); -static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show, +static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show, dcssblk_save_store); -static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show, +static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show, dcssblk_shared_store); +static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL); static struct device *dcssblk_root_dev; -struct dcssblk_dev_info { - struct list_head lh; - struct device dev; - char segment_name[BUS_ID_SIZE]; - atomic_t use_count; - struct gendisk *gd; - unsigned long start; - unsigned long end; - int segment_type; - unsigned char save_pending; - unsigned char is_shared; - struct request_queue *dcssblk_queue; -}; - static LIST_HEAD(dcssblk_devices); static struct rw_semaphore dcssblk_devices_sem; @@ -91,8 +104,15 @@ static struct rw_semaphore dcssblk_devices_sem; static void dcssblk_release_segment(struct device *dev) { - PRINT_DEBUG("segment release fn called for %s\n", dev_name(dev)); - kfree(container_of(dev, struct dcssblk_dev_info, dev)); + struct dcssblk_dev_info *dev_info; + struct segment_info *entry, *temp; + + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + list_for_each_entry_safe(entry, temp, &dev_info->seg_list, lh) { + list_del(&entry->lh); + kfree(entry); + } + kfree(dev_info); module_put(THIS_MODULE); } @@ -142,6 +162,169 @@ dcssblk_get_device_by_name(char *name) return NULL; } +/* + * get the struct segment_info from seg_list + * for the given name. + * down_read(&dcssblk_devices_sem) must be held. + */ +static struct segment_info * +dcssblk_get_segment_by_name(char *name) +{ + struct dcssblk_dev_info *dev_info; + struct segment_info *entry; + + list_for_each_entry(dev_info, &dcssblk_devices, lh) { + list_for_each_entry(entry, &dev_info->seg_list, lh) { + if (!strcmp(name, entry->segment_name)) + return entry; + } + } + return NULL; +} + +/* + * get the highest address of the multi-segment block. + */ +static unsigned long +dcssblk_find_highest_addr(struct dcssblk_dev_info *dev_info) +{ + unsigned long highest_addr; + struct segment_info *entry; + + highest_addr = 0; + list_for_each_entry(entry, &dev_info->seg_list, lh) { + if (highest_addr < entry->end) + highest_addr = entry->end; + } + return highest_addr; +} + +/* + * get the lowest address of the multi-segment block. + */ +static unsigned long +dcssblk_find_lowest_addr(struct dcssblk_dev_info *dev_info) +{ + int set_first; + unsigned long lowest_addr; + struct segment_info *entry; + + set_first = 0; + lowest_addr = 0; + list_for_each_entry(entry, &dev_info->seg_list, lh) { + if (set_first == 0) { + lowest_addr = entry->start; + set_first = 1; + } else { + if (lowest_addr > entry->start) + lowest_addr = entry->start; + } + } + return lowest_addr; +} + +/* + * Check continuity of segments. + */ +static int +dcssblk_is_continuous(struct dcssblk_dev_info *dev_info) +{ + int i, j, rc; + struct segment_info *sort_list, *entry, temp; + + if (dev_info->num_of_segments <= 1) + return 0; + + sort_list = kzalloc( + sizeof(struct segment_info) * dev_info->num_of_segments, + GFP_KERNEL); + if (sort_list == NULL) + return -ENOMEM; + i = 0; + list_for_each_entry(entry, &dev_info->seg_list, lh) { + memcpy(&sort_list[i], entry, sizeof(struct segment_info)); + i++; + } + + /* sort segments */ + for (i = 0; i < dev_info->num_of_segments; i++) + for (j = 0; j < dev_info->num_of_segments; j++) + if (sort_list[j].start > sort_list[i].start) { + memcpy(&temp, &sort_list[i], + sizeof(struct segment_info)); + memcpy(&sort_list[i], &sort_list[j], + sizeof(struct segment_info)); + memcpy(&sort_list[j], &temp, + sizeof(struct segment_info)); + } + + /* check continuity */ + for (i = 0; i < dev_info->num_of_segments - 1; i++) { + if ((sort_list[i].end + 1) != sort_list[i+1].start) { + PRINT_ERR("Segment %s is not contiguous with " + "segment %s\n", + sort_list[i].segment_name, + sort_list[i+1].segment_name); + rc = -EINVAL; + goto out; + } + /* EN and EW are allowed in a block device */ + if (sort_list[i].segment_type != sort_list[i+1].segment_type) { + if (!(sort_list[i].segment_type & SEGMENT_EXCLUSIVE) || + (sort_list[i].segment_type == SEG_TYPE_ER) || + !(sort_list[i+1].segment_type & + SEGMENT_EXCLUSIVE) || + (sort_list[i+1].segment_type == SEG_TYPE_ER)) { + PRINT_ERR("Segment %s has different type from " + "segment %s\n", + sort_list[i].segment_name, + sort_list[i+1].segment_name); + rc = -EINVAL; + goto out; + } + } + } + rc = 0; +out: + kfree(sort_list); + return rc; +} + +/* + * Load a segment + */ +static int +dcssblk_load_segment(char *name, struct segment_info **seg_info) +{ + int rc; + + /* already loaded? */ + down_read(&dcssblk_devices_sem); + *seg_info = dcssblk_get_segment_by_name(name); + up_read(&dcssblk_devices_sem); + if (*seg_info != NULL) + return -EEXIST; + + /* get a struct segment_info */ + *seg_info = kzalloc(sizeof(struct segment_info), GFP_KERNEL); + if (*seg_info == NULL) + return -ENOMEM; + + strcpy((*seg_info)->segment_name, name); + + /* load the segment */ + rc = segment_load(name, SEGMENT_SHARED, + &(*seg_info)->start, &(*seg_info)->end); + if (rc < 0) { + segment_warning(rc, (*seg_info)->segment_name); + kfree(*seg_info); + } else { + INIT_LIST_HEAD(&(*seg_info)->lh); + (*seg_info)->segment_type = rc; + } + return rc; +} + static void dcssblk_unregister_callback(struct device *dev) { device_unregister(dev); @@ -165,6 +348,7 @@ static ssize_t dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) { struct dcssblk_dev_info *dev_info; + struct segment_info *entry, *temp; int rc; if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) @@ -172,46 +356,46 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch down_write(&dcssblk_devices_sem); dev_info = container_of(dev, struct dcssblk_dev_info, dev); if (atomic_read(&dev_info->use_count)) { - PRINT_ERR("share: segment %s is busy!\n", - dev_info->segment_name); rc = -EBUSY; goto out; } if (inbuf[0] == '1') { - // reload segment in shared mode - rc = segment_modify_shared(dev_info->segment_name, - SEGMENT_SHARED); - if (rc < 0) { - BUG_ON(rc == -EINVAL); - if (rc != -EAGAIN) - goto removeseg; - } else { - dev_info->is_shared = 1; - switch (dev_info->segment_type) { - case SEG_TYPE_SR: - case SEG_TYPE_ER: - case SEG_TYPE_SC: - set_disk_ro(dev_info->gd,1); + /* reload segments in shared mode */ + list_for_each_entry(entry, &dev_info->seg_list, lh) { + rc = segment_modify_shared(entry->segment_name, + SEGMENT_SHARED); + if (rc < 0) { + BUG_ON(rc == -EINVAL); + if (rc != -EAGAIN) + goto removeseg; } } + dev_info->is_shared = 1; + switch (dev_info->segment_type) { + case SEG_TYPE_SR: + case SEG_TYPE_ER: + case SEG_TYPE_SC: + set_disk_ro(dev_info->gd, 1); + } } else if (inbuf[0] == '0') { - // reload segment in exclusive mode + /* reload segments in exclusive mode */ if (dev_info->segment_type == SEG_TYPE_SC) { PRINT_ERR("Segment type SC (%s) cannot be loaded in " - "non-shared mode\n", dev_info->segment_name); + "non-shared mode\n", dev_info->segment_name); rc = -EINVAL; goto out; } - rc = segment_modify_shared(dev_info->segment_name, - SEGMENT_EXCLUSIVE); - if (rc < 0) { - BUG_ON(rc == -EINVAL); - if (rc != -EAGAIN) - goto removeseg; - } else { - dev_info->is_shared = 0; - set_disk_ro(dev_info->gd, 0); + list_for_each_entry(entry, &dev_info->seg_list, lh) { + rc = segment_modify_shared(entry->segment_name, + SEGMENT_EXCLUSIVE); + if (rc < 0) { + BUG_ON(rc == -EINVAL); + if (rc != -EAGAIN) + goto removeseg; + } } + dev_info->is_shared = 0; + set_disk_ro(dev_info->gd, 0); } else { rc = -EINVAL; goto out; @@ -220,8 +404,14 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch goto out; removeseg: - PRINT_ERR("Could not reload segment %s, removing it now!\n", - dev_info->segment_name); + PRINT_ERR("Could not reload segment(s) of the device %s, removing " + "segment(s) now!\n", + dev_info->segment_name); + temp = entry; + list_for_each_entry(entry, &dev_info->seg_list, lh) { + if (entry != temp) + segment_unload(entry->segment_name); + } list_del(&dev_info->lh); del_gendisk(dev_info->gd); @@ -254,6 +444,7 @@ static ssize_t dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) { struct dcssblk_dev_info *dev_info; + struct segment_info *entry; if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) return -EINVAL; @@ -263,14 +454,16 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char if (inbuf[0] == '1') { if (atomic_read(&dev_info->use_count) == 0) { // device is idle => we save immediately - PRINT_INFO("Saving segment %s\n", + PRINT_INFO("Saving segment(s) of the device %s\n", dev_info->segment_name); - segment_save(dev_info->segment_name); + list_for_each_entry(entry, &dev_info->seg_list, lh) { + segment_save(entry->segment_name); + } } else { // device is busy => we save it when it becomes // idle in dcssblk_release - PRINT_INFO("Segment %s is currently busy, it will " - "be saved when it becomes idle...\n", + PRINT_INFO("Device %s is currently busy, segment(s) " + "will be saved when it becomes idle...\n", dev_info->segment_name); dev_info->save_pending = 1; } @@ -279,7 +472,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char // device is busy & the user wants to undo his save // request dev_info->save_pending = 0; - PRINT_INFO("Pending save for segment %s deactivated\n", + PRINT_INFO("Pending save for segment(s) of the device " + "%s deactivated\n", dev_info->segment_name); } } else { @@ -290,67 +484,124 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char return count; } +/* + * device attribute for showing all segments in a device + */ +static ssize_t +dcssblk_seglist_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + + struct dcssblk_dev_info *dev_info; + struct segment_info *entry; + + down_read(&dcssblk_devices_sem); + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + i = 0; + buf[0] = '\0'; + list_for_each_entry(entry, &dev_info->seg_list, lh) { + strcpy(&buf[i], entry->segment_name); + i += strlen(entry->segment_name); + buf[i] = '\n'; + i++; + } + up_read(&dcssblk_devices_sem); + return i; +} + /* * device attribute for adding devices */ static ssize_t dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int rc, i; + int rc, i, j, num_of_segments; struct dcssblk_dev_info *dev_info; + struct segment_info *seg_info, *temp; char *local_buf; unsigned long seg_byte_size; dev_info = NULL; + seg_info = NULL; if (dev != dcssblk_root_dev) { rc = -EINVAL; goto out_nobuf; } + if ((count < 1) || (buf[0] == '\0') || (buf[0] == '\n')) { + rc = -ENAMETOOLONG; + goto out_nobuf; + } + local_buf = kmalloc(count + 1, GFP_KERNEL); if (local_buf == NULL) { rc = -ENOMEM; goto out_nobuf; } + /* * parse input */ + num_of_segments = 0; for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) { - local_buf[i] = toupper(buf[i]); + for (j = i; (buf[j] != ':') && + (buf[j] != '\0') && + (buf[j] != '\n') && + j < count; j++) { + local_buf[j-i] = toupper(buf[j]); + } + local_buf[j-i] = '\0'; + if (((j - i) == 0) || ((j - i) > 8)) { + rc = -ENAMETOOLONG; + goto seg_list_del; + } + + rc = dcssblk_load_segment(local_buf, &seg_info); + if (rc < 0) + goto seg_list_del; + /* + * get a struct dcssblk_dev_info + */ + if (num_of_segments == 0) { + dev_info = kzalloc(sizeof(struct dcssblk_dev_info), + GFP_KERNEL); + if (dev_info == NULL) { + rc = -ENOMEM; + goto out; + } + strcpy(dev_info->segment_name, local_buf); + dev_info->segment_type = seg_info->segment_type; + INIT_LIST_HEAD(&dev_info->seg_list); + } + list_add_tail(&seg_info->lh, &dev_info->seg_list); + num_of_segments++; + i = j; + + if ((buf[j] == '\0') || (buf[j] == '\n')) + break; } - local_buf[i] = '\0'; - if ((i == 0) || (i > 8)) { + + /* no trailing colon at the end of the input */ + if ((i > 0) && (buf[i-1] == ':')) { rc = -ENAMETOOLONG; - goto out; - } - /* - * already loaded? - */ - down_read(&dcssblk_devices_sem); - dev_info = dcssblk_get_device_by_name(local_buf); - up_read(&dcssblk_devices_sem); - if (dev_info != NULL) { - PRINT_WARN("Segment %s already loaded!\n", local_buf); - rc = -EEXIST; - goto out; - } - /* - * get a struct dcssblk_dev_info - */ - dev_info = kzalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL); - if (dev_info == NULL) { - rc = -ENOMEM; - goto out; + goto seg_list_del; } + strlcpy(local_buf, buf, i + 1); + dev_info->num_of_segments = num_of_segments; + rc = dcssblk_is_continuous(dev_info); + if (rc < 0) + goto seg_list_del; + + dev_info->start = dcssblk_find_lowest_addr(dev_info); + dev_info->end = dcssblk_find_highest_addr(dev_info); - strcpy(dev_info->segment_name, local_buf); - dev_set_name(&dev_info->dev, local_buf); + dev_set_name(&dev_info->dev, dev_info->segment_name); dev_info->dev.release = dcssblk_release_segment; INIT_LIST_HEAD(&dev_info->lh); - dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK); if (dev_info->gd == NULL) { rc = -ENOMEM; - goto free_dev_info; + goto seg_list_del; } dev_info->gd->major = dcssblk_major; dev_info->gd->fops = &dcssblk_devops; @@ -360,65 +611,52 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char dev_info->gd->driverfs_dev = &dev_info->dev; blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); - /* - * load the segment - */ - rc = segment_load(local_buf, SEGMENT_SHARED, - &dev_info->start, &dev_info->end); - if (rc < 0) { - segment_warning(rc, dev_info->segment_name); - goto dealloc_gendisk; - } + seg_byte_size = (dev_info->end - dev_info->start + 1); set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors - PRINT_INFO("Loaded segment %s, size = %lu Byte, " + PRINT_INFO("Loaded segment(s) %s, size = %lu Byte, " "capacity = %lu (512 Byte) sectors\n", local_buf, seg_byte_size, seg_byte_size >> 9); - dev_info->segment_type = rc; dev_info->save_pending = 0; dev_info->is_shared = 1; dev_info->dev.parent = dcssblk_root_dev; /* - * get minor, add to list + *get minor, add to list */ down_write(&dcssblk_devices_sem); - if (dcssblk_get_device_by_name(local_buf)) { - up_write(&dcssblk_devices_sem); + if (dcssblk_get_segment_by_name(local_buf)) { rc = -EEXIST; - goto unload_seg; + goto release_gd; } rc = dcssblk_assign_free_minor(dev_info); - if (rc) { - up_write(&dcssblk_devices_sem); - PRINT_ERR("No free minor number available! " - "Unloading segment...\n"); - goto unload_seg; - } + if (rc) + goto release_gd; sprintf(dev_info->gd->disk_name, "dcssblk%d", MINOR(disk_devt(dev_info->gd))); list_add_tail(&dev_info->lh, &dcssblk_devices); if (!try_module_get(THIS_MODULE)) { rc = -ENODEV; - goto list_del; + goto dev_list_del; } /* * register the device */ rc = device_register(&dev_info->dev); if (rc) { - PRINT_ERR("Segment %s could not be registered RC=%d\n", - local_buf, rc); module_put(THIS_MODULE); - goto list_del; + goto dev_list_del; } get_device(&dev_info->dev); rc = device_create_file(&dev_info->dev, &dev_attr_shared); if (rc) goto unregister_dev; rc = device_create_file(&dev_info->dev, &dev_attr_save); + if (rc) + goto unregister_dev; + rc = device_create_file(&dev_info->dev, &dev_attr_seglist); if (rc) goto unregister_dev; @@ -434,7 +672,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char set_disk_ro(dev_info->gd,0); break; } - PRINT_DEBUG("Segment %s loaded successfully\n", local_buf); up_write(&dcssblk_devices_sem); rc = count; goto out; @@ -445,20 +682,27 @@ unregister_dev: dev_info->gd->queue = NULL; put_disk(dev_info->gd); device_unregister(&dev_info->dev); - segment_unload(dev_info->segment_name); + list_for_each_entry(seg_info, &dev_info->seg_list, lh) { + segment_unload(seg_info->segment_name); + } put_device(&dev_info->dev); up_write(&dcssblk_devices_sem); goto out; -list_del: +dev_list_del: list_del(&dev_info->lh); - up_write(&dcssblk_devices_sem); -unload_seg: - segment_unload(local_buf); -dealloc_gendisk: +release_gd: blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); -free_dev_info: + up_write(&dcssblk_devices_sem); +seg_list_del: + if (dev_info == NULL) + goto out; + list_for_each_entry_safe(seg_info, temp, &dev_info->seg_list, lh) { + list_del(&seg_info->lh); + segment_unload(seg_info->segment_name); + kfree(seg_info); + } kfree(dev_info); out: kfree(local_buf); @@ -473,6 +717,7 @@ static ssize_t dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dcssblk_dev_info *dev_info; + struct segment_info *entry; int rc, i; char *local_buf; @@ -499,26 +744,28 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch dev_info = dcssblk_get_device_by_name(local_buf); if (dev_info == NULL) { up_write(&dcssblk_devices_sem); - PRINT_WARN("Segment %s is not loaded!\n", local_buf); + PRINT_WARN("Device %s is not loaded!\n", local_buf); rc = -ENODEV; goto out_buf; } if (atomic_read(&dev_info->use_count) != 0) { up_write(&dcssblk_devices_sem); - PRINT_WARN("Segment %s is in use!\n", local_buf); + PRINT_WARN("Device %s is in use!\n", local_buf); rc = -EBUSY; goto out_buf; } - list_del(&dev_info->lh); + list_del(&dev_info->lh); del_gendisk(dev_info->gd); blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); device_unregister(&dev_info->dev); - segment_unload(dev_info->segment_name); - PRINT_DEBUG("Segment %s unloaded successfully\n", - dev_info->segment_name); + + /* unload all related segments */ + list_for_each_entry(entry, &dev_info->seg_list, lh) + segment_unload(entry->segment_name); + put_device(&dev_info->dev); up_write(&dcssblk_devices_sem); @@ -550,6 +797,7 @@ static int dcssblk_release(struct inode *inode, struct file *filp) { struct dcssblk_dev_info *dev_info; + struct segment_info *entry; int rc; dev_info = inode->i_bdev->bd_disk->private_data; @@ -560,9 +808,11 @@ dcssblk_release(struct inode *inode, struct file *filp) down_write(&dcssblk_devices_sem); if (atomic_dec_and_test(&dev_info->use_count) && (dev_info->save_pending)) { - PRINT_INFO("Segment %s became idle and is being saved now\n", + PRINT_INFO("Device %s became idle and is being saved now\n", dev_info->segment_name); - segment_save(dev_info->segment_name); + list_for_each_entry(entry, &dev_info->seg_list, lh) { + segment_save(entry->segment_name); + } dev_info->save_pending = 0; } up_write(&dcssblk_devices_sem); @@ -602,7 +852,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) case SEG_TYPE_SC: /* cannot write to these segments */ if (bio_data_dir(bio) == WRITE) { - PRINT_WARN("rejecting write to ro segment %s\n", + PRINT_WARN("rejecting write to ro device %s\n", dev_name(&dev_info->dev)); goto fail; } @@ -658,7 +908,7 @@ static void dcssblk_check_params(void) { int rc, i, j, k; - char buf[9]; + char buf[DCSSBLK_PARM_LEN + 1]; struct dcssblk_dev_info *dev_info; for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0'); @@ -666,15 +916,16 @@ dcssblk_check_params(void) for (j = i; (dcssblk_segments[j] != ',') && (dcssblk_segments[j] != '\0') && (dcssblk_segments[j] != '(') && - (j - i) < 8; j++) + (j < DCSSBLK_PARM_LEN); j++) { buf[j-i] = dcssblk_segments[j]; } buf[j-i] = '\0'; rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i); if ((rc >= 0) && (dcssblk_segments[j] == '(')) { - for (k = 0; buf[k] != '\0'; k++) + for (k = 0; (buf[k] != ':') && (buf[k] != '\0'); k++) buf[k] = toupper(buf[k]); + buf[k] = '\0'; if (!strncmp(&dcssblk_segments[j], "(local)", 7)) { down_read(&dcssblk_devices_sem); dev_info = dcssblk_get_device_by_name(buf); @@ -741,10 +992,12 @@ module_exit(dcssblk_exit); module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444); MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, " - "comma-separated list, each name max. 8 chars.\n" - "Adding \"(local)\" to segment name equals echoing 0 to " - "/sys/devices/dcssblk//shared after loading " - "the segment - \n" - "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\""); + "comma-separated list, names in each set separated " + "by commas are separated by colons, each set contains " + "names of contiguous segments and each name max. 8 chars.\n" + "Adding \"(local)\" to the end of each set equals echoing 0 " + "to /sys/devices/dcssblk//shared after loading " + "the contiguous segments - \n" + "e.g. segments=\"mydcss1,mydcss2:mydcss3,mydcss4(local)\""); MODULE_LICENSE("GPL"); -- GitLab From 5a0d0e65379256b4da2c9092e197a2c761f51c01 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 10 Oct 2008 21:33:22 +0200 Subject: [PATCH 3763/5416] [S390] Move private simple udelay function to arch/s390/lib/delay.c. Move cio's private simple udelay function to lib/delay.c and turn it into something much more readable. So we have all implementations at one place. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/delay.h | 1 + arch/s390/lib/delay.c | 13 +++++++++++++ drivers/s390/cio/cio.c | 17 ++--------------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index 78357314c45..a356c958e26 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h @@ -15,6 +15,7 @@ #define _S390_DELAY_H extern void __udelay(unsigned long usecs); +extern void udelay_simple(unsigned long usecs); extern void __delay(unsigned long loops); #define udelay(n) __udelay(n) diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 0953cee05ef..6ccb9fab055 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -92,3 +92,16 @@ out: local_irq_restore(flags); preempt_enable(); } + +/* + * Simple udelay variant. To be used on startup and reboot + * when the interrupt handler isn't working. + */ +void udelay_simple(unsigned long usecs) +{ + u64 end; + + end = get_clock() + ((u64) usecs << 12); + while (get_clock() < end) + cpu_relax(); +} diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index c0cb7254725..3db2c386546 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -859,19 +859,6 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) return -EBUSY; /* uhm... */ } -/* we can't use the normal udelay here, since it enables external interrupts */ - -static void udelay_reset(unsigned long usecs) -{ - uint64_t start_cc, end_cc; - - asm volatile ("STCK %0" : "=m" (start_cc)); - do { - cpu_relax(); - asm volatile ("STCK %0" : "=m" (end_cc)); - } while (((end_cc - start_cc)/4096) < usecs); -} - static int __clear_io_subchannel_easy(struct subchannel_id schid) { @@ -887,7 +874,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid) if (schid_equal(&ti.schid, &schid)) return 0; } - udelay_reset(100); + udelay_simple(100); } return -EBUSY; } @@ -895,7 +882,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid) static void __clear_chsc_subchannel_easy(void) { /* It seems we can only wait for a bit here :/ */ - udelay_reset(100); + udelay_simple(100); } static int pgm_check_occured; -- GitLab From ada3df9171e48b2a5f1e9c828337b61746e19ff0 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Fri, 10 Oct 2008 21:33:23 +0200 Subject: [PATCH 3764/5416] [S390] dasd: fix message flood for unsolicited interrupts In the unsolicited interupt handler fake IRBs from CIO have to be ignored because there is nothing to do. The function dump_sense should not be called if there is no sense data available. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 72d3970f11a..8095629bc49 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1501,12 +1501,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, return; } - /* just report other unsolicited interrupts */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", - "unsolicited interrupt received"); - device->discipline->dump_sense(device, NULL, irb); - dasd_schedule_device_bh(device); + if ((irb->scsw.cmd.cc == 1) && + (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && + (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) && + (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) { + /* fake irb do nothing, they are handled elsewhere */ + dasd_schedule_device_bh(device); + return; + } + if (!(irb->esw.esw0.erw.cons)) { + /* just report other unsolicited interrupts */ + DEV_MESSAGE(KERN_ERR, device, "%s", + "unsolicited interrupt received"); + } else { + DEV_MESSAGE(KERN_ERR, device, "%s", + "unsolicited interrupt received " + "(sense available)"); + device->discipline->dump_sense(device, NULL, irb); + } + + dasd_schedule_device_bh(device); return; }; -- GitLab From 3ce66093f5ec5a6ae0ca90c79d81eee15e842293 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:24 +0200 Subject: [PATCH 3765/5416] [S390] xpram: per device block request queues. The xpram driver uses a single block device queue for all of its devices so far. With recent kernels removing xpram module fails to clean up all sysfs files. The next time the xpram module is loaded you'll get warnings: WARNING: at fs/sysfs/dir.c:463 sysfs_add_one+0x5e/0x64() sysfs: duplicate filename '35:0' can not be created Modules linked in: xpram(+) [last unloaded: xpram] Followed by the usual WARN_ON output, followed by an error message from kobject_add_internal, followed by a badness in genhd. Allocating a block queue per device fixes this. Signed-off-by: Martin Schwidefsky --- drivers/s390/block/xpram.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index dd9b986389a..03916989ed2 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -56,6 +56,7 @@ typedef struct { static xpram_device_t xpram_devices[XPRAM_MAX_DEVS]; static unsigned int xpram_sizes[XPRAM_MAX_DEVS]; static struct gendisk *xpram_disks[XPRAM_MAX_DEVS]; +static struct request_queue *xpram_queues[XPRAM_MAX_DEVS]; static unsigned int xpram_pages; static int xpram_devs; @@ -330,18 +331,22 @@ static int __init xpram_setup_sizes(unsigned long pages) return 0; } -static struct request_queue *xpram_queue; - static int __init xpram_setup_blkdev(void) { unsigned long offset; int i, rc = -ENOMEM; for (i = 0; i < xpram_devs; i++) { - struct gendisk *disk = alloc_disk(1); - if (!disk) + xpram_disks[i] = alloc_disk(1); + if (!xpram_disks[i]) + goto out; + xpram_queues[i] = blk_alloc_queue(GFP_KERNEL); + if (!xpram_queues[i]) { + put_disk(xpram_disks[i]); goto out; - xpram_disks[i] = disk; + } + blk_queue_make_request(xpram_queues[i], xpram_make_request); + blk_queue_hardsect_size(xpram_queues[i], 4096); } /* @@ -351,18 +356,6 @@ static int __init xpram_setup_blkdev(void) if (rc < 0) goto out; - /* - * Assign the other needed values: make request function, sizes and - * hardsect size. All the minor devices feature the same value. - */ - xpram_queue = blk_alloc_queue(GFP_KERNEL); - if (!xpram_queue) { - rc = -ENOMEM; - goto out_unreg; - } - blk_queue_make_request(xpram_queue, xpram_make_request); - blk_queue_hardsect_size(xpram_queue, 4096); - /* * Setup device structures. */ @@ -377,18 +370,18 @@ static int __init xpram_setup_blkdev(void) disk->first_minor = i; disk->fops = &xpram_devops; disk->private_data = &xpram_devices[i]; - disk->queue = xpram_queue; + disk->queue = xpram_queues[i]; sprintf(disk->disk_name, "slram%d", i); set_capacity(disk, xpram_sizes[i] << 1); add_disk(disk); } return 0; -out_unreg: - unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); out: - while (i--) + while (i--) { + blk_cleanup_queue(xpram_queues[i]); put_disk(xpram_disks[i]); + } return rc; } @@ -400,10 +393,10 @@ static void __exit xpram_exit(void) int i; for (i = 0; i < xpram_devs; i++) { del_gendisk(xpram_disks[i]); + blk_cleanup_queue(xpram_queues[i]); put_disk(xpram_disks[i]); } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); - blk_cleanup_queue(xpram_queue); } static int __init xpram_init(void) -- GitLab From ab1d848fd6a9151b02c6cbf4bddce6e24707b094 Mon Sep 17 00:00:00 2001 From: Nigel Hislop Date: Fri, 10 Oct 2008 21:33:25 +0200 Subject: [PATCH 3766/5416] [S390] Add ioctl support for EMC Symmetrix Subsystem Control I/O EMC Symmetrix Subsystem Control I/O through CKD dasd requires a specific parameter list sent to the array via a Perform Subsystem Function CCW. The Symmetrix response is retrieved from the array via a Read Subsystem Data CCW. Signed-off-by: Nigel Hislop Signed-off-by: Hannes Reinecke Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/dasd.h | 13 +++++ drivers/s390/block/dasd_eckd.c | 101 +++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index 3f002e13d02..55b2b80cdf6 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h @@ -3,6 +3,8 @@ * Author(s)......: Holger Smolinski * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 + * Author.........: Nigel Hislop * * This file is the interface of the DASD device driver, which is exported to user space * any future changes wrt the API will result in a change of the APIVERSION reported @@ -202,6 +204,16 @@ typedef struct attrib_data_t { #define DASD_SEQ_PRESTAGE 0x4 #define DASD_REC_ACCESS 0x5 +/* + * Perform EMC Symmetrix I/O + */ +typedef struct dasd_symmio_parms { + unsigned char reserved[8]; /* compat with older releases */ + unsigned long long psf_data; /* char * cast to u64 */ + unsigned long long rssd_result; /* char * cast to u64 */ + int psf_data_len; + int rssd_result_len; +} __attribute__ ((packed)) dasd_symmio_parms_t; /******************************************************************************** * SECTION: Definition of IOCTLs @@ -247,6 +259,7 @@ typedef struct attrib_data_t { /* Set Attributes (cache operations) */ #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) +#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) #endif /* DASD_H */ diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 8095629bc49..49f9d221e23 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -6,6 +6,8 @@ * Martin Schwidefsky * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + * EMC Symmetrix ioctl Copyright EMC Corporation, 2008 + * Author.........: Nigel Hislop * */ @@ -2083,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) return 0; } +/* + * Issue syscall I/O to EMC Symmetrix array. + * CCWs are PSF and RSSD + */ +static int dasd_symm_io(struct dasd_device *device, void __user *argp) +{ + struct dasd_symmio_parms usrparm; + char *psf_data, *rssd_result; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + int rc; + + /* Copy parms from caller */ + rc = -EFAULT; + if (copy_from_user(&usrparm, argp, sizeof(usrparm))) + goto out; +#ifndef CONFIG_64BIT + /* Make sure pointers are sane even on 31 bit. */ + if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) { + rc = -EINVAL; + goto out; + } +#endif + /* alloc I/O data area */ + psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); + rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); + if (!psf_data || !rssd_result) { + rc = -ENOMEM; + goto out_free; + } + + /* get syscall header from user space */ + rc = -EFAULT; + if (copy_from_user(psf_data, + (void __user *)(unsigned long) usrparm.psf_data, + usrparm.psf_data_len)) + goto out_free; + + /* sanity check on syscall header */ + if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { + rc = -EINVAL; + goto out_free; + } + + /* setup CCWs for PSF + RSSD */ + cqr = dasd_smalloc_request("ECKD", 2 , 0, device); + if (IS_ERR(cqr)) { + DEV_MESSAGE(KERN_WARNING, device, "%s", + "Could not allocate initialization request"); + rc = PTR_ERR(cqr); + goto out_free; + } + + cqr->startdev = device; + cqr->memdev = device; + cqr->retries = 3; + cqr->expires = 10 * HZ; + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + + /* Build the ccws */ + ccw = cqr->cpaddr; + + /* PSF ccw */ + ccw->cmd_code = DASD_ECKD_CCW_PSF; + ccw->count = usrparm.psf_data_len; + ccw->flags |= CCW_FLAG_CC; + ccw->cda = (__u32)(addr_t) psf_data; + + ccw++; + + /* RSSD ccw */ + ccw->cmd_code = DASD_ECKD_CCW_RSSD; + ccw->count = usrparm.rssd_result_len; + ccw->flags = CCW_FLAG_SLI ; + ccw->cda = (__u32)(addr_t) rssd_result; + + rc = dasd_sleep_on(cqr); + if (rc) + goto out_sfree; + + rc = -EFAULT; + if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result, + rssd_result, usrparm.rssd_result_len)) + goto out_sfree; + rc = 0; + +out_sfree: + dasd_sfree_request(cqr, cqr->memdev); +out_free: + kfree(rssd_result); + kfree(psf_data); +out: + DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); + return rc; +} + static int dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) { @@ -2101,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) return dasd_eckd_reserve(device); case BIODASDSLCK: return dasd_eckd_steal_lock(device); + case BIODASDSYMMIO: + return dasd_symm_io(device, argp); default: return -ENOIOCTLCMD; } -- GitLab From 15e86b0c752d50e910b2cca6e83ce74c4440d06c Mon Sep 17 00:00:00 2001 From: Florian Funke Date: Fri, 10 Oct 2008 21:33:26 +0200 Subject: [PATCH 3767/5416] [S390] introduce dirty bit for kvm live migration This patch defines a dirty bit in the PGSTE that can be used to implement dirty pages logging for KVM's live migration. The bit is set in the ptep_rcp_copy function, which is called to save dirty and referenced information from the storage key in the PGSTE. The bit can be tested and reset by KVM using the kvm_s390_test_and_clear_page_dirty function that is introduced by this patch. Acked-by: Carsten Otte Signed-off-by: Florian Funke Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/pgtable.h | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 0bdb704ae05..1a928f84afd 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE]; #define RCP_GR_BIT 50 #define RCP_GC_BIT 49 +/* User dirty bit for KVM's migration feature */ +#define KVM_UD_BIT 47 + #ifndef __s390x__ /* Bits in the segment table address-space-control-element */ @@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep) unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); skey = page_get_storage_key(page_to_phys(page)); - if (skey & _PAGE_CHANGED) + if (skey & _PAGE_CHANGED) { set_bit_simple(RCP_GC_BIT, pgste); + set_bit_simple(KVM_UD_BIT, pgste); + } if (skey & _PAGE_REFERENCED) set_bit_simple(RCP_GR_BIT, pgste); - if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) + if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { SetPageDirty(page); + set_bit_simple(KVM_UD_BIT, pgste); + } if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) SetPageReferenced(page); #endif @@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte) return pte; } +#ifdef CONFIG_PGSTE +/* + * Get (and clear) the user dirty bit for a PTE. + */ +static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm, + pte_t *ptep) +{ + int dirty; + unsigned long *pgste; + struct page *page; + unsigned int skey; + + if (!mm->context.pgstes) + return -EINVAL; + rcp_lock(ptep); + pgste = (unsigned long *) (ptep + PTRS_PER_PTE); + page = virt_to_page(pte_val(*ptep)); + skey = page_get_storage_key(page_to_phys(page)); + if (skey & _PAGE_CHANGED) { + set_bit_simple(RCP_GC_BIT, pgste); + set_bit_simple(KVM_UD_BIT, pgste); + } + if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { + SetPageDirty(page); + set_bit_simple(KVM_UD_BIT, pgste); + } + dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste); + if (skey & _PAGE_CHANGED) + page_clear_dirty(page); + rcp_unlock(ptep); + return dirty; +} +#endif + #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) -- GitLab From 2332ce1a97963b7769e0c2d40492a10a124efba5 Mon Sep 17 00:00:00 2001 From: Holger Smolinski Date: Fri, 10 Oct 2008 21:33:27 +0200 Subject: [PATCH 3768/5416] [S390] console flush on panic / reboot The s390 console drivers use the unblank callback of the console structure to flush the console buffer. In case of a panic or a reboot the CPU doing the callback can block on the console i/o. The other CPUs in the system continue to work. For panic this is not a good idea. Replace the unblank callback with proper panic/reboot notifier. These get called after all but one CPU have been stopped. Signed-off-by: Holger Smolinski Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 27 +++++++++++++++++++++++---- drivers/s390/char/con3270.c | 27 +++++++++++++++++++++++---- drivers/s390/char/sclp_con.c | 24 ++++++++++++++++++++++-- drivers/s390/char/sclp_vt220.c | 26 ++++++++++++++++++-------- 4 files changed, 86 insertions(+), 18 deletions(-) diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index d3ec9b55ab3..982cf62ab66 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -775,11 +776,11 @@ static struct tty_driver *con3215_device(struct console *c, int *index) } /* - * panic() calls console_unblank before the system enters a - * disabled, endless loop. + * panic() calls con3215_flush through a panic_notifier + * before the system enters a disabled, endless loop. */ static void -con3215_unblank(void) +con3215_flush(void) { struct raw3215_info *raw; unsigned long flags; @@ -790,6 +791,23 @@ con3215_unblank(void) spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } +static int con3215_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + con3215_flush(); + return NOTIFY_OK; +} + +static struct notifier_block on_panic_nb = { + .notifier_call = con3215_notify, + .priority = 0, +}; + +static struct notifier_block on_reboot_nb = { + .notifier_call = con3215_notify, + .priority = 0, +}; + /* * The console structure for the 3215 console */ @@ -797,7 +815,6 @@ static struct console con3215 = { .name = "ttyS", .write = con3215_write, .device = con3215_device, - .unblank = con3215_unblank, .flags = CON_PRINTBUFFER, }; @@ -859,6 +876,8 @@ con3215_init(void) raw3215[0] = NULL; return -ENODEV; } + atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + register_reboot_notifier(&on_reboot_nb); register_console(&con3215); return 0; } diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 3c07974886e..d028d2ee83d 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -528,11 +529,11 @@ con3270_wait_write(struct con3270 *cp) } /* - * panic() calls console_unblank before the system enters a - * disabled, endless loop. + * panic() calls con3270_flush through a panic_notifier + * before the system enters a disabled, endless loop. */ static void -con3270_unblank(void) +con3270_flush(void) { struct con3270 *cp; unsigned long flags; @@ -554,6 +555,23 @@ con3270_unblank(void) spin_unlock_irqrestore(&cp->view.lock, flags); } +static int con3270_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + con3270_flush(); + return NOTIFY_OK; +} + +static struct notifier_block on_panic_nb = { + .notifier_call = con3270_notify, + .priority = 0, +}; + +static struct notifier_block on_reboot_nb = { + .notifier_call = con3270_notify, + .priority = 0, +}; + /* * The console structure for the 3270 console */ @@ -561,7 +579,6 @@ static struct console con3270 = { .name = "tty3270", .write = con3270_write, .device = con3270_device, - .unblank = con3270_unblank, .flags = CON_PRINTBUFFER, }; @@ -623,6 +640,8 @@ con3270_init(void) condev->cline->len = 0; con3270_create_status(condev); condev->input = alloc_string(&condev->freemem, 80); + atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + register_reboot_notifier(&on_reboot_nb); register_console(&con3270); return 0; } diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index 7e619c534bf..9a25c4bd142 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "sclp.h" #include "sclp_rw.h" @@ -172,7 +173,7 @@ sclp_console_device(struct console *c, int *index) * will be flushed to the SCLP. */ static void -sclp_console_unblank(void) +sclp_console_flush(void) { unsigned long flags; @@ -188,6 +189,24 @@ sclp_console_unblank(void) spin_unlock_irqrestore(&sclp_con_lock, flags); } +static int +sclp_console_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + sclp_console_flush(); + return NOTIFY_OK; +} + +static struct notifier_block on_panic_nb = { + .notifier_call = sclp_console_notify, + .priority = 1, +}; + +static struct notifier_block on_reboot_nb = { + .notifier_call = sclp_console_notify, + .priority = 1, +}; + /* * used to register the SCLP console to the kernel and to * give printk necessary information @@ -197,7 +216,6 @@ static struct console sclp_console = .name = sclp_console_name, .write = sclp_console_write, .device = sclp_console_device, - .unblank = sclp_console_unblank, .flags = CON_PRINTBUFFER, .index = 0 /* ttyS0 */ }; @@ -241,6 +259,8 @@ sclp_console_init(void) sclp_con_width_htab = 8; /* enable printk-access to this driver */ + atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + register_reboot_notifier(&on_reboot_nb); register_console(&sclp_console); return 0; } diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index ad51738c426..9854f19f5e6 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -24,6 +24,8 @@ #include #include #include +#include + #include #include "sclp.h" @@ -743,24 +745,30 @@ sclp_vt220_con_device(struct console *c, int *index) return sclp_vt220_driver; } -/* - * This routine is called from panic when the kernel is going to give up. - * We have to make sure that all buffers will be flushed to the SCLP. - * Note that this function may be called from within an interrupt context. - */ -static void -sclp_vt220_con_unblank(void) +static int +sclp_vt220_notify(struct notifier_block *self, + unsigned long event, void *data) { __sclp_vt220_flush_buffer(); + return NOTIFY_OK; } +static struct notifier_block on_panic_nb = { + .notifier_call = sclp_vt220_notify, + .priority = 1, +}; + +static struct notifier_block on_reboot_nb = { + .notifier_call = sclp_vt220_notify, + .priority = 1, +}; + /* Structure needed to register with printk */ static struct console sclp_vt220_console = { .name = SCLP_VT220_CONSOLE_NAME, .write = sclp_vt220_con_write, .device = sclp_vt220_con_device, - .unblank = sclp_vt220_con_unblank, .flags = CON_PRINTBUFFER, .index = SCLP_VT220_CONSOLE_INDEX }; @@ -776,6 +784,8 @@ sclp_vt220_con_init(void) if (rc) return rc; /* Attach linux console */ + atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + register_reboot_notifier(&on_reboot_nb); register_console(&sclp_vt220_console); return 0; } -- GitLab From 408aec3c6c3cb5b4774f96ea7a35cd15ee91a56f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 10 Oct 2008 21:33:28 +0200 Subject: [PATCH 3769/5416] [S390] 3215: Remove tasklet. The 3215 console irq handler used to schedule a tasklet. However the console irq handler also gets called from the infamous cio_tpi() function. Which in turn does something like local_bh_disable() [call console irq handler] _local_bh_enable() _local_bh_enable() prevents execution of softirqs, which is intended within cio_tpi(). However there might be a new softirq pending because irq handler scheduled a tasklet. In order to prevent this behaviour we just get rid of the tasklet. It's not doing much anyway. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 982cf62ab66..9ab06e0dad4 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -89,7 +89,6 @@ struct raw3215_info { int count; /* number of bytes in output buffer */ int written; /* number of bytes in write requests */ struct tty_struct *tty; /* pointer to tty structure if present */ - struct tasklet_struct tasklet; struct raw3215_req *queued_read; /* pointer to queued read requests */ struct raw3215_req *queued_write;/* pointer to queued write requests */ wait_queue_head_t empty_wait; /* wait queue for flushing */ @@ -342,21 +341,14 @@ raw3215_try_io(struct raw3215_info *raw) } /* - * The bottom half handler routine for 3215 devices. It tries to start - * the next IO and wakes up processes waiting on the tty. + * Try to start the next IO and wake up processes waiting on the tty. */ -static void -raw3215_tasklet(void *data) +static void raw3215_next_io(struct raw3215_info *raw) { - struct raw3215_info *raw; struct tty_struct *tty; - unsigned long flags; - raw = (struct raw3215_info *) data; - spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); raw3215_mk_write_req(raw); raw3215_try_io(raw); - spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); tty = raw->tty; if (tty != NULL && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) { @@ -381,7 +373,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) cstat = irb->scsw.cmd.cstat; dstat = irb->scsw.cmd.dstat; if (cstat != 0) - tasklet_schedule(&raw->tasklet); + raw3215_next_io(raw); if (dstat & 0x01) { /* we got a unit exception */ dstat &= ~0x01; /* we can ignore it */ } @@ -391,7 +383,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) break; /* Attention interrupt, someone hit the enter key */ raw3215_mk_read_req(raw); - tasklet_schedule(&raw->tasklet); + raw3215_next_io(raw); break; case 0x08: case 0x0C: @@ -449,7 +441,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) raw->queued_read == NULL) { wake_up_interruptible(&raw->empty_wait); } - tasklet_schedule(&raw->tasklet); + raw3215_next_io(raw); break; default: /* Strange interrupt, I'll do my best to clean up */ @@ -461,7 +453,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) raw->flags &= ~RAW3215_WORKING; raw3215_free_req(req); } - tasklet_schedule(&raw->tasklet); + raw3215_next_io(raw); } return; } @@ -675,9 +667,6 @@ raw3215_probe (struct ccw_device *cdev) kfree(raw); return -ENOMEM; } - tasklet_init(&raw->tasklet, - (void (*)(unsigned long)) raw3215_tasklet, - (unsigned long) raw); init_waitqueue_head(&raw->empty_wait); cdev->dev.driver_data = raw; @@ -863,9 +852,6 @@ con3215_init(void) cdev->handler = raw3215_irq; raw->flags |= RAW3215_FIXED; - tasklet_init(&raw->tasklet, - (void (*)(unsigned long)) raw3215_tasklet, - (unsigned long) raw); init_waitqueue_head(&raw->empty_wait); /* Request the console irq */ -- GitLab From 4a672cfa3a7fcbc6f2adc558f34148be1096c561 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 10 Oct 2008 21:33:29 +0200 Subject: [PATCH 3770/5416] [S390] fix initialization of stp chsc_sstpc returns -EIO on error and 0 on success but stp_reset checks against 1 instead of 0. chsc_sstpc used to return 1 on success, one call location has not been updated .. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 06acb1a18bb..b94e9e3b694 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -1356,7 +1356,7 @@ static void __init stp_reset(void) stp_page = alloc_bootmem_pages(PAGE_SIZE); rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); - if (rc == 1) + if (rc == 0) set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); else if (stp_online) { printk(KERN_WARNING "Running on non STP capable machine.\n"); -- GitLab From 89d49841e9e7a90b04b036b7dbe7521b55edbe24 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 10 Oct 2008 21:33:30 +0200 Subject: [PATCH 3771/5416] [S390] Fix checkstack for s390 With -march=z990 and later gcc can use the long displacement facility insruction lay for stack register handling. This patch adopts checkstack to catch lay in addition to ahi and aghi. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- scripts/checkstack.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index 3eca62566d6..f7e8e93ff30 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -81,7 +81,10 @@ my (@stack, $re, $dre, $x, $xs); $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; } elsif ($arch =~ /^s390x?$/) { # 11160: a7 fb ff 60 aghi %r15,-160 - $re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o; + # or + # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) + $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) + (?:\(\%r15\))?$/ox; } elsif ($arch =~ /^sh64$/) { #XXX: we only check for the immediate case presently, # though we will want to check for the movi/sub -- GitLab From 730616b2026838c4535c1daf9b91b118fd7caecf Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Fri, 10 Oct 2008 22:39:17 +0200 Subject: [PATCH 3772/5416] ide-tape: Buildfix when IDETAPE_DEBUG_LOG is set to 1. The format specifier for rq->sector didn't specify the proper size and signedness. Borislav Petkov discovered that the signedness for rq->nr_sectors and rq->current_nr_sectors also were incorrect. Signed-off-by: Mark de Wever Acked-by: Borislav Petkov [bart: remove trailing whitespace] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-tape.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 3833189144e..a373cc4142b 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -978,9 +978,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, struct request *postponed_rq = tape->postponed_rq; u8 stat; - debug_log(DBG_SENSE, "sector: %ld, nr_sectors: %ld," - " current_nr_sectors: %d\n", - rq->sector, rq->nr_sectors, rq->current_nr_sectors); + debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," + " current_nr_sectors: %u\n", + (unsigned long long)rq->sector, rq->nr_sectors, + rq->current_nr_sectors); if (!blk_special_request(rq)) { /* We do not support buffer cache originated requests. */ -- GitLab From f8881000d7cc6b8b520e8fcba95177d2cde1ae36 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:18 +0200 Subject: [PATCH 3773/5416] ide: remove superfluous check from ide_disk_special() This condition is checked by both ide_disk_init_mult_count() and set_multcount() so no need to do it again in ide_disk_special(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index a896a283f27..1678043701d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -540,8 +540,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) ide_tf_set_restore_cmd(drive, &args.tf); } else if (s->b.set_multmode) { s->b.set_multmode = 0; - if (drive->mult_req > drive->id->max_multsect) - drive->mult_req = drive->id->max_multsect; ide_tf_set_setmult_cmd(drive, &args.tf); } else if (s->all) { int special = s->all; -- GitLab From df1f8378c2fd898fa08be5d72283d68c77f519e9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:18 +0200 Subject: [PATCH 3774/5416] ide: cleanup ide_disk_init_mult_count() * Remove superfluous checks for drive->mult_req. * No need to zero drive's fields. * Move the common code out of #ifdef scope. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 70aa86c8807..a776a6d73c5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -89,20 +89,19 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) { struct hd_driveid *id = drive->id; - drive->mult_count = 0; if (id->max_multsect) { #ifdef CONFIG_IDEDISK_MULTI_MODE - id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; - id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : 0; - drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = 0; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; + if ((id->max_multsect / 2) > 1) { + id->multsect = id->max_multsect; + id->multsect_valid = 1; + } else { + id->multsect = 0; + id->multsect_valid = 0; + } + drive->mult_req = id->multsect; #endif + if ((id->multsect_valid & 1) && id->multsect) + drive->special.b.set_multmode = 1; } } -- GitLab From 5b90e990928919ae411a68b865e8a6ecac09a603 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:18 +0200 Subject: [PATCH 3775/5416] ide: cleanup ide_fix_driveid() Do all __le16_to_cpu() swapping in one loop. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 107 ++++++++--------------------------------- 1 file changed, 20 insertions(+), 87 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 2cbadffe922..68d655e0fa4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -400,97 +400,30 @@ const struct ide_tp_ops default_tp_ops = { .output_data = ide_output_data, }; -void ide_fix_driveid (struct hd_driveid *id) +void ide_fix_driveid(struct hd_driveid *driveid) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN + u16 *id = (u16 *)driveid; int i; - u16 *stringcast; - - id->config = __le16_to_cpu(id->config); - id->cyls = __le16_to_cpu(id->cyls); - id->reserved2 = __le16_to_cpu(id->reserved2); - id->heads = __le16_to_cpu(id->heads); - id->track_bytes = __le16_to_cpu(id->track_bytes); - id->sector_bytes = __le16_to_cpu(id->sector_bytes); - id->sectors = __le16_to_cpu(id->sectors); - id->vendor0 = __le16_to_cpu(id->vendor0); - id->vendor1 = __le16_to_cpu(id->vendor1); - id->vendor2 = __le16_to_cpu(id->vendor2); - stringcast = (u16 *)&id->serial_no[0]; - for (i = 0; i < (20/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->buf_type = __le16_to_cpu(id->buf_type); - id->buf_size = __le16_to_cpu(id->buf_size); - id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); - stringcast = (u16 *)&id->fw_rev[0]; - for (i = 0; i < (8/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - stringcast = (u16 *)&id->model[0]; - for (i = 0; i < (40/2); i++) - stringcast[i] = __le16_to_cpu(stringcast[i]); - id->dword_io = __le16_to_cpu(id->dword_io); - id->reserved50 = __le16_to_cpu(id->reserved50); - id->field_valid = __le16_to_cpu(id->field_valid); - id->cur_cyls = __le16_to_cpu(id->cur_cyls); - id->cur_heads = __le16_to_cpu(id->cur_heads); - id->cur_sectors = __le16_to_cpu(id->cur_sectors); - id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); - id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); - id->lba_capacity = __le32_to_cpu(id->lba_capacity); - id->dma_1word = __le16_to_cpu(id->dma_1word); - id->dma_mword = __le16_to_cpu(id->dma_mword); - id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); - id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); - id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); - id->eide_pio = __le16_to_cpu(id->eide_pio); - id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); - for (i = 0; i < 2; ++i) - id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); - for (i = 0; i < 4; ++i) - id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); - id->queue_depth = __le16_to_cpu(id->queue_depth); - for (i = 0; i < 4; ++i) - id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); - id->major_rev_num = __le16_to_cpu(id->major_rev_num); - id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); - id->command_set_1 = __le16_to_cpu(id->command_set_1); - id->command_set_2 = __le16_to_cpu(id->command_set_2); - id->cfsse = __le16_to_cpu(id->cfsse); - id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); - id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); - id->csf_default = __le16_to_cpu(id->csf_default); - id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->trseuc = __le16_to_cpu(id->trseuc); - id->trsEuc = __le16_to_cpu(id->trsEuc); - id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->mprc = __le16_to_cpu(id->mprc); - id->hw_config = __le16_to_cpu(id->hw_config); - id->acoustic = __le16_to_cpu(id->acoustic); - id->msrqs = __le16_to_cpu(id->msrqs); - id->sxfert = __le16_to_cpu(id->sxfert); - id->sal = __le16_to_cpu(id->sal); - id->spg = __le32_to_cpu(id->spg); - id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); - for (i = 0; i < 22; i++) - id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); - id->last_lun = __le16_to_cpu(id->last_lun); - id->word127 = __le16_to_cpu(id->word127); - id->dlf = __le16_to_cpu(id->dlf); - id->csfo = __le16_to_cpu(id->csfo); - for (i = 0; i < 26; i++) - id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); - id->word156 = __le16_to_cpu(id->word156); - for (i = 0; i < 3; i++) - id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); - id->cfa_power = __le16_to_cpu(id->cfa_power); - for (i = 0; i < 15; i++) - id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); - for (i = 0; i < 30; i++) - id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); - for (i = 0; i < 49; i++) - id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); - id->integrity_word = __le16_to_cpu(id->integrity_word); + + for (i = 0; i < 256; i++) { + /* these words are accessed as two 8-bit values */ + if (i == 47 || i == 49 || i == 51 || i == 52 || i == 59) + continue; + if (i == 60 || i == 61) /* ->lba_capacity is 32-bit */ + continue; + if (i == 98 || i == 99) /* ->spg is 32-bit */ + continue; + if (i > 99 && i < 104) /* ->lba_capacity_2 is 64-bit */ + continue; + + id[i] = __le16_to_cpu(id[i]); + } + + driveid->lba_capacity = __le32_to_cpu(driveid->lba_capacity); + driveid->spg = __le32_to_cpu(driveid->spg); + driveid->lba_capacity_2 = __le64_to_cpu(driveid->lba_capacity_2); # else # error "Please fix " # endif -- GitLab From 4dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5ab Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:19 +0200 Subject: [PATCH 3776/5416] ide: make drive->id an union (take 2) Make drive->id an unnamed union so id can be accessed either by using 'u16 *id' or 'struct hd_driveid *driveid'. Then convert all existing drive->id users accordingly (using 'u16 *id' when possible). This is an intermediate step to make ide 'struct hd_driveid'-free. While at it: - Add missing KERN_CONTs in it821x.c. - Use ATA_ID_WORDS and ATA_ID_*_LEN defines. - Remove unnecessary checks for drive->id. - s/drive_table/table/ in ide_in_drive_list(). - Cleanup ide_config_drive_speed() a bit. - s/drive1/dev1/ & s/drive0/dev0/ in ide_undecoded_slave(). v2: Fix typo in drivers/ide/ppc/pmac.c. (From Stephen Rothwell) There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/icside.c | 4 +- drivers/ide/arm/palm_bk3710.c | 3 +- drivers/ide/ide-acpi.c | 6 +- drivers/ide/ide-cd.c | 15 +++-- drivers/ide/ide-disk.c | 63 +++++++++--------- drivers/ide/ide-dma.c | 50 +++++++------- drivers/ide/ide-floppy.c | 14 ++-- drivers/ide/ide-iops.c | 80 +++++++++++----------- drivers/ide/ide-lib.c | 24 +++---- drivers/ide/ide-probe.c | 117 +++++++++++++++++---------------- drivers/ide/ide-proc.c | 5 +- drivers/ide/ide-tape.c | 7 +- drivers/ide/ide-taskfile.c | 6 +- drivers/ide/ide-timings.c | 21 +++--- drivers/ide/ide.c | 8 +-- drivers/ide/legacy/qd65xx.c | 22 ++++--- drivers/ide/pci/alim15x3.c | 4 +- drivers/ide/pci/cs5530.c | 10 +-- drivers/ide/pci/hpt366.c | 8 +-- drivers/ide/pci/it821x.c | 51 +++++++------- drivers/ide/pci/pdc202xx_new.c | 4 +- drivers/ide/pci/pdc202xx_old.c | 6 +- drivers/ide/pci/sc1200.c | 10 +-- drivers/ide/pci/serverworks.c | 4 +- drivers/ide/pci/siimage.c | 8 ++- drivers/ide/ppc/pmac.c | 6 +- drivers/scsi/ide-scsi.c | 13 ++-- include/linux/ide.h | 23 ++++--- 28 files changed, 312 insertions(+), 280 deletions(-) diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index df4af408395..ca9e8ea32ee 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -265,8 +265,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should * take care to note the values in the ID... */ - if (use_dma_info && drive->id->eide_dma_time > cycle_time) - cycle_time = drive->id->eide_dma_time; + if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time) + cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME]; drive->drive_data = cycle_time; diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 4fd91dcf1dc..6cea984776f 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -213,7 +213,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) palm_bk3710_setudmamode(base, is_slave, xferspeed - XFER_UDMA_0); } else { - palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min, + palm_bk3710_setdmamode(base, is_slave, + drive->id[ATA_ID_EIDE_DMA_MIN], xferspeed); } } diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 6f704628c27..2427c380b3d 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -584,7 +584,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) * This function executes the _STM ACPI method for the target channel. * * _STM requires Identify Drive data, which has to passed as an argument. - * Unfortunately hd_driveid is a mangled version which we can't readily + * Unfortunately drive->id is a mangled version which we can't readily * use; hence we'll get the information afresh. */ void ide_acpi_push_timing(ide_hwif_t *hwif) @@ -614,10 +614,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) in_params[0].buffer.length = sizeof(struct GTM_buffer); in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; in_params[1].type = ACPI_TYPE_BUFFER; - in_params[1].buffer.length = sizeof(struct hd_driveid); + in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2); in_params[1].buffer.pointer = (u8 *)&master->idbuff; in_params[2].type = ACPI_TYPE_BUFFER; - in_params[2].buffer.length = sizeof(struct hd_driveid); + in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2); in_params[2].buffer.pointer = (u8 *)&slave->idbuff; /* Output buffer: _STM has no output */ diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 03c2cb6a58b..46f9720f1ec 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1866,14 +1866,14 @@ static const struct cd_list_entry ide_cd_quirks_list[] = { { NULL, NULL, 0 } }; -static unsigned int ide_cd_flags(struct hd_driveid *id) +static unsigned int ide_cd_flags(u16 *id) { const struct cd_list_entry *cle = ide_cd_quirks_list; while (cle->id_model) { - if (strcmp(cle->id_model, id->model) == 0 && + if (strcmp(cle->id_model, (char *)&id[ATA_ID_PROD]) == 0 && (cle->id_firmware == NULL || - strstr(id->fw_rev, cle->id_firmware))) + strstr((char *)&id[ATA_ID_FW_REV], cle->id_firmware))) return cle->cd_flags; cle++; } @@ -1885,7 +1885,8 @@ static int ide_cdrom_setup(ide_drive_t *drive) { struct cdrom_info *cd = drive->driver_data; struct cdrom_device_info *cdi = &cd->devinfo; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; + char *fw_rev = (char *)&id[ATA_ID_FW_REV]; int nslots; blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); @@ -1900,15 +1901,15 @@ static int ide_cdrom_setup(ide_drive_t *drive) drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT | ide_cd_flags(id); - if ((id->config & 0x0060) == 0x20) + if ((id[ATA_ID_CONFIG] & 0x0060) == 0x20) drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) && - id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') + fw_rev[4] == '1' && fw_rev[6] <= '2') drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD | IDE_AFLAG_TOCADDR_AS_BCD); else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) && - id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') + fw_rev[4] == '1' && fw_rev[6] <= '2') drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD; else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD) /* 3 => use CD in slot 0 */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 33ea8c04871..f1669bca3ca 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -99,12 +99,13 @@ static void ide_disk_put(struct ide_disk_obj *idkp) * * It is called only once for each drive. */ -static int lba_capacity_is_ok(struct hd_driveid *id) +static int lba_capacity_is_ok(u16 *id) { + struct hd_driveid *driveid = (struct hd_driveid *)id; unsigned long lba_sects, chs_sects, head, tail; /* No non-LBA info .. so valid! */ - if (id->cyls == 0) + if (id[ATA_ID_CYLS] == 0) return 1; /* @@ -113,15 +114,15 @@ static int lba_capacity_is_ok(struct hd_driveid *id) * Some drives can be jumpered to use 15 heads instead of 16. * Some drives can be jumpered to use 4092 cyls instead of 16383. */ - if ((id->cyls == 16383 - || (id->cyls == 4092 && id->cur_cyls == 16383)) && - id->sectors == 63 && - (id->heads == 15 || id->heads == 16) && - (id->lba_capacity >= 16383*63*id->heads)) + if ((id[ATA_ID_CYLS] == 16383 || + (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) && + id[ATA_ID_SECTORS] == 63 && + (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) && + (driveid->lba_capacity >= 16383 * 63 * id[ATA_ID_HEADS])) return 1; - lba_sects = id->lba_capacity; - chs_sects = id->cyls * id->heads * id->sectors; + lba_sects = driveid->lba_capacity; + chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS]; /* perform a rough sanity check on lba_sects: within 10% is OK */ if ((lba_sects - chs_sects) < chs_sects/10) @@ -132,7 +133,7 @@ static int lba_capacity_is_ok(struct hd_driveid *id) tail = (lba_sects & 0xffff); lba_sects = (head | (tail << 16)); if ((lba_sects - chs_sects) < chs_sects/10) { - id->lba_capacity = lba_sects; + driveid->lba_capacity = lba_sects; return 1; /* lba_capacity is (now) good */ } @@ -389,18 +390,20 @@ static unsigned long long sectors_to_MB(unsigned long long n) * so on non-buggy drives we need test only one. * However, we should also check whether these fields are valid. */ -static inline int idedisk_supports_hpa(const struct hd_driveid *id) +static inline int idedisk_supports_hpa(const u16 *id) { - return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400); + return (id[ATA_ID_COMMAND_SET_1] & 0x0400) && + (id[ATA_ID_CFS_ENABLE_1] & 0x0400); } /* * The same here. */ -static inline int idedisk_supports_lba48(const struct hd_driveid *id) +static inline int idedisk_supports_lba48(const u16 *id) { - return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) - && id->lba_capacity_2; + return (id[ATA_ID_COMMAND_SET_2] & 0x0400) && + (id[ATA_ID_CFS_ENABLE_2] & 0x0400) && + ((struct hd_driveid *)id)->lba_capacity_2; } /* @@ -453,7 +456,8 @@ static void idedisk_check_hpa(ide_drive_t *drive) static void init_idedisk_capacity(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + struct hd_driveid *driveid = drive->driveid; + u16 *id = drive->id; /* * If this drive supports the Host Protected Area feature set, * then we may need to change our opinion about the drive's capacity. @@ -463,13 +467,13 @@ static void init_idedisk_capacity(ide_drive_t *drive) if (idedisk_supports_lba48(id)) { /* drive speaks 48-bit LBA */ drive->select.b.lba = 1; - drive->capacity64 = id->lba_capacity_2; + drive->capacity64 = driveid->lba_capacity_2; if (hpa) idedisk_check_hpa(drive); - } else if ((id->capability & 2) && lba_capacity_is_ok(id)) { + } else if ((driveid->capability & 2) && lba_capacity_is_ok(id)) { /* drive speaks 28-bit LBA */ drive->select.b.lba = 1; - drive->capacity64 = id->lba_capacity; + drive->capacity64 = driveid->lba_capacity; if (hpa) idedisk_check_hpa(drive); } else { @@ -523,7 +527,7 @@ static int proc_idedisk_read_cache int len; if (drive->id_read) - len = sprintf(out, "%i\n", drive->id->buf_size / 2); + len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2); else len = sprintf(out, "(none)\n"); @@ -618,7 +622,7 @@ static int set_multcount(ide_drive_t *drive, int arg) struct request *rq; int error; - if (arg < 0 || arg > drive->id->max_multsect) + if (arg < 0 || arg > drive->driveid->max_multsect) return -EINVAL; if (drive->special.b.set_multmode) @@ -650,7 +654,7 @@ static int set_nowerr(ide_drive_t *drive, int arg) static void update_ordered(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; unsigned ordered = QUEUE_ORDERED_NONE; prepare_flush_fn *prep_fn = NULL; @@ -762,8 +766,6 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) #ifdef CONFIG_IDE_PROC_FS static void idedisk_add_settings(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, @@ -773,7 +775,7 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, - id->max_multsect, 1, 1, &drive->mult_count, + drive->driveid->max_multsect, 1, 1, &drive->mult_count, set_multcount); ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); @@ -795,7 +797,8 @@ static inline void idedisk_add_settings(ide_drive_t *drive) { ; } static void idedisk_setup(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; unsigned long long capacity; idedisk_add_settings(drive); @@ -807,7 +810,7 @@ static void idedisk_setup(ide_drive_t *drive) /* * Removable disks (eg. SYQUEST); ignore 'WD' drives */ - if (id->model[0] != 'W' || id->model[1] != 'D') + if (m[0] != 'W' || m[1] != 'D') drive->doorlocking = 1; } @@ -880,14 +883,14 @@ static void idedisk_setup(ide_drive_t *drive) drive->name, capacity, sectors_to_MB(capacity)); /* Only print cache size when it was specified */ - if (id->buf_size) - printk(KERN_CONT " w/%dKiB Cache", id->buf_size / 2); + if (id[ATA_ID_BUF_SIZE]) + printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2); printk(KERN_CONT ", CHS=%d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); /* write cache enabled? */ - if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5))) + if ((id[ATA_ID_CSFO] & 1) || (id[ATA_ID_CFS_ENABLE_1] & (1 << 5))) drive->wcache = 1; write_cache(drive, 1); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 3fa07c0aeaa..abab26de768 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable); static int config_drive_for_dma (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; if (drive->media != ide_disk) { if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA) @@ -299,16 +299,17 @@ static int config_drive_for_dma (ide_drive_t *drive) * Enable DMA on any drive that has * UltraDMA (mode 0/1/2/3/4/5/6) enabled */ - if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) + if ((id[ATA_ID_FIELD_VALID] & 4) && + ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f)) return 1; /* * Enable DMA on any drive that has mode2 DMA * (multi or single) enabled */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || - (id->dma_1word & 0x404) == 0x404) + if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */ + if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 || + (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404) return 1; /* Consult the list of known "good" drives */ @@ -591,12 +592,12 @@ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; } int __ide_dma_bad_drive (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; int blacklist = ide_in_drive_list(id, drive_blacklist); if (blacklist) { printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n", - drive->name, id->model); + drive->name, (char *)&id[ATA_ID_PROD]); return blacklist; } return 0; @@ -612,21 +613,21 @@ static const u8 xfer_mode_bases[] = { static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; ide_hwif_t *hwif = drive->hwif; const struct ide_port_ops *port_ops = hwif->port_ops; unsigned int mask = 0; switch(base) { case XFER_UDMA_0: - if ((id->field_valid & 4) == 0) + if ((id[ATA_ID_FIELD_VALID] & 4) == 0) break; if (port_ops && port_ops->udma_filter) mask = port_ops->udma_filter(drive); else mask = hwif->ultra_mask; - mask &= id->dma_ultra; + mask &= id[ATA_ID_UDMA_MODES]; /* * avoid false cable warning from eighty_ninty_three() @@ -637,19 +638,19 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) } break; case XFER_MW_DMA_0: - if ((id->field_valid & 2) == 0) + if ((id[ATA_ID_FIELD_VALID] & 2) == 0) break; if (port_ops && port_ops->mdma_filter) mask = port_ops->mdma_filter(drive); else mask = hwif->mwdma_mask; - mask &= id->dma_mword; + mask &= id[ATA_ID_MWDMA_MODES]; break; case XFER_SW_DMA_0: - if (id->field_valid & 2) { - mask = id->dma_1word & hwif->swdma_mask; - } else if (id->tDMA) { - u8 mode = id->tDMA; + if (id[ATA_ID_FIELD_VALID] & 2) { + mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask; + } else if (drive->driveid->tDMA) { + u8 mode = drive->driveid->tDMA; /* * if the mode is valid convert it to the mask @@ -706,7 +707,8 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) /* * is this correct? */ - if (ide_dma_good_drive(drive) && drive->id->eide_dma_time < 150) + if (ide_dma_good_drive(drive) && + drive->id[ATA_ID_EIDE_DMA_TIME] < 150) mode = XFER_MW_DMA_1; } @@ -725,7 +727,7 @@ static int ide_tune_dma(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; u8 speed; - if (drive->nodma || (drive->id->capability & 1) == 0) + if (drive->nodma || (drive->driveid->capability & 1) == 0) return 0; /* consult the list of known "bad" drives */ @@ -767,13 +769,15 @@ static int ide_dma_check(ide_drive_t *drive) int ide_id_dma_bug(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; - if (id->field_valid & 4) { - if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) + if (id[ATA_ID_FIELD_VALID] & 4) { + if ((id[ATA_ID_UDMA_MODES] >> 8) && + (id[ATA_ID_MWDMA_MODES] >> 8)) goto err_out; - } else if (id->field_valid & 2) { - if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) + } else if (id[ATA_ID_FIELD_VALID] & 2) { + if ((id[ATA_ID_MWDMA_MODES] >> 8) && + (id[ATA_ID_SWDMA_MODES] >> 8)) goto err_out; } return 0; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index e9034c0125f..67f93a46f51 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -965,12 +965,12 @@ static sector_t idefloppy_capacity(ide_drive_t *drive) * Check whether we can support a drive, based on the ATAPI IDENTIFY command * results. */ -static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id) +static int idefloppy_identify_device(ide_drive_t *drive, u16 *id) { u8 gcw[2]; u8 device_type, protocol, removable, drq_type, packet_size; - *((u16 *) &gcw) = id->config; + *((u16 *)&gcw) = id[ATA_ID_CONFIG]; device_type = gcw[1] & 0x1F; removable = (gcw[0] & 0x80) >> 7; @@ -981,7 +981,8 @@ static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id) #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ if (device_type == 5 && - !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) + !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && + strstr((char *)&id[ATA_ID_PROD], "ZIP")) device_type = 0; #endif @@ -1024,9 +1025,10 @@ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) { + u16 *id = drive->id; u8 gcw[2]; - *((u16 *) &gcw) = drive->id->config; + *((u16 *)&gcw) = id[ATA_ID_CONFIG]; floppy->pc = floppy->pc_stack; drive->pc_callback = ide_floppy_callback; @@ -1041,7 +1043,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) * it. It should be fixed as of version 1.9, but to be on the safe side * we'll leave the limitation below for the 2.2.x tree. */ - if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) { + if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) { drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE; /* This value will be visible in the /proc/ide/hdx/settings */ floppy->ticks = IDEFLOPPY_TICKS_DELAY; @@ -1052,7 +1054,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes * nasty clicking noises without it, so please don't remove this. */ - if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) { + if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) { blk_queue_max_sectors(drive->queue, 64); drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE; } diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 68d655e0fa4..01b1943b315 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -400,11 +400,11 @@ const struct ide_tp_ops default_tp_ops = { .output_data = ide_output_data, }; -void ide_fix_driveid(struct hd_driveid *driveid) +void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN - u16 *id = (u16 *)driveid; + struct hd_driveid *driveid = (struct hd_driveid *)id; int i; for (i = 0; i < 256; i++) { @@ -593,18 +593,18 @@ EXPORT_SYMBOL(ide_wait_stat); /** * ide_in_drive_list - look for drive in black/white list * @id: drive identifier - * @drive_table: list to inspect + * @table: list to inspect * * Look for a drive in the blacklist and the whitelist tables * Returns 1 if the drive is found in the table. */ -int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) +int ide_in_drive_list(u16 *id, const struct drive_list_entry *table) { - for ( ; drive_table->id_model; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - (!drive_table->id_firmware || - strstr(id->fw_rev, drive_table->id_firmware))) + for ( ; table->id_model; table++) + if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) && + (!table->id_firmware || + strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware))) return 1; return 0; } @@ -635,7 +635,7 @@ static const struct drive_list_entry ivb_list[] = { u8 eighty_ninty_three (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; int ivb = ide_in_drive_list(id, ivb_list); if (hwif->cbl == ATA_CBL_PATA40_SHORT) @@ -657,7 +657,8 @@ u8 eighty_ninty_three (ide_drive_t *drive) * - force bit13 (80c cable present) check also for !ivb devices * (unless the slave device is pre-ATA3) */ - if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000))) + if ((id[ATA_ID_HW_CONFIG] & 0x4000) || + (ivb && (id[ATA_ID_HW_CONFIG] & 0x2000))) return 1; no_80w: @@ -678,7 +679,7 @@ int ide_driveid_update(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; - struct hd_driveid *id; + u16 *id; unsigned long timeout, flags; u8 stat; @@ -722,16 +723,16 @@ int ide_driveid_update(ide_drive_t *drive) local_irq_enable(); local_irq_restore(flags); ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - - if (drive->using_dma && ide_id_dma_bug(drive)) - ide_dma_off(drive); - } + + drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; + drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; + drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; + /* anything more ? */ + + kfree(id); + + if (drive->using_dma && ide_id_dma_bug(drive)) + ide_dma_off(drive); return 1; } @@ -740,6 +741,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; + u16 *id = drive->id, i; int error = 0; u8 stat; ide_task_t task; @@ -750,7 +752,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ - if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) + if ((speed & 0xf8) == XFER_PIO_0 && !(drive->driveid->capability & 8)) goto skip; /* @@ -802,9 +804,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) return error; } - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; + id[ATA_ID_UDMA_MODES] &= ~0xFF00; + id[ATA_ID_MWDMA_MODES] &= ~0x0F00; + id[ATA_ID_SWDMA_MODES] &= ~0x0F00; skip: #ifdef CONFIG_BLK_DEV_IDEDMA @@ -814,23 +816,17 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ide_dma_off_quietly(drive); #endif - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; + if (speed >= XFER_UDMA_0) { + i = 1 << (speed - XFER_UDMA_0); + id[ATA_ID_UDMA_MODES] |= (i << 8 | i); + } else if (speed >= XFER_MW_DMA_0) { + i = 1 << (speed - XFER_MW_DMA_0); + id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); + } else if (speed >= XFER_SW_DMA_0) { + i = 1 << (speed - XFER_SW_DMA_0); + id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); } + if (!drive->init_speed) drive->init_speed = speed; drive->current_speed = speed; @@ -1035,7 +1031,7 @@ out: static void ide_disk_pre_reset(ide_drive_t *drive) { - int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; + int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; drive->special.all = 0; drive->special.b.set_geometry = legacy; diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 97fefabea8b..3066d7e75c7 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -90,29 +90,31 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) { - int pio_mode; - struct hd_driveid* id = drive->id; - int overridden = 0; + u16 *id = drive->id; + int pio_mode = -1, overridden = 0; if (mode_wanted != 255) return min_t(u8, mode_wanted, max_mode); - if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 && - (pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { + if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) + pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); + + if (pio_mode != -1) { printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); } else { - pio_mode = id->tPIO; + pio_mode = drive->driveid->tPIO; if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ pio_mode = 2; overridden = 1; } - if (id->field_valid & 2) { /* drive implements ATA2? */ - if (id->capability & 8) { /* IORDY supported? */ - if (id->eide_pio_modes & 7) { + + if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ + if (drive->driveid->capability & 8) { /* IORDY sup? */ + if (id[ATA_ID_PIO_MODES] & 7) { overridden = 0; - if (id->eide_pio_modes & 4) + if (id[ATA_ID_PIO_MODES] & 4) pio_mode = 5; - else if (id->eide_pio_modes & 2) + else if (id[ATA_ID_PIO_MODES] & 2) pio_mode = 4; else pio_mode = 3; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a776a6d73c5..b4f8ca10663 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -50,44 +50,44 @@ static void generic_id(ide_drive_t *drive) { - drive->id->cyls = drive->cyl; - drive->id->heads = drive->head; - drive->id->sectors = drive->sect; - drive->id->cur_cyls = drive->cyl; - drive->id->cur_heads = drive->head; - drive->id->cur_sectors = drive->sect; + u16 *id = drive->id; + + id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl; + id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head; + id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect; } static void ide_disk_init_chs(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; + drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS]; + drive->head = drive->bios_head = id[ATA_ID_HEADS]; + drive->sect = drive->bios_sect = id[ATA_ID_SECTORS]; } /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; + if ((id[ATA_ID_FIELD_VALID] & 1) && id[ATA_ID_CUR_CYLS] && + id[ATA_ID_CUR_HEADS] && id[ATA_ID_CUR_HEADS] <= 16 && + id[ATA_ID_CUR_SECTORS]) { + drive->cyl = id[ATA_ID_CUR_CYLS]; + drive->head = id[ATA_ID_CUR_HEADS]; + drive->sect = id[ATA_ID_CUR_SECTORS]; } /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; + if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) { + drive->cyl = id[ATA_ID_CYLS]; + drive->head = id[ATA_ID_HEADS]; + drive->sect = id[ATA_ID_SECTORS]; } } static void ide_disk_init_mult_count(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + struct hd_driveid *id = drive->driveid; if (id->max_multsect) { #ifdef CONFIG_IDEDISK_MULTI_MODE @@ -118,10 +118,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) static inline void do_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; int bswap = 1; - struct hd_driveid *id; - id = drive->id; /* read 512 bytes of id info */ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); @@ -138,23 +138,24 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) * WIN_PIDENTIFY *usually* returns little-endian info. */ if (cmd == WIN_PIDENTIFY) { - if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ - || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ - || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ + if ((m[0] == 'N' && m[1] == 'E') || /* NEC */ + (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */ + (m[0] == 'P' && m[1] == 'i')) /* Pioneer */ /* Vertos drives may still be weird */ - bswap ^= 1; + bswap ^= 1; } - ide_fixstring(id->model, sizeof(id->model), bswap); - ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); + + ide_fixstring(m, ATA_ID_PROD_LEN, bswap); + ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap); + ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap); /* we depend on this a lot! */ - id->model[sizeof(id->model)-1] = '\0'; + m[ATA_ID_PROD_LEN - 1] = '\0'; - if (strstr(id->model, "E X A B Y T E N E S T")) + if (strstr(m, "E X A B Y T E N E S T")) goto err_misc; - printk(KERN_INFO "%s: %s, ", drive->name, id->model); + printk(KERN_INFO "%s: %s, ", drive->name, m); drive->present = 1; drive->dead = 0; @@ -163,15 +164,15 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) * Check for an ATAPI device */ if (cmd == WIN_PIDENTIFY) { - u8 type = (id->config >> 8) & 0x1f; + u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; printk(KERN_CONT "ATAPI "); switch (type) { case ide_floppy: - if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && - !strstr(id->model, "poyp") && - !strstr(id->model, "ZIP")) + if (!strstr(m, "CD-ROM")) { + if (!strstr(m, "oppy") && + !strstr(m, "poyp") && + !strstr(m, "ZIP")) printk(KERN_CONT "cdrom or floppy?, assuming "); if (drive->media != ide_cdrom) { printk(KERN_CONT "FLOPPY"); @@ -185,8 +186,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) drive->removable = 1; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && - strstr(id->model, "ZIP")) { + if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { printk(KERN_CONT "FLOPPY"); type = ide_floppy; break; @@ -220,14 +220,13 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) * 0x848a = CompactFlash device * These are *not* removable in Linux definition of the term */ - - if ((id->config != 0x848a) && (id->config & (1<<7))) + if (id[ATA_ID_CONFIG] != 0x848a && (id[ATA_ID_CONFIG] & (1 << 7))) drive->removable = 1; drive->media = ide_disk; printk(KERN_CONT "%s DISK drive\n", - (id->config == 0x848a) ? "CFA" : "ATA"); + (id[ATA_ID_CONFIG] == 0x848a) ? "CFA" : "ATA"); return; @@ -525,7 +524,8 @@ static void enable_nest (ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u8 stat; - printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model); + printk(KERN_INFO "%s: enabling %s -- ", + hwif->name, (char *)&drive->id[ATA_ID_PROD]); SELECT_DRIVE(drive); msleep(50); @@ -566,6 +566,8 @@ static void enable_nest (ide_drive_t *drive) static inline u8 probe_for_drive (ide_drive_t *drive) { + char *m; + /* * In order to keep things simple we have an id * block for all drives at all times. If the device @@ -582,8 +584,10 @@ static inline u8 probe_for_drive (ide_drive_t *drive) printk(KERN_ERR "ide: out of memory for id data.\n"); return 0; } - strcpy(drive->id->model, "UNKNOWN"); - + + m = (char *)&drive->id[ATA_ID_PROD]; + strcpy(m, "UNKNOWN"); + /* skip probing? */ if (!drive->noprobe) { @@ -595,7 +599,8 @@ static inline u8 probe_for_drive (ide_drive_t *drive) if (!drive->present) /* drive not found */ return 0; - if (strstr(drive->id->model, "E X A B Y T E N E S T")) + + if (strstr(m, "E X A B Y T E N E S T")) enable_nest(drive); /* identification failed? */ @@ -739,36 +744,38 @@ out: /** * ide_undecoded_slave - look for bad CF adapters - * @drive1: drive + * @dev1: slave device * * Analyse the drives on the interface and attempt to decide if we * have the same drive viewed twice. This occurs with crap CF adapters * and PCMCIA sometimes. */ -void ide_undecoded_slave(ide_drive_t *drive1) +void ide_undecoded_slave(ide_drive_t *dev1) { - ide_drive_t *drive0 = &drive1->hwif->drives[0]; + ide_drive_t *dev0 = &dev1->hwif->drives[0]; - if ((drive1->dn & 1) == 0 || drive0->present == 0) + if ((dev1->dn & 1) == 0 || dev0->present == 0) return; /* If the models don't match they are not the same product */ - if (strcmp(drive0->id->model, drive1->id->model)) + if (strcmp((char *)&dev0->id[ATA_ID_PROD], + (char *)&dev1->id[ATA_ID_PROD])) return; /* Serial numbers do not match */ - if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20)) + if (strncmp((char *)&dev0->id[ATA_ID_SERNO], + (char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN)) return; /* No serial number, thankfully very rare for CF */ - if (drive0->id->serial_no[0] == 0) + if (*(char *)&dev0->id[ATA_ID_SERNO] == 0) return; /* Appears to be an IDE flash adapter with decode bugs */ printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n"); - drive1->present = 0; + dev1->present = 0; } EXPORT_SYMBOL_GPL(ide_undecoded_slave); @@ -852,7 +859,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) drive->no_io_32bit = 1; else - drive->no_io_32bit = drive->id->dword_io ? 1 : 0; + drive->no_io_32bit = drive->id[ATA_ID_DWORD_IO] ? 1 : 0; } } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index f66c9c3f6fc..0bdbb9bf90b 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -561,11 +561,10 @@ static int proc_ide_read_dmodel (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; - struct hd_driveid *id = drive->id; + char *m = (char *)&drive->id[ATA_ID_PROD]; int len; - len = sprintf(page, "%.40s\n", - (id && id->model[0]) ? (char *)id->model : "(none)"); + len = sprintf(page, "%.40s\n", m[0] ? m : "(none)"); PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index a373cc4142b..2c4c6674db6 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2311,7 +2311,7 @@ static int idetape_identify_device(ide_drive_t *drive) if (drive->id_read == 0) return 1; - *((unsigned short *) &gcw) = drive->id->config; + *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG]; protocol = (gcw[1] & 0xC0) >> 6; device_type = gcw[1] & 0x1F; @@ -2463,7 +2463,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) drive->dsc_overlap = 0; } /* Seagate Travan drives do not support DSC overlap. */ - if (strstr(drive->id->model, "Seagate STT3401")) + if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401")) drive->dsc_overlap = 0; tape->minor = minor; tape->name[0] = 'h'; @@ -2471,7 +2471,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->name[2] = '0' + minor; tape->chrdev_dir = IDETAPE_DIR_NONE; tape->pc = tape->pc_stack; - *((unsigned short *) &gcw) = drive->id->config; + + *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG]; /* Command packet DRQ type */ if (((gcw[0] & 0x60) >> 5) == 1) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 7fb6f1c8627..f889373d7f9 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -729,7 +729,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) u8 args[4], xfer_rate = 0; ide_task_t tfargs; struct ide_taskfile *tf = &tfargs.tf; - struct hd_driveid *id = drive->id; + u16 *id = drive->id; if (NULL == (void *) arg) { struct request *rq; @@ -772,7 +772,9 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) if (tf->command == WIN_SETFEATURES && tf->feature == SETFEATURES_XFER && tf->nsect >= XFER_SW_DMA_0 && - (id->dma_ultra || id->dma_mword || id->dma_1word)) { + (id[ATA_ID_UDMA_MODES] || + id[ATA_ID_MWDMA_MODES] || + id[ATA_ID_SWDMA_MODES])) { xfer_rate = args[1]; if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c index 8c2f8327f48..d64f345f2fc 100644 --- a/drivers/ide/ide-timings.c +++ b/drivers/ide/ide-timings.c @@ -78,15 +78,15 @@ EXPORT_SYMBOL_GPL(ide_timing_find_mode); u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); u16 cycle = 0; - if (id->field_valid & 2) { - if (id->capability & 8) - cycle = id->eide_pio_iordy; + if (id[ATA_ID_FIELD_VALID] & 2) { + if (drive->driveid->capability & 8) + cycle = id[ATA_ID_EIDE_PIO_IORDY]; else - cycle = id->eide_pio; + cycle = id[ATA_ID_EIDE_PIO]; /* conservative "downgrade" for all pre-ATA2 drives */ if (pio < 3 && cycle < t->cycle) @@ -138,7 +138,7 @@ EXPORT_SYMBOL_GPL(ide_timing_merge); int ide_timing_compute(ide_drive_t *drive, u8 speed, struct ide_timing *t, int T, int UT) { - struct hd_driveid *id = drive->id; + u16 *id = drive->id; struct ide_timing *s, p; /* @@ -157,16 +157,15 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed, * If the drive is an EIDE drive, it can tell us it needs extended * PIO/MWDMA cycle timing. */ - if (id && id->field_valid & 2) { /* EIDE drive */ - + if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */ memset(&p, 0, sizeof(p)); if (speed <= XFER_PIO_2) - p.cycle = p.cyc8b = id->eide_pio; + p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; else if (speed <= XFER_PIO_5) - p.cycle = p.cyc8b = id->eide_pio_iordy; + p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY]; else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) - p.cycle = id->eide_dma_min; + p.cycle = id[ATA_ID_EIDE_DMA_MIN]; ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B); } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 772451600e4..8d3fab33a3c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -328,7 +328,7 @@ int set_using_dma(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1) return -EINVAL; - if (!drive->id || !(drive->id->capability & 1)) + if ((drive->driveid->capability & 1) == 0) goto out; if (hwif->dma_ops == NULL) @@ -710,21 +710,21 @@ static ssize_t model_show(struct device *dev, struct device_attribute *attr, char *buf) { ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->id->model); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); } static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->id->fw_rev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); } static ssize_t serial_show(struct device *dev, struct device_attribute *attr, char *buf) { ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->id->serial_no); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); } static struct device_attribute ide_dev_attrs[] = { diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 2338f344ea2..ef4e84053a8 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -151,12 +151,14 @@ static int qd_find_disk_type (ide_drive_t *drive, int *active_time, int *recovery_time) { struct qd65xx_timing_s *p; - char model[40]; + char *m = (char *)&drive->id[ATA_ID_PROD]; + char model[ATA_ID_PROD_LEN]; - if (!*drive->id->model) return 0; + if (*m == 0) + return 0; - strncpy(model,drive->id->model,40); - ide_fixstring(model,40,1); /* byte-swap */ + strncpy(model, m, ATA_ID_PROD_LEN); + ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */ for (p = qd65xx_timing ; p->offset != -1 ; p++) { if (!strncmp(p->model, model+p->offset, 4)) { @@ -185,20 +187,20 @@ static void qd_set_timing (ide_drive_t *drive, u8 timing) static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio) { + u16 *id = drive->id; int active_time = 175; int recovery_time = 415; /* worst case values from the dos driver */ /* * FIXME: use "pio" value */ - if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time) - && drive->id->tPIO && (drive->id->field_valid & 0x02) - && drive->id->eide_pio >= 240) { - + if (!qd_find_disk_type(drive, &active_time, &recovery_time) && + drive->driveid->tPIO && (id[ATA_ID_FIELD_VALID] & 2) && + id[ATA_ID_EIDE_PIO] >= 240) { printk(KERN_INFO "%s: PIO mode%d\n", drive->name, - drive->id->tPIO); + drive->driveid->tPIO); active_time = 110; - recovery_time = drive->id->eide_pio - 120; + recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120; } qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time)); diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index d647526af55..fcc701b3c0a 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -134,8 +134,8 @@ static u8 ali_udma_filter(ide_drive_t *drive) if (m5229_revision > 0x20 && m5229_revision < 0xC2) { if (drive->media != ide_disk) return 0; - if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") && - wdc_udma == 0) + if (wdc_udma == 0 && chip_is_1543c_e && + strstr((char *)&drive->id[ATA_ID_PROD], "WDC ")) return 0; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index f235db8c678..774ff58603a 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -82,16 +82,18 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; - struct hd_driveid *mateid = mate->id; + u16 *mateid = mate->id; u8 mask = hwif->ultra_mask; if (mate->present == 0) goto out; - if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { - if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + if ((mate->driveid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { + if ((mateid[ATA_ID_FIELD_VALID] & 4) && + (mateid[ATA_ID_UDMA_MODES] & 7)) goto out; - if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + if ((mateid[ATA_ID_FIELD_VALID] & 2) && + (mateid[ATA_ID_MWDMA_MODES] & 7)) mask = 0; } out: diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index c37ab174381..b7f77fd3cb6 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -605,10 +605,10 @@ static const struct hpt_info hpt371n __devinitdata = { static int check_in_drive_list(ide_drive_t *drive, const char **list) { - struct hd_driveid *id = drive->id; + char *m = (char *)&drive->id[ATA_ID_PROD]; while (*list) - if (!strcmp(*list++,id->model)) + if (!strcmp(*list++, m)) return 1; return 0; } @@ -731,11 +731,11 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) static void hpt3xx_quirkproc(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + char *m = (char *)&drive->id[ATA_ID_PROD]; const char **list = quirk_drives; while (*list) - if (strstr(id->model, *list++)) { + if (strstr(m, *list++)) { drive->quirk_list = 1; return; } diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 4a1508a707c..31d4e6aef1b 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -446,8 +446,7 @@ static u8 it821x_cable_detect(ide_hwif_t *hwif) static void it821x_quirkproc(ide_drive_t *drive) { struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif); - struct hd_driveid *id = drive->id; - u16 *idbits = (u16 *)drive->id; + u16 *id = drive->id; if (!itdev->smart) { /* @@ -466,36 +465,36 @@ static void it821x_quirkproc(ide_drive_t *drive) */ /* Check for RAID v native */ - if(strstr(id->model, "Integrated Technology Express")) { + if (strstr((char *)&id[ATA_ID_PROD], + "Integrated Technology Express")) { /* In raid mode the ident block is slightly buggy We need to set the bits so that the IDE layer knows LBA28. LBA48 and DMA ar valid */ - id->capability |= 3; /* LBA28, DMA */ - id->command_set_2 |= 0x0400; /* LBA48 valid */ - id->cfs_enable_2 |= 0x0400; /* LBA48 on */ + drive->driveid->capability |= 3; /* LBA28, DMA */ + id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */ + id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */ /* Reporting logic */ printk(KERN_INFO "%s: IT8212 %sRAID %d volume", - drive->name, - idbits[147] ? "Bootable ":"", - idbits[129]); - if(idbits[129] != 1) - printk("(%dK stripe)", idbits[146]); - printk(".\n"); + drive->name, id[147] ? "Bootable " : "", + id[ATA_ID_CSFO]); + if (id[ATA_ID_CSFO] != 1) + printk(KERN_CONT "(%dK stripe)", id[146]); + printk(KERN_CONT ".\n"); } else { /* Non RAID volume. Fixups to stop the core code doing unsupported things */ - id->field_valid &= 3; - id->queue_depth = 0; - id->command_set_1 = 0; - id->command_set_2 &= 0xC400; - id->cfsse &= 0xC000; - id->cfs_enable_1 = 0; - id->cfs_enable_2 &= 0xC400; - id->csf_default &= 0xC000; - id->word127 = 0; - id->dlf = 0; - id->csfo = 0; - id->cfa_power = 0; + id[ATA_ID_FIELD_VALID] &= 3; + id[ATA_ID_QUEUE_DEPTH] = 0; + id[ATA_ID_COMMAND_SET_1] = 0; + id[ATA_ID_COMMAND_SET_2] &= 0xC400; + id[ATA_ID_CFSSE] &= 0xC000; + id[ATA_ID_CFS_ENABLE_1] = 0; + id[ATA_ID_CFS_ENABLE_2] &= 0xC400; + id[ATA_ID_CSF_DEFAULT] &= 0xC000; + id[127] = 0; + id[ATA_ID_DLF] = 0; + id[ATA_ID_CSFO] = 0; + id[ATA_ID_CFA_POWER] = 0; printk(KERN_INFO "%s: Performing identify fixups.\n", drive->name); } @@ -505,8 +504,8 @@ static void it821x_quirkproc(ide_drive_t *drive) * IDE core that DMA is supported (it821x hardware * takes care of DMA mode programming). */ - if (id->capability & 1) { - id->dma_mword |= 0x0101; + if (drive->driveid->capability & 1) { + id[ATA_ID_MWDMA_MODES] |= 0x0101; drive->current_speed = XFER_MW_DMA_0; } } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index d477da6b585..7ecfcd06f47 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -203,10 +203,10 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) static void pdcnew_quirkproc(ide_drive_t *drive) { - const char **list, *model = drive->id->model; + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) { + if (strstr(m, *list) != NULL) { drive->quirk_list = 2; return; } diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index de9a2740046..23e861b177c 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -86,7 +86,7 @@ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A */ AP &= ~0x3f; - if (drive->id->capability & 4) + if (drive->driveid->capability & 4) AP |= 0x20; /* set IORDY_EN bit */ if (drive->media == ide_disk) AP |= 0x10; /* set Prefetch_EN bit */ @@ -154,10 +154,10 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) static void pdc202xx_quirkproc(ide_drive_t *drive) { - const char **list, *model = drive->id->model; + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) { + if (strstr(m, *list) != NULL) { drive->quirk_list = 2; return; } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 8efaed16fea..5c8367df14e 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -105,16 +105,18 @@ static u8 sc1200_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; - struct hd_driveid *mateid = mate->id; + u16 *mateid = mate->id; u8 mask = hwif->ultra_mask; if (mate->present == 0) goto out; - if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { - if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + if ((mate->driveid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { + if ((mateid[ATA_ID_FIELD_VALID] & 4) && + (mateid[ATA_ID_UDMA_MODES] & 7)) goto out; - if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + if ((mateid[ATA_ID_FIELD_VALID] & 2) && + (mateid[ATA_ID_MWDMA_MODES] & 7)) mask = 0; } out: diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index c3bdc6e51a4..ded6a13fd40 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -57,8 +57,10 @@ static struct pci_dev *isa_dev; static int check_in_drive_lists (ide_drive_t *drive, const char **list) { + char *m = (char *)&drive->id[ATA_ID_PROD]; + while (*list) - if (!strcmp(*list++, drive->id->model)) + if (!strcmp(*list++, m)) return 1; return 0; } diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index db2b88a369a..7b5bd8729f6 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -223,7 +223,9 @@ static u8 sil_pata_udma_filter(ide_drive_t *drive) static u8 sil_sata_udma_filter(ide_drive_t *drive) { - return strstr(drive->id->model, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6; + char *m = (char *)&drive->id[ATA_ID_PROD]; + + return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6; } /** @@ -616,8 +618,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) static int is_dev_seagate_sata(ide_drive_t *drive) { - const char *s = &drive->id->model[0]; - unsigned len = strnlen(s, sizeof(drive->id->model)); + const char *s = (const char *)&drive->id[ATA_ID_PROD]; + unsigned len = strnlen(s, ATA_ID_PROD_LEN); if ((len > 4) && (!memcmp(s, "ST", 2))) if ((!memcmp(s + len - 2, "AS", 2)) || diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index fa2be26272d..c3432da78d5 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -669,9 +669,9 @@ static void set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, u8 speed) { + u16 *id = drive->id; int cycleTime, accessTime = 0, recTime = 0; unsigned accessTicks, recTicks; - struct hd_driveid *id = drive->id; struct mdma_timings_t* tm = NULL; int i; @@ -686,8 +686,8 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, } /* Check if drive provides explicit DMA cycle time */ - if ((id->field_valid & 2) && id->eide_dma_time) - cycleTime = max_t(int, id->eide_dma_time, cycleTime); + if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME]) + cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime); /* OHare limits according to some old Apple sources */ if ((intf_type == controller_ohare) && (cycleTime < 150)) diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 81c16cba541..b1b506f31be 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -452,7 +452,7 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; } */ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) { - if (drive->id && (drive->id->config & 0x0060) == 0x20) + if ((drive->id[ATA_ID_CONFIG] & 0x0060) == 0x20) set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags); clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); #if IDESCSI_DEBUG_LOG @@ -811,6 +811,7 @@ static int ide_scsi_probe(ide_drive_t *drive) struct gendisk *g; static int warned; int err = -ENOMEM; + u16 last_lun; if (!warned && drive->media == ide_cdrom) { printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n"); @@ -836,12 +837,12 @@ static int ide_scsi_probe(ide_drive_t *drive) host->max_id = 1; - if (drive->id->last_lun) - debug_log("%s: id->last_lun=%u\n", drive->name, - drive->id->last_lun); + last_lun = drive->id[ATA_ID_LAST_LUN]; + if (last_lun) + debug_log("%s: last_lun=%u\n", drive->name, last_lun); - if ((drive->id->last_lun & 0x7) != 7) - host->max_lun = (drive->id->last_lun & 0x7) + 1; + if ((last_lun & 7) != 7) + host->max_lun = (last_lun & 7) + 1; else host->max_lun = 1; diff --git a/include/linux/ide.h b/include/linux/ide.h index 6514db8fd2e..0c85aff3edf 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -380,7 +380,11 @@ struct ide_drive_s { struct request *rq; /* current request */ struct ide_drive_s *next; /* circular list of hwgroup drives */ void *driver_data; /* extra driver data */ - struct hd_driveid *id; /* drive model identification info */ + union { + /* identification info */ + struct hd_driveid *driveid; + u16 *id; + }; #ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct ide_settings_s *settings;/* /proc/ide/ drive settings */ @@ -920,7 +924,7 @@ ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8); ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); -extern void ide_fix_driveid(struct hd_driveid *); +void ide_fix_driveid(u16 *); extern void ide_fixstring(u8 *, const int, const int); @@ -1240,7 +1244,7 @@ struct drive_list_entry { const char *id_firmware; }; -int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *); +int ide_in_drive_list(u16 *, const struct drive_list_entry *); #ifdef CONFIG_BLK_DEV_IDEDMA int __ide_dma_bad_drive(ide_drive_t *); @@ -1347,12 +1351,13 @@ const char *ide_xfer_verbose(u8 mode); extern void ide_toggle_bounce(ide_drive_t *drive, int on); extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); -static inline int ide_dev_has_iordy(struct hd_driveid *id) +static inline int ide_dev_has_iordy(u16 *id) { - return ((id->field_valid & 2) && (id->capability & 8)) ? 1 : 0; + return ((id[ATA_ID_FIELD_VALID] & 2) && + (((struct hd_driveid *)id)->capability & 8)) ? 1 : 0; } -static inline int ide_dev_is_sata(struct hd_driveid *id) +static inline int ide_dev_is_sata(u16 *id) { /* * See if word 93 is 0 AND drive is at least ATA-5 compatible @@ -1360,7 +1365,7 @@ static inline int ide_dev_is_sata(struct hd_driveid *id) * this trick allows us to filter out the reserved values of * 0x0000 and 0xffff along with the earlier ATA revisions... */ - if (id->hw_config == 0 && (short)id->major_rev_num >= 0x0020) + if (id[ATA_ID_HW_CONFIG] == 0 && (short)id[ATA_ID_MAJOR_VER] >= 0x0020) return 1; return 0; } @@ -1437,11 +1442,11 @@ extern struct bus_type ide_bus_type; extern struct class *ide_port_class; /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ -#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) +#define ide_id_has_flush_cache(id) ((id)[ATA_ID_CFS_ENABLE_2] & 0x3000) /* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ #define ide_id_has_flush_cache_ext(id) \ - (((id)->cfs_enable_2 & 0x2400) == 0x2400) + (((id)[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400) static inline void ide_dump_identify(u8 *id) { -- GitLab From 48fb2688aa67baba373531cc4ed2d9e695983c3f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:19 +0200 Subject: [PATCH 3777/5416] ide: remove drive->driveid * Factor out HDIO_[OBSOLETE,GET]_IDENTITY ioctls handling to ide_get_identity_ioctl(). * Use temporary buffer in ide_get_identity_ioctl() instead of accessing drive->id directly. * Add ide_id_to_hd_driveid() inline to convert raw id into struct hd_driveid format (needed on big-endian). * Use ide_id_to_hd_driveid() in ide_get_identity_ioctl(), cleanup ide_fix_driveid() and switch ide to use use raw id. * Remove no longer needed drive->driveid. This leaves us with 3 users of struct hd_driveid in tree: - arch/um/drivers/ubd_kern.c - drivers/block/xsysace.c - drivers/usb/storage/isd200.c While at it: * Use ata_id_u{32,64}() and ata_id_has_{dma,lba,iordy}() macros. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 23 +++++++------ drivers/ide/ide-dma.c | 6 ++-- drivers/ide/ide-iops.c | 20 ++---------- drivers/ide/ide-lib.c | 4 +-- drivers/ide/ide-probe.c | 22 ++++++------- drivers/ide/ide-timings.c | 2 +- drivers/ide/ide.c | 59 +++++++++++++++++++++++++++++----- drivers/ide/legacy/qd65xx.c | 4 +-- drivers/ide/pci/cs5530.c | 2 +- drivers/ide/pci/it821x.c | 4 +-- drivers/ide/pci/pdc202xx_old.c | 2 +- drivers/ide/pci/sc1200.c | 2 +- include/linux/ide.h | 9 ++---- 13 files changed, 90 insertions(+), 69 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f1669bca3ca..8f1ec037309 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -101,13 +101,14 @@ static void ide_disk_put(struct ide_disk_obj *idkp) */ static int lba_capacity_is_ok(u16 *id) { - struct hd_driveid *driveid = (struct hd_driveid *)id; unsigned long lba_sects, chs_sects, head, tail; /* No non-LBA info .. so valid! */ if (id[ATA_ID_CYLS] == 0) return 1; + lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY); + /* * The ATA spec tells large drives to return * C/H/S = 16383/16/63 independent of their size. @@ -118,10 +119,9 @@ static int lba_capacity_is_ok(u16 *id) (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) && id[ATA_ID_SECTORS] == 63 && (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) && - (driveid->lba_capacity >= 16383 * 63 * id[ATA_ID_HEADS])) + (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS])) return 1; - lba_sects = driveid->lba_capacity; chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS]; /* perform a rough sanity check on lba_sects: within 10% is OK */ @@ -133,7 +133,7 @@ static int lba_capacity_is_ok(u16 *id) tail = (lba_sects & 0xffff); lba_sects = (head | (tail << 16)); if ((lba_sects - chs_sects) < chs_sects/10) { - driveid->lba_capacity = lba_sects; + *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects); return 1; /* lba_capacity is (now) good */ } @@ -403,7 +403,7 @@ static inline int idedisk_supports_lba48(const u16 *id) { return (id[ATA_ID_COMMAND_SET_2] & 0x0400) && (id[ATA_ID_CFS_ENABLE_2] & 0x0400) && - ((struct hd_driveid *)id)->lba_capacity_2; + ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); } /* @@ -456,7 +456,6 @@ static void idedisk_check_hpa(ide_drive_t *drive) static void init_idedisk_capacity(ide_drive_t *drive) { - struct hd_driveid *driveid = drive->driveid; u16 *id = drive->id; /* * If this drive supports the Host Protected Area feature set, @@ -467,13 +466,13 @@ static void init_idedisk_capacity(ide_drive_t *drive) if (idedisk_supports_lba48(id)) { /* drive speaks 48-bit LBA */ drive->select.b.lba = 1; - drive->capacity64 = driveid->lba_capacity_2; + drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); if (hpa) idedisk_check_hpa(drive); - } else if ((driveid->capability & 2) && lba_capacity_is_ok(id)) { + } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) { /* drive speaks 28-bit LBA */ drive->select.b.lba = 1; - drive->capacity64 = driveid->lba_capacity; + drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY); if (hpa) idedisk_check_hpa(drive); } else { @@ -622,7 +621,7 @@ static int set_multcount(ide_drive_t *drive, int arg) struct request *rq; int error; - if (arg < 0 || arg > drive->driveid->max_multsect) + if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) return -EINVAL; if (drive->special.b.set_multmode) @@ -775,8 +774,8 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, - drive->driveid->max_multsect, 1, 1, &drive->mult_count, - set_multcount); + drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1, + &drive->mult_count, set_multcount); ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index abab26de768..15e608f52eb 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -649,8 +649,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) case XFER_SW_DMA_0: if (id[ATA_ID_FIELD_VALID] & 2) { mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask; - } else if (drive->driveid->tDMA) { - u8 mode = drive->driveid->tDMA; + } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) { + u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8; /* * if the mode is valid convert it to the mask @@ -727,7 +727,7 @@ static int ide_tune_dma(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; u8 speed; - if (drive->nodma || (drive->driveid->capability & 1) == 0) + if (drive->nodma || ata_id_has_dma(drive->id) == 0) return 0; /* consult the list of known "bad" drives */ diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 01b1943b315..95495e4219f 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -404,26 +404,10 @@ void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN # ifdef __BIG_ENDIAN - struct hd_driveid *driveid = (struct hd_driveid *)id; int i; - for (i = 0; i < 256; i++) { - /* these words are accessed as two 8-bit values */ - if (i == 47 || i == 49 || i == 51 || i == 52 || i == 59) - continue; - if (i == 60 || i == 61) /* ->lba_capacity is 32-bit */ - continue; - if (i == 98 || i == 99) /* ->spg is 32-bit */ - continue; - if (i > 99 && i < 104) /* ->lba_capacity_2 is 64-bit */ - continue; - + for (i = 0; i < 256; i++) id[i] = __le16_to_cpu(id[i]); - } - - driveid->lba_capacity = __le32_to_cpu(driveid->lba_capacity); - driveid->spg = __le32_to_cpu(driveid->spg); - driveid->lba_capacity_2 = __le64_to_cpu(driveid->lba_capacity_2); # else # error "Please fix " # endif @@ -752,7 +736,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ - if ((speed & 0xf8) == XFER_PIO_0 && !(drive->driveid->capability & 8)) + if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0) goto skip; /* diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 3066d7e75c7..738c007a04d 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -102,14 +102,14 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) if (pio_mode != -1) { printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); } else { - pio_mode = drive->driveid->tPIO; + pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ pio_mode = 2; overridden = 1; } if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ - if (drive->driveid->capability & 8) { /* IORDY sup? */ + if (ata_id_has_iordy(id)) { if (id[ATA_ID_PIO_MODES] & 7) { overridden = 0; if (id[ATA_ID_PIO_MODES] & 4) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index b4f8ca10663..1bb4b2c0e2f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -87,20 +87,20 @@ static void ide_disk_init_chs(ide_drive_t *drive) static void ide_disk_init_mult_count(ide_drive_t *drive) { - struct hd_driveid *id = drive->driveid; + u16 *id = drive->id; + u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff; - if (id->max_multsect) { + if (max_multsect) { #ifdef CONFIG_IDEDISK_MULTI_MODE - if ((id->max_multsect / 2) > 1) { - id->multsect = id->max_multsect; - id->multsect_valid = 1; - } else { - id->multsect = 0; - id->multsect_valid = 0; - } - drive->mult_req = id->multsect; + if ((max_multsect / 2) > 1) + id[ATA_ID_MULTSECT] = max_multsect | 0x100; + else + id[ATA_ID_MULTSECT] &= ~0x1ff; + + drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; #endif - if ((id->multsect_valid & 1) && id->multsect) + if ((id[ATA_ID_MULTSECT] & 0x100) && + (id[ATA_ID_MULTSECT] & 0xff)) drive->special.b.set_multmode = 1; } } diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c index d64f345f2fc..96e3d467a74 100644 --- a/drivers/ide/ide-timings.c +++ b/drivers/ide/ide-timings.c @@ -83,7 +83,7 @@ u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio) u16 cycle = 0; if (id[ATA_ID_FIELD_VALID] & 2) { - if (drive->driveid->capability & 8) + if (ata_id_has_iordy(drive->id)) cycle = id[ATA_ID_EIDE_PIO_IORDY]; else cycle = id[ATA_ID_EIDE_PIO]; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8d3fab33a3c..21b3a767e7d 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -328,7 +328,7 @@ int set_using_dma(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1) return -EINVAL; - if ((drive->driveid->capability & 1) == 0) + if (ata_id_has_dma(drive->id) == 0) goto out; if (hwif->dma_ops == NULL) @@ -502,12 +502,60 @@ static int generic_drive_reset(ide_drive_t *drive) return ret; } +static inline void ide_id_to_hd_driveid(u16 *id) +{ +#ifdef __BIG_ENDIAN + /* accessed in struct hd_driveid as 8-bit values */ + id[ATA_ID_MAX_MULTSECT] = __cpu_to_le16(id[ATA_ID_MAX_MULTSECT]); + id[ATA_ID_CAPABILITY] = __cpu_to_le16(id[ATA_ID_CAPABILITY]); + id[ATA_ID_OLD_PIO_MODES] = __cpu_to_le16(id[ATA_ID_OLD_PIO_MODES]); + id[ATA_ID_OLD_DMA_MODES] = __cpu_to_le16(id[ATA_ID_OLD_DMA_MODES]); + id[ATA_ID_MULTSECT] = __cpu_to_le16(id[ATA_ID_MULTSECT]); + + /* as 32-bit values */ + *(u32 *)&id[ATA_ID_LBA_CAPACITY] = ata_id_u32(id, ATA_ID_LBA_CAPACITY); + *(u32 *)&id[ATA_ID_SPG] = ata_id_u32(id, ATA_ID_SPG); + + /* as 64-bit value */ + *(u64 *)&id[ATA_ID_LBA_CAPACITY_2] = + ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); +#endif +} + +static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, + unsigned long arg) +{ + u16 *id = NULL; + int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; + int rc = 0; + + if (drive->id_read == 0) { + rc = -ENOMSG; + goto out; + } + + id = kmalloc(size, GFP_KERNEL); + if (id == NULL) { + rc = -ENOMEM; + goto out; + } + + memcpy(id, drive->id, size); + ide_id_to_hd_driveid(id); + + if (copy_to_user((void __user *)arg, id, size)) + rc = -EFAULT; + + kfree(id); +out: + return rc; +} + int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { unsigned long flags; ide_driver_t *drv; - void __user *p = (void __user *)arg; int err = 0, (*setfunc)(ide_drive_t *, int); u8 *val; @@ -528,12 +576,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) return -EINVAL; - if (drive->id_read == 0) - return -ENOMSG; - if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) - return -EFAULT; - return 0; - + return ide_get_identity_ioctl(drive, cmd, arg); case HDIO_GET_NICE: return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index ef4e84053a8..6d7f548655e 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -195,10 +195,10 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio) * FIXME: use "pio" value */ if (!qd_find_disk_type(drive, &active_time, &recovery_time) && - drive->driveid->tPIO && (id[ATA_ID_FIELD_VALID] & 2) && + (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_PIO] >= 240) { printk(KERN_INFO "%s: PIO mode%d\n", drive->name, - drive->driveid->tPIO); + id[ATA_ID_OLD_PIO_MODES] & 0xff); active_time = 110; recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 774ff58603a..ef91e9d7c54 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -88,7 +88,7 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) if (mate->present == 0) goto out; - if ((mate->driveid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { + if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { if ((mateid[ATA_ID_FIELD_VALID] & 4) && (mateid[ATA_ID_UDMA_MODES] & 7)) goto out; diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 31d4e6aef1b..ed24065f74e 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -470,7 +470,7 @@ static void it821x_quirkproc(ide_drive_t *drive) /* In raid mode the ident block is slightly buggy We need to set the bits so that the IDE layer knows LBA28. LBA48 and DMA ar valid */ - drive->driveid->capability |= 3; /* LBA28, DMA */ + id[ATA_ID_CAPABILITY] |= (3 << 8); /* LBA28, DMA */ id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */ id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */ /* Reporting logic */ @@ -504,7 +504,7 @@ static void it821x_quirkproc(ide_drive_t *drive) * IDE core that DMA is supported (it821x hardware * takes care of DMA mode programming). */ - if (drive->driveid->capability & 1) { + if (ata_id_has_dma(id)) { id[ATA_ID_MWDMA_MODES] |= 0x0101; drive->current_speed = XFER_MW_DMA_0; } diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 23e861b177c..5d4436f3efd 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -86,7 +86,7 @@ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A */ AP &= ~0x3f; - if (drive->driveid->capability & 4) + if (ata_id_iordy_disable(drive->id)) AP |= 0x20; /* set IORDY_EN bit */ if (drive->media == ide_disk) AP |= 0x10; /* set Prefetch_EN bit */ diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 5c8367df14e..695cc974204 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -111,7 +111,7 @@ static u8 sc1200_udma_filter(ide_drive_t *drive) if (mate->present == 0) goto out; - if ((mate->driveid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { + if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { if ((mateid[ATA_ID_FIELD_VALID] & 4) && (mateid[ATA_ID_UDMA_MODES] & 7)) goto out; diff --git a/include/linux/ide.h b/include/linux/ide.h index 0c85aff3edf..e887927e00e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -380,11 +380,7 @@ struct ide_drive_s { struct request *rq; /* current request */ struct ide_drive_s *next; /* circular list of hwgroup drives */ void *driver_data; /* extra driver data */ - union { - /* identification info */ - struct hd_driveid *driveid; - u16 *id; - }; + u16 *id; /* identification info */ #ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct ide_settings_s *settings;/* /proc/ide/ drive settings */ @@ -1353,8 +1349,7 @@ extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); static inline int ide_dev_has_iordy(u16 *id) { - return ((id[ATA_ID_FIELD_VALID] & 2) && - (((struct hd_driveid *)id)->capability & 8)) ? 1 : 0; + return ((id[ATA_ID_FIELD_VALID] & 2) && ata_id_has_iordy(id)) ? 1 : 0; } static inline int ide_dev_is_sata(u16 *id) -- GitLab From dd8f46f64ae66659df3358fad73ed7699aa729dd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:19 +0200 Subject: [PATCH 3778/5416] ide: use ata_id_current_chs_valid() Replace open-coded checks by ata_id_current_chs_valid(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1bb4b2c0e2f..2f105f4bbde 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -69,9 +69,7 @@ static void ide_disk_init_chs(ide_drive_t *drive) } /* Handle logical geometry translation by the drive */ - if ((id[ATA_ID_FIELD_VALID] & 1) && id[ATA_ID_CUR_CYLS] && - id[ATA_ID_CUR_HEADS] && id[ATA_ID_CUR_HEADS] <= 16 && - id[ATA_ID_CUR_SECTORS]) { + if (ata_id_current_chs_valid(id)) { drive->cyl = id[ATA_ID_CUR_CYLS]; drive->head = id[ATA_ID_CUR_HEADS]; drive->sect = id[ATA_ID_CUR_SECTORS]; -- GitLab From 8a089c6679a9f1c0a00b7e08554e90b507ec527a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:20 +0200 Subject: [PATCH 3779/5416] ide-disk: use ata_id_wcache_enabled() Replace open-coded check by ata_id_wcache_enabled() (which also checks validity of word 85). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 8f1ec037309..696658d504d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -889,7 +889,7 @@ static void idedisk_setup(ide_drive_t *drive) drive->bios_cyl, drive->bios_head, drive->bios_sect); /* write cache enabled? */ - if ((id[ATA_ID_CSFO] & 1) || (id[ATA_ID_CFS_ENABLE_1] & (1 << 5))) + if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) drive->wcache = 1; write_cache(drive, 1); -- GitLab From f41891c134ccdd07583ebd8d4af7fed883375672 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:20 +0200 Subject: [PATCH 3780/5416] ide-disk: use ata_id_hpa_enabled() idedisk_supports_hpa() -> ata_id_hpa_enabled(). The latter one also checks validity of words 82 & 85. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 696658d504d..40253c51ace 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -385,17 +385,6 @@ static unsigned long long sectors_to_MB(unsigned long long n) return n; } -/* - * Bits 10 of command_set_1 and cfs_enable_1 must be equal, - * so on non-buggy drives we need test only one. - * However, we should also check whether these fields are valid. - */ -static inline int idedisk_supports_hpa(const u16 *id) -{ - return (id[ATA_ID_COMMAND_SET_1] & 0x0400) && - (id[ATA_ID_CFS_ENABLE_1] & 0x0400); -} - /* * The same here. */ @@ -461,7 +450,7 @@ static void init_idedisk_capacity(ide_drive_t *drive) * If this drive supports the Host Protected Area feature set, * then we may need to change our opinion about the drive's capacity. */ - int hpa = idedisk_supports_hpa(id); + int hpa = ata_id_hpa_enabled(id); if (idedisk_supports_lba48(id)) { /* drive speaks 48-bit LBA */ @@ -939,7 +928,7 @@ static int ide_disk_probe(ide_drive_t *drive); */ static void ide_disk_resume(ide_drive_t *drive) { - if (idedisk_supports_hpa(drive->id)) + if (ata_id_hpa_enabled(drive->id)) init_idedisk_capacity(drive); } -- GitLab From a4f19040a3a6cd431efe0a10b9d2e8d5e3904865 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:20 +0200 Subject: [PATCH 3781/5416] libata: WIN_* -> ATA_CMD_* Acked-by: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 59fe051957e..5d312dc9be9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -503,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) scsi_cmd[0] = ATA_16; scsi_cmd[4] = args[2]; - if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */ + if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too */ scsi_cmd[6] = args[3]; scsi_cmd[8] = args[1]; scsi_cmd[10] = 0x4f; -- GitLab From aaaade3f059fa1b57283d4a7c8351a42ec747bf0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:21 +0200 Subject: [PATCH 3782/5416] ide: WIN_* -> ATA_CMD_* * Use ATA_CMD_* defines instead of WIN_* ones. While at it: * EXABYTE_ENABLE_NEXT -> ATA_EXABYTE_ENABLE_NEST * SETFEATURES_{EN,DIS}_WCACHE -> SETFEATURES_WC_{ON,OFF} * SETFEATURES_{EN,DIS}_AAM -> SETFEATURES_AAM_{ON,OFF} * SMART_* -> ATA_SMART_* * Remove stale comment from ide-proc.c. Partially based on earlier work by Chris Wedgwood. Acked-by: Chris Wedgwood Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 2 +- drivers/ide/ide-cd.c | 2 +- drivers/ide/ide-disk.c | 68 +++++++++++++++++++------------------- drivers/ide/ide-io.c | 27 +++++++-------- drivers/ide/ide-iops.c | 10 +++--- drivers/ide/ide-probe.c | 34 +++++++++---------- drivers/ide/ide-proc.c | 10 +----- drivers/ide/ide-taskfile.c | 27 +++++++++------ drivers/scsi/ide-scsi.c | 2 +- 9 files changed, 89 insertions(+), 93 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index adf04f99cde..2433fce6c11 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -303,7 +303,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, /* Issue the packet command */ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { - ide_execute_command(drive, WIN_PACKETCMD, handler, + ide_execute_command(drive, ATA_CMD_PACKET, handler, timeout, NULL); return ide_started; } else { diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 46f9720f1ec..77e0f9ab769 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -541,7 +541,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, drive->waiting_for_dma = 0; /* packet command */ - ide_execute_command(drive, WIN_PACKETCMD, handler, + ide_execute_command(drive, ATA_CMD_PACKET, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; } else { diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 40253c51ace..83da9a98dab 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -141,18 +141,18 @@ static int lba_capacity_is_ok(u16 *id) } static const u8 ide_rw_cmds[] = { - WIN_MULTREAD, - WIN_MULTWRITE, - WIN_MULTREAD_EXT, - WIN_MULTWRITE_EXT, - WIN_READ, - WIN_WRITE, - WIN_READ_EXT, - WIN_WRITE_EXT, - WIN_READDMA, - WIN_WRITEDMA, - WIN_READDMA_EXT, - WIN_WRITEDMA_EXT, + ATA_CMD_READ_MULTI, + ATA_CMD_WRITE_MULTI, + ATA_CMD_READ_MULTI_EXT, + ATA_CMD_WRITE_MULTI_EXT, + ATA_CMD_PIO_READ, + ATA_CMD_PIO_WRITE, + ATA_CMD_PIO_READ_EXT, + ATA_CMD_PIO_WRITE_EXT, + ATA_CMD_READ, + ATA_CMD_WRITE, + ATA_CMD_READ_EXT, + ATA_CMD_WRITE_EXT, }; static const u8 ide_data_phases[] = { @@ -323,9 +323,9 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); if (lba48) - tf->command = WIN_READ_NATIVE_MAX_EXT; + tf->command = ATA_CMD_READ_NATIVE_MAX_EXT; else - tf->command = WIN_READ_NATIVE_MAX; + tf->command = ATA_CMD_READ_NATIVE_MAX; tf->device = ATA_LBA; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; if (lba48) @@ -360,10 +360,10 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) tf->hob_lbal = (addr_req >>= 8) & 0xff; tf->hob_lbam = (addr_req >>= 8) & 0xff; tf->hob_lbah = (addr_req >>= 8) & 0xff; - tf->command = WIN_SET_MAX_EXT; + tf->command = ATA_CMD_SET_MAX_EXT; } else { tf->device = (addr_req >>= 8) & 0x0f; - tf->command = WIN_SET_MAX; + tf->command = ATA_CMD_SET_MAX; } tf->device |= ATA_LBA; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; @@ -482,10 +482,10 @@ static int smart_enable(ide_drive_t *drive) struct ide_taskfile *tf = &args.tf; memset(&args, 0, sizeof(ide_task_t)); - tf->feature = SMART_ENABLE; - tf->lbam = SMART_LCYL_PASS; - tf->lbah = SMART_HCYL_PASS; - tf->command = WIN_SMART; + tf->feature = ATA_SMART_ENABLE; + tf->lbam = ATA_SMART_LBAM_PASS; + tf->lbah = ATA_SMART_LBAH_PASS; + tf->command = ATA_CMD_SMART; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; return ide_no_data_taskfile(drive, &args); } @@ -498,9 +498,9 @@ static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) memset(&args, 0, sizeof(ide_task_t)); tf->feature = sub_cmd; tf->nsect = 0x01; - tf->lbam = SMART_LCYL_PASS; - tf->lbah = SMART_HCYL_PASS; - tf->command = WIN_SMART; + tf->lbam = ATA_SMART_LBAM_PASS; + tf->lbah = ATA_SMART_LBAH_PASS; + tf->command = ATA_CMD_SMART; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; args.data_phase = TASKFILE_IN; (void) smart_enable(drive); @@ -558,14 +558,14 @@ static int proc_idedisk_read_sv (char *page, char **start, off_t off, int count, int *eof, void *data) { return proc_idedisk_read_smart(page, start, off, count, eof, data, - SMART_READ_VALUES); + ATA_SMART_READ_VALUES); } static int proc_idedisk_read_st (char *page, char **start, off_t off, int count, int *eof, void *data) { return proc_idedisk_read_smart(page, start, off, count, eof, data, - SMART_READ_THRESHOLDS); + ATA_SMART_READ_THRESHOLDS); } static ide_proc_entry_t idedisk_proc[] = { @@ -589,9 +589,9 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) memset(task, 0, sizeof(*task)); if (ide_id_has_flush_cache_ext(drive->id) && (drive->capacity64 >= (1UL << 28))) - task->tf.command = WIN_FLUSH_CACHE_EXT; + task->tf.command = ATA_CMD_FLUSH_EXT; else - task->tf.command = WIN_FLUSH_CACHE; + task->tf.command = ATA_CMD_FLUSH; task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE | IDE_TFLAG_DYN; task->data_phase = TASKFILE_NO_DATA; @@ -686,8 +686,8 @@ static int write_cache(ide_drive_t *drive, int arg) if (ide_id_has_flush_cache(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); args.tf.feature = arg ? - SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.tf.command = WIN_SETFEATURES; + SETFEATURES_WC_ON : SETFEATURES_WC_OFF; + args.tf.command = ATA_CMD_SET_FEATURES; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; err = ide_no_data_taskfile(drive, &args); if (err == 0) @@ -705,9 +705,9 @@ static int do_idedisk_flushcache(ide_drive_t *drive) memset(&args, 0, sizeof(ide_task_t)); if (ide_id_has_flush_cache_ext(drive->id)) - args.tf.command = WIN_FLUSH_CACHE_EXT; + args.tf.command = ATA_CMD_FLUSH_EXT; else - args.tf.command = WIN_FLUSH_CACHE; + args.tf.command = ATA_CMD_FLUSH; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; return ide_no_data_taskfile(drive, &args); } @@ -720,9 +720,9 @@ static int set_acoustic(ide_drive_t *drive, int arg) return -EINVAL; memset(&args, 0, sizeof(ide_task_t)); - args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; + args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF; args.tf.nsect = arg; - args.tf.command = WIN_SETFEATURES; + args.tf.command = ATA_CMD_SET_FEATURES; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; ide_no_data_taskfile(drive, &args); drive->acoustic = arg; @@ -985,7 +985,7 @@ static int idedisk_set_doorlock(ide_drive_t *drive, int on) ide_task_t task; memset(&task, 0, sizeof(task)); - task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK; + task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; return ide_no_data_taskfile(drive, &task); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1678043701d..ce9ecd13883 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -188,13 +188,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * return ide_stopped; } if (ide_id_has_flush_cache_ext(drive->id)) - args->tf.command = WIN_FLUSH_CACHE_EXT; + args->tf.command = ATA_CMD_FLUSH_EXT; else - args->tf.command = WIN_FLUSH_CACHE; + args->tf.command = ATA_CMD_FLUSH; goto out_do_tf; case idedisk_pm_standby: /* Suspend step 2 (standby) */ - args->tf.command = WIN_STANDBYNOW1; + args->tf.command = ATA_CMD_STANDBYNOW1; goto out_do_tf; case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ @@ -209,7 +209,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * return ide_stopped; case idedisk_pm_idle: /* Resume step 2 (idle) */ - args->tf.command = WIN_IDLEIMMEDIATE; + args->tf.command = ATA_CMD_IDLEIMMEDIATE; goto out_do_tf; case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ @@ -380,8 +380,8 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { if (drive->select.b.lba && - /* some newer drives don't support WIN_SPECIFY */ - hwif->tp_ops->read_status(hwif) == WIN_SPECIFY) + /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ + hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) return ide_stopped; } else if ((err & BAD_CRC) == BAD_CRC) { /* UDMA crc error, just retry the operation */ @@ -436,7 +436,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) /* force an abort */ - hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE); + hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); if (rq->errors >= ERROR_MAX) { ide_kill_rq(drive, rq); @@ -509,19 +509,19 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) tf->lbam = drive->cyl; tf->lbah = drive->cyl >> 8; tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA; - tf->command = WIN_SPECIFY; + tf->command = ATA_CMD_INIT_DEV_PARAMS; } static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { tf->nsect = drive->sect; - tf->command = WIN_RESTORE; + tf->command = ATA_CMD_RESTORE; } static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { tf->nsect = drive->mult_req; - tf->command = WIN_SETMULT; + tf->command = ATA_CMD_SET_MULTI; } static ide_startstop_t ide_disk_special(ide_drive_t *drive) @@ -584,9 +584,10 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) * do_special - issue some special commands * @drive: drive the command is for * - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled - * back. + * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, + * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. + * + * It used to do much more, but has been scaled back. */ static ide_startstop_t do_special (ide_drive_t *drive) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 95495e4219f..21647a2eaff 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -418,7 +418,7 @@ void ide_fix_driveid(u16 *id) * ide_fixstring() cleans up and (optionally) byte-swaps a text string, * removing leading/trailing blanks and compressing internal blanks. * It is primarily used to tidy up the model name/number fields as - * returned by the WIN_[P]IDENTIFY commands. + * returned by the ATA_CMD_ID_ATA[PI] commands. */ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) @@ -675,7 +675,7 @@ int ide_driveid_update(ide_drive_t *drive) SELECT_MASK(drive, 1); tp_ops->set_irq(hwif, 0); msleep(50); - tp_ops->exec_command(hwif, WIN_IDENTIFY); + tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); timeout = jiffies + WAIT_WORSTCASE; do { if (time_after(jiffies, timeout)) { @@ -770,7 +770,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) tp_ops->tf_load(drive, &task); - tp_ops->exec_command(hwif, WIN_SETFEATURES); + tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); if (drive->quirk_list == 2) tp_ops->set_irq(hwif, 1); @@ -890,7 +890,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD); + hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); ndelay(400); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1100,7 +1100,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) pre_reset(drive); SELECT_DRIVE(drive); udelay (20); - tp_ops->exec_command(hwif, WIN_SRST); + tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); ndelay(400); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 2f105f4bbde..4829daacb34 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -132,10 +132,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ide_fix_driveid(id); /* - * WIN_IDENTIFY returns little-endian info, - * WIN_PIDENTIFY *usually* returns little-endian info. + * ATA_CMD_ID_ATA returns little-endian info, + * ATA_CMD_ID_ATAPI *usually* returns little-endian info. */ - if (cmd == WIN_PIDENTIFY) { + if (cmd == ATA_CMD_ID_ATAPI) { if ((m[0] == 'N' && m[1] == 'E') || /* NEC */ (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */ (m[0] == 'P' && m[1] == 'i')) /* Pioneer */ @@ -161,7 +161,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) /* * Check for an ATAPI device */ - if (cmd == WIN_PIDENTIFY) { + if (cmd == ATA_CMD_ID_ATAPI) { u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; printk(KERN_CONT "ATAPI "); @@ -277,7 +277,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* set features register for atapi * identify command to be sure of reply */ - if (cmd == WIN_PIDENTIFY) { + if (cmd == ATA_CMD_ID_ATAPI) { ide_task_t task; memset(&task, 0, sizeof(task)); @@ -290,7 +290,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* ask drive for ID */ tp_ops->exec_command(hwif, cmd); - timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; + timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { if (time_after(jiffies, timeout)) { @@ -440,13 +440,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (drive->present) { /* avoid waiting for inappropriate probes */ - if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) + if (drive->media != ide_disk && cmd == ATA_CMD_ID_ATA) return 4; } #ifdef DEBUG printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", drive->name, drive->present, drive->media, - (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); + (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI"); #endif /* needed for some systems @@ -470,7 +470,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) stat = tp_ops->read_status(hwif); if (OK_STAT(stat, READY_STAT, BUSY_STAT) || - drive->present || cmd == WIN_PIDENTIFY) { + drive->present || cmd == ATA_CMD_ID_ATAPI) { /* send cmd and wait */ if ((rc = try_to_identify(drive, cmd))) { /* failed: try again */ @@ -482,13 +482,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (stat == (BUSY_STAT | READY_STAT)) return 4; - if (rc == 1 && cmd == WIN_PIDENTIFY) { + if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) { printk(KERN_ERR "%s: no response (status = 0x%02x), " "resetting drive\n", drive->name, stat); msleep(50); SELECT_DRIVE(drive); msleep(50); - tp_ops->exec_command(hwif, WIN_SRST); + tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); (void)ide_busy_sleep(hwif); rc = try_to_identify(drive, cmd); } @@ -527,7 +527,7 @@ static void enable_nest (ide_drive_t *drive) SELECT_DRIVE(drive); msleep(50); - tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST); + tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST); if (ide_busy_sleep(hwif)) { printk(KERN_CONT "failed (timeout)\n"); @@ -544,10 +544,9 @@ static void enable_nest (ide_drive_t *drive) printk(KERN_CONT "success\n"); /* if !(success||timed-out) */ - if (do_probe(drive, WIN_IDENTIFY) >= 2) { + if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ - (void) do_probe(drive, WIN_PIDENTIFY); - } + (void)do_probe(drive, ATA_CMD_ID_ATAPI); } /** @@ -590,10 +589,9 @@ static inline u8 probe_for_drive (ide_drive_t *drive) if (!drive->noprobe) { /* if !(success||timed-out) */ - if (do_probe(drive, WIN_IDENTIFY) >= 2) { + if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ - (void) do_probe(drive, WIN_PIDENTIFY); - } + (void)do_probe(drive, ATA_CMD_ID_ATAPI); if (!drive->present) /* drive not found */ return 0; diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 0bdbb9bf90b..22f41fa4e5b 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -12,14 +12,6 @@ * "settings" files. e.g. "cat /proc/ide0/hda/settings" * To write a new value "val" into a specific setting "name", use: * echo "name:val" >/proc/ide/ide0/hda/settings - * - * Also useful, "cat /proc/ide0/hda/[identify, smart_values, - * smart_thresholds, capabilities]" will issue an IDENTIFY / - * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS / - * SENSE CAPABILITIES command to /dev/hda, and then dump out the - * returned data as 256 16-bit words. The "hdparm" utility will - * be updated someday soon to use this mechanism. - * */ #include @@ -349,7 +341,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) return -EINVAL; memset(&task, 0, sizeof(task)); - task.tf.command = WIN_SETFEATURES; + task.tf.command = ATA_CMD_SET_FEATURES; task.tf.feature = SETFEATURES_XFER; task.tf.nsect = (u8)arg; task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index f889373d7f9..9224f679718 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -44,9 +44,9 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) memset(&args, 0, sizeof(ide_task_t)); args.tf.nsect = 0x01; if (drive->media == ide_disk) - args.tf.command = WIN_IDENTIFY; + args.tf.command = ATA_CMD_ID_ATA; else - args.tf.command = WIN_PIDENTIFY; + args.tf.command = ATA_CMD_ID_ATAPI; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; args.data_phase = TASKFILE_IN; return ide_raw_taskfile(drive, &args, buf, 1); @@ -99,12 +99,17 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_NO_DATA: if (handler == NULL) handler = task_no_data_intr; - /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */ if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) { switch (tf->command) { - case WIN_SPECIFY: handler = set_geometry_intr; break; - case WIN_RESTORE: handler = recal_intr; break; - case WIN_SETMULT: handler = set_multmode_intr; break; + case ATA_CMD_INIT_DEV_PARAMS: + handler = set_geometry_intr; + break; + case ATA_CMD_RESTORE: + handler = recal_intr; + break; + case ATA_CMD_SET_MULTI: + handler = set_multmode_intr; + break; } } ide_execute_command(drive, tf->command, handler, @@ -121,7 +126,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) EXPORT_SYMBOL_GPL(do_rw_taskfile); /* - * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. + * set_multmode_intr() is invoked on completion of a ATA_CMD_SET_MULTI cmd. */ static ide_startstop_t set_multmode_intr(ide_drive_t *drive) { @@ -142,7 +147,7 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive) } /* - * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. + * set_geometry_intr() is invoked on completion of a ATA_CMD_INIT_DEV_PARAMS cmd. */ static ide_startstop_t set_geometry_intr(ide_drive_t *drive) { @@ -170,7 +175,7 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive) } /* - * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. + * recal_intr() is invoked on completion of a ATA_CMD_RESTORE (recalibrate) cmd. */ static ide_startstop_t recal_intr(ide_drive_t *drive) { @@ -747,7 +752,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) memset(&tfargs, 0, sizeof(ide_task_t)); tf->feature = args[2]; - if (args[0] == WIN_SMART) { + if (args[0] == ATA_CMD_SMART) { tf->nsect = args[3]; tf->lbal = args[1]; tf->lbam = 0x4f; @@ -769,7 +774,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) return -ENOMEM; } - if (tf->command == WIN_SETFEATURES && + if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_XFER && tf->nsect >= XFER_SW_DMA_0 && (id[ATA_ID_UDMA_MODES] || diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index b1b506f31be..167c3b62521 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -246,7 +246,7 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) /* force an abort */ - hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE); + hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); rq->errors++; -- GitLab From f26b3d75959e9a0e43a2e1e1148c075592746c3d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:21 +0200 Subject: [PATCH 3783/5416] hd: WIN_* -> ATA_CMD_* * Use ATA_CMD_* defines instead of WIN_* ones. * Include directly instead of through . Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/block/hd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 682243bf2e4..482c0c4b964 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #define REALLY_SLOW_IO @@ -370,7 +371,7 @@ repeat: struct hd_i_struct *disk = &hd_info[i]; disk->special_op = disk->recalibrate = 1; hd_out(disk, disk->sect, disk->sect, disk->head-1, - disk->cyl, WIN_SPECIFY, &reset_hd); + disk->cyl, ATA_CMD_INIT_DEV_PARAMS, &reset_hd); if (reset) goto repeat; } else @@ -558,7 +559,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) { if (disk->recalibrate) { disk->recalibrate = 0; - hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr); + hd_out(disk, disk->sect, 0, 0, 0, ATA_CMD_RESTORE, &recal_intr); return reset; } if (disk->head > 16) { @@ -631,13 +632,13 @@ repeat: if (blk_fs_request(req)) { switch (rq_data_dir(req)) { case READ: - hd_out(disk, nsect, sec, head, cyl, WIN_READ, + hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ, &read_intr); if (reset) goto repeat; break; case WRITE: - hd_out(disk, nsect, sec, head, cyl, WIN_WRITE, + hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_WRITE, &write_intr); if (reset) goto repeat; -- GitLab From 3a7d24841ad794ae64c90d7d00d62a83741912aa Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:21 +0200 Subject: [PATCH 3784/5416] ide: use ATA_* defines instead of *_STAT and *_ERR ones * ERR_STAT -> ATA_ERR * INDEX_STAT -> ATA_IDX * ECC_STAT -> ATA_CORR * DRQ_STAT -> ATA_DRQ * SEEK_STAT -> ATA_DSC * WRERR_STAT -> ATA_DF * READY_STAT -> ATA_DRDY * BUSY_STAT -> ATA_BUSY * MARK_ERR -> ATA_AMNF * TRK0_ERR -> ATA_TRK0NF * ABRT_ERR -> ATA_ABORTED * MCR_ERR -> ATA_MCR * ID_ERR -> ATA_IDNF * MC_ERR -> ATA_MC * ECC_ERR -> ATA_UNC * ICRC_ERR -> ATA_ICRC * BBD_ERR -> ATA_BBK Also: * ILI_ERR -> ATAPI_ILI * EOM_ERR -> ATAPI_EOM * LFS_ERR -> ATAPI_LFS * CD -> ATAPI_COD * IO -> ATAPI_IO Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 32 +++++++++++++------------ drivers/ide/ide-cd.c | 16 ++++++------- drivers/ide/ide-dma.c | 2 +- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-io.c | 25 ++++++++++---------- drivers/ide/ide-iops.c | 22 ++++++++--------- drivers/ide/ide-lib.c | 48 +++++++++++++++++++------------------- drivers/ide/ide-probe.c | 16 ++++++------- drivers/ide/ide-tape.c | 6 ++--- drivers/ide/ide-taskfile.c | 26 ++++++++++----------- drivers/ide/ide.c | 8 +++---- drivers/ide/pci/ns87415.c | 6 ++--- drivers/ide/pci/scc_pata.c | 4 ++-- drivers/scsi/ide-scsi.c | 2 +- include/linux/ide.h | 15 ++++++------ 15 files changed, 117 insertions(+), 113 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 2433fce6c11..12674e6519e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -41,7 +41,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { if (hwif->dma_ops->dma_end(drive) || - (drive->media == ide_tape && !scsi && (stat & ERR_STAT))) { + (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) { if (drive->media == ide_floppy && !scsi) printk(KERN_ERR "%s: DMA %s error\n", drive->name, rq_data_dir(pc->rq) @@ -56,7 +56,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, } /* No more interrupts */ - if ((stat & DRQ_STAT) == 0) { + if ((stat & ATA_DRQ) == 0) { debug_log("Packet command completed, %d bytes transferred\n", pc->xferred); @@ -65,10 +65,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, local_irq_enable_in_hardirq(); if (drive->media == ide_tape && !scsi && - (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE) - stat &= ~ERR_STAT; + (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) + stat &= ~ATA_ERR; - if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { + if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) { /* Error detected */ debug_log("%s: I/O error\n", drive->name); @@ -95,7 +95,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, cmd_finished: pc->error = 0; if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && - (stat & SEEK_STAT) == 0) { + (stat & ATA_DSC) == 0) { dsc_handle(drive); return ide_stopped; } @@ -117,17 +117,18 @@ cmd_finished: /* Get the number of bytes to transfer on this interrupt. */ ide_read_bcount_and_ireason(drive, &bcount, &ireason); - if (ireason & CD) { + if (ireason & ATAPI_COD) { printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); return ide_do_reset(drive); } - if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { + if (((ireason & ATAPI_IO) == ATAPI_IO) == + !!(pc->flags & PC_FLAG_WRITING)) { /* Hopefully, we will never get here */ printk(KERN_ERR "%s: We wanted to %s, but the device wants us " "to %s!\n", drive->name, - (ireason & IO) ? "Write" : "Read", - (ireason & IO) ? "Read" : "Write"); + (ireason & ATAPI_IO) ? "Write" : "Read", + (ireason & ATAPI_IO) ? "Read" : "Write"); return ide_do_reset(drive); } @@ -205,7 +206,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) { int retries = 100; - while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { + while (retries-- && ((ireason & ATAPI_COD) == 0 || + (ireason & ATAPI_IO))) { printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " "a packet command, retrying\n", drive->name); udelay(100); @@ -214,8 +216,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " "a packet command, ignoring\n", drive->name); - ireason |= CD; - ireason &= ~IO; + ireason |= ATAPI_COD; + ireason &= ~ATAPI_IO; } } @@ -231,7 +233,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_startstop_t startstop; u8 ireason; - if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { + if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { printk(KERN_ERR "%s: Strange, packet command initiated yet " "DRQ isn't asserted\n", drive->name); return startstop; @@ -241,7 +243,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, if (drive->media == ide_tape && !drive->scsi) ireason = ide_wait_ireason(drive, ireason); - if ((ireason & CD) == 0 || (ireason & IO)) { + if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " "a packet command\n", drive->name); return ide_do_reset(drive); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 77e0f9ab769..239557f8920 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -436,7 +436,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) ide_dump_status_no_sense(drive, "media error (blank)", stat); do_end_request = 1; - } else if ((err & ~ABRT_ERR) != 0) { + } else if ((err & ~ATA_ABORTED) != 0) { /* go to the default handler for other errors */ ide_error(drive, "cdrom_decode_status", stat); return 1; @@ -457,7 +457,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) * If we got a CHECK_CONDITION status, queue * a request sense command. */ - if (stat & ERR_STAT) + if (stat & ATA_ERR) cdrom_queue_request_sense(drive, NULL, NULL); } else { blk_dump_rq_flags(rq, "ide-cd: bad rq"); @@ -468,7 +468,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) return 1; end_request: - if (stat & ERR_STAT) { + if (stat & ATA_ERR) { unsigned long flags; spin_lock_irqsave(&ide_lock, flags); @@ -574,7 +574,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, */ /* check for errors */ - if (cdrom_decode_status(drive, DRQ_STAT, NULL)) + if (cdrom_decode_status(drive, ATA_DRQ, NULL)) return ide_stopped; /* ok, next interrupt will be DMA interrupt */ @@ -582,8 +582,8 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, drive->waiting_for_dma = 1; } else { /* otherwise, we must wait for DRQ to get set */ - if (ide_wait_stat(&startstop, drive, DRQ_STAT, - BUSY_STAT, WAIT_READY)) + if (ide_wait_stat(&startstop, drive, ATA_DRQ, + ATA_BUSY, WAIT_READY)) return startstop; } @@ -938,7 +938,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) thislen = len; /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { + if ((stat & ATA_DRQ) == 0) { if (blk_fs_request(rq)) { /* * If we're not done reading/writing, complain. @@ -1206,7 +1206,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, unsigned long elapsed = jiffies - info->start_seek; int stat = hwif->tp_ops->read_status(hwif); - if ((stat & SEEK_STAT) != SEEK_STAT) { + if ((stat & ATA_DSC) != ATA_DSC) { if (elapsed < IDECD_SEEK_TIMEOUT) { ide_stall_queue(drive, IDECD_SEEK_TIMER); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 15e608f52eb..ef2f1504c0d 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -106,7 +106,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive) dma_stat = hwif->dma_ops->dma_end(drive); stat = hwif->tp_ops->read_status(hwif); - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) { if (!dma_stat) { struct request *rq = HWGROUP(drive)->rq; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 67f93a46f51..59baa9643f8 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -945,7 +945,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) stat = hwif->tp_ops->read_status(hwif); local_irq_restore(flags); - progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000; + progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000; } if (put_user(progress_indication, arg)) return (-EFAULT); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ce9ecd13883..8dd7b46b41b 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -322,7 +322,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) ide_task_t *task = (ide_task_t *)rq->special; if (rq->errors == 0) - rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT); + rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT); if (task) { struct ide_taskfile *tf = &task->tf; @@ -373,12 +373,12 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 { ide_hwif_t *hwif = drive->hwif; - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; - } else if (stat & ERR_STAT) { + } else if (stat & ATA_ERR) { /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { + if (err == ATA_ABORTED) { if (drive->select.b.lba && /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) @@ -386,16 +386,16 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 } else if ((err & BAD_CRC) == BAD_CRC) { /* UDMA crc error, just retry the operation */ drive->crc_count++; - } else if (err & (BBD_ERR | ECC_ERR)) { + } else if (err & (ATA_BBK | ATA_UNC)) { /* retries won't help these */ rq->errors = ERROR_MAX; - } else if (err & TRK0_ERR) { + } else if (err & ATA_TRK0NF) { /* help it find track zero */ rq->errors |= ERROR_RECAL; } } - if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && + if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { int nsect = drive->mult_count ? drive->mult_count : 1; @@ -407,7 +407,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 return ide_stopped; } - if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) rq->errors |= ERROR_RESET; if ((rq->errors & ERROR_RESET) == ERROR_RESET) { @@ -427,14 +427,14 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u { ide_hwif_t *hwif = drive->hwif; - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { /* add decoding error stuff */ } - if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) /* force an abort */ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); @@ -804,7 +804,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) ide_check_pm_state(drive, rq); SELECT_DRIVE(drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { + if (ide_wait_stat(&startstop, drive, drive->ready_stat, + ATA_BUSY | ATA_DRQ, WAIT_READY)) { printk(KERN_ERR "%s: drive not ready for command\n", drive->name); return startstop; } @@ -1324,7 +1325,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) if (hwif->irq == irq) { stat = hwif->tp_ops->read_status(hwif); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { /* Try to not flood the console with msgs */ static unsigned long last_msgtime, count; ++count; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 21647a2eaff..8cfa6125c7a 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -473,7 +473,7 @@ int drive_is_ready (ide_drive_t *drive) /* Note: this may clear a pending IRQ!! */ stat = hwif->tp_ops->read_status(hwif); - if (stat & BUSY_STAT) + if (stat & ATA_BUSY) /* drive busy: definitely not interrupting */ return 0; @@ -505,10 +505,10 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti udelay(1); /* spec allows drive 400ns to assert "BUSY" */ stat = tp_ops->read_status(hwif); - if (stat & BUSY_STAT) { + if (stat & ATA_BUSY) { local_irq_set(flags); timeout += jiffies; - while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) { + while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) { if (time_after(jiffies, timeout)) { /* * One last read after the timeout in case @@ -516,7 +516,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti * progress during the timeout.. */ stat = tp_ops->read_status(hwif); - if (!(stat & BUSY_STAT)) + if ((stat & ATA_BUSY) == 0) break; local_irq_restore(flags); @@ -685,12 +685,12 @@ int ide_driveid_update(ide_drive_t *drive) msleep(50); /* give drive a breather */ stat = tp_ops->read_altstatus(hwif); - } while (stat & BUSY_STAT); + } while (stat & ATA_BUSY); - msleep(50); /* wait for IRQ and DRQ_STAT */ + msleep(50); /* wait for IRQ and ATA_DRQ */ stat = tp_ops->read_status(hwif); - if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { + if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { SELECT_MASK(drive, 0); printk("%s: CHECK for good STATUS\n", drive->name); return 0; @@ -776,7 +776,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) tp_ops->set_irq(hwif, 1); error = __ide_wait_stat(drive, drive->ready_stat, - BUSY_STAT|DRQ_STAT|ERR_STAT, + ATA_BUSY | ATA_DRQ | ATA_ERR, WAIT_CMD, &stat); SELECT_MASK(drive, 0); @@ -923,7 +923,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) udelay (10); stat = hwif->tp_ops->read_status(hwif); - if (OK_STAT(stat, 0, BUSY_STAT)) + if (OK_STAT(stat, 0, ATA_BUSY)) printk("%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwgroup->poll_timeout)) { @@ -969,7 +969,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) tmp = hwif->tp_ops->read_status(hwif); - if (!OK_STAT(tmp, 0, BUSY_STAT)) { + if (!OK_STAT(tmp, 0, ATA_BUSY)) { if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); /* continue polling */ @@ -1183,7 +1183,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) */ mdelay(1); stat = hwif->tp_ops->read_status(hwif); - if ((stat & BUSY_STAT) == 0) + if ((stat & ATA_BUSY) == 0) return 0; /* * Assume a value of 0xff means nothing is connected to diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 738c007a04d..c5c37bfd8b0 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -340,16 +340,16 @@ static void ide_dump_sector(ide_drive_t *drive) static void ide_dump_ata_error(ide_drive_t *drive, u8 err) { printk("{ "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) - printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); + if (err & ATA_ABORTED) printk("DriveStatusError "); + if (err & ATA_ICRC) + printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector "); + if (err & ATA_UNC) printk("UncorrectableError "); + if (err & ATA_IDNF) printk("SectorIdNotFound "); + if (err & ATA_TRK0NF) printk("TrackZeroNotFound "); + if (err & ATA_AMNF) printk("AddrMarkNotFound "); printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || - (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK || + (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) { ide_dump_sector(drive); if (HWGROUP(drive) && HWGROUP(drive)->rq) printk(", sector=%llu", @@ -361,12 +361,12 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err) static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) { printk("{ "); - if (err & ILI_ERR) printk("IllegalLengthIndication "); - if (err & EOM_ERR) printk("EndOfMedia "); - if (err & ABRT_ERR) printk("AbortedCommand "); - if (err & MCR_ERR) printk("MediaChangeRequested "); - if (err & LFS_ERR) printk("LastFailedSense=0x%02x ", - (err & LFS_ERR) >> 4); + if (err & ATAPI_ILI) printk("IllegalLengthIndication "); + if (err & ATAPI_EOM) printk("EndOfMedia "); + if (err & ATA_ABORTED) printk("AbortedCommand "); + if (err & ATA_MCR) printk("MediaChangeRequested "); + if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ", + (err & ATAPI_LFS) >> 4); printk("}\n"); } @@ -388,19 +388,19 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); - if (stat & BUSY_STAT) + if (stat & ATA_BUSY) printk("Busy "); else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); + if (stat & ATA_DRDY) printk("DriveReady "); + if (stat & ATA_DF) printk("DeviceFault "); + if (stat & ATA_DSC) printk("SeekComplete "); + if (stat & ATA_DRQ) printk("DataRequest "); + if (stat & ATA_CORR) printk("CorrectedError "); + if (stat & ATA_IDX) printk("Index "); + if (stat & ATA_ERR) printk("Error "); } printk("}\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) { err = ide_read_error(drive); printk("%s: %s: error=0x%02x ", drive->name, msg, err); if (drive->media == ide_disk) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 4829daacb34..7578ad48080 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -264,7 +264,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) if (io_ports->ctl_addr) { a = tp_ops->read_altstatus(hwif); s = tp_ops->read_status(hwif); - if ((a ^ s) & ~INDEX_STAT) + if ((a ^ s) & ~ATA_IDX) /* ancient Seagate drives, broken interfaces */ printk(KERN_INFO "%s: probing with STATUS(0x%02x) " "instead of ALTSTATUS(0x%02x)\n", @@ -301,13 +301,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) msleep(50); s = use_altstatus ? tp_ops->read_altstatus(hwif) : tp_ops->read_status(hwif); - } while (s & BUSY_STAT); + } while (s & ATA_BUSY); - /* wait for IRQ and DRQ_STAT */ + /* wait for IRQ and ATA_DRQ */ msleep(50); s = tp_ops->read_status(hwif); - if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) { + if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { unsigned long flags; /* local CPU only; some systems need this */ @@ -391,7 +391,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif) do { msleep(50); stat = hwif->tp_ops->read_status(hwif); - if ((stat & BUSY_STAT) == 0) + if ((stat & ATA_BUSY) == 0) return 0; } while (time_before(jiffies, timeout)); @@ -460,7 +460,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (drive->select.b.unit != 0) { /* exit with drive0 selected */ SELECT_DRIVE(&hwif->drives[0]); - /* allow BUSY_STAT to assert & clear */ + /* allow ATA_BUSY to assert & clear */ msleep(50); } /* no i/f present: mmm.. this should be a 4 -ml */ @@ -469,7 +469,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) stat = tp_ops->read_status(hwif); - if (OK_STAT(stat, READY_STAT, BUSY_STAT) || + if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || drive->present || cmd == ATA_CMD_ID_ATAPI) { /* send cmd and wait */ if ((rc = try_to_identify(drive, cmd))) { @@ -479,7 +479,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) stat = tp_ops->read_status(hwif); - if (stat == (BUSY_STAT | READY_STAT)) + if (stat == (ATA_BUSY | ATA_DRDY)) return 4; if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) { diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 2c4c6674db6..2745e5d2684 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -920,8 +920,8 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) stat = hwif->tp_ops->read_status(hwif); - if (stat & SEEK_STAT) { - if (stat & ERR_STAT) { + if (stat & ATA_DSC) { + if (stat & ATA_ERR) { /* Error detected */ if (pc->c[0] != TEST_UNIT_READY) printk(KERN_ERR "ide-tape: %s: I/O error, ", @@ -1022,7 +1022,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) && - (stat & SEEK_STAT) == 0) { + (stat & ATA_DSC) == 0) { if (postponed_rq == NULL) { tape->dsc_polling_start = jiffies; tape->dsc_poll_freq = tape->best_dsc_rw_freq; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9224f679718..b1fb815dbf6 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -136,7 +136,7 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive) local_irq_enable_in_hardirq(); stat = hwif->tp_ops->read_status(hwif); - if (OK_STAT(stat, READY_STAT, BAD_STAT)) + if (OK_STAT(stat, ATA_DRDY, BAD_STAT)) drive->mult_count = drive->mult_req; else { drive->mult_req = drive->mult_count = 0; @@ -159,15 +159,15 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive) while (1) { stat = hwif->tp_ops->read_status(hwif); - if ((stat & BUSY_STAT) == 0 || retries-- == 0) + if ((stat & ATA_BUSY) == 0 || retries-- == 0) break; udelay(10); }; - if (OK_STAT(stat, READY_STAT, BAD_STAT)) + if (OK_STAT(stat, ATA_DRDY, BAD_STAT)) return ide_stopped; - if (stat & (ERR_STAT|DRQ_STAT)) + if (stat & (ATA_ERR | ATA_DRQ)) return ide_error(drive, "set_geometry_intr", stat); ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL); @@ -185,7 +185,7 @@ static ide_startstop_t recal_intr(ide_drive_t *drive) local_irq_enable_in_hardirq(); stat = hwif->tp_ops->read_status(hwif); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) return ide_error(drive, "recal_intr", stat); return ide_stopped; } @@ -202,7 +202,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) local_irq_enable_in_hardirq(); stat = hwif->tp_ops->read_status(hwif); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ @@ -225,13 +225,13 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) for (retries = 0; retries < 1000; retries++) { stat = hwif->tp_ops->read_status(hwif); - if (stat & BUSY_STAT) + if (stat & ATA_BUSY) udelay(10); else break; } - if (stat & BUSY_STAT) + if (stat & ATA_BUSY) printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); return stat; @@ -390,7 +390,7 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat) { /* Command all done? */ - if (OK_STAT(stat, READY_STAT, BUSY_STAT)) { + if (OK_STAT(stat, ATA_DRDY, ATA_BUSY)) { task_end_request(drive, rq, stat); return ide_stopped; } @@ -410,11 +410,11 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) u8 stat = hwif->tp_ops->read_status(hwif); /* Error? */ - if (stat & ERR_STAT) + if (stat & ATA_ERR) return task_error(drive, rq, __func__, stat); /* Didn't want any data? Odd. */ - if (!(stat & DRQ_STAT)) + if ((stat & ATA_DRQ) == 0) return task_in_unexpected(drive, rq, stat); ide_pio_datablock(drive, rq, 0); @@ -447,7 +447,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive) return task_error(drive, rq, __func__, stat); /* Deal with unexpected ATA data phase. */ - if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft) + if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft) return task_error(drive, rq, __func__, stat); if (!hwif->nleft) { @@ -466,7 +466,7 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - if (ide_wait_stat(&startstop, drive, DRQ_STAT, + if (ide_wait_stat(&startstop, drive, ATA_DRQ, drive->bad_wstat, WAIT_DRQ)) { printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", drive->name, diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 21b3a767e7d..7fddfe16179 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -119,7 +119,7 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) drive->media = ide_disk; drive->select.all = (unit<<4)|0xa0; drive->hwif = hwif; - drive->ready_stat = READY_STAT; + drive->ready_stat = ATA_DRDY; drive->bad_wstat = BAD_W_STAT; drive->special.b.recalibrate = 1; drive->special.b.set_geometry = 1; @@ -884,7 +884,7 @@ MODULE_PARM_DESC(noprobe, "skip probing for a device"); static unsigned int ide_nowerr; module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); -MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device"); +MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); static unsigned int ide_cdroms; @@ -949,7 +949,7 @@ static void ide_dev_apply_params(ide_drive_t *drive) drive->noprobe = 1; } if (ide_nowerr & (1 << i)) { - printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n", + printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n", drive->name); drive->bad_wstat = BAD_R_STAT; } @@ -970,7 +970,7 @@ static void ide_dev_apply_params(ide_drive_t *drive) drive->cyl, drive->head, drive->sect); drive->present = 1; drive->media = ide_disk; - drive->ready_stat = READY_STAT; + drive->ready_stat = ATA_DRDY; } } diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index ffefcd15196..17685f0ade1 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -274,9 +274,9 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) do { udelay(50); stat = hwif->tp_ops->read_status(hwif); - if (stat == 0xff) - break; - } while ((stat & BUSY_STAT) && --timeout); + if (stat == 0xff) + break; + } while ((stat & ATA_BUSY) && --timeout); #endif } diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index 44cccd1e086..192a6a70a63 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -400,7 +400,7 @@ static int scc_dma_end(ide_drive_t *drive) /* errata A308 workaround: Step5 (check data loss) */ /* We don't check non ide_disk because it is limited to UDMA4 */ if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr) - & ERR_STAT) && + & ATA_ERR) && drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) { reg = in_be32((void __iomem *)intsts_port); if (!(reg & INTSTS_ACTEINT)) { @@ -504,7 +504,7 @@ static int scc_dma_test_irq(ide_drive_t *drive) /* SCC errata A252,A308 workaround: Step4 */ if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr) - & ERR_STAT) && + & ATA_ERR) && (int_stat & INTSTS_INTRQ)) return 1; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 167c3b62521..daa5f3115dd 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -244,7 +244,7 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) { ide_hwif_t *hwif = drive->hwif; - if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT)) + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) /* force an abort */ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); diff --git a/include/linux/ide.h b/include/linux/ide.h index e887927e00e..d963c1929c8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -87,12 +87,13 @@ struct ide_io_ports { }; #define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good)) -#define BAD_R_STAT (BUSY_STAT | ERR_STAT) -#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) -#define BAD_STAT (BAD_R_STAT | DRQ_STAT) -#define DRIVE_READY (READY_STAT | SEEK_STAT) -#define BAD_CRC (ABRT_ERR | ICRC_ERR) +#define BAD_R_STAT (ATA_BUSY | ATA_ERR) +#define BAD_W_STAT (BAD_R_STAT | ATA_DF) +#define BAD_STAT (BAD_R_STAT | ATA_DRQ) +#define DRIVE_READY (ATA_DRDY | ATA_DSC) + +#define BAD_CRC (ATA_ABORTED | ATA_ICRC) #define SATA_NR_PORTS (3) /* 16 possible ?? */ @@ -438,8 +439,8 @@ struct ide_drive_s { u8 mult_req; /* requested multiple sector setting */ u8 tune_req; /* requested drive tuning setting */ u8 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ - u8 bad_wstat; /* used for ignoring WRERR_STAT */ - u8 nowerr; /* used for ignoring WRERR_STAT */ + u8 bad_wstat; /* used for ignoring ATA_DF */ + u8 nowerr; /* used for ignoring ATA_DF */ u8 sect0; /* offset of first sector for DM6:DDO */ u8 head; /* "real" number of heads */ u8 sect; /* "real" sectors per track */ -- GitLab From 3c619ffd48d7fdb3b17f0df67c4eb4b0bd80e253 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:22 +0200 Subject: [PATCH 3785/5416] ide: remove no longer needed ide_drive_t fields Remove ->remap_0_to_1 and ->sect0 (they are always zero now). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-io.c | 18 +++--------------- include/linux/ide.h | 2 -- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 83da9a98dab..d4d73025266 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -472,7 +472,7 @@ static void init_idedisk_capacity(ide_drive_t *drive) static sector_t idedisk_capacity(ide_drive_t *drive) { - return drive->capacity64 - drive->sect0; + return drive->capacity64; } #ifdef CONFIG_IDE_PROC_FS diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8dd7b46b41b..96975e24a0c 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -765,9 +765,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) * start_request - start of I/O and command issuing for IDE * * start_request() initiates handling of a new I/O request. It - * accepts commands and I/O (read/write) requests. It also does - * the final remapping for weird stuff like EZDrive. Once - * device mapper can work sector level the EZDrive stuff can go away + * accepts commands and I/O (read/write) requests. * * FIXME: this function needs a rename */ @@ -775,7 +773,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - sector_t block; BUG_ON(!blk_rq_started(rq)); @@ -790,16 +787,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) goto kill_rq; } - block = rq->sector; - if (blk_fs_request(rq) && - (drive->media == ide_disk || drive->media == ide_floppy)) { - block += drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ - if (blk_pm_request(rq)) ide_check_pm_state(drive, rq); @@ -844,7 +831,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) return ide_special_rq(drive, rq); drv = *(ide_driver_t **)rq->rq_disk->private_data; - return drv->do_request(drive, rq, block); + + return drv->do_request(drive, rq, rq->sector); } return do_special(drive); kill_rq: diff --git a/include/linux/ide.h b/include/linux/ide.h index d963c1929c8..ca0b132de1a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -418,7 +418,6 @@ struct ide_drive_s { unsigned atapi_overlap : 1; /* ATAPI overlap (not supported) */ unsigned doorlocking : 1; /* for removable only: door lock/unlock works */ unsigned nodma : 1; /* disallow DMA */ - unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */ unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ @@ -441,7 +440,6 @@ struct ide_drive_s { u8 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ u8 bad_wstat; /* used for ignoring ATA_DF */ u8 nowerr; /* used for ignoring ATA_DF */ - u8 sect0; /* offset of first sector for DM6:DDO */ u8 head; /* "real" number of heads */ u8 sect; /* "real" sectors per track */ u8 bios_head; /* BIOS/fdisk/LILO number of heads */ -- GitLab From 1a7809e3499921a016d203b9ee51a77d3cc1dc98 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 10 Oct 2008 22:39:22 +0200 Subject: [PATCH 3786/5416] ide: re-code ide_fixstring() loop to be less evil On Friday 25 July 2008, Linus Torvalds wrote: > > On Fri, 25 Jul 2008, Ben Dooks wrote: > > > > personally, i would much prefer to see the loop being less evil > > like: > > > > for (p = s; p < end; p += 2) > > be16_to_cpus((u16 *)p); > > Well, in this case, the code actually depends on 'p' being back at the > start of the buffer by the end of it all, so it would need some more > changes than that. > > But yes, I applied David's patch, but I _also_ suspect that we would be > better off without code that does horrid things like casts and assignments > inside the function arguments. > > So it would be nice to re-code that loop to be more readable. But due to > the reliance of 'p' being 's' after the loop, the minimal patch would be > something like the appended. > > Bartlomiej - take this or not, I'm not going to commit it - I haven't > tested it, nor do I even have any machines that would trigger it. So this > is more a "maybe something like this" than anything else. From: Linus Torvalds CC: Ben Dooks Cc: David Miller Cc: harvey.harrison@gmail.com Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 8cfa6125c7a..004803030f6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -423,14 +423,16 @@ void ide_fix_driveid(u16 *id) void ide_fixstring (u8 *s, const int bytecount, const int byteswap) { - u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ + u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */ if (byteswap) { /* convert from big-endian to host byte order */ - for (p = end ; p != s;) - be16_to_cpus((u16 *)(p -= 2)); + for (p = s ; p != end ; p += 2) + be16_to_cpus((u16 *) p); } + /* strip leading blanks */ + p = s; while (s != end && *s == ' ') ++s; /* compress internal blanks and strip trailing blanks */ -- GitLab From efa402d59e99b7940501ead18a11b3d6604ad720 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 10 Oct 2008 22:39:22 +0200 Subject: [PATCH 3787/5416] ide-cd: use the new object_is_in_stack() helper Signed-off-by: FUJITA Tomonori Cc: Borislav Petkov Cc: Thomas Bogendoerfer Cc: Tejun Heo Cc: Jens Axboe Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 239557f8920..accb53b85ba 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1164,13 +1164,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { struct request_queue *q = drive->queue; unsigned int alignment; - unsigned long addr; - unsigned long stack_mask = ~(THREAD_SIZE - 1); + char *buf; if (rq->bio) - addr = (unsigned long)bio_data(rq->bio); + buf = bio_data(rq->bio); else - addr = (unsigned long)rq->data; + buf = rq->data; info->dma = drive->using_dma; @@ -1181,11 +1180,8 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) * separate masks. */ alignment = queue_dma_alignment(q) | q->dma_pad_mask; - if (addr & alignment || rq->data_len & alignment) - info->dma = 0; - - if (!((addr & stack_mask) ^ - ((unsigned long)current->stack & stack_mask))) + if ((unsigned long)buf & alignment || rq->data_len & alignment + || object_is_on_stack(buf)) info->dma = 0; } } -- GitLab From c36a7e98846a7a4a1c09b7f148395089bce512d8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:23 +0200 Subject: [PATCH 3788/5416] ide: fix EXABYTENEST handling in probe_for_drive() Fix EXABYTENEST handling in probe_for_drive() (so drive->present is checked for "nested" device) and cleanup enable_nest(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7578ad48080..e78cfde5bd6 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -542,11 +542,6 @@ static void enable_nest (ide_drive_t *drive) printk(KERN_CONT "failed (status = 0x%02x)\n", stat); else printk(KERN_CONT "success\n"); - - /* if !(success||timed-out) */ - if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) - /* look for ATAPI device */ - (void)do_probe(drive, ATA_CMD_ID_ATAPI); } /** @@ -586,19 +581,22 @@ static inline u8 probe_for_drive (ide_drive_t *drive) strcpy(m, "UNKNOWN"); /* skip probing? */ - if (!drive->noprobe) - { + if (!drive->noprobe) { +retry: /* if !(success||timed-out) */ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ (void)do_probe(drive, ATA_CMD_ID_ATAPI); + if (!drive->present) /* drive not found */ return 0; - if (strstr(m, "E X A B Y T E N E S T")) + if (strstr(m, "E X A B Y T E N E S T")) { enable_nest(drive); - + goto retry; + } + /* identification failed? */ if (!drive->id_read) { if (drive->media == ide_disk) { -- GitLab From b163f46d5ecf48d883ce156e5e5a21a1a9a125c7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:23 +0200 Subject: [PATCH 3789/5416] ide: enhance ide_busy_sleep() * Make ide_busy_sleep() take timeout value as a parameter and also allow use of AltStatus Register if requested with altstatus parameter. Update existing users accordingly. * Convert ide_driveid_update() and actual_try_to_identify() to use ide_busy_sleep(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 15 +++++---------- drivers/ide/ide-probe.c | 30 ++++++++++++------------------ include/linux/ide.h | 2 ++ 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 004803030f6..a940d127aae 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -666,7 +666,7 @@ int ide_driveid_update(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; - unsigned long timeout, flags; + unsigned long flags; u8 stat; /* @@ -678,16 +678,11 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->set_irq(hwif, 0); msleep(50); tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - SELECT_MASK(drive, 0); - return 0; /* drive timed-out */ - } - msleep(50); /* give drive a breather */ - stat = tp_ops->read_altstatus(hwif); - } while (stat & ATA_BUSY); + if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { + SELECT_MASK(drive, 0); + return 0; + } msleep(50); /* wait for IRQ and ATA_DRQ */ stat = tp_ops->read_status(hwif); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e78cfde5bd6..ef773384aaa 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -291,17 +291,9 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) tp_ops->exec_command(hwif, cmd); timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; - timeout += jiffies; - do { - if (time_after(jiffies, timeout)) { - /* drive timed-out */ - return 1; - } - /* give drive a breather */ - msleep(50); - s = use_altstatus ? tp_ops->read_altstatus(hwif) - : tp_ops->read_status(hwif); - } while (s & ATA_BUSY); + + if (ide_busy_sleep(hwif, timeout, use_altstatus)) + return 1; /* wait for IRQ and ATA_DRQ */ msleep(50); @@ -383,19 +375,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) return retval; } -static int ide_busy_sleep(ide_hwif_t *hwif) +int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; u8 stat; + timeout += jiffies; + do { - msleep(50); - stat = hwif->tp_ops->read_status(hwif); + msleep(50); /* give drive a breather */ + stat = altstatus ? hwif->tp_ops->read_altstatus(hwif) + : hwif->tp_ops->read_status(hwif); if ((stat & ATA_BUSY) == 0) return 0; } while (time_before(jiffies, timeout)); - return 1; + return 1; /* drive timed-out */ } static u8 ide_read_device(ide_drive_t *drive) @@ -489,7 +483,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) SELECT_DRIVE(drive); msleep(50); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); - (void)ide_busy_sleep(hwif); + (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); rc = try_to_identify(drive, cmd); } @@ -529,7 +523,7 @@ static void enable_nest (ide_drive_t *drive) msleep(50); tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST); - if (ide_busy_sleep(hwif)) { + if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) { printk(KERN_CONT "failed (timeout)\n"); return; } diff --git a/include/linux/ide.h b/include/linux/ide.h index ca0b132de1a..2ad8548135d 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -923,6 +923,8 @@ void ide_fix_driveid(u16 *); extern void ide_fixstring(u8 *, const int, const int); +int ide_busy_sleep(ide_hwif_t *, unsigned long, int); + int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); extern ide_startstop_t ide_do_reset (ide_drive_t *); -- GitLab From 7c199a5496d0579d388636ee34a954e2e566d2fb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:23 +0200 Subject: [PATCH 3790/5416] ide: remove no longer needed BUG_ON()-s from init_irq() init_irq() is now called only during initial host registration so these BUG_ON()-s are no loner needed (+ the last one was done too late anyway). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ef773384aaa..a27c0398b15 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1031,11 +1031,6 @@ static int init_irq (ide_hwif_t *hwif) ide_hwgroup_t *hwgroup; ide_hwif_t *match = NULL; - - BUG_ON(in_interrupt()); - BUG_ON(irqs_disabled()); - BUG_ON(hwif == NULL); - mutex_lock(&ide_cfg_mtx); hwif->hwgroup = NULL; #if MAX_HWIFS > 1 -- GitLab From a2cdee5a9a93360165d0576bbc7e9ccb3127afee Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:24 +0200 Subject: [PATCH 3791/5416] ide: remove IDE_CHIPSET_* macros They just obfuscate the code. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 3 ++- include/linux/ide.h | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a27c0398b15..8cfce50c71e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1105,7 +1105,8 @@ static int init_irq (ide_hwif_t *hwif) sa = IRQF_SHARED; #endif /* __mc68000__ */ - if (IDE_CHIPSET_IS_PCI(hwif->chipset)) + if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 || + hwif->chipset == ide_ali14xx) sa = IRQF_SHARED; if (io_ports->ctl_addr) diff --git a/include/linux/ide.h b/include/linux/ide.h index 2ad8548135d..a9206c463d7 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -473,10 +473,6 @@ typedef struct ide_drive_s ide_drive_t; #define to_ide_device(dev)container_of(dev, ide_drive_t, gendev) -#define IDE_CHIPSET_PCI_MASK \ - ((1<> (c)) & 1) - struct ide_task_s; struct ide_port_info; -- GitLab From 3cd5f1eae093a7d6ff8a63c746eba9d6f689ba91 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:24 +0200 Subject: [PATCH 3792/5416] ide: remove unused _IDE_C and _IDE_DISK defines Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 3 --- drivers/ide/ide.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index d4d73025266..edfa63750dd 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -30,9 +30,6 @@ #include #include #include - -#define _IDE_DISK - #include #include diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 7fddfe16179..27d5d6a1625 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -44,8 +44,6 @@ * inspiration from lots of linux users, esp. hamish@zot.apana.org.au */ -#define _IDE_C /* Tell ide.h it's really us */ - #include #include #include -- GitLab From 2a924662b646fa25cb491d50aa1202a94aa4ac55 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:24 +0200 Subject: [PATCH 3793/5416] ide: remove needless drive->present checks from device drivers Remove needless drive->present checks from ->probe methods (device model takes care of that). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 4 ++-- drivers/ide/ide-disk.c | 3 +-- drivers/ide/ide-floppy.c | 4 ++-- drivers/ide/ide-tape.c | 4 ++-- drivers/scsi/ide-scsi.c | 1 - 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index accb53b85ba..607af5de16f 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2109,10 +2109,10 @@ static int ide_cd_probe(ide_drive_t *drive) if (!strstr("ide-cdrom", drive->driver_req)) goto failed; - if (!drive->present) - goto failed; + if (drive->media != ide_cdrom && drive->media != ide_optical) goto failed; + /* skip drives that we were told to ignore */ if (ignore != NULL) { if (strstr(ignore, drive->name)) { diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index edfa63750dd..eeb2c3b22e9 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1136,8 +1136,7 @@ static int ide_disk_probe(ide_drive_t *drive) /* strstr("foo", "") is non-NULL */ if (!strstr("ide-disk", drive->driver_req)) goto failed; - if (!drive->present) - goto failed; + if (drive->media != ide_disk) goto failed; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 59baa9643f8..32796038090 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1390,10 +1390,10 @@ static int ide_floppy_probe(ide_drive_t *drive) if (!strstr("ide-floppy", drive->driver_req)) goto failed; - if (!drive->present) - goto failed; + if (drive->media != ide_floppy) goto failed; + if (!idefloppy_identify_device(drive, drive->id)) { printk(KERN_ERR "ide-floppy: %s: not supported by this version" " of ide-floppy\n", drive->name); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 2745e5d2684..874e60fc85d 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2647,10 +2647,10 @@ static int ide_tape_probe(ide_drive_t *drive) if (!strstr("ide-tape", drive->driver_req)) goto failed; - if (!drive->present) - goto failed; + if (drive->media != ide_tape) goto failed; + if (!idetape_identify_device(drive)) { printk(KERN_ERR "ide-tape: %s: not supported by this version of" " the driver\n", drive->name); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index daa5f3115dd..6a661a4454e 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -822,7 +822,6 @@ static int ide_scsi_probe(ide_drive_t *drive) return -ENODEV; if (!strstr("ide-scsi", drive->driver_req) || - !drive->present || drive->media == ide_disk || !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return -ENODEV; -- GitLab From 7e59ea21aab1a91ca31bc64c7d3035ebdbd336d1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:26 +0200 Subject: [PATCH 3794/5416] ide: check drive->present in ide_get_paired_drive() * Change ide_get_paired_drive() to return NULL if peer device is not present and update all users accordingly. While at it: * ide_get_paired_drive() -> ide_get_pair_dev() * Use ide_get_pair_dev() in cs5530.c, sc1200.c and via82cxxx.c. There should be no functional changes caused by this patch. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/palm_bk3710.c | 4 ++-- drivers/ide/pci/cs5530.c | 4 ++-- drivers/ide/pci/cs5535.c | 4 ++-- drivers/ide/pci/opti621.c | 4 ++-- drivers/ide/pci/sc1200.c | 4 ++-- drivers/ide/pci/siimage.c | 4 ++-- drivers/ide/pci/via82cxxx.c | 4 ++-- include/linux/ide.h | 6 +++--- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 6cea984776f..320971c78cb 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -180,7 +180,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, val32 |= (t2i << (dev ? 8 : 0)); writel(val32, base + BK3710_DATRCVR); - if (mate && mate->present) { + if (mate) { u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); if (mode2 < mode) @@ -230,7 +230,7 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio) * Obtain the drive PIO data for tuning the Palm Chip registers */ cycle_time = ide_pio_cycle_time(drive, pio); - mate = ide_get_paired_drive(drive); + mate = ide_get_pair_dev(drive); palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index ef91e9d7c54..804ecabbd65 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -81,11 +81,11 @@ static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio) static u8 cs5530_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; + ide_drive_t *mate = ide_get_pair_dev(drive); u16 *mateid = mate->id; u8 mask = hwif->ultra_mask; - if (mate->present == 0) + if (mate == NULL) goto out; if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index dd3dc23af99..707d2e18255 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -80,12 +80,12 @@ static void cs5535_set_speed(ide_drive_t *drive, const u8 speed) /* Set the PIO timings */ if (speed < XFER_SW_DMA_0) { - ide_drive_t *pair = ide_get_paired_drive(drive); + ide_drive_t *pair = ide_get_pair_dev(drive); u8 cmd, pioa; cmd = pioa = speed - XFER_PIO_0; - if (pair->present) { + if (pair) { u8 piob = ide_get_best_pio_mode(pair, 255, 4); if (piob < cmd) diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index e28e672ddaf..e913da47980 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -137,7 +137,7 @@ static u8 read_reg(int reg) static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = drive->hwif; - ide_drive_t *pair = ide_get_paired_drive(drive); + ide_drive_t *pair = ide_get_pair_dev(drive); unsigned long flags; u8 tim, misc, addr_pio = pio, clk; @@ -153,7 +153,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->drive_data = XFER_PIO_0 + pio; - if (pair->present) { + if (pair) { if (pair->drive_data && pair->drive_data < drive->drive_data) addr_pio = pair->drive_data - XFER_PIO_0; } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 695cc974204..37326d2205b 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -104,11 +104,11 @@ static void sc1200_tunepio(ide_drive_t *drive, u8 pio) static u8 sc1200_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; + ide_drive_t *mate = ide_get_pair_dev(drive); u16 *mateid = mate->id; u8 mask = hwif->ultra_mask; - if (mate->present == 0) + if (mate == NULL) goto out; if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 7b5bd8729f6..83c36e6035f 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -245,7 +245,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); - ide_drive_t *pair = ide_get_paired_drive(drive); + ide_drive_t *pair = ide_get_pair_dev(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); @@ -259,7 +259,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) u8 unit = drive->select.b.unit; /* trim *taskfile* PIO to the slowest of the master/slave */ - if (pair->present) { + if (pair) { u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4); if (pair_pio < tf_pio) diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 94fb9ab3223..9cb531dc905 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -154,7 +154,7 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) static void via_set_drive(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = drive->hwif; - ide_drive_t *peer = hwif->drives + (~drive->dn & 1); + ide_drive_t *peer = ide_get_pair_dev(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); struct ide_host *host = pci_get_drvdata(dev); struct via82cxxx_dev *vdev = host->host_priv; @@ -173,7 +173,7 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed) ide_timing_compute(drive, speed, &t, T, UT); - if (peer->present) { + if (peer) { ide_timing_compute(peer, peer->current_speed, &p, T, UT); ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); } diff --git a/include/linux/ide.h b/include/linux/ide.h index a9206c463d7..1d9716a95dc 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1450,10 +1450,10 @@ static inline int hwif_to_node(ide_hwif_t *hwif) return hwif->dev ? dev_to_node(hwif->dev) : -1; } -static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive) +static inline ide_drive_t *ide_get_pair_dev(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); + ide_drive_t *peer = &drive->hwif->drives[(drive->dn ^ 1) & 1]; - return &hwif->drives[(drive->dn ^ 1) & 1]; + return peer->present ? peer : NULL; } #endif /* _IDE_H */ -- GitLab From 7c51c17e0431d2f26bc23ee07de12eafb125ce83 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:26 +0200 Subject: [PATCH 3795/5416] ide: remove CONFIG_IDEDISK_MULTI_MODE Use multi PIO by default when available and remove no longer needed CONFIG_IDEDISK_MULTI_MODE (it should be safe nowadays, despite to what help entry has been saying). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 23 ----------------------- drivers/ide/ide-probe.c | 6 ++---- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 052879a6f85..b50b5dac95b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -131,29 +131,6 @@ config BLK_DEV_IDEDISK If unsure, say Y. -config IDEDISK_MULTI_MODE - bool "Use multiple sector mode for Programmed Input/Output by default" - help - This setting is irrelevant for most IDE disks, with direct memory - access, to which multiple sector mode does not apply. Multiple sector - mode is a feature of most modern IDE hard drives, permitting the - transfer of multiple sectors per Programmed Input/Output interrupt, - rather than the usual one sector per interrupt. When this feature is - enabled, it can reduce operating system overhead for disk Programmed - Input/Output. On some systems, it also can increase the data - throughput of Programmed Input/Output. Some drives, however, seemed - to run slower with multiple sector mode enabled. Some drives claimed - to support multiple sector mode, but lost data at some settings. - Under rare circumstances, such failures could result in massive - filesystem corruption. - - If you get the following error, try to say Y here: - - hda: set_multmode: status=0x51 { DriveReady SeekComplete Error } - hda: set_multmode: error=0x04 { DriveStatusError } - - If in doubt, say N. - config BLK_DEV_IDECS tristate "PCMCIA IDE support" depends on PCMCIA diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 8cfce50c71e..9926e12783b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -89,16 +89,14 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff; if (max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE if ((max_multsect / 2) > 1) id[ATA_ID_MULTSECT] = max_multsect | 0x100; else id[ATA_ID_MULTSECT] &= ~0x1ff; drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; -#endif - if ((id[ATA_ID_MULTSECT] & 0x100) && - (id[ATA_ID_MULTSECT] & 0xff)) + + if (drive->mult_req) drive->special.b.set_multmode = 1; } } -- GitLab From 3ceca727fe3a38dd8d7a3adf938fefda83eee8af Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:27 +0200 Subject: [PATCH 3796/5416] ide: include only when needed * Include directly in instead of through . * Include only when needed. Cc: Christoph Hellwig Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/icside.c | 1 - drivers/ide/arm/palm_bk3710.c | 1 - drivers/ide/ide-disk.c | 1 + drivers/ide/ide-floppy.c | 1 + drivers/ide/ide-io.c | 1 + drivers/ide/ide-iops.c | 1 - drivers/ide/ide-lib.c | 1 - drivers/ide/ide-proc.c | 1 - drivers/ide/ide-timings.c | 1 - drivers/ide/ide.c | 1 + drivers/ide/legacy/ali14xx.c | 1 - drivers/ide/legacy/buddha.c | 1 - drivers/ide/legacy/dtc2278.c | 1 - drivers/ide/legacy/falconide.c | 1 - drivers/ide/legacy/gayle.c | 1 - drivers/ide/legacy/ht6560b.c | 1 - drivers/ide/legacy/ide-cs.c | 1 - drivers/ide/legacy/macide.c | 1 - drivers/ide/legacy/q40ide.c | 2 -- drivers/ide/legacy/qd65xx.c | 1 - drivers/ide/legacy/umc8672.c | 1 - drivers/ide/pci/aec62xx.c | 1 - drivers/ide/pci/alim15x3.c | 1 - drivers/ide/pci/atiixp.c | 1 - drivers/ide/pci/cmd640.c | 1 - drivers/ide/pci/cmd64x.c | 1 - drivers/ide/pci/cs5520.c | 1 - drivers/ide/pci/cs5530.c | 1 - drivers/ide/pci/delkin_cb.c | 1 - drivers/ide/pci/generic.c | 1 - drivers/ide/pci/hpt34x.c | 1 - drivers/ide/pci/hpt366.c | 1 - drivers/ide/pci/it8213.c | 1 - drivers/ide/pci/it821x.c | 1 - drivers/ide/pci/jmicron.c | 1 - drivers/ide/pci/ns87415.c | 1 - drivers/ide/pci/opti621.c | 1 - drivers/ide/pci/pdc202xx_new.c | 1 - drivers/ide/pci/pdc202xx_old.c | 1 - drivers/ide/pci/piix.c | 1 - drivers/ide/pci/rz1000.c | 1 - drivers/ide/pci/sc1200.c | 1 - drivers/ide/pci/scc_pata.c | 1 - drivers/ide/pci/serverworks.c | 1 - drivers/ide/pci/sgiioc4.c | 1 - drivers/ide/pci/siimage.c | 1 - drivers/ide/pci/sis5513.c | 1 - drivers/ide/pci/sl82c105.c | 1 - drivers/ide/pci/slc90e66.c | 1 - drivers/ide/pci/triflex.c | 1 - drivers/ide/pci/trm290.c | 1 - drivers/scsi/ide-scsi.c | 1 - include/linux/ide.h | 2 +- 53 files changed, 5 insertions(+), 50 deletions(-) diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index ca9e8ea32ee..70f5b164828 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 320971c78cb..122ed3c072f 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index eeb2c3b22e9..6e1a25e61df 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 32796038090..b0f4d8459a9 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 96975e24a0c..99e0bbca3ac 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index a940d127aae..ee44878e40d 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index c5c37bfd8b0..ed426dd0fdd 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 22f41fa4e5b..cbe5a7efbba 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c index 96e3d467a74..81f527af8fa 100644 --- a/drivers/ide/ide-timings.c +++ b/drivers/ide/ide-timings.c @@ -22,7 +22,6 @@ */ #include -#include #include #include diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 27d5d6a1625..080314e3d6b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 4ec19737f3c..7276c96aaa2 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 7c2afa97f41..c5a3c9ef6a5 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index af791a02a12..689b2e49341 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index 724f95073d8..39d500d84b0 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index 51ba085d7aa..69150688656 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 98f7c95e39e..5123ea291d0 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 21bfac13784..ee6fc30d5e2 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index a0bb167980e..43f97cc1d30 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 4abd8fc7819..4af4a8ce4cd 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -14,8 +14,6 @@ #include #include #include -#include - #include /* diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 6d7f548655e..ec408b3a710 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index b54a14a5775..1da076e0c91 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 3187215e8f8..f65828da65d 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index fcc701b3c0a..ef41e2677a5 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 41f6cb6c163..86e3120cb7c 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index e6c62006ca1..5b756757e04 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -103,7 +103,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index e064398e03b..13dfeab1d19 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 151844fcbb0..27163147896 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 804ecabbd65..d60806bd7db 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index f84bfb4f600..83b63b365e5 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index b07d4f4273b..bdc53986870 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 6009b0b9655..4f624899f44 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index b7f77fd3cb6..d706eb6b8ac 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -122,7 +122,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 652e47dd7e8..a0e058a2abf 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index ed24065f74e..0fdea7e91a7 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index bb9d09d8f19..4010b4a8dfb 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index 17685f0ade1..a482ade8e45 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index e913da47980..fefac2c174b 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -85,7 +85,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 7ecfcd06f47..73bd264fbf9 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 5d4436f3efd..8f0acb956c6 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 30cfc815fe3..13136dddb2b 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index 8d11ee838a2..c117a068761 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 37326d2205b..bdc1fed4126 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index 192a6a70a63..e92a874b31d 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index ded6a13fd40..5f79d284ff8 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 681306c9d79..1017fb4f631 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 83c36e6035f..874c8ca40ed 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 5efe21d6ef9..56bfb245f1f 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 73905bcc08f..61a006cb474 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 866d6c65e3a..a31c6911442 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index b77ec35151b..c980a7f3905 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index fd28b49977f..4dfbc6a68b5 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -135,7 +135,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 6a661a4454e..d9a2cc09f5c 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/include/linux/ide.h b/include/linux/ide.h index 1d9716a95dc..a7f980d2fe5 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include -- GitLab From 1e874f448365b80e69b8a60b8b575b17f00811f3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:27 +0200 Subject: [PATCH 3797/5416] ide: call ide_proc_register_driver() later Call ide_proc_register_driver() in ide*_setup() (just before ide*_add_settings() call) instead of in ->probe method. Despite being basically a preparation for /proc/ide/hd*/settings rework this is a nice cleanup in itself. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 5 ++--- drivers/ide/ide-disk.c | 4 ++-- drivers/ide/ide-floppy.c | 4 ++-- drivers/ide/ide-tape.c | 3 +-- drivers/scsi/ide-scsi.c | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 607af5de16f..34a1aeaa15d 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1924,6 +1924,8 @@ static int ide_cdrom_setup(ide_drive_t *drive) cd->devinfo.handle = NULL; return 1; } + + ide_proc_register_driver(drive, cd->driver); ide_cdrom_add_settings(drive); return 0; } @@ -2134,8 +2136,6 @@ static int ide_cd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &ide_cdrom_driver); - kref_init(&info->kref); info->drive = drive; @@ -2150,7 +2150,6 @@ static int ide_cd_probe(ide_drive_t *drive) g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { - ide_proc_unregister_driver(drive, &ide_cdrom_driver); ide_cd_release(&info->kref); goto failed; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 6e1a25e61df..5fc4213437a 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -782,11 +782,13 @@ static inline void idedisk_add_settings(ide_drive_t *drive) { ; } static void idedisk_setup(ide_drive_t *drive) { + struct ide_disk_obj *idkp = drive->driver_data; ide_hwif_t *hwif = drive->hwif; u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; unsigned long long capacity; + ide_proc_register_driver(drive, idkp->driver); idedisk_add_settings(drive); if (drive->id_read == 0) @@ -1151,8 +1153,6 @@ static int ide_disk_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idedisk_driver); - kref_init(&idkp->kref); idkp->drive = drive; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index b0f4d8459a9..597459c81d5 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1061,6 +1061,8 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) } (void) ide_floppy_get_capacity(drive); + + ide_proc_register_driver(drive, floppy->driver); idefloppy_add_settings(drive); } @@ -1413,8 +1415,6 @@ static int ide_floppy_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idefloppy_driver); - kref_init(&floppy->kref); floppy->drive = drive; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 874e60fc85d..f41983e4a4e 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2514,6 +2514,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->best_dsc_rw_freq * 1000 / HZ, drive->using_dma ? ", DMA":""); + ide_proc_register_driver(drive, tape->driver); idetape_add_settings(drive); } @@ -2669,8 +2670,6 @@ static int ide_tape_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idetape_driver); - kref_init(&tape->kref); tape->drive = drive; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index d9a2cc09f5c..02bd5c487d1 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -460,6 +460,7 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) drive->pc_callback = ide_scsi_callback; + ide_proc_register_driver(drive, scsi->driver); idescsi_add_settings(drive); } @@ -851,7 +852,6 @@ static int ide_scsi_probe(ide_drive_t *drive) idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; - ide_proc_register_driver(drive, &idescsi_driver); err = 0; idescsi_setup(drive, idescsi); g->fops = &idescsi_ops; -- GitLab From 263138a0ad6e38de7f6526b7de037ed4511308ef Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:27 +0200 Subject: [PATCH 3798/5416] ide: preparations for /proc/ide/hd*/settings rework After rework settings will be no longer created dynamically for each device so we need to make some fixups first. * Use set_[ksettings,unmaskirq]() as a set function for ["keepsettings","unmaskirq"] setting. * Allow writes to ["io_32bit","unmaskirq"] settings also when drive->no_[io_32bit,unmask] is set (this is checked later inside set_[io_32bit,unmaskirq]() anywyay and keeps consistency with the corresponding HDIO_SET_[32BIT,UNMASKINTR] ioctls). * Use max possible multi sectors value (16) as an allowed max for "multcount" setting. set_multcount() set function checks against device's max possbile value anyway and it makes the proc setting consistent with the corresponding HDIO_SET_MULTCOUNT ioctl. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 3 +-- drivers/ide/ide-proc.c | 6 +++--- drivers/ide/ide.c | 4 ++-- include/linux/ide.h | 2 ++ 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 5fc4213437a..7a15907dce1 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -760,8 +760,7 @@ static void idedisk_add_settings(ide_drive_t *drive) &drive->bios_sect, NULL); ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, - drive->id[ATA_ID_MAX_MULTSECT] & 0xff, 1, 1, + ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, 16, 1, 1, &drive->mult_count, set_multcount); ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index cbe5a7efbba..7a64aedfa64 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -368,11 +368,11 @@ void ide_add_generic_settings (ide_drive_t *drive) /* * drive setting name read/write access data type min max mul_factor div_factor data pointer set function */ - __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "io_32bit", SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, set_ksettings, 0); __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "unmaskirq", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, set_unmaskirq, 0); __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 080314e3d6b..8e0c9f27ae4 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -305,7 +305,7 @@ int set_io_32bit(ide_drive_t *drive, int arg) return 0; } -static int set_ksettings(ide_drive_t *drive, int arg) +int set_ksettings(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 1) return -EINVAL; @@ -394,7 +394,7 @@ int set_pio_mode(ide_drive_t *drive, int arg) return 0; } -static int set_unmaskirq(ide_drive_t *drive, int arg) +int set_unmaskirq(ide_drive_t *drive, int arg) { if (drive->no_unmask) return -EPERM; diff --git a/include/linux/ide.h b/include/linux/ide.h index a7f980d2fe5..ad09e7c81ae 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -688,7 +688,9 @@ typedef struct ide_driver_s ide_driver_t; extern struct mutex ide_setting_mtx; int set_io_32bit(ide_drive_t *, int); +int set_ksettings(ide_drive_t *, int); int set_pio_mode(ide_drive_t *, int); +int set_unmaskirq(ide_drive_t *, int); int set_using_dma(ide_drive_t *, int); /* ATAPI packet command flags */ -- GitLab From 8185d5aa93e0a5c111adc4952a5b87193a68ae5b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:28 +0200 Subject: [PATCH 3799/5416] ide: /proc/ide/hd*/settings rework * Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros. * Add 'const struct ide_devset **settings' to ide_driver_t. * Use 'const struct ide_devset **settings' in ide_drive_t instead of 'struct ide_settings_s *settings'. Then convert core code and device drivers to use struct ide_devset and co.: - device settings are no longer allocated dynamically for each device but instead there is an unique struct ide_devset instance per setting - device driver keeps the pointer to the table of pointers to its settings in ide_driver_t.settings - generic settings are kept in ide_generic_setting[] - ide_proc_[un]register_driver(), ide_find_setting_by_name(), ide_{read,write}_setting() and proc_ide_{read,write}_settings() are updated accordingly - ide*_add_settings() are removed * Remove no longer used __ide_add_setting(), ide_add_setting(), __ide_remove_setting() and auto_remove_settings(). * Remove no longer used TYPE_*, SETTING_*, ide_procset_t and ide_settings_t. * ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap, ->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields can now be bitfield flags. While at it: * Rename ide_find_setting_by_name() to ide_find_setting(). * Rename write_wcache() to set_wcache(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 15 +-- drivers/ide/ide-disk.c | 87 ++++++------ drivers/ide/ide-floppy.c | 35 +++-- drivers/ide/ide-probe.c | 2 - drivers/ide/ide-proc.c | 279 ++++++++++++--------------------------- drivers/ide/ide-tape.c | 74 +++++++---- drivers/ide/ide.c | 21 ++- drivers/scsi/ide-scsi.c | 52 +++++--- include/linux/ide.h | 110 ++++++++++----- 9 files changed, 340 insertions(+), 335 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 34a1aeaa15d..1f565232648 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1809,13 +1809,12 @@ static ide_proc_entry_t idecd_proc[] = { { NULL, 0, NULL, NULL } }; -static void ide_cdrom_add_settings(ide_drive_t *drive) -{ - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, - &drive->dsc_overlap, NULL); -} -#else -static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } +ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); + +static const struct ide_devset *idecd_settings[] = { + &ide_devset_dsc_overlap, + NULL +}; #endif static const struct cd_list_entry ide_cd_quirks_list[] = { @@ -1926,7 +1925,6 @@ static int ide_cdrom_setup(ide_drive_t *drive) } ide_proc_register_driver(drive, cd->driver); - ide_cdrom_add_settings(drive); return 0; } @@ -1977,6 +1975,7 @@ static ide_driver_t ide_cdrom_driver = { .error = __ide_error, #ifdef CONFIG_IDE_PROC_FS .proc = idecd_proc, + .settings = idecd_settings, #endif }; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7a15907dce1..2e43ae15fb1 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -599,6 +599,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) rq->special = task; } +ide_devset_get(multcount, mult_count); + /* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. @@ -625,6 +627,8 @@ static int set_multcount(ide_drive_t *drive, int arg) return (drive->mult_count == arg) ? 0 : -EIO; } +ide_devset_get(nowerr, nowerr); + static int set_nowerr(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 1) @@ -673,7 +677,9 @@ static void update_ordered(ide_drive_t *drive) blk_queue_ordered(drive->queue, ordered, prep_fn); } -static int write_cache(ide_drive_t *drive, int arg) +ide_devset_get(wcache, wcache); + +static int set_wcache(ide_drive_t *drive, int arg) { ide_task_t args; int err = 1; @@ -710,6 +716,8 @@ static int do_idedisk_flushcache(ide_drive_t *drive) return ide_no_data_taskfile(drive, &args); } +ide_devset_get(acoustic, acoustic); + static int set_acoustic(ide_drive_t *drive, int arg) { ide_task_t args; @@ -727,6 +735,8 @@ static int set_acoustic(ide_drive_t *drive, int arg) return 0; } +ide_devset_get(lba_addressing, addressing); + /* * drive->addressing: * 0: 28-bit @@ -750,33 +760,33 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) } #ifdef CONFIG_IDE_PROC_FS -static void idedisk_add_settings(ide_drive_t *drive) -{ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, - &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, - &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, - &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, - &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, 16, 1, 1, - &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, - &drive->nowerr, set_nowerr); - ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, - &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, - &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, - &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, - &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, - 1, 1, &drive->max_failures, NULL); -} -#else -static inline void idedisk_add_settings(ide_drive_t *drive) { ; } +ide_devset_rw_nolock(acoustic, 0, 254, acoustic); +ide_devset_rw_nolock(address, 0, 2, lba_addressing); +ide_devset_rw_nolock(multcount, 0, 16, multcount); +ide_devset_rw_nolock(nowerr, 0, 1, nowerr); +ide_devset_rw_nolock(wcache, 0, 1, wcache); + +ide_devset_rw(bios_cyl, 0, 65535, bios_cyl); +ide_devset_rw(bios_head, 0, 255, bios_head); +ide_devset_rw(bios_sect, 0, 63, bios_sect); +ide_devset_rw(failures, 0, 65535, failures); +ide_devset_rw(lun, 0, 7, lun); +ide_devset_rw(max_failures, 0, 65535, max_failures); + +static const struct ide_devset *idedisk_settings[] = { + &ide_devset_acoustic, + &ide_devset_address, + &ide_devset_bios_cyl, + &ide_devset_bios_head, + &ide_devset_bios_sect, + &ide_devset_failures, + &ide_devset_lun, + &ide_devset_max_failures, + &ide_devset_multcount, + &ide_devset_nowerr, + &ide_devset_wcache, + NULL +}; #endif static void idedisk_setup(ide_drive_t *drive) @@ -788,7 +798,6 @@ static void idedisk_setup(ide_drive_t *drive) unsigned long long capacity; ide_proc_register_driver(drive, idkp->driver); - idedisk_add_settings(drive); if (drive->id_read == 0) return; @@ -880,7 +889,7 @@ static void idedisk_setup(ide_drive_t *drive) if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) drive->wcache = 1; - write_cache(drive, 1); + set_wcache(drive, 1); } static void ide_cacheflush_p(ide_drive_t *drive) @@ -976,6 +985,7 @@ static ide_driver_t idedisk_driver = { .error = __ide_error, #ifdef CONFIG_IDE_PROC_FS .proc = idedisk_proc, + .settings = idedisk_settings, #endif }; @@ -1056,19 +1066,18 @@ static int idedisk_ioctl(struct inode *inode, struct file *file, struct block_device *bdev = inode->i_bdev; struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); ide_drive_t *drive = idkp->drive; - int err, (*setfunc)(ide_drive_t *, int); - u8 *val; + int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int); switch (cmd) { - case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; - case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; - case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; - case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; - case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; + case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val; + case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val; + case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val; + case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val; + case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val; case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; - case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; + case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val; case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; } @@ -1077,7 +1086,7 @@ static int idedisk_ioctl(struct inode *inode, struct file *file, read_val: mutex_lock(&ide_setting_mtx); spin_lock_irqsave(&ide_lock, flags); - err = *val; + err = getfunc(drive); spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); return err >= 0 ? put_user(err, (long __user *)arg) : err; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 597459c81d5..673644fdb6f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1007,21 +1007,32 @@ static int idefloppy_identify_device(ide_drive_t *drive, u16 *id) } #ifdef CONFIG_IDE_PROC_FS -static void idefloppy_add_settings(ide_drive_t *drive) +ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); +ide_devset_rw(bios_head, 0, 255, bios_head); +ide_devset_rw(bios_sect, 0, 63, bios_sect); + +static int get_ticks(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; + return floppy->ticks; +} - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, - &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, - &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, - &drive->bios_sect, NULL); - ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, - &floppy->ticks, NULL); +static int set_ticks(ide_drive_t *drive, int arg) +{ + idefloppy_floppy_t *floppy = drive->driver_data; + floppy->ticks = arg; + return 0; } -#else -static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } + +IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks); + +static const struct ide_devset *idefloppy_settings[] = { + &ide_devset_bios_cyl, + &ide_devset_bios_head, + &ide_devset_bios_sect, + &ide_devset_ticks, + NULL +}; #endif static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) @@ -1063,7 +1074,6 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) (void) ide_floppy_get_capacity(drive); ide_proc_register_driver(drive, floppy->driver); - idefloppy_add_settings(drive); } static void ide_floppy_remove(ide_drive_t *drive) @@ -1126,6 +1136,7 @@ static ide_driver_t idefloppy_driver = { .error = __ide_error, #ifdef CONFIG_IDE_PROC_FS .proc = idefloppy_proc, + .settings = idefloppy_settings, #endif }; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 9926e12783b..62f7e1ef10c 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1332,8 +1332,6 @@ static void hwif_register_devices(ide_hwif_t *hwif) if (!drive->present) continue; - ide_add_generic_settings(drive); - snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); dev->parent = &hwif->gendev; dev->bus = &ide_bus_type; diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 7a64aedfa64..5634b3971d2 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -114,140 +114,24 @@ static int proc_ide_read_identify } /** - * __ide_add_setting - add an ide setting option - * @drive: drive to use + * ide_find_setting - find a specific setting + * @st: setting table pointer * @name: setting name - * @rw: true if the function is read write - * @data_type: type of data - * @min: range minimum - * @max: range maximum - * @mul_factor: multiplication scale - * @div_factor: divison scale - * @data: private data field - * @set: setting - * @auto_remove: setting auto removal flag * - * Removes the setting named from the device if it is present. - * The function takes the settings_lock to protect against - * parallel changes. This function must not be called from IRQ - * context. Returns 0 on success or -1 on failure. - * - * BUGS: This code is seriously over-engineered. There is also - * magic about how the driver specific features are setup. If - * a driver is attached we assume the driver settings are auto - * remove. - */ - -static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - mutex_lock(&ide_setting_mtx); - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); - setting->rw = rw; - setting->data_type = data_type; - setting->min = min; - setting->max = max; - setting->mul_factor = mul_factor; - setting->div_factor = div_factor; - setting->data = data; - setting->set = set; - - setting->next = *p; - if (auto_remove) - setting->auto_remove = 1; - *p = setting; - mutex_unlock(&ide_setting_mtx); - return 0; -abort: - mutex_unlock(&ide_setting_mtx); - kfree(setting); - return -1; -} - -int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); -} - -EXPORT_SYMBOL(ide_add_setting); - -/** - * __ide_remove_setting - remove an ide setting option - * @drive: drive to use - * @name: setting name - * - * Removes the setting named from the device if it is present. - * The caller must hold the setting semaphore. - */ - -static void __ide_remove_setting(ide_drive_t *drive, char *name) -{ - ide_settings_t **p, *setting; - - p = (ide_settings_t **) &drive->settings; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - setting = (*p); - if (setting == NULL) - return; - - (*p) = setting->next; - - kfree(setting->name); - kfree(setting); -} - -/** - * auto_remove_settings - remove driver specific settings - * @drive: drive - * - * Automatically remove all the driver specific settings for this - * drive. This function may not be called from IRQ context. The - * caller must hold ide_setting_mtx. - */ - -static void auto_remove_settings(ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - __ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -/** - * ide_find_setting_by_name - find a drive specific setting - * @drive: drive to scan - * @name: setting name - * - * Scan's the device setting table for a matching entry and returns + * Scan's the setting table for a matching entry and returns * this or NULL if no entry is found. The caller must hold the * setting semaphore */ -static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) +static const struct ide_devset *ide_find_setting(const struct ide_devset **st, + char *name) { - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) + while (*st) { + if (strcmp((*st)->name, name) == 0) break; - setting = setting->next; + st++; } - return setting; + return *st; } /** @@ -263,26 +147,19 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) * be told apart */ -static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) +static int ide_read_setting(ide_drive_t *drive, + const struct ide_devset *setting) { - int val = -EINVAL; - unsigned long flags; + int val = -EINVAL; + + if ((setting->flags & S_READ)) { + unsigned long flags; - if ((setting->rw & SETTING_READ)) { spin_lock_irqsave(&ide_lock, flags); - switch (setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - val = *((u32 *) setting->data); - break; - } + val = setting->get(drive); spin_unlock_irqrestore(&ide_lock, flags); } + return val; } @@ -304,33 +181,26 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) * The current scheme of polling is kludgy, though safe enough. */ -static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) +static int ide_write_setting(ide_drive_t *drive, + const struct ide_devset *setting, int val) { if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (setting->set) + if (setting->set && (setting->flags & S_NOLOCK)) return setting->set(drive, val); - if (!(setting->rw & SETTING_WRITE)) + if (!(setting->flags & S_WRITE)) return -EPERM; if (val < setting->min || val > setting->max) return -EINVAL; if (ide_spin_wait_hwgroup(drive)) return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - } + setting->set(drive, val); spin_unlock_irq(&ide_lock); return 0; } +static ide_devset_get(xfer_rate, current_speed); + static int set_xfer_rate (ide_drive_t *drive, int arg) { ide_task_t task; @@ -355,29 +225,30 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) return err; } -/** - * ide_add_generic_settings - generic ide settings - * @drive: drive being configured - * - * Add the generic parts of the system settings to the /proc files. - * The caller must not be holding the ide_setting_mtx. - */ - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access data type min max mul_factor div_factor data pointer set function - */ - __ide_add_setting(drive, "io_32bit", SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, set_ksettings, 0); - __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); - __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, set_unmaskirq, 0); - __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); - __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); - __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); - __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); -} +ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate); +ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit); +ide_devset_rw_nolock(keepsettings, 0, 1, ksettings); +ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq); +ide_devset_rw_nolock(using_dma, 0, 1, using_dma); + +ide_devset_w_nolock(pio_mode, 0, 255, pio_mode); + +ide_devset_rw(init_speed, 0, 70, init_speed); +ide_devset_rw(nice1, 0, 1, nice1); +ide_devset_rw(number, 0, 3, dn); + +static const struct ide_devset *ide_generic_settings[] = { + &ide_devset_current_speed, + &ide_devset_init_speed, + &ide_devset_io_32bit, + &ide_devset_keepsettings, + &ide_devset_nice1, + &ide_devset_number, + &ide_devset_pio_mode, + &ide_devset_unmaskirq, + &ide_devset_using_dma, + NULL +}; static void proc_ide_settings_warn(void) { @@ -394,19 +265,31 @@ static void proc_ide_settings_warn(void) static int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { + const struct ide_devset *setting, **g, **d; ide_drive_t *drive = (ide_drive_t *) data; - ide_settings_t *setting = (ide_settings_t *) drive->settings; char *out = page; int len, rc, mul_factor, div_factor; proc_ide_settings_warn(); mutex_lock(&ide_setting_mtx); + g = ide_generic_settings; + d = drive->settings; out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); - while (setting) { - mul_factor = setting->mul_factor; - div_factor = setting->div_factor; + while (*g || (d && *d)) { + /* read settings in the alphabetical order */ + if (*g && d && *d) { + if (strcmp((*d)->name, (*g)->name) < 0) + setting = *d++; + else + setting = *g++; + } else if (d && *d) { + setting = *d++; + } else + setting = *g++; + mul_factor = setting->mulf ? setting->mulf(drive) : 1; + div_factor = setting->divf ? setting->divf(drive) : 1; out += sprintf(out, "%-24s", setting->name); rc = ide_read_setting(drive, setting); if (rc >= 0) @@ -414,12 +297,11 @@ static int proc_ide_read_settings else out += sprintf(out, "%-16s", "write-only"); out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); - if (setting->rw & SETTING_READ) + if (setting->flags & S_READ) out += sprintf(out, "r"); - if (setting->rw & SETTING_WRITE) + if (setting->flags & S_WRITE) out += sprintf(out, "w"); out += sprintf(out, "\n"); - setting = setting->next; } len = out - page; mutex_unlock(&ide_setting_mtx); @@ -433,9 +315,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, { ide_drive_t *drive = (ide_drive_t *) data; char name[MAX_LEN + 1]; - int for_real = 0; + int for_real = 0, mul_factor, div_factor; unsigned long n; - ide_settings_t *setting; + + const struct ide_devset *setting; char *buf, *s; if (!capable(CAP_SYS_ADMIN)) @@ -503,13 +386,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, } mutex_lock(&ide_setting_mtx); - setting = ide_find_setting_by_name(drive, name); + /* generic settings first, then driver specific ones */ + setting = ide_find_setting(ide_generic_settings, name); if (!setting) { - mutex_unlock(&ide_setting_mtx); - goto parse_error; + if (drive->settings) + setting = ide_find_setting(drive->settings, name); + if (!setting) { + mutex_unlock(&ide_setting_mtx); + goto parse_error; + } + } + if (for_real) { + mul_factor = setting->mulf ? setting->mulf(drive) : 1; + div_factor = setting->divf ? setting->divf(drive) : 1; + ide_write_setting(drive, setting, val * div_factor / mul_factor); } - if (for_real) - ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor); mutex_unlock(&ide_setting_mtx); } } while (!for_real++); @@ -680,6 +571,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { + mutex_lock(&ide_setting_mtx); + drive->settings = driver->settings; + mutex_unlock(&ide_setting_mtx); + ide_add_proc_entries(drive->proc, driver->proc, drive); } @@ -716,7 +611,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) * OTOH both ide_{read,write}_setting are only ever used under * ide_setting_mtx. */ - auto_remove_settings(drive); + drive->settings = NULL; spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index f41983e4a4e..7037accb058 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2410,28 +2410,56 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive) } #ifdef CONFIG_IDE_PROC_FS -static void idetape_add_settings(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, - 1, 2, (u16 *)&tape->caps[16], NULL); - ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, - 1, 1, (u16 *)&tape->caps[14], NULL); - ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff, - 1, 1024, &tape->buffer_size, NULL); - ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, - IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq, - NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, - 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, - 1, 1, &tape->avg_speed, NULL); - ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1, - 1, &tape->debug_mask, NULL); -} -#else -static inline void idetape_add_settings(ide_drive_t *drive) { ; } +#define ide_tape_devset_get(name, field) \ +static int get_##name(ide_drive_t *drive) \ +{ \ + idetape_tape_t *tape = drive->driver_data; \ + return tape->field; \ +} + +#define ide_tape_devset_set(name, field) \ +static int set_##name(ide_drive_t *drive, int arg) \ +{ \ + idetape_tape_t *tape = drive->driver_data; \ + tape->field = arg; \ + return 0; \ +} + +#define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \ +ide_tape_devset_get(_name, _field) \ +ide_tape_devset_set(_name, _field) \ +__IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf) + +#define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \ +ide_tape_devset_get(_name, _field) \ +__IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf) + +static int mulf_tdsc(ide_drive_t *drive) { return 1000; } +static int divf_tdsc(ide_drive_t *drive) { return HZ; } +static int divf_buffer(ide_drive_t *drive) { return 2; } +static int divf_buffer_size(ide_drive_t *drive) { return 1024; } + +ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); + +ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL); +ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, + best_dsc_rw_freq, mulf_tdsc, divf_tdsc); + +ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL); +ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL); +ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer); +ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size); + +static const struct ide_devset *idetape_settings[] = { + &ide_devset_avg_speed, + &ide_devset_buffer, + &ide_devset_buffer_size, + &ide_devset_debug_mask, + &ide_devset_dsc_overlap, + &ide_devset_speed, + &ide_devset_tdsc, + NULL +}; #endif /* @@ -2515,7 +2543,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) drive->using_dma ? ", DMA":""); ide_proc_register_driver(drive, tape->driver); - idetape_add_settings(drive); } static void ide_tape_remove(ide_drive_t *drive) @@ -2586,6 +2613,7 @@ static ide_driver_t idetape_driver = { .error = __ide_error, #ifdef CONFIG_IDE_PROC_FS .proc = idetape_proc, + .settings = idetape_settings, #endif }; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8e0c9f27ae4..eb64e942f58 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -287,6 +287,8 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive) EXPORT_SYMBOL(ide_spin_wait_hwgroup); +ide_devset_get(io_32bit, io_32bit); + int set_io_32bit(ide_drive_t *drive, int arg) { if (drive->no_io_32bit) @@ -305,6 +307,8 @@ int set_io_32bit(ide_drive_t *drive, int arg) return 0; } +ide_devset_get(ksettings, keep_settings); + int set_ksettings(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 1) @@ -318,6 +322,8 @@ int set_ksettings(ide_drive_t *drive, int arg) return 0; } +ide_devset_get(using_dma, using_dma); + int set_using_dma(ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA @@ -394,6 +400,8 @@ int set_pio_mode(ide_drive_t *drive, int arg) return 0; } +ide_devset_get(unmaskirq, unmask); + int set_unmaskirq(ide_drive_t *drive, int arg) { if (drive->no_unmask) @@ -555,14 +563,13 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device { unsigned long flags; ide_driver_t *drv; - int err = 0, (*setfunc)(ide_drive_t *, int); - u8 *val; + int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int); switch (cmd) { - case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; - case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; - case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; - case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; + case HDIO_GET_32BIT: getfunc = get_io_32bit; goto read_val; + case HDIO_GET_KEEPSETTINGS: getfunc = get_ksettings; goto read_val; + case HDIO_GET_UNMASKINTR: getfunc = get_unmaskirq; goto read_val; + case HDIO_GET_DMA: getfunc = get_using_dma; goto read_val; case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; @@ -638,7 +645,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device read_val: mutex_lock(&ide_setting_mtx); spin_lock_irqsave(&ide_lock, flags); - err = *val; + err = getfunc(drive); spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); return err >= 0 ? put_user(err, (long __user *)arg) : err; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 02bd5c487d1..65cf84b222c 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -429,21 +429,41 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r } #ifdef CONFIG_IDE_PROC_FS -static void idescsi_add_settings(ide_drive_t *drive) -{ - idescsi_scsi_t *scsi = drive_to_idescsi(drive); - -/* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function - */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); - ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); -} -#else -static inline void idescsi_add_settings(ide_drive_t *drive) { ; } +#define ide_scsi_devset_get(name, field) \ +static int get_##name(ide_drive_t *drive) \ +{ \ + idescsi_scsi_t *scsi = drive_to_idescsi(drive); \ + return scsi->field; \ +} + +#define ide_scsi_devset_set(name, field) \ +static int set_##name(ide_drive_t *drive, int arg) \ +{ \ + idescsi_scsi_t *scsi = drive_to_idescsi(drive); \ + scsi->field = arg; \ + return 0; \ +} + +#define ide_scsi_devset_rw(_name, _min, _max, _field) \ +ide_scsi_devset_get(_name, _field); \ +ide_scsi_devset_set(_name, _field); \ +IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) + +ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); +ide_devset_rw(bios_head, 0, 255, bios_head); +ide_devset_rw(bios_sect, 0, 63, bios_sect); + +ide_scsi_devset_rw(transform, 0, 3, transform); +ide_scsi_devset_rw(log, 0, 1, log); + +static const struct ide_devset *idescsi_settings[] = { + &ide_devset_bios_cyl, + &ide_devset_bios_head, + &ide_devset_bios_sect, + &ide_devset_log, + &ide_devset_transform, + NULL +}; #endif /* @@ -461,7 +481,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) drive->pc_callback = ide_scsi_callback; ide_proc_register_driver(drive, scsi->driver); - idescsi_add_settings(drive); } static void ide_scsi_remove(ide_drive_t *drive) @@ -509,6 +528,7 @@ static ide_driver_t idescsi_driver = { .error = idescsi_atapi_error, #ifdef CONFIG_IDE_PROC_FS .proc = idescsi_proc, + .settings = idescsi_settings, #endif }; diff --git a/include/linux/ide.h b/include/linux/ide.h index ad09e7c81ae..4667ec8aeeb 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -304,8 +304,8 @@ typedef enum { ide_started, /* a drive operation was started, handler was set */ } ide_startstop_t; +struct ide_devset; struct ide_driver_s; -struct ide_settings_s; #ifdef CONFIG_BLK_DEV_IDEACPI struct ide_acpi_drive_link; @@ -384,7 +384,7 @@ struct ide_drive_s { u16 *id; /* identification info */ #ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ - struct ide_settings_s *settings;/* /proc/ide/ drive settings */ + const struct ide_devset **settings; /* /proc/ide/ drive settings */ #endif struct hwif_s *hwif; /* actually (ide_hwif_t *) */ @@ -396,16 +396,16 @@ struct ide_drive_s { special_t special; /* special action flags */ select_t select; /* basic drive/head select reg value */ - u8 keep_settings; /* restore settings after drive reset */ - u8 using_dma; /* disk is using dma for read/write */ u8 retry_pio; /* retrying dma capable host in pio */ u8 state; /* retry state */ u8 waiting_for_dma; /* dma currently in progress */ - u8 unmask; /* okay to unmask other irqs */ - u8 noflush; /* don't attempt flushes */ - u8 dsc_overlap; /* DSC overlap */ - u8 nice1; /* give potential excess bandwidth */ + unsigned keep_settings : 1; /* restore settings after drive reset */ + unsigned using_dma : 1; /* disk is using dma for read/write */ + unsigned unmask : 1; /* okay to unmask other irqs */ + unsigned noflush : 1; /* don't attempt flushes */ + unsigned dsc_overlap : 1; /* DSC overlap */ + unsigned nice1 : 1; /* give potential excess bandwidth */ unsigned present : 1; /* drive is physically present */ unsigned dead : 1; /* device ejected hint */ unsigned id_read : 1; /* 1=id read from disk 0 = synthetic */ @@ -423,14 +423,15 @@ struct ide_drive_s { unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ unsigned post_reset : 1; unsigned udma33_warned : 1; + unsigned addressing : 2; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */ + unsigned wcache : 1; /* status of write cache */ + unsigned nowerr : 1; /* used for ignoring ATA_DF */ - u8 addressing; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */ u8 quirk_list; /* considered quirky, set for a specific host */ u8 init_speed; /* transfer rate set at boot */ u8 current_speed; /* current transfer rate set */ u8 desired_speed; /* desired transfer rate set */ u8 dn; /* now wide spread use */ - u8 wcache; /* status of write cache */ u8 acoustic; /* acoustic management */ u8 media; /* disk, cdrom, tape, floppy, ... */ u8 ready_stat; /* min status value for drive ready */ @@ -439,7 +440,6 @@ struct ide_drive_s { u8 tune_req; /* requested drive tuning setting */ u8 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ u8 bad_wstat; /* used for ignoring ATA_DF */ - u8 nowerr; /* used for ignoring ATA_DF */ u8 head; /* "real" number of heads */ u8 sect; /* "real" sectors per track */ u8 bios_head; /* BIOS/fdisk/LILO number of heads */ @@ -687,12 +687,29 @@ typedef struct ide_driver_s ide_driver_t; extern struct mutex ide_setting_mtx; +int get_io_32bit(ide_drive_t *); int set_io_32bit(ide_drive_t *, int); +int get_ksettings(ide_drive_t *); int set_ksettings(ide_drive_t *, int); int set_pio_mode(ide_drive_t *, int); +int get_unmaskirq(ide_drive_t *); int set_unmaskirq(ide_drive_t *, int); +int get_using_dma(ide_drive_t *); int set_using_dma(ide_drive_t *, int); +#define ide_devset_get(name, field) \ +int get_##name(ide_drive_t *drive) \ +{ \ + return drive->field; \ +} + +#define ide_devset_set(name, field) \ +int set_##name(ide_drive_t *drive, int arg) \ +{ \ + drive->field = arg; \ + return 0; \ +} + /* ATAPI packet command flags */ enum { /* set when an error is considered normal - no retry (ide-tape) */ @@ -757,30 +774,53 @@ struct ide_atapi_pc { * configurable drive settings */ -#define TYPE_INT 0 -#define TYPE_BYTE 1 -#define TYPE_SHORT 2 +#define S_READ (1 << 0) +#define S_WRITE (1 << 1) +#define S_RW (S_READ | S_WRITE) +#define S_NOLOCK (1 << 2) -#define SETTING_READ (1 << 0) -#define SETTING_WRITE (1 << 1) -#define SETTING_RW (SETTING_READ | SETTING_WRITE) +struct ide_devset { + const char *name; + unsigned int flags; + int min, max; + int (*get)(ide_drive_t *); + int (*set)(ide_drive_t *, int); + int (*mulf)(ide_drive_t *); + int (*divf)(ide_drive_t *); +}; -typedef int (ide_procset_t)(ide_drive_t *, int); -typedef struct ide_settings_s { - char *name; - int rw; - int data_type; - int min; - int max; - int mul_factor; - int div_factor; - void *data; - ide_procset_t *set; - int auto_remove; - struct ide_settings_s *next; -} ide_settings_t; - -int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); +#define __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) { \ + .name = __stringify(_name), \ + .flags = _flags, \ + .min = _min, \ + .max = _max, \ + .get = _get, \ + .set = _set, \ + .mulf = _mulf, \ + .divf = _divf, \ +} + +#define __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) \ +static const struct ide_devset ide_devset_##_name = \ + __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) + +#define IDE_DEVSET(_name, _flags, _min, _max, _get, _set) \ +__IDE_DEVSET(_name, _flags, _min, _max, _get, _set, NULL, NULL) + +#define ide_devset_rw_nolock(_name, _min, _max, _func) \ +IDE_DEVSET(_name, S_RW | S_NOLOCK, _min, _max, get_##_func, set_##_func) + +#define ide_devset_w_nolock(_name, _min, _max, _func) \ +IDE_DEVSET(_name, S_WRITE | S_NOLOCK, _min, _max, NULL, set_##_func) + +#define ide_devset_rw(_name, _min, _max, _field) \ +static ide_devset_get(_name, _field); \ +static ide_devset_set(_name, _field); \ +IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) + +#define ide_devset_r(_name, _min, _max, _field) \ +ide_devset_get(_name, _field) \ +IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL) /* * /proc/ide interface @@ -801,8 +841,6 @@ void ide_proc_unregister_port(ide_hwif_t *); void ide_proc_register_driver(ide_drive_t *, ide_driver_t *); void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *); -void ide_add_generic_settings(ide_drive_t *); - read_proc_t proc_ide_read_capacity; read_proc_t proc_ide_read_geometry; @@ -830,7 +868,6 @@ static inline void ide_proc_unregister_device(ide_drive_t *drive) { ; } static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; } static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } -static inline void ide_add_generic_settings(ide_drive_t *drive) { ; } #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; #endif @@ -887,6 +924,7 @@ struct ide_driver_s { void (*shutdown)(ide_drive_t *); #ifdef CONFIG_IDE_PROC_FS ide_proc_entry_t *proc; + const struct ide_devset **settings; #endif }; -- GitLab From 151a670186a0f8441798f90c8701647adb7a1589 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:28 +0200 Subject: [PATCH 3800/5416] ide: remove SECTOR_WORDS define Just use SECTOR_SIZE instead. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 5 +++-- drivers/ide/ide-iops.c | 2 +- drivers/ide/ide-probe.c | 2 +- drivers/ide/ide-proc.c | 5 +++-- drivers/ide/ide-taskfile.c | 2 +- include/linux/ide.h | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 2e43ae15fb1..474070c1ddb 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -539,13 +539,14 @@ static int proc_idedisk_read_smart(char *page, char **start, off_t off, if (get_smart_data(drive, page, sub_cmd) == 0) { unsigned short *val = (unsigned short *) page; - char *out = ((char *)val) + (SECTOR_WORDS * 4); + char *out = (char *)val + SECTOR_SIZE; + page = out; do { out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); val += 1; - } while (i < (SECTOR_WORDS * 2)); + } while (i < SECTOR_SIZE / 2); len = out - page; } diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index ee44878e40d..6256c2df62c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -693,7 +693,7 @@ int ide_driveid_update(ide_drive_t *drive) } local_irq_save(flags); SELECT_MASK(drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (!id) { local_irq_restore(flags); return 0; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 62f7e1ef10c..be121ffcc1d 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -561,7 +561,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive) * Also note that 0 everywhere means "can't do X" */ - drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL); + drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); drive->id_read = 0; if(drive->id == NULL) { diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 5634b3971d2..6489c647be8 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -100,13 +100,14 @@ static int proc_ide_read_identify err = taskfile_lib_get_identify(drive, page); if (!err) { - char *out = ((char *)page) + (SECTOR_WORDS * 4); + char *out = (char *)page + SECTOR_SIZE; + page = out; do { out += sprintf(out, "%04x%c", le16_to_cpup(val), (++i & 7) ? ' ' : '\n'); val += 1; - } while (i < (SECTOR_WORDS * 2)); + } while (i < SECTOR_SIZE / 2); len = out - page; } } diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index b1fb815dbf6..7ffe9004a4d 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -768,7 +768,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) if (args[3]) { tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; - bufsize = SECTOR_WORDS * 4 * args[3]; + bufsize = SECTOR_SIZE * args[3]; buf = kzalloc(bufsize, GFP_KERNEL); if (buf == NULL) return -ENOMEM; diff --git a/include/linux/ide.h b/include/linux/ide.h index 4667ec8aeeb..4444b0884e5 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -126,7 +126,7 @@ struct ide_io_ports { #define PARTN_BITS 6 /* number of minor dev bits for partitions */ #define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */ #define SECTOR_SIZE 512 -#define SECTOR_WORDS (SECTOR_SIZE / 4) /* number of 32bit words per sector */ + #define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t))) /* -- GitLab From af5dfe8cf07b6f4fbd6b7d8ff1aeda718fdd0166 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:28 +0200 Subject: [PATCH 3801/5416] cmd640: add __set_prefetch_mode() Factor out the common code from check_prefetch() and set_prefetch_mode() to __set_prefetch_mode(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/cmd640.c | 42 +++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 5b756757e04..7f39cdb4141 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -374,6 +374,21 @@ static void cmd640_dump_regs(void) } #endif +static void __set_prefetch_mode(ide_drive_t *drive, int mode) +{ + if (mode) { /* want prefetch on? */ +#if CMD640_PREFETCH_MASKS + drive->no_unmask = 1; + drive->unmask = 0; +#endif + drive->no_io_32bit = 0; + } else { + drive->no_unmask = 0; + drive->no_io_32bit = 1; + drive->io_32bit = 0; + } +} + #ifndef CONFIG_BLK_DEV_CMD640_ENHANCED /* * Check whether prefetch is on for a drive, @@ -383,19 +398,10 @@ static void __init check_prefetch(ide_drive_t *drive, unsigned int index) { u8 b = get_cmd640_reg(prefetch_regs[index]); - if (b & prefetch_masks[index]) { /* is prefetch off? */ - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; - } else { -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; - } + __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1); } #else + /* * Sets prefetch mode for a drive. */ @@ -407,19 +413,11 @@ static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode) spin_lock_irqsave(&cmd640_lock, flags); b = __get_cmd640_reg(reg); - if (mode) { /* want prefetch on? */ -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; + __set_prefetch_mode(drive, mode); + if (mode) b &= ~prefetch_masks[index]; /* enable prefetch */ - } else { - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; + else b |= prefetch_masks[index]; /* disable prefetch */ - } __put_cmd640_reg(reg, b); spin_unlock_irqrestore(&cmd640_lock, flags); } -- GitLab From ebc6be520673f65aef188abde43972f9cd2162e9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:29 +0200 Subject: [PATCH 3802/5416] ide: remove read-only ->atapi_overlap field from ide_drive_t Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 1 - include/linux/ide.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index eb64e942f58..5b3bfc78dcd 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -585,7 +585,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device return ide_get_identity_ioctl(drive, cmd, arg); case HDIO_GET_NICE: return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | - drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | drive->nice1 << IDE_NICE_1, (long __user *) arg); #ifdef CONFIG_IDE_TASK_IOCTL diff --git a/include/linux/ide.h b/include/linux/ide.h index 4444b0884e5..9cb935f2e7c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -415,7 +415,6 @@ struct ide_drive_s { unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */ unsigned no_unmask : 1; /* disallow setting unmask bit */ unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ - unsigned atapi_overlap : 1; /* ATAPI overlap (not supported) */ unsigned doorlocking : 1; /* for removable only: door lock/unlock works */ unsigned nodma : 1; /* disallow DMA */ unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ -- GitLab From 02d599a365d04658bc9ea71762ed17c895079927 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:29 +0200 Subject: [PATCH 3803/5416] ide: remove ->supports_dsc_overlap field from ide_driver_t * Use drive->media and drive->scsi to check if ->dsc_overlap can be set by HDIO_SET_NICE ioctl in generic_ide_ioctl(). * Remove unused ->supports_dsc_overlap field from ide_driver_t. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 1 - drivers/ide/ide-disk.c | 1 - drivers/ide/ide-floppy.c | 1 - drivers/ide/ide-tape.c | 1 - drivers/ide/ide.c | 11 +++++------ drivers/scsi/ide-scsi.c | 1 - include/linux/ide.h | 1 - 7 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 1f565232648..7ea90de5505 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1969,7 +1969,6 @@ static ide_driver_t ide_cdrom_driver = { .remove = ide_cd_remove, .version = IDECD_VERSION, .media = ide_cdrom, - .supports_dsc_overlap = 1, .do_request = ide_cd_do_request, .end_request = ide_end_request, .error = __ide_error, diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 474070c1ddb..08f47cb1342 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -980,7 +980,6 @@ static ide_driver_t idedisk_driver = { .shutdown = ide_device_shutdown, .version = IDEDISK_VERSION, .media = ide_disk, - .supports_dsc_overlap = 0, .do_request = ide_do_rw_disk, .end_request = ide_end_request, .error = __ide_error, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 673644fdb6f..de8d42b3f69 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1130,7 +1130,6 @@ static ide_driver_t idefloppy_driver = { .remove = ide_floppy_remove, .version = IDEFLOPPY_VERSION, .media = ide_floppy, - .supports_dsc_overlap = 0, .do_request = idefloppy_do_request, .end_request = idefloppy_end_request, .error = __ide_error, diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7037accb058..1fc1c2a6888 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2607,7 +2607,6 @@ static ide_driver_t idetape_driver = { .remove = ide_tape_remove, .version = IDETAPE_VERSION, .media = ide_tape, - .supports_dsc_overlap = 1, .do_request = idetape_do_request, .end_request = idetape_end_request, .error = __ide_error, diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 5b3bfc78dcd..4d0c661e78a 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -562,7 +562,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device unsigned int cmd, unsigned long arg) { unsigned long flags; - ide_driver_t *drv; int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int); switch (cmd) { @@ -612,12 +611,12 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - drv = *(ide_driver_t **)bdev->bd_disk->private_data; - if (drive->dsc_overlap && !drv->supports_dsc_overlap) { - drive->dsc_overlap = 0; + if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && + (drive->media == ide_disk || + drive->media == ide_floppy || + drive->scsi)) return -EPERM; - } + drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; drive->nice1 = (arg >> IDE_NICE_1) & 1; return 0; case HDIO_DRIVE_RESET: diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 65cf84b222c..a2d003c5e85 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -522,7 +522,6 @@ static ide_driver_t idescsi_driver = { .remove = ide_scsi_remove, .version = IDESCSI_VERSION, .media = ide_scsi, - .supports_dsc_overlap = 0, .do_request = idescsi_do_request, .end_request = idescsi_end_request, .error = idescsi_atapi_error, diff --git a/include/linux/ide.h b/include/linux/ide.h index 9cb935f2e7c..e5622bb5a4a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -912,7 +912,6 @@ enum { struct ide_driver_s { const char *version; u8 media; - unsigned supports_dsc_overlap : 1; ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t); int (*end_request)(ide_drive_t *, int, int); ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); -- GitLab From 9fa295e12d490fd571c614b221defaa9212c20dc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:29 +0200 Subject: [PATCH 3804/5416] ide: factor out HDIO_*_NICE ioctl handling to ide_*_nice_ioctl() Factor out HDIO_{GET,SET}_NICE ioctl handling from generic_ide_ioctl() to ide_{get,set}_nice_ioctl(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 4d0c661e78a..12618d2aed2 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -558,6 +558,28 @@ out: return rc; } +static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) +{ + return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) | + (drive->nice1 << IDE_NICE_1), (long __user *)arg); +} + +static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) +{ + if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) + return -EPERM; + + if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && + (drive->media == ide_disk || drive->media == ide_floppy || + drive->scsi)) + return -EPERM; + + drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; + drive->nice1 = (arg >> IDE_NICE_1) & 1; + + return 0; +} + int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { @@ -583,9 +605,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device return -EINVAL; return ide_get_identity_ioctl(drive, cmd, arg); case HDIO_GET_NICE: - return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | - drive->nice1 << IDE_NICE_1, - (long __user *) arg); + return ide_get_nice_ioctl(drive, arg); #ifdef CONFIG_IDE_TASK_IOCTL case HDIO_DRIVE_TASKFILE: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) @@ -608,17 +628,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device return -EACCES; return ide_task_ioctl(drive, cmd, arg); case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) - return -EPERM; - if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && - (drive->media == ide_disk || - drive->media == ide_floppy || - drive->scsi)) - return -EPERM; - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - drive->nice1 = (arg >> IDE_NICE_1) & 1; - return 0; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return ide_set_nice_ioctl(drive, arg); case HDIO_DRIVE_RESET: if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- GitLab From 5d5870f0a26e2304c4a82592870c5bc88017f7c9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:29 +0200 Subject: [PATCH 3805/5416] ide: ide_dev_has_iordy() -> ata_id_has_iordy() * Remove (id[ATA_ID_FIELD_VALID] & 2) check from ide_dev_has_iordy() (it is for validity of words 64-70, IORDY is in word 49). * ide_dev_has_iordy() -> ata_id_has_iordy() Cc: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/sl82c105.c | 2 +- include/linux/ide.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 61a006cb474..8cc4e137c60 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -61,7 +61,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) if (cmd_off == 0) cmd_off = 1; - if (pio > 2 || ide_dev_has_iordy(drive->id)) + if (pio > 2 || ata_id_has_iordy(drive->id)) iordy = 0x40; return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; diff --git a/include/linux/ide.h b/include/linux/ide.h index e5622bb5a4a..27829c13bef 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1382,11 +1382,6 @@ const char *ide_xfer_verbose(u8 mode); extern void ide_toggle_bounce(ide_drive_t *drive, int on); extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); -static inline int ide_dev_has_iordy(u16 *id) -{ - return ((id[ATA_ID_FIELD_VALID] & 2) && ata_id_has_iordy(id)) ? 1 : 0; -} - static inline int ide_dev_is_sata(u16 *id) { /* -- GitLab From 367d7e78dd48cf6ad35182a99d97abb5486e040e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:30 +0200 Subject: [PATCH 3806/5416] ide: ide_dev_is_sata() -> ata_id_is_sata() * Use optimized ATA version check from Sergei in ata_id_is_sata(). * ide_dev_is_sata() -> ata_id_is_sata() Cc: Jeff Garzik Cc: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- drivers/ide/pci/hpt366.c | 4 ++-- include/linux/ata.h | 10 +++++++++- include/linux/ide.h | 13 ------------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 6256c2df62c..0a2fd3b37ac 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -630,7 +630,7 @@ u8 eighty_ninty_three (ide_drive_t *drive) printk(KERN_DEBUG "%s: skipping word 93 validity check\n", drive->name); - if (ide_dev_is_sata(id) && !ivb) + if (ata_id_is_sata(id) && !ivb) return 1; if (hwif->cbl != ATA_CBL_PATA80 && !ivb) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index d706eb6b8ac..9056e3acc78 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -654,7 +654,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) case HPT372A: case HPT372N: case HPT374 : - if (ide_dev_is_sata(drive->id)) + if (ata_id_is_sata(drive->id)) mask &= ~0x0e; /* Fall thru */ default: @@ -674,7 +674,7 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive) case HPT372A: case HPT372N: case HPT374 : - if (ide_dev_is_sata(drive->id)) + if (ata_id_is_sata(drive->id)) return 0x00; /* Fall thru */ default: diff --git a/include/linux/ata.h b/include/linux/ata.h index be00973d1a8..d28aad991c7 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -645,7 +645,15 @@ static inline unsigned int ata_id_major_version(const u16 *id) static inline int ata_id_is_sata(const u16 *id) { - return ata_id_major_version(id) >= 5 && id[ATA_ID_HW_CONFIG] == 0; + /* + * See if word 93 is 0 AND drive is at least ATA-5 compatible + * verifying that word 80 by casting it to a signed type -- + * this trick allows us to filter out the reserved values of + * 0x0000 and 0xffff along with the earlier ATA revisions... + */ + if (id[ATA_ID_HW_CONFIG] == 0 && (short)id[ATA_ID_MAJOR_VER] >= 0x0020) + return 1; + return 0; } static inline int ata_id_has_tpm(const u16 *id) diff --git a/include/linux/ide.h b/include/linux/ide.h index 27829c13bef..87b5b5d3953 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1382,19 +1382,6 @@ const char *ide_xfer_verbose(u8 mode); extern void ide_toggle_bounce(ide_drive_t *drive, int on); extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); -static inline int ide_dev_is_sata(u16 *id) -{ - /* - * See if word 93 is 0 AND drive is at least ATA-5 compatible - * verifying that word 80 by casting it to a signed type -- - * this trick allows us to filter out the reserved values of - * 0x0000 and 0xffff along with the earlier ATA revisions... - */ - if (id[ATA_ID_HW_CONFIG] == 0 && (short)id[ATA_ID_MAJOR_VER] >= 0x0020) - return 1; - return 0; -} - u64 ide_get_lba_addr(struct ide_taskfile *, int); u8 ide_dump_status(ide_drive_t *, const char *, u8); -- GitLab From 942dcd85bf8edf38cdc3745306ca250684d99a61 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:30 +0200 Subject: [PATCH 3807/5416] ide: idedisk_supports_lba48() -> ata_id_lba48_enabled() * Add ata_id_lba48_enabled() inline helper to . * idedisk_supports_lba48() -> ata_id_lba48_enabled() The latter one also checks validity of words 83 & 86. Cc: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 21 ++++++--------------- include/linux/ata.h | 9 +++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 08f47cb1342..8f49bc0ecbf 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -383,16 +383,6 @@ static unsigned long long sectors_to_MB(unsigned long long n) return n; } -/* - * The same here. - */ -static inline int idedisk_supports_lba48(const u16 *id) -{ - return (id[ATA_ID_COMMAND_SET_2] & 0x0400) && - (id[ATA_ID_CFS_ENABLE_2] & 0x0400) && - ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); -} - /* * Some disks report total number of sectors instead of * maximum sector address. We list them here. @@ -407,7 +397,7 @@ static const struct drive_list_entry hpa_list[] = { static void idedisk_check_hpa(ide_drive_t *drive) { unsigned long long capacity, set_max; - int lba48 = idedisk_supports_lba48(drive->id); + int lba48 = ata_id_lba48_enabled(drive->id); capacity = drive->capacity64; @@ -450,7 +440,7 @@ static void init_idedisk_capacity(ide_drive_t *drive) */ int hpa = ata_id_hpa_enabled(id); - if (idedisk_supports_lba48(id)) { + if (ata_id_lba48_enabled(id)) { /* drive speaks 48-bit LBA */ drive->select.b.lba = 1; drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); @@ -754,9 +744,11 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) return 0; - if (!idedisk_supports_lba48(drive->id)) + if (ata_id_lba48_enabled(drive->id) == 0) return -EIO; + drive->addressing = arg; + return 0; } @@ -853,8 +845,7 @@ static void idedisk_setup(ide_drive_t *drive) capacity = idedisk_capacity(drive); if (!drive->forced_geom) { - - if (idedisk_supports_lba48(drive->id)) { + if (ata_id_lba48_enabled(drive->id)) { /* compatibility */ drive->bios_sect = 63; drive->bios_head = 255; diff --git a/include/linux/ata.h b/include/linux/ata.h index d28aad991c7..8162257b474 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -574,6 +574,15 @@ static inline int ata_id_has_lba48(const u16 *id) return id[ATA_ID_COMMAND_SET_2] & (1 << 10); } +static inline int ata_id_lba48_enabled(const u16 *id) +{ + if (ata_id_has_lba48(id) == 0) + return 0; + if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000) + return 0; + return id[ATA_ID_CFS_ENABLE_2] & (1 << 10); +} + static inline int ata_id_hpa_enabled(const u16 *id) { /* Yes children, word 83 valid bits cover word 82 data */ -- GitLab From 1a4e4d4d2cceb72be70526a485914abd638c7de1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:30 +0200 Subject: [PATCH 3808/5416] ide: check only for CACHE FLUSH command support in ide_id_has_flush_cache() All devices supporting CACHE FLUSH EXT command should also support CACHE FLUSH command so it is sufficient to check only for CACHE FLUSH in ide_id_has_flush_cache(). Signed-off-by: Bartlomiej Zolnierkiewicz --- include/linux/ide.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ide.h b/include/linux/ide.h index 87b5b5d3953..6e22cd20dd8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1453,8 +1453,8 @@ extern struct mutex ide_cfg_mtx; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; -/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ -#define ide_id_has_flush_cache(id) ((id)[ATA_ID_CFS_ENABLE_2] & 0x3000) +/* check if CACHE FLUSH command is supported (as defined in ATA-6) */ +#define ide_id_has_flush_cache(id) ((id)[ATA_ID_CFS_ENABLE_2] & 0x1000) /* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ #define ide_id_has_flush_cache_ext(id) \ -- GitLab From 4b58f17d7c45a8e5f4acda641bec388398b9c0fa Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:30 +0200 Subject: [PATCH 3809/5416] ide: ide_id_has_flush_cache() -> ata_id_flush_enabled() * Add ata_id_flush_enabled() inline helper to . * ide_id_has_flush_cache() -> ata_id_flush_enabled() The latter one also checks if the command is marked as supported in word 83 and validity of words 83 & 86. Cc: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 6 +++--- drivers/ide/ide-io.c | 2 +- include/linux/ata.h | 9 +++++++++ include/linux/ide.h | 3 --- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 8f49bc0ecbf..7b24dff1746 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -651,7 +651,7 @@ static void update_ordered(ide_drive_t *drive) * not available so we don't need to recheck that. */ capacity = idedisk_capacity(drive); - barrier = ide_id_has_flush_cache(id) && !drive->noflush && + barrier = ata_id_flush_enabled(id) && !drive->noflush && (drive->addressing == 0 || capacity <= (1ULL << 28) || ide_id_has_flush_cache_ext(id)); @@ -678,7 +678,7 @@ static int set_wcache(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1) return -EINVAL; - if (ide_id_has_flush_cache(drive->id)) { + if (ata_id_flush_enabled(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); args.tf.feature = arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF; @@ -886,7 +886,7 @@ static void idedisk_setup(ide_drive_t *drive) static void ide_cacheflush_p(ide_drive_t *drive) { - if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) + if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0) return; if (do_idedisk_flushcache(drive)) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 99e0bbca3ac..c1596178fca 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -184,7 +184,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * if (drive->media != ide_disk) break; /* Not supported? Switch to next step now. */ - if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { + if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0) { ide_complete_power_step(drive, rq, 0, 0); return ide_stopped; } diff --git a/include/linux/ata.h b/include/linux/ata.h index 8162257b474..921cf0fc337 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -558,6 +558,15 @@ static inline int ata_id_has_flush(const u16 *id) return id[ATA_ID_COMMAND_SET_2] & (1 << 12); } +static inline int ata_id_flush_enabled(const u16 *id) +{ + if (ata_id_has_flush(id) == 0) + return 0; + if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000) + return 0; + return id[ATA_ID_CFS_ENABLE_2] & (1 << 12); +} + static inline int ata_id_has_flush_ext(const u16 *id) { if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000) diff --git a/include/linux/ide.h b/include/linux/ide.h index 6e22cd20dd8..d2213d7cc4c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1453,9 +1453,6 @@ extern struct mutex ide_cfg_mtx; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; -/* check if CACHE FLUSH command is supported (as defined in ATA-6) */ -#define ide_id_has_flush_cache(id) ((id)[ATA_ID_CFS_ENABLE_2] & 0x1000) - /* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ #define ide_id_has_flush_cache_ext(id) \ (((id)[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400) -- GitLab From ff2779b568e70822e0ef2cc7afeeefbe7c607652 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:31 +0200 Subject: [PATCH 3810/5416] ide: ide_id_has_flush_cache_ext() -> ata_id_flush_ext_enabled() * Add ata_id_flush_ext_enabled() inline helper to . * ide_id_has_flush_cache_ext() -> ata_id_flush_ext_enabled() The latter one also checks if the command is marked as supported in word 83 and validity of words 83 & 86. Cc: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 6 +++--- drivers/ide/ide-io.c | 2 +- include/linux/ata.h | 13 +++++++++++++ include/linux/ide.h | 4 ---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7b24dff1746..587d5aac7d5 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -576,7 +576,7 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) BUG_ON(task == NULL); memset(task, 0, sizeof(*task)); - if (ide_id_has_flush_cache_ext(drive->id) && + if (ata_id_flush_ext_enabled(drive->id) && (drive->capacity64 >= (1UL << 28))) task->tf.command = ATA_CMD_FLUSH_EXT; else @@ -653,7 +653,7 @@ static void update_ordered(ide_drive_t *drive) capacity = idedisk_capacity(drive); barrier = ata_id_flush_enabled(id) && !drive->noflush && (drive->addressing == 0 || capacity <= (1ULL << 28) || - ide_id_has_flush_cache_ext(id)); + ata_id_flush_ext_enabled(id)); printk(KERN_INFO "%s: cache flushes %ssupported\n", drive->name, barrier ? "" : "not "); @@ -699,7 +699,7 @@ static int do_idedisk_flushcache(ide_drive_t *drive) ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); - if (ide_id_has_flush_cache_ext(drive->id)) + if (ata_id_flush_ext_enabled(drive->id)) args.tf.command = ATA_CMD_FLUSH_EXT; else args.tf.command = ATA_CMD_FLUSH; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c1596178fca..ec6664b0d3a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -188,7 +188,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * ide_complete_power_step(drive, rq, 0, 0); return ide_stopped; } - if (ide_id_has_flush_cache_ext(drive->id)) + if (ata_id_flush_ext_enabled(drive->id)) args->tf.command = ATA_CMD_FLUSH_EXT; else args->tf.command = ATA_CMD_FLUSH; diff --git a/include/linux/ata.h b/include/linux/ata.h index 921cf0fc337..81d9adeb819 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -574,6 +574,19 @@ static inline int ata_id_has_flush_ext(const u16 *id) return id[ATA_ID_COMMAND_SET_2] & (1 << 13); } +static inline int ata_id_flush_ext_enabled(const u16 *id) +{ + if (ata_id_has_flush_ext(id) == 0) + return 0; + if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000) + return 0; + /* + * some Maxtor disks have bit 13 defined incorrectly + * so check bit 10 too + */ + return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400; +} + static inline int ata_id_has_lba48(const u16 *id) { if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000) diff --git a/include/linux/ide.h b/include/linux/ide.h index d2213d7cc4c..432eb98f7fe 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1453,10 +1453,6 @@ extern struct mutex ide_cfg_mtx; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; -/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ -#define ide_id_has_flush_cache_ext(id) \ - (((id)[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400) - static inline void ide_dump_identify(u8 *id) { print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 2, id, 512, 0); -- GitLab From 718c72e83da295efc9c8625b6f380ef10352d955 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:31 +0200 Subject: [PATCH 3811/5416] ide: use ata_id_is_cfa() Use ata_id_is_cfa() in do_identify() instead of open-coding check for CompactFlash devices (the inline helper also takes care of detecting CFs advertising themselves as ATA disks). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index be121ffcc1d..e526f496714 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -116,7 +116,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ide_hwif_t *hwif = HWIF(drive); u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; - int bswap = 1; + int bswap = 1, is_cfa; /* read 512 bytes of id info */ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); @@ -212,17 +212,15 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) * Not an ATAPI device: looks like a "regular" hard disk */ - /* - * 0x848a = CompactFlash device - * These are *not* removable in Linux definition of the term - */ - if (id[ATA_ID_CONFIG] != 0x848a && (id[ATA_ID_CONFIG] & (1 << 7))) + is_cfa = ata_id_is_cfa(id); + + /* CF devices are *not* removable in Linux definition of the term */ + if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) drive->removable = 1; drive->media = ide_disk; - printk(KERN_CONT "%s DISK drive\n", - (id[ATA_ID_CONFIG] == 0x848a) ? "CFA" : "ATA"); + printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA"); return; -- GitLab From 93734a234447a3c091f76d76f7351af9d4dde518 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:31 +0200 Subject: [PATCH 3812/5416] ide: ide_id_to_hd_driveid() -> ata_id_to_hd_driveid() Rename ide_id_to_hd_driveid() to ata_id_to_hd_driveid() and move it to . Cc: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 22 +--------------------- include/linux/ata.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 12618d2aed2..f42de5fe9bc 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -509,26 +509,6 @@ static int generic_drive_reset(ide_drive_t *drive) return ret; } -static inline void ide_id_to_hd_driveid(u16 *id) -{ -#ifdef __BIG_ENDIAN - /* accessed in struct hd_driveid as 8-bit values */ - id[ATA_ID_MAX_MULTSECT] = __cpu_to_le16(id[ATA_ID_MAX_MULTSECT]); - id[ATA_ID_CAPABILITY] = __cpu_to_le16(id[ATA_ID_CAPABILITY]); - id[ATA_ID_OLD_PIO_MODES] = __cpu_to_le16(id[ATA_ID_OLD_PIO_MODES]); - id[ATA_ID_OLD_DMA_MODES] = __cpu_to_le16(id[ATA_ID_OLD_DMA_MODES]); - id[ATA_ID_MULTSECT] = __cpu_to_le16(id[ATA_ID_MULTSECT]); - - /* as 32-bit values */ - *(u32 *)&id[ATA_ID_LBA_CAPACITY] = ata_id_u32(id, ATA_ID_LBA_CAPACITY); - *(u32 *)&id[ATA_ID_SPG] = ata_id_u32(id, ATA_ID_SPG); - - /* as 64-bit value */ - *(u64 *)&id[ATA_ID_LBA_CAPACITY_2] = - ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); -#endif -} - static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg) { @@ -548,7 +528,7 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, } memcpy(id, drive->id, size); - ide_id_to_hd_driveid(id); + ata_id_to_hd_driveid(id); if (copy_to_user((void __user *)arg, id, size)) rc = -EFAULT; diff --git a/include/linux/ata.h b/include/linux/ata.h index 81d9adeb819..4c3f5007003 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -30,6 +30,7 @@ #define __LINUX_ATA_H__ #include +#include /* defines only for the constants which don't work well as enums */ #define ATA_DMA_BOUNDARY 0xffffUL @@ -781,6 +782,26 @@ static inline int atapi_id_dmadir(const u16 *dev_id) return ata_id_major_version(dev_id) >= 7 && (dev_id[62] & 0x8000); } +static inline void ata_id_to_hd_driveid(u16 *id) +{ +#ifdef __BIG_ENDIAN + /* accessed in struct hd_driveid as 8-bit values */ + id[ATA_ID_MAX_MULTSECT] = __cpu_to_le16(id[ATA_ID_MAX_MULTSECT]); + id[ATA_ID_CAPABILITY] = __cpu_to_le16(id[ATA_ID_CAPABILITY]); + id[ATA_ID_OLD_PIO_MODES] = __cpu_to_le16(id[ATA_ID_OLD_PIO_MODES]); + id[ATA_ID_OLD_DMA_MODES] = __cpu_to_le16(id[ATA_ID_OLD_DMA_MODES]); + id[ATA_ID_MULTSECT] = __cpu_to_le16(id[ATA_ID_MULTSECT]); + + /* as 32-bit values */ + *(u32 *)&id[ATA_ID_LBA_CAPACITY] = ata_id_u32(id, ATA_ID_LBA_CAPACITY); + *(u32 *)&id[ATA_ID_SPG] = ata_id_u32(id, ATA_ID_SPG); + + /* as 64-bit value */ + *(u64 *)&id[ATA_ID_LBA_CAPACITY_2] = + ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); +#endif +} + static inline int is_multi_taskfile(struct ata_taskfile *tf) { return (tf->command == ATA_CMD_READ_MULTI) || -- GitLab From a02227c9774b3bff08c7f557d06247e0a03ac435 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:31 +0200 Subject: [PATCH 3813/5416] ide: lba_capacity_is_ok() -> ata_id_is_lba_capacity_ok() Rename lba_capacity_is_ok() to ata_id_is_lba_capacity_ok() and move it to (remove needless parens while at it). Cc: Jeff Garzik Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 52 +----------------------------------------- include/linux/ata.h | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 587d5aac7d5..43025c9d835 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -88,56 +88,6 @@ static void ide_disk_put(struct ide_disk_obj *idkp) mutex_unlock(&idedisk_ref_mutex); } -/* - * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" - * value for this drive (from its reported identification information). - * - * Returns: 1 if lba_capacity looks sensible - * 0 otherwise - * - * It is called only once for each drive. - */ -static int lba_capacity_is_ok(u16 *id) -{ - unsigned long lba_sects, chs_sects, head, tail; - - /* No non-LBA info .. so valid! */ - if (id[ATA_ID_CYLS] == 0) - return 1; - - lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY); - - /* - * The ATA spec tells large drives to return - * C/H/S = 16383/16/63 independent of their size. - * Some drives can be jumpered to use 15 heads instead of 16. - * Some drives can be jumpered to use 4092 cyls instead of 16383. - */ - if ((id[ATA_ID_CYLS] == 16383 || - (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) && - id[ATA_ID_SECTORS] == 63 && - (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) && - (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS])) - return 1; - - chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS]; - - /* perform a rough sanity check on lba_sects: within 10% is OK */ - if ((lba_sects - chs_sects) < chs_sects/10) - return 1; - - /* some drives have the word order reversed */ - head = ((lba_sects >> 16) & 0xffff); - tail = (lba_sects & 0xffff); - lba_sects = (head | (tail << 16)); - if ((lba_sects - chs_sects) < chs_sects/10) { - *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects); - return 1; /* lba_capacity is (now) good */ - } - - return 0; /* lba_capacity value may be bad */ -} - static const u8 ide_rw_cmds[] = { ATA_CMD_READ_MULTI, ATA_CMD_WRITE_MULTI, @@ -446,7 +396,7 @@ static void init_idedisk_capacity(ide_drive_t *drive) drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); if (hpa) idedisk_check_hpa(drive); - } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) { + } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) { /* drive speaks 28-bit LBA */ drive->select.b.lba = 1; drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY); diff --git a/include/linux/ata.h b/include/linux/ata.h index 4c3f5007003..a53318b8cbd 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -782,6 +782,56 @@ static inline int atapi_id_dmadir(const u16 *dev_id) return ata_id_major_version(dev_id) >= 7 && (dev_id[62] & 0x8000); } +/* + * ata_id_is_lba_capacity_ok() performs a sanity check on + * the claimed LBA capacity value for the device. + * + * Returns 1 if LBA capacity looks sensible, 0 otherwise. + * + * It is called only once for each device. + */ +static inline int ata_id_is_lba_capacity_ok(u16 *id) +{ + unsigned long lba_sects, chs_sects, head, tail; + + /* No non-LBA info .. so valid! */ + if (id[ATA_ID_CYLS] == 0) + return 1; + + lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY); + + /* + * The ATA spec tells large drives to return + * C/H/S = 16383/16/63 independent of their size. + * Some drives can be jumpered to use 15 heads instead of 16. + * Some drives can be jumpered to use 4092 cyls instead of 16383. + */ + if ((id[ATA_ID_CYLS] == 16383 || + (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) && + id[ATA_ID_SECTORS] == 63 && + (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) && + (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS])) + return 1; + + chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS]; + + /* perform a rough sanity check on lba_sects: within 10% is OK */ + if (lba_sects - chs_sects < chs_sects/10) + return 1; + + /* some drives have the word order reversed */ + head = (lba_sects >> 16) & 0xffff; + tail = lba_sects & 0xffff; + lba_sects = head | (tail << 16); + + if (lba_sects - chs_sects < chs_sects/10) { + *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects); + return 1; /* LBA capacity is (now) good */ + } + + return 0; /* LBA capacity value may be bad */ +} + static inline void ata_id_to_hd_driveid(u16 *id) { #ifdef __BIG_ENDIAN -- GitLab From 1785192b5310ee25165768f5bb80f13146788e3e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:32 +0200 Subject: [PATCH 3814/5416] hpt366: add hpt3xx_disable_fast_irq() helper * Factor out disabling of "fast interrupt" prediction from init_hwif_hpt366() to hpt3xx_disable_fast_irq() helper. * Use hpt3xx_disable_fast_irq() in ->init_chipset instead of ->init_hwif method. This is a preparation for adding proper PCI PM support. While at it: * Cache chip type in chip_type variable in hpt3xx_disable_fast_irq(). There should be no functional changes caused by this patch. Cc: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 58 +++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 9056e3acc78..ab6c217f104 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -971,6 +971,36 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f return 1; } +static void __devinit hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); + u8 chip_type = info->chip_type; + u8 new_mcr, old_mcr = 0; + + /* + * Disable the "fast interrupt" prediction. Don't hold off + * on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, mcr_addr + 1, &old_mcr); + + if (chip_type >= HPT374) + new_mcr = old_mcr & ~0x07; + else if (chip_type >= HPT370) { + new_mcr = old_mcr; + new_mcr &= ~0x02; +#ifdef HPT_DELAY_INTERRUPT + new_mcr &= ~0x01; +#else + new_mcr |= 0x01; +#endif + } else /* HPT366 and HPT368 */ + new_mcr = old_mcr & ~0x80; + + if (new_mcr != old_mcr) + pci_write_config_byte(dev, mcr_addr + 1, new_mcr); +} + static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev) { unsigned long io_base = pci_resource_start(dev, 4); @@ -1208,9 +1238,11 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev) * NOTE: This register is only writeable via I/O space. */ if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) - outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); + hpt3xx_disable_fast_irq(dev, 0x50); + hpt3xx_disable_fast_irq(dev, 0x54); + return dev->irq; } @@ -1264,7 +1296,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) struct hpt_info *info = hpt3xx_get_info(hwif->dev); int serialize = HPT_SERIALIZE_IO; u8 chip_type = info->chip_type; - u8 new_mcr, old_mcr = 0; /* Cache the channel's MISC. control registers' offset */ hwif->select_data = hwif->channel ? 0x54 : 0x50; @@ -1287,29 +1318,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) /* Serialize access to this device if needed */ if (serialize && hwif->mate) hwif->serialized = hwif->mate->serialized = 1; - - /* - * Disable the "fast interrupt" prediction. Don't hold off - * on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); - - if (info->chip_type >= HPT374) - new_mcr = old_mcr & ~0x07; - else if (info->chip_type >= HPT370) { - new_mcr = old_mcr; - new_mcr &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - new_mcr &= ~0x01; -#else - new_mcr |= 0x01; -#endif - } else /* HPT366 and HPT368 */ - new_mcr = old_mcr & ~0x80; - - if (new_mcr != old_mcr) - pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); } static int __devinit init_dma_hpt366(ide_hwif_t *hwif, -- GitLab From feb22b7f8e62b1b987a3a1dbad95af767a1df832 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:32 +0200 Subject: [PATCH 3815/5416] ide: add proper PCI PM support (v2) * Keep pointer to ->init_chipset method also in struct ide_host and set it in ide_host_alloc_all(). * Add ide_pci_suspend() and ide_pci_resume() helpers (default ->suspend and ->resume implementations). * ->init_chipset can no longer be marked __devinit. * Add proper PCI PM support to IDE PCI host drivers (rz1000.c and tc86c001.c are skipped for now since they need to be converted from using ->init_hwif to use ->init_chipset instead). v2: * Cleanup CONFIG_PM #ifdef-s per akpm's suggestion. Cc: Andrew Morton Cc: "Rafael J. Wysocki" Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 +++- drivers/ide/pci/aec62xx.c | 4 +++- drivers/ide/pci/alim15x3.c | 4 +++- drivers/ide/pci/amd74xx.c | 8 +++++--- drivers/ide/pci/atiixp.c | 2 ++ drivers/ide/pci/cmd64x.c | 4 +++- drivers/ide/pci/cs5520.c | 2 ++ drivers/ide/pci/cs5530.c | 4 +++- drivers/ide/pci/cs5535.c | 10 ++++++---- drivers/ide/pci/cy82c693.c | 4 +++- drivers/ide/pci/generic.c | 2 ++ drivers/ide/pci/hpt34x.c | 4 +++- drivers/ide/pci/hpt366.c | 8 +++++--- drivers/ide/pci/it8213.c | 2 ++ drivers/ide/pci/it821x.c | 6 ++++-- drivers/ide/pci/jmicron.c | 2 ++ drivers/ide/pci/ns87415.c | 2 ++ drivers/ide/pci/opti621.c | 2 ++ drivers/ide/pci/pdc202xx_new.c | 10 ++++++---- drivers/ide/pci/pdc202xx_old.c | 4 +++- drivers/ide/pci/piix.c | 4 +++- drivers/ide/pci/serverworks.c | 4 +++- drivers/ide/pci/siimage.c | 4 +++- drivers/ide/pci/sis5513.c | 4 +++- drivers/ide/pci/sl82c105.c | 4 +++- drivers/ide/pci/slc90e66.c | 2 ++ drivers/ide/pci/triflex.c | 2 ++ drivers/ide/pci/via82cxxx.c | 6 ++++-- drivers/ide/setup-pci.c | 33 +++++++++++++++++++++++++++++++++ include/linux/ide.h | 10 ++++++++++ 30 files changed, 130 insertions(+), 31 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e526f496714..06575a12b63 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1586,8 +1586,10 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, if (hws[0]) host->dev[0] = hws[0]->dev; - if (d) + if (d) { + host->init_chipset = d->init_chipset; host->host_flags = d->host_flags; + } return host; } diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index f65828da65d..e7475ba559c 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -139,7 +139,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); } -static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev) +static unsigned int init_chipset_aec62xx(struct pci_dev *dev) { /* These are necessary to get AEC6280 Macintosh cards to work */ if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || @@ -307,6 +307,8 @@ static struct pci_driver driver = { .id_table = aec62xx_pci_tbl, .probe = aec62xx_init_one, .remove = __devexit_p(aec62xx_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init aec62xx_ide_init(void) diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index ef41e2677a5..053c7526391 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -213,7 +213,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive) * appropriate also sets up the 1533 southbridge. */ -static unsigned int __devinit init_chipset_ali15x3(struct pci_dev *dev) +static unsigned int init_chipset_ali15x3(struct pci_dev *dev) { unsigned long flags; u8 tmpbyte; @@ -581,6 +581,8 @@ static struct pci_driver driver = { .id_table = alim15x3_pci_tbl, .probe = alim15x3_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init ali15x3_ide_init(void) diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 1e66a960a96..824471f91bf 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -112,13 +112,13 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio) amd_set_drive(drive, XFER_PIO_0 + pio); } -static void __devinit amd7409_cable_detect(struct pci_dev *dev) +static void amd7409_cable_detect(struct pci_dev *dev) { /* no host side cable detection */ amd_80w = 0x03; } -static void __devinit amd7411_cable_detect(struct pci_dev *dev) +static void amd7411_cable_detect(struct pci_dev *dev) { int i; u32 u = 0; @@ -140,7 +140,7 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev) * The initialization callback. Initialize drive independent registers. */ -static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev) +static unsigned int init_chipset_amd74xx(struct pci_dev *dev) { u8 t = 0, offset = amd_offset(dev); @@ -324,6 +324,8 @@ static struct pci_driver driver = { .id_table = amd74xx_pci_tbl, .probe = amd74xx_probe, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init amd74xx_ide_init(void) diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 86e3120cb7c..e4437034dd0 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -187,6 +187,8 @@ static struct pci_driver driver = { .id_table = atiixp_pci_tbl, .probe = atiixp_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init atiixp_ide_init(void) diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 13dfeab1d19..456dee18b66 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -331,7 +331,7 @@ static int cmd646_1_dma_end(ide_drive_t *drive) return (dma_stat & 7) != 4; } -static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev) +static unsigned int init_chipset_cmd64x(struct pci_dev *dev) { u8 mrdmode = 0; @@ -510,6 +510,8 @@ static struct pci_driver driver = { .id_table = cmd64x_pci_tbl, .probe = cmd64x_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init cmd64x_ide_init(void) diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 27163147896..d6341f7c414 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -149,6 +149,8 @@ static struct pci_driver driver = { .name = "Cyrix_IDE", .id_table = cs5520_pci_tbl, .probe = cs5520_init_one, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init cs5520_ide_init(void) diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index d60806bd7db..da42fa7e9f9 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -134,7 +134,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) * Initialize the cs5530 bridge for reliable IDE DMA operation. */ -static unsigned int __devinit init_chipset_cs5530(struct pci_dev *dev) +static unsigned int init_chipset_cs5530(struct pci_dev *dev) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; @@ -272,6 +272,8 @@ static struct pci_driver driver = { .id_table = cs5530_pci_tbl, .probe = cs5530_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init cs5530_ide_init(void) diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 707d2e18255..1e5bc59ea2f 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -193,10 +193,12 @@ static const struct pci_device_id cs5535_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl); static struct pci_driver driver = { - .name = "CS5535_IDE", - .id_table = cs5535_pci_tbl, - .probe = cs5535_init_one, - .remove = ide_pci_remove, + .name = "CS5535_IDE", + .id_table = cs5535_pci_tbl, + .probe = cs5535_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init cs5535_ide_init(void) diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index e6d8ee88d56..69820e9224d 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -332,7 +332,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) /* * this function is called during init and is used to setup the cy82c693 chip */ -static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev) +static unsigned int init_chipset_cy82c693(struct pci_dev *dev) { if (PCI_FUNC(dev->devfn) != 1) return 0; @@ -448,6 +448,8 @@ static struct pci_driver driver = { .id_table = cy82c693_pci_tbl, .probe = cy82c693_init_one, .remove = __devexit_p(cy82c693_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init cy82c693_ide_init(void) diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index bdc53986870..092b238cb25 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -171,6 +171,8 @@ static struct pci_driver driver = { .id_table = generic_pci_tbl, .probe = generic_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init generic_ide_init(void) diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 4f624899f44..644de29f8fe 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -78,7 +78,7 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio) */ #define HPT34X_PCI_INIT_REG 0x80 -static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev) +static unsigned int init_chipset_hpt34x(struct pci_dev *dev) { int i = 0; unsigned long hpt34xIoBase = pci_resource_start(dev, 4); @@ -171,6 +171,8 @@ static struct pci_driver driver = { .id_table = hpt34x_pci_tbl, .probe = hpt34x_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init hpt34x_ide_init(void) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index ab6c217f104..a194022b6a6 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -943,7 +943,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) * Perform a calibration cycle on the DPLL. * Returns 1 if this succeeds */ -static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) +static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) { u32 dpll = (f_high << 16) | f_low | 0x100; u8 scr2; @@ -971,7 +971,7 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f return 1; } -static void __devinit hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) +static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) { struct ide_host *host = pci_get_drvdata(dev); struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); @@ -1001,7 +1001,7 @@ static void __devinit hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) pci_write_config_byte(dev, mcr_addr + 1, new_mcr); } -static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev) +static unsigned int init_chipset_hpt366(struct pci_dev *dev) { unsigned long io_base = pci_resource_start(dev, 4); struct hpt_info *info = hpt3xx_get_info(&dev->dev); @@ -1627,6 +1627,8 @@ static struct pci_driver driver = { .id_table = hpt366_pci_tbl, .probe = hpt366_init_one, .remove = __devexit_p(hpt366_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init hpt366_ide_init(void) diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index a0e058a2abf..0954ccd08d6 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -194,6 +194,8 @@ static struct pci_driver driver = { .id_table = it8213_pci_tbl, .probe = it8213_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init it8213_ide_init(void) diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 0fdea7e91a7..46edd083b34 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -586,7 +586,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) hwif->mwdma_mask = ATA_MWDMA2; } -static void __devinit it8212_disable_raid(struct pci_dev *dev) +static void it8212_disable_raid(struct pci_dev *dev) { /* Reset local CPU, and set BIOS not ready */ pci_write_config_byte(dev, 0x5E, 0x01); @@ -603,7 +603,7 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } -static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev) +static unsigned int init_chipset_it821x(struct pci_dev *dev) { u8 conf; static char *mode[2] = { "pass through", "smart" }; @@ -685,6 +685,8 @@ static struct pci_driver driver = { .id_table = it821x_pci_tbl, .probe = it821x_init_one, .remove = __devexit_p(it821x_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init it821x_ide_init(void) diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index 4010b4a8dfb..acd64711064 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -154,6 +154,8 @@ static struct pci_driver driver = { .id_table = jmicron_pci_tbl, .probe = jmicron_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init jmicron_ide_init(void) diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index a482ade8e45..53bd645736d 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -339,6 +339,8 @@ static struct pci_driver driver = { .id_table = ns87415_pci_tbl, .probe = ns87415_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init ns87415_ide_init(void) diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index fefac2c174b..3de11ddcf86 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -225,6 +225,8 @@ static struct pci_driver driver = { .id_table = opti621_pci_tbl, .probe = opti621_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init opti621_ide_init(void) diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 73bd264fbf9..9fc59962553 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -226,7 +226,7 @@ static void pdcnew_reset(ide_drive_t *drive) * read_counter - Read the byte count registers * @dma_base: for the port address */ -static long __devinit read_counter(u32 dma_base) +static long read_counter(u32 dma_base) { u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; u8 cnt0, cnt1, cnt2, cnt3; @@ -266,7 +266,7 @@ static long __devinit read_counter(u32 dma_base) * @dma_base: for the port address * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. */ -static long __devinit detect_pll_input_clock(unsigned long dma_base) +static long detect_pll_input_clock(unsigned long dma_base) { struct timeval start_time, end_time; long start_count, end_count; @@ -309,7 +309,7 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base) } #ifdef CONFIG_PPC_PMAC -static void __devinit apple_kiwi_init(struct pci_dev *pdev) +static void apple_kiwi_init(struct pci_dev *pdev) { struct device_node *np = pci_device_to_OF_node(pdev); u8 conf; @@ -325,7 +325,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ -static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev) +static unsigned int init_chipset_pdcnew(struct pci_dev *dev) { const char *name = DRV_NAME; unsigned long dma_base = pci_resource_start(dev, 4); @@ -566,6 +566,8 @@ static struct pci_driver driver = { .id_table = pdc202new_pci_tbl, .probe = pdc202new_init_one, .remove = __devexit_p(pdc202new_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init pdc202new_ide_init(void) diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 8f0acb956c6..cb6d2a00c51 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -264,7 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive) ide_dma_timeout(drive); } -static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev) +static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) { unsigned long dmabase = pci_resource_start(dev, 4); u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; @@ -431,6 +431,8 @@ static struct pci_driver driver = { .id_table = pdc202xx_pci_tbl, .probe = pdc202xx_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init pdc202xx_ide_init(void) diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 13136dddb2b..a06c03f8e29 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -204,7 +204,7 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) * out to be nice and simple. */ -static unsigned int __devinit init_chipset_ich(struct pci_dev *dev) +static unsigned int init_chipset_ich(struct pci_dev *dev) { u32 extra = 0; @@ -449,6 +449,8 @@ static struct pci_driver driver = { .id_table = piix_pci_tbl, .probe = piix_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init piix_ide_init(void) diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index 5f79d284ff8..3dff2aea317 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -175,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, ultra_enable); } -static unsigned int __devinit init_chipset_svwks(struct pci_dev *dev) +static unsigned int init_chipset_svwks(struct pci_dev *dev) { unsigned int reg; u8 btr; @@ -448,6 +448,8 @@ static struct pci_driver driver = { .id_table = svwks_pci_tbl, .probe = svwks_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init svwks_ide_init(void) diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 874c8ca40ed..174a873b4c6 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -463,7 +463,7 @@ static void sil_sata_pre_reset(ide_drive_t *drive) * to 133 MHz clocking if the system isn't already set up to do it. */ -static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev) +static unsigned int init_chipset_siimage(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); void __iomem *ioaddr = host->host_priv; @@ -834,6 +834,8 @@ static struct pci_driver driver = { .id_table = siimage_pci_tbl, .probe = siimage_init_one, .remove = __devexit_p(siimage_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init siimage_ide_init(void) diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 56bfb245f1f..734dd41f1f6 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -447,7 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev) return chipset_family; } -static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev) +static unsigned int init_chipset_sis5513(struct pci_dev *dev) { /* Make general config ops here 1/ tell IDE channels to operate in Compatibility mode only @@ -610,6 +610,8 @@ static struct pci_driver driver = { .id_table = sis5513_pci_tbl, .probe = sis5513_init_one, .remove = __devexit_p(sis5513_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init sis5513_ide_init(void) diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 8cc4e137c60..37a6b7bdc04 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -271,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev) * channel 0 here at least, but channel 1 has to be enabled by * firmware or arch code. We still set both to 16 bits mode. */ -static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev) +static unsigned int init_chipset_sl82c105(struct pci_dev *dev) { u32 val; @@ -350,6 +350,8 @@ static struct pci_driver driver = { .id_table = sl82c105_pci_tbl, .probe = sl82c105_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init sl82c105_ide_init(void) diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index a31c6911442..a9551a13ac5 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -159,6 +159,8 @@ static struct pci_driver driver = { .id_table = slc90e66_pci_tbl, .probe = slc90e66_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init slc90e66_ide_init(void) diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index c980a7f3905..be8715dcee0 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -119,6 +119,8 @@ static struct pci_driver driver = { .id_table = triflex_pci_tbl, .probe = triflex_init_one, .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init triflex_ide_init(void) diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 9cb531dc905..acacdaab69c 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -215,7 +215,7 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa) /* * Check and handle 80-wire cable presence */ -static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u) +static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u) { int i; @@ -267,7 +267,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u) * and initialize its drive independent registers. */ -static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev) +static unsigned int init_chipset_via82cxxx(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); struct via82cxxx_dev *vdev = host->host_priv; @@ -492,6 +492,8 @@ static struct pci_driver driver = { .id_table = via_pci_tbl, .probe = via_init_one, .remove = __devexit_p(via_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init via_ide_init(void) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index a8e9e8a69a5..9f1f9163a13 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -659,3 +659,36 @@ void ide_pci_remove(struct pci_dev *dev) pci_disable_device(dev); } EXPORT_SYMBOL_GPL(ide_pci_remove); + +#ifdef CONFIG_PM +int ide_pci_suspend(struct pci_dev *dev, pm_message_t state) +{ + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + + return 0; +} +EXPORT_SYMBOL_GPL(ide_pci_suspend); + +int ide_pci_resume(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + int rc; + + pci_set_power_state(dev, PCI_D0); + + rc = pci_enable_device(dev); + if (rc) + return rc; + + pci_restore_state(dev); + pci_set_master(dev); + + if (host->init_chipset) + host->init_chipset(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(ide_pci_resume); +#endif diff --git a/include/linux/ide.h b/include/linux/ide.h index 432eb98f7fe..2c5d83ddaef 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_IDEACPI #include #endif @@ -639,6 +640,7 @@ struct ide_host { ide_hwif_t *ports[MAX_HWIFS]; unsigned int n_ports; struct device *dev[2]; + unsigned int (*init_chipset)(struct pci_dev *); unsigned long host_flags; void *host_priv; }; @@ -1264,6 +1266,14 @@ int ide_pci_init_two(struct pci_dev *, struct pci_dev *, const struct ide_port_info *, void *); void ide_pci_remove(struct pci_dev *); +#ifdef CONFIG_PM +int ide_pci_suspend(struct pci_dev *, pm_message_t); +int ide_pci_resume(struct pci_dev *); +#else +#define ide_pci_suspend NULL +#define ide_pci_resume NULL +#endif + void ide_map_sg(ide_drive_t *, struct request *); void ide_init_sg_cmd(ide_drive_t *, struct request *); -- GitLab From 9232c14bff36d65de254f34386c00b732c5b6099 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:33 +0200 Subject: [PATCH 3816/5416] ide: remove ->bus_state field from ide_hwif_t It is always set to BUSSTATE_ON. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 4 +--- include/linux/ide.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index f42de5fe9bc..f78e789ea5f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -96,8 +96,6 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) hwif->name[2] = 'e'; hwif->name[3] = '0' + index; - hwif->bus_state = BUSSTATE_ON; - init_completion(&hwif->gendev_rel_comp); hwif->tp_ops = &default_tp_ops; @@ -620,7 +618,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device case HDIO_GET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (put_user(HWIF(drive)->bus_state, (long __user *)arg)) + if (put_user(BUSSTATE_ON, (long __user *)arg)) return -EFAULT; return 0; diff --git a/include/linux/ide.h b/include/linux/ide.h index 2c5d83ddaef..42f39781af8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -562,7 +562,6 @@ typedef struct hwif_s { u8 major; /* our major number */ u8 index; /* 0 for ide0; 1 for ide1; ... */ u8 channel; /* for dual-port chips: 0=primary, 1=secondary */ - u8 bus_state; /* power state of the IDE bus */ u32 host_flags; -- GitLab From aa7687738af3332470e02ac1060f6c046d83c9a3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:33 +0200 Subject: [PATCH 3817/5416] ide: add ide_setting_ioctl() helper * Add struct ide_ioctl_devset representing ioctl device setting. * Add ide_setting_ioctl() helper for matching given ioctl and its parameters against table of ioctl device settings. * Convert ide_setting_ioctl() and idedisk_ioctl() to use ide_setting_ioctl(). * Un-export ide_setting_mtx. While at it: * {get,set}_lba_addressing() -> {get,set}_addressing() There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 59 +++++++++++++----------------------------- drivers/ide/ide.c | 53 +++++++++++++++++++++++-------------- include/linux/ide.h | 14 +++++++++- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 43025c9d835..11906347082 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -676,7 +676,7 @@ static int set_acoustic(ide_drive_t *drive, int arg) return 0; } -ide_devset_get(lba_addressing, addressing); +ide_devset_get(addressing, addressing); /* * drive->addressing: @@ -684,7 +684,7 @@ ide_devset_get(lba_addressing, addressing); * 1: 48-bit * 2: 48-bit capable doing 28-bit */ -static int set_lba_addressing(ide_drive_t *drive, int arg) +static int set_addressing(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 2) return -EINVAL; @@ -704,7 +704,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) #ifdef CONFIG_IDE_PROC_FS ide_devset_rw_nolock(acoustic, 0, 254, acoustic); -ide_devset_rw_nolock(address, 0, 2, lba_addressing); +ide_devset_rw_nolock(address, 0, 2, addressing); ide_devset_rw_nolock(multcount, 0, 16, multcount); ide_devset_rw_nolock(nowerr, 0, 1, nowerr); ide_devset_rw_nolock(wcache, 0, 1, wcache); @@ -753,7 +753,7 @@ static void idedisk_setup(ide_drive_t *drive) drive->doorlocking = 1; } - (void)set_lba_addressing(drive, 1); + (void)set_addressing(drive, 1); if (drive->addressing == 1) { int max_s = 2048; @@ -1000,51 +1000,28 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } +static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { +{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, get_addressing, set_addressing }, +{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, get_multcount, set_multcount }, +{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, get_nowerr, set_nowerr }, +{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, get_wcache, set_wcache }, +{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, get_acoustic, set_acoustic }, +{ 0 } +}; + static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long flags; struct block_device *bdev = inode->i_bdev; struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); ide_drive_t *drive = idkp->drive; - int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int); - - switch (cmd) { - case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val; - case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val; - case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val; - case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val; - case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val; - case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; - case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; - case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; - case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val; - case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; - } + int err; - return generic_ide_ioctl(drive, file, bdev, cmd, arg); + err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); + if (err != -EOPNOTSUPP) + return err; -read_val: - mutex_lock(&ide_setting_mtx); - spin_lock_irqsave(&ide_lock, flags); - err = getfunc(drive); - spin_unlock_irqrestore(&ide_lock, flags); - mutex_unlock(&ide_setting_mtx); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - mutex_lock(&ide_setting_mtx); - err = setfunc(drive, arg); - mutex_unlock(&ide_setting_mtx); - } - } - return err; + return generic_ide_ioctl(drive, file, bdev, cmd, arg); } static int idedisk_media_changed(struct gendisk *disk) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index f78e789ea5f..4910924abeb 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -250,8 +250,6 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) DEFINE_MUTEX(ide_setting_mtx); -EXPORT_SYMBOL_GPL(ide_setting_mtx); - /** * ide_spin_wait_hwgroup - wait for group * @drive: drive in the group @@ -558,23 +556,23 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return 0; } +static const struct ide_ioctl_devset ide_ioctl_settings[] = { +{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit }, +{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings }, +{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq }, +{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma }, +{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode }, +{ 0 } +}; + int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - unsigned long flags; - int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int); + int err; - switch (cmd) { - case HDIO_GET_32BIT: getfunc = get_io_32bit; goto read_val; - case HDIO_GET_KEEPSETTINGS: getfunc = get_ksettings; goto read_val; - case HDIO_GET_UNMASKINTR: getfunc = get_unmaskirq; goto read_val; - case HDIO_GET_DMA: getfunc = get_using_dma; goto read_val; - case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; - case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; - case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; - case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; - case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; - } + err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); + if (err != -EOPNOTSUPP) + return err; switch (cmd) { case HDIO_OBSOLETE_IDENTITY: @@ -629,11 +627,29 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device default: return -EINVAL; } +} +EXPORT_SYMBOL(generic_ide_ioctl); + +int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, + unsigned int cmd, unsigned long arg, + const struct ide_ioctl_devset *s) +{ + unsigned long flags; + int err = -EOPNOTSUPP; + + for (; s->get_ioctl; s++) { + if (s->get && s->get_ioctl == cmd) + goto read_val; + else if (s->set && s->set_ioctl == cmd) + goto set_val; + } + + return err; read_val: mutex_lock(&ide_setting_mtx); spin_lock_irqsave(&ide_lock, flags); - err = getfunc(drive); + err = s->get(drive); spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); return err >= 0 ? put_user(err, (long __user *)arg) : err; @@ -646,14 +662,13 @@ set_val: err = -EACCES; else { mutex_lock(&ide_setting_mtx); - err = setfunc(drive, arg); + err = s->set(drive, arg); mutex_unlock(&ide_setting_mtx); } } return err; } - -EXPORT_SYMBOL(generic_ide_ioctl); +EXPORT_SYMBOL_GPL(ide_setting_ioctl); /** * ide_device_get - get an additional reference to a ide_drive_t diff --git a/include/linux/ide.h b/include/linux/ide.h index 42f39781af8..64624b9b645 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -932,7 +932,19 @@ struct ide_driver_s { int ide_device_get(ide_drive_t *); void ide_device_put(ide_drive_t *); -int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); +struct ide_ioctl_devset { + unsigned int get_ioctl; + unsigned int set_ioctl; + + int (*get)(ide_drive_t *); + int (*set)(ide_drive_t *, int); +}; + +int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int, + unsigned long, const struct ide_ioctl_devset *); + +int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, + unsigned, unsigned long); extern int ide_vlb_clk; extern int ide_pci_clk; -- GitLab From 170dc5b085e688639aa2b7acd1b907e2e1c7a48a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:33 +0200 Subject: [PATCH 3818/5416] ide: cleanup generic_ide_ioctl() * Fix intendation for the main 'switch ()'. * 'switch ()' -> 'if ()' for HDIO_DRIVE_TASKFILE case. * Move HDIO_SET_NICE case under HDIO_GET_NICE one. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 97 ++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 52 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 4910924abeb..19181493e72 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -565,8 +565,9 @@ static const struct ide_ioctl_devset ide_ioctl_settings[] = { { 0 } }; -int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, - unsigned int cmd, unsigned long arg) +int generic_ide_ioctl(ide_drive_t *drive, struct file *file, + struct block_device *bdev, + unsigned int cmd, unsigned long arg) { int err; @@ -575,57 +576,49 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device return err; switch (cmd) { - case HDIO_OBSOLETE_IDENTITY: - case HDIO_GET_IDENTITY: - if (bdev != bdev->bd_contains) - return -EINVAL; - return ide_get_identity_ioctl(drive, cmd, arg); - case HDIO_GET_NICE: - return ide_get_nice_ioctl(drive, arg); -#ifdef CONFIG_IDE_TASK_IOCTL - case HDIO_DRIVE_TASKFILE: - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - switch(drive->media) { - case ide_disk: - return ide_taskfile_ioctl(drive, cmd, arg); - default: - return -ENOMSG; - } -#endif /* CONFIG_IDE_TASK_IOCTL */ - - case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - return ide_cmd_ioctl(drive, cmd, arg); - - case HDIO_DRIVE_TASK: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - return ide_task_ioctl(drive, cmd, arg); - case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return ide_set_nice_ioctl(drive, arg); - case HDIO_DRIVE_RESET: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - return generic_drive_reset(drive); - - case HDIO_GET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (put_user(BUSSTATE_ON, (long __user *)arg)) - return -EFAULT; - return 0; - - case HDIO_SET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return -EOPNOTSUPP; - default: + case HDIO_OBSOLETE_IDENTITY: + case HDIO_GET_IDENTITY: + if (bdev != bdev->bd_contains) return -EINVAL; + return ide_get_identity_ioctl(drive, cmd, arg); + case HDIO_GET_NICE: + return ide_get_nice_ioctl(drive, arg); + case HDIO_SET_NICE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return ide_set_nice_ioctl(drive, arg); +#ifdef CONFIG_IDE_TASK_IOCTL + case HDIO_DRIVE_TASKFILE: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + if (drive->media == ide_disk) + return ide_taskfile_ioctl(drive, cmd, arg); + return -ENOMSG; +#endif + case HDIO_DRIVE_CMD: + if (!capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_cmd_ioctl(drive, cmd, arg); + case HDIO_DRIVE_TASK: + if (!capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_task_ioctl(drive, cmd, arg); + case HDIO_DRIVE_RESET: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return generic_drive_reset(drive); + case HDIO_GET_BUSSTATE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (put_user(BUSSTATE_ON, (long __user *)arg)) + return -EFAULT; + return 0; + case HDIO_SET_BUSSTATE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return -EOPNOTSUPP; + default: + return -EINVAL; } } EXPORT_SYMBOL(generic_ide_ioctl); -- GitLab From 05236ea6df7419f0f37cf9603cfee265cfce5832 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:33 +0200 Subject: [PATCH 3819/5416] ide: move ioctls handling to ide-ioctls.c * Move ioctls handling to ide-ioctls.c (except HDIO_DRIVE_TASKFILE for now). * Make ide_{cmd,task}() static. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 4 +- drivers/ide/ide-ioctls.c | 289 +++++++++++++++++++++++++++++++++++++ drivers/ide/ide-taskfile.c | 109 -------------- drivers/ide/ide.c | 174 ---------------------- include/linux/ide.h | 2 - 5 files changed, 291 insertions(+), 287 deletions(-) create mode 100644 drivers/ide/ide-ioctls.c diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 64e0ecdc4ed..76a30d76338 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -4,8 +4,8 @@ EXTRA_CFLAGS += -Idrivers/ide -ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o \ - ide-pio-blacklist.o +ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ + ide-taskfile.o ide-pio-blacklist.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c new file mode 100644 index 00000000000..7a0d62e7286 --- /dev/null +++ b/drivers/ide/ide-ioctls.c @@ -0,0 +1,289 @@ +/* + * IDE ioctls handling. + */ + +#include +#include + +static const struct ide_ioctl_devset ide_ioctl_settings[] = { +{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit }, +{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings }, +{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq }, +{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma }, +{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode }, +{ 0 } +}; + +int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, + unsigned int cmd, unsigned long arg, + const struct ide_ioctl_devset *s) +{ + unsigned long flags; + int err = -EOPNOTSUPP; + + for (; s->get_ioctl; s++) { + if (s->get && s->get_ioctl == cmd) + goto read_val; + else if (s->set && s->set_ioctl == cmd) + goto set_val; + } + + return err; + +read_val: + mutex_lock(&ide_setting_mtx); + spin_lock_irqsave(&ide_lock, flags); + err = s->get(drive); + spin_unlock_irqrestore(&ide_lock, flags); + mutex_unlock(&ide_setting_mtx); + return err >= 0 ? put_user(err, (long __user *)arg) : err; + +set_val: + if (bdev != bdev->bd_contains) + err = -EINVAL; + else { + if (!capable(CAP_SYS_ADMIN)) + err = -EACCES; + else { + mutex_lock(&ide_setting_mtx); + err = s->set(drive, arg); + mutex_unlock(&ide_setting_mtx); + } + } + return err; +} +EXPORT_SYMBOL_GPL(ide_setting_ioctl); + +static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, + unsigned long arg) +{ + u16 *id = NULL; + int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; + int rc = 0; + + if (drive->id_read == 0) { + rc = -ENOMSG; + goto out; + } + + id = kmalloc(size, GFP_KERNEL); + if (id == NULL) { + rc = -ENOMEM; + goto out; + } + + memcpy(id, drive->id, size); + ata_id_to_hd_driveid(id); + + if (copy_to_user((void __user *)arg, id, size)) + rc = -EFAULT; + + kfree(id); +out: + return rc; +} + +static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) +{ + return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) | + (drive->nice1 << IDE_NICE_1), (long __user *)arg); +} + +static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) +{ + if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) + return -EPERM; + + if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && + (drive->media == ide_disk || drive->media == ide_floppy || + drive->scsi)) + return -EPERM; + + drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; + drive->nice1 = (arg >> IDE_NICE_1) & 1; + + return 0; +} + +static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) +{ + u8 *buf = NULL; + int bufsize = 0, err = 0; + u8 args[4], xfer_rate = 0; + ide_task_t tfargs; + struct ide_taskfile *tf = &tfargs.tf; + u16 *id = drive->id; + + if (NULL == (void *) arg) { + struct request *rq; + + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_ATA_TASKFILE; + err = blk_execute_rq(drive->queue, NULL, rq, 0); + blk_put_request(rq); + + return err; + } + + if (copy_from_user(args, (void __user *)arg, 4)) + return -EFAULT; + + memset(&tfargs, 0, sizeof(ide_task_t)); + tf->feature = args[2]; + if (args[0] == ATA_CMD_SMART) { + tf->nsect = args[3]; + tf->lbal = args[1]; + tf->lbam = 0x4f; + tf->lbah = 0xc2; + tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; + } else { + tf->nsect = args[1]; + tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE | + IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT; + } + tf->command = args[0]; + tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA; + + if (args[3]) { + tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; + bufsize = SECTOR_SIZE * args[3]; + buf = kzalloc(bufsize, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + } + + if (tf->command == ATA_CMD_SET_FEATURES && + tf->feature == SETFEATURES_XFER && + tf->nsect >= XFER_SW_DMA_0 && + (id[ATA_ID_UDMA_MODES] || + id[ATA_ID_MWDMA_MODES] || + id[ATA_ID_SWDMA_MODES])) { + xfer_rate = args[1]; + if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { + printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " + "be set\n", drive->name); + goto abort; + } + } + + err = ide_raw_taskfile(drive, &tfargs, buf, args[3]); + + args[0] = tf->status; + args[1] = tf->error; + args[2] = tf->nsect; + + if (!err && xfer_rate) { + /* active-retuning-calls future */ + ide_set_xfer_rate(drive, xfer_rate); + ide_driveid_update(drive); + } +abort: + if (copy_to_user((void __user *)arg, &args, 4)) + err = -EFAULT; + if (buf) { + if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) + err = -EFAULT; + kfree(buf); + } + return err; +} + +static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) +{ + void __user *p = (void __user *)arg; + int err = 0; + u8 args[7]; + ide_task_t task; + + if (copy_from_user(args, p, 7)) + return -EFAULT; + + memset(&task, 0, sizeof(task)); + memcpy(&task.tf_array[7], &args[1], 6); + task.tf.command = args[0]; + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + + err = ide_no_data_taskfile(drive, &task); + + args[0] = task.tf.command; + memcpy(&args[1], &task.tf_array[7], 6); + + if (copy_to_user(p, args, 7)) + err = -EFAULT; + + return err; +} + +static int generic_drive_reset(ide_drive_t *drive) +{ + struct request *rq; + int ret = 0; + + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_len = 1; + rq->cmd[0] = REQ_DRIVE_RESET; + rq->cmd_flags |= REQ_SOFTBARRIER; + if (blk_execute_rq(drive->queue, NULL, rq, 1)) + ret = rq->errors; + blk_put_request(rq); + return ret; +} + +int generic_ide_ioctl(ide_drive_t *drive, struct file *file, + struct block_device *bdev, + unsigned int cmd, unsigned long arg) +{ + int err; + + err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); + if (err != -EOPNOTSUPP) + return err; + + switch (cmd) { + case HDIO_OBSOLETE_IDENTITY: + case HDIO_GET_IDENTITY: + if (bdev != bdev->bd_contains) + return -EINVAL; + return ide_get_identity_ioctl(drive, cmd, arg); + case HDIO_GET_NICE: + return ide_get_nice_ioctl(drive, arg); + case HDIO_SET_NICE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return ide_set_nice_ioctl(drive, arg); +#ifdef CONFIG_IDE_TASK_IOCTL + case HDIO_DRIVE_TASKFILE: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + if (drive->media == ide_disk) + return ide_taskfile_ioctl(drive, cmd, arg); + return -ENOMSG; +#endif + case HDIO_DRIVE_CMD: + if (!capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_cmd_ioctl(drive, cmd, arg); + case HDIO_DRIVE_TASK: + if (!capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_task_ioctl(drive, cmd, arg); + case HDIO_DRIVE_RESET: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return generic_drive_reset(drive); + case HDIO_GET_BUSSTATE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (put_user(BUSSTATE_ON, (long __user *)arg)) + return -EFAULT; + return 0; + case HDIO_SET_BUSSTATE: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return -EOPNOTSUPP; + default: + return -EINVAL; + } +} +EXPORT_SYMBOL(generic_ide_ioctl); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 7ffe9004a4d..487b18b3eba 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -726,112 +726,3 @@ abort: return err; } #endif - -int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) -{ - u8 *buf = NULL; - int bufsize = 0, err = 0; - u8 args[4], xfer_rate = 0; - ide_task_t tfargs; - struct ide_taskfile *tf = &tfargs.tf; - u16 *id = drive->id; - - if (NULL == (void *) arg) { - struct request *rq; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_ATA_TASKFILE; - err = blk_execute_rq(drive->queue, NULL, rq, 0); - blk_put_request(rq); - - return err; - } - - if (copy_from_user(args, (void __user *)arg, 4)) - return -EFAULT; - - memset(&tfargs, 0, sizeof(ide_task_t)); - tf->feature = args[2]; - if (args[0] == ATA_CMD_SMART) { - tf->nsect = args[3]; - tf->lbal = args[1]; - tf->lbam = 0x4f; - tf->lbah = 0xc2; - tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; - } else { - tf->nsect = args[1]; - tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE | - IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT; - } - tf->command = args[0]; - tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA; - - if (args[3]) { - tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; - bufsize = SECTOR_SIZE * args[3]; - buf = kzalloc(bufsize, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - } - - if (tf->command == ATA_CMD_SET_FEATURES && - tf->feature == SETFEATURES_XFER && - tf->nsect >= XFER_SW_DMA_0 && - (id[ATA_ID_UDMA_MODES] || - id[ATA_ID_MWDMA_MODES] || - id[ATA_ID_SWDMA_MODES])) { - xfer_rate = args[1]; - if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { - printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " - "be set\n", drive->name); - goto abort; - } - } - - err = ide_raw_taskfile(drive, &tfargs, buf, args[3]); - - args[0] = tf->status; - args[1] = tf->error; - args[2] = tf->nsect; - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - ide_set_xfer_rate(drive, xfer_rate); - ide_driveid_update(drive); - } -abort: - if (copy_to_user((void __user *)arg, &args, 4)) - err = -EFAULT; - if (buf) { - if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) - err = -EFAULT; - kfree(buf); - } - return err; -} - -int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) -{ - void __user *p = (void __user *)arg; - int err = 0; - u8 args[7]; - ide_task_t task; - - if (copy_from_user(args, p, 7)) - return -EFAULT; - - memset(&task, 0, sizeof(task)); - memcpy(&task.tf_array[7], &args[1], 6); - task.tf.command = args[0]; - task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - err = ide_no_data_taskfile(drive, &task); - - args[0] = task.tf.command; - memcpy(&args[1], &task.tf_array[7], 6); - - if (copy_to_user(p, args, 7)) - err = -EFAULT; - - return err; -} diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 19181493e72..349d7fa7558 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -489,180 +489,6 @@ static int generic_ide_resume(struct device *dev) return err; } -static int generic_drive_reset(ide_drive_t *drive) -{ - struct request *rq; - int ret = 0; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_len = 1; - rq->cmd[0] = REQ_DRIVE_RESET; - rq->cmd_flags |= REQ_SOFTBARRIER; - if (blk_execute_rq(drive->queue, NULL, rq, 1)) - ret = rq->errors; - blk_put_request(rq); - return ret; -} - -static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, - unsigned long arg) -{ - u16 *id = NULL; - int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; - int rc = 0; - - if (drive->id_read == 0) { - rc = -ENOMSG; - goto out; - } - - id = kmalloc(size, GFP_KERNEL); - if (id == NULL) { - rc = -ENOMEM; - goto out; - } - - memcpy(id, drive->id, size); - ata_id_to_hd_driveid(id); - - if (copy_to_user((void __user *)arg, id, size)) - rc = -EFAULT; - - kfree(id); -out: - return rc; -} - -static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) -{ - return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) | - (drive->nice1 << IDE_NICE_1), (long __user *)arg); -} - -static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) -{ - if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) - return -EPERM; - - if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && - (drive->media == ide_disk || drive->media == ide_floppy || - drive->scsi)) - return -EPERM; - - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - drive->nice1 = (arg >> IDE_NICE_1) & 1; - - return 0; -} - -static const struct ide_ioctl_devset ide_ioctl_settings[] = { -{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit }, -{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings }, -{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq }, -{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma }, -{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode }, -{ 0 } -}; - -int generic_ide_ioctl(ide_drive_t *drive, struct file *file, - struct block_device *bdev, - unsigned int cmd, unsigned long arg) -{ - int err; - - err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); - if (err != -EOPNOTSUPP) - return err; - - switch (cmd) { - case HDIO_OBSOLETE_IDENTITY: - case HDIO_GET_IDENTITY: - if (bdev != bdev->bd_contains) - return -EINVAL; - return ide_get_identity_ioctl(drive, cmd, arg); - case HDIO_GET_NICE: - return ide_get_nice_ioctl(drive, arg); - case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return ide_set_nice_ioctl(drive, arg); -#ifdef CONFIG_IDE_TASK_IOCTL - case HDIO_DRIVE_TASKFILE: - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - if (drive->media == ide_disk) - return ide_taskfile_ioctl(drive, cmd, arg); - return -ENOMSG; -#endif - case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - return ide_cmd_ioctl(drive, cmd, arg); - case HDIO_DRIVE_TASK: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - return ide_task_ioctl(drive, cmd, arg); - case HDIO_DRIVE_RESET: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return generic_drive_reset(drive); - case HDIO_GET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (put_user(BUSSTATE_ON, (long __user *)arg)) - return -EFAULT; - return 0; - case HDIO_SET_BUSSTATE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return -EOPNOTSUPP; - default: - return -EINVAL; - } -} -EXPORT_SYMBOL(generic_ide_ioctl); - -int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, - unsigned int cmd, unsigned long arg, - const struct ide_ioctl_devset *s) -{ - unsigned long flags; - int err = -EOPNOTSUPP; - - for (; s->get_ioctl; s++) { - if (s->get && s->get_ioctl == cmd) - goto read_val; - else if (s->set && s->set_ioctl == cmd) - goto set_val; - } - - return err; - -read_val: - mutex_lock(&ide_setting_mtx); - spin_lock_irqsave(&ide_lock, flags); - err = s->get(drive); - spin_unlock_irqrestore(&ide_lock, flags); - mutex_unlock(&ide_setting_mtx); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - mutex_lock(&ide_setting_mtx); - err = s->set(drive, arg); - mutex_unlock(&ide_setting_mtx); - } - } - return err; -} -EXPORT_SYMBOL_GPL(ide_setting_ioctl); - /** * ide_device_get - get an additional reference to a ide_drive_t * @drive: device to get a reference to diff --git a/include/linux/ide.h b/include/linux/ide.h index 64624b9b645..40102bd50a7 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1128,8 +1128,6 @@ int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *, u16); int ide_no_data_taskfile(ide_drive_t *, ide_task_t *); int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long); -int ide_cmd_ioctl(ide_drive_t *, unsigned int, unsigned long); -int ide_task_ioctl(ide_drive_t *, unsigned int, unsigned long); extern int ide_driveid_update(ide_drive_t *); extern int ide_config_drive_speed(ide_drive_t *, u8); -- GitLab From 51509eec34debffec3c6f481f7371c9aeb6c63c1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:34 +0200 Subject: [PATCH 3820/5416] ide: add ide_check_atapi_device() helper * Add ide_check_atapi_device() to ide-atapi.c and convert ide-{floppy,tape}.c to use it instead of ide*_identify_device(). While at it: * Add DRV_NAME defines to ide-{floppy,tape}.c. Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 47 +++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-floppy.c | 48 +++------------------------------------- drivers/ide/ide-tape.c | 43 +++-------------------------------- include/linux/ide.h | 2 ++ 4 files changed, 55 insertions(+), 85 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 12674e6519e..61c52fb665c 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -14,6 +14,53 @@ #define debug_log(fmt, args...) do {} while (0) #endif +/* + * Check whether we can support a device, + * based on the ATAPI IDENTIFY command results. + */ +int ide_check_atapi_device(ide_drive_t *drive, const char *s) +{ + u16 *id = drive->id; + u8 gcw[2], protocol, device_type, removable, drq_type, packet_size; + + *((u16 *)&gcw) = id[ATA_ID_CONFIG]; + + protocol = (gcw[1] & 0xC0) >> 6; + device_type = gcw[1] & 0x1F; + removable = (gcw[0] & 0x80) >> 7; + drq_type = (gcw[0] & 0x60) >> 5; + packet_size = gcw[0] & 0x03; + +#ifdef CONFIG_PPC + /* kludge for Apple PowerBook internal zip */ + if (drive->media == ide_floppy && device_type == 5 && + !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && + strstr((char *)&id[ATA_ID_PROD], "ZIP")) + device_type = 0; +#endif + + if (protocol != 2) + printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n", + s, drive->name, protocol); + else if ((drive->media == ide_floppy && device_type != 0) || + (drive->media == ide_tape && device_type != 1)) + printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n", + s, drive->name, device_type); + else if (removable == 0) + printk(KERN_ERR "%s: %s: the removable flag is not set\n", + s, drive->name); + else if (drive->media == ide_floppy && drq_type == 3) + printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not " + "supported\n", s, drive->name, drq_type); + else if (packet_size != 0) + printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 " + "bytes\n", s, drive->name, packet_size); + else + return 1; + return 0; +} +EXPORT_SYMBOL_GPL(ide_check_atapi_device); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index de8d42b3f69..ace6f26a296 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -15,6 +15,8 @@ * Documentation/ide/ChangeLog.ide-floppy.1996-2002 */ +#define DRV_NAME "ide-floppy" + #define IDEFLOPPY_VERSION "1.00" #include @@ -962,50 +964,6 @@ static sector_t idefloppy_capacity(ide_drive_t *drive) return capacity; } -/* - * Check whether we can support a drive, based on the ATAPI IDENTIFY command - * results. - */ -static int idefloppy_identify_device(ide_drive_t *drive, u16 *id) -{ - u8 gcw[2]; - u8 device_type, protocol, removable, drq_type, packet_size; - - *((u16 *)&gcw) = id[ATA_ID_CONFIG]; - - device_type = gcw[1] & 0x1F; - removable = (gcw[0] & 0x80) >> 7; - protocol = (gcw[1] & 0xC0) >> 6; - drq_type = (gcw[0] & 0x60) >> 5; - packet_size = gcw[0] & 0x03; - -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (device_type == 5 && - !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && - strstr((char *)&id[ATA_ID_PROD], "ZIP")) - device_type = 0; -#endif - - if (protocol != 2) - printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n", - protocol); - else if (device_type != 0) - printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set " - "to floppy\n", device_type); - else if (!removable) - printk(KERN_ERR "ide-floppy: The removable flag is not set\n"); - else if (drq_type == 3) - printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not " - "supported\n", drq_type); - else if (packet_size != 0) - printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 " - "bytes\n", packet_size); - else - return 1; - return 0; -} - #ifdef CONFIG_IDE_PROC_FS ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); ide_devset_rw(bios_head, 0, 255, bios_head); @@ -1407,7 +1365,7 @@ static int ide_floppy_probe(ide_drive_t *drive) if (drive->media != ide_floppy) goto failed; - if (!idefloppy_identify_device(drive, drive->id)) { + if (!ide_check_atapi_device(drive, DRV_NAME)) { printk(KERN_ERR "ide-floppy: %s: not supported by this version" " of ide-floppy\n", drive->name); goto failed; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 1fc1c2a6888..7f56f200334 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -15,6 +15,8 @@ * Documentation/ide/ChangeLog.ide-tape.1995-2002 */ +#define DRV_NAME "ide-tape" + #define IDETAPE_VERSION "1.20" #include @@ -2296,45 +2298,6 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) return 0; } -/* - * check the contents of the ATAPI IDENTIFY command results. We return: - * - * 1 - If the tape can be supported by us, based on the information we have so - * far. - * - * 0 - If this tape driver is not currently supported by us. - */ -static int idetape_identify_device(ide_drive_t *drive) -{ - u8 gcw[2], protocol, device_type, removable, packet_size; - - if (drive->id_read == 0) - return 1; - - *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG]; - - protocol = (gcw[1] & 0xC0) >> 6; - device_type = gcw[1] & 0x1F; - removable = !!(gcw[0] & 0x80); - packet_size = gcw[0] & 0x3; - - /* Check that we can support this device */ - if (protocol != 2) - printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n", - protocol); - else if (device_type != 1) - printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set " - "to tape\n", device_type); - else if (!removable) - printk(KERN_ERR "ide-tape: The removable flag is not set\n"); - else if (packet_size != 0) { - printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12" - " bytes\n", packet_size); - } else - return 1; - return 0; -} - static void idetape_get_inquiry_results(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -2679,7 +2642,7 @@ static int ide_tape_probe(ide_drive_t *drive) if (drive->media != ide_tape) goto failed; - if (!idetape_identify_device(drive)) { + if (drive->id_read == 1 && !ide_check_atapi_device(drive, DRV_NAME)) { printk(KERN_ERR "ide-tape: %s: not supported by this version of" " the driver\n", drive->name); goto failed; diff --git a/include/linux/ide.h b/include/linux/ide.h index 40102bd50a7..e63ff63d1f0 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1109,6 +1109,8 @@ extern int drive_is_ready(ide_drive_t *); void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); +int ide_check_atapi_device(ide_drive_t *, const char *); + ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), -- GitLab From e3faa2481e832568d13dfa3a52d17525b322cb8f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:34 +0200 Subject: [PATCH 3821/5416] ide-floppy: remove needless parens Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ace6f26a296..6a944cb7054 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -738,7 +738,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) return 1; floppy->srfp = pc.buf[8 + 2] & 0x40; - return (0); + return 0; } /* @@ -866,16 +866,17 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) int __user *argp; if (get_user(u_array_size, arg)) - return (-EFAULT); + return -EFAULT; if (u_array_size <= 0) - return (-EINVAL); + return -EINVAL; idefloppy_create_read_capacity_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return (-EIO); + return -EIO; } + header_len = pc.buf[3]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ @@ -897,19 +898,22 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); if (put_user(blocks, argp)) - return(-EFAULT); + return -EFAULT; + ++argp; if (put_user(length, argp)) - return (-EFAULT); + return -EFAULT; + ++argp; ++u_index; } if (put_user(u_index, arg)) - return (-EFAULT); - return (0); + return -EFAULT; + + return 0; } /* @@ -931,7 +935,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) if (floppy->srfp) { idefloppy_create_request_sense_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) - return (-EIO); + return -EIO; if (floppy->sense_key == 2 && floppy->asc == 4 && @@ -950,10 +954,11 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000; } + if (put_user(progress_indication, arg)) - return (-EFAULT); + return -EFAULT; - return (0); + return 0; } static sector_t idefloppy_capacity(ide_drive_t *drive) -- GitLab From d56c99e26b0ff45009bdf85556abee60591507cb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:34 +0200 Subject: [PATCH 3822/5416] ide-floppy: add ide_floppy_format_ioctl() helper * Factor out IDEFLOPPY_IOCTL_FORMAT_* ioctls handling from idefloppy_ioctl() to ide_floppy_format_ioctl(). While at it: * Pass 'drive' instead of 'floppy' to ide_floppy_format_unit(). * idefloppy_get_format_progress() -> ide_floppy_get_format_progress() There should be no functional changes caused by this patch. Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 6a944cb7054..84c333e4434 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -926,7 +926,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) * the dsc bit, and return either 0 or 65536. */ -static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) +static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) { idefloppy_floppy_t *floppy = drive->driver_data; struct ide_atapi_pc pc; @@ -1232,11 +1232,10 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, return 0; } -static int ide_floppy_format_unit(idefloppy_floppy_t *floppy, - int __user *arg) +static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) { + idefloppy_floppy_t *floppy = drive->driver_data; struct ide_atapi_pc pc; - ide_drive_t *drive = floppy->drive; int blocks, length, flags, err = 0; if (floppy->openers > 1) { @@ -1281,6 +1280,24 @@ out: return err; } +static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file, + unsigned int cmd, void __user *argp) +{ + switch (cmd) { + case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: + return 0; + case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: + return ide_floppy_get_format_capacities(drive, argp); + case IDEFLOPPY_IOCTL_FORMAT_START: + if (!(file->f_mode & 2)) + return -EPERM; + return ide_floppy_format_unit(drive, (int __user *)argp); + case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: + return ide_floppy_get_format_progress(drive, argp); + default: + return -ENOTTY; + } +} static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -1292,23 +1309,12 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file, void __user *argp = (void __user *)arg; int err; - switch (cmd) { - case CDROMEJECT: - /* fall through */ - case CDROM_LOCKDOOR: + if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) return ide_floppy_lockdoor(drive, &pc, arg, cmd); - case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: - return 0; - case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: - return ide_floppy_get_format_capacities(drive, argp); - case IDEFLOPPY_IOCTL_FORMAT_START: - if (!(file->f_mode & 2)) - return -EPERM; - return ide_floppy_format_unit(floppy, (int __user *)arg); - case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: - return idefloppy_get_format_progress(drive, argp); - } + err = ide_floppy_format_ioctl(drive, file, cmd, argp); + if (err != -ENOTTY) + return err; /* * skip SCSI_IOCTL_SEND_COMMAND (deprecated) @@ -1317,8 +1323,6 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file, if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, argp); - else - err = -ENOTTY; if (err == -ENOTTY) err = generic_ide_ioctl(drive, file, bdev, cmd, arg); -- GitLab From f025ffdcc3450ae66c9d5df368d97f07e7fcf489 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:34 +0200 Subject: [PATCH 3823/5416] ide-tape: remove idetape_init_rq() idetape_init_rq() is only used in idetape_queue_pc_head() so inline it there. Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-tape.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7f56f200334..83014abf330 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -689,13 +689,6 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) pc->req_xfer = 20; } -static void idetape_init_rq(struct request *rq, u8 cmd) -{ - blk_rq_init(NULL, rq); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd[13] = cmd; -} - /* * Generate a new packet command request in front of the request queue, before * the current request, so that it will be processed immediately, on the next @@ -716,11 +709,13 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, { struct ide_tape_obj *tape = drive->driver_data; - idetape_init_rq(rq, REQ_IDETAPE_PC1); + blk_rq_init(NULL, rq); + rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *) pc; rq->rq_disk = tape->disk; memcpy(rq->cmd, pc->c, 12); + rq->cmd[13] = REQ_IDETAPE_PC1; ide_do_drive_cmd(drive, rq); } -- GitLab From b98b3409abb697321d1b53e3e96a14243fe9fc79 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 10 Oct 2008 22:39:35 +0200 Subject: [PATCH 3824/5416] ide-floppy: use scatterlists for pio transfers Use hwif->sg_table for pio transfers instead of fumbling with block layer internals in the driver. Also, make debug statements more informative in .._do_request() while at it. Signed-off-by: Borislav Petkov [bart: fixup pc->b_count in idefloppy_blockpc_cmd()] [bart: add missing include (noticed by Stephen Rothwell)] [bart: map hwif->sg_{table,nents} on pc->{sg,sg_cnt} (multi-IRQs-per-sg fix)] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 68 +++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 84c333e4434..06db5edf9ce 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -226,29 +227,36 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int bcount, int direction) { ide_hwif_t *hwif = drive->hwif; - struct request *rq = pc->rq; - struct req_iterator iter; - struct bio_vec *bvec; - unsigned long flags; + const struct ide_tp_ops *tp_ops = hwif->tp_ops; + xfer_func_t *xf = direction ? tp_ops->output_data : tp_ops->input_data; + struct scatterlist *sg = pc->sg; + char *buf; int count, done = 0; - char *data; - - rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; - - count = min(bvec->bv_len, bcount); - - data = bvec_kmap_irq(bvec, &flags); - if (direction) - hwif->tp_ops->output_data(drive, NULL, data, count); - else - hwif->tp_ops->input_data(drive, NULL, data, count); - bvec_kunmap_irq(data, &flags); + while (bcount) { + count = min(sg->length - pc->b_count, bcount); + if (PageHighMem(sg_page(sg))) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; + xf(drive, NULL, buf + pc->b_count, count); + kunmap_atomic(buf - sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = sg_virt(sg); + xf(drive, NULL, buf + pc->b_count, count); + } bcount -= count; pc->b_count += count; done += count; + + if (pc->b_count == sg->length) { + if (!--pc->sg_cnt) + break; + pc->sg = sg = sg_next(sg); + pc->b_count = 0; + } } idefloppy_end_request(drive, 1, done >> 9); @@ -571,7 +579,7 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, memcpy(rq->cmd, pc->c, 12); pc->rq = rq; - pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; + pc->b_count = 0; if (rq->cmd_flags & REQ_RW) pc->flags |= PC_FLAG_WRITING; pc->buf = NULL; @@ -585,7 +593,7 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_init_pc(pc); memcpy(pc->c, rq->cmd, sizeof(pc->c)); pc->rq = rq; - pc->b_count = rq->data_len; + pc->b_count = 0; if (rq->data_len && rq_data_dir(rq) == WRITE) pc->flags |= PC_FLAG_WRITING; pc->buf = rq->data; @@ -602,15 +610,17 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, struct request *rq, sector_t block_s) { idefloppy_floppy_t *floppy = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; struct ide_atapi_pc *pc; unsigned long block = (unsigned long)block_s; - debug_log("dev: %s, cmd_type: %x, errors: %d\n", - rq->rq_disk ? rq->rq_disk->disk_name : "?", - rq->cmd_type, rq->errors); - debug_log("sector: %ld, nr_sectors: %ld, " - "current_nr_sectors: %d\n", (long)rq->sector, - rq->nr_sectors, rq->current_nr_sectors); + debug_log("%s: dev: %s, cmd: 0x%x, cmd_type: %x, errors: %d\n", + __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?", + rq->cmd[0], rq->cmd_type, rq->errors); + + debug_log("%s: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n", + __func__, (long)rq->sector, rq->nr_sectors, + rq->current_nr_sectors); if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc) @@ -643,6 +653,12 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, return ide_stopped; } + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + + pc->sg = hwif->sg_table; + pc->sg_cnt = hwif->sg_nents; + pc->rq = rq; return idefloppy_issue_pc(drive, pc); -- GitLab From 20df429dd6671804999493baf2952f82582869fa Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 10 Oct 2008 22:39:35 +0200 Subject: [PATCH 3825/5416] ide-generic: handle probing of legacy io-ports v5 Avoid probing the io-ports in case an IDE PCI controller is present and it uses the legacy iobases. If we still want to enforce the probing, we do ide_generic.probe_mask=0x3f on the kernel command line. The iobase checking code is adapted from drivers/ata/pata_legacy.c after converting hex pci ids into their corresponding macros in . Also, check only BAR0/2 resources since those are guaranteed by the workaround in drivers/pci/probe.c:pci_setup_device(). Signed-off-by: Borislav Petkov Acked-by: Sergei Shtylyov Cc: Alan Cox [bart: trivial printk() fixups] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-generic.c | 55 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 8fe8b5b9cf7..0a3cb0c33ae 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -19,6 +19,7 @@ #include #include #include +#include /* FIXME: convert m32r to use ide_platform host driver */ #ifdef CONFIG_M32R @@ -27,7 +28,7 @@ #define DRV_NAME "ide_generic" -static int probe_mask = 0x03; +static int probe_mask; module_param(probe_mask, int, 0); MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); @@ -100,19 +101,65 @@ static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 }; #endif +static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) +{ + struct pci_dev *p = NULL; + u16 val; + + for_each_pci_dev(p) { + + if (pci_resource_start(p, 0) == 0x1f0) + *primary = 1; + if (pci_resource_start(p, 2) == 0x170) + *secondary = 1; + + /* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */ + if (p->vendor == PCI_VENDOR_ID_CYRIX && + (p->device == PCI_DEVICE_ID_CYRIX_5510 || + p->device == PCI_DEVICE_ID_CYRIX_5520)) + *primary = *secondary = 1; + + /* Intel MPIIX - PIO ATA on non PCI side of bridge */ + if (p->vendor == PCI_VENDOR_ID_INTEL && + p->device == PCI_DEVICE_ID_INTEL_82371MX) { + + pci_read_config_word(p, 0x6C, &val); + if (val & 0x8000) { + /* ATA port enabled */ + if (val & 0x4000) + *secondary = 1; + else + *primary = 1; + } + } + } +} + static int __init ide_generic_init(void) { hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS]; struct ide_host *host; unsigned long io_addr; - int i, rc; + int i, rc, primary = 0, secondary = 0; #ifdef CONFIG_MIPS if (!ide_probe_legacy()) return -ENODEV; #endif - printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module " - "parameter for probing all legacy ISA IDE ports\n"); + ide_generic_check_pci_legacy_iobases(&primary, &secondary); + + if (!probe_mask) { + printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" " + "module parameter for probing all legacy ISA IDE ports\n"); + + if (primary == 0) + probe_mask |= 0x1; + + if (secondary == 0) + probe_mask |= 0x2; + } else + printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports " + "upon user request\n"); memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS); -- GitLab From 394a4c2101f43bfb5fea7b5d1f5789a14ac018d7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:35 +0200 Subject: [PATCH 3826/5416] ide-{floppy,tape}: remove request stack * Add 'struct request request_sense_rq' to struct ide_{floppy,tape}_obj and switch ide*_retry_pc() to use it (there can be only one REQUEST SENSE request active for a given device). * Remove no longer needed ide*_next_rq_storage(), rq_stack[] and rq_stack_index. * DBG_PCRQ_STACK -> DBG_PC_STACK * Update comments for IDE*_PC_STACK and idetape_queue_pc_{head,tail}(). There should be no functional changes caused by this patch. Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 22 ++++--------- drivers/ide/ide-tape.c | 68 +++++++--------------------------------- 2 files changed, 18 insertions(+), 72 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 06db5edf9ce..41bb61037da 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -77,8 +77,8 @@ /* * In various places in the driver, we need to allocate storage for packet - * commands and requests, which will remain valid while we leave the driver to - * wait for an interrupt or a timeout event. + * commands, which will remain valid while we leave the driver to wait for + * an interrupt or a timeout event. */ #define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) @@ -108,9 +108,8 @@ typedef struct ide_floppy_obj { struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK]; /* Next free packet command storage space */ int pc_stack_index; - struct request rq_stack[IDEFLOPPY_PC_STACK]; - /* We implement a circular array */ - int rq_stack_index; + + struct request request_sense_rq; /* Last error information */ u8 sense_key, asc, ascq; @@ -306,15 +305,6 @@ static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive) return (&floppy->pc_stack[floppy->pc_stack_index++]); } -static struct request *idefloppy_next_rq_storage(ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK) - floppy->rq_stack_index = 0; - return (&floppy->rq_stack[floppy->rq_stack_index++]); -} - static void ide_floppy_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -373,12 +363,12 @@ static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc) */ static void idefloppy_retry_pc(ide_drive_t *drive) { + struct ide_floppy_obj *floppy = drive->driver_data; + struct request *rq = &floppy->request_sense_rq; struct ide_atapi_pc *pc; - struct request *rq; (void)ide_read_error(drive); pc = idefloppy_next_pc_storage(drive); - rq = idefloppy_next_rq_storage(drive); idefloppy_create_request_sense_cmd(pc); idefloppy_queue_pc_head(drive, pc, rq); } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 83014abf330..dd3533505e3 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -56,8 +56,8 @@ enum { DBG_CHRDEV = (1 << 2), /* all remaining procedures */ DBG_PROCS = (1 << 3), - /* buffer alloc info (pc_stack & rq_stack) */ - DBG_PCRQ_STACK = (1 << 4), + /* buffer alloc info (pc_stack) */ + DBG_PC_STACK = (1 << 4), }; /* define to see debug info */ @@ -89,9 +89,9 @@ enum { #define IDETAPE_PC_BUFFER_SIZE 256 /* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. + * In various places in the driver, we need to allocate storage for packet + * commands, which will remain valid while we leave the driver to wait for + * an interrupt or a timeout event. */ #define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) @@ -230,9 +230,8 @@ typedef struct ide_tape_obj { struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK]; /* Next free packet command storage space */ int pc_stack_index; - struct request rq_stack[IDETAPE_PC_STACK]; - /* We implement a circular array */ - int rq_stack_index; + + struct request request_sense_rq; /* * DSC polling variables. @@ -462,37 +461,13 @@ static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index); + debug_log(DBG_PC_STACK, "pc_stack_index=%d\n", tape->pc_stack_index); if (tape->pc_stack_index == IDETAPE_PC_STACK) tape->pc_stack_index = 0; return (&tape->pc_stack[tape->pc_stack_index++]); } -/* - * idetape_next_rq_storage is used along with idetape_next_pc_storage. - * Since we queue packet commands in the request queue, we need to - * allocate a request, along with the allocation of a packet command. - */ - -/************************************************************** - * * - * This should get fixed to use kmalloc(.., GFP_ATOMIC) * - * followed later on by kfree(). -ml * - * * - **************************************************************/ - -static struct request *idetape_next_rq_storage(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index); - - if (tape->rq_stack_index == IDETAPE_PC_STACK) - tape->rq_stack_index = 0; - return (&tape->rq_stack[tape->rq_stack_index++]); -} - /* * called on each failed packet command retry to analyze the request sense. We * currently do not utilize this information. @@ -692,17 +667,7 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) /* * Generate a new packet command request in front of the request queue, before * the current request, so that it will be processed immediately, on the next - * pass through the driver. The function below is called from the request - * handling part of the driver (the "bottom" part). Safe storage for the request - * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that. - * - * Memory for those requests is pre-allocated at initialization time, and is - * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for - * the maximum possible number of inter-dependent packet commands. - * - * The higher level of the driver - The ioctl handler and the character device - * handling functions should queue request to the lower level part and wait for - * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail. + * pass through the driver. */ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, struct request *rq) @@ -726,12 +691,12 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, */ static void idetape_retry_pc(ide_drive_t *drive) { + struct ide_tape_obj *tape = drive->driver_data; + struct request *rq = &tape->request_sense_rq; struct ide_atapi_pc *pc; - struct request *rq; (void)ide_read_error(drive); pc = idetape_next_pc_storage(drive); - rq = idetape_next_rq_storage(drive); idetape_create_request_sense_cmd(pc); set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); idetape_queue_pc_head(drive, pc, rq); @@ -1247,16 +1212,7 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) /* * We add a special packet command request to the tail of the request queue, and - * wait for it to be serviced. This is not to be called from within the request - * handling part of the driver! We allocate here data on the stack and it is - * valid until the request is finished. This is not the case for the bottom part - * of the driver, where we are always leaving the functions to wait for an - * interrupt or a timer event. - * - * From the bottom part of the driver, we should allocate safe memory using - * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request - * to the request list without waiting for it to be serviced! In that case, we - * usually use idetape_queue_pc_head(). + * wait for it to be serviced. */ static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) { -- GitLab From 2e8a6f89de69d149bde135c2dc89daa9127984a9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:36 +0200 Subject: [PATCH 3827/5416] ide-{floppy,tape}: remove packet command stack * Add 'struct ide_atapi_pc queued_pc' to struct ide_{floppy,tape}_obj and switch ide*_do_request() to use it (there can be only one active request for a given device). * Add 'struct ide_atapi_pc request_sense_pc' to struct ide_*_obj and switch ide*_retry_pc() to use it. * Remove needless {floppy,tape}->pc assignment from ide*_setup(). * Remove no longer needed ide*_next_pc_storage(), pc_stack[], rq_stack_index, IDE*_PC_STACK and DBG_PC_STACK. There should be no functional changes caused by this patch. Cc: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 32 ++++++--------------------- drivers/ide/ide-tape.c | 48 +++++----------------------------------- 2 files changed, 13 insertions(+), 67 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 41bb61037da..58cd6e6c687 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -75,13 +75,6 @@ */ #define IDEFLOPPY_PC_BUFFER_SIZE 256 -/* - * In various places in the driver, we need to allocate storage for packet - * commands, which will remain valid while we leave the driver to wait for - * an interrupt or a timeout event. - */ -#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) - /* format capacities descriptor codes */ #define CAPACITY_INVALID 0x00 #define CAPACITY_UNFORMATTED 0x01 @@ -104,11 +97,10 @@ typedef struct ide_floppy_obj { struct ide_atapi_pc *pc; /* Last failed packet command */ struct ide_atapi_pc *failed_pc; - /* Packet command stack */ - struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK]; - /* Next free packet command storage space */ - int pc_stack_index; + /* used for blk_{fs,pc}_request() requests */ + struct ide_atapi_pc queued_pc; + struct ide_atapi_pc request_sense_pc; struct request request_sense_rq; /* Last error information */ @@ -296,15 +288,6 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_do_drive_cmd(drive, rq); } -static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK) - floppy->pc_stack_index = 0; - return (&floppy->pc_stack[floppy->pc_stack_index++]); -} - static void ide_floppy_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -365,10 +348,9 @@ static void idefloppy_retry_pc(ide_drive_t *drive) { struct ide_floppy_obj *floppy = drive->driver_data; struct request *rq = &floppy->request_sense_rq; - struct ide_atapi_pc *pc; + struct ide_atapi_pc *pc = &floppy->request_sense_pc; (void)ide_read_error(drive); - pc = idefloppy_next_pc_storage(drive); idefloppy_create_request_sense_cmd(pc); idefloppy_queue_pc_head(drive, pc, rq); } @@ -629,12 +611,12 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, idefloppy_end_request(drive, 0, 0); return ide_stopped; } - pc = idefloppy_next_pc_storage(drive); + pc = &floppy->queued_pc; idefloppy_create_rw_cmd(floppy, pc, rq, block); } else if (blk_special_request(rq)) { pc = (struct ide_atapi_pc *) rq->buffer; } else if (blk_pc_request(rq)) { - pc = idefloppy_next_pc_storage(drive); + pc = &floppy->queued_pc; idefloppy_blockpc_cmd(floppy, pc, rq); } else { blk_dump_rq_flags(rq, @@ -1010,7 +992,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) u8 gcw[2]; *((u16 *)&gcw) = id[ATA_ID_CONFIG]; - floppy->pc = floppy->pc_stack; + drive->pc_callback = ide_floppy_callback; if (((gcw[0] & 0x60) >> 5) == 1) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index dd3533505e3..ba05e03f482 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -56,8 +56,6 @@ enum { DBG_CHRDEV = (1 << 2), /* all remaining procedures */ DBG_PROCS = (1 << 3), - /* buffer alloc info (pc_stack) */ - DBG_PC_STACK = (1 << 4), }; /* define to see debug info */ @@ -88,13 +86,6 @@ enum { */ #define IDETAPE_PC_BUFFER_SIZE 256 -/* - * In various places in the driver, we need to allocate storage for packet - * commands, which will remain valid while we leave the driver to wait for - * an interrupt or a timeout event. - */ -#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) - /* * Some drives (for example, Seagate STT3401A Travan) require a very long * timeout, because they don't return an interrupt or clear their busy bit @@ -208,13 +199,6 @@ typedef struct ide_tape_obj { struct kref kref; /* - * Since a typical character device operation requires more - * than one packet command, we provide here enough memory - * for the maximum of interconnected packet commands. - * The packet commands are stored in the circular array pc_stack. - * pc_stack_index points to the last used entry, and warps around - * to the start when we get to the last array entry. - * * pc points to the current processed packet command. * * failed_pc points to the last failed packet command, or contains @@ -226,11 +210,10 @@ typedef struct ide_tape_obj { struct ide_atapi_pc *pc; /* Last failed packet command */ struct ide_atapi_pc *failed_pc; - /* Packet command stack */ - struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK]; - /* Next free packet command storage space */ - int pc_stack_index; + /* used by REQ_IDETAPE_{READ,WRITE} requests */ + struct ide_atapi_pc queued_pc; + struct ide_atapi_pc request_sense_pc; struct request request_sense_rq; /* @@ -451,23 +434,6 @@ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) pc->bh = bh; } -/* - * idetape_next_pc_storage returns a pointer to a place in which we can - * safely store a packet command, even though we intend to leave the - * driver. A storage space for a maximum of IDETAPE_PC_STACK packet - * commands is allocated at initialization time. - */ -static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - debug_log(DBG_PC_STACK, "pc_stack_index=%d\n", tape->pc_stack_index); - - if (tape->pc_stack_index == IDETAPE_PC_STACK) - tape->pc_stack_index = 0; - return (&tape->pc_stack[tape->pc_stack_index++]); -} - /* * called on each failed packet command retry to analyze the request sense. We * currently do not utilize this information. @@ -693,10 +659,9 @@ static void idetape_retry_pc(ide_drive_t *drive) { struct ide_tape_obj *tape = drive->driver_data; struct request *rq = &tape->request_sense_rq; - struct ide_atapi_pc *pc; + struct ide_atapi_pc *pc = &tape->request_sense_pc; (void)ide_read_error(drive); - pc = idetape_next_pc_storage(drive); idetape_create_request_sense_cmd(pc); set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); idetape_queue_pc_head(drive, pc, rq); @@ -1006,12 +971,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, return ide_stopped; } if (rq->cmd[13] & REQ_IDETAPE_READ) { - pc = idetape_next_pc_storage(drive); + pc = &tape->queued_pc; ide_tape_create_rw_cmd(tape, pc, rq, READ_6); goto out; } if (rq->cmd[13] & REQ_IDETAPE_WRITE) { - pc = idetape_next_pc_storage(drive); + pc = &tape->queued_pc; ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6); goto out; } @@ -2412,7 +2377,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->name[1] = 't'; tape->name[2] = '0' + minor; tape->chrdev_dir = IDETAPE_DIR_NONE; - tape->pc = tape->pc_stack; *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG]; -- GitLab From 4de4b9e1405aef41d199dd20dbce7e9a5dbbf7bf Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:36 +0200 Subject: [PATCH 3828/5416] ide-floppy: remove MODE_SENSE_* defines Only MODE_SENSE_CURRENT (0x00) is ever used so just remove these defines and then drop no longer needed 'type' argument from idefloppy_create_mode_sense_cmd(). Cc: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 58cd6e6c687..a0a8ad3a303 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -124,12 +124,6 @@ typedef struct ide_floppy_obj { #define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ -/* Defines for the MODE SENSE command */ -#define MODE_SENSE_CURRENT 0x00 -#define MODE_SENSE_CHANGEABLE 0x01 -#define MODE_SENSE_DEFAULT 0x02 -#define MODE_SENSE_SAVED 0x03 - /* IOCTLs used in low-level formatting. */ #define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 #define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 @@ -501,14 +495,14 @@ static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, /* A mode sense command is used to "sense" floppy parameters. */ static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, - u8 page_code, u8 type) + u8 page_code) { u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ idefloppy_init_pc(pc); pc->c[0] = GPCMD_MODE_SENSE_10; pc->c[1] = 0; - pc->c[2] = page_code + (type << 6); + pc->c[2] = page_code; switch (page_code) { case IDEFLOPPY_CAPABILITIES_PAGE: @@ -669,8 +663,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) u16 transfer_rate, sector_size, cyls, rpm; u8 heads, sectors; - idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, - MODE_SENSE_CURRENT); + idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); if (idefloppy_queue_pc_tail(drive, &pc)) { printk(KERN_ERR "ide-floppy: Can't get flexible disk page" @@ -718,10 +711,10 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) struct ide_atapi_pc pc; floppy->srfp = 0; - idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE, - MODE_SENSE_CURRENT); + idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); pc.flags |= PC_FLAG_SUPPRESS_ERROR; + if (idefloppy_queue_pc_tail(drive, &pc)) return 1; -- GitLab From c860f955681ebd83df4a03089f1910fc4b54651f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:36 +0200 Subject: [PATCH 3829/5416] ide-scsi: cleanup ide_scsi_io_buffers() Preparation for ide_{floppy,scsi}_io_buffers() unification. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/scsi/ide-scsi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index a2d003c5e85..26e8c3c4947 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -139,29 +139,29 @@ static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; + struct scatterlist *sg = pc->sg; char *buf; int count; while (bcount) { - count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(sg_page(pc->sg))) { + count = min(sg->length - pc->b_count, bcount); + if (PageHighMem(sg_page(sg))) { unsigned long flags; local_irq_save(flags); - buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + - pc->sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; xf(drive, NULL, buf + pc->b_count, count); - kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); + kunmap_atomic(buf - sg->offset, KM_IRQ0); local_irq_restore(flags); } else { - buf = sg_virt(pc->sg); + buf = sg_virt(sg); xf(drive, NULL, buf + pc->b_count, count); } bcount -= count; pc->b_count += count; - if (pc->b_count == pc->sg->length) { + if (pc->b_count == sg->length) { if (!--pc->sg_cnt) break; - pc->sg = sg_next(pc->sg); + pc->sg = sg = sg_next(sg); pc->b_count = 0; } } -- GitLab From acaa0f5f675ccf6b8a3a11a933419068b1ea1f46 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:36 +0200 Subject: [PATCH 3830/5416] ide: add ide_io_buffers() helper * Make ->io_buffers method return number of bytes transferred. * Use ide_end_request() instead of idefloppy_end_request() in ide_floppy_io_buffers() and then move the call out to ide_pc_intr(). * Add ide_io_buffers() helper and convert ide-{floppy,scsi}.c to use it instead of ide*_io_buffers(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 63 +++++++++++++++++++++++++++++++++++++--- drivers/ide/ide-floppy.c | 47 +----------------------------- drivers/ide/ide-tape.c | 4 ++- drivers/scsi/ide-scsi.c | 46 +---------------------------- include/linux/ide.h | 4 ++- 5 files changed, 67 insertions(+), 97 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 61c52fb665c..3d44b45650f 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -61,12 +61,62 @@ int ide_check_atapi_device(ide_drive_t *drive, const char *s) } EXPORT_SYMBOL_GPL(ide_check_atapi_device); +/* PIO data transfer routine using the scatter gather table. */ +int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount, int write) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_tp_ops *tp_ops = hwif->tp_ops; + xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; + struct scatterlist *sg = pc->sg; + char *buf; + int count, done = 0; + + while (bcount) { + count = min(sg->length - pc->b_count, bcount); + + if (PageHighMem(sg_page(sg))) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; + xf(drive, NULL, buf + pc->b_count, count); + kunmap_atomic(buf - sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = sg_virt(sg); + xf(drive, NULL, buf + pc->b_count, count); + } + + bcount -= count; + pc->b_count += count; + done += count; + + if (pc->b_count == sg->length) { + if (!--pc->sg_cnt) + break; + pc->sg = sg = sg_next(sg); + pc->b_count = 0; + } + } + + if (bcount) { + printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, + bcount, write ? "padding with zeros" + : "discarding data"); + ide_pad_transfer(drive, write, bcount); + } + + return done; +} +EXPORT_SYMBOL_GPL(ide_io_buffers); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), - void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) + int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->hwgroup->rq; @@ -219,9 +269,14 @@ cmd_finished: if ((drive->media == ide_floppy && !scsi && !pc->buf) || (drive->media == ide_tape && !scsi && pc->bh) || - (scsi && pc->sg)) - io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); - else + (scsi && pc->sg)) { + int done = io_buffers(drive, pc, bcount, + !!(pc->flags & PC_FLAG_WRITING)); + + /* FIXME: don't do partial completions */ + if (drive->media == ide_floppy && !scsi) + ide_end_request(drive, 1, done >> 9); + } else xferfunc(drive, NULL, pc->cur_pos, bcount); /* Update the current position */ diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a0a8ad3a303..38dca45ffd1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -208,51 +208,6 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) return 0; } -static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, - unsigned int bcount, int direction) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - xfer_func_t *xf = direction ? tp_ops->output_data : tp_ops->input_data; - struct scatterlist *sg = pc->sg; - char *buf; - int count, done = 0; - - while (bcount) { - count = min(sg->length - pc->b_count, bcount); - if (PageHighMem(sg_page(sg))) { - unsigned long flags; - - local_irq_save(flags); - buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; - xf(drive, NULL, buf + pc->b_count, count); - kunmap_atomic(buf - sg->offset, KM_IRQ0); - local_irq_restore(flags); - } else { - buf = sg_virt(sg); - xf(drive, NULL, buf + pc->b_count, count); - } - bcount -= count; - pc->b_count += count; - done += count; - - if (pc->b_count == sg->length) { - if (!--pc->sg_cnt) - break; - pc->sg = sg = sg_next(sg); - pc->b_count = 0; - } - } - - idefloppy_end_request(drive, 1, done >> 9); - - if (bcount) { - printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n", - drive->name, __func__, bcount); - ide_pad_transfer(drive, direction, bcount); - } -} - static void idefloppy_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) { @@ -356,7 +311,7 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers, - idefloppy_retry_pc, NULL, ide_floppy_io_buffers); + idefloppy_retry_pc, NULL, ide_io_buffers); } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index ba05e03f482..d4a9c471dd1 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -693,13 +693,15 @@ static void ide_tape_handle_dsc(ide_drive_t *drive) idetape_postpone_request(drive); } -static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, +static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int bcount, int write) { if (write) idetape_output_buffers(drive, pc, bcount); else idetape_input_buffers(drive, pc, bcount); + + return bcount; } /* diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 26e8c3c4947..27c01e36897 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -130,50 +130,6 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive) return scsihost_to_idescsi(ide_drive->driver_data); } -/* - * PIO data transfer routine using the scatter gather table. - */ -static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, - unsigned int bcount, int write) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; - struct scatterlist *sg = pc->sg; - char *buf; - int count; - - while (bcount) { - count = min(sg->length - pc->b_count, bcount); - if (PageHighMem(sg_page(sg))) { - unsigned long flags; - - local_irq_save(flags); - buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; - xf(drive, NULL, buf + pc->b_count, count); - kunmap_atomic(buf - sg->offset, KM_IRQ0); - local_irq_restore(flags); - } else { - buf = sg_virt(sg); - xf(drive, NULL, buf + pc->b_count, count); - } - bcount -= count; pc->b_count += count; - if (pc->b_count == sg->length) { - if (!--pc->sg_cnt) - break; - pc->sg = sg = sg_next(sg); - pc->b_count = 0; - } - } - - if (bcount) { - printk(KERN_ERR "%s: scatter gather table too small, %s\n", - drive->name, write ? "padding with zeros" - : "discarding data"); - ide_pad_transfer(drive, write, bcount); - } -} - static void ide_scsi_hex_dump(u8 *data, int len) { print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0); @@ -343,7 +299,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc), idescsi_expiry, NULL, NULL, NULL, - ide_scsi_io_buffers); + ide_io_buffers); } static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) diff --git a/include/linux/ide.h b/include/linux/ide.h index e63ff63d1f0..03dc2157a2b 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1099,6 +1099,8 @@ void ide_tf_read(ide_drive_t *, ide_task_t *); void ide_input_data(ide_drive_t *, struct request *, void *, unsigned int); void ide_output_data(ide_drive_t *, struct request *, void *, unsigned int); +int ide_io_buffers(ide_drive_t *, struct ide_atapi_pc *, unsigned int, int); + extern void SELECT_DRIVE(ide_drive_t *); void SELECT_MASK(ide_drive_t *, int); @@ -1115,7 +1117,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), - void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned int, + int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned int, int)); ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *, ide_handler_t *, unsigned int, ide_expiry_t *); -- GitLab From e996fc8ae96a822f037e25463cb8dac5b93839f7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:37 +0200 Subject: [PATCH 3831/5416] ide-floppy: add ide_floppy_set_media_lock() helper Add ide_floppy_set_media_lock() helper and convert idefloppy_open(), idefloppy_release() and ide_floppy_lockdoor() to use it. There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 38dca45ffd1..4bab0932c94 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1038,6 +1038,17 @@ static ide_driver_t idefloppy_driver = { #endif }; +static void ide_floppy_set_media_lock(ide_drive_t *drive, int on) +{ + struct ide_atapi_pc pc; + + /* IOMEGA Clik! drives do not support lock/unlock commands */ + if ((drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE) == 0) { + idefloppy_create_prevent_cmd(&pc, on); + (void)idefloppy_queue_pc_tail(drive, &pc); + } +} + static int idefloppy_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; @@ -1084,12 +1095,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp) ret = -EROFS; goto out_put_floppy; } + drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED; - /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) { - idefloppy_create_prevent_cmd(&pc, 1); - (void) idefloppy_queue_pc_tail(drive, &pc); - } + ide_floppy_set_media_lock(drive, 1); check_disk_change(inode->i_bdev); } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) { ret = -EBUSY; @@ -1108,17 +1116,11 @@ static int idefloppy_release(struct inode *inode, struct file *filp) struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy = ide_floppy_g(disk); ide_drive_t *drive = floppy->drive; - struct ide_atapi_pc pc; debug_log("Reached %s\n", __func__); if (floppy->openers == 1) { - /* IOMEGA Clik! drives do not support lock/unlock commands */ - if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) { - idefloppy_create_prevent_cmd(&pc, 0); - (void) idefloppy_queue_pc_tail(drive, &pc); - } - + ide_floppy_set_media_lock(drive, 0); drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; } @@ -1144,21 +1146,12 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd) { idefloppy_floppy_t *floppy = drive->driver_data; + int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0; if (floppy->openers > 1) return -EBUSY; - /* The IOMEGA Clik! Drive doesn't support this command - - * no room for an eject mechanism */ - if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) { - int prevent = arg ? 1 : 0; - - if (cmd == CDROMEJECT) - prevent = 0; - - idefloppy_create_prevent_cmd(pc, prevent); - (void) idefloppy_queue_pc_tail(floppy->drive, pc); - } + ide_floppy_set_media_lock(drive, prevent); if (cmd == CDROMEJECT) { idefloppy_create_start_stop_cmd(pc, 2); -- GitLab From 385a4b8787c70b708688bee65139f15b0f79f144 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:37 +0200 Subject: [PATCH 3832/5416] ide-tape: add ide_tape_set_media_lock() helper Add ide_tape_set_media_lock() helper and convert idetape_mtioctop(), idetape_chrdev_open() and idetape_chrdev_release() to use it. There should be no functional changes caused by this patch (it is OK to modify ->door_locked if idetape_create_prevent_cmd() fails). Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-tape.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d4a9c471dd1..26d5b0576f0 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1299,6 +1299,16 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, return 1; } +static int ide_tape_set_media_lock(ide_drive_t *drive, int on) +{ + struct ide_atapi_pc pc; + + if (!idetape_create_prevent_cmd(drive, &pc, on)) + return 0; + + return idetape_queue_pc_tail(drive, &pc); +} + static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -1927,9 +1937,8 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) * attempting to eject. */ if (tape->door_locked) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) - if (!idetape_queue_pc_tail(drive, &pc)) - tape->door_locked = DOOR_UNLOCKED; + if (!ide_tape_set_media_lock(drive, 0)) + tape->door_locked = DOOR_UNLOCKED; } ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, @@ -1973,17 +1982,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) case MTFSR: case MTBSR: case MTLOCK: - if (!idetape_create_prevent_cmd(drive, &pc, 1)) - return 0; - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_tape_set_media_lock(drive, 1); if (retval) return retval; tape->door_locked = DOOR_EXPLICITLY_LOCKED; return 0; case MTUNLOCK: - if (!idetape_create_prevent_cmd(drive, &pc, 0)) - return 0; - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_tape_set_media_lock(drive, 0); if (retval) return retval; tape->door_locked = DOOR_UNLOCKED; @@ -2085,7 +2090,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) unsigned int minor = iminor(inode), i = minor & ~0xc0; ide_drive_t *drive; idetape_tape_t *tape; - struct ide_atapi_pc pc; int retval; if (i >= MAX_HWIFS * MAX_DRIVES) @@ -2148,11 +2152,9 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) /* Lock the tape drive door so user can't eject. */ if (tape->chrdev_dir == IDETAPE_DIR_NONE) { - if (idetape_create_prevent_cmd(drive, &pc, 1)) { - if (!idetape_queue_pc_tail(drive, &pc)) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) - tape->door_locked = DOOR_LOCKED; - } + if (!ide_tape_set_media_lock(drive, 1)) { + if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) + tape->door_locked = DOOR_LOCKED; } } unlock_kernel(); @@ -2185,7 +2187,6 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) { struct ide_tape_obj *tape = ide_tape_f(filp); ide_drive_t *drive = tape->drive; - struct ide_atapi_pc pc; unsigned int minor = iminor(inode); lock_kernel(); @@ -2204,10 +2205,8 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) (void) idetape_rewind_tape(drive); if (tape->chrdev_dir == IDETAPE_DIR_NONE) { if (tape->door_locked == DOOR_LOCKED) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) { - if (!idetape_queue_pc_tail(drive, &pc)) - tape->door_locked = DOOR_UNLOCKED; - } + if (!ide_tape_set_media_lock(drive, 0)) + tape->door_locked = DOOR_UNLOCKED; } } clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); -- GitLab From 7bf7420a318978cd6042e5a5da34b7cfa18ae559 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:37 +0200 Subject: [PATCH 3833/5416] ide: add ide_init_pc() helper * Add IDE_PC_BUFFER_SIZE define. * Add ide_init_pc() and convert ide-{floppy,tape}.c to use it instead of ide*_init_pc(). * Remove no longer used IDE*_PC_BUFFER_SIZE and ide*_init_pc(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 8 ++++++++ drivers/ide/ide-floppy.c | 31 ++++++++-------------------- drivers/ide/ide-tape.c | 44 ++++++++++++---------------------------- include/linux/ide.h | 10 ++++++++- 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3d44b45650f..8f0842ce77f 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -111,6 +111,14 @@ int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, } EXPORT_SYMBOL_GPL(ide_io_buffers); +void ide_init_pc(struct ide_atapi_pc *pc) +{ + memset(pc, 0, sizeof(*pc)); + pc->buf = pc->pc_buf; + pc->buf_size = IDE_PC_BUFFER_SIZE; +} +EXPORT_SYMBOL_GPL(ide_init_pc); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 4bab0932c94..e04eaa49a8b 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -69,12 +69,6 @@ */ #define IDEFLOPPY_MAX_PC_RETRIES 3 -/* - * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE - * bytes. - */ -#define IDEFLOPPY_PC_BUFFER_SIZE 256 - /* format capacities descriptor codes */ #define CAPACITY_INVALID 0x00 #define CAPACITY_UNFORMATTED 0x01 @@ -274,16 +268,9 @@ static void ide_floppy_callback(ide_drive_t *drive) idefloppy_end_request(drive, uptodate, 0); } -static void idefloppy_init_pc(struct ide_atapi_pc *pc) -{ - memset(pc, 0, sizeof(*pc)); - pc->buf = pc->pc_buf; - pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE; -} - static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc) { - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_REQUEST_SENSE; pc->c[4] = 255; pc->req_xfer = 18; @@ -413,14 +400,14 @@ static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent) { debug_log("creating prevent removal command, prevent = %d\n", prevent); - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; } static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) { - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; pc->c[7] = 255; pc->c[8] = 255; @@ -430,7 +417,7 @@ static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, int l, int flags) { - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_FORMAT_UNIT; pc->c[1] = 0x17; @@ -454,7 +441,7 @@ static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, { u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_MODE_SENSE_10; pc->c[1] = 0; pc->c[2] = page_code; @@ -476,7 +463,7 @@ static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start) { - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = GPCMD_START_STOP_UNIT; pc->c[4] = start; } @@ -492,7 +479,7 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, debug_log("create_rw10_cmd: block == %d, blocks == %d\n", block, blocks); - idefloppy_init_pc(pc); + ide_init_pc(pc); pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); @@ -511,7 +498,7 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, struct ide_atapi_pc *pc, struct request *rq) { - idefloppy_init_pc(pc); + ide_init_pc(pc); memcpy(pc->c, rq->cmd, sizeof(pc->c)); pc->rq = rq; pc->b_count = 0; @@ -1071,7 +1058,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; /* Just in case */ - idefloppy_init_pc(&pc); + ide_init_pc(&pc); pc.c[0] = GPCMD_TEST_UNIT_READY; if (idefloppy_queue_pc_tail(drive, &pc)) { diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 26d5b0576f0..5c879fbcca8 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -80,12 +80,6 @@ enum { */ #define IDETAPE_MAX_PC_RETRIES 3 -/* - * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE - * bytes. This is used for several packet commands (Not for READ/WRITE commands) - */ -#define IDETAPE_PC_BUFFER_SIZE 256 - /* * Some drives (for example, Seagate STT3401A Travan) require a very long * timeout, because they don't return an interrupt or clear their busy bit @@ -610,21 +604,9 @@ static void ide_tape_callback(ide_drive_t *drive) idetape_end_request(drive, uptodate, 0); } -static void idetape_init_pc(struct ide_atapi_pc *pc) -{ - memset(pc->c, 0, 12); - pc->retries = 0; - pc->flags = 0; - pc->req_xfer = 0; - pc->buf = pc->pc_buf; - pc->buf_size = IDETAPE_PC_BUFFER_SIZE; - pc->bh = NULL; - pc->b_data = NULL; -} - static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = REQUEST_SENSE; pc->c[4] = 20; pc->req_xfer = 20; @@ -816,7 +798,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, /* A mode sense command is used to "sense" tape parameters. */ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = MODE_SENSE; if (page_code != IDETAPE_BLOCK_DESCRIPTOR) /* DBD = 1 - Don't return block descriptors */ @@ -875,7 +857,7 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape, struct idetape_bh *bh = (struct idetape_bh *)rq->special; unsigned int length = rq->current_nr_sectors; - idetape_init_pc(pc); + ide_init_pc(pc); put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->bh = bh; @@ -1165,7 +1147,7 @@ static void idetape_init_merge_buffer(idetape_tape_t *tape) static void idetape_create_write_filemark_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc, int write_filemark) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = WRITE_FILEMARKS; pc->c[4] = write_filemark; pc->flags |= PC_FLAG_WAIT_FOR_DSC; @@ -1173,7 +1155,7 @@ static void idetape_create_write_filemark_cmd(ide_drive_t *drive, static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = TEST_UNIT_READY; } @@ -1200,7 +1182,7 @@ static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) static void idetape_create_load_unload_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc, int cmd) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = START_STOP; pc->c[4] = cmd; pc->flags |= PC_FLAG_WAIT_FOR_DSC; @@ -1252,7 +1234,7 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive) static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = READ_POSITION; pc->req_xfer = 20; } @@ -1276,7 +1258,7 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int block, u8 partition, int skip) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = POSITION_TO_ELEMENT; pc->c[1] = 2; put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]); @@ -1293,7 +1275,7 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, if (!(tape->caps[6] & 0x01)) return 0; - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; return 1; @@ -1408,7 +1390,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = INQUIRY; pc->c[4] = 254; pc->req_xfer = 254; @@ -1417,14 +1399,14 @@ static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) static void idetape_create_rewind_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = REZERO_UNIT; pc->flags |= PC_FLAG_WAIT_FOR_DSC; } static void idetape_create_erase_cmd(struct ide_atapi_pc *pc) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = ERASE; pc->c[1] = 1; pc->flags |= PC_FLAG_WAIT_FOR_DSC; @@ -1432,7 +1414,7 @@ static void idetape_create_erase_cmd(struct ide_atapi_pc *pc) static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) { - idetape_init_pc(pc); + ide_init_pc(pc); pc->c[0] = SPACE; put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]); pc->c[1] = cmd; diff --git a/include/linux/ide.h b/include/linux/ide.h index 03dc2157a2b..bba2f73b99a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -724,6 +724,12 @@ enum { PC_FLAG_TIMEDOUT = (1 << 7), }; +/* + * With each packet command, we allocate a buffer of IDE_PC_BUFFER_SIZE bytes. + * This is used for several packet commands (not for READ/WRITE commands). + */ +#define IDE_PC_BUFFER_SIZE 256 + struct ide_atapi_pc { /* actual packet bytes */ u8 c[12]; @@ -753,7 +759,7 @@ struct ide_atapi_pc { * those are more or less driver-specific and some of them are subject * to change/removal later. */ - u8 pc_buf[256]; + u8 pc_buf[IDE_PC_BUFFER_SIZE]; /* idetape only */ struct idetape_bh *bh; @@ -1113,6 +1119,8 @@ void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); int ide_check_atapi_device(ide_drive_t *, const char *); +void ide_init_pc(struct ide_atapi_pc *); + ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), -- GitLab From 7645c1514c7d34ebdf3ea0e8ee3a935c08abceb2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:37 +0200 Subject: [PATCH 3834/5416] ide: add ide_queue_pc_head() helper * Move REQ_IDETAPE_* enums to . * Add ide_queue_pc_head() and convert ide-{floppy,tape}.c to use it instead of ide*_queue_pc_head(). * Remove no longer used ide*_queue_pc_head(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 20 ++++++++++++++++++++ drivers/ide/ide-floppy.c | 21 +-------------------- drivers/ide/ide-tape.c | 36 +----------------------------------- include/linux/ide.h | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 55 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 8f0842ce77f..da71bfce92e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -119,6 +119,26 @@ void ide_init_pc(struct ide_atapi_pc *pc) } EXPORT_SYMBOL_GPL(ide_init_pc); +/* + * Generate a new packet command request in front of the request queue, before + * the current request, so that it will be processed immediately, on the next + * pass through the driver. + */ +void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, + struct ide_atapi_pc *pc, struct request *rq) +{ + blk_rq_init(NULL, rq); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_flags |= REQ_PREEMPT; + rq->buffer = (char *)pc; + rq->rq_disk = disk; + memcpy(rq->cmd, pc->c, 12); + if (drive->media == ide_tape) + rq->cmd[13] = REQ_IDETAPE_PC1; + ide_do_drive_cmd(drive, rq); +} +EXPORT_SYMBOL_GPL(ide_queue_pc_head); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index e04eaa49a8b..ddce28e77a4 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -212,25 +212,6 @@ static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_end_request(drive, 1, 0); } -/* - * Generate a new packet command request in front of the request queue, before - * the current request so that it will be processed immediately, on the next - * pass through the driver. - */ -static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, - struct request *rq) -{ - struct ide_floppy_obj *floppy = drive->driver_data; - - blk_rq_init(NULL, rq); - rq->buffer = (char *) pc; - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_flags |= REQ_PREEMPT; - rq->rq_disk = floppy->disk; - memcpy(rq->cmd, pc->c, 12); - ide_do_drive_cmd(drive, rq); -} - static void ide_floppy_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -288,7 +269,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive) (void)ide_read_error(drive); idefloppy_create_request_sense_cmd(pc); - idefloppy_queue_pc_head(drive, pc, rq); + ide_queue_pc_head(drive, floppy->disk, pc, rq); } /* The usual interrupt handler called during a packet command. */ diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 5c879fbcca8..7103b98eb53 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -159,20 +159,6 @@ struct idetape_bh { #define IDETAPE_LU_RETENSION_MASK 2 #define IDETAPE_LU_EOT_MASK 4 -/* - * Special requests for our block device strategy routine. - * - * In order to service a character device command, we add special requests to - * the tail of our block device request queue and wait for their completion. - */ - -enum { - REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ - REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ - REQ_IDETAPE_READ = (1 << 2), - REQ_IDETAPE_WRITE = (1 << 3), -}; - /* Error codes returned in rq->errors to the higher part of the driver. */ #define IDETAPE_ERROR_GENERAL 101 #define IDETAPE_ERROR_FILEMARK 102 @@ -612,26 +598,6 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) pc->req_xfer = 20; } -/* - * Generate a new packet command request in front of the request queue, before - * the current request, so that it will be processed immediately, on the next - * pass through the driver. - */ -static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, - struct request *rq) -{ - struct ide_tape_obj *tape = drive->driver_data; - - blk_rq_init(NULL, rq); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_flags |= REQ_PREEMPT; - rq->buffer = (char *) pc; - rq->rq_disk = tape->disk; - memcpy(rq->cmd, pc->c, 12); - rq->cmd[13] = REQ_IDETAPE_PC1; - ide_do_drive_cmd(drive, rq); -} - /* * idetape_retry_pc is called when an error was detected during the * last packet command. We queue a request sense packet command in @@ -646,7 +612,7 @@ static void idetape_retry_pc(ide_drive_t *drive) (void)ide_read_error(drive); idetape_create_request_sense_cmd(pc); set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); - idetape_queue_pc_head(drive, pc, rq); + ide_queue_pc_head(drive, tape->disk, pc, rq); } /* diff --git a/include/linux/ide.h b/include/linux/ide.h index bba2f73b99a..1bd49784e4d 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1121,6 +1121,22 @@ int ide_check_atapi_device(ide_drive_t *, const char *); void ide_init_pc(struct ide_atapi_pc *); +/* + * Special requests for ide-tape block device strategy routine. + * + * In order to service a character device command, we add special requests to + * the tail of our block device request queue and wait for their completion. + */ +enum { + REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ + REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ + REQ_IDETAPE_READ = (1 << 2), + REQ_IDETAPE_WRITE = (1 << 3), +}; + +void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, + struct request *); + ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), -- GitLab From 2ac07d920604eeee8966d52e70161f9b31fe90a3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:38 +0200 Subject: [PATCH 3835/5416] ide: add ide_queue_pc_tail() helper * Add ide_queue_pc_tail() and convert ide-{floppy,tape}.c to use it instead of ide*_queue_pc_tail(). * Remove no longer used ide*_queue_pc_tail(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 23 ++++++++++++++ drivers/ide/ide-floppy.c | 49 ++++++++++------------------ drivers/ide/ide-tape.c | 69 ++++++++++++++++------------------------ include/linux/ide.h | 1 + 4 files changed, 69 insertions(+), 73 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index da71bfce92e..f82ddfb9a44 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -139,6 +139,29 @@ void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, } EXPORT_SYMBOL_GPL(ide_queue_pc_head); +/* + * Add a special packet command request to the tail of the request queue, + * and wait for it to be serviced. + */ +int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, + struct ide_atapi_pc *pc) +{ + struct request *rq; + int error; + + rq = blk_get_request(drive->queue, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->buffer = (char *)pc; + memcpy(rq->cmd, pc->c, 12); + if (drive->media == ide_tape) + rq->cmd[13] = REQ_IDETAPE_PC1; + error = blk_execute_rq(drive->queue, disk, rq, 0); + blk_put_request(rq); + + return error; +} +EXPORT_SYMBOL_GPL(ide_queue_pc_tail); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ddce28e77a4..de611c57b28 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -553,26 +553,6 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, return idefloppy_issue_pc(drive, pc); } -/* - * Add a special packet command request to the tail of the request queue, - * and wait for it to be serviced. - */ -static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) -{ - struct ide_floppy_obj *floppy = drive->driver_data; - struct request *rq; - int error; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->buffer = (char *) pc; - rq->cmd_type = REQ_TYPE_SPECIAL; - memcpy(rq->cmd, pc->c, 12); - error = blk_execute_rq(drive->queue, floppy->disk, rq, 0); - blk_put_request(rq); - - return error; -} - /* * Look at the flexible disk page parameters. We ignore the CHS capacity * parameters and use the LBA parameters instead. @@ -580,6 +560,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; + struct gendisk *disk = floppy->disk; struct ide_atapi_pc pc; u8 *page; int capacity, lba_capacity; @@ -588,13 +569,13 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); - if (idefloppy_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, disk, &pc)) { printk(KERN_ERR "ide-floppy: Can't get flexible disk page" " parameters\n"); return 1; } floppy->wp = !!(pc.buf[3] & 0x80); - set_disk_ro(floppy->disk, floppy->wp); + set_disk_ro(disk, floppy->wp); page = &pc.buf[8]; transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]); @@ -638,7 +619,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); pc.flags |= PC_FLAG_SUPPRESS_ERROR; - if (idefloppy_queue_pc_tail(drive, &pc)) + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) return 1; floppy->srfp = pc.buf[8 + 2] & 0x40; @@ -652,6 +633,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) static int ide_floppy_get_capacity(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; + struct gendisk *disk = floppy->disk; struct ide_atapi_pc pc; u8 *cap_desc; u8 header_len, desc_cnt; @@ -664,7 +646,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) set_capacity(floppy->disk, 0); idefloppy_create_read_capacity_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, disk, &pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; } @@ -739,7 +721,8 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) (void) ide_floppy_get_flexible_disk_page(drive); - set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor); + set_capacity(disk, floppy->blocks * floppy->bs_factor); + return rc; } @@ -764,6 +747,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) { + struct ide_floppy_obj *floppy = drive->driver_data; struct ide_atapi_pc pc; u8 header_len, desc_cnt; int i, blocks, length, u_array_size, u_index; @@ -776,7 +760,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) return -EINVAL; idefloppy_create_read_capacity_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return -EIO; } @@ -838,7 +822,7 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) if (floppy->srfp) { idefloppy_create_request_sense_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) return -EIO; if (floppy->sense_key == 2 && @@ -1008,12 +992,13 @@ static ide_driver_t idefloppy_driver = { static void ide_floppy_set_media_lock(ide_drive_t *drive, int on) { + struct ide_floppy_obj *floppy = drive->driver_data; struct ide_atapi_pc pc; /* IOMEGA Clik! drives do not support lock/unlock commands */ if ((drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE) == 0) { idefloppy_create_prevent_cmd(&pc, on); - (void)idefloppy_queue_pc_tail(drive, &pc); + (void)ide_queue_pc_tail(drive, floppy->disk, &pc); } } @@ -1042,9 +1027,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp) ide_init_pc(&pc); pc.c[0] = GPCMD_TEST_UNIT_READY; - if (idefloppy_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, disk, &pc)) { idefloppy_create_start_stop_cmd(&pc, 1); - (void) idefloppy_queue_pc_tail(drive, &pc); + (void)ide_queue_pc_tail(drive, disk, &pc); } if (ide_floppy_get_capacity(drive) @@ -1123,7 +1108,7 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, if (cmd == CDROMEJECT) { idefloppy_create_start_stop_cmd(pc, 2); - (void) idefloppy_queue_pc_tail(floppy->drive, pc); + (void)ide_queue_pc_tail(drive, floppy->disk, pc); } return 0; @@ -1168,7 +1153,7 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) (void) idefloppy_get_sfrp_bit(drive); idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); - if (idefloppy_queue_pc_tail(drive, &pc)) + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) err = -EIO; out: diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7103b98eb53..88cb9455426 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1125,26 +1125,6 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) pc->c[0] = TEST_UNIT_READY; } -/* - * We add a special packet command request to the tail of the request queue, and - * wait for it to be serviced. - */ -static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) -{ - struct ide_tape_obj *tape = drive->driver_data; - struct request *rq; - int error; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd[13] = REQ_IDETAPE_PC1; - rq->buffer = (char *)pc; - memcpy(rq->cmd, pc->c, 12); - error = blk_execute_rq(drive->queue, tape->disk, rq, 0); - blk_put_request(rq); - return error; -} - static void idetape_create_load_unload_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc, int cmd) { @@ -1157,6 +1137,7 @@ static void idetape_create_load_unload_cmd(ide_drive_t *drive, static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) { idetape_tape_t *tape = drive->driver_data; + struct gendisk *disk = tape->disk; struct ide_atapi_pc pc; int load_attempted = 0; @@ -1165,7 +1146,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) timeout += jiffies; while (time_before(jiffies, timeout)) { idetape_create_test_unit_ready_cmd(&pc); - if (!idetape_queue_pc_tail(drive, &pc)) + if (!ide_queue_pc_tail(drive, disk, &pc)) return 0; if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) || (tape->asc == 0x3A)) { @@ -1174,7 +1155,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) return -ENOMEDIUM; idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); - idetape_queue_pc_tail(drive, &pc); + ide_queue_pc_tail(drive, disk, &pc); load_attempted = 1; /* not about to be ready */ } else if (!(tape->sense_key == 2 && tape->asc == 4 && @@ -1187,11 +1168,12 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) static int idetape_flush_tape_buffers(ide_drive_t *drive) { + struct ide_tape_obj *tape = drive->driver_data; struct ide_atapi_pc pc; int rc; idetape_create_write_filemark_cmd(drive, &pc, 0); - rc = idetape_queue_pc_tail(drive, &pc); + rc = ide_queue_pc_tail(drive, tape->disk, &pc); if (rc) return rc; idetape_wait_ready(drive, 60 * 5 * HZ); @@ -1214,7 +1196,7 @@ static int idetape_read_position(ide_drive_t *drive) debug_log(DBG_PROCS, "Enter %s\n", __func__); idetape_create_read_position_cmd(&pc); - if (idetape_queue_pc_tail(drive, &pc)) + if (ide_queue_pc_tail(drive, tape->disk, &pc)) return -1; position = tape->first_frame; return position; @@ -1249,12 +1231,13 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, static int ide_tape_set_media_lock(ide_drive_t *drive, int on) { + struct ide_tape_obj *tape = drive->driver_data; struct ide_atapi_pc pc; if (!idetape_create_prevent_cmd(drive, &pc, on)) return 0; - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, tape->disk, &pc); } static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) @@ -1284,6 +1267,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block, u8 partition, int skip) { idetape_tape_t *tape = drive->driver_data; + struct gendisk *disk = tape->disk; int retval; struct ide_atapi_pc pc; @@ -1291,12 +1275,12 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block, __ide_tape_discard_merge_buffer(drive); idetape_wait_ready(drive, 60 * 5 * HZ); idetape_create_locate_cmd(drive, &pc, block, partition, skip); - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_queue_pc_tail(drive, disk, &pc); if (retval) return (retval); idetape_create_read_position_cmd(&pc); - return (idetape_queue_pc_tail(drive, &pc)); + return ide_queue_pc_tail(drive, disk, &pc); } static void ide_tape_discard_merge_buffer(ide_drive_t *drive, @@ -1543,20 +1527,20 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount) */ static int idetape_rewind_tape(ide_drive_t *drive) { + struct ide_tape_obj *tape = drive->driver_data; + struct gendisk *disk = tape->disk; int retval; struct ide_atapi_pc pc; - idetape_tape_t *tape; - tape = drive->driver_data; debug_log(DBG_SENSE, "Enter %s\n", __func__); idetape_create_rewind_cmd(drive, &pc); - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_queue_pc_tail(drive, disk, &pc); if (retval) return retval; idetape_create_read_position_cmd(&pc); - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_queue_pc_tail(drive, disk, &pc); if (retval) return retval; return 0; @@ -1599,6 +1583,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, int mt_count) { idetape_tape_t *tape = drive->driver_data; + struct gendisk *disk = tape->disk; struct ide_atapi_pc pc; int retval, count = 0; int sprev = !!(tape->caps[4] & 0x20); @@ -1623,7 +1608,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, case MTBSF: idetape_create_space_cmd(&pc, mt_count - count, IDETAPE_SPACE_OVER_FILEMARK); - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, disk, &pc); case MTFSFM: case MTBSFM: if (!sprev) @@ -1812,11 +1797,12 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, static int idetape_write_filemark(ide_drive_t *drive) { + struct ide_tape_obj *tape = drive->driver_data; struct ide_atapi_pc pc; /* Write a filemark */ idetape_create_write_filemark_cmd(drive, &pc, 1); - if (idetape_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, tape->disk, &pc)) { printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); return -EIO; } @@ -1839,6 +1825,7 @@ static int idetape_write_filemark(ide_drive_t *drive) static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) { idetape_tape_t *tape = drive->driver_data; + struct gendisk *disk = tape->disk; struct ide_atapi_pc pc; int i, retval; @@ -1877,7 +1864,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, disk, &pc); case MTUNLOAD: case MTOFFL: /* @@ -1891,7 +1878,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, !IDETAPE_LU_LOAD_MASK); - retval = idetape_queue_pc_tail(drive, &pc); + retval = ide_queue_pc_tail(drive, disk, &pc); if (!retval) clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); return retval; @@ -1902,14 +1889,14 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, disk, &pc); case MTEOM: idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD); - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, disk, &pc); case MTERASE: (void)idetape_rewind_tape(drive); idetape_create_erase_cmd(&pc); - return idetape_queue_pc_tail(drive, &pc); + return ide_queue_pc_tail(drive, disk, &pc); case MTSETBLK: if (mt_count) { if (mt_count < tape->blk_size || @@ -2018,7 +2005,7 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive) struct ide_atapi_pc pc; idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR); - if (idetape_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, tape->disk, &pc)) { printk(KERN_ERR "ide-tape: Can't get block descriptor\n"); if (tape->blk_size == 0) { printk(KERN_WARNING "ide-tape: Cannot deal with zero " @@ -2170,7 +2157,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) char fw_rev[4], vendor_id[8], product_id[16]; idetape_create_inquiry_cmd(&pc); - if (idetape_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, tape->disk, &pc)) { printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); return; @@ -2199,7 +2186,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive) u8 speed, max_speed; idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE); - if (idetape_queue_pc_tail(drive, &pc)) { + if (ide_queue_pc_tail(drive, tape->disk, &pc)) { printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming" " some default values\n"); tape->blk_size = 512; diff --git a/include/linux/ide.h b/include/linux/ide.h index 1bd49784e4d..b5be2368c96 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1136,6 +1136,7 @@ enum { void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, struct request *); +int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *); ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, -- GitLab From 49cac39e71bd6bbcf934c6ba837e21503902c088 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:38 +0200 Subject: [PATCH 3836/5416] ide-floppy: ->{srfp,wp} -> IDE_AFLAG_{SRFP,WP} Add IDE_AFLAG_{SRFP,WP} drive->atapi_flags and use them instead of ->{srfp,wp} struct ide_floppy_obj fields. There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 24 ++++++++++++++---------- include/linux/ide.h | 18 +++++++++++------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index de611c57b28..78d92835a3c 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -110,10 +110,6 @@ typedef struct ide_floppy_obj { u8 cap_desc[8]; /* Copy of the flexible disk page */ u8 flexible_disk_page[32]; - /* Write protect */ - int wp; - /* Supports format progress report */ - int srfp; } idefloppy_floppy_t; #define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ @@ -574,8 +570,14 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) " parameters\n"); return 1; } - floppy->wp = !!(pc.buf[3] & 0x80); - set_disk_ro(disk, floppy->wp); + + if (pc.buf[3] & 0x80) + drive->atapi_flags |= IDE_AFLAG_WP; + else + drive->atapi_flags &= ~IDE_AFLAG_WP; + + set_disk_ro(disk, !!(drive->atapi_flags & IDE_AFLAG_WP)); + page = &pc.buf[8]; transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]); @@ -614,7 +616,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; struct ide_atapi_pc pc; - floppy->srfp = 0; + drive->atapi_flags &= ~IDE_AFLAG_SRFP; idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); pc.flags |= PC_FLAG_SUPPRESS_ERROR; @@ -622,7 +624,9 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) if (ide_queue_pc_tail(drive, floppy->disk, &pc)) return 1; - floppy->srfp = pc.buf[8 + 2] & 0x40; + if (pc.buf[8 + 2] & 0x40) + drive->atapi_flags |= IDE_AFLAG_SRFP; + return 0; } @@ -820,7 +824,7 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) struct ide_atapi_pc pc; int progress_indication = 0x10000; - if (floppy->srfp) { + if (drive->atapi_flags & IDE_AFLAG_SRFP) { idefloppy_create_request_sense_cmd(&pc); if (ide_queue_pc_tail(drive, floppy->disk, &pc)) return -EIO; @@ -1044,7 +1048,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) goto out_put_floppy; } - if (floppy->wp && (filp->f_mode & 2)) { + if ((drive->atapi_flags & IDE_AFLAG_WP) && (filp->f_mode & 2)) { ret = -EROFS; goto out_put_floppy; } diff --git a/include/linux/ide.h b/include/linux/ide.h index b5be2368c96..cc41a885688 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -356,21 +356,25 @@ enum { IDE_AFLAG_CLIK_DRIVE = (1 << 19), /* Requires BH algorithm for packets */ IDE_AFLAG_ZIP_DRIVE = (1 << 20), + /* Write protect */ + IDE_AFLAG_WP = (1 << 21), + /* Supports format progress report */ + IDE_AFLAG_SRFP = (1 << 22), /* ide-tape */ - IDE_AFLAG_IGNORE_DSC = (1 << 21), + IDE_AFLAG_IGNORE_DSC = (1 << 23), /* 0 When the tape position is unknown */ - IDE_AFLAG_ADDRESS_VALID = (1 << 22), + IDE_AFLAG_ADDRESS_VALID = (1 << 24), /* Device already opened */ - IDE_AFLAG_BUSY = (1 << 23), + IDE_AFLAG_BUSY = (1 << 25), /* Attempt to auto-detect the current user block size */ - IDE_AFLAG_DETECT_BS = (1 << 24), + IDE_AFLAG_DETECT_BS = (1 << 26), /* Currently on a filemark */ - IDE_AFLAG_FILEMARK = (1 << 25), + IDE_AFLAG_FILEMARK = (1 << 27), /* 0 = no tape is loaded, so we don't rewind after ejecting */ - IDE_AFLAG_MEDIUM_PRESENT = (1 << 26), + IDE_AFLAG_MEDIUM_PRESENT = (1 << 28), - IDE_AFLAG_NO_AUTOCLOSE = (1 << 27), + IDE_AFLAG_NO_AUTOCLOSE = (1 << 29), }; struct ide_drive_s { -- GitLab From 0127854d7c96612a454bed6de242e28f8021fa7f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:38 +0200 Subject: [PATCH 3837/5416] ide-floppy: move floppy ioctls handling to ide-floppy_ioctl.c While at it: - idefloppy_create_read_capacity_cmd() -> ide_floppy_create_read_capacity_cmd() - idefloppy_create_mode_sense_cmd() -> ide_floppy_create_mode_sense_cmd() - idefloppy_create_request_sense_cmd() -> ide_floppy_create_request_sense_cmd() - idefloppy_create_format_unit_cmd() -> ide_floppy_create_format_unit_cmd() - idefloppy_get_sfrp_bit() -> ide_floppy_get_sfrp_bit() Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 3 +- drivers/ide/ide-floppy.c | 296 +-------------------------------- drivers/ide/ide-floppy.h | 63 +++++++ drivers/ide/ide-floppy_ioctl.c | 243 +++++++++++++++++++++++++++ 4 files changed, 317 insertions(+), 288 deletions(-) create mode 100644 drivers/ide/ide-floppy.h create mode 100644 drivers/ide/ide-floppy_ioctl.c diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 76a30d76338..308b8a12f31 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -37,11 +37,12 @@ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o +ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o +obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o -obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o ifeq ($(CONFIG_BLK_DEV_IDECS), y) ide-cs-core-y += legacy/ide-cs.o diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 78d92835a3c..ca12a230d9a 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -46,6 +46,8 @@ #include #include +#include "ide-floppy.h" + /* define to see debug info */ #define IDEFLOPPY_DEBUG_LOG 0 @@ -75,61 +77,11 @@ #define CAPACITY_CURRENT 0x02 #define CAPACITY_NO_CARTRIDGE 0x03 -/* - * Most of our global data which we need to save even as we leave the driver - * due to an interrupt or a timer event is stored in a variable of type - * idefloppy_floppy_t, defined below. - */ -typedef struct ide_floppy_obj { - ide_drive_t *drive; - ide_driver_t *driver; - struct gendisk *disk; - struct kref kref; - unsigned int openers; /* protected by BKL for now */ - - /* Current packet command */ - struct ide_atapi_pc *pc; - /* Last failed packet command */ - struct ide_atapi_pc *failed_pc; - /* used for blk_{fs,pc}_request() requests */ - struct ide_atapi_pc queued_pc; - - struct ide_atapi_pc request_sense_pc; - struct request request_sense_rq; - - /* Last error information */ - u8 sense_key, asc, ascq; - /* delay this long before sending packet command */ - u8 ticks; - int progress_indication; - - /* Device information */ - /* Current format */ - int blocks, block_size, bs_factor; - /* Last format capacity descriptor */ - u8 cap_desc[8]; - /* Copy of the flexible disk page */ - u8 flexible_disk_page[32]; -} idefloppy_floppy_t; - #define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ -/* IOCTLs used in low-level formatting. */ -#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 -#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 -#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 -#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 - /* Error code returned in rq->errors to the higher part of the driver. */ #define IDEFLOPPY_ERROR_GENERAL 101 -/* - * Pages of the SELECT SENSE / MODE SENSE packet commands. - * See SFF-8070i spec. - */ -#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b -#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05 - static DEFINE_MUTEX(idefloppy_ref_mutex); #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) @@ -245,7 +197,7 @@ static void ide_floppy_callback(ide_drive_t *drive) idefloppy_end_request(drive, uptodate, 0); } -static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc) +void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *pc) { ide_init_pc(pc); pc->c[0] = GPCMD_REQUEST_SENSE; @@ -264,7 +216,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive) struct ide_atapi_pc *pc = &floppy->request_sense_pc; (void)ide_read_error(drive); - idefloppy_create_request_sense_cmd(pc); + ide_floppy_create_request_sense_cmd(pc); ide_queue_pc_head(drive, floppy->disk, pc, rq); } @@ -382,7 +334,7 @@ static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent) pc->c[4] = prevent; } -static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) +void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) { ide_init_pc(pc); pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; @@ -391,30 +343,8 @@ static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) pc->req_xfer = 255; } -static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, - int l, int flags) -{ - ide_init_pc(pc); - pc->c[0] = GPCMD_FORMAT_UNIT; - pc->c[1] = 0x17; - - memset(pc->buf, 0, 12); - pc->buf[1] = 0xA2; - /* Default format list header, u8 1: FOV/DCRT/IMM bits set */ - - if (flags & 1) /* Verify bit on... */ - pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */ - pc->buf[3] = 8; - - put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4])); - put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8])); - pc->buf_size = 12; - pc->flags |= PC_FLAG_WRITING; -} - /* A mode sense command is used to "sense" floppy parameters. */ -static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, - u8 page_code) +void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) { u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ @@ -563,7 +493,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) u16 transfer_rate, sector_size, cyls, rpm; u8 heads, sectors; - idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); + ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); if (ide_queue_pc_tail(drive, disk, &pc)) { printk(KERN_ERR "ide-floppy: Can't get flexible disk page" @@ -611,25 +541,6 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) return 0; } -static int idefloppy_get_sfrp_bit(ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct ide_atapi_pc pc; - - drive->atapi_flags &= ~IDE_AFLAG_SRFP; - - idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); - pc.flags |= PC_FLAG_SUPPRESS_ERROR; - - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) - return 1; - - if (pc.buf[8 + 2] & 0x40) - drive->atapi_flags |= IDE_AFLAG_SRFP; - - return 0; -} - /* * Determine if a media is present in the floppy drive, and if so, its LBA * capacity. @@ -649,7 +560,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) floppy->bs_factor = 1; set_capacity(floppy->disk, 0); - idefloppy_create_read_capacity_cmd(&pc); + ide_floppy_create_read_capacity_cmd(&pc); if (ide_queue_pc_tail(drive, disk, &pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; @@ -730,129 +641,6 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) return rc; } -/* - * Obtain the list of formattable capacities. - * Very similar to ide_floppy_get_capacity, except that we push the capacity - * descriptors to userland, instead of our own structures. - * - * Userland gives us the following structure: - * - * struct idefloppy_format_capacities { - * int nformats; - * struct { - * int nblocks; - * int blocksize; - * } formats[]; - * }; - * - * userland initializes nformats to the number of allocated formats[] records. - * On exit we set nformats to the number of records we've actually initialized. - */ - -static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) -{ - struct ide_floppy_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; - u8 header_len, desc_cnt; - int i, blocks, length, u_array_size, u_index; - int __user *argp; - - if (get_user(u_array_size, arg)) - return -EFAULT; - - if (u_array_size <= 0) - return -EINVAL; - - idefloppy_create_read_capacity_cmd(&pc); - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) { - printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return -EIO; - } - - header_len = pc.buf[3]; - desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ - - u_index = 0; - argp = arg + 1; - - /* - * We always skip the first capacity descriptor. That's the current - * capacity. We are interested in the remaining descriptors, the - * formattable capacities. - */ - for (i = 1; i < desc_cnt; i++) { - unsigned int desc_start = 4 + i*8; - - if (u_index >= u_array_size) - break; /* User-supplied buffer too small */ - - blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); - length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); - - if (put_user(blocks, argp)) - return -EFAULT; - - ++argp; - - if (put_user(length, argp)) - return -EFAULT; - - ++argp; - - ++u_index; - } - - if (put_user(u_index, arg)) - return -EFAULT; - - return 0; -} - -/* - * Get ATAPI_FORMAT_UNIT progress indication. - * - * Userland gives a pointer to an int. The int is set to a progress - * indicator 0-65536, with 65536=100%. - * - * If the drive does not support format progress indication, we just check - * the dsc bit, and return either 0 or 65536. - */ - -static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct ide_atapi_pc pc; - int progress_indication = 0x10000; - - if (drive->atapi_flags & IDE_AFLAG_SRFP) { - idefloppy_create_request_sense_cmd(&pc); - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) - return -EIO; - - if (floppy->sense_key == 2 && - floppy->asc == 4 && - floppy->ascq == 4) - progress_indication = floppy->progress_indication; - - /* Else assume format_unit has finished, and we're at 0x10000 */ - } else { - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - u8 stat; - - local_irq_save(flags); - stat = hwif->tp_ops->read_status(hwif); - local_irq_restore(flags); - - progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000; - } - - if (put_user(progress_indication, arg)) - return -EFAULT; - - return 0; -} - static sector_t idefloppy_capacity(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -1118,73 +906,6 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, return 0; } -static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - struct ide_atapi_pc pc; - int blocks, length, flags, err = 0; - - if (floppy->openers > 1) { - /* Don't format if someone is using the disk */ - drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; - return -EBUSY; - } - - drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS; - - /* - * Send ATAPI_FORMAT_UNIT to the drive. - * - * Userland gives us the following structure: - * - * struct idefloppy_format_command { - * int nblocks; - * int blocksize; - * int flags; - * } ; - * - * flags is a bitmask, currently, the only defined flag is: - * - * 0x01 - verify media after format. - */ - if (get_user(blocks, arg) || - get_user(length, arg+1) || - get_user(flags, arg+2)) { - err = -EFAULT; - goto out; - } - - (void) idefloppy_get_sfrp_bit(drive); - idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); - - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) - err = -EIO; - -out: - if (err) - drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; - return err; -} - -static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file, - unsigned int cmd, void __user *argp) -{ - switch (cmd) { - case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: - return 0; - case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: - return ide_floppy_get_format_capacities(drive, argp); - case IDEFLOPPY_IOCTL_FORMAT_START: - if (!(file->f_mode & 2)) - return -EPERM; - return ide_floppy_format_unit(drive, (int __user *)argp); - case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: - return ide_floppy_get_format_progress(drive, argp); - default: - return -ENOTTY; - } -} - static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -1316,6 +1037,7 @@ static int __init idefloppy_init(void) } MODULE_ALIAS("ide:*m-floppy*"); +MODULE_ALIAS("ide-floppy"); module_init(idefloppy_init); module_exit(idefloppy_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h new file mode 100644 index 00000000000..ecadc2bc322 --- /dev/null +++ b/drivers/ide/ide-floppy.h @@ -0,0 +1,63 @@ +#ifndef __IDE_FLOPPY_H +#define __IDE_FLOPPY_H + +/* + * Most of our global data which we need to save even as we leave the driver + * due to an interrupt or a timer event is stored in a variable of type + * idefloppy_floppy_t, defined below. + */ +typedef struct ide_floppy_obj { + ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; + struct kref kref; + unsigned int openers; /* protected by BKL for now */ + + /* Current packet command */ + struct ide_atapi_pc *pc; + /* Last failed packet command */ + struct ide_atapi_pc *failed_pc; + /* used for blk_{fs,pc}_request() requests */ + struct ide_atapi_pc queued_pc; + + struct ide_atapi_pc request_sense_pc; + struct request request_sense_rq; + + /* Last error information */ + u8 sense_key, asc, ascq; + /* delay this long before sending packet command */ + u8 ticks; + int progress_indication; + + /* Device information */ + /* Current format */ + int blocks, block_size, bs_factor; + /* Last format capacity descriptor */ + u8 cap_desc[8]; + /* Copy of the flexible disk page */ + u8 flexible_disk_page[32]; +} idefloppy_floppy_t; + +/* + * Pages of the SELECT SENSE / MODE SENSE packet commands. + * See SFF-8070i spec. + */ +#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b +#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05 + +/* IOCTLs used in low-level formatting. */ +#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 +#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 +#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 +#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 + +/* ide-floppy.c */ +void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); +void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); +void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *); + +/* ide-floppy_ioctl.c */ +int ide_floppy_format_ioctl(ide_drive_t *, struct file *, unsigned int, + void __user *); + +#endif /*__IDE_FLOPPY_H */ diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c new file mode 100644 index 00000000000..5ffc4512d14 --- /dev/null +++ b/drivers/ide/ide-floppy_ioctl.c @@ -0,0 +1,243 @@ +/* + * ide-floppy IOCTLs handling. + */ + +#include +#include +#include + +#include + +#include + +#include "ide-floppy.h" + +/* + * Obtain the list of formattable capacities. + * Very similar to ide_floppy_get_capacity, except that we push the capacity + * descriptors to userland, instead of our own structures. + * + * Userland gives us the following structure: + * + * struct idefloppy_format_capacities { + * int nformats; + * struct { + * int nblocks; + * int blocksize; + * } formats[]; + * }; + * + * userland initializes nformats to the number of allocated formats[] records. + * On exit we set nformats to the number of records we've actually initialized. + */ + +static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) +{ + struct ide_floppy_obj *floppy = drive->driver_data; + struct ide_atapi_pc pc; + u8 header_len, desc_cnt; + int i, blocks, length, u_array_size, u_index; + int __user *argp; + + if (get_user(u_array_size, arg)) + return -EFAULT; + + if (u_array_size <= 0) + return -EINVAL; + + ide_floppy_create_read_capacity_cmd(&pc); + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) { + printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); + return -EIO; + } + + header_len = pc.buf[3]; + desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ + + u_index = 0; + argp = arg + 1; + + /* + * We always skip the first capacity descriptor. That's the current + * capacity. We are interested in the remaining descriptors, the + * formattable capacities. + */ + for (i = 1; i < desc_cnt; i++) { + unsigned int desc_start = 4 + i*8; + + if (u_index >= u_array_size) + break; /* User-supplied buffer too small */ + + blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); + length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); + + if (put_user(blocks, argp)) + return -EFAULT; + + ++argp; + + if (put_user(length, argp)) + return -EFAULT; + + ++argp; + + ++u_index; + } + + if (put_user(u_index, arg)) + return -EFAULT; + + return 0; +} + +static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, + int l, int flags) +{ + ide_init_pc(pc); + pc->c[0] = GPCMD_FORMAT_UNIT; + pc->c[1] = 0x17; + + memset(pc->buf, 0, 12); + pc->buf[1] = 0xA2; + /* Default format list header, u8 1: FOV/DCRT/IMM bits set */ + + if (flags & 1) /* Verify bit on... */ + pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */ + pc->buf[3] = 8; + + put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4])); + put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8])); + pc->buf_size = 12; + pc->flags |= PC_FLAG_WRITING; +} + +static int ide_floppy_get_sfrp_bit(ide_drive_t *drive) +{ + idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_atapi_pc pc; + + drive->atapi_flags &= ~IDE_AFLAG_SRFP; + + ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); + pc.flags |= PC_FLAG_SUPPRESS_ERROR; + + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + return 1; + + if (pc.buf[8 + 2] & 0x40) + drive->atapi_flags |= IDE_AFLAG_SRFP; + + return 0; +} + +static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) +{ + idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_atapi_pc pc; + int blocks, length, flags, err = 0; + + if (floppy->openers > 1) { + /* Don't format if someone is using the disk */ + drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; + return -EBUSY; + } + + drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS; + + /* + * Send ATAPI_FORMAT_UNIT to the drive. + * + * Userland gives us the following structure: + * + * struct idefloppy_format_command { + * int nblocks; + * int blocksize; + * int flags; + * } ; + * + * flags is a bitmask, currently, the only defined flag is: + * + * 0x01 - verify media after format. + */ + if (get_user(blocks, arg) || + get_user(length, arg+1) || + get_user(flags, arg+2)) { + err = -EFAULT; + goto out; + } + + (void)ide_floppy_get_sfrp_bit(drive); + ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags); + + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + err = -EIO; + +out: + if (err) + drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; + return err; +} + +/* + * Get ATAPI_FORMAT_UNIT progress indication. + * + * Userland gives a pointer to an int. The int is set to a progress + * indicator 0-65536, with 65536=100%. + * + * If the drive does not support format progress indication, we just check + * the dsc bit, and return either 0 or 65536. + */ + +static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) +{ + idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_atapi_pc pc; + int progress_indication = 0x10000; + + if (drive->atapi_flags & IDE_AFLAG_SRFP) { + ide_floppy_create_request_sense_cmd(&pc); + if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + return -EIO; + + if (floppy->sense_key == 2 && + floppy->asc == 4 && + floppy->ascq == 4) + progress_indication = floppy->progress_indication; + + /* Else assume format_unit has finished, and we're at 0x10000 */ + } else { + ide_hwif_t *hwif = drive->hwif; + unsigned long flags; + u8 stat; + + local_irq_save(flags); + stat = hwif->tp_ops->read_status(hwif); + local_irq_restore(flags); + + progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000; + } + + if (put_user(progress_indication, arg)) + return -EFAULT; + + return 0; +} + +int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file, + unsigned int cmd, void __user *argp) +{ + switch (cmd) { + case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: + return 0; + case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: + return ide_floppy_get_format_capacities(drive, argp); + case IDEFLOPPY_IOCTL_FORMAT_START: + if (!(file->f_mode & 2)) + return -EPERM; + return ide_floppy_format_unit(drive, (int __user *)argp); + case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: + return ide_floppy_get_format_progress(drive, argp); + default: + return -ENOTTY; + } +} -- GitLab From 0578042db3191e1ac76b53d213f2a691c3e1eaed Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:38 +0200 Subject: [PATCH 3838/5416] ide: add ide_set_media_lock() helper * Set IDE_AFLAG_NO_DOORLOCK in idetape_get_mode_sense_result(), check it in ide_tape_set_media_lock() and cleanup idetape_create_prevent_cmd(). * Set IDE_AFLAG_NO_DOORLOCK in ide_floppy_create_read_capacity_cmd() and check it instead of IDE_AFLAG_CLIK_DRIVE in ide_floppy_set_media_lock(). * Add ide_set_media_lock() helper and convert ide-{floppy,tape}.c to use it. * Remove no longer used ide*_create_prevent_cmd()/ide*_set_media_lock(). * Update comment in accordingly. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 15 +++++++++++++++ drivers/ide/ide-floppy.c | 32 +++++++------------------------ drivers/ide/ide-tape.c | 41 ++++++++++------------------------------ include/linux/ide.h | 6 ++++-- 4 files changed, 36 insertions(+), 58 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index f82ddfb9a44..c647a40c0d3 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -162,6 +162,21 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, } EXPORT_SYMBOL_GPL(ide_queue_pc_tail); +int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on) +{ + struct ide_atapi_pc pc; + + if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK) + return 0; + + ide_init_pc(&pc); + pc.c[0] = ALLOW_MEDIUM_REMOVAL; + pc.c[4] = on; + + return ide_queue_pc_tail(drive, disk, &pc); +} +EXPORT_SYMBOL_GPL(ide_set_media_lock); + /* TODO: unify the code thus making some arguments go away */ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ca12a230d9a..f39cf404b03 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -325,15 +325,6 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, IDEFLOPPY_WAIT_CMD, NULL); } -static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent) -{ - debug_log("creating prevent removal command, prevent = %d\n", prevent); - - ide_init_pc(pc); - pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - pc->c[4] = prevent; -} - void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) { ide_init_pc(pc); @@ -712,6 +703,8 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) { blk_queue_max_sectors(drive->queue, 64); drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE; + /* IOMEGA Clik! drives do not support lock/unlock commands */ + drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK; } (void) ide_floppy_get_capacity(drive); @@ -782,18 +775,6 @@ static ide_driver_t idefloppy_driver = { #endif }; -static void ide_floppy_set_media_lock(ide_drive_t *drive, int on) -{ - struct ide_floppy_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; - - /* IOMEGA Clik! drives do not support lock/unlock commands */ - if ((drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE) == 0) { - idefloppy_create_prevent_cmd(&pc, on); - (void)ide_queue_pc_tail(drive, floppy->disk, &pc); - } -} - static int idefloppy_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; @@ -842,7 +823,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) } drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED; - ide_floppy_set_media_lock(drive, 1); + ide_set_media_lock(drive, disk, 1); check_disk_change(inode->i_bdev); } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) { ret = -EBUSY; @@ -865,7 +846,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp) debug_log("Reached %s\n", __func__); if (floppy->openers == 1) { - ide_floppy_set_media_lock(drive, 0); + ide_set_media_lock(drive, disk, 0); drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; } @@ -891,16 +872,17 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd) { idefloppy_floppy_t *floppy = drive->driver_data; + struct gendisk *disk = floppy->disk; int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0; if (floppy->openers > 1) return -EBUSY; - ide_floppy_set_media_lock(drive, prevent); + ide_set_media_lock(drive, disk, prevent); if (cmd == CDROMEJECT) { idefloppy_create_start_stop_cmd(pc, 2); - (void)ide_queue_pc_tail(drive, floppy->disk, pc); + (void)ide_queue_pc_tail(drive, disk, pc); } return 0; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 88cb9455426..b7f3eebc0d1 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1214,32 +1214,6 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, pc->flags |= PC_FLAG_WAIT_FOR_DSC; } -static int idetape_create_prevent_cmd(ide_drive_t *drive, - struct ide_atapi_pc *pc, int prevent) -{ - idetape_tape_t *tape = drive->driver_data; - - /* device supports locking according to capabilities page */ - if (!(tape->caps[6] & 0x01)) - return 0; - - ide_init_pc(pc); - pc->c[0] = ALLOW_MEDIUM_REMOVAL; - pc->c[4] = prevent; - return 1; -} - -static int ide_tape_set_media_lock(ide_drive_t *drive, int on) -{ - struct ide_tape_obj *tape = drive->driver_data; - struct ide_atapi_pc pc; - - if (!idetape_create_prevent_cmd(drive, &pc, on)) - return 0; - - return ide_queue_pc_tail(drive, tape->disk, &pc); -} - static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -1872,7 +1846,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) * attempting to eject. */ if (tape->door_locked) { - if (!ide_tape_set_media_lock(drive, 0)) + if (!ide_set_media_lock(drive, disk, 0)) tape->door_locked = DOOR_UNLOCKED; } ide_tape_discard_merge_buffer(drive, 0); @@ -1917,13 +1891,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) case MTFSR: case MTBSR: case MTLOCK: - retval = ide_tape_set_media_lock(drive, 1); + retval = ide_set_media_lock(drive, disk, 1); if (retval) return retval; tape->door_locked = DOOR_EXPLICITLY_LOCKED; return 0; case MTUNLOCK: - retval = ide_tape_set_media_lock(drive, 0); + retval = ide_set_media_lock(drive, disk, 0); if (retval) return retval; tape->door_locked = DOOR_UNLOCKED; @@ -2087,7 +2061,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) /* Lock the tape drive door so user can't eject. */ if (tape->chrdev_dir == IDETAPE_DIR_NONE) { - if (!ide_tape_set_media_lock(drive, 1)) { + if (!ide_set_media_lock(drive, tape->disk, 1)) { if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) tape->door_locked = DOOR_LOCKED; } @@ -2140,7 +2114,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) (void) idetape_rewind_tape(drive); if (tape->chrdev_dir == IDETAPE_DIR_NONE) { if (tape->door_locked == DOOR_LOCKED) { - if (!ide_tape_set_media_lock(drive, 0)) + if (!ide_set_media_lock(drive, tape->disk, 0)) tape->door_locked = DOOR_UNLOCKED; } } @@ -2218,6 +2192,11 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive) } memcpy(&tape->caps, caps, 20); + + /* device lacks locking support according to capabilities page */ + if ((caps[6] & 1) == 0) + drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK; + if (caps[7] & 0x02) tape->blk_size = 512; else if (caps[7] & 0x04) diff --git a/include/linux/ide.h b/include/linux/ide.h index cc41a885688..ac067a3c1be 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -317,10 +317,10 @@ struct ide_acpi_hwif_link; enum { IDE_AFLAG_DRQ_INTERRUPT = (1 << 0), IDE_AFLAG_MEDIA_CHANGED = (1 << 1), - - /* ide-cd */ /* Drive cannot lock the door. */ IDE_AFLAG_NO_DOORLOCK = (1 << 2), + + /* ide-cd */ /* Drive cannot eject the disc. */ IDE_AFLAG_NO_EJECT = (1 << 3), /* Drive is a pre ATAPI 1.2 drive. */ @@ -1142,6 +1142,8 @@ void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, struct request *); int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *); +int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); + ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), -- GitLab From 0c8a6c7aead1d3be85ce53e3aaacd52e38ede03e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:39 +0200 Subject: [PATCH 3839/5416] ide: add ide_do_start_stop() helper * Add ide_do_start_stop() helper and convert ide-{floppy,tape}.c to use it. * Remove no longer used idefloppy_create_start_stop_cmd() and idetape_create_load_unload_cmd(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 15 +++++++++++++++ drivers/ide/ide-floppy.c | 19 ++++--------------- drivers/ide/ide-tape.c | 24 ++++-------------------- include/linux/ide.h | 1 + 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index c647a40c0d3..58411591edf 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -162,6 +162,21 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, } EXPORT_SYMBOL_GPL(ide_queue_pc_tail); +int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start) +{ + struct ide_atapi_pc pc; + + ide_init_pc(&pc); + pc.c[0] = START_STOP; + pc.c[4] = start; + + if (drive->media == ide_tape) + pc.flags |= PC_FLAG_WAIT_FOR_DSC; + + return ide_queue_pc_tail(drive, disk, &pc); +} +EXPORT_SYMBOL_GPL(ide_do_start_stop); + int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on) { struct ide_atapi_pc pc; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index f39cf404b03..b221a456e53 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -359,13 +359,6 @@ void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) pc->req_xfer = length; } -static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start) -{ - ide_init_pc(pc); - pc->c[0] = GPCMD_START_STOP_UNIT; - pc->c[4] = start; -} - static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, struct ide_atapi_pc *pc, struct request *rq, unsigned long sector) @@ -800,10 +793,8 @@ static int idefloppy_open(struct inode *inode, struct file *filp) ide_init_pc(&pc); pc.c[0] = GPCMD_TEST_UNIT_READY; - if (ide_queue_pc_tail(drive, disk, &pc)) { - idefloppy_create_start_stop_cmd(&pc, 1); - (void)ide_queue_pc_tail(drive, disk, &pc); - } + if (ide_queue_pc_tail(drive, disk, &pc)) + ide_do_start_stop(drive, disk, 1); if (ide_floppy_get_capacity(drive) && (filp->f_flags & O_NDELAY) == 0 @@ -880,10 +871,8 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, ide_set_media_lock(drive, disk, prevent); - if (cmd == CDROMEJECT) { - idefloppy_create_start_stop_cmd(pc, 2); - (void)ide_queue_pc_tail(drive, disk, pc); - } + if (cmd == CDROMEJECT) + ide_do_start_stop(drive, disk, 2); return 0; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b7f3eebc0d1..5204bef4a21 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1125,15 +1125,6 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) pc->c[0] = TEST_UNIT_READY; } -static void idetape_create_load_unload_cmd(ide_drive_t *drive, - struct ide_atapi_pc *pc, int cmd) -{ - ide_init_pc(pc); - pc->c[0] = START_STOP; - pc->c[4] = cmd; - pc->flags |= PC_FLAG_WAIT_FOR_DSC; -} - static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) { idetape_tape_t *tape = drive->driver_data; @@ -1153,9 +1144,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) /* no media */ if (load_attempted) return -ENOMEDIUM; - idetape_create_load_unload_cmd(drive, &pc, - IDETAPE_LU_LOAD_MASK); - ide_queue_pc_tail(drive, disk, &pc); + ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK); load_attempted = 1; /* not about to be ready */ } else if (!(tape->sense_key == 2 && tape->asc == 4 && @@ -1836,9 +1825,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) return 0; case MTLOAD: ide_tape_discard_merge_buffer(drive, 0); - idetape_create_load_unload_cmd(drive, &pc, - IDETAPE_LU_LOAD_MASK); - return ide_queue_pc_tail(drive, disk, &pc); + return ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK); case MTUNLOAD: case MTOFFL: /* @@ -1850,9 +1837,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) tape->door_locked = DOOR_UNLOCKED; } ide_tape_discard_merge_buffer(drive, 0); - idetape_create_load_unload_cmd(drive, &pc, - !IDETAPE_LU_LOAD_MASK); - retval = ide_queue_pc_tail(drive, disk, &pc); + retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK); if (!retval) clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); return retval; @@ -1861,9 +1846,8 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) return idetape_flush_tape_buffers(drive); case MTRETEN: ide_tape_discard_merge_buffer(drive, 0); - idetape_create_load_unload_cmd(drive, &pc, + return ide_do_start_stop(drive, disk, IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return ide_queue_pc_tail(drive, disk, &pc); case MTEOM: idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD); return ide_queue_pc_tail(drive, disk, &pc); diff --git a/include/linux/ide.h b/include/linux/ide.h index ac067a3c1be..be79122b943 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1142,6 +1142,7 @@ void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, struct request *); int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *); +int ide_do_start_stop(ide_drive_t *, struct gendisk *, int); int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, -- GitLab From de699ad595fb45022d1b049ed91ffd06fdd16c13 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:39 +0200 Subject: [PATCH 3840/5416] ide: add ide_do_test_unit_ready() helper * Add ide_do_test_unit_ready() helper and convert ide-{floppy,tape}.c to use it. * Remove no longer used idetape_create_test_unit_ready_cmd(). There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 11 +++++++++++ drivers/ide/ide-floppy.c | 6 +----- drivers/ide/ide-tape.c | 10 +--------- include/linux/ide.h | 1 + 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 58411591edf..608c5bade92 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -162,6 +162,17 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, } EXPORT_SYMBOL_GPL(ide_queue_pc_tail); +int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk) +{ + struct ide_atapi_pc pc; + + ide_init_pc(&pc); + pc.c[0] = TEST_UNIT_READY; + + return ide_queue_pc_tail(drive, disk, &pc); +} +EXPORT_SYMBOL_GPL(ide_do_test_unit_ready); + int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start) { struct ide_atapi_pc pc; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index b221a456e53..4d7e9ef8242 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -773,7 +773,6 @@ static int idefloppy_open(struct inode *inode, struct file *filp) struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy; ide_drive_t *drive; - struct ide_atapi_pc pc; int ret = 0; debug_log("Reached %s\n", __func__); @@ -790,10 +789,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS; /* Just in case */ - ide_init_pc(&pc); - pc.c[0] = GPCMD_TEST_UNIT_READY; - - if (ide_queue_pc_tail(drive, disk, &pc)) + if (ide_do_test_unit_ready(drive, disk)) ide_do_start_stop(drive, disk, 1); if (ide_floppy_get_capacity(drive) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 5204bef4a21..737dd7db6bb 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1119,25 +1119,17 @@ static void idetape_create_write_filemark_cmd(ide_drive_t *drive, pc->flags |= PC_FLAG_WAIT_FOR_DSC; } -static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) -{ - ide_init_pc(pc); - pc->c[0] = TEST_UNIT_READY; -} - static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) { idetape_tape_t *tape = drive->driver_data; struct gendisk *disk = tape->disk; - struct ide_atapi_pc pc; int load_attempted = 0; /* Wait for the tape to become ready */ set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); timeout += jiffies; while (time_before(jiffies, timeout)) { - idetape_create_test_unit_ready_cmd(&pc); - if (!ide_queue_pc_tail(drive, disk, &pc)) + if (ide_do_test_unit_ready(drive, disk) == 0) return 0; if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) || (tape->asc == 0x3A)) { diff --git a/include/linux/ide.h b/include/linux/ide.h index be79122b943..55098eed3b2 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1142,6 +1142,7 @@ void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, struct request *); int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *); +int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *); int ide_do_start_stop(ide_drive_t *, struct gendisk *, int); int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); -- GitLab From d6e2955a6b82d2312b5ff885ce13c8ab54d59d96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 10 Oct 2008 22:39:39 +0200 Subject: [PATCH 3841/5416] ide: move IDE{FLOPPY,TAPE}_WAIT_CMD defines to While at it: * IDE{FLOPPY,TAPE}_WAIT_CMD -> WAIT_{FLOPPY,TAPE}_CMD * Use enum for WAIT_* defines. There should be no functional changes caused by this patch. Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-floppy.c | 13 ++++--------- drivers/ide/ide-tape.c | 13 +++---------- include/linux/ide.h | 28 ++++++++++++++++++++++------ 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 4d7e9ef8242..a63aba2c826 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -61,10 +61,6 @@ #define debug_log(fmt, args...) do {} while (0) #endif - -/* Some drives require a longer irq timeout. */ -#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD) - /* * After each failed packet command we issue a request sense command and retry * the packet command IDEFLOPPY_MAX_PC_RETRIES times. @@ -226,7 +222,7 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr, - IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers, + WAIT_FLOPPY_CMD, NULL, idefloppy_update_buffers, idefloppy_retry_pc, NULL, ide_io_buffers); } @@ -244,10 +240,9 @@ static int idefloppy_transfer_pc(ide_drive_t *drive) drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12); /* Timeout for the packet command */ - return IDEFLOPPY_WAIT_CMD; + return WAIT_FLOPPY_CMD; } - /* * Called as an interrupt (or directly). When the device says it's ready for a * packet, we schedule the packet transfer to occur about 2-3 ticks later in @@ -272,7 +267,7 @@ static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive) timeout = floppy->ticks; expiry = &idefloppy_transfer_pc; } else { - timeout = IDEFLOPPY_WAIT_CMD; + timeout = WAIT_FLOPPY_CMD; expiry = NULL; } @@ -322,7 +317,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, pc->retries++; return ide_issue_pc(drive, pc, idefloppy_start_pc_transfer, - IDEFLOPPY_WAIT_CMD, NULL); + WAIT_FLOPPY_CMD, NULL); } void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 737dd7db6bb..25190966ed3 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -80,13 +80,6 @@ enum { */ #define IDETAPE_MAX_PC_RETRIES 3 -/* - * Some drives (for example, Seagate STT3401A Travan) require a very long - * timeout, because they don't return an interrupt or clear their busy bit - * until after the command completes (even retension commands). - */ -#define IDETAPE_WAIT_CMD (900*HZ) - /* * The following parameter is used to select the point in the internal tape fifo * in which we will start to refill the buffer. Decreasing the following @@ -663,7 +656,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD, + return ide_pc_intr(drive, tape->pc, idetape_pc_intr, WAIT_TAPE_CMD, NULL, idetape_update_buffers, idetape_retry_pc, ide_tape_handle_dsc, ide_tape_io_buffers); } @@ -709,7 +702,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) idetape_tape_t *tape = drive->driver_data; return ide_transfer_pc(drive, tape->pc, idetape_pc_intr, - IDETAPE_WAIT_CMD, NULL); + WAIT_TAPE_CMD, NULL); } static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, @@ -758,7 +751,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, pc->retries++; return ide_issue_pc(drive, pc, idetape_transfer_pc, - IDETAPE_WAIT_CMD, NULL); + WAIT_TAPE_CMD, NULL); } /* A mode sense command is used to "sense" tape parameters. */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 55098eed3b2..a9eced25acc 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -133,12 +133,28 @@ struct ide_io_ports { /* * Timeouts for various operations: */ -#define WAIT_DRQ (HZ/10) /* 100msec - spec allows up to 20ms */ -#define WAIT_READY (5*HZ) /* 5sec - some laptops are very slow */ -#define WAIT_PIDENTIFY (10*HZ) /* 10sec - should be less than 3ms (?), if all ATAPI CD is closed at boot */ -#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */ -#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */ -#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */ +enum { + /* spec allows up to 20ms */ + WAIT_DRQ = HZ / 10, /* 100ms */ + /* some laptops are very slow */ + WAIT_READY = 5 * HZ, /* 5s */ + /* should be less than 3ms (?), if all ATAPI CD is closed at boot */ + WAIT_PIDENTIFY = 10 * HZ, /* 10s */ + /* worst case when spinning up */ + WAIT_WORSTCASE = 30 * HZ, /* 30s */ + /* maximum wait for an IRQ to happen */ + WAIT_CMD = 10 * HZ, /* 10s */ + /* Some drives require a longer IRQ timeout. */ + WAIT_FLOPPY_CMD = 50 * HZ, /* 50s */ + /* + * Some drives (for example, Seagate STT3401A Travan) require a very + * long timeout, because they don't return an interrupt or clear their + * BSY bit until after the command completes (even retension commands). + */ + WAIT_TAPE_CMD = 900 * HZ, /* 900s */ + /* minimum sleep time */ + WAIT_MIN_SLEEP = HZ / 50, /* 20ms */ +}; /* * Op codes for special requests to be handled by ide_special_rq(). -- GitLab From 92f1f8fd8040e7b50a67a850a935509bb01201bb Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Fri, 10 Oct 2008 22:39:40 +0200 Subject: [PATCH 3842/5416] ide: Remove ide_spin_wait_hwgroup() and use special requests instead Use a special request for serialisation purposes and get rid of the awkward ide_spin_wait_hwgroup(). This also involves converting the ide_devset structure so it can be shared by the /proc and the ioctl code. Signed-off-by: Elias Oltmanns [bart: use rq->cmd[] directly] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 8 +-- drivers/ide/ide-disk.c | 66 +++++++++---------- drivers/ide/ide-floppy.c | 20 +++--- drivers/ide/ide-io.c | 40 ++++++++++++ drivers/ide/ide-ioctls.c | 21 +++--- drivers/ide/ide-proc.c | 102 ++++++++++++++--------------- drivers/ide/ide-tape.c | 48 +++++++------- drivers/ide/ide.c | 81 +++++------------------ drivers/scsi/ide-scsi.c | 34 +++++----- include/linux/ide.h | 138 +++++++++++++++++++++------------------ 10 files changed, 274 insertions(+), 284 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 7ea90de5505..465a92ca017 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1809,11 +1809,11 @@ static ide_proc_entry_t idecd_proc[] = { { NULL, 0, NULL, NULL } }; -ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); +ide_devset_rw_field(dsc_overlap, dsc_overlap); -static const struct ide_devset *idecd_settings[] = { - &ide_devset_dsc_overlap, - NULL +static const struct ide_proc_devset idecd_settings[] = { + IDE_PROC_DEVSET(dsc_overlap, 0, 1), + { 0 }, }; #endif diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 11906347082..01846f244b4 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -575,11 +575,8 @@ static int set_nowerr(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1) return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; drive->nowerr = arg; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - spin_unlock_irq(&ide_lock); return 0; } @@ -702,33 +699,34 @@ static int set_addressing(ide_drive_t *drive, int arg) return 0; } +ide_devset_rw(acoustic, acoustic); +ide_devset_rw(address, addressing); +ide_devset_rw(multcount, multcount); +ide_devset_rw(wcache, wcache); + +ide_devset_rw_sync(nowerr, nowerr); + #ifdef CONFIG_IDE_PROC_FS -ide_devset_rw_nolock(acoustic, 0, 254, acoustic); -ide_devset_rw_nolock(address, 0, 2, addressing); -ide_devset_rw_nolock(multcount, 0, 16, multcount); -ide_devset_rw_nolock(nowerr, 0, 1, nowerr); -ide_devset_rw_nolock(wcache, 0, 1, wcache); - -ide_devset_rw(bios_cyl, 0, 65535, bios_cyl); -ide_devset_rw(bios_head, 0, 255, bios_head); -ide_devset_rw(bios_sect, 0, 63, bios_sect); -ide_devset_rw(failures, 0, 65535, failures); -ide_devset_rw(lun, 0, 7, lun); -ide_devset_rw(max_failures, 0, 65535, max_failures); - -static const struct ide_devset *idedisk_settings[] = { - &ide_devset_acoustic, - &ide_devset_address, - &ide_devset_bios_cyl, - &ide_devset_bios_head, - &ide_devset_bios_sect, - &ide_devset_failures, - &ide_devset_lun, - &ide_devset_max_failures, - &ide_devset_multcount, - &ide_devset_nowerr, - &ide_devset_wcache, - NULL +ide_devset_rw_field(bios_cyl, bios_cyl); +ide_devset_rw_field(bios_head, bios_head); +ide_devset_rw_field(bios_sect, bios_sect); +ide_devset_rw_field(failures, failures); +ide_devset_rw_field(lun, lun); +ide_devset_rw_field(max_failures, max_failures); + +static const struct ide_proc_devset idedisk_settings[] = { + IDE_PROC_DEVSET(acoustic, 0, 254), + IDE_PROC_DEVSET(address, 0, 2), + IDE_PROC_DEVSET(bios_cyl, 0, 65535), + IDE_PROC_DEVSET(bios_head, 0, 255), + IDE_PROC_DEVSET(bios_sect, 0, 63), + IDE_PROC_DEVSET(failures, 0, 65535), + IDE_PROC_DEVSET(lun, 0, 7), + IDE_PROC_DEVSET(max_failures, 0, 65535), + IDE_PROC_DEVSET(multcount, 0, 16), + IDE_PROC_DEVSET(nowerr, 0, 1), + IDE_PROC_DEVSET(wcache, 0, 1), + { 0 }, }; #endif @@ -1001,11 +999,11 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) } static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { -{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, get_addressing, set_addressing }, -{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, get_multcount, set_multcount }, -{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, get_nowerr, set_nowerr }, -{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, get_wcache, set_wcache }, -{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, get_acoustic, set_acoustic }, +{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address }, +{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount }, +{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr }, +{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache }, +{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic }, { 0 } }; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a63aba2c826..d36f155470a 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -629,9 +629,9 @@ static sector_t idefloppy_capacity(ide_drive_t *drive) } #ifdef CONFIG_IDE_PROC_FS -ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); -ide_devset_rw(bios_head, 0, 255, bios_head); -ide_devset_rw(bios_sect, 0, 63, bios_sect); +ide_devset_rw_field(bios_cyl, bios_cyl); +ide_devset_rw_field(bios_head, bios_head); +ide_devset_rw_field(bios_sect, bios_sect); static int get_ticks(ide_drive_t *drive) { @@ -646,14 +646,14 @@ static int set_ticks(ide_drive_t *drive, int arg) return 0; } -IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks); +IDE_DEVSET(ticks, DS_SYNC, get_ticks, set_ticks); -static const struct ide_devset *idefloppy_settings[] = { - &ide_devset_bios_cyl, - &ide_devset_bios_head, - &ide_devset_bios_sect, - &ide_devset_ticks, - NULL +static const struct ide_proc_devset idefloppy_settings[] = { + IDE_PROC_DEVSET(bios_cyl, 0, 1023), + IDE_PROC_DEVSET(bios_head, 0, 255), + IDE_PROC_DEVSET(bios_sect, 0, 63), + IDE_PROC_DEVSET(ticks, 0, 255), + { 0 }, }; #endif diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ec6664b0d3a..1c51949833b 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -716,9 +716,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, return ide_stopped; } +int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, + int arg) +{ + struct request_queue *q = drive->queue; + struct request *rq; + int ret = 0; + + if (!(setting->flags & DS_SYNC)) + return setting->set(drive, arg); + + rq = blk_get_request(q, READ, GFP_KERNEL); + if (!rq) + return -ENOMEM; + + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_len = 5; + rq->cmd[0] = REQ_DEVSET_EXEC; + *(int *)&rq->cmd[1] = arg; + rq->special = setting->set; + + if (blk_execute_rq(q, NULL, rq, 0)) + ret = rq->errors; + blk_put_request(rq); + + return ret; +} +EXPORT_SYMBOL_GPL(ide_devset_execute); + static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { switch (rq->cmd[0]) { + case REQ_DEVSET_EXEC: + { + int err, (*setfunc)(ide_drive_t *, int) = rq->special; + + err = setfunc(drive, *(int *)&rq->cmd[1]); + if (err) + rq->errors = err; + else + err = 1; + ide_end_request(drive, err, 0); + return ide_stopped; + } case REQ_DRIVE_RESET: return ide_do_reset(drive); default: diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 7a0d62e7286..cf01564901a 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -6,11 +6,11 @@ #include static const struct ide_ioctl_devset ide_ioctl_settings[] = { -{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit }, -{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings }, -{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq }, -{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma }, -{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode }, +{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, +{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings }, +{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq }, +{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma }, +{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode }, { 0 } }; @@ -18,13 +18,14 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, unsigned int cmd, unsigned long arg, const struct ide_ioctl_devset *s) { + const struct ide_devset *ds; unsigned long flags; int err = -EOPNOTSUPP; - for (; s->get_ioctl; s++) { - if (s->get && s->get_ioctl == cmd) + for (; (ds = s->setting); s++) { + if (ds->get && s->get_ioctl == cmd) goto read_val; - else if (s->set && s->set_ioctl == cmd) + else if (ds->set && s->set_ioctl == cmd) goto set_val; } @@ -33,7 +34,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, read_val: mutex_lock(&ide_setting_mtx); spin_lock_irqsave(&ide_lock, flags); - err = s->get(drive); + err = ds->get(drive); spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); return err >= 0 ? put_user(err, (long __user *)arg) : err; @@ -46,7 +47,7 @@ set_val: err = -EACCES; else { mutex_lock(&ide_setting_mtx); - err = s->set(drive, arg); + err = ide_devset_execute(drive, ds, arg); mutex_unlock(&ide_setting_mtx); } } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 6489c647be8..e7030a49146 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -124,15 +124,16 @@ static int proc_ide_read_identify * setting semaphore */ -static const struct ide_devset *ide_find_setting(const struct ide_devset **st, - char *name) +static +const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st, + char *name) { - while (*st) { - if (strcmp((*st)->name, name) == 0) + while (st->name) { + if (strcmp(st->name, name) == 0) break; st++; } - return *st; + return st->name ? st : NULL; } /** @@ -149,15 +150,16 @@ static const struct ide_devset *ide_find_setting(const struct ide_devset **st, */ static int ide_read_setting(ide_drive_t *drive, - const struct ide_devset *setting) + const struct ide_proc_devset *setting) { + const struct ide_devset *ds = setting->setting; int val = -EINVAL; - if ((setting->flags & S_READ)) { + if (ds->get) { unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - val = setting->get(drive); + val = ds->get(drive); spin_unlock_irqrestore(&ide_lock, flags); } @@ -183,24 +185,21 @@ static int ide_read_setting(ide_drive_t *drive, */ static int ide_write_setting(ide_drive_t *drive, - const struct ide_devset *setting, int val) + const struct ide_proc_devset *setting, int val) { + const struct ide_devset *ds = setting->setting; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (setting->set && (setting->flags & S_NOLOCK)) - return setting->set(drive, val); - if (!(setting->flags & S_WRITE)) + if (!ds->set) return -EPERM; - if (val < setting->min || val > setting->max) + if ((ds->flags & DS_SYNC) + && (val < setting->min || val > setting->max)) return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - setting->set(drive, val); - spin_unlock_irq(&ide_lock); - return 0; + return ide_devset_execute(drive, ds, val); } -static ide_devset_get(xfer_rate, current_speed); +ide_devset_get(xfer_rate, current_speed); static int set_xfer_rate (ide_drive_t *drive, int arg) { @@ -226,29 +225,22 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) return err; } -ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate); -ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit); -ide_devset_rw_nolock(keepsettings, 0, 1, ksettings); -ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq); -ide_devset_rw_nolock(using_dma, 0, 1, using_dma); - -ide_devset_w_nolock(pio_mode, 0, 255, pio_mode); - -ide_devset_rw(init_speed, 0, 70, init_speed); -ide_devset_rw(nice1, 0, 1, nice1); -ide_devset_rw(number, 0, 3, dn); - -static const struct ide_devset *ide_generic_settings[] = { - &ide_devset_current_speed, - &ide_devset_init_speed, - &ide_devset_io_32bit, - &ide_devset_keepsettings, - &ide_devset_nice1, - &ide_devset_number, - &ide_devset_pio_mode, - &ide_devset_unmaskirq, - &ide_devset_using_dma, - NULL +ide_devset_rw(current_speed, xfer_rate); +ide_devset_rw_field(init_speed, init_speed); +ide_devset_rw_field(nice1, nice1); +ide_devset_rw_field(number, dn); + +static const struct ide_proc_devset ide_generic_settings[] = { + IDE_PROC_DEVSET(current_speed, 0, 70), + IDE_PROC_DEVSET(init_speed, 0, 70), + IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)), + IDE_PROC_DEVSET(keepsettings, 0, 1), + IDE_PROC_DEVSET(nice1, 0, 1), + IDE_PROC_DEVSET(number, 0, 3), + IDE_PROC_DEVSET(pio_mode, 0, 255), + IDE_PROC_DEVSET(unmaskirq, 0, 1), + IDE_PROC_DEVSET(using_dma, 0, 1), + { 0 }, }; static void proc_ide_settings_warn(void) @@ -266,7 +258,8 @@ static void proc_ide_settings_warn(void) static int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { - const struct ide_devset *setting, **g, **d; + const struct ide_proc_devset *setting, *g, *d; + const struct ide_devset *ds; ide_drive_t *drive = (ide_drive_t *) data; char *out = page; int len, rc, mul_factor, div_factor; @@ -278,17 +271,17 @@ static int proc_ide_read_settings d = drive->settings; out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); - while (*g || (d && *d)) { + while (g->name || (d && d->name)) { /* read settings in the alphabetical order */ - if (*g && d && *d) { - if (strcmp((*d)->name, (*g)->name) < 0) - setting = *d++; + if (g->name && d && d->name) { + if (strcmp(d->name, g->name) < 0) + setting = d++; else - setting = *g++; - } else if (d && *d) { - setting = *d++; + setting = g++; + } else if (d && d->name) { + setting = d++; } else - setting = *g++; + setting = g++; mul_factor = setting->mulf ? setting->mulf(drive) : 1; div_factor = setting->divf ? setting->divf(drive) : 1; out += sprintf(out, "%-24s", setting->name); @@ -298,9 +291,10 @@ static int proc_ide_read_settings else out += sprintf(out, "%-16s", "write-only"); out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); - if (setting->flags & S_READ) + ds = setting->setting; + if (ds->get) out += sprintf(out, "r"); - if (setting->flags & S_WRITE) + if (ds->set) out += sprintf(out, "w"); out += sprintf(out, "\n"); } @@ -319,7 +313,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, int for_real = 0, mul_factor, div_factor; unsigned long n; - const struct ide_devset *setting; + const struct ide_proc_devset *setting; char *buf, *s; if (!capable(CAP_SYS_ADMIN)) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 25190966ed3..f8c84df4a0b 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2188,40 +2188,40 @@ static int set_##name(ide_drive_t *drive, int arg) \ return 0; \ } -#define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \ +#define ide_tape_devset_rw_field(_name, _field) \ ide_tape_devset_get(_name, _field) \ ide_tape_devset_set(_name, _field) \ -__IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf) +IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name) -#define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \ +#define ide_tape_devset_r_field(_name, _field) \ ide_tape_devset_get(_name, _field) \ -__IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf) +IDE_DEVSET(_name, 0, get_##_name, NULL) static int mulf_tdsc(ide_drive_t *drive) { return 1000; } static int divf_tdsc(ide_drive_t *drive) { return HZ; } static int divf_buffer(ide_drive_t *drive) { return 2; } static int divf_buffer_size(ide_drive_t *drive) { return 1024; } -ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); - -ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL); -ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, - best_dsc_rw_freq, mulf_tdsc, divf_tdsc); - -ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL); -ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL); -ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer); -ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size); - -static const struct ide_devset *idetape_settings[] = { - &ide_devset_avg_speed, - &ide_devset_buffer, - &ide_devset_buffer_size, - &ide_devset_debug_mask, - &ide_devset_dsc_overlap, - &ide_devset_speed, - &ide_devset_tdsc, - NULL +ide_devset_rw_field(dsc_overlap, dsc_overlap); + +ide_tape_devset_rw_field(debug_mask, debug_mask); +ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq); + +ide_tape_devset_r_field(avg_speed, avg_speed); +ide_tape_devset_r_field(speed, caps[14]); +ide_tape_devset_r_field(buffer, caps[16]); +ide_tape_devset_r_field(buffer_size, buffer_size); + +static const struct ide_proc_devset idetape_settings[] = { + __IDE_PROC_DEVSET(avg_speed, 0, 0xffff, NULL, NULL), + __IDE_PROC_DEVSET(buffer, 0, 0xffff, NULL, divf_buffer), + __IDE_PROC_DEVSET(buffer_size, 0, 0xffff, NULL, divf_buffer_size), + __IDE_PROC_DEVSET(debug_mask, 0, 0xffff, NULL, NULL), + __IDE_PROC_DEVSET(dsc_overlap, 0, 1, NULL, NULL), + __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), + __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, + mulf_tdsc, divf_tdsc), + { 0 }, }; #endif diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 349d7fa7558..9dcf5aed92c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -250,42 +250,9 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) DEFINE_MUTEX(ide_setting_mtx); -/** - * ide_spin_wait_hwgroup - wait for group - * @drive: drive in the group - * - * Wait for an IDE device group to go non busy and then return - * holding the ide_lock which guards the hwgroup->busy status - * and right to use it. - */ - -int ide_spin_wait_hwgroup (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long timeout = jiffies + (3 * HZ); - - spin_lock_irq(&ide_lock); - - while (hwgroup->busy) { - unsigned long lflags; - spin_unlock_irq(&ide_lock); - local_irq_set(lflags); - if (time_after(jiffies, timeout)) { - local_irq_restore(lflags); - printk(KERN_ERR "%s: channel busy\n", drive->name); - return -EBUSY; - } - local_irq_restore(lflags); - spin_lock_irq(&ide_lock); - } - return 0; -} - -EXPORT_SYMBOL(ide_spin_wait_hwgroup); - ide_devset_get(io_32bit, io_32bit); -int set_io_32bit(ide_drive_t *drive, int arg) +static int set_io_32bit(ide_drive_t *drive, int arg) { if (drive->no_io_32bit) return -EPERM; @@ -293,37 +260,28 @@ int set_io_32bit(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->io_32bit = arg; - spin_unlock_irq(&ide_lock); - return 0; } ide_devset_get(ksettings, keep_settings); -int set_ksettings(ide_drive_t *drive, int arg) +static int set_ksettings(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 1) return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; drive->keep_settings = arg; - spin_unlock_irq(&ide_lock); return 0; } ide_devset_get(using_dma, using_dma); -int set_using_dma(ide_drive_t *drive, int arg) +static int set_using_dma(ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA - ide_hwif_t *hwif = drive->hwif; int err = -EPERM; if (arg < 0 || arg > 1) @@ -332,18 +290,9 @@ int set_using_dma(ide_drive_t *drive, int arg) if (ata_id_has_dma(drive->id) == 0) goto out; - if (hwif->dma_ops == NULL) + if (drive->hwif->dma_ops == NULL) goto out; - err = -EBUSY; - if (ide_spin_wait_hwgroup(drive)) - goto out; - /* - * set ->busy flag, unlock and let it ride - */ - hwif->hwgroup->busy = 1; - spin_unlock_irq(&ide_lock); - err = 0; if (arg) { @@ -352,12 +301,6 @@ int set_using_dma(ide_drive_t *drive, int arg) } else ide_dma_off(drive); - /* - * lock, clear ->busy flag and unlock before leaving - */ - spin_lock_irq(&ide_lock); - hwif->hwgroup->busy = 0; - spin_unlock_irq(&ide_lock); out: return err; #else @@ -368,7 +311,7 @@ out: #endif } -int set_pio_mode(ide_drive_t *drive, int arg) +static int set_pio_mode(ide_drive_t *drive, int arg) { struct request *rq; ide_hwif_t *hwif = drive->hwif; @@ -398,7 +341,7 @@ int set_pio_mode(ide_drive_t *drive, int arg) ide_devset_get(unmaskirq, unmask); -int set_unmaskirq(ide_drive_t *drive, int arg) +static int set_unmaskirq(ide_drive_t *drive, int arg) { if (drive->no_unmask) return -EPERM; @@ -406,14 +349,20 @@ int set_unmaskirq(ide_drive_t *drive, int arg) if (arg < 0 || arg > 1) return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; drive->unmask = arg; - spin_unlock_irq(&ide_lock); return 0; } +#define ide_gen_devset_rw(_name, _func) \ +__IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) + +ide_gen_devset_rw(io_32bit, io_32bit); +ide_gen_devset_rw(keepsettings, ksettings); +ide_gen_devset_rw(unmaskirq, unmaskirq); +ide_gen_devset_rw(using_dma, using_dma); +__IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); + static int generic_ide_suspend(struct device *dev, pm_message_t mesg) { ide_drive_t *drive = dev->driver_data; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 27c01e36897..90212ac33be 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -400,25 +400,25 @@ static int set_##name(ide_drive_t *drive, int arg) \ return 0; \ } -#define ide_scsi_devset_rw(_name, _min, _max, _field) \ +#define ide_scsi_devset_rw_field(_name, _field) \ ide_scsi_devset_get(_name, _field); \ ide_scsi_devset_set(_name, _field); \ -IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) - -ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); -ide_devset_rw(bios_head, 0, 255, bios_head); -ide_devset_rw(bios_sect, 0, 63, bios_sect); - -ide_scsi_devset_rw(transform, 0, 3, transform); -ide_scsi_devset_rw(log, 0, 1, log); - -static const struct ide_devset *idescsi_settings[] = { - &ide_devset_bios_cyl, - &ide_devset_bios_head, - &ide_devset_bios_sect, - &ide_devset_log, - &ide_devset_transform, - NULL +IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name); + +ide_devset_rw_field(bios_cyl, bios_cyl); +ide_devset_rw_field(bios_head, bios_head); +ide_devset_rw_field(bios_sect, bios_sect); + +ide_scsi_devset_rw_field(transform, transform); +ide_scsi_devset_rw_field(log, log); + +static const struct ide_proc_devset idescsi_settings[] = { + IDE_PROC_DEVSET(bios_cyl, 0, 1023), + IDE_PROC_DEVSET(bios_head, 0, 255), + IDE_PROC_DEVSET(bios_sect, 0, 63), + IDE_PROC_DEVSET(log, 0, 1), + IDE_PROC_DEVSET(transform, 0, 3), + { 0 }, }; #endif diff --git a/include/linux/ide.h b/include/linux/ide.h index a9eced25acc..a9d82d6e6bd 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -161,6 +161,7 @@ enum { * Values should be in the range of 0x20 to 0x3f. */ #define REQ_DRIVE_RESET 0x20 +#define REQ_DEVSET_EXEC 0x21 /* * Check for an interrupt and acknowledge the interrupt status @@ -405,7 +406,7 @@ struct ide_drive_s { u16 *id; /* identification info */ #ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ - const struct ide_devset **settings; /* /proc/ide/ drive settings */ + const struct ide_proc_devset *settings; /* /proc/ide/ drive settings */ #endif struct hwif_s *hwif; /* actually (ide_hwif_t *) */ @@ -707,29 +708,62 @@ typedef struct ide_driver_s ide_driver_t; extern struct mutex ide_setting_mtx; -int get_io_32bit(ide_drive_t *); -int set_io_32bit(ide_drive_t *, int); -int get_ksettings(ide_drive_t *); -int set_ksettings(ide_drive_t *, int); -int set_pio_mode(ide_drive_t *, int); -int get_unmaskirq(ide_drive_t *); -int set_unmaskirq(ide_drive_t *, int); -int get_using_dma(ide_drive_t *); -int set_using_dma(ide_drive_t *, int); +/* + * configurable drive settings + */ + +#define DS_SYNC (1 << 0) + +struct ide_devset { + int (*get)(ide_drive_t *); + int (*set)(ide_drive_t *, int); + unsigned int flags; +}; + +#define __DEVSET(_flags, _get, _set) { \ + .flags = _flags, \ + .get = _get, \ + .set = _set, \ +} #define ide_devset_get(name, field) \ -int get_##name(ide_drive_t *drive) \ +static int get_##name(ide_drive_t *drive) \ { \ return drive->field; \ } #define ide_devset_set(name, field) \ -int set_##name(ide_drive_t *drive, int arg) \ +static int set_##name(ide_drive_t *drive, int arg) \ { \ drive->field = arg; \ return 0; \ } +#define __IDE_DEVSET(_name, _flags, _get, _set) \ +const struct ide_devset ide_devset_##_name = \ + __DEVSET(_flags, _get, _set) + +#define IDE_DEVSET(_name, _flags, _get, _set) \ +static __IDE_DEVSET(_name, _flags, _get, _set) + +#define ide_devset_rw(_name, _func) \ +IDE_DEVSET(_name, 0, get_##_func, set_##_func) + +#define ide_devset_w(_name, _func) \ +IDE_DEVSET(_name, 0, NULL, set_##_func) + +#define ide_devset_rw_sync(_name, _func) \ +IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) + +#define ide_decl_devset(_name) \ +extern const struct ide_devset ide_devset_##_name + +ide_decl_devset(io_32bit); +ide_decl_devset(keepsettings); +ide_decl_devset(pio_mode); +ide_decl_devset(unmaskirq); +ide_decl_devset(using_dma); + /* ATAPI packet command flags */ enum { /* set when an error is considered normal - no retry (ide-tape) */ @@ -797,60 +831,34 @@ struct ide_atapi_pc { #ifdef CONFIG_IDE_PROC_FS /* - * configurable drive settings + * /proc/ide interface */ -#define S_READ (1 << 0) -#define S_WRITE (1 << 1) -#define S_RW (S_READ | S_WRITE) -#define S_NOLOCK (1 << 2) - -struct ide_devset { - const char *name; - unsigned int flags; - int min, max; - int (*get)(ide_drive_t *); - int (*set)(ide_drive_t *, int); - int (*mulf)(ide_drive_t *); - int (*divf)(ide_drive_t *); +#define ide_devset_rw_field(_name, _field) \ +ide_devset_get(_name, _field); \ +ide_devset_set(_name, _field); \ +IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name) + +struct ide_proc_devset { + const char *name; + const struct ide_devset *setting; + int min, max; + int (*mulf)(ide_drive_t *); + int (*divf)(ide_drive_t *); }; -#define __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) { \ - .name = __stringify(_name), \ - .flags = _flags, \ - .min = _min, \ - .max = _max, \ - .get = _get, \ - .set = _set, \ - .mulf = _mulf, \ - .divf = _divf, \ +#define __IDE_PROC_DEVSET(_name, _min, _max, _mulf, _divf) { \ + .name = __stringify(_name), \ + .setting = &ide_devset_##_name, \ + .min = _min, \ + .max = _max, \ + .mulf = _mulf, \ + .divf = _divf, \ } -#define __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) \ -static const struct ide_devset ide_devset_##_name = \ - __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) - -#define IDE_DEVSET(_name, _flags, _min, _max, _get, _set) \ -__IDE_DEVSET(_name, _flags, _min, _max, _get, _set, NULL, NULL) - -#define ide_devset_rw_nolock(_name, _min, _max, _func) \ -IDE_DEVSET(_name, S_RW | S_NOLOCK, _min, _max, get_##_func, set_##_func) +#define IDE_PROC_DEVSET(_name, _min, _max) \ +__IDE_PROC_DEVSET(_name, _min, _max, NULL, NULL) -#define ide_devset_w_nolock(_name, _min, _max, _func) \ -IDE_DEVSET(_name, S_WRITE | S_NOLOCK, _min, _max, NULL, set_##_func) - -#define ide_devset_rw(_name, _min, _max, _field) \ -static ide_devset_get(_name, _field); \ -static ide_devset_set(_name, _field); \ -IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) - -#define ide_devset_r(_name, _min, _max, _field) \ -ide_devset_get(_name, _field) \ -IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL) - -/* - * /proc/ide interface - */ typedef struct { const char *name; mode_t mode; @@ -948,8 +956,8 @@ struct ide_driver_s { void (*resume)(ide_drive_t *); void (*shutdown)(ide_drive_t *); #ifdef CONFIG_IDE_PROC_FS - ide_proc_entry_t *proc; - const struct ide_devset **settings; + ide_proc_entry_t *proc; + const struct ide_proc_devset *settings; #endif }; @@ -961,9 +969,7 @@ void ide_device_put(ide_drive_t *); struct ide_ioctl_devset { unsigned int get_ioctl; unsigned int set_ioctl; - - int (*get)(ide_drive_t *); - int (*set)(ide_drive_t *, int); + const struct ide_devset *setting; }; int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int, @@ -1002,6 +1008,9 @@ int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); extern ide_startstop_t ide_do_reset (ide_drive_t *); +extern int ide_devset_execute(ide_drive_t *drive, + const struct ide_devset *setting, int arg); + extern void ide_do_drive_cmd(ide_drive_t *, struct request *); extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); @@ -1191,7 +1200,6 @@ extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout); extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); -extern int ide_spin_wait_hwgroup(ide_drive_t *); extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id); extern void do_ide_request(struct request_queue *); -- GitLab From 1839faab9a2747bcd30ee14e50575a39bf6735d4 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 10 Oct 2008 14:07:03 -0700 Subject: [PATCH 3843/5416] af_key: fix SADB_X_SPDDELETE response When deleting an SPD entry using SADB_X_SPDDELETE, c.data.byid is not initialized to zero in pfkey_spddelete(). Thus, key_notify_policy() responds with a PF_KEY message of type SADB_X_SPDDELETE2 instead of SADB_X_SPDDELETE. Signed-off-by: Tobias Brunner Signed-off-by: David S. Miller --- net/key/af_key.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/key/af_key.c b/net/key/af_key.c index 362fe317e1f..e55e0441e4d 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2341,6 +2341,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; + c.data.byid = 0; c.event = XFRM_MSG_DELPOLICY; km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); -- GitLab From a2de6b89b74b28052e293fdb39975a5a03c432e0 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 4 Sep 2008 00:17:12 +0200 Subject: [PATCH 3844/5416] r8169: wake up the PHY of the 8168 This is typically needed when some other OS puts the PHY to sleep due to the disabling of WOL options in the BIOS of the system. Signed-off-by: Francois Romieu Tested-by: Chiaki Ishikawa Cc: Edward Hsu Cc: RyanKao --- drivers/net/r8169.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 59fbc64d7c4..9881563898d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -865,9 +865,13 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if ((tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ + if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || + (tp->mac_version == RTL_GIGA_MAC_VER_12) || + (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { + /* + * Wake up the PHY. + * Vendor specific (0x1f) and reserved (0x0e) MII registers. + */ mdio_write(ioaddr, 0x1f, 0x0000); mdio_write(ioaddr, 0x0e, 0x0000); } -- GitLab From f50d4275422415cfb2a5b94bad3b2b229d0ec1aa Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 30 May 2008 16:07:07 +0200 Subject: [PATCH 3845/5416] r8169: update phy init parameters The modified parameters are synced with Realtek's driver version 8.006.00. The change should only be noticeable with some 8168c. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 9881563898d..62e11159156 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1379,26 +1379,45 @@ static void rtl8168c_hw_phy_config(void __iomem *ioaddr) { 0x1f, 0x0003 }, { 0x12, 0xc096 }, { 0x16, 0x000a }, - { 0x1f, 0x0000 } + { 0x1f, 0x0000 }, + { 0x1f, 0x0000 }, + { 0x09, 0x2000 }, + { 0x09, 0x0000 } }; rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); + + mdio_patch(ioaddr, 0x14, 1 << 5); + mdio_patch(ioaddr, 0x0d, 1 << 5); + mdio_write(ioaddr, 0x1f, 0x0000); } static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, + { 0x1f, 0x0001 }, { 0x12, 0x2300 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 }, + { 0x03, 0x802f }, + { 0x02, 0x4f02 }, + { 0x01, 0x0409 }, + { 0x00, 0xf099 }, + { 0x04, 0x9800 }, + { 0x04, 0x9000 }, + { 0x1d, 0x3d98 }, { 0x1f, 0x0002 }, { 0x0c, 0x7eb8 }, + { 0x06, 0x0761 }, + { 0x1f, 0x0003 }, + { 0x16, 0x0f0a }, { 0x1f, 0x0000 } }; rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); + + mdio_patch(ioaddr, 0x16, 1 << 0); + mdio_patch(ioaddr, 0x14, 1 << 5); + mdio_patch(ioaddr, 0x0d, 1 << 5); + mdio_write(ioaddr, 0x1f, 0x0000); } static void rtl8102e_hw_phy_config(void __iomem *ioaddr) -- GitLab From 236b8082aa239e91c3cd9cb466d0527a735e54db Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 30 May 2008 16:11:48 +0200 Subject: [PATCH 3846/5416] r8169: new phy init parameters for the 8168b The new parameters are synced with Realtek's driver version 8.006.00. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 62e11159156..8086bacabcf 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1350,6 +1350,30 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } +static void rtl8168bb_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init[] = { + { 0x10, 0xf41b }, + { 0x1f, 0x0000 } + }; + + mdio_write(ioaddr, 0x1f, 0x0001); + mdio_patch(ioaddr, 0x16, 1 << 0); + + rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); +} + +static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init[] = { + { 0x1f, 0x0001 }, + { 0x10, 0xf41b }, + { 0x1f, 0x0000 } + }; + + rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); +} + static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { @@ -1458,6 +1482,15 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_09: rtl8102e_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_11: + rtl8168bb_hw_phy_config(ioaddr); + break; + case RTL_GIGA_MAC_VER_12: + rtl8168bef_hw_phy_config(ioaddr); + break; + case RTL_GIGA_MAC_VER_17: + rtl8168bef_hw_phy_config(ioaddr); + break; case RTL_GIGA_MAC_VER_18: rtl8168cp_hw_phy_config(ioaddr); break; -- GitLab From b8363901596f64ef74db906df0c4a95daea47464 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 1 Jun 2008 12:31:57 +0200 Subject: [PATCH 3847/5416] r8169: shuffle some registers handling around (8168 operation only) I can not argue strongly for (or against) a specific ordering on a purely technical ground but the patch avoids to swallow Realtek's changes in one big, hard-to-read gulp. Let aside the way the RxConfig register is written (see rtl_set_rx_tx_config_registers / RxConfig / rtl_set_rx_mode), this change brings the registers write ordering closer with Realtek's driver one (version 8.006.00) for the 8168 chipsets. More 8168 specific code which touches the Configx registers will be added in the section covered by Cfg9346_UnLock / Cfg9346_Lock. This code should not be the cause of regression for 810x and 8110 users. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 8086bacabcf..273afb56170 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2396,14 +2396,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_set_rx_max_size(ioaddr); - rtl_set_rx_tx_config_registers(tp); - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; RTL_W16(CPlusCmd, tp->cp_cmd); - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ @@ -2414,14 +2410,19 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_set_rx_tx_desc_registers(tp, ioaddr); - RTL_W8(Cfg9346, Cfg9346_Lock); + rtl_set_rx_mode(dev); + + RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | + (InterFrameGap << TxInterFrameGapShift)); RTL_R8(IntrMask); - rtl_set_rx_mode(dev); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8(Cfg9346, Cfg9346_Lock); + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); RTL_W16(IntrMask, tp->intr_event); -- GitLab From 219a1e9d46dcc21f279c428941ded2328f1a5ee5 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 28 Jun 2008 11:58:39 +0200 Subject: [PATCH 3848/5416] r8169: make room for more specific 8168 hardware start procedure Broadly speaking the 8168c* share some common code which will be factored in __rtl_hw_start_8168cp. The 8168b* share some code too but it will be a bit different. Any change of behavior should be confined to the currently unidentified 8168 chipsets. They will not be applied the Tx performance tweak and will emit a warning instead. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 66 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 273afb56170..60d2ded5571 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1387,7 +1387,7 @@ static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } -static void rtl8168c_hw_phy_config(void __iomem *ioaddr) +static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { { 0x1f, 0x0001 }, @@ -1416,7 +1416,7 @@ static void rtl8168c_hw_phy_config(void __iomem *ioaddr) mdio_write(ioaddr, 0x1f, 0x0000); } -static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) +static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { { 0x1f, 0x0001 }, @@ -1495,10 +1495,10 @@ static void rtl_hw_phy_config(struct net_device *dev) rtl8168cp_hw_phy_config(ioaddr); break; case RTL_GIGA_MAC_VER_19: - rtl8168c_hw_phy_config(ioaddr); + rtl8168c_1_hw_phy_config(ioaddr); break; case RTL_GIGA_MAC_VER_20: - rtl8168cx_hw_phy_config(ioaddr); + rtl8168c_2_hw_phy_config(ioaddr); break; default: break; @@ -2384,6 +2384,36 @@ static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) } } +static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); +} + +static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_hw_start_8168bb(ioaddr, pdev); +} + +static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); +} + +static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) +{ + __rtl_hw_start_8168cp(ioaddr, pdev); +} + +static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) +{ + __rtl_hw_start_8168cp(ioaddr, pdev); +} + +static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) +{ + __rtl_hw_start_8168cp(ioaddr, pdev); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2417,7 +2447,33 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_R8(IntrMask); - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + rtl_hw_start_8168bb(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + rtl_hw_start_8168bef(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_18: + rtl_hw_start_8168cp(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_19: + rtl_hw_start_8168c_1(ioaddr, pdev); + break; + + case RTL_GIGA_MAC_VER_20: + rtl_hw_start_8168c_2(ioaddr, pdev); + break; + + default: + printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", + dev->name, tp->mac_version); + break; + } RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -- GitLab From 2e68ae44309bfadccdb5ddd68b9c38d2a1efeb94 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 28 Jun 2008 12:00:55 +0200 Subject: [PATCH 3849/5416] r8169: 8168b Tx performance tweak Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 60d2ded5571..f929dbada84 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2386,7 +2386,8 @@ static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) { - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, + (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) -- GitLab From b726e493e8dc13537d1d7f8cd66bcd28516606c3 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 28 Jun 2008 12:22:59 +0200 Subject: [PATCH 3850/5416] r8169: sync existing 8168 device hardware start sequences with vendor driver This part of the driver should be reasonably in line with Realtek's 8.006.00 driver. I have left some bits related to jumbo frame and optional features aside for now. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f929dbada84..f0f842d7b94 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2384,8 +2384,38 @@ static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) } } +static void rtl_disable_clock_request(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8169_private *tp = netdev_priv(dev); + int cap = tp->pcie_cap; + + if (cap) { + u16 ctl; + + pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); + ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); + } +} + +#define R8168_CPCMD_QUIRK_MASK (\ + EnableBist | \ + Mac_dbgo_oe | \ + Force_half_dup | \ + Force_rxflow_en | \ + Force_txflow_en | \ + Cxpl_dbg_sel | \ + ASF | \ + PktCntrDisable | \ + Mac_dbgo_sel) + static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) { + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); + rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } @@ -2393,25 +2423,70 @@ static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev) static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev) { rtl_hw_start_8168bb(ioaddr, pdev); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); } static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) { + RTL_W8(Config1, RTL_R8(Config1) | Speed_down); + + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + rtl_disable_clock_request(pdev); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) { + static struct ephy_info e_info_8168cp[] = { + { 0x01, 0, 0x0001 }, + { 0x02, 0x0800, 0x1000 }, + { 0x03, 0, 0x0042 }, + { 0x06, 0x0080, 0x0000 }, + { 0x07, 0, 0x2000 } + }; + + rtl_csi_access_enable(ioaddr); + + rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); + __rtl_hw_start_8168cp(ioaddr, pdev); } static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) { + static struct ephy_info e_info_8168c_1[] = { + { 0x02, 0x0800, 0x1000 }, + { 0x03, 0, 0x0002 }, + { 0x06, 0x0080, 0x0000 } + }; + + rtl_csi_access_enable(ioaddr); + + RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); + + rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); + __rtl_hw_start_8168cp(ioaddr, pdev); } static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) { + static struct ephy_info e_info_8168c_2[] = { + { 0x01, 0, 0x0001 }, + { 0x03, 0x0400, 0x0220 } + }; + + rtl_csi_access_enable(ioaddr); + + rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); + __rtl_hw_start_8168cp(ioaddr, pdev); } -- GitLab From 197ff761dbf9fa5de9a4684a51ee5cb534cbb852 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 28 Jun 2008 13:16:02 +0200 Subject: [PATCH 3851/5416] r8169: add a new 8168c flavor Taken from Realtek's 8.006.00 r8168 driver. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f0f842d7b94..9681aca75af 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -109,7 +109,8 @@ enum mac_version { RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14 // 8168C + RTL_GIGA_MAC_VER_20 = 0x14, // 8168C + RTL_GIGA_MAC_VER_21 = 0x15 // 8168C }; #define _R(NAME,MAC,MASK) \ @@ -139,7 +140,8 @@ static const struct { _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880) // PCI-E }; #undef _R @@ -1220,6 +1222,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, + { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, /* 8168B family. */ @@ -1444,6 +1447,28 @@ static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr) mdio_write(ioaddr, 0x1f, 0x0000); } +static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init[] = { + { 0x1f, 0x0001 }, + { 0x12, 0x2300 }, + { 0x1d, 0x3d98 }, + { 0x1f, 0x0002 }, + { 0x0c, 0x7eb8 }, + { 0x06, 0x5461 }, + { 0x1f, 0x0003 }, + { 0x16, 0x0f0a }, + { 0x1f, 0x0000 } + }; + + rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); + + mdio_patch(ioaddr, 0x16, 1 << 0); + mdio_patch(ioaddr, 0x14, 1 << 5); + mdio_patch(ioaddr, 0x0d, 1 << 5); + mdio_write(ioaddr, 0x1f, 0x0000); +} + static void rtl8102e_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { @@ -1500,6 +1525,9 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_20: rtl8168c_2_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_21: + rtl8168c_3_hw_phy_config(ioaddr); + break; default: break; } @@ -2490,6 +2518,11 @@ static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev) __rtl_hw_start_8168cp(ioaddr, pdev); } +static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_hw_start_8168c_2(ioaddr, pdev); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2545,6 +2578,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168c_2(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_21: + rtl_hw_start_8168c_3(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); -- GitLab From 6fb07058d2b6c748c308e4ee453035433d34ca93 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 29 Jun 2008 11:54:28 +0200 Subject: [PATCH 3852/5416] r8169: add a new 8168c flavor (bis) Taken from Realtek's 8.006.00 r8168 driver. I have left some bits related to jumbo frame aside for now. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 9681aca75af..9a0d4e631af 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -110,7 +110,8 @@ enum mac_version { RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP RTL_GIGA_MAC_VER_19 = 0x13, // 8168C RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15 // 8168C + RTL_GIGA_MAC_VER_21 = 0x15, // 8168C + RTL_GIGA_MAC_VER_22 = 0x16 // 8168C }; #define _R(NAME,MAC,MASK) \ @@ -141,7 +142,8 @@ static const struct { _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880) // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880) // PCI-E }; #undef _R @@ -1223,6 +1225,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, + { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, /* 8168B family. */ @@ -1469,6 +1472,11 @@ static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr) mdio_write(ioaddr, 0x1f, 0x0000); } +static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) +{ + rtl8168c_3_hw_phy_config(ioaddr); +} + static void rtl8102e_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { @@ -1528,6 +1536,9 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_21: rtl8168c_3_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_22: + rtl8168c_4_hw_phy_config(ioaddr); + break; default: break; } @@ -2523,6 +2534,13 @@ static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev) rtl_hw_start_8168c_2(ioaddr, pdev); } +static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable(ioaddr); + + __rtl_hw_start_8168cp(ioaddr, pdev); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2582,6 +2600,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168c_3(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_22: + rtl_hw_start_8168c_4(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); -- GitLab From ef3386f00fcd18a40343047329ec7ed2eb98bbe8 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 29 Jun 2008 12:24:30 +0200 Subject: [PATCH 3853/5416] r8169: add a new 8168cp flavor Taken from Realtek's 8.006.00 r8168 driver. I have left some bits related to jumbo frame aside for now. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 49 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 9a0d4e631af..775dc84336b 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -111,7 +111,8 @@ enum mac_version { RTL_GIGA_MAC_VER_19 = 0x13, // 8168C RTL_GIGA_MAC_VER_20 = 0x14, // 8168C RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16 // 8168C + RTL_GIGA_MAC_VER_22 = 0x16, // 8168C + RTL_GIGA_MAC_VER_23 = 0x17 // 8168CP }; #define _R(NAME,MAC,MASK) \ @@ -143,7 +144,8 @@ static const struct { _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880) // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880) // PCI-E }; #undef _R @@ -1221,6 +1223,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, int mac_version; } mac_info[] = { /* 8168B family. */ + { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, @@ -1380,7 +1383,7 @@ static void rtl8168bef_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } -static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) +static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { { 0x1f, 0x0000 }, @@ -1393,6 +1396,21 @@ static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } +static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init[] = { + { 0x1f, 0x0001 }, + { 0x1d, 0x3d98 }, + { 0x1f, 0x0000 } + }; + + mdio_write(ioaddr, 0x1f, 0x0000); + mdio_patch(ioaddr, 0x14, 1 << 5); + mdio_patch(ioaddr, 0x0d, 1 << 5); + + rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); +} + static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { @@ -1525,7 +1543,7 @@ static void rtl_hw_phy_config(struct net_device *dev) rtl8168bef_hw_phy_config(ioaddr); break; case RTL_GIGA_MAC_VER_18: - rtl8168cp_hw_phy_config(ioaddr); + rtl8168cp_1_hw_phy_config(ioaddr); break; case RTL_GIGA_MAC_VER_19: rtl8168c_1_hw_phy_config(ioaddr); @@ -1539,6 +1557,10 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_22: rtl8168c_4_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_23: + rtl8168cp_2_hw_phy_config(ioaddr); + break; + default: break; } @@ -2481,7 +2503,7 @@ static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } -static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) +static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev) { static struct ephy_info e_info_8168cp[] = { { 0x01, 0, 0x0001 }, @@ -2498,6 +2520,17 @@ static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev) __rtl_hw_start_8168cp(ioaddr, pdev); } +static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable(ioaddr); + + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); +} + static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) { static struct ephy_info e_info_8168c_1[] = { @@ -2585,7 +2618,7 @@ static void rtl_hw_start_8168(struct net_device *dev) break; case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp(ioaddr, pdev); + rtl_hw_start_8168cp_1(ioaddr, pdev); break; case RTL_GIGA_MAC_VER_19: @@ -2604,6 +2637,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168c_4(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_23: + rtl_hw_start_8168cp_2(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); -- GitLab From ef808d502cc3b18b2d823bbe8c03c0b8ea0df1b5 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 29 Jun 2008 13:10:54 +0200 Subject: [PATCH 3854/5416] r8169: change default behavior for mildly identified 8168c chipsets The addition of a new device has so far implied a specialization of these masks. While they identify 8168c devices, they can be expected to be further refined as they have been by Realtek so far. The change should bring the driver closer to the version 8.006.00 of Realtek's 8168 driver. Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 775dc84336b..4edc6b0d2b9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1222,14 +1222,15 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { - /* 8168B family. */ + /* 8168C family. */ { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, + { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, + { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_23 }, { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 }, + { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, /* 8168B family. */ { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, -- GitLab From 7f3e3d3a69da262016db6eec803881603c61ddf6 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 20 Jul 2008 18:53:20 +0200 Subject: [PATCH 3855/5416] r8169: support additional 8168cp chipset Taken from Realtek's 8.007.00 r8168 driver. Signed-off-by: Francois Romieu Fixed-by: Ivan Vecera Cc: Edward Hsu --- drivers/net/r8169.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4edc6b0d2b9..96b9b0bb470 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -112,7 +112,8 @@ enum mac_version { RTL_GIGA_MAC_VER_20 = 0x14, // 8168C RTL_GIGA_MAC_VER_21 = 0x15, // 8168C RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17 // 8168CP + RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP + RTL_GIGA_MAC_VER_24 = 0x18 // 8168CP }; #define _R(NAME,MAC,MASK) \ @@ -145,7 +146,8 @@ static const struct { _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880) // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880) // PCI-E }; #undef _R @@ -1223,9 +1225,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, int mac_version; } mac_info[] = { /* 8168C family. */ + { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_23 }, + { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, @@ -1559,6 +1562,7 @@ static void rtl_hw_phy_config(struct net_device *dev) rtl8168c_4_hw_phy_config(ioaddr); break; case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: rtl8168cp_2_hw_phy_config(ioaddr); break; @@ -2532,6 +2536,22 @@ static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev) RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } +static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable(ioaddr); + + RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); + + /* Magic. */ + RTL_W8(DBG_REG, 0x20); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); +} + static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev) { static struct ephy_info e_info_8168c_1[] = { @@ -2642,6 +2662,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168cp_2(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_24: + rtl_hw_start_8168cp_3(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); -- GitLab From 5b538df9dedb3469b688b93ffab2a7efb64c88e3 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 20 Jul 2008 16:22:45 +0200 Subject: [PATCH 3856/5416] r8169: preliminary 8168d support Taken from Realtek's 8.007.00 r8168 driver. Signed-off-by: Francois Romieu Fixed-by: Ivan Vecera Cc: Edward Hsu --- drivers/net/r8169.c | 99 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 96b9b0bb470..02b11a0814d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -113,7 +113,8 @@ enum mac_version { RTL_GIGA_MAC_VER_21 = 0x15, // 8168C RTL_GIGA_MAC_VER_22 = 0x16, // 8168C RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18 // 8168CP + RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP + RTL_GIGA_MAC_VER_25 = 0x19 // 8168D }; #define _R(NAME,MAC,MASK) \ @@ -147,7 +148,8 @@ static const struct { _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880) // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E + _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E }; #undef _R @@ -1224,6 +1226,9 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { + /* 8168D family. */ + { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, + /* 8168C family. */ { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, @@ -1499,6 +1504,76 @@ static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr) rtl8168c_3_hw_phy_config(ioaddr); } +static void rtl8168d_hw_phy_config(void __iomem *ioaddr) +{ + struct phy_reg phy_reg_init_0[] = { + { 0x1f, 0x0001 }, + { 0x09, 0x2770 }, + { 0x08, 0x04d0 }, + { 0x0b, 0xad15 }, + { 0x0c, 0x5bf0 }, + { 0x1c, 0xf101 }, + { 0x1f, 0x0003 }, + { 0x14, 0x94d7 }, + { 0x12, 0xf4d6 }, + { 0x09, 0xca0f }, + { 0x1f, 0x0002 }, + { 0x0b, 0x0b10 }, + { 0x0c, 0xd1f7 }, + { 0x1f, 0x0002 }, + { 0x06, 0x5461 }, + { 0x1f, 0x0002 }, + { 0x05, 0x6662 }, + { 0x1f, 0x0000 }, + { 0x14, 0x0060 }, + { 0x1f, 0x0000 }, + { 0x0d, 0xf8a0 }, + { 0x1f, 0x0005 }, + { 0x05, 0xffc2 } + }; + + rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); + + if (mdio_read(ioaddr, 0x06) == 0xc400) { + struct phy_reg phy_reg_init_1[] = { + { 0x1f, 0x0005 }, + { 0x01, 0x0300 }, + { 0x1f, 0x0000 }, + { 0x11, 0x401c }, + { 0x16, 0x4100 }, + { 0x1f, 0x0005 }, + { 0x07, 0x0010 }, + { 0x05, 0x83dc }, + { 0x06, 0x087d }, + { 0x05, 0x8300 }, + { 0x06, 0x0101 }, + { 0x06, 0x05f8 }, + { 0x06, 0xf9fa }, + { 0x06, 0xfbef }, + { 0x06, 0x79e2 }, + { 0x06, 0x835f }, + { 0x06, 0xe0f8 }, + { 0x06, 0x9ae1 }, + { 0x06, 0xf89b }, + { 0x06, 0xef31 }, + { 0x06, 0x3b65 }, + { 0x06, 0xaa07 }, + { 0x06, 0x81e4 }, + { 0x06, 0xf89a }, + { 0x06, 0xe5f8 }, + { 0x06, 0x9baf }, + { 0x06, 0x06ae }, + { 0x05, 0x83dc }, + { 0x06, 0x8300 }, + }; + + rtl_phy_write(ioaddr, phy_reg_init_1, + ARRAY_SIZE(phy_reg_init_1)); + } + + mdio_write(ioaddr, 0x1f, 0x0000); +} + static void rtl8102e_hw_phy_config(void __iomem *ioaddr) { struct phy_reg phy_reg_init[] = { @@ -1565,6 +1640,9 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_24: rtl8168cp_2_hw_phy_config(ioaddr); break; + case RTL_GIGA_MAC_VER_25: + rtl8168d_hw_phy_config(ioaddr); + break; default: break; @@ -2595,6 +2673,19 @@ static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev) __rtl_hw_start_8168cp(ioaddr, pdev); } +static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable(ioaddr); + + rtl_disable_clock_request(pdev); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -2666,6 +2757,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168cp_3(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_25: + rtl_hw_start_8168d(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); -- GitLab From 1765f95d2db0a516b5816e016fdf459c4bb5affb Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 13 Sep 2008 17:21:40 +0200 Subject: [PATCH 3857/5416] r8169: add shutdown handler Signed-off-by: Francois Romieu Cc: Edward Hsu --- drivers/net/r8169.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 02b11a0814d..bdae2c59a75 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3874,6 +3874,11 @@ out: return 0; } +static void rtl_shutdown(struct pci_dev *pdev) +{ + rtl8169_suspend(pdev, PMSG_SUSPEND); +} + #endif /* CONFIG_PM */ static struct pci_driver rtl8169_pci_driver = { @@ -3884,6 +3889,7 @@ static struct pci_driver rtl8169_pci_driver = { #ifdef CONFIG_PM .suspend = rtl8169_suspend, .resume = rtl8169_resume, + .shutdown = rtl_shutdown, #endif }; -- GitLab From 2ef3783608668a32e497a16cb8696cee9b0aa47c Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 10 Oct 2008 14:33:37 -0700 Subject: [PATCH 3858/5416] myri10ge: update driver version number to 1.4.3-1.369 Update myri10ge driver version number to 1.4.3-1.369. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 8cec6f3c2f8..6dce901c7f4 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.3-1.358" +#define MYRI10GE_VERSION_STR "1.4.3-1.369" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); -- GitLab From f89c5edb86abfac4c914f4eb808b07684164eca0 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Sat, 11 Oct 2008 09:03:39 +1100 Subject: [PATCH 3859/5416] Remove the BKL calls from the TPM driver, which were added in the overall misc-char-dev-BKL-pushdown.patch, as they are not needed. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Cc: "Serge E. Hallyn" Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ae766d86845..ceba6082bd9 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -954,13 +954,16 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel); /* * Device file system interface to the TPM + * + * It's assured that the chip will be opened just once, + * by the check of is_open variable, which is protected + * by driver_lock. */ int tpm_open(struct inode *inode, struct file *file) { int rc = 0, minor = iminor(inode); struct tpm_chip *chip = NULL, *pos; - lock_kernel(); spin_lock(&driver_lock); list_for_each_entry(pos, &tpm_chip_list, list) { @@ -990,19 +993,16 @@ int tpm_open(struct inode *inode, struct file *file) if (chip->data_buffer == NULL) { chip->num_opens--; put_device(chip->dev); - unlock_kernel(); return -ENOMEM; } atomic_set(&chip->data_pending, 0); file->private_data = chip; - unlock_kernel(); return 0; err_out: spin_unlock(&driver_lock); - unlock_kernel(); return rc; } EXPORT_SYMBOL_GPL(tpm_open); -- GitLab From dc36d32cc5bea5e985294c79995e10a159c3019a Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Sat, 11 Oct 2008 09:04:02 +1100 Subject: [PATCH 3860/5416] Renames num_open to is_open, as only one process can open the file at a time. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Cc: "Serge E. Hallyn" Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 7 +++---- drivers/char/tpm/tpm.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ceba6082bd9..dfd4e7fc350 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -978,20 +978,19 @@ int tpm_open(struct inode *inode, struct file *file) goto err_out; } - if (chip->num_opens) { + if (test_and_set_bit(0, &chip->is_open)) { dev_dbg(chip->dev, "Another process owns this TPM\n"); rc = -EBUSY; goto err_out; } - chip->num_opens++; get_device(chip->dev); spin_unlock(&driver_lock); chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (chip->data_buffer == NULL) { - chip->num_opens--; + clear_bit(0, &chip->is_open); put_device(chip->dev); return -ENOMEM; } @@ -1016,7 +1015,7 @@ int tpm_release(struct inode *inode, struct file *file) file->private_data = NULL; del_singleshot_timer_sync(&chip->user_read_timer); atomic_set(&chip->data_pending, 0); - chip->num_opens--; + clear_bit(0, &chip->is_open); put_device(chip->dev); kfree(chip->data_buffer); spin_unlock(&driver_lock); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e885148b4cf..2756cab9aee 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -90,7 +90,7 @@ struct tpm_chip { struct device *dev; /* Device stuff */ int dev_num; /* /dev/tpm# */ - int num_opens; /* only one allowed */ + unsigned long is_open; /* only one allowed */ int time_expired; /* Data passed to and from the tpm via the read/write calls */ -- GitLab From f02a93645e6200a9da0f26dac8ced28c612f5e86 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Sat, 11 Oct 2008 09:04:23 +1100 Subject: [PATCH 3861/5416] Protect tpm_chip_list when transversing it. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Acked-by: Serge E. Hallyn Cc: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 61 +++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index dfd4e7fc350..4f18f84b498 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -961,33 +961,28 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel); */ int tpm_open(struct inode *inode, struct file *file) { - int rc = 0, minor = iminor(inode); + int minor = iminor(inode); struct tpm_chip *chip = NULL, *pos; - spin_lock(&driver_lock); - - list_for_each_entry(pos, &tpm_chip_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(pos, &tpm_chip_list, list) { if (pos->vendor.miscdev.minor == minor) { chip = pos; + get_device(chip->dev); break; } } + rcu_read_unlock(); - if (chip == NULL) { - rc = -ENODEV; - goto err_out; - } + if (!chip) + return -ENODEV; if (test_and_set_bit(0, &chip->is_open)) { dev_dbg(chip->dev, "Another process owns this TPM\n"); - rc = -EBUSY; - goto err_out; + put_device(chip->dev); + return -EBUSY; } - get_device(chip->dev); - - spin_unlock(&driver_lock); - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (chip->data_buffer == NULL) { clear_bit(0, &chip->is_open); @@ -999,26 +994,23 @@ int tpm_open(struct inode *inode, struct file *file) file->private_data = chip; return 0; - -err_out: - spin_unlock(&driver_lock); - return rc; } EXPORT_SYMBOL_GPL(tpm_open); +/* + * Called on file close + */ int tpm_release(struct inode *inode, struct file *file) { struct tpm_chip *chip = file->private_data; flush_scheduled_work(); - spin_lock(&driver_lock); file->private_data = NULL; del_singleshot_timer_sync(&chip->user_read_timer); atomic_set(&chip->data_pending, 0); + kfree(chip->data_buffer); clear_bit(0, &chip->is_open); put_device(chip->dev); - kfree(chip->data_buffer); - spin_unlock(&driver_lock); return 0; } EXPORT_SYMBOL_GPL(tpm_release); @@ -1092,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev) } spin_lock(&driver_lock); - - list_del(&chip->list); - + list_del_rcu(&chip->list); spin_unlock(&driver_lock); + synchronize_rcu(); misc_deregister(&chip->vendor.miscdev); - sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); tpm_bios_log_teardown(chip->bios_dir); @@ -1146,8 +1136,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); /* * Once all references to platform device are down to 0, * release all allocated structures. - * In case vendor provided release function, - * call it too. + * In case vendor provided release function, call it too. */ static void tpm_dev_release(struct device *dev) { @@ -1155,7 +1144,6 @@ static void tpm_dev_release(struct device *dev) if (chip->vendor.release) chip->vendor.release(dev); - chip->release(dev); clear_bit(chip->dev_num, dev_mask); @@ -1170,8 +1158,8 @@ static void tpm_dev_release(struct device *dev) * upon errant exit from this function specific probe function should call * pci_disable_device */ -struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific - *entry) +struct tpm_chip *tpm_register_hardware(struct device *dev, + const struct tpm_vendor_specific *entry) { #define DEVNAME_SIZE 7 @@ -1230,21 +1218,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend return NULL; } - spin_lock(&driver_lock); - - list_add(&chip->list, &tpm_chip_list); - - spin_unlock(&driver_lock); - if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { - list_del(&chip->list); misc_deregister(&chip->vendor.miscdev); put_device(chip->dev); + return NULL; } chip->bios_dir = tpm_bios_log_setup(devname); + /* Make chip available */ + spin_lock(&driver_lock); + list_add_rcu(&chip->list, &tpm_chip_list); + spin_unlock(&driver_lock); + return chip; } EXPORT_SYMBOL_GPL(tpm_register_hardware); -- GitLab From 253115b71fa06330bd58afbe01ccaf763a8a0cf1 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Sat, 11 Oct 2008 09:04:39 +1100 Subject: [PATCH 3862/5416] The tpm_dev_release function is only called for platform devices, not pnp devices, so we implemented the .remove function for pnp ones. Since it's code is very similar to the one inside tpm_dev_release, we've created a helper function tpm_dev_vendor_release, which is called by both. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Cc: "Serge E. Hallyn" Cc: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 22 ++++++++++++++++------ drivers/char/tpm/tpm.h | 1 + drivers/char/tpm/tpm_tis.c | 14 +++++++++++++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 4f18f84b498..02a495c2e06 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1133,23 +1133,33 @@ int tpm_pm_resume(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_pm_resume); +/* In case vendor provided release function, call it too.*/ + +void tpm_dev_vendor_release(struct tpm_chip *chip) +{ + if (chip->vendor.release) + chip->vendor.release(chip->dev); + + clear_bit(chip->dev_num, dev_mask); + kfree(chip->vendor.miscdev.name); +} +EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); + + /* * Once all references to platform device are down to 0, * release all allocated structures. - * In case vendor provided release function, call it too. */ static void tpm_dev_release(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip->vendor.release) - chip->vendor.release(dev); - chip->release(dev); + tpm_dev_vendor_release(chip); - clear_bit(chip->dev_num, dev_mask); - kfree(chip->vendor.miscdev.name); + chip->release(dev); kfree(chip); } +EXPORT_SYMBOL_GPL(tpm_dev_release); /* * Called from tpm_.c probe function only for devices diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 2756cab9aee..8e30df4a438 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); extern int tpm_open(struct inode *, struct file *); extern int tpm_release(struct inode *, struct file *); +extern void tpm_dev_vendor_release(struct tpm_chip *); extern ssize_t tpm_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index ed1879c0dd8..717af7ad1bd 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"", 0} /* Terminator */ }; +static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) +{ + struct tpm_chip *chip = pnp_get_drvdata(dev); + + tpm_dev_vendor_release(chip); + + kfree(chip); +} + + static struct pnp_driver tis_pnp_driver = { .name = "tpm_tis", .id_table = tpm_pnp_tbl, .probe = tpm_tis_pnp_init, .suspend = tpm_tis_pnp_suspend, .resume = tpm_tis_pnp_resume, + .remove = tpm_tis_pnp_remove, }; #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 @@ -683,6 +694,7 @@ static void __exit cleanup_tis(void) spin_lock(&tis_lock); list_for_each_entry_safe(i, j, &tis_chips, list) { chip = to_tpm_chip(i); + tpm_remove_hardware(chip->dev); iowrite32(~TPM_GLOBAL_INT_ENABLE & ioread32(chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor. @@ -694,9 +706,9 @@ static void __exit cleanup_tis(void) free_irq(chip->vendor.irq, chip); iounmap(i->iobase); list_del(&i->list); - tpm_remove_hardware(chip->dev); } spin_unlock(&tis_lock); + if (force) { platform_device_unregister(pdev); driver_unregister(&tis_drv); -- GitLab From 15c220d003f7914aab99cdb71cd7834a0c9b4557 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 11 Oct 2008 09:04:48 +1100 Subject: [PATCH 3863/5416] ERROR: code indent should use tabs where possible #32: FILE: drivers/char/tpm/tpm.c:1148: +^I ^Ichip->vendor.release(chip->dev);$ total: 1 errors, 0 warnings, 86 lines checked ./patches/tpm-addition-of-pnp_remove.patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Please run checkpatch prior to sending patches Cc: "Serge E. Hallyn" Cc: Bjorn Helgaas Cc: Mimi Zohar Cc: Rajiv Andrade Signed-off-by: Andrew Morton Signed-off-by: James Morris -- GitLab From 4bdec11f560b8f405a011288a50e65b1a81b3654 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Sat, 11 Oct 2008 09:05:20 +1100 Subject: [PATCH 3864/5416] As pointed out by Jonathan Corbet, the timer must be deleted before flushing the work queue in order to avoid a job being submitted after the chip had been released. Signed-off-by: Rajiv Andrade Signed-off-by: Mimi Zohar Cc: Jonathan Corbet Cc: "Serge E. Hallyn" Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 02a495c2e06..1fee7034a38 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1004,9 +1004,9 @@ int tpm_release(struct inode *inode, struct file *file) { struct tpm_chip *chip = file->private_data; + del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); file->private_data = NULL; - del_singleshot_timer_sync(&chip->user_read_timer); atomic_set(&chip->data_pending, 0); kfree(chip->data_buffer); clear_bit(0, &chip->is_open); -- GitLab From 03010a3350301baac2154fa66de925ae2981b7e3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 10 Oct 2008 20:02:48 -0400 Subject: [PATCH 3865/5416] ext4: Rename ext4dev to ext4 The ext4 filesystem is getting stable enough that it's time to drop the "dev" prefix. Also remove the requirement for the TEST_FILESYS flag. Signed-off-by: "Theodore Ts'o" --- Documentation/filesystems/ext4.txt | 8 +-- fs/Kconfig | 88 +++++++++++++++++------------- fs/Makefile | 2 +- fs/ext4/Makefile | 10 ++-- fs/ext4/acl.h | 6 +- fs/ext4/ext4_i.h | 4 +- fs/ext4/file.c | 2 +- fs/ext4/inode.c | 2 +- fs/ext4/namei.c | 6 +- fs/ext4/super.c | 63 ++++++++++++++------- fs/ext4/symlink.c | 4 +- fs/ext4/xattr.c | 8 +-- fs/ext4/xattr.h | 8 +-- 13 files changed, 123 insertions(+), 88 deletions(-) diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 289057958f9..74484e69640 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -32,9 +32,9 @@ Mailing list: linux-ext4@vger.kernel.org you will need to merge your changes with the version from e2fsprogs 1.41.x. - - Create a new filesystem using the ext4dev filesystem type: + - Create a new filesystem using the ext4 filesystem type: - # mke2fs -t ext4dev /dev/hda1 + # mke2fs -t ext4 /dev/hda1 Or configure an existing ext3 filesystem to support extents and set the test_fs flag to indicate that it's ok for an in-development @@ -47,13 +47,13 @@ Mailing list: linux-ext4@vger.kernel.org # tune2fs -I 256 /dev/hda1 - (Note: we currently do not have tools to convert an ext4dev + (Note: we currently do not have tools to convert an ext4 filesystem back to ext3; so please do not do try this on production filesystems.) - Mounting: - # mount -t ext4dev /dev/hda1 /wherever + # mount -t ext4 /dev/hda1 /wherever - When comparing performance with other filesystems, remember that ext3/4 by default offers higher data integrity guarantees than most. diff --git a/fs/Kconfig b/fs/Kconfig index abccb5dab9a..40183d94b68 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -136,37 +136,51 @@ config EXT3_FS_SECURITY If you are not using a security module that requires using extended attributes for file security labels, say N. -config EXT4DEV_FS - tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)" - depends on EXPERIMENTAL +config EXT4_FS + tristate "The Extended 4 (ext4) filesystem" select JBD2 select CRC16 help - Ext4dev is a predecessor filesystem of the next generation - extended fs ext4, based on ext3 filesystem code. It will be - renamed ext4 fs later, once ext4dev is mature and stabilized. + This is the next generation of the ext3 filesystem. Unlike the change from ext2 filesystem to ext3 filesystem, - the on-disk format of ext4dev is not the same as ext3 any more: - it is based on extent maps and it supports 48-bit physical block - numbers. These combined on-disk format changes will allow - ext4dev/ext4 to handle more than 16 TB filesystem volumes -- - a hard limit that ext3 cannot overcome without changing the - on-disk format. - - Other than extent maps and 48-bit block numbers, ext4dev also is - likely to have other new features such as persistent preallocation, - high resolution time stamps, and larger file support etc. These - features will be added to ext4dev gradually. + the on-disk format of ext4 is not forwards compatible with + ext3; it is based on extent maps and it supports 48-bit + physical block numbers. The ext4 filesystem also supports delayed + allocation, persistent preallocation, high resolution time stamps, + and a number of other features to improve performance and speed + up fsck time. For more information, please see the web pages at + http://ext4.wiki.kernel.org. + + The ext4 filesystem will support mounting an ext3 + filesystem; while there will be some performance gains from + the delayed allocation and inode table readahead, the best + performance gains will require enabling ext4 features in the + filesystem, or formating a new filesystem as an ext4 + filesystem initially. To compile this file system support as a module, choose M here. The module will be called ext4dev. If unsure, say N. -config EXT4DEV_FS_XATTR - bool "Ext4dev extended attributes" - depends on EXT4DEV_FS +config EXT4DEV_COMPAT + bool "Enable ext4dev compatibility" + depends on EXT4_FS + help + Starting with 2.6.28, the name of the ext4 filesystem was + renamed from ext4dev to ext4. Unfortunately there are some + lagecy userspace programs (such as klibc's fstype) have + "ext4dev" hardcoded. + + To enable backwards compatibility so that systems that are + still expecting to mount ext4 filesystems using ext4dev, + chose Y here. This feature will go away by 2.6.31, so + please arrange to get your userspace programs fixed! + +config EXT4_FS_XATTR + bool "Ext4 extended attributes" + depends on EXT4_FS default y help Extended attributes are name:value pairs associated with inodes by @@ -175,11 +189,11 @@ config EXT4DEV_FS_XATTR If unsure, say N. - You need this for POSIX ACL support on ext4dev/ext4. + You need this for POSIX ACL support on ext4. -config EXT4DEV_FS_POSIX_ACL - bool "Ext4dev POSIX Access Control Lists" - depends on EXT4DEV_FS_XATTR +config EXT4_FS_POSIX_ACL + bool "Ext4 POSIX Access Control Lists" + depends on EXT4_FS_XATTR select FS_POSIX_ACL help POSIX Access Control Lists (ACLs) support permissions for users and @@ -190,14 +204,14 @@ config EXT4DEV_FS_POSIX_ACL If you don't know what Access Control Lists are, say N -config EXT4DEV_FS_SECURITY - bool "Ext4dev Security Labels" - depends on EXT4DEV_FS_XATTR +config EXT4_FS_SECURITY + bool "Ext4 Security Labels" + depends on EXT4_FS_XATTR help Security labels support alternative access control models implemented by security modules like SELinux. This option enables an extended attribute handler for file security - labels in the ext4dev/ext4 filesystem. + labels in the ext4 filesystem. If you are not using a security module that requires using extended attributes for file security labels, say N. @@ -240,22 +254,22 @@ config JBD2 help This is a generic journaling layer for block devices that support both 32-bit and 64-bit block numbers. It is currently used by - the ext4dev/ext4 filesystem, but it could also be used to add + the ext4 filesystem, but it could also be used to add journal support to other file systems or block devices such as RAID or LVM. - If you are using ext4dev/ext4, you need to say Y here. If you are not - using ext4dev/ext4 then you will probably want to say N. + If you are using ext4, you need to say Y here. If you are not + using ext4 then you will probably want to say N. To compile this device as a module, choose M here. The module will be - called jbd2. If you are compiling ext4dev/ext4 into the kernel, + called jbd2. If you are compiling ext4 into the kernel, you cannot compile this code as a module. config JBD2_DEBUG - bool "JBD2 (ext4dev/ext4) debugging support" + bool "JBD2 (ext4) debugging support" depends on JBD2 && DEBUG_FS help - If you are using the ext4dev/ext4 journaled file system (or + If you are using the ext4 journaled file system (or potentially any other filesystem/device using JBD2), this option allows you to enable debugging output while the system is running, in order to help track down any problems you are having. @@ -270,9 +284,9 @@ config JBD2_DEBUG config FS_MBCACHE # Meta block cache for Extended Attributes (ext2/ext3/ext4) tristate - depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR - default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y - default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m + depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR + default y if EXT2_FS=y || EXT3_FS=y || EXT4_FS=y + default m if EXT2_FS=m || EXT3_FS=m || EXT4_FS=m config REISERFS_FS tristate "Reiserfs support" diff --git a/fs/Makefile b/fs/Makefile index a1482a5eff1..de404b00eb0 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -69,7 +69,7 @@ obj-$(CONFIG_DLM) += dlm/ # Do not add any filesystems before this line obj-$(CONFIG_REISERFS_FS) += reiserfs/ obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 -obj-$(CONFIG_EXT4DEV_FS) += ext4/ # Before ext2 so root fs can be ext4dev +obj-$(CONFIG_EXT4_FS) += ext4/ # Before ext2 so root fs can be ext4dev obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index ac6fa8ca0a2..a8ff003a00f 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -2,12 +2,12 @@ # Makefile for the linux ext4-filesystem routines. # -obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o +obj-$(CONFIG_EXT4_FS) += ext4.o -ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ +ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ ext4_jbd2.o migrate.o mballoc.o -ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o -ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o -ext4dev-$(CONFIG_EXT4DEV_FS_SECURITY) += xattr_security.o +ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o +ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o +ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h index 4c9948f69f8..cb45257a246 100644 --- a/fs/ext4/acl.h +++ b/fs/ext4/acl.h @@ -51,7 +51,7 @@ static inline int ext4_acl_count(size_t size) } } -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL /* Value for inode->u.ext4_i.i_acl and inode->u.ext4_i.i_default_acl if the ACL has not been cached */ @@ -62,7 +62,7 @@ extern int ext4_permission(struct inode *, int); extern int ext4_acl_chmod(struct inode *); extern int ext4_init_acl(handle_t *, struct inode *, struct inode *); -#else /* CONFIG_EXT4DEV_FS_POSIX_ACL */ +#else /* CONFIG_EXT4_FS_POSIX_ACL */ #include #define ext4_permission NULL @@ -77,5 +77,5 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) { return 0; } -#endif /* CONFIG_EXT4DEV_FS_POSIX_ACL */ +#endif /* CONFIG_EXT4_FS_POSIX_ACL */ diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h index 2875eeca172..5c124c0ac6d 100644 --- a/fs/ext4/ext4_i.h +++ b/fs/ext4/ext4_i.h @@ -66,7 +66,7 @@ struct ext4_inode_info { __u32 i_state; /* Dynamic state flags for ext4 */ ext4_lblk_t i_dir_start_lookup; -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR /* * Extended attributes can be read independently of the main file * data. Taking i_mutex even when reading would cause contention @@ -76,7 +76,7 @@ struct ext4_inode_info { */ struct rw_semaphore xattr_sem; #endif -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL struct posix_acl *i_acl; struct posix_acl *i_default_acl; #endif diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 6d5be156202..6bd11fba71f 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -165,7 +165,7 @@ const struct inode_operations ext4_file_inode_operations = { .truncate = ext4_truncate, .setattr = ext4_setattr, .getattr = ext4_getattr, -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext4_listxattr, diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a4747867411..9b4ec9decfd 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4041,7 +4041,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL ei->i_acl = EXT4_ACL_NOT_CACHED; ei->i_default_acl = EXT4_ACL_NOT_CACHED; #endif diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5295a9225cf..92db9e94514 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1773,7 +1773,7 @@ retry: err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR inode->i_op = &ext4_special_inode_operations; #endif err = ext4_add_nondir(handle, dentry, inode); @@ -2456,7 +2456,7 @@ const struct inode_operations ext4_dir_inode_operations = { .mknod = ext4_mknod, .rename = ext4_rename, .setattr = ext4_setattr, -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext4_listxattr, @@ -2467,7 +2467,7 @@ const struct inode_operations ext4_dir_inode_operations = { const struct inode_operations ext4_special_inode_operations = { .setattr = ext4_setattr, -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext4_listxattr, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7d865608e81..0e661c56966 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -569,7 +569,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); if (!ei) return NULL; -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL ei->i_acl = EXT4_ACL_NOT_CACHED; ei->i_default_acl = EXT4_ACL_NOT_CACHED; #endif @@ -605,7 +605,7 @@ static void init_once(void *foo) struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; INIT_LIST_HEAD(&ei->i_orphan); -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR init_rwsem(&ei->xattr_sem); #endif init_rwsem(&ei->i_data_sem); @@ -631,7 +631,7 @@ static void destroy_inodecache(void) static void ext4_clear_inode(struct inode *inode) { -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL if (EXT4_I(inode)->i_acl && EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { posix_acl_release(EXT4_I(inode)->i_acl); @@ -720,7 +720,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",debug"); if (test_opt(sb, OLDALLOC)) seq_puts(seq, ",oldalloc"); -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR if (test_opt(sb, XATTR_USER) && !(def_mount_opts & EXT4_DEFM_XATTR_USER)) seq_puts(seq, ",user_xattr"); @@ -729,7 +729,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",nouser_xattr"); } #endif -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) seq_puts(seq, ",acl"); if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) @@ -1078,7 +1078,7 @@ static int parse_options(char *options, struct super_block *sb, case Opt_orlov: clear_opt(sbi->s_mount_opt, OLDALLOC); break; -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR case Opt_user_xattr: set_opt(sbi->s_mount_opt, XATTR_USER); break; @@ -1092,7 +1092,7 @@ static int parse_options(char *options, struct super_block *sb, "not supported\n"); break; #endif -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL case Opt_acl: set_opt(sbi->s_mount_opt, POSIX_ACL); break; @@ -1987,11 +1987,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) set_opt(sbi->s_mount_opt, GRPID); if (def_mount_opts & EXT4_DEFM_UID16) set_opt(sbi->s_mount_opt, NO_UID32); -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR if (def_mount_opts & EXT4_DEFM_XATTR_USER) set_opt(sbi->s_mount_opt, XATTR_USER); #endif -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL if (def_mount_opts & EXT4_DEFM_ACL) set_opt(sbi->s_mount_opt, POSIX_ACL); #endif @@ -2049,16 +2049,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) "EXT4-fs warning: feature flags set on rev 0 fs, " "running e2fsck is recommended\n"); - /* - * Since ext4 is still considered development code, we require - * that the TEST_FILESYS flag in s->flags be set. - */ - if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) { - printk(KERN_WARNING "EXT4-fs: %s: not marked " - "OK to use with test code.\n", sb->s_id); - goto failed_mount; - } - /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, @@ -3580,13 +3570,34 @@ const struct file_operations ext4_ui_proc_fops = { }; #endif +static struct file_system_type ext4_fs_type = { + .owner = THIS_MODULE, + .name = "ext4", + .get_sb = ext4_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +#ifdef CONFIG_EXT4DEV_COMPAT +static int ext4dev_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) +{ + printk(KERN_WARNING "EXT4-fs: Update your userspace programs " + "to mount using ext4\n"); + printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility " + "will go away by 2.6.31\n"); + return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); +} + static struct file_system_type ext4dev_fs_type = { .owner = THIS_MODULE, .name = "ext4dev", - .get_sb = ext4_get_sb, + .get_sb = ext4dev_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; +MODULE_ALIAS("ext4dev"); +#endif static int __init init_ext4_fs(void) { @@ -3603,9 +3614,16 @@ static int __init init_ext4_fs(void) err = init_inodecache(); if (err) goto out1; - err = register_filesystem(&ext4dev_fs_type); + err = register_filesystem(&ext4_fs_type); if (err) goto out; +#ifdef CONFIG_EXT4DEV_COMPAT + err = register_filesystem(&ext4dev_fs_type); + if (err) { + unregister_filesystem(&ext4_fs_type); + goto out; + } +#endif return 0; out: destroy_inodecache(); @@ -3618,7 +3636,10 @@ out2: static void __exit exit_ext4_fs(void) { + unregister_filesystem(&ext4_fs_type); +#ifdef CONFIG_EXT4DEV_COMPAT unregister_filesystem(&ext4dev_fs_type); +#endif destroy_inodecache(); exit_ext4_xattr(); exit_ext4_mballoc(); diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 0013d52f73b..00740cb32be 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c @@ -34,7 +34,7 @@ const struct inode_operations ext4_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext4_listxattr, @@ -45,7 +45,7 @@ const struct inode_operations ext4_symlink_inode_operations = { const struct inode_operations ext4_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ext4_follow_link, -#ifdef CONFIG_EXT4DEV_FS_XATTR +#ifdef CONFIG_EXT4_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext4_listxattr, diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 362b0edd3db..80626d516fe 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -99,12 +99,12 @@ static struct mb_cache *ext4_xattr_cache; static struct xattr_handler *ext4_xattr_handler_map[] = { [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL [EXT4_XATTR_INDEX_POSIX_ACL_ACCESS] = &ext4_xattr_acl_access_handler, [EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext4_xattr_acl_default_handler, #endif [EXT4_XATTR_INDEX_TRUSTED] = &ext4_xattr_trusted_handler, -#ifdef CONFIG_EXT4DEV_FS_SECURITY +#ifdef CONFIG_EXT4_FS_SECURITY [EXT4_XATTR_INDEX_SECURITY] = &ext4_xattr_security_handler, #endif }; @@ -112,11 +112,11 @@ static struct xattr_handler *ext4_xattr_handler_map[] = { struct xattr_handler *ext4_xattr_handlers[] = { &ext4_xattr_user_handler, &ext4_xattr_trusted_handler, -#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL +#ifdef CONFIG_EXT4_FS_POSIX_ACL &ext4_xattr_acl_access_handler, &ext4_xattr_acl_default_handler, #endif -#ifdef CONFIG_EXT4DEV_FS_SECURITY +#ifdef CONFIG_EXT4_FS_SECURITY &ext4_xattr_security_handler, #endif NULL diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 814ea58d4d5..8ede88b18c2 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h @@ -63,7 +63,7 @@ struct ext4_xattr_entry { EXT4_I(inode)->i_extra_isize)) #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1)) -# ifdef CONFIG_EXT4DEV_FS_XATTR +# ifdef CONFIG_EXT4_FS_XATTR extern struct xattr_handler ext4_xattr_user_handler; extern struct xattr_handler ext4_xattr_trusted_handler; @@ -88,7 +88,7 @@ extern void exit_ext4_xattr(void); extern struct xattr_handler *ext4_xattr_handlers[]; -# else /* CONFIG_EXT4DEV_FS_XATTR */ +# else /* CONFIG_EXT4_FS_XATTR */ static inline int ext4_xattr_get(struct inode *inode, int name_index, const char *name, @@ -141,9 +141,9 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, #define ext4_xattr_handlers NULL -# endif /* CONFIG_EXT4DEV_FS_XATTR */ +# endif /* CONFIG_EXT4_FS_XATTR */ -#ifdef CONFIG_EXT4DEV_FS_SECURITY +#ifdef CONFIG_EXT4_FS_SECURITY extern int ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir); #else -- GitLab From 77e841de8abac4755cc83ca224fdf71418d65380 Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Sun, 12 Oct 2008 16:39:16 -0400 Subject: [PATCH 3866/5416] jbd2: abort when failed to log metadata buffers If we failed to write metadata buffers to the journal space and succeeded to write the commit record, stale data can be written back to the filesystem as metadata in the recovery phase. To avoid this, when we failed to write out metadata buffers, abort the journal before writing the commit record. We can also avoid this kind of corruption by using the journal checksum feature because it can detect invalid metadata blocks in the journal and avoid them from being replayed. So we don't need to care about asynchronous commit record writeout with a checksum. Signed-off-by: Hidehiro Kawai Signed-off-by: Theodore Ts'o --- fs/jbd2/commit.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 0d3814a35ed..78e4da93412 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -783,6 +783,9 @@ wait_for_iobuf: /* AKPM: bforget here */ } + if (err) + jbd2_journal_abort(journal, err); + jbd_debug(3, "JBD: commit phase 5\n"); if (!JBD2_HAS_INCOMPAT_FEATURE(journal, -- GitLab From 44519faf22ad6ce924ad0352d3dc200d9e0b66e8 Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Fri, 10 Oct 2008 20:29:13 -0400 Subject: [PATCH 3867/5416] jbd2: fix error handling for checkpoint io When a checkpointing IO fails, current JBD2 code doesn't check the error and continue journaling. This means latest metadata can be lost from both the journal and filesystem. This patch leaves the failed metadata blocks in the journal space and aborts journaling in the case of jbd2_log_do_checkpoint(). To achieve this, we need to do: 1. don't remove the failed buffer from the checkpoint list where in the case of __try_to_free_cp_buf() because it may be released or overwritten by a later transaction 2. jbd2_log_do_checkpoint() is the last chance, remove the failed buffer from the checkpoint list and abort the journal 3. when checkpointing fails, don't update the journal super block to prevent the journaled contents from being cleaned. For safety, don't update j_tail and j_tail_sequence either 4. when checkpointing fails, notify this error to the ext4 layer so that ext4 don't clear the needs_recovery flag, otherwise the journaled contents are ignored and cleaned in the recovery phase 5. if the recovery fails, keep the needs_recovery flag 6. prevent jbd2_cleanup_journal_tail() from being called between __jbd2_journal_drop_transaction() and jbd2_journal_abort() (a possible race issue between jbd2_log_do_checkpoint()s called by jbd2_journal_flush() and __jbd2_log_wait_for_space()) Signed-off-by: Hidehiro Kawai Signed-off-by: Theodore Ts'o --- fs/jbd2/checkpoint.c | 49 +++++++++++++++++++++++++++++++++----------- fs/jbd2/journal.c | 28 +++++++++++++++++++------ fs/jbd2/recovery.c | 7 +++++-- include/linux/jbd2.h | 2 +- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 42895d36945..9203c3332f1 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -94,7 +94,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh) int ret = 0; struct buffer_head *bh = jh2bh(jh); - if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { + if (jh->b_jlist == BJ_None && !buffer_locked(bh) && + !buffer_dirty(bh) && !buffer_write_io_error(bh)) { JBUFFER_TRACE(jh, "remove from checkpoint list"); ret = __jbd2_journal_remove_checkpoint(jh) + 1; jbd_unlock_bh_state(bh); @@ -176,21 +177,25 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) * buffers. Note that we take the buffers in the opposite ordering * from the one in which they were submitted for IO. * + * Return 0 on success, and return <0 if some buffers have failed + * to be written out. + * * Called with j_list_lock held. */ -static void __wait_cp_io(journal_t *journal, transaction_t *transaction) +static int __wait_cp_io(journal_t *journal, transaction_t *transaction) { struct journal_head *jh; struct buffer_head *bh; tid_t this_tid; int released = 0; + int ret = 0; this_tid = transaction->t_tid; restart: /* Did somebody clean up the transaction in the meanwhile? */ if (journal->j_checkpoint_transactions != transaction || transaction->t_tid != this_tid) - return; + return ret; while (!released && transaction->t_checkpoint_io_list) { jh = transaction->t_checkpoint_io_list; bh = jh2bh(jh); @@ -210,6 +215,9 @@ restart: spin_lock(&journal->j_list_lock); goto restart; } + if (unlikely(buffer_write_io_error(bh))) + ret = -EIO; + /* * Now in whatever state the buffer currently is, we know that * it has been written out and so we can drop it from the list @@ -219,6 +227,8 @@ restart: jbd2_journal_remove_journal_head(bh); __brelse(bh); } + + return ret; } #define NR_BATCH 64 @@ -242,7 +252,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) * Try to flush one buffer from the checkpoint list to disk. * * Return 1 if something happened which requires us to abort the current - * scan of the checkpoint list. + * scan of the checkpoint list. Return <0 if the buffer has failed to + * be written out. * * Called with j_list_lock held and drops it if 1 is returned * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it @@ -274,6 +285,9 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, jbd2_log_wait_commit(journal, tid); ret = 1; } else if (!buffer_dirty(bh)) { + ret = 1; + if (unlikely(buffer_write_io_error(bh))) + ret = -EIO; J_ASSERT_JH(jh, !buffer_jbddirty(bh)); BUFFER_TRACE(bh, "remove from checkpoint"); __jbd2_journal_remove_checkpoint(jh); @@ -281,7 +295,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, jbd_unlock_bh_state(bh); jbd2_journal_remove_journal_head(bh); __brelse(bh); - ret = 1; } else { /* * Important: we are about to write the buffer, and @@ -314,6 +327,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, * to disk. We submit larger chunks of data at once. * * The journal should be locked before calling this function. + * Called with j_checkpoint_mutex held. */ int jbd2_log_do_checkpoint(journal_t *journal) { @@ -339,6 +353,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) * OK, we need to start writing disk blocks. Take one transaction * and write it. */ + result = 0; spin_lock(&journal->j_list_lock); if (!journal->j_checkpoint_transactions) goto out; @@ -357,7 +372,7 @@ restart: int batch_count = 0; struct buffer_head *bhs[NR_BATCH]; struct journal_head *jh; - int retry = 0; + int retry = 0, err; while (!retry && transaction->t_checkpoint_list) { struct buffer_head *bh; @@ -371,6 +386,8 @@ restart: } retry = __process_buffer(journal, jh, bhs, &batch_count, transaction); + if (retry < 0 && !result) + result = retry; if (!retry && (need_resched() || spin_needbreak(&journal->j_list_lock))) { spin_unlock(&journal->j_list_lock); @@ -395,14 +412,18 @@ restart: * Now we have cleaned up the first transaction's checkpoint * list. Let's clean up the second one */ - __wait_cp_io(journal, transaction); + err = __wait_cp_io(journal, transaction); + if (!result) + result = err; } out: spin_unlock(&journal->j_list_lock); - result = jbd2_cleanup_journal_tail(journal); if (result < 0) - return result; - return 0; + jbd2_journal_abort(journal, result); + else + result = jbd2_cleanup_journal_tail(journal); + + return (result < 0) ? result : 0; } /* @@ -418,8 +439,9 @@ out: * This is the only part of the journaling code which really needs to be * aware of transaction aborts. Checkpointing involves writing to the * main filesystem area rather than to the journal, so it can proceed - * even in abort state, but we must not update the journal superblock if - * we have an abort error outstanding. + * even in abort state, but we must not update the super block if + * checkpointing may have failed. Otherwise, we would lose some metadata + * buffers which should be written-back to the filesystem. */ int jbd2_cleanup_journal_tail(journal_t *journal) @@ -428,6 +450,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal) tid_t first_tid; unsigned long blocknr, freed; + if (is_journal_aborted(journal)) + return 1; + /* OK, work out the oldest transaction remaining in the log, and * the log block it starts at. * diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 01c3901c3a0..783de118de9 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1451,9 +1451,12 @@ recovery_error: * * Release a journal_t structure once it is no longer in use by the * journaled object. + * Return <0 if we couldn't clean up the journal. */ -void jbd2_journal_destroy(journal_t *journal) +int jbd2_journal_destroy(journal_t *journal) { + int err = 0; + /* Wait for the commit thread to wake up and die. */ journal_kill_thread(journal); @@ -1476,11 +1479,16 @@ void jbd2_journal_destroy(journal_t *journal) J_ASSERT(journal->j_checkpoint_transactions == NULL); spin_unlock(&journal->j_list_lock); - /* We can now mark the journal as empty. */ - journal->j_tail = 0; - journal->j_tail_sequence = ++journal->j_transaction_sequence; if (journal->j_sb_buffer) { - jbd2_journal_update_superblock(journal, 1); + if (!is_journal_aborted(journal)) { + /* We can now mark the journal as empty. */ + journal->j_tail = 0; + journal->j_tail_sequence = + ++journal->j_transaction_sequence; + jbd2_journal_update_superblock(journal, 1); + } else { + err = -EIO; + } brelse(journal->j_sb_buffer); } @@ -1492,6 +1500,8 @@ void jbd2_journal_destroy(journal_t *journal) jbd2_journal_destroy_revoke(journal); kfree(journal->j_wbuf); kfree(journal); + + return err; } @@ -1717,10 +1727,16 @@ int jbd2_journal_flush(journal_t *journal) spin_lock(&journal->j_list_lock); while (!err && journal->j_checkpoint_transactions != NULL) { spin_unlock(&journal->j_list_lock); + mutex_lock(&journal->j_checkpoint_mutex); err = jbd2_log_do_checkpoint(journal); + mutex_unlock(&journal->j_checkpoint_mutex); spin_lock(&journal->j_list_lock); } spin_unlock(&journal->j_list_lock); + + if (is_journal_aborted(journal)) + return -EIO; + jbd2_cleanup_journal_tail(journal); /* Finally, mark the journal as really needing no recovery. @@ -1742,7 +1758,7 @@ int jbd2_journal_flush(journal_t *journal) J_ASSERT(journal->j_head == journal->j_tail); J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); spin_unlock(&journal->j_state_lock); - return err; + return 0; } /** diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 058f50f65b7..73063285b13 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c @@ -225,7 +225,7 @@ do { \ */ int jbd2_journal_recover(journal_t *journal) { - int err; + int err, err2; journal_superblock_t * sb; struct recovery_info info; @@ -263,7 +263,10 @@ int jbd2_journal_recover(journal_t *journal) journal->j_transaction_sequence = ++info.end_transaction; jbd2_journal_clear_revoke(journal); - sync_blockdev(journal->j_fs_dev); + err2 = sync_blockdev(journal->j_fs_dev); + if (!err) + err = err2; + return err; } diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 66c3499478b..c9e7d781db3 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1060,7 +1060,7 @@ extern void jbd2_journal_clear_features (journal_t *, unsigned long, unsigned long, unsigned long); extern int jbd2_journal_create (journal_t *); extern int jbd2_journal_load (journal_t *journal); -extern void jbd2_journal_destroy (journal_t *); +extern int jbd2_journal_destroy (journal_t *); extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); extern int jbd2_journal_skip_recovery (journal_t *); -- GitLab From 7ffe1ea8949c75ecffb7a4d988bb881a9fa62fbe Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Fri, 10 Oct 2008 20:29:21 -0400 Subject: [PATCH 3868/5416] ext4: add checks for errors from jbd2 If the journal has aborted due to a checkpointing failure, we have to keep the contents of the journal space. Otherwise, the filesystem will lose uncheckpointed metadata completely and become inconsistent. To avoid this, we need to keep needs_recovery flag if checkpoint has failed. With this patch, ext4_put_super() detects a checkpointing failure from the return value of journal_destroy(), then it invokes ext4_abort() to make the filesystem read only and keep needs_recovery flag. Errors from jbd2_journal_flush() are also handled by this patch in some places. Signed-off-by: Hidehiro Kawai Signed-off-by: Theodore Ts'o --- fs/ext4/ioctl.c | 12 ++++++++---- fs/ext4/super.c | 23 +++++++++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index ea27eaa0cfe..dc99b4776d5 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -192,7 +192,7 @@ setversion_out: case EXT4_IOC_GROUP_EXTEND: { ext4_fsblk_t n_blocks_count; struct super_block *sb = inode->i_sb; - int err; + int err, err2; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; @@ -206,8 +206,10 @@ setversion_out: err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); - jbd2_journal_flush(EXT4_SB(sb)->s_journal); + err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); + if (err == 0) + err = err2; mnt_drop_write(filp->f_path.mnt); return err; @@ -215,7 +217,7 @@ setversion_out: case EXT4_IOC_GROUP_ADD: { struct ext4_new_group_data input; struct super_block *sb = inode->i_sb; - int err; + int err, err2; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; @@ -230,8 +232,10 @@ setversion_out: err = ext4_group_add(sb, &input); jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); - jbd2_journal_flush(EXT4_SB(sb)->s_journal); + err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); + if (err == 0) + err = err2; mnt_drop_write(filp->f_path.mnt); return err; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0e661c56966..79bd3989e84 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -507,7 +507,8 @@ static void ext4_put_super(struct super_block *sb) ext4_mb_release(sb); ext4_ext_release(sb); ext4_xattr_put_super(sb); - jbd2_journal_destroy(sbi->s_journal); + if (jbd2_journal_destroy(sbi->s_journal) < 0) + ext4_abort(sb, __func__, "Couldn't clean up the journal"); sbi->s_journal = NULL; if (!(sb->s_flags & MS_RDONLY)) { EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); @@ -2853,7 +2854,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb, journal_t *journal = EXT4_SB(sb)->s_journal; jbd2_journal_lock_updates(journal); - jbd2_journal_flush(journal); + if (jbd2_journal_flush(journal) < 0) + goto out; + lock_super(sb); if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && sb->s_flags & MS_RDONLY) { @@ -2862,6 +2865,8 @@ static void ext4_mark_recovery_complete(struct super_block *sb, ext4_commit_super(sb, es, 1); } unlock_super(sb); + +out: jbd2_journal_unlock_updates(journal); } @@ -2962,7 +2967,13 @@ static void ext4_write_super_lockfs(struct super_block *sb) /* Now we set up the journal barrier. */ jbd2_journal_lock_updates(journal); - jbd2_journal_flush(journal); + + /* + * We don't want to clear needs_recovery flag when we failed + * to flush the journal. + */ + if (jbd2_journal_flush(journal) < 0) + return; /* Journal blocked and flushed, clear needs_recovery flag. */ EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); @@ -3402,8 +3413,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, * otherwise be livelocked... */ jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); - jbd2_journal_flush(EXT4_SB(sb)->s_journal); + err = jbd2_journal_flush(EXT4_SB(sb)->s_journal); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); + if (err) { + path_put(&nd.path); + return err; + } } err = vfs_quota_on_path(sb, type, format_id, &nd.path); -- GitLab From 7ad7445f60fe4d46c4c9d2a9463db180d2a3b270 Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Fri, 10 Oct 2008 20:29:31 -0400 Subject: [PATCH 3869/5416] jbd2: don't dirty original metadata buffer on abort Currently, original metadata buffers are dirtied when they are unfiled whether the journal has aborted or not. Eventually these buffers will be written-back to the filesystem by pdflush. This means some metadata buffers are written to the filesystem without journaling if the journal aborts. So if both journal abort and system crash happen at the same time, the filesystem would become inconsistent state. Additionally, replaying journaled metadata can overwrite the latest metadata on the filesystem partly. Because, if the journal gets aborted, journaled metadata are preserved and replayed during the next mount not to lose uncheckpointed metadata. This would also break the consistency of the filesystem. This patch prevents original metadata buffers from being dirtied on abort by clearing BH_JBDDirty flag from those buffers. Thus, no metadata buffers are written to the filesystem without journaling. Signed-off-by: Hidehiro Kawai Signed-off-by: Theodore Ts'o --- fs/jbd2/commit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 78e4da93412..849f10496ce 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -504,9 +504,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) jh = commit_transaction->t_buffers; /* If we're in abort mode, we just un-journal the buffer and - release it for background writing. */ + release it. */ if (is_journal_aborted(journal)) { + clear_buffer_jbddirty(jh2bh(jh)); JBUFFER_TRACE(jh, "journal is aborting: refile"); jbd2_journal_refile_buffer(journal, jh); /* If that was the last one, we need to clean up @@ -884,6 +885,8 @@ restart_loop: if (buffer_jbddirty(bh)) { JBUFFER_TRACE(jh, "add to new checkpointing trans"); __jbd2_journal_insert_checkpoint(jh, commit_transaction); + if (is_journal_aborted(journal)) + clear_buffer_jbddirty(bh); JBUFFER_TRACE(jh, "refile for checkpoint writeback"); __jbd2_journal_refile_buffer(jh); jbd_unlock_bh_state(bh); -- GitLab From 5bf5683a33f3584da6eced480967c4f7e11515a8 Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Fri, 10 Oct 2008 22:12:43 -0400 Subject: [PATCH 3870/5416] ext4: add an option to control error handling on file data If the journal doesn't abort when it gets an IO error in file data blocks, the file data corruption will spread silently. Because most of applications and commands do buffered writes without fsync(), they don't notice the IO error. It's scary for mission critical systems. On the other hand, if the journal aborts whenever it gets an IO error in file data blocks, the system will easily become inoperable. So this patch introduces a filesystem option to determine whether it aborts the journal or just call printk() when it gets an IO error in file data. If you mount an ext4 fs with data_err=abort option, it aborts on file data write error. If you mount it with data_err=ignore, it doesn't abort, just call printk(). data_err=ignore is the default. Here is the corresponding patch of the ext3 version: http://kerneltrap.org/mailarchive/linux-kernel/2008/9/9/3239374 Signed-off-by: Hidehiro Kawai Signed-off-by: Theodore Ts'o --- Documentation/filesystems/ext4.txt | 5 +++++ fs/ext4/ext4.h | 2 ++ fs/ext4/super.c | 16 ++++++++++++++++ fs/jbd2/commit.c | 2 ++ include/linux/jbd2.h | 3 +++ 5 files changed, 28 insertions(+) diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 74484e69640..eb154ef36c2 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -223,6 +223,11 @@ errors=remount-ro(*) Remount the filesystem read-only on an error. errors=continue Keep going on a filesystem error. errors=panic Panic and halt the machine if an error occurs. +data_err=ignore(*) Just print an error message if an error occurs + in a file data buffer in ordered mode. +data_err=abort Abort the journal if an error occurs in a file + data buffer in ordered mode. + grpid Give objects the same group ID as their creator. bsdgroups diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f46a513a515..6690a41cdd9 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -540,6 +540,8 @@ do { \ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ +#define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ + /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ #ifndef _LINUX_EXT2_FS_H #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 79bd3989e84..014677b8e22 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -778,6 +778,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_printf(seq, ",inode_readahead_blks=%u", sbi->s_inode_readahead_blks); + if (test_opt(sb, DATA_ERR_ABORT)) + seq_puts(seq, ",data_err=abort"); + ext4_show_quota_options(seq, sb); return 0; } @@ -907,6 +910,7 @@ enum { Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, Opt_journal_checksum, Opt_journal_async_commit, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, + Opt_data_err_abort, Opt_data_err_ignore, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, @@ -953,6 +957,8 @@ static match_table_t tokens = { {Opt_data_journal, "data=journal"}, {Opt_data_ordered, "data=ordered"}, {Opt_data_writeback, "data=writeback"}, + {Opt_data_err_abort, "data_err=abort"}, + {Opt_data_err_ignore, "data_err=ignore"}, {Opt_offusrjquota, "usrjquota="}, {Opt_usrjquota, "usrjquota=%s"}, {Opt_offgrpjquota, "grpjquota="}, @@ -1187,6 +1193,12 @@ static int parse_options(char *options, struct super_block *sb, sbi->s_mount_opt |= data_opt; } break; + case Opt_data_err_abort: + set_opt(sbi->s_mount_opt, DATA_ERR_ABORT); + break; + case Opt_data_err_ignore: + clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); + break; #ifdef CONFIG_QUOTA case Opt_usrjquota: qtype = USRQUOTA; @@ -2535,6 +2547,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) journal->j_flags |= JBD2_BARRIER; else journal->j_flags &= ~JBD2_BARRIER; + if (test_opt(sb, DATA_ERR_ABORT)) + journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; + else + journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; spin_unlock(&journal->j_state_lock); } diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 849f10496ce..0abe02c4242 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -684,6 +684,8 @@ start_journal_io: printk(KERN_WARNING "JBD2: Detected IO errors while flushing file data " "on %s\n", journal->j_devname); + if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) + jbd2_journal_abort(journal, err); err = 0; } diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index c9e7d781db3..d2e91ea998f 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -967,6 +967,9 @@ struct journal_s #define JBD2_FLUSHED 0x008 /* The journal superblock has been flushed */ #define JBD2_LOADED 0x010 /* The journal superblock has been loaded */ #define JBD2_BARRIER 0x020 /* Use IDE barriers */ +#define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file + * data write error in ordered + * mode */ /* * Function declarations for the journaling transaction and buffer -- GitLab From f9da8d157b60d8c5bfc5a21fc50538fdb754a65b Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 10 Oct 2008 23:14:14 -0400 Subject: [PATCH 3871/5416] Input: move map_to_7segment.h to include/linux The map_to_7segment.h provides generic 7segment LED mappings and is designed to be used by other drivers. Moving it to common area will make it more usable. Also exporting it to userspace will help users of sysfs interface. Signed-off-by: Atsushi Nemoto Acked-by: Henk Vergonet Signed-off-by: Dmitry Torokhov --- drivers/input/misc/yealink.c | 2 +- include/linux/Kbuild | 1 + {drivers/input/misc => include/linux}/map_to_7segment.h | 4 +--- 3 files changed, 3 insertions(+), 4 deletions(-) rename {drivers/input/misc => include/linux}/map_to_7segment.h (98%) diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index facefd3dba2..11b5c7e84ed 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -52,8 +52,8 @@ #include #include #include +#include -#include "map_to_7segment.h" #include "yealink.h" #define DRIVER_VERSION "yld-20051230" diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 4c4142c5aa6..0b136c5990c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -106,6 +106,7 @@ header-y += keyctl.h header-y += limits.h header-y += magic.h header-y += major.h +header-y += map_to_7segment.h header-y += matroxfb.h header-y += meye.h header-y += minix_fs.h diff --git a/drivers/input/misc/map_to_7segment.h b/include/linux/map_to_7segment.h similarity index 98% rename from drivers/input/misc/map_to_7segment.h rename to include/linux/map_to_7segment.h index a424094d9fe..7df8432c440 100644 --- a/drivers/input/misc/map_to_7segment.h +++ b/include/linux/map_to_7segment.h @@ -1,6 +1,4 @@ /* - * drivers/usb/input/map_to_7segment.h - * * Copyright (c) 2005 Henk Vergonet * * This program is free software; you can redistribute it and/or @@ -36,7 +34,7 @@ * Usage: * * Register a map variable, and fill it with a character set: - * static SEG7_DEFAULT_MAP(map_seg7); + * static SEG7_DEFAULT_MAP(map_seg7); * * * Then use for conversion: -- GitLab From 69fc7eed5f56bce15b239e5110de2575a6970df4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 9 Oct 2008 16:58:13 +0100 Subject: [PATCH 3872/5416] [ARM] 5300/1: fixup spitz reset during boot Some machines don't have the pullup/down on their reset pin, so configuring the reset generating pin as input makes them reset immediately. Fix that by making reset pin direction configurable. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/include/mach/reset.h | 9 ++++++--- arch/arm/mach-pxa/reset.c | 9 ++++++--- arch/arm/mach-pxa/spitz.c | 2 +- arch/arm/mach-pxa/tosa.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/reset.h b/arch/arm/mach-pxa/include/mach/reset.h index 9489a48871a..7b8842cfa5f 100644 --- a/arch/arm/mach-pxa/include/mach/reset.h +++ b/arch/arm/mach-pxa/include/mach/reset.h @@ -10,9 +10,12 @@ extern unsigned int reset_status; extern void clear_reset_status(unsigned int mask); -/* - * register GPIO as reset generator +/** + * init_gpio_reset() - register GPIO as reset generator + * + * @gpio - gpio nr + * @output - set gpio as out/low instead of input during normal work */ -extern int init_gpio_reset(int gpio); +extern int init_gpio_reset(int gpio, int output); #endif /* __ASM_ARCH_RESET_H */ diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index 31d78855aac..1b2af575c40 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -20,7 +20,7 @@ static void do_hw_reset(void); static int reset_gpio = -1; -int init_gpio_reset(int gpio) +int init_gpio_reset(int gpio, int output) { int rc; @@ -30,9 +30,12 @@ int init_gpio_reset(int gpio) goto out; } - rc = gpio_direction_input(gpio); + if (output) + rc = gpio_direction_output(gpio, 0); + else + rc = gpio_direction_input(gpio); if (rc) { - printk(KERN_ERR "Can't configure reset_gpio for input\n"); + printk(KERN_ERR "Can't configure reset_gpio\n"); gpio_free(gpio); goto out; } diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 9b4f24c7c05..524f656dc56 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -618,7 +618,7 @@ static void spitz_restart(char mode) static void __init common_init(void) { - init_gpio_reset(SPITZ_GPIO_ON_RESET); + init_gpio_reset(SPITZ_GPIO_ON_RESET, 1); pm_power_off = spitz_poweroff; arm_pm_restart = spitz_restart; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 9f3ef9eb32e..130e37e4ebd 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -781,7 +781,7 @@ static void __init tosa_init(void) gpio_set_wake(MFP_PIN_GPIO1, 1); /* We can't pass to gpio-keys since it will drop the Reset altfunc */ - init_gpio_reset(TOSA_GPIO_ON_RESET); + init_gpio_reset(TOSA_GPIO_ON_RESET, 0); pm_power_off = tosa_poweroff; arm_pm_restart = tosa_restart; -- GitLab From 5d9a76cd0ed367d01b0b237253adb7607e86a277 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Sun, 17 Aug 2008 16:49:25 +0200 Subject: [PATCH 3873/5416] MIPS: Use compat_sys_ptrace This replaces mips's sys_ptrace32 with a compat_arch_ptrace and enables the new generic definition of compat_sys_ptrace instead. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace32.c | 43 +++++++--------------------------- arch/mips/kernel/scall64-n32.S | 2 +- arch/mips/kernel/scall64-o32.S | 2 +- arch/mips/kernel/signal32.c | 12 ++++++++++ include/asm-mips/ptrace.h | 3 +++ 5 files changed, 25 insertions(+), 37 deletions(-) diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 76818be6ba7..cac56a8c867 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -15,6 +15,7 @@ * binaries. */ #include +#include #include #include #include @@ -46,37 +47,13 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); * Tracing a 32-bit process with a 64-bit strace and vice versa will not * work. I don't know how to fix this. */ -asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - struct task_struct *child; + int addr = caddr; + int data = cdata; int ret; -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -214,7 +191,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } dregs = __get_dsp_regs(child); tmp = (unsigned long) (dregs[addr - DSP_BASE]); @@ -224,14 +201,14 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } ret = put_user(tmp, (unsigned __user *) (unsigned long) data); break; @@ -414,10 +391,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = ptrace_request(child, request, addr, data); break; } - -out_tsk: - put_task_struct(child); out: - unlock_kernel(); return ret; } diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index da7f1b6ea0f..324c5499dec 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -219,7 +219,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_getrusage PTR compat_sys_sysinfo PTR compat_sys_times - PTR sys32_ptrace + PTR compat_sys_ptrace PTR sys_getuid /* 6100 */ PTR sys_syslog PTR sys_getgid diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d7cd1aac9ad..85fedac99a5 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -231,7 +231,7 @@ sys_call_table: PTR sys_setuid PTR sys_getuid PTR compat_sys_stime /* 4025 */ - PTR sys32_ptrace + PTR compat_sys_ptrace PTR sys_alarm PTR sys_ni_syscall /* was sys_fstat */ PTR sys_pause diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 572c610db1b..652709b353a 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -482,6 +482,18 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) return err; } +int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) +{ + memset(to, 0, sizeof *to); + + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) + return -EFAULT; + + return 0; +} + asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) { struct sigframe32 __user *frame; diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h index 786f7e3c99b..c00cca24dae 100644 --- a/include/asm-mips/ptrace.h +++ b/include/asm-mips/ptrace.h @@ -9,6 +9,9 @@ #ifndef _ASM_PTRACE_H #define _ASM_PTRACE_H +#ifdef CONFIG_64BIT +#define __ARCH_WANT_COMPAT_SYS_PTRACE +#endif /* 0 - 31 are integer registers, 32 - 63 are fp registers. */ #define FPR_BASE 32 -- GitLab From 9fa32c6b0275ab1e8b19f74fbfa3ed8411345db6 Mon Sep 17 00:00:00 2001 From: Patrick Glass Date: Mon, 18 Aug 2008 14:41:30 -0700 Subject: [PATCH 3874/5416] MIPS: PMC MSP71XX gpio drivers This new gpio driver for PMC-Sierra's MSP71xx SoC allows standard api calls for access to the general and extended gpio's. Signed-off-by: Patrick Glass Signed-off-by: Ralf Baechle create mode 100755 arch/mips/pmc-sierra/msp71xx/gpio.c create mode 100755 arch/mips/pmc-sierra/msp71xx/gpio_extended.c create mode 100755 include/asm-mips/pmc-sierra/msp71xx/gpio.h --- arch/mips/pmc-sierra/msp71xx/Makefile | 1 + arch/mips/pmc-sierra/msp71xx/gpio.c | 218 +++++++++++++++++++ arch/mips/pmc-sierra/msp71xx/gpio_extended.c | 148 +++++++++++++ include/asm-mips/pmc-sierra/msp71xx/gpio.h | 46 ++++ 4 files changed, 413 insertions(+) create mode 100644 arch/mips/pmc-sierra/msp71xx/gpio.c create mode 100644 arch/mips/pmc-sierra/msp71xx/gpio_extended.c create mode 100644 include/asm-mips/pmc-sierra/msp71xx/gpio.h diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile index 4bba79c1cc7..e107f79b149 100644 --- a/arch/mips/pmc-sierra/msp71xx/Makefile +++ b/arch/mips/pmc-sierra/msp71xx/Makefile @@ -3,6 +3,7 @@ # obj-y += msp_prom.o msp_setup.o msp_irq.o \ msp_time.o msp_serial.o msp_elb.o +obj-$(CONFIG_HAVE_GPIO_LIB) += gpio.o gpio_extended.o obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o diff --git a/arch/mips/pmc-sierra/msp71xx/gpio.c b/arch/mips/pmc-sierra/msp71xx/gpio.c new file mode 100644 index 00000000000..69848c5813e --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/gpio.c @@ -0,0 +1,218 @@ +/* + * @file /arch/mips/pmc-sierra/msp71xx/gpio.c + * + * Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two + * types of registers. The data register sets the output level when in output + * mode and when in input mode will contain the value at the input. The config + * register sets the various modes for each gpio. + * + * 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. + * + * @author Patrick Glass + */ + +#include +#include +#include +#include +#include +#include + +#define MSP71XX_CFG_OFFSET(gpio) (4 * (gpio)) +#define CONF_MASK 0x0F +#define MSP71XX_GPIO_INPUT 0x01 +#define MSP71XX_GPIO_OUTPUT 0x08 + +#define MSP71XX_GPIO_BASE 0x0B8400000L + +#define to_msp71xx_gpio_chip(c) container_of(c, struct msp71xx_gpio_chip, chip) + +static spinlock_t gpio_lock; + +/* + * struct msp71xx_gpio_chip - container for gpio chip and registers + * @chip: chip structure for the specified gpio bank + * @data_reg: register for reading and writing the gpio pin value + * @config_reg: register to set the mode for the gpio pin bank + * @out_drive_reg: register to set the output drive mode for the gpio pin bank + */ +struct msp71xx_gpio_chip { + struct gpio_chip chip; + void __iomem *data_reg; + void __iomem *config_reg; + void __iomem *out_drive_reg; +}; + +/* + * msp71xx_gpio_get() - return the chip's gpio value + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be returned + * + * It will return 0 if gpio value is low and other if high. + */ +static int msp71xx_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + + return __raw_readl(msp_chip->data_reg) & (1 << offset); +} + +/* + * msp71xx_gpio_set() - set the output value for the gpio + * @chip: chip structure who controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This will set the gpio bit specified to the desired value. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static void msp71xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&gpio_lock, flags); + + data = __raw_readl(msp_chip->data_reg); + if (value) + data |= (1 << offset); + else + data &= ~(1 << offset); + __raw_writel(data, msp_chip->data_reg); + + spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* + * msp71xx_set_gpio_mode() - declare the mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @mode: desired configuration for the gpio (see datasheet) + * + * It will set the gpio pin config to the @mode value passed in. + */ +static int msp71xx_set_gpio_mode(struct gpio_chip *chip, + unsigned offset, int mode) +{ + struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); + const unsigned bit_offset = MSP71XX_CFG_OFFSET(offset); + unsigned long flags; + u32 cfg; + + spin_lock_irqsave(&gpio_lock, flags); + + cfg = __raw_readl(msp_chip->config_reg); + cfg &= ~(CONF_MASK << bit_offset); + cfg |= (mode << bit_offset); + __raw_writel(cfg, msp_chip->config_reg); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} + +/* + * msp71xx_direction_output() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This call will set the mode for the @gpio to output. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static int msp71xx_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + msp71xx_gpio_set(chip, offset, value); + + return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_OUTPUT); +} + +/* + * msp71xx_direction_input() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose to which the value will be assigned + * + * This call will set the mode for the @gpio to input. + */ +static int msp71xx_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_INPUT); +} + +/* + * msp71xx_set_output_drive() - declare the output drive for the gpio line + * @gpio: gpio pin whose output drive you wish to modify + * @value: zero for active drain 1 for open drain drive + * + * This call will set the output drive mode for the @gpio to output. + */ +int msp71xx_set_output_drive(unsigned gpio, int value) +{ + unsigned long flags; + u32 data; + + if (gpio > 15 || gpio < 0) + return -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + + data = __raw_readl((void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); + if (value) + data |= (1 << gpio); + else + data &= ~(1 << gpio); + __raw_writel(data, (void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(msp71xx_set_output_drive); + +#define MSP71XX_GPIO_BANK(name, dr, cr, base_gpio, num_gpio) \ +{ \ + .chip = { \ + .label = name, \ + .direction_input = msp71xx_direction_input, \ + .direction_output = msp71xx_direction_output, \ + .get = msp71xx_gpio_get, \ + .set = msp71xx_gpio_set, \ + .base = base_gpio, \ + .ngpio = num_gpio \ + }, \ + .data_reg = (void __iomem *)(MSP71XX_GPIO_BASE + dr), \ + .config_reg = (void __iomem *)(MSP71XX_GPIO_BASE + cr), \ + .out_drive_reg = (void __iomem *)(MSP71XX_GPIO_BASE + 0x190), \ +} + +/* + * struct msp71xx_gpio_banks[] - container array of gpio banks + * @chip: chip structure for the specified gpio bank + * @data_reg: register for reading and writing the gpio pin value + * @config_reg: register to set the mode for the gpio pin bank + * + * This array structure defines the gpio banks for the PMC MIPS Processor. + * We specify the bank name, the data register, the config register, base + * starting gpio number, and the number of gpios exposed by the bank. + */ +static struct msp71xx_gpio_chip msp71xx_gpio_banks[] = { + + MSP71XX_GPIO_BANK("GPIO_1_0", 0x170, 0x180, 0, 2), + MSP71XX_GPIO_BANK("GPIO_5_2", 0x174, 0x184, 2, 4), + MSP71XX_GPIO_BANK("GPIO_9_6", 0x178, 0x188, 6, 4), + MSP71XX_GPIO_BANK("GPIO_15_10", 0x17C, 0x18C, 10, 6), +}; + +void __init msp71xx_init_gpio(void) +{ + int i; + + spin_lock_init(&gpio_lock); + + for (i = 0; i < ARRAY_SIZE(msp71xx_gpio_banks); i++) + gpiochip_add(&msp71xx_gpio_banks[i].chip); +} diff --git a/arch/mips/pmc-sierra/msp71xx/gpio_extended.c b/arch/mips/pmc-sierra/msp71xx/gpio_extended.c new file mode 100644 index 00000000000..fc6dbc6cf1c --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/gpio_extended.c @@ -0,0 +1,148 @@ +/* + * @file /arch/mips/pmc-sierra/msp71xx/gpio_extended.c + * + * Generic PMC MSP71xx EXTENDED (EXD) GPIO handling. The extended gpio is + * a set of hardware registers that have no need for explicit locking as + * it is handled by unique method of writing individual set/clr bits. + * + * 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. + * + * @author Patrick Glass + */ + +#include +#include +#include +#include +#include + +#define MSP71XX_DATA_OFFSET(gpio) (2 * (gpio)) +#define MSP71XX_READ_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 1) +#define MSP71XX_CFG_OUT_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 16) +#define MSP71XX_CFG_IN_OFFSET(gpio) (MSP71XX_CFG_OUT_OFFSET(gpio) + 1) + +#define MSP71XX_EXD_GPIO_BASE 0x0BC000000L + +#define to_msp71xx_exd_gpio_chip(c) \ + container_of(c, struct msp71xx_exd_gpio_chip, chip) + +/* + * struct msp71xx_exd_gpio_chip - container for gpio chip and registers + * @chip: chip structure for the specified gpio bank + * @reg: register for control and data of gpio pin + */ +struct msp71xx_exd_gpio_chip { + struct gpio_chip chip; + void __iomem *reg; +}; + +/* + * msp71xx_exd_gpio_get() - return the chip's gpio value + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be returned + * + * It will return 0 if gpio value is low and other if high. + */ +static int msp71xx_exd_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + const unsigned bit = MSP71XX_READ_OFFSET(offset); + + return __raw_readl(msp71xx_chip->reg) & (1 << bit); +} + +/* + * msp71xx_exd_gpio_set() - set the output value for the gpio + * @chip: chip structure who controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This will set the gpio bit specified to the desired value. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static void msp71xx_exd_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + const unsigned bit = MSP71XX_DATA_OFFSET(offset); + + __raw_writel(1 << (bit + (value ? 1 : 0)), msp71xx_chip->reg); +} + +/* + * msp71xx_exd_direction_output() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose value will be assigned + * @value: logic level to assign to the gpio initially + * + * This call will set the mode for the @gpio to output. It will set the + * gpio pin low if value is 0 otherwise it will be high. + */ +static int msp71xx_exd_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + + msp71xx_exd_gpio_set(chip, offset, value); + __raw_writel(1 << MSP71XX_CFG_OUT_OFFSET(offset), msp71xx_chip->reg); + return 0; +} + +/* + * msp71xx_exd_direction_input() - declare the direction mode for a gpio + * @chip: chip structure which controls the specified gpio + * @offset: gpio whose to which the value will be assigned + * + * This call will set the mode for the @gpio to input. + */ +static int msp71xx_exd_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct msp71xx_exd_gpio_chip *msp71xx_chip = + to_msp71xx_exd_gpio_chip(chip); + + __raw_writel(1 << MSP71XX_CFG_IN_OFFSET(offset), msp71xx_chip->reg); + return 0; +} + +#define MSP71XX_EXD_GPIO_BANK(name, exd_reg, base_gpio, num_gpio) \ +{ \ + .chip = { \ + .label = name, \ + .direction_input = msp71xx_exd_direction_input, \ + .direction_output = msp71xx_exd_direction_output, \ + .get = msp71xx_exd_gpio_get, \ + .set = msp71xx_exd_gpio_set, \ + .base = base_gpio, \ + .ngpio = num_gpio, \ + }, \ + .reg = (void __iomem *)(MSP71XX_EXD_GPIO_BASE + exd_reg), \ +} + +/* + * struct msp71xx_exd_gpio_banks[] - container array of gpio banks + * @chip: chip structure for the specified gpio bank + * @reg: register for reading and writing the gpio pin value + * + * This array structure defines the extended gpio banks for the + * PMC MIPS Processor. We specify the bank name, the data/config + * register,the base starting gpio number, and the number of + * gpios exposed by the bank of gpios. + */ +static struct msp71xx_exd_gpio_chip msp71xx_exd_gpio_banks[] = { + + MSP71XX_EXD_GPIO_BANK("GPIO_23_16", 0x188, 16, 8), + MSP71XX_EXD_GPIO_BANK("GPIO_27_24", 0x18C, 24, 4), +}; + +void __init msp71xx_init_gpio_extended(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(msp71xx_exd_gpio_banks); i++) + gpiochip_add(&msp71xx_exd_gpio_banks[i].chip); +} diff --git a/include/asm-mips/pmc-sierra/msp71xx/gpio.h b/include/asm-mips/pmc-sierra/msp71xx/gpio.h new file mode 100644 index 00000000000..ebdbab973e4 --- /dev/null +++ b/include/asm-mips/pmc-sierra/msp71xx/gpio.h @@ -0,0 +1,46 @@ +/* + * include/asm-mips/pmc-sierra/msp71xx/gpio.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * @author Patrick Glass + */ + +#ifndef __PMC_MSP71XX_GPIO_H +#define __PMC_MSP71XX_GPIO_H + +/* Max number of gpio's is 28 on chip plus 3 banks of I2C IO Expanders */ +#define ARCH_NR_GPIOS (28 + (3 * 8)) + +/* new generic GPIO API - see Documentation/gpio.txt */ +#include + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep + +/* Setup calls for the gpio and gpio extended */ +extern void msp71xx_init_gpio(void); +extern void msp71xx_init_gpio_extended(void); +extern int msp71xx_set_output_drive(unsigned gpio, int value); + +/* Custom output drive functionss */ +static inline int gpio_set_output_drive(unsigned gpio, int value) +{ + return msp71xx_set_output_drive(gpio, value); +} + +/* IRQ's are not supported for gpio lines */ +static inline int gpio_to_irq(unsigned gpio) +{ + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return -EINVAL; +} + +#endif /* __PMC_MSP71XX_GPIO_H */ -- GitLab From f96a3383cfede841cdf80a5927f14478981ed78c Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:05 +0900 Subject: [PATCH 3875/5416] MIPS: RBTX4927: More explicit initialization * Make sure all interrupts cleared on startup * Initialize some GPIOs Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/rbtx4927/irq.c | 5 +++++ arch/mips/txx9/rbtx4927/setup.c | 9 +++++++++ include/asm-mips/txx9/rbtx4927.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c index 00cd5231da3..22076e3f03a 100644 --- a/arch/mips/txx9/rbtx4927/irq.c +++ b/arch/mips/txx9/rbtx4927/irq.c @@ -142,6 +142,11 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void) { int i; + /* mask all IOC interrupts */ + writeb(0, rbtx4927_imask_addr); + /* clear SoftInt interrupts */ + writeb(0, rbtx4927_softint_addr); + for (i = RBTX4927_IRQ_IOC; i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++) set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type, diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 0d39bafea79..5985f330838 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -212,6 +213,14 @@ static void __init rbtx4927_mem_setup(void) set_io_port_base(KSEG1 + RBTX4927_ISA_IO_OFFSET); #endif + /* TX4927-SIO DTR on (PIO[15]) */ + gpio_request(15, "sio-dtr"); + gpio_direction_output(15, 1); + gpio_request(0, "led"); + gpio_direction_output(0, 1); + gpio_request(1, "led"); + gpio_direction_output(1, 1); + tx4927_sio_init(0, 0); #ifdef CONFIG_SERIAL_TXX9_CONSOLE argptr = prom_getcmdline(); diff --git a/include/asm-mips/txx9/rbtx4927.h b/include/asm-mips/txx9/rbtx4927.h index 6fcec912c14..c6015463432 100644 --- a/include/asm-mips/txx9/rbtx4927.h +++ b/include/asm-mips/txx9/rbtx4927.h @@ -36,6 +36,7 @@ #define RBTX4927_IMASK_ADDR (IO_BASE + TXX9_CE(2) + 0x00002000) #define RBTX4927_IMSTAT_ADDR (IO_BASE + TXX9_CE(2) + 0x00002006) +#define RBTX4927_SOFTINT_ADDR (IO_BASE + TXX9_CE(2) + 0x00003000) #define RBTX4927_SOFTRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f000) #define RBTX4927_SOFTRESETLOCK_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f002) #define RBTX4927_PCIRESET_ADDR (IO_BASE + TXX9_CE(2) + 0x0000f006) @@ -47,6 +48,7 @@ #define rbtx4927_imask_addr ((__u8 __iomem *)RBTX4927_IMASK_ADDR) #define rbtx4927_imstat_addr ((__u8 __iomem *)RBTX4927_IMSTAT_ADDR) +#define rbtx4927_softint_addr ((__u8 __iomem *)RBTX4927_SOFTINT_ADDR) #define rbtx4927_softreset_addr ((__u8 __iomem *)RBTX4927_SOFTRESET_ADDR) #define rbtx4927_softresetlock_addr \ ((__u8 __iomem *)RBTX4927_SOFTRESETLOCK_ADDR) -- GitLab From e0dfb20c2b77c6626a24578240266ace928cd2e7 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:06 +0900 Subject: [PATCH 3876/5416] MIPS: TXx9: Improve handling of built-in and command-line args * Make prom_init_cmdline() static and be called from prom_init. * Append built-in args if the first character was '+'. * Drop command-line args if the first character of built-in was '-'. * Enclose args include spaces by quotes. * TX4938_NAND_BOOT is no longer needed. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/Kconfig | 7 ------ arch/mips/txx9/generic/setup.c | 42 ++++++++++++++++++++++++--------- arch/mips/txx9/jmr3927/prom.c | 1 - arch/mips/txx9/rbtx4927/prom.c | 1 - arch/mips/txx9/rbtx4938/prom.c | 3 --- include/asm-mips/txx9/generic.h | 1 - 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 840fe757c48..6fb2ef09d5d 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -97,13 +97,6 @@ config TOSHIBA_RBTX4938_MPLEX_ATA endchoice -config TX4938_NAND_BOOT - depends on EXPERIMENTAL && TOSHIBA_RBTX4938_MPLEX_NAND - bool "NAND Boot Support (EXPERIMENTAL)" - help - This is only for Toshiba RBTX4938 reference board, which has NAND IPL. - Select this option if you need to use NAND boot. - endif config PCI_TX4927 diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fe6bee09cec..33d8c9e3223 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -127,31 +127,51 @@ extern struct txx9_board_vec rbtx4938_vec; struct txx9_board_vec *txx9_board_vec __initdata; static char txx9_system_type[32]; -void __init prom_init_cmdline(void) +static void __init prom_init_cmdline(void) { int argc = (int)fw_arg0; - char **argv = (char **)fw_arg1; + int *argv32 = (int *)fw_arg1; int i; /* Always ignore the "-c" at argv[0] */ -#ifdef CONFIG_64BIT - char *fixed_argv[32]; - for (i = 0; i < argc; i++) - fixed_argv[i] = (char *)(long)(*((__s32 *)argv + i)); - argv = fixed_argv; -#endif + char builtin[CL_SIZE]; /* ignore all built-in args if any f/w args given */ - if (argc > 1) - *arcs_cmdline = '\0'; + /* + * But if built-in strings was started with '+', append them + * to command line args. If built-in was started with '-', + * ignore all f/w args. + */ + builtin[0] = '\0'; + if (arcs_cmdline[0] == '+') + strcpy(builtin, arcs_cmdline + 1); + else if (arcs_cmdline[0] == '-') { + strcpy(builtin, arcs_cmdline + 1); + argc = 0; + } else if (argc <= 1) + strcpy(builtin, arcs_cmdline); + arcs_cmdline[0] = '\0'; for (i = 1; i < argc; i++) { + char *str = (char *)(long)argv32[i]; if (i != 1) strcat(arcs_cmdline, " "); - strcat(arcs_cmdline, argv[i]); + if (strchr(str, ' ')) { + strcat(arcs_cmdline, "\""); + strcat(arcs_cmdline, str); + strcat(arcs_cmdline, "\""); + } else + strcat(arcs_cmdline, str); + } + /* append saved builtin args */ + if (builtin[0]) { + if (arcs_cmdline[0]) + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, builtin); } } void __init prom_init(void) { + prom_init_cmdline(); #ifdef CONFIG_CPU_TX39XX txx9_board_vec = &jmr3927_vec; #endif diff --git a/arch/mips/txx9/jmr3927/prom.c b/arch/mips/txx9/jmr3927/prom.c index 70c4c8ec3e8..c899c0c087a 100644 --- a/arch/mips/txx9/jmr3927/prom.c +++ b/arch/mips/txx9/jmr3927/prom.c @@ -47,7 +47,6 @@ void __init jmr3927_prom_init(void) if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) printk(KERN_ERR "TX3927 TLB off\n"); - prom_init_cmdline(); add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); txx9_sio_putchar_init(TX3927_SIO_REG(1)); } diff --git a/arch/mips/txx9/rbtx4927/prom.c b/arch/mips/txx9/rbtx4927/prom.c index 1dc0a5b1956..cc97c6a6011 100644 --- a/arch/mips/txx9/rbtx4927/prom.c +++ b/arch/mips/txx9/rbtx4927/prom.c @@ -36,7 +36,6 @@ void __init rbtx4927_prom_init(void) { - prom_init_cmdline(); add_memory_region(0, tx4927_get_mem_size(), BOOT_MEM_RAM); txx9_sio_putchar_init(TX4927_SIO_REG(0) & 0xfffffffffULL); } diff --git a/arch/mips/txx9/rbtx4938/prom.c b/arch/mips/txx9/rbtx4938/prom.c index d73123cd2ab..bcb469247e8 100644 --- a/arch/mips/txx9/rbtx4938/prom.c +++ b/arch/mips/txx9/rbtx4938/prom.c @@ -18,9 +18,6 @@ void __init rbtx4938_prom_init(void) { -#ifndef CONFIG_TX4938_NAND_BOOT - prom_init_cmdline(); -#endif add_memory_region(0, tx4938_get_mem_size(), BOOT_MEM_RAM); txx9_sio_putchar_init(TX4938_SIO_REG(0) & 0xfffffffffULL); } diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index 5b1ccf901c6..c9eed7ea148 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -42,7 +42,6 @@ struct txx9_board_vec { }; extern struct txx9_board_vec *txx9_board_vec; extern int (*txx9_irq_dispatch)(int pending); -void prom_init_cmdline(void); char *prom_getcmdline(void); void txx9_wdt_init(unsigned long base); void txx9_spi_init(int busid, unsigned long base, int irq); -- GitLab From 265b89db1058124ddbf0091ba3f8c020e3a5ae9d Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:07 +0900 Subject: [PATCH 3877/5416] MIPS: TXx9: Add prom_getenv Add prom_getenv() which can be used for YAMON. This assumes other firmware should pass NULL for fw_arg2. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 15 +++++++++++++++ include/asm-mips/txx9/generic.h | 1 + 2 files changed, 16 insertions(+) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 33d8c9e3223..005179c2af2 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -212,6 +212,21 @@ char * __init prom_getcmdline(void) return &(arcs_cmdline[0]); } +const char *__init prom_getenv(const char *name) +{ + const s32 *str = (const s32 *)fw_arg2; + + if (!str) + return NULL; + /* YAMON style ("name", "value" pairs) */ + while (str[0] && str[1]) { + if (!strcmp((const char *)(unsigned long)str[0], name)) + return (const char *)(unsigned long)str[1]; + str += 2; + } + return NULL; +} + static void __noreturn txx9_machine_halt(void) { local_irq_disable(); diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index c9eed7ea148..0a225bf7349 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -43,6 +43,7 @@ struct txx9_board_vec { extern struct txx9_board_vec *txx9_board_vec; extern int (*txx9_irq_dispatch)(int pending); char *prom_getcmdline(void); +const char *prom_getenv(const char *name); void txx9_wdt_init(unsigned long base); void txx9_spi_init(int busid, unsigned long base, int irq); void txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr); -- GitLab From 860e546c19d88c21819c7f0861c505debd2d6eed Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:08 +0900 Subject: [PATCH 3878/5416] MIPS: TXx9: Early command-line preprocessing * Select board by command-line option or firmware environment variable. * Handle "masterclk=" option. * Add boards.h to centerize board_vec declaration. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 include/asm-mips/txx9/boards.h --- arch/mips/txx9/generic/setup.c | 74 +++++++++++++++++++++++++++++++--- include/asm-mips/txx9/boards.h | 10 +++++ 2 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 include/asm-mips/txx9/boards.h diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 005179c2af2..dc5dbcc53a9 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -119,14 +119,31 @@ int irq_to_gpio(unsigned irq) EXPORT_SYMBOL(irq_to_gpio); #endif -extern struct txx9_board_vec jmr3927_vec; -extern struct txx9_board_vec rbtx4927_vec; -extern struct txx9_board_vec rbtx4937_vec; -extern struct txx9_board_vec rbtx4938_vec; +#define BOARD_VEC(board) extern struct txx9_board_vec board; +#include +#undef BOARD_VEC struct txx9_board_vec *txx9_board_vec __initdata; static char txx9_system_type[32]; +static struct txx9_board_vec *board_vecs[] __initdata = { +#define BOARD_VEC(board) &board, +#include +#undef BOARD_VEC +}; + +static struct txx9_board_vec *__init find_board_byname(const char *name) +{ + int i; + + /* search board_vecs table */ + for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { + if (strstr(board_vecs[i]->system, name)) + return board_vecs[i]; + } + return NULL; +} + static void __init prom_init_cmdline(void) { int argc = (int)fw_arg0; @@ -169,9 +186,47 @@ static void __init prom_init_cmdline(void) } } -void __init prom_init(void) +static void __init preprocess_cmdline(void) { - prom_init_cmdline(); + char cmdline[CL_SIZE]; + char *s; + + strcpy(cmdline, arcs_cmdline); + s = cmdline; + arcs_cmdline[0] = '\0'; + while (s && *s) { + char *str = strsep(&s, " "); + if (strncmp(str, "board=", 6) == 0) { + txx9_board_vec = find_board_byname(str + 6); + continue; + } else if (strncmp(str, "masterclk=", 10) == 0) { + unsigned long val; + if (strict_strtoul(str + 10, 10, &val) == 0) + txx9_master_clock = val; + continue; + } + if (arcs_cmdline[0]) + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, str); + } +} + +static void __init select_board(void) +{ + const char *envstr; + + /* first, determine by "board=" argument in preprocess_cmdline() */ + if (txx9_board_vec) + return; + /* next, determine by "board" envvar */ + envstr = prom_getenv("board"); + if (envstr) { + txx9_board_vec = find_board_byname(envstr); + if (txx9_board_vec) + return; + } + + /* select "default" board */ #ifdef CONFIG_CPU_TX39XX txx9_board_vec = &jmr3927_vec; #endif @@ -192,6 +247,13 @@ void __init prom_init(void) #endif } #endif +} + +void __init prom_init(void) +{ + prom_init_cmdline(); + preprocess_cmdline(); + select_board(); strcpy(txx9_system_type, txx9_board_vec->system); diff --git a/include/asm-mips/txx9/boards.h b/include/asm-mips/txx9/boards.h new file mode 100644 index 00000000000..4abc8142fbb --- /dev/null +++ b/include/asm-mips/txx9/boards.h @@ -0,0 +1,10 @@ +#ifdef CONFIG_TOSHIBA_JMR3927 +BOARD_VEC(jmr3927_vec) +#endif +#ifdef CONFIG_TOSHIBA_RBTX4927 +BOARD_VEC(rbtx4927_vec) +BOARD_VEC(rbtx4937_vec) +#endif +#ifdef CONFIG_TOSHIBA_RBTX4938 +BOARD_VEC(rbtx4938_vec) +#endif -- GitLab From d10e025f0e4ba4b96d7b5786d232ac5b0b232b11 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:09 +0900 Subject: [PATCH 3879/5416] MIPS: TXx9: Cache fixup TX39/TX49 can enable/disable I/D cache at runtime. Add kernel options to control them. This is useful to debug some cache-related issues, such as aliasing or I/D coherency. Also enable CWF bit for TX49 SoCs. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 113 ++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 18 ++-- arch/mips/txx9/generic/setup_tx4927.c | 1 + arch/mips/txx9/generic/setup_tx4938.c | 1 + arch/mips/txx9/jmr3927/setup.c | 11 +-- arch/mips/txx9/rbtx4927/setup.c | 6 -- 6 files changed, 124 insertions(+), 26 deletions(-) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index dc5dbcc53a9..fa88aefea9e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_CPU_TX49XX @@ -186,6 +187,110 @@ static void __init prom_init_cmdline(void) } } +static int txx9_ic_disable __initdata; +static int txx9_dc_disable __initdata; + +#if defined(CONFIG_CPU_TX49XX) +/* flush all cache on very early stage (before 4k_cache_init) */ +static void __init early_flush_dcache(void) +{ + unsigned int conf = read_c0_config(); + unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); + unsigned int linesz = 32; + unsigned long addr, end; + + end = INDEX_BASE + dc_size / 4; + /* 4way, waybit=0 */ + for (addr = INDEX_BASE; addr < end; addr += linesz) { + cache_op(Index_Writeback_Inv_D, addr | 0); + cache_op(Index_Writeback_Inv_D, addr | 1); + cache_op(Index_Writeback_Inv_D, addr | 2); + cache_op(Index_Writeback_Inv_D, addr | 3); + } +} + +static void __init txx9_cache_fixup(void) +{ + unsigned int conf; + + conf = read_c0_config(); + /* flush and disable */ + if (txx9_ic_disable) { + conf |= TX49_CONF_IC; + write_c0_config(conf); + } + if (txx9_dc_disable) { + early_flush_dcache(); + conf |= TX49_CONF_DC; + write_c0_config(conf); + } + + /* enable cache */ + conf = read_c0_config(); + if (!txx9_ic_disable) + conf &= ~TX49_CONF_IC; + if (!txx9_dc_disable) + conf &= ~TX49_CONF_DC; + write_c0_config(conf); + + if (conf & TX49_CONF_IC) + pr_info("TX49XX I-Cache disabled.\n"); + if (conf & TX49_CONF_DC) + pr_info("TX49XX D-Cache disabled.\n"); +} +#elif defined(CONFIG_CPU_TX39XX) +/* flush all cache on very early stage (before tx39_cache_init) */ +static void __init early_flush_dcache(void) +{ + unsigned int conf = read_c0_config(); + unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> + TX39_CONF_DCS_SHIFT)); + unsigned int linesz = 16; + unsigned long addr, end; + + end = INDEX_BASE + dc_size / 2; + /* 2way, waybit=0 */ + for (addr = INDEX_BASE; addr < end; addr += linesz) { + cache_op(Index_Writeback_Inv_D, addr | 0); + cache_op(Index_Writeback_Inv_D, addr | 1); + } +} + +static void __init txx9_cache_fixup(void) +{ + unsigned int conf; + + conf = read_c0_config(); + /* flush and disable */ + if (txx9_ic_disable) { + conf &= ~TX39_CONF_ICE; + write_c0_config(conf); + } + if (txx9_dc_disable) { + early_flush_dcache(); + conf &= ~TX39_CONF_DCE; + write_c0_config(conf); + } + + /* enable cache */ + conf = read_c0_config(); + if (!txx9_ic_disable) + conf |= TX39_CONF_ICE; + if (!txx9_dc_disable) + conf |= TX39_CONF_DCE; + write_c0_config(conf); + + if (!(conf & TX39_CONF_ICE)) + pr_info("TX39XX I-Cache disabled.\n"); + if (!(conf & TX39_CONF_DCE)) + pr_info("TX39XX D-Cache disabled.\n"); +} +#else +static inline void txx9_cache_fixup(void) +{ +} +#endif + static void __init preprocess_cmdline(void) { char cmdline[CL_SIZE]; @@ -204,11 +309,19 @@ static void __init preprocess_cmdline(void) if (strict_strtoul(str + 10, 10, &val) == 0) txx9_master_clock = val; continue; + } else if (strcmp(str, "icdisable") == 0) { + txx9_ic_disable = 1; + continue; + } else if (strcmp(str, "dcdisable") == 0) { + txx9_dc_disable = 1; + continue; } if (arcs_cmdline[0]) strcat(arcs_cmdline, " "); strcat(arcs_cmdline, str); } + + txx9_cache_fixup(); } static void __init select_board(void) diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 7bd963d37fc..4bc2f859379 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -99,16 +99,14 @@ void __init tx3927_setup(void) txx9_gpio_init(TX3927_PIO_REG, 0, 16); conf = read_c0_conf(); - if (!(conf & TX39_CONF_ICE)) - printk(KERN_INFO "TX3927 I-Cache disabled.\n"); - if (!(conf & TX39_CONF_DCE)) - printk(KERN_INFO "TX3927 D-Cache disabled.\n"); - else if (!(conf & TX39_CONF_WBON)) - printk(KERN_INFO "TX3927 D-Cache WriteThrough.\n"); - else if (!(conf & TX39_CONF_CWFON)) - printk(KERN_INFO "TX3927 D-Cache WriteBack.\n"); - else - printk(KERN_INFO "TX3927 D-Cache WriteBack (CWF) .\n"); + if (conf & TX39_CONF_DCE) { + if (!(conf & TX39_CONF_WBON)) + pr_info("TX3927 D-Cache WriteThrough.\n"); + else if (!(conf & TX39_CONF_CWFON)) + pr_info("TX3927 D-Cache WriteBack.\n"); + else + pr_info("TX3927 D-Cache WriteBack (CWF) .\n"); + } } void __init tx3927_time_init(unsigned int evt_tmrnr, unsigned int src_tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index f80d4b7a694..e679c79a4b0 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -44,6 +44,7 @@ void __init tx4927_setup(void) txx9_reg_res_init(TX4927_REV_PCODE(), TX4927_REG_BASE, TX4927_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); /* SDRAMC,EBUSC are configured by PROM */ for (i = 0; i < 8; i++) { diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index f3040b9ba05..95c058f0a96 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -47,6 +47,7 @@ void __init tx4938_setup(void) txx9_reg_res_init(TX4938_REV_PCODE(), TX4938_REG_BASE, TX4938_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); /* SDRAMC,EBUSC are configured by PROM */ for (i = 0; i < 8; i++) { diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 87db41be8a5..2e40a926825 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -62,7 +62,6 @@ static void __init jmr3927_time_init(void) } #define DO_WRITE_THROUGH -#define DO_ENABLE_CACHE static void jmr3927_board_init(void); @@ -77,11 +76,6 @@ static void __init jmr3927_mem_setup(void) /* cache setup */ { unsigned int conf; -#ifdef DO_ENABLE_CACHE - int mips_ic_disable = 0, mips_dc_disable = 0; -#else - int mips_ic_disable = 1, mips_dc_disable = 1; -#endif #ifdef DO_WRITE_THROUGH int mips_config_cwfon = 0; int mips_config_wbon = 0; @@ -91,10 +85,7 @@ static void __init jmr3927_mem_setup(void) #endif conf = read_c0_conf(); - conf &= ~(TX39_CONF_ICE | TX39_CONF_DCE | - TX39_CONF_WBON | TX39_CONF_CWFON); - conf |= mips_ic_disable ? 0 : TX39_CONF_ICE; - conf |= mips_dc_disable ? 0 : TX39_CONF_DCE; + conf &= ~(TX39_CONF_WBON | TX39_CONF_CWFON); conf |= mips_config_wbon ? TX39_CONF_WBON : 0; conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0; diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 5985f330838..0464a39b39a 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -186,14 +186,8 @@ static void __init rbtx4937_clock_init(void); static void __init rbtx4927_mem_setup(void) { - u32 cp0_config; char *argptr; - /* enable caches -- HCP5 does this, pmon does not */ - cp0_config = read_c0_config(); - cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC); - write_c0_config(cp0_config); - if (TX4927_REV_PCODE() == 0x4927) { rbtx4927_clock_init(); tx4927_setup(); -- GitLab From c7b95bcb38ea492fd025008ef99501a2b90aa237 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:10 +0900 Subject: [PATCH 3880/5416] MIPS: TXx9: Runtime configuration of timeout-error Add kernel options to control bus timeout error. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 11 +++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 5 ----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fa88aefea9e..fa45f174b0e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -68,7 +68,12 @@ unsigned int txx9_master_clock; unsigned int txx9_cpu_clock; unsigned int txx9_gbus_clock; +#ifdef CONFIG_CPU_TX39XX +/* don't enable by default - see errata */ +int txx9_ccfg_toeon __initdata; +#else int txx9_ccfg_toeon __initdata = 1; +#endif /* Minimum CLK support */ @@ -315,6 +320,12 @@ static void __init preprocess_cmdline(void) } else if (strcmp(str, "dcdisable") == 0) { txx9_dc_disable = 1; continue; + } else if (strcmp(str, "toeoff") == 0) { + txx9_ccfg_toeon = 0; + continue; + } else if (strcmp(str, "toeon") == 0) { + txx9_ccfg_toeon = 1; + continue; } if (arcs_cmdline[0]) strcat(arcs_cmdline, " "); diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 4bc2f859379..06c49257607 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -32,11 +32,6 @@ void __init tx3927_setup(void) int i; unsigned int conf; - /* don't enable - see errata */ - txx9_ccfg_toeon = 0; - if (strstr(prom_getcmdline(), "toeon") != NULL) - txx9_ccfg_toeon = 1; - txx9_reg_res_init(TX3927_REV_PCODE(), TX3927_REG_BASE, TX3927_REG_SIZE); -- GitLab From 51f607c76e1e7bd089dcad97b6b0a58649be06a3 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:11 +0900 Subject: [PATCH 3881/5416] MIPS: TXx9: Add mtd support Add helper routines to register physmap-flash platform devices for NOR flashes. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 41 +++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx3927.c | 14 +++++++++ arch/mips/txx9/generic/setup_tx4927.c | 14 +++++++++ arch/mips/txx9/generic/setup_tx4938.c | 14 +++++++++ arch/mips/txx9/jmr3927/setup.c | 9 ++++++ arch/mips/txx9/rbtx4927/setup.c | 9 ++++++ arch/mips/txx9/rbtx4938/setup.c | 38 +++++++++++++++++++++++++ include/asm-mips/txx9/generic.h | 4 +++ include/asm-mips/txx9/tx3927.h | 2 ++ include/asm-mips/txx9/tx4927.h | 3 ++ include/asm-mips/txx9/tx4938.h | 2 ++ 11 files changed, 150 insertions(+) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index fa45f174b0e..cfa3ccf493b 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -593,3 +594,43 @@ static unsigned long __swizzle_addr_none(unsigned long port) unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; EXPORT_SYMBOL(__swizzle_addr_b); #endif + +void __init txx9_physmap_flash_init(int no, unsigned long addr, + unsigned long size, + const struct physmap_flash_data *pdata) +{ +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) + struct resource res = { + .start = addr, + .end = addr + size - 1, + .flags = IORESOURCE_MEM, + }; + struct platform_device *pdev; +#ifdef CONFIG_MTD_PARTITIONS + static struct mtd_partition parts[2]; + struct physmap_flash_data pdata_part; + + /* If this area contained boot area, make separate partition */ + if (pdata->nr_parts == 0 && !pdata->parts && + addr < 0x1fc00000 && addr + size > 0x1fc00000 && + !parts[0].name) { + parts[0].name = "boot"; + parts[0].offset = 0x1fc00000 - addr; + parts[0].size = addr + size - 0x1fc00000; + parts[1].name = "user"; + parts[1].offset = 0; + parts[1].size = 0x1fc00000 - addr; + pdata_part = *pdata; + pdata_part.nr_parts = ARRAY_SIZE(parts); + pdata_part.parts = parts; + pdata = &pdata_part; + } +#endif + pdev = platform_device_alloc("physmap-flash", no); + if (!pdev || + platform_device_add_resources(pdev, &res, 1) || + platform_device_add_data(pdev, pdata, sizeof(*pdata)) || + platform_device_add(pdev)) + platform_device_put(pdev); +#endif +} diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c index 06c49257607..9505d58454c 100644 --- a/arch/mips/txx9/generic/setup_tx3927.c +++ b/arch/mips/txx9/generic/setup_tx3927.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -121,3 +122,16 @@ void __init tx3927_sio_init(unsigned int sclk, unsigned int cts_mask) TXX9_IRQ_BASE + TX3927_IR_SIO(i), i, sclk, (1 << i) & cts_mask); } + +void __init tx3927_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX3927_ROMC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(tx3927_romcptr->cr[ch] & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index e679c79a4b0..0840ef930e4 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -187,3 +188,16 @@ void __init tx4927_sio_init(unsigned int sclk, unsigned int cts_mask) TXX9_IRQ_BASE + TX4927_IR_SIO(i), i, sclk, (1 << i) & cts_mask); } + +void __init tx4927_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4927_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4927_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 95c058f0a96..630a7aac61f 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -269,3 +270,16 @@ void __init tx4938_ethaddr_init(unsigned char *addr0, unsigned char *addr1) if (addr1 && (pcfg & TX4938_PCFG_ETH1_SEL)) txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH1, addr1); } + +void __init tx4938_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4938_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4938_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 2e40a926825..0f3843c92cf 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -190,11 +190,20 @@ static void __init jmr3927_rtc_init(void) platform_device_register_simple("rtc-ds1742", -1, &res, 1); } +static void __init jmr3927_mtd_init(void) +{ + int i; + + for (i = 0; i < 2; i++) + tx3927_mtd_init(i); +} + static void __init jmr3927_device_init(void) { __swizzle_addr_b = jmr3927_swizzle_addr_b; jmr3927_rtc_init(); tx3927_wdt_init(); + jmr3927_mtd_init(); } struct txx9_board_vec jmr3927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index 0464a39b39a..abe32c1a79d 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -307,11 +307,20 @@ static void __init rbtx4927_ne_init(void) platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res)); } +static void __init rbtx4927_mtd_init(void) +{ + int i; + + for (i = 0; i < 2; i++) + tx4927_mtd_init(i); +} + static void __init rbtx4927_device_init(void) { toshiba_rbtx4927_rtc_init(); rbtx4927_ne_init(); tx4927_wdt_init(); + rbtx4927_mtd_init(); } struct txx9_board_vec rbtx4927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index 9ab48dec0fe..e7bc5b8c7db 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -294,6 +295,42 @@ static int __init rbtx4938_spi_init(void) return 0; } +static void __init rbtx4938_mtd_init(void) +{ + struct physmap_flash_data pdata = { + .width = 4, + }; + + switch (readb(rbtx4938_bdipsw_addr) & 7) { + case 0: + /* Boot */ + txx9_physmap_flash_init(0, 0x1fc00000, 0x400000, &pdata); + /* System */ + txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); + break; + case 1: + /* System */ + txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); + /* Boot */ + txx9_physmap_flash_init(1, 0x1ec00000, 0x400000, &pdata); + break; + case 2: + /* Ext */ + txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); + /* System */ + txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); + /* Boot */ + txx9_physmap_flash_init(2, 0x1dc00000, 0x400000, &pdata); + break; + case 3: + /* Boot */ + txx9_physmap_flash_init(1, 0x1bc00000, 0x400000, &pdata); + /* System */ + txx9_physmap_flash_init(2, 0x1a000000, 0x1000000, &pdata); + break; + } +} + static void __init rbtx4938_arch_init(void) { gpiochip_add(&rbtx4938_spi_gpio_chip); @@ -306,6 +343,7 @@ static void __init rbtx4938_device_init(void) rbtx4938_ethaddr_init(); rbtx4938_ne_init(); tx4938_wdt_init(); + rbtx4938_mtd_init(); } struct txx9_board_vec rbtx4938_vec __initdata = { diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index 0a225bf7349..1982c4437b1 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -59,4 +59,8 @@ static inline void txx9_sio_putchar_init(unsigned long baseaddr) } #endif +struct physmap_flash_data; +void txx9_physmap_flash_init(int no, unsigned long addr, unsigned long size, + const struct physmap_flash_data *pdata); + #endif /* __ASM_TXX9_GENERIC_H */ diff --git a/include/asm-mips/txx9/tx3927.h b/include/asm-mips/txx9/tx3927.h index 587deb9592d..dc30c8d4206 100644 --- a/include/asm-mips/txx9/tx3927.h +++ b/include/asm-mips/txx9/tx3927.h @@ -325,6 +325,7 @@ struct tx3927_ccfg_reg { #define TX3927_ROMC_BA(ch) (tx3927_romcptr->cr[(ch)] & 0xfff00000) #define TX3927_ROMC_SIZE(ch) \ (0x00100000 << ((tx3927_romcptr->cr[(ch)] >> 8) & 0xf)) +#define TX3927_ROMC_WIDTH(ch) (32 >> ((tx3927_romcptr->cr[(ch)] >> 7) & 0x1)) void tx3927_wdt_init(void); void tx3927_setup(void); @@ -335,5 +336,6 @@ void tx3927_pcic_setup(struct pci_controller *channel, unsigned long sdram_size, int extarb); void tx3927_setup_pcierr_irq(void); void tx3927_irq_init(void); +void tx3927_mtd_init(int ch); #endif /* __ASM_TXX9_TX3927_H */ diff --git a/include/asm-mips/txx9/tx4927.h b/include/asm-mips/txx9/tx4927.h index 195f6515db9..36a9241b0ca 100644 --- a/include/asm-mips/txx9/tx4927.h +++ b/include/asm-mips/txx9/tx4927.h @@ -196,6 +196,8 @@ struct tx4927_ccfg_reg { #define TX4927_EBUSC_BA(ch) ((TX4927_EBUSC_CR(ch) >> 48) << 20) #define TX4927_EBUSC_SIZE(ch) \ (0x00100000 << ((unsigned long)(TX4927_EBUSC_CR(ch) >> 8) & 0xf)) +#define TX4927_EBUSC_WIDTH(ch) \ + (64 >> ((__u32)(TX4927_EBUSC_CR(ch) >> 20) & 0x3)) /* utilities */ static inline void txx9_clear64(__u64 __iomem *adr, __u64 bits) @@ -251,5 +253,6 @@ int tx4927_report_pciclk(void); int tx4927_pciclk66_setup(void); void tx4927_setup_pcierr_irq(void); void tx4927_irq_init(void); +void tx4927_mtd_init(int ch); #endif /* __ASM_TXX9_TX4927_H */ diff --git a/include/asm-mips/txx9/tx4938.h b/include/asm-mips/txx9/tx4938.h index 8175d4ccbc3..989e7751135 100644 --- a/include/asm-mips/txx9/tx4938.h +++ b/include/asm-mips/txx9/tx4938.h @@ -274,6 +274,7 @@ struct tx4938_ccfg_reg { #define TX4938_EBUSC_CR(ch) TX4927_EBUSC_CR(ch) #define TX4938_EBUSC_BA(ch) TX4927_EBUSC_BA(ch) #define TX4938_EBUSC_SIZE(ch) TX4927_EBUSC_SIZE(ch) +#define TX4938_EBUSC_WIDTH(ch) TX4927_EBUSC_WIDTH(ch) #define tx4938_get_mem_size() tx4927_get_mem_size() void tx4938_wdt_init(void); @@ -289,5 +290,6 @@ struct pci_dev; int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot); void tx4938_setup_pcierr_irq(void); void tx4938_irq_init(void); +void tx4938_mtd_init(int ch); #endif -- GitLab From 74894363499942a76f2c20e41e8bfebc9fdc267a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:12 +0900 Subject: [PATCH 3882/5416] MIPS: TXx9: Raise priority of interrupts for errors, timers, SIO Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/irq_tx4927.c | 11 +++++++++++ arch/mips/txx9/generic/irq_tx4938.c | 11 +++++++++++ include/asm-mips/txx9/tx4927.h | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c index cbea1fdde82..ad2870def8f 100644 --- a/arch/mips/txx9/generic/irq_tx4927.c +++ b/arch/mips/txx9/generic/irq_tx4927.c @@ -30,8 +30,19 @@ void __init tx4927_irq_init(void) { + int i; + mips_cpu_irq_init(); txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL); set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT, handle_simple_irq); + /* raise priority for errors, timers, SIO */ + txx9_irq_set_pri(TX4927_IR_ECCERR, 7); + txx9_irq_set_pri(TX4927_IR_WTOERR, 7); + txx9_irq_set_pri(TX4927_IR_PCIERR, 7); + txx9_irq_set_pri(TX4927_IR_PCIPME, 7); + for (i = 0; i < TX4927_NUM_IR_TMR; i++) + txx9_irq_set_pri(TX4927_IR_TMR(i), 6); + for (i = 0; i < TX4927_NUM_IR_SIO; i++) + txx9_irq_set_pri(TX4927_IR_SIO(i), 5); } diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c index 6eac684bf19..025ae11359a 100644 --- a/arch/mips/txx9/generic/irq_tx4938.c +++ b/arch/mips/txx9/generic/irq_tx4938.c @@ -18,8 +18,19 @@ void __init tx4938_irq_init(void) { + int i; + mips_cpu_irq_init(); txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL); set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT, handle_simple_irq); + /* raise priority for errors, timers, SIO */ + txx9_irq_set_pri(TX4938_IR_ECCERR, 7); + txx9_irq_set_pri(TX4938_IR_WTOERR, 7); + txx9_irq_set_pri(TX4938_IR_PCIERR, 7); + txx9_irq_set_pri(TX4938_IR_PCIPME, 7); + for (i = 0; i < TX4938_NUM_IR_TMR; i++) + txx9_irq_set_pri(TX4938_IR_TMR(i), 6); + for (i = 0; i < TX4938_NUM_IR_SIO; i++) + txx9_irq_set_pri(TX4938_IR_SIO(i), 5); } diff --git a/include/asm-mips/txx9/tx4927.h b/include/asm-mips/txx9/tx4927.h index 36a9241b0ca..7d813f1cb98 100644 --- a/include/asm-mips/txx9/tx4927.h +++ b/include/asm-mips/txx9/tx4927.h @@ -50,12 +50,23 @@ #define TX4927_SIO_REG(ch) (TX4927_REG_BASE + 0xf300 + (ch) * 0x100) #define TX4927_PIO_REG (TX4927_REG_BASE + 0xf500) +#define TX4927_IR_ECCERR 0 +#define TX4927_IR_WTOERR 1 +#define TX4927_NUM_IR_INT 6 #define TX4927_IR_INT(n) (2 + (n)) +#define TX4927_NUM_IR_SIO 2 #define TX4927_IR_SIO(n) (8 + (n)) +#define TX4927_NUM_IR_DMA 4 +#define TX4927_IR_DMA(n) (10 + (n)) +#define TX4927_IR_PIO 14 +#define TX4927_IR_PDMAC 15 #define TX4927_IR_PCIC 16 #define TX4927_NUM_IR_TMR 3 #define TX4927_IR_TMR(n) (17 + (n)) #define TX4927_IR_PCIERR 22 +#define TX4927_IR_PCIPME 23 +#define TX4927_IR_ACLC 24 +#define TX4927_IR_ACLCPME 25 #define TX4927_NUM_IR 32 #define TX4927_IRC_INT 2 /* IP[2] in Status register */ -- GitLab From e6332374770ae5aa370af5792115261edbad05c1 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:13 +0900 Subject: [PATCH 3883/5416] MIPS: RBTX4938: Add TOSHIBA_RBTX4938_MPLEX_KEEP Add TOSHIBA_RBTX4938_MPLEX_KEEP to keep MPLEX settings by firmware. Also replace some printk with pr_info. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/Kconfig | 2 ++ arch/mips/txx9/rbtx4938/setup.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 6fb2ef09d5d..aade3348af2 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -94,6 +94,8 @@ config TOSHIBA_RBTX4938_MPLEX_NAND bool "NAND" config TOSHIBA_RBTX4938_MPLEX_ATA bool "ATA" +config TOSHIBA_RBTX4938_MPLEX_KEEP + bool "Keep firmware settings" endchoice diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index e7bc5b8c7db..7aba92a1239 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -174,23 +174,30 @@ static void __init rbtx4938_mem_setup(void) #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 - printk(KERN_INFO "PIOSEL: disabling both ata and nand selection\n"); + pr_info("PIOSEL: disabling both ATA and NAND selection\n"); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL); #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND - printk(KERN_INFO "PIOSEL: enabling nand selection\n"); + pr_info("PIOSEL: enabling NAND selection\n"); txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); #endif #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA - printk(KERN_INFO "PIOSEL: enabling ata selection\n"); + pr_info("PIOSEL: enabling ATA selection\n"); txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); #endif +#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP + pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); + pr_info("PIOSEL: NAND %s, ATA %s\n", + (pcfg & TX4938_PCFG_NDF_SEL) ? "enabled" : "disabled", + (pcfg & TX4938_PCFG_ATA_SEL) ? "enabled" : "disabled"); +#endif + rbtx4938_spi_setup(); pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); /* updated */ /* fixup piosel */ -- GitLab From d75a40e90e9eb08c2159e719a90a7922dab231d3 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:14 +0900 Subject: [PATCH 3884/5416] MIPS: TXx9: Make spi_eeprom.c more generic Helper routines in txx9/rbtx4938/spi_eeprom.c is not TX4938 specific. Move it to txx9/generic/ directory and make it works with SPI bus number other than 0. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/txx9/generic/spi_eeprom.c delete mode 100644 arch/mips/txx9/rbtx4938/spi_eeprom.c --- arch/mips/txx9/generic/Makefile | 1 + .../txx9/{rbtx4938 => generic}/spi_eeprom.c | 28 +++++++++++-------- arch/mips/txx9/rbtx4938/Makefile | 2 +- arch/mips/txx9/rbtx4938/setup.c | 11 ++++---- include/asm-mips/txx9/spi.h | 19 +++++++++++-- 5 files changed, 41 insertions(+), 20 deletions(-) rename arch/mips/txx9/{rbtx4938 => generic}/spi_eeprom.c (79%) diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index 9bb34af26b7..986852cc774 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_SOC_TX3927) += setup_tx3927.o irq_tx3927.o obj-$(CONFIG_SOC_TX4927) += mem_tx4927.o setup_tx4927.o irq_tx4927.o obj-$(CONFIG_SOC_TX4938) += mem_tx4927.o setup_tx4938.o irq_tx4938.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o +obj-$(CONFIG_SPI) += spi_eeprom.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4938/spi_eeprom.c b/arch/mips/txx9/generic/spi_eeprom.c similarity index 79% rename from arch/mips/txx9/rbtx4938/spi_eeprom.c rename to arch/mips/txx9/generic/spi_eeprom.c index a7ea8b041c1..75c347238f4 100644 --- a/arch/mips/txx9/rbtx4938/spi_eeprom.c +++ b/arch/mips/txx9/generic/spi_eeprom.c @@ -18,29 +18,31 @@ #define AT250X0_PAGE_SIZE 8 /* register board information for at25 driver */ -int __init spi_eeprom_register(int chipid) +int __init spi_eeprom_register(int busid, int chipid, int size) { - static struct spi_eeprom eeprom = { - .name = "at250x0", - .byte_len = 128, - .page_size = AT250X0_PAGE_SIZE, - .flags = EE_ADDR1, - }; struct spi_board_info info = { .modalias = "at25", .max_speed_hz = 1500000, /* 1.5Mbps */ - .bus_num = 0, + .bus_num = busid, .chip_select = chipid, - .platform_data = &eeprom, /* Mode 0: High-Active, Sample-Then-Shift */ }; - + struct spi_eeprom *eeprom; + eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL); + if (!eeprom) + return -ENOMEM; + strcpy(eeprom->name, "at250x0"); + eeprom->byte_len = size; + eeprom->page_size = AT250X0_PAGE_SIZE; + eeprom->flags = EE_ADDR1; + info.platform_data = eeprom; return spi_register_board_info(&info, 1); } /* simple temporary spi driver to provide early access to seeprom. */ static struct read_param { + int busid; int chipid; int address; unsigned char *buf; @@ -57,7 +59,8 @@ static int __init early_seeprom_probe(struct spi_device *spi) dev_info(&spi->dev, "spiclk %u KHz.\n", (spi->max_speed_hz + 500) / 1000); - if (read_param->chipid != spi->chip_select) + if (read_param->busid != spi->master->bus_num || + read_param->chipid != spi->chip_select) return -ENODEV; while (len > 0) { /* spi_write_then_read can only work with small chunk */ @@ -80,11 +83,12 @@ static struct spi_driver early_seeprom_driver __initdata = { .probe = early_seeprom_probe, }; -int __init spi_eeprom_read(int chipid, int address, +int __init spi_eeprom_read(int busid, int chipid, int address, unsigned char *buf, int len) { int ret; struct read_param param = { + .busid = busid, .chipid = chipid, .address = address, .buf = buf, diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile index 9dcc52ae5b9..f3e1f597b4f 100644 --- a/arch/mips/txx9/rbtx4938/Makefile +++ b/arch/mips/txx9/rbtx4938/Makefile @@ -1,3 +1,3 @@ -obj-y += prom.o setup.o irq.o spi_eeprom.o +obj-y += prom.o setup.o irq.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index 7aba92a1239..ec6e81258f7 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -111,6 +111,7 @@ static void __init rbtx4938_pci_setup(void) #define SEEPROM2_CS 0 /* IOC */ #define SEEPROM3_CS 1 /* IOC */ #define SRTC_CS 2 /* IOC */ +#define SPI_BUSNO 0 static int __init rbtx4938_ethaddr_init(void) { @@ -120,7 +121,7 @@ static int __init rbtx4938_ethaddr_init(void) int i; /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ - if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) { + if (spi_eeprom_read(SPI_BUSNO, SEEPROM1_CS, 0, dat, sizeof(dat))) { printk(KERN_ERR "seeprom: read error.\n"); return -ENODEV; } else { @@ -287,9 +288,9 @@ static int __init rbtx4938_spi_init(void) .mode = SPI_MODE_1 | SPI_CS_HIGH, }; spi_register_board_info(&srtc_info, 1); - spi_eeprom_register(SEEPROM1_CS); - spi_eeprom_register(16 + SEEPROM2_CS); - spi_eeprom_register(16 + SEEPROM3_CS); + spi_eeprom_register(SPI_BUSNO, SEEPROM1_CS, 128); + spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM2_CS, 128); + spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM3_CS, 128); gpio_request(16 + SRTC_CS, "rtc-rs5c348"); gpio_direction_output(16 + SRTC_CS, 0); gpio_request(SEEPROM1_CS, "seeprom1"); @@ -298,7 +299,7 @@ static int __init rbtx4938_spi_init(void) gpio_direction_output(16 + SEEPROM2_CS, 1); gpio_request(16 + SEEPROM3_CS, "seeprom3"); gpio_direction_output(16 + SEEPROM3_CS, 1); - tx4938_spi_init(0); + tx4938_spi_init(SPI_BUSNO); return 0; } diff --git a/include/asm-mips/txx9/spi.h b/include/asm-mips/txx9/spi.h index ddfb2a0dc43..0d727f35455 100644 --- a/include/asm-mips/txx9/spi.h +++ b/include/asm-mips/txx9/spi.h @@ -13,7 +13,22 @@ #ifndef __ASM_TXX9_SPI_H #define __ASM_TXX9_SPI_H -extern int spi_eeprom_register(int chipid); -extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len); +#include + +#ifdef CONFIG_SPI +int spi_eeprom_register(int busid, int chipid, int size); +int spi_eeprom_read(int busid, int chipid, + int address, unsigned char *buf, int len); +#else +static inline int spi_eeprom_register(int busid, int chipid, int size) +{ + return -ENODEV; +} +static inline int spi_eeprom_read(int busid, int chipid, + int address, unsigned char *buf, int len) +{ + return -ENODEV; +} +#endif #endif /* __ASM_TXX9_SPI_H */ -- GitLab From 496a3b5c2c188e8af07261792b3d4e6cf1c1dab9 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:15 +0900 Subject: [PATCH 3885/5416] MIPS: TXx9: Default machine_restart using watchdog reset Add default machine_restart routine using watchdog reset of TX4927 and TX4938. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 15 ++++++++++++++ arch/mips/txx9/generic/setup_tx4927.c | 28 +++++++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 28 +++++++++++++++++++++++++++ include/asm-mips/txx9/generic.h | 1 + 4 files changed, 72 insertions(+) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index cfa3ccf493b..118d716f783 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_CPU_TX49XX #include #endif @@ -444,6 +445,20 @@ void __init txx9_wdt_init(unsigned long base) platform_device_register_simple("txx9wdt", -1, &res, 1); } +void txx9_wdt_now(unsigned long base) +{ + struct txx9_tmr_reg __iomem *tmrptr = + ioremap(base, sizeof(struct txx9_tmr_reg)); + /* disable watch dog timer */ + __raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr); + __raw_writel(0, &tmrptr->tcr); + /* kick watchdog */ + __raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr); + __raw_writel(1, &tmrptr->cpra); /* immediate */ + __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, + &tmrptr->tcr); +} + /* SPI support */ void __init txx9_spi_init(int busid, unsigned long base, int irq) { diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index 0840ef930e4..7189675f6a2 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,10 @@ static void __init tx4927_wdr_init(void) { + /* report watchdog reset status */ + if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); /* clear WatchDogReset (W1C) */ tx4927_ccfg_set(TX4927_CCFG_WDRST); /* do reset on watchdog */ @@ -34,6 +39,27 @@ void __init tx4927_wdt_init(void) txx9_wdt_init(TX4927_TMR_REG(2) & 0xfffffffffULL); } +static void tx4927_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4927_ccfg_set(TX4927_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4927_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4927_ccfg_clear(TX4927_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + static struct resource tx4927_sdram_resource[4]; void __init tx4927_setup(void) @@ -169,6 +195,8 @@ void __init tx4927_setup(void) txx9_gpio_init(TX4927_PIO_REG & 0xfffffffffULL, 0, TX4927_NUM_PIO); __raw_writel(0, &tx4927_pioptr->maskcpu); __raw_writel(0, &tx4927_pioptr->maskext); + + _machine_restart = tx4927_machine_restart; } void __init tx4927_time_init(unsigned int tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 630a7aac61f..4fbc85a8597 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,10 @@ static void __init tx4938_wdr_init(void) { + /* report watchdog reset status */ + if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); /* clear WatchDogReset (W1C) */ tx4938_ccfg_set(TX4938_CCFG_WDRST); /* do reset on watchdog */ @@ -34,6 +39,27 @@ void __init tx4938_wdt_init(void) txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL); } +static void tx4938_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4938_ccfg_set(TX4938_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4938_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4938_ccfg_clear(TX4938_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + static struct resource tx4938_sdram_resource[4]; static struct resource tx4938_sram_resource; @@ -229,6 +255,8 @@ void __init tx4938_setup(void) TX4938_CLKCTR_ETH1CKD); } } + + _machine_restart = tx4938_machine_restart; } void __init tx4938_time_init(unsigned int tmrnr) diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index 1982c4437b1..1e1a9f2d237 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -45,6 +45,7 @@ extern int (*txx9_irq_dispatch)(int pending); char *prom_getcmdline(void); const char *prom_getenv(const char *name); void txx9_wdt_init(unsigned long base); +void txx9_wdt_now(unsigned long base); void txx9_spi_init(int busid, unsigned long base, int irq); void txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr); void txx9_sio_init(unsigned long baseaddr, int irq, -- GitLab From ce8e74112b1b1215aa5bbe261ed751498ce65434 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:16 +0900 Subject: [PATCH 3886/5416] MIPS: TXx9: Add board_be_init for TX4927/TX4938 Setup default board_be_handler for TX4927/TX4938. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup_tx4927.c | 23 +++++++++++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index 7189675f6a2..c4248cbbd84 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -60,6 +62,26 @@ static void tx4927_machine_restart(char *command) (*_machine_halt)(); } +void show_registers(struct pt_regs *regs); +static int tx4927_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4927_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4927_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4927_be_init(void) +{ + board_be_handler = tx4927_be_handler; +} + static struct resource tx4927_sdram_resource[4]; void __init tx4927_setup(void) @@ -197,6 +219,7 @@ void __init tx4927_setup(void) __raw_writel(0, &tx4927_pioptr->maskext); _machine_restart = tx4927_machine_restart; + board_be_init = tx4927_be_init; } void __init tx4927_time_init(unsigned int tmrnr) diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 4fbc85a8597..0d8517ad3ad 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -60,6 +62,26 @@ static void tx4938_machine_restart(char *command) (*_machine_halt)(); } +void show_registers(struct pt_regs *regs); +static int tx4938_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4938_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4938_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4938_be_init(void) +{ + board_be_handler = tx4938_be_handler; +} + static struct resource tx4938_sdram_resource[4]; static struct resource tx4938_sram_resource; @@ -257,6 +279,7 @@ void __init tx4938_setup(void) } _machine_restart = tx4938_machine_restart; + board_be_init = tx4938_be_init; } void __init tx4938_time_init(unsigned int tmrnr) -- GitLab From ee25d33f87348fd9e0ea148c4a25a3e7415fb5ba Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:17 +0900 Subject: [PATCH 3887/5416] MIPS: TXx9: Add __init tag for tx4938_pcic1_map_irq. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-tx4938.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c index 60e2c52c2c5..1ea257bc3b8 100644 --- a/arch/mips/pci/pci-tx4938.c +++ b/arch/mips/pci/pci-tx4938.c @@ -114,7 +114,7 @@ int __init tx4938_pciclk66_setup(void) return pciclk; } -int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) +int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) { if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) { switch (slot) { -- GitLab From 021635280d4572b9d9bb5481b00afea8a66b295f Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 19 Aug 2008 22:55:18 +0900 Subject: [PATCH 3888/5416] MIPS: TXx9: Declare smsc_fdc37m81x_config_get() in smsc_fdc37m81x.h Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/txx9/smsc_fdc37m81x.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-mips/txx9/smsc_fdc37m81x.h b/include/asm-mips/txx9/smsc_fdc37m81x.h index 02e161d0755..d1d6332b4ca 100644 --- a/include/asm-mips/txx9/smsc_fdc37m81x.h +++ b/include/asm-mips/txx9/smsc_fdc37m81x.h @@ -62,6 +62,7 @@ void smsc_fdc37m81x_config_beg(void); void smsc_fdc37m81x_config_end(void); +u8 smsc_fdc37m81x_config_get(u8 reg); void smsc_fdc37m81x_config_set(u8 reg, u8 val); #endif -- GitLab From 3cd4e067a3e548a56a8b5e202552dcd18a2783a9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:00:22 +0200 Subject: [PATCH 3889/5416] MIPS: RB532: Cleanup and group definitions to their right places This patch moves GPIO related definitions to gpio.h and IRQ related to irq.h Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/devices.c | 16 ++-------------- include/asm-mips/mach-rc32434/gpio.h | 9 +++++++++ include/asm-mips/mach-rc32434/irq.h | 5 +++++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 82ab395efa3..7090dc97606 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -34,21 +34,11 @@ #include #include #include - -#define ETH0_DMA_RX_IRQ (GROUP1_IRQ_BASE + 0) -#define ETH0_DMA_TX_IRQ (GROUP1_IRQ_BASE + 1) -#define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9) -#define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10) +#include #define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET) #define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET) -/* NAND definitions */ -#define GPIO_RDY (1 << 0x08) -#define GPIO_WPX (1 << 0x09) -#define GPIO_ALE (1 << 0x0a) -#define GPIO_CLE (1 << 0x0b) - static struct resource korina_dev0_res[] = { { .name = "korina_regs", @@ -101,8 +91,6 @@ static struct platform_device korina_dev0 = { .num_resources = ARRAY_SIZE(korina_dev0_res), }; -#define CF_GPIO_NUM 13 - static struct resource cf_slot0_res[] = { { .name = "cf_membase", @@ -116,7 +104,7 @@ static struct resource cf_slot0_res[] = { }; static struct cf_device cf_slot0_data = { - .gpio_pin = 13 + .gpio_pin = CF_GPIO_NUM }; static struct platform_device cf_slot0 = { diff --git a/include/asm-mips/mach-rc32434/gpio.h b/include/asm-mips/mach-rc32434/gpio.h index f946f5f45bb..4fe18dbacaf 100644 --- a/include/asm-mips/mach-rc32434/gpio.h +++ b/include/asm-mips/mach-rc32434/gpio.h @@ -61,6 +61,15 @@ struct rb532_gpio_reg { /* PCI messaging unit */ #define RC32434_PCI_MSU_GPIO (1 << 13) +/* NAND GPIO signals */ +#define GPIO_RDY (1 << 0x08) +#define GPIO_WPX (1 << 0x09) +#define GPIO_ALE (1 << 0x0a) +#define GPIO_CLE (1 << 0x0b) + +/* Compact Flash GPIO pin */ +#define CF_GPIO_NUM 13 + extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val); extern unsigned get_434_reg(unsigned reg_offs); diff --git a/include/asm-mips/mach-rc32434/irq.h b/include/asm-mips/mach-rc32434/irq.h index cb9e4725f5d..d68318b6b76 100644 --- a/include/asm-mips/mach-rc32434/irq.h +++ b/include/asm-mips/mach-rc32434/irq.h @@ -5,4 +5,9 @@ #include +#define ETH0_DMA_RX_IRQ (GROUP1_IRQ_BASE + 0) +#define ETH0_DMA_TX_IRQ (GROUP1_IRQ_BASE + 1) +#define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9) +#define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10) + #endif /* __ASM_RC32434_IRQ_H */ -- GitLab From 3c8cf8caa5b217fbb17d0dce7f6bbec1d7da7249 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:01:03 +0200 Subject: [PATCH 3890/5416] MIPS: RB532: Use physical addresses for gpio and device controller registers This patch fixes the misuse of virtual addresses for the GPIO and third device controller which would lead to problems while accessing ioremap'd registers. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/gpio.c | 8 ++++---- include/asm-mips/mach-rc32434/rb.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 00a1c7877bf..11d7127655e 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -47,8 +47,8 @@ struct mpmc_device dev3; static struct resource rb532_gpio_reg0_res[] = { { .name = "gpio_reg0", - .start = (u32)(IDT434_REG_BASE + GPIOBASE), - .end = (u32)(IDT434_REG_BASE + GPIOBASE + sizeof(struct rb532_gpio_reg)), + .start = REGBASE + GPIOBASE, + .end = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1, .flags = IORESOURCE_MEM, } }; @@ -56,8 +56,8 @@ static struct resource rb532_gpio_reg0_res[] = { static struct resource rb532_dev3_ctl_res[] = { { .name = "dev3_ctl", - .start = (u32)(IDT434_REG_BASE + DEV3BASE), - .end = (u32)(IDT434_REG_BASE + DEV3BASE + sizeof(struct dev_reg)), + .start = REGBASE + DEV3BASE, + .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1, .flags = IORESOURCE_MEM, } }; diff --git a/include/asm-mips/mach-rc32434/rb.h b/include/asm-mips/mach-rc32434/rb.h index e0a76e3ffea..62ac73c999c 100644 --- a/include/asm-mips/mach-rc32434/rb.h +++ b/include/asm-mips/mach-rc32434/rb.h @@ -17,7 +17,8 @@ #include -#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(0x18000000)) +#define REGBASE 0x18000000 +#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(REGBASE)) #define DEV0BASE 0x010000 #define DEV0MASK 0x010004 #define DEV0C 0x010008 -- GitLab From 49afa0a15180c22c8836ef36edd6aa48ab7b2915 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:01:31 +0200 Subject: [PATCH 3891/5416] MIPS: RB532: Remove gpio bootup state We are no longer using gpio bootup state, so do not export it and do not parse the kernel command line tag for it. Instead we provide gpio-keys for the button the gpio bootup state was checking. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/prom.c | 10 ---------- include/asm-mips/mach-rc32434/prom.h | 4 ---- 2 files changed, 14 deletions(-) diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index 1bc0af8febf..c5d8868e1b1 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -41,8 +41,6 @@ extern void __init setup_serial_port(void); unsigned int idt_cpu_freq = 132000000; EXPORT_SYMBOL(idt_cpu_freq); -unsigned int gpio_bootup_state; -EXPORT_SYMBOL(gpio_bootup_state); static struct resource ddr_reg[] = { { @@ -108,9 +106,6 @@ void __init prom_setup_cmdline(void) mips_machtype = MACH_MIKROTIK_RB532; } - if (match_tag(prom_argv[i], GPIO_TAG)) - gpio_bootup_state = tag2ul(prom_argv[i], GPIO_TAG); - strcpy(cp, prom_argv[i]); cp += strlen(prom_argv[i]); } @@ -122,11 +117,6 @@ void __init prom_setup_cmdline(void) strcpy(cp, arcs_cmdline); cp += strlen(arcs_cmdline); } - if (gpio_bootup_state & 0x02) - strcpy(cp, GPIO_INIT_NOBUTTON); - else - strcpy(cp, GPIO_INIT_BUTTON); - cmd_line[CL_SIZE-1] = '\0'; strcpy(arcs_cmdline, cmd_line); diff --git a/include/asm-mips/mach-rc32434/prom.h b/include/asm-mips/mach-rc32434/prom.h index 1d66ddcda89..660707f1bcc 100644 --- a/include/asm-mips/mach-rc32434/prom.h +++ b/include/asm-mips/mach-rc32434/prom.h @@ -28,14 +28,10 @@ #define PROM_ENTRY(x) (0xbfc00000 + ((x) * 8)) -#define GPIO_INIT_NOBUTTON "" -#define GPIO_INIT_BUTTON " 2" - #define SR_NMI 0x00180000 #define SERIAL_SPEED_ENTRY 0x00000001 #define FREQ_TAG "HZ=" -#define GPIO_TAG "gpio=" #define KMAC_TAG "kmac=" #define MEM_TAG "mem=" #define BOARD_TAG "board=" -- GitLab From c76befc3429354909d3242d11b8d3bcb3bea4b03 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:02:03 +0200 Subject: [PATCH 3892/5416] MIPS: RB532: replace raw volatile read with a readl This patch replaces a raw read using volatiles with a readl. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 11d7127655e..b028779fedd 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -70,7 +70,7 @@ void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val) spin_lock_irqsave(&dev3.lock, flags); - data = *(volatile unsigned *) (IDT434_REG_BASE + reg_offs); + data = readl(IDT434_REG_BASE + reg_offs); for (i = 0; i != len; ++i) { if (val & (1 << i)) data |= (1 << (i + bit)); -- GitLab From b6e2f58a503b56e154f90dc516647c93c5fe873d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Aug 2008 17:03:03 +0200 Subject: [PATCH 3893/5416] MIPS: RB532: Fix id usage in platform devices When there is only platform device of the same type, id = -1 should be used, fix this. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/devices.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 7090dc97606..31619c601b1 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -84,7 +84,7 @@ static struct korina_device korina_dev0_data = { }; static struct platform_device korina_dev0 = { - .id = 0, + .id = -1, .name = "korina", .dev.platform_data = &korina_dev0_data, .resource = korina_dev0_res, @@ -108,7 +108,7 @@ static struct cf_device cf_slot0_data = { }; static struct platform_device cf_slot0 = { - .id = 0, + .id = -1, .name = "pata-rb532-cf", .dev.platform_data = &cf_slot0_data, .resource = cf_slot0_res, @@ -173,7 +173,7 @@ static struct mtd_partition rb532_partition_info[] = { static struct platform_device rb532_led = { .name = "rb532-led", - .id = 0, + .id = -1, }; static struct gpio_keys_button rb532_gpio_btn[] = { -- GitLab From deeb45ac4a32c8271b022ecba73913bc1112e8e6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:53:24 +0200 Subject: [PATCH 3894/5416] MIPS: RB532: Remove obsolute reference to setup_serial_port We are no longer using setup_serial_port. So just remove it from the prom code. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/prom.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index c5d8868e1b1..46ca24dbcc2 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -37,8 +37,6 @@ #include #include -extern void __init setup_serial_port(void); - unsigned int idt_cpu_freq = 132000000; EXPORT_SYMBOL(idt_cpu_freq); -- GitLab From 606a083b1e1a357cb66454e4581b80f1a67d8368 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:53:50 +0200 Subject: [PATCH 3895/5416] MIPS: RB532: Cleanup the headers again This patch cleans up headers and regroups informations to where they should reside. While moving, try to have a consistant naming for defines. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/rb532/irq.c | 2 +- arch/mips/rb532/serial.c | 6 ++--- arch/mips/rb532/setup.c | 4 ++-- include/asm-mips/mach-rc32434/irq.h | 20 +++++++++++++++++ include/asm-mips/mach-rc32434/rb.h | 2 ++ include/asm-mips/mach-rc32434/rc32434.h | 30 ------------------------- 6 files changed, 28 insertions(+), 36 deletions(-) diff --git a/arch/mips/rb532/irq.c b/arch/mips/rb532/irq.c index c0d0f950caf..549b46d2fce 100644 --- a/arch/mips/rb532/irq.c +++ b/arch/mips/rb532/irq.c @@ -45,7 +45,7 @@ #include #include -#include +#include struct intr_group { u32 mask; /* mask of valid bits in pending/mask registers */ diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c index 1a05b5ddee0..3e0d7ec3a57 100644 --- a/arch/mips/rb532/serial.c +++ b/arch/mips/rb532/serial.c @@ -31,16 +31,16 @@ #include #include -#include +#include extern unsigned int idt_cpu_freq; static struct uart_port rb532_uart = { .type = PORT_16550A, .line = 0, - .irq = RC32434_UART0_IRQ, + .irq = UART0_IRQ, .iotype = UPIO_MEM, - .membase = (char *)KSEG1ADDR(RC32434_UART0_BASE), + .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE), .regshift = 2 }; diff --git a/arch/mips/rb532/setup.c b/arch/mips/rb532/setup.c index 7aafa95ac20..50f530f5b60 100644 --- a/arch/mips/rb532/setup.c +++ b/arch/mips/rb532/setup.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include struct pci_reg __iomem *pci_reg; @@ -27,7 +27,7 @@ static struct resource pci0_res[] = { static void rb_machine_restart(char *command) { /* just jump to the reset vector */ - writel(0x80000001, (void *)KSEG1ADDR(RC32434_REG_BASE + RC32434_RST)); + writel(0x80000001, IDT434_REG_BASE + RST); ((void (*)(void)) KSEG1ADDR(0x1FC00000u))(); } diff --git a/include/asm-mips/mach-rc32434/irq.h b/include/asm-mips/mach-rc32434/irq.h index d68318b6b76..56738d8ec4e 100644 --- a/include/asm-mips/mach-rc32434/irq.h +++ b/include/asm-mips/mach-rc32434/irq.h @@ -4,6 +4,26 @@ #define NR_IRQS 256 #include +#include + +/* Interrupt Controller */ +#define IC_GROUP0_PEND (REGBASE + 0x38000) +#define IC_GROUP0_MASK (REGBASE + 0x38008) +#define IC_GROUP_OFFSET 0x0C + +#define NUM_INTR_GROUPS 5 + +/* 16550 UARTs */ +#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */ + /* GRP3 IRQ numbers start here */ +#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) + /* GRP4 IRQ numbers start here */ +#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) + /* GRP5 IRQ numbers start here */ +#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) +#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32) + +#define UART0_IRQ (GROUP3_IRQ_BASE + 0) #define ETH0_DMA_RX_IRQ (GROUP1_IRQ_BASE + 0) #define ETH0_DMA_TX_IRQ (GROUP1_IRQ_BASE + 1) diff --git a/include/asm-mips/mach-rc32434/rb.h b/include/asm-mips/mach-rc32434/rb.h index 62ac73c999c..79e8ef67d0d 100644 --- a/include/asm-mips/mach-rc32434/rb.h +++ b/include/asm-mips/mach-rc32434/rb.h @@ -19,6 +19,8 @@ #define REGBASE 0x18000000 #define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(REGBASE)) +#define UART0BASE 0x58000 +#define RST (1 << 15) #define DEV0BASE 0x010000 #define DEV0MASK 0x010004 #define DEV0C 0x010008 diff --git a/include/asm-mips/mach-rc32434/rc32434.h b/include/asm-mips/mach-rc32434/rc32434.h index c4a02145104..9df04b72744 100644 --- a/include/asm-mips/mach-rc32434/rc32434.h +++ b/include/asm-mips/mach-rc32434/rc32434.h @@ -8,37 +8,7 @@ #include #include -#define RC32434_REG_BASE 0x18000000 -#define RC32434_RST (1 << 15) - #define IDT_CLOCK_MULT 2 -#define MIPS_CPU_TIMER_IRQ 7 - -/* Interrupt Controller */ -#define IC_GROUP0_PEND (RC32434_REG_BASE + 0x38000) -#define IC_GROUP0_MASK (RC32434_REG_BASE + 0x38008) -#define IC_GROUP_OFFSET 0x0C - -#define NUM_INTR_GROUPS 5 - -/* 16550 UARTs */ -#define GROUP0_IRQ_BASE 8 /* GRP2 IRQ numbers start here */ - /* GRP3 IRQ numbers start here */ -#define GROUP1_IRQ_BASE (GROUP0_IRQ_BASE + 32) - /* GRP4 IRQ numbers start here */ -#define GROUP2_IRQ_BASE (GROUP1_IRQ_BASE + 32) - /* GRP5 IRQ numbers start here */ -#define GROUP3_IRQ_BASE (GROUP2_IRQ_BASE + 32) -#define GROUP4_IRQ_BASE (GROUP3_IRQ_BASE + 32) - - -#ifdef __MIPSEB__ -#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58003) -#else -#define RC32434_UART0_BASE (RC32434_REG_BASE + 0x58000) -#endif - -#define RC32434_UART0_IRQ (GROUP3_IRQ_BASE + 0) /* cpu pipeline flush */ static inline void rc32434_sync(void) -- GitLab From 09b7dcf220a37245b16fd4a716923d75bf6edf8b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:54:04 +0200 Subject: [PATCH 3896/5416] MIPS: RB532: Remove unused rc32434_sync_delay and rc32434_sync_udelay This patch removes these two unused functions : rc32434_sync_delay and rc32434_sync_udelay Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- include/asm-mips/mach-rc32434/rc32434.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/asm-mips/mach-rc32434/rc32434.h b/include/asm-mips/mach-rc32434/rc32434.h index 9df04b72744..fce25d4231f 100644 --- a/include/asm-mips/mach-rc32434/rc32434.h +++ b/include/asm-mips/mach-rc32434/rc32434.h @@ -16,16 +16,4 @@ static inline void rc32434_sync(void) __asm__ volatile ("sync"); } -static inline void rc32434_sync_udelay(int us) -{ - __asm__ volatile ("sync"); - udelay(us); -} - -static inline void rc32434_sync_delay(int ms) -{ - __asm__ volatile ("sync"); - mdelay(ms); -} - #endif /* _ASM_RC32434_RC32434_H_ */ -- GitLab From d888e25b8dd1b501ac75b0c6587c043a394319c3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:54:34 +0200 Subject: [PATCH 3897/5416] MIPS: RB532: Convert to GPIO lib This patch converts the rb532 code to use gpio library and register its gpio chip. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/rb532/gpio.c | 228 +++++++++++++++++++-------- include/asm-mips/mach-rc32434/gpio.h | 75 ++------- 3 files changed, 176 insertions(+), 129 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1e06d233fa8..00a23a11849 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -568,7 +568,7 @@ config MIKROTIK_RB532 select SYS_SUPPORTS_LITTLE_ENDIAN select SWAP_IO_SPACE select BOOT_RAW - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support the Mikrotik(tm) RouterBoard 532 series, based on the IDT RC32434 SoC. diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index b028779fedd..76a7fd96d56 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -27,20 +27,23 @@ */ #include -#include #include #include -#include #include -#include #include - -#include +#include #include - -struct rb532_gpio_reg __iomem *rb532_gpio_reg0; -EXPORT_SYMBOL(rb532_gpio_reg0); +#include + +struct rb532_gpio_chip { + struct gpio_chip chip; + void __iomem *regbase; + void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value); + int (*get_int_level)(struct gpio_chip *chip, unsigned offset); + void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value); + int (*get_int_status)(struct gpio_chip *chip, unsigned offset); +}; struct mpmc_device dev3; @@ -108,108 +111,199 @@ unsigned char get_latch_u5(void) } EXPORT_SYMBOL(get_latch_u5); -int rb532_gpio_get_value(unsigned gpio) +/* + * Return GPIO level */ +static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpiod) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOD) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_value); -void rb532_gpio_set_value(unsigned gpio, int value) +/* + * Set output GPIO level + */ +static void rb532_gpio_set(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpvr; - tmp = readl(&rb532_gpio_reg0->gpiod) & ~(1 << gpio); - if (value) - tmp |= 1 << gpio; + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpvr = gpch->regbase + GPIOD; - writel(tmp, (void *)&rb532_gpio_reg0->gpiod); + local_irq_save(flags); + tmp = readl(gpvr); + if (value) + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpvr); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_value); -int rb532_gpio_direction_input(unsigned gpio) +/* + * Set GPIO direction to input + */ +static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - writel(readl(&rb532_gpio_reg0->gpiocfg) & ~(1 << gpio), - (void *)&rb532_gpio_reg0->gpiocfg); + unsigned long flags; + u32 mask = 1 << offset; + u32 value; + struct rb532_gpio_chip *gpch; + void __iomem *gpdr; - return 0; -} -EXPORT_SYMBOL(rb532_gpio_direction_input); + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpdr = gpch->regbase + GPIOCFG; -int rb532_gpio_direction_output(unsigned gpio, int value) -{ - gpio_set_value(gpio, value); - writel(readl(&rb532_gpio_reg0->gpiocfg) | (1 << gpio), - (void *)&rb532_gpio_reg0->gpiocfg); + local_irq_save(flags); + value = readl(gpdr); + value &= ~mask; + writel(value, gpdr); + local_irq_restore(flags); return 0; } -EXPORT_SYMBOL(rb532_gpio_direction_output); -void rb532_gpio_set_int_level(unsigned gpio, int value) +/* + * Set GPIO direction to output + */ +static int rb532_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpdr; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + writel(mask, gpch->regbase + GPIOD); + gpdr = gpch->regbase + GPIOCFG; + + local_irq_save(flags); + tmp = readl(gpdr); + tmp |= mask; + writel(tmp, gpdr); + local_irq_restore(flags); - tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio); - if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel); + return 0; } -EXPORT_SYMBOL(rb532_gpio_set_int_level); -int rb532_gpio_get_int_level(unsigned gpio) +/* + * Set the GPIO interrupt level + */ +static void rb532_gpio_set_int_level(struct gpio_chip *chip, + unsigned offset, int value) { - return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio); -} -EXPORT_SYMBOL(rb532_gpio_get_int_level); + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpil; -void rb532_gpio_set_int_status(unsigned gpio, int value) -{ - unsigned tmp; + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpil = gpch->regbase + GPIOILEVEL; - tmp = readl(&rb532_gpio_reg0->gpioistat); + local_irq_save(flags); + tmp = readl(gpil); if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpioistat); + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpil); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_int_status); -int rb532_gpio_get_int_status(unsigned gpio) +/* + * Get the GPIO interrupt level + */ +static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpioistat) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOILEVEL) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_int_status); -void rb532_gpio_set_func(unsigned gpio, int value) +/* + * Set the GPIO interrupt status + */ +static void rb532_gpio_set_int_status(struct gpio_chip *chip, + unsigned offset, int value) { - unsigned tmp; + unsigned long flags; + u32 mask = 1 << offset; + u32 tmp; + struct rb532_gpio_chip *gpch; + void __iomem *gpis; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + gpis = gpch->regbase + GPIOISTAT; - tmp = readl(&rb532_gpio_reg0->gpiofunc); + local_irq_save(flags); + tmp = readl(gpis); if (value) - tmp |= 1 << gpio; - writel(tmp, (void *)&rb532_gpio_reg0->gpiofunc); + tmp |= mask; + else + tmp &= ~mask; + writel(tmp, gpis); + local_irq_restore(flags); } -EXPORT_SYMBOL(rb532_gpio_set_func); -int rb532_gpio_get_func(unsigned gpio) +/* + * Get the GPIO interrupt status + */ +static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset) { - return readl(&rb532_gpio_reg0->gpiofunc) & (1 << gpio); + u32 mask = 1 << offset; + struct rb532_gpio_chip *gpch; + + gpch = container_of(chip, struct rb532_gpio_chip, chip); + return readl(gpch->regbase + GPIOISTAT) & mask; } -EXPORT_SYMBOL(rb532_gpio_get_func); + +static struct rb532_gpio_chip rb532_gpio_chip[] = { + [0] = { + .chip = { + .label = "gpio0", + .direction_input = rb532_gpio_direction_input, + .direction_output = rb532_gpio_direction_output, + .get = rb532_gpio_get, + .set = rb532_gpio_set, + .base = 0, + .ngpio = 32, + }, + .get_int_level = rb532_gpio_get_int_level, + .set_int_level = rb532_gpio_set_int_level, + .get_int_status = rb532_gpio_get_int_status, + .set_int_status = rb532_gpio_set_int_status, + }, +}; int __init rb532_gpio_init(void) { - rb532_gpio_reg0 = ioremap_nocache(rb532_gpio_reg0_res[0].start, - rb532_gpio_reg0_res[0].end - - rb532_gpio_reg0_res[0].start); + struct resource *r; - if (!rb532_gpio_reg0) { + r = rb532_gpio_reg0_res; + rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start); + + if (!rb532_gpio_chip->regbase) { printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); return -ENXIO; } - dev3.base = ioremap_nocache(rb532_dev3_ctl_res[0].start, - rb532_dev3_ctl_res[0].end - - rb532_dev3_ctl_res[0].start); + /* Register our GPIO chip */ + gpiochip_add(&rb532_gpio_chip->chip); + + r = rb532_dev3_ctl_res; + dev3.base = ioremap_nocache(r->start, r->end - r->start); if (!dev3.base) { printk(KERN_ERR "rb532: cannot remap device controller 3\n"); diff --git a/include/asm-mips/mach-rc32434/gpio.h b/include/asm-mips/mach-rc32434/gpio.h index 4fe18dbacaf..3a70b41cd7a 100644 --- a/include/asm-mips/mach-rc32434/gpio.h +++ b/include/asm-mips/mach-rc32434/gpio.h @@ -15,6 +15,16 @@ #include +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value + +#define gpio_cansleep __gpio_cansleep + +#define gpio_to_irq(gpio) IRQ_GPIO(gpio) +#define irq_to_gpio(irq) IRQ_TO_GPIO(irq) + +#include + struct rb532_gpio_reg { u32 gpiofunc; /* GPIO Function Register * gpiofunc[x]==0 bit = gpio @@ -62,74 +72,17 @@ struct rb532_gpio_reg { #define RC32434_PCI_MSU_GPIO (1 << 13) /* NAND GPIO signals */ -#define GPIO_RDY (1 << 0x08) -#define GPIO_WPX (1 << 0x09) -#define GPIO_ALE (1 << 0x0a) -#define GPIO_CLE (1 << 0x0b) +#define GPIO_RDY 8 +#define GPIO_WPX 9 +#define GPIO_ALE 10 +#define GPIO_CLE 11 /* Compact Flash GPIO pin */ #define CF_GPIO_NUM 13 - extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val); extern unsigned get_434_reg(unsigned reg_offs); extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); extern unsigned char get_latch_u5(void); -extern int rb532_gpio_get_value(unsigned gpio); -extern void rb532_gpio_set_value(unsigned gpio, int value); -extern int rb532_gpio_direction_input(unsigned gpio); -extern int rb532_gpio_direction_output(unsigned gpio, int value); -extern void rb532_gpio_set_int_level(unsigned gpio, int value); -extern int rb532_gpio_get_int_level(unsigned gpio); -extern void rb532_gpio_set_int_status(unsigned gpio, int value); -extern int rb532_gpio_get_int_status(unsigned gpio); - - -/* Wrappers for the arch-neutral GPIO API */ - -static inline int gpio_request(unsigned gpio, const char *label) -{ - /* Not yet implemented */ - return 0; -} - -static inline void gpio_free(unsigned gpio) -{ - /* Not yet implemented */ -} - -static inline int gpio_direction_input(unsigned gpio) -{ - return rb532_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return rb532_gpio_direction_output(gpio, value); -} - -static inline int gpio_get_value(unsigned gpio) -{ - return rb532_gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - rb532_gpio_set_value(gpio, value); -} - -static inline int gpio_to_irq(unsigned gpio) -{ - return gpio; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return irq; -} - -/* For cansleep */ -#include - #endif /* _RC32434_GPIO_H_ */ -- GitLab From 9bed90c6a46f10c2d3052c0585057a5cb7392b92 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 23 Aug 2008 18:54:37 +0200 Subject: [PATCH 3898/5416] Documentation: Document the RB532 specific kmac tag The Routerboard 532 bootloader passes the korina ethernet MAC adapter address to the kernel on the command line. Document this in the kernel-parameters file. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- Documentation/kernel-parameters.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 329dcabe4c5..d0fff6302f6 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1014,6 +1014,10 @@ and is between 256 and 4096 characters. It is defined in the file (only serial suported for now) Format: [,baud] + kmac= [MIPS] korina ethernet MAC address. + Configure the RouterBoard 532 series on-chip + Ethernet adapter MAC address. + l2cr= [PPC] l3cr= [PPC] -- GitLab From f6d9831bb11eb465f95fb1736b866d405d9c7cbf Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:36 +0900 Subject: [PATCH 3899/5416] MIPS: TXx9: stop_unused_modules TXx9 SoCs have pin multiplex. Stop some controller modules which can not be used due to pin configurations. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup_tx4927.c | 31 +++++++++++++++ arch/mips/txx9/generic/setup_tx4938.c | 56 +++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index c4248cbbd84..914e93c6263 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c @@ -252,3 +252,34 @@ void __init tx4927_mtd_init(int ch) return; /* disabled */ txx9_physmap_flash_init(ch, start, size, &pdata); } + +static void __init tx4927_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4927_ccfgptr->pcfg); + if (!(pcfg & TX4927_PCFG_SEL2)) { + rst |= TX4927_CLKCTR_ACLRST; + ckd |= TX4927_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if (rst | ckd) { + txx9_set64(&tx4927_ccfgptr->clkctr, rst); + txx9_set64(&tx4927_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4927_late_init(void) +{ + if (txx9_pcode != 0x4927) + return -ENODEV; + tx4927_stop_unused_modules(); + return 0; +} +late_initcall(tx4927_late_init); diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 0d8517ad3ad..af724e53ef9 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c @@ -334,3 +334,59 @@ void __init tx4938_mtd_init(int ch) return; /* disabled */ txx9_physmap_flash_init(ch, start, size, &pdata); } + +static void __init tx4938_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); + switch (txx9_pcode) { + case 0x4937: + if (!(pcfg & TX4938_PCFG_SEL2)) { + rst |= TX4938_CLKCTR_ACLRST; + ckd |= TX4938_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + break; + case 0x4938: + if (!(pcfg & TX4938_PCFG_SEL2) || + (pcfg & TX4938_PCFG_ETH0_SEL)) { + rst |= TX4938_CLKCTR_ACLRST; + ckd |= TX4938_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if ((pcfg & + (TX4938_PCFG_ATA_SEL | TX4938_PCFG_ISA_SEL | + TX4938_PCFG_NDF_SEL)) + != TX4938_PCFG_NDF_SEL) { + rst |= TX4938_CLKCTR_NDFRST; + ckd |= TX4938_CLKCTR_NDFCKD; + strcat(buf, " NDFMC"); + } + if (!(pcfg & TX4938_PCFG_SPI_SEL)) { + rst |= TX4938_CLKCTR_SPIRST; + ckd |= TX4938_CLKCTR_SPICKD; + strcat(buf, " SPI"); + } + break; + } + if (rst | ckd) { + txx9_set64(&tx4938_ccfgptr->clkctr, rst); + txx9_set64(&tx4938_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4938_late_init(void) +{ + if (txx9_pcode != 0x4937 && txx9_pcode != 0x4938) + return -ENODEV; + tx4938_stop_unused_modules(); + return 0; +} +late_initcall(tx4938_late_init); -- GitLab From 21e77df215e58523a755b5dd006cb17610616f20 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:37 +0900 Subject: [PATCH 3900/5416] MIPS: TXx9: Microoptimize interrupt handlers The IOC interrupt status register on RBTX49XX only have 8 bits. Use 8-bit version of __fls() to optimize interrupt handlers. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/rbtx4927/irq.c | 6 +++--- arch/mips/txx9/rbtx4938/irq.c | 8 ++++---- include/asm-mips/txx9/generic.h | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c index 22076e3f03a..9c14ebb26cb 100644 --- a/arch/mips/txx9/rbtx4927/irq.c +++ b/arch/mips/txx9/rbtx4927/irq.c @@ -133,9 +133,9 @@ static int toshiba_rbtx4927_irq_nested(int sw_irq) u8 level3; level3 = readb(rbtx4927_imstat_addr) & 0x1f; - if (level3) - sw_irq = RBTX4927_IRQ_IOC + fls(level3) - 1; - return sw_irq; + if (unlikely(!level3)) + return -1; + return RBTX4927_IRQ_IOC + __fls8(level3); } static void __init toshiba_rbtx4927_irq_ioc_init(void) diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c index ca2f8306ce9..7d21befb893 100644 --- a/arch/mips/txx9/rbtx4938/irq.c +++ b/arch/mips/txx9/rbtx4938/irq.c @@ -85,10 +85,10 @@ static int toshiba_rbtx4938_irq_nested(int sw_irq) u8 level3; level3 = readb(rbtx4938_imstat_addr); - if (level3) - /* must use fls so onboard ATA has priority */ - sw_irq = RBTX4938_IRQ_IOC + fls(level3) - 1; - return sw_irq; + if (unlikely(!level3)) + return -1; + /* must use fls so onboard ATA has priority */ + return RBTX4938_IRQ_IOC + __fls8(level3); } static void __init diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index 1e1a9f2d237..dc85515eac1 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -64,4 +64,22 @@ struct physmap_flash_data; void txx9_physmap_flash_init(int no, unsigned long addr, unsigned long size, const struct physmap_flash_data *pdata); +/* 8 bit version of __fls(): find first bit set (returns 0..7) */ +static inline unsigned int __fls8(unsigned char x) +{ + int r = 7; + + if (!(x & 0xf0)) { + r -= 4; + x <<= 4; + } + if (!(x & 0xc0)) { + r -= 2; + x <<= 2; + } + if (!(x & 0x80)) + r -= 1; + return r; +} + #endif /* __ASM_TXX9_GENERIC_H */ -- GitLab From ae027ead87b13cff99b4f48da7696aa4fe75393b Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:38 +0900 Subject: [PATCH 3901/5416] MIPS: TXx9: IOC LED support Add leds-gpio platform device for controlling LEDs connected to IOC on RBTX49XX and JMR3927 board. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 111 +++++++++++++++++++++++++++++++ arch/mips/txx9/jmr3927/setup.c | 5 ++ arch/mips/txx9/rbtx4927/setup.c | 1 + arch/mips/txx9/rbtx4938/setup.c | 1 + include/asm-mips/txx9/generic.h | 4 ++ include/asm-mips/txx9/rbtx4927.h | 1 + 6 files changed, 123 insertions(+) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 118d716f783..1ea06553a1e 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -649,3 +650,113 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, platform_device_put(pdev); #endif } + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +static DEFINE_SPINLOCK(txx9_iocled_lock); + +#define TXX9_IOCLED_MAXLEDS 8 + +struct txx9_iocled_data { + struct gpio_chip chip; + u8 cur_val; + void __iomem *mmioaddr; + struct gpio_led_platform_data pdata; + struct gpio_led leds[TXX9_IOCLED_MAXLEDS]; + char names[TXX9_IOCLED_MAXLEDS][32]; +}; + +static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset) +{ + struct txx9_iocled_data *data = + container_of(chip, struct txx9_iocled_data, chip); + return data->cur_val & (1 << offset); +} + +static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct txx9_iocled_data *data = + container_of(chip, struct txx9_iocled_data, chip); + unsigned long flags; + spin_lock_irqsave(&txx9_iocled_lock, flags); + if (value) + data->cur_val |= 1 << offset; + else + data->cur_val &= ~(1 << offset); + writeb(data->cur_val, data->mmioaddr); + mmiowb(); + spin_unlock_irqrestore(&txx9_iocled_lock, flags); +} + +static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset) +{ + return 0; +} + +static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset, + int value) +{ + txx9_iocled_set(chip, offset, value); + return 0; +} + +void __init txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers) +{ + struct txx9_iocled_data *iocled; + struct platform_device *pdev; + int i; + static char *default_triggers[] __initdata = { + "heartbeat", + "ide-disk", + "nand-disk", + NULL, + }; + + if (!deftriggers) + deftriggers = default_triggers; + iocled = kzalloc(sizeof(*iocled), GFP_KERNEL); + if (!iocled) + return; + iocled->mmioaddr = ioremap(baseaddr, 1); + if (!iocled->mmioaddr) + return; + iocled->chip.get = txx9_iocled_get; + iocled->chip.set = txx9_iocled_set; + iocled->chip.direction_input = txx9_iocled_dir_in; + iocled->chip.direction_output = txx9_iocled_dir_out; + iocled->chip.label = "iocled"; + iocled->chip.base = basenum; + iocled->chip.ngpio = num; + if (gpiochip_add(&iocled->chip)) + return; + if (basenum < 0) + basenum = iocled->chip.base; + + pdev = platform_device_alloc("leds-gpio", basenum); + if (!pdev) + return; + iocled->pdata.num_leds = num; + iocled->pdata.leds = iocled->leds; + for (i = 0; i < num; i++) { + struct gpio_led *led = &iocled->leds[i]; + snprintf(iocled->names[i], sizeof(iocled->names[i]), + "iocled:%s:%u", color, i); + led->name = iocled->names[i]; + led->gpio = basenum + i; + led->active_low = lowactive; + if (deftriggers && *deftriggers) + led->default_trigger = *deftriggers++; + } + pdev->dev.platform_data = &iocled->pdata; + if (platform_device_add(pdev)) + platform_device_put(pdev); +} +#else /* CONFIG_LEDS_GPIO */ +void __init txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers) +{ +} +#endif /* CONFIG_LEDS_GPIO */ diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c index 0f3843c92cf..25e50a7be38 100644 --- a/arch/mips/txx9/jmr3927/setup.c +++ b/arch/mips/txx9/jmr3927/setup.c @@ -200,10 +200,15 @@ static void __init jmr3927_mtd_init(void) static void __init jmr3927_device_init(void) { + unsigned long iocled_base = JMR3927_IOC_LED_ADDR - IO_BASE; +#ifdef __LITTLE_ENDIAN + iocled_base |= 1; +#endif __swizzle_addr_b = jmr3927_swizzle_addr_b; jmr3927_rtc_init(); tx3927_wdt_init(); jmr3927_mtd_init(); + txx9_iocled_init(iocled_base, -1, 8, 1, "green", NULL); } struct txx9_board_vec jmr3927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c index abe32c1a79d..4a74423b2ba 100644 --- a/arch/mips/txx9/rbtx4927/setup.c +++ b/arch/mips/txx9/rbtx4927/setup.c @@ -321,6 +321,7 @@ static void __init rbtx4927_device_init(void) rbtx4927_ne_init(); tx4927_wdt_init(); rbtx4927_mtd_init(); + txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL); } struct txx9_board_vec rbtx4927_vec __initdata = { diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index ec6e81258f7..e077cc4d3a5 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c @@ -352,6 +352,7 @@ static void __init rbtx4938_device_init(void) rbtx4938_ne_init(); tx4938_wdt_init(); rbtx4938_mtd_init(); + txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); } struct txx9_board_vec rbtx4938_vec __initdata = { diff --git a/include/asm-mips/txx9/generic.h b/include/asm-mips/txx9/generic.h index dc85515eac1..4316a3e5767 100644 --- a/include/asm-mips/txx9/generic.h +++ b/include/asm-mips/txx9/generic.h @@ -82,4 +82,8 @@ static inline unsigned int __fls8(unsigned char x) return r; } +void txx9_iocled_init(unsigned long baseaddr, + int basenum, unsigned int num, int lowactive, + const char *color, char **deftriggers); + #endif /* __ASM_TXX9_GENERIC_H */ diff --git a/include/asm-mips/txx9/rbtx4927.h b/include/asm-mips/txx9/rbtx4927.h index c6015463432..b2adab3d1ac 100644 --- a/include/asm-mips/txx9/rbtx4927.h +++ b/include/asm-mips/txx9/rbtx4927.h @@ -34,6 +34,7 @@ #define RBTX4927_PCIIO 0x16000000 #define RBTX4927_PCIIO_SIZE 0x01000000 +#define RBTX4927_LED_ADDR (IO_BASE + TXX9_CE(2) + 0x00001000) #define RBTX4927_IMASK_ADDR (IO_BASE + TXX9_CE(2) + 0x00002000) #define RBTX4927_IMSTAT_ADDR (IO_BASE + TXX9_CE(2) + 0x00002006) #define RBTX4927_SOFTINT_ADDR (IO_BASE + TXX9_CE(2) + 0x00003000) -- GitLab From 0dcdbe6add26719e956299eb519542f7d2f7d0a8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:39 +0900 Subject: [PATCH 3902/5416] MIPS: TXx9: Add TX4939 SoC support Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/pci/pci-tx4939.c create mode 100644 arch/mips/txx9/generic/irq_tx4939.c create mode 100644 arch/mips/txx9/generic/setup_tx4939.c create mode 100644 include/asm-mips/txx9/tx4939.h --- arch/mips/pci/Makefile | 1 + arch/mips/pci/pci-tx4939.c | 109 ++++++ arch/mips/txx9/Kconfig | 7 + arch/mips/txx9/generic/Makefile | 1 + arch/mips/txx9/generic/irq_tx4939.c | 215 ++++++++++ arch/mips/txx9/generic/setup_tx4939.c | 460 ++++++++++++++++++++++ include/asm-mips/txx9/tx4939.h | 544 ++++++++++++++++++++++++++ 7 files changed, 1337 insertions(+) create mode 100644 arch/mips/pci/pci-tx4939.c create mode 100644 arch/mips/txx9/generic/irq_tx4939.c create mode 100644 arch/mips/txx9/generic/setup_tx4939.c create mode 100644 include/asm-mips/txx9/tx4939.h diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c8c32f417b6..b1886244ced 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o obj-$(CONFIG_SOC_TX4927) += pci-tx4927.o obj-$(CONFIG_SOC_TX4938) += pci-tx4938.o +obj-$(CONFIG_SOC_TX4939) += pci-tx4939.o obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-rbtx4938.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o diff --git a/arch/mips/pci/pci-tx4939.c b/arch/mips/pci/pci-tx4939.c new file mode 100644 index 00000000000..5fecf1cdc32 --- /dev/null +++ b/arch/mips/pci/pci-tx4939.c @@ -0,0 +1,109 @@ +/* + * linux/arch/mips/pci/pci-tx4939.c + * + * Based on linux/arch/mips/txx9/rbtx4939/setup.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright 2001, 2003-2005 MontaVista Software Inc. + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +int __init tx4939_report_pciclk(void) +{ + int pciclk = 0; + + pr_info("PCIC --%s PCICLK:", + (__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66) ? + " PCI66" : ""); + if (__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_PCICLKEN_ALL) { + pciclk = txx9_master_clock * 20 / 6; + if (!(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66)) + pciclk /= 2; + printk(KERN_CONT "Internal(%u.%uMHz)", + (pciclk + 50000) / 1000000, + ((pciclk + 50000) / 100000) % 10); + } else { + printk(KERN_CONT "External"); + pciclk = -1; + } + printk(KERN_CONT "\n"); + return pciclk; +} + +void __init tx4939_report_pci1clk(void) +{ + unsigned int pciclk = txx9_master_clock * 20 / 6; + + pr_info("PCIC1 -- PCICLK:%u.%uMHz\n", + (pciclk + 50000) / 1000000, + ((pciclk + 50000) / 100000) % 10); +} + +int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot) +{ + if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) { + switch (slot) { + case TX4927_PCIC_IDSEL_AD_TO_SLOT(31): + if (__raw_readq(&tx4939_ccfgptr->pcfg) & + TX4939_PCFG_ET0MODE) + return TXX9_IRQ_BASE + TX4939_IR_ETH(0); + break; + case TX4927_PCIC_IDSEL_AD_TO_SLOT(30): + if (__raw_readq(&tx4939_ccfgptr->pcfg) & + TX4939_PCFG_ET1MODE) + return TXX9_IRQ_BASE + TX4939_IR_ETH(1); + break; + } + return 0; + } + return -1; +} + +int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = tx4939_pcic1_map_irq(dev, slot); + + if (irq >= 0) + return irq; + irq = pin; + /* IRQ rotation */ + irq--; /* 0-3 */ + irq = (irq + 33 - slot) % 4; + irq++; /* 1-4 */ + + switch (irq) { + case 1: + irq = TXX9_IRQ_BASE + TX4939_IR_INTA; + break; + case 2: + irq = TXX9_IRQ_BASE + TX4939_IR_INTB; + break; + case 3: + irq = TXX9_IRQ_BASE + TX4939_IR_INTC; + break; + case 4: + irq = TXX9_IRQ_BASE + TX4939_IR_INTD; + break; + } + return irq; +} + +void __init tx4939_setup_pcierr_irq(void) +{ + if (request_irq(TXX9_IRQ_BASE + TX4939_IR_PCIERR, + tx4927_pcierr_interrupt, + IRQF_DISABLED, "PCI error", + (void *)TX4939_PCIC_REG)) + pr_warning("Failed to request irq for PCIERR\n"); +} diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index aade3348af2..58691a1fe77 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -71,6 +71,13 @@ config SOC_TX4938 select PCI_TX4927 select GPIO_TXX9 +config SOC_TX4939 + bool + select CEVT_TXX9 + select HAS_TXX9_SERIAL + select HW_HAS_PCI + select PCI_TX4927 + config TOSHIBA_FPCIB0 bool "FPCIB0 Backplane Support" depends on PCI && MACH_TXX9 diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index 986852cc774..0030d23bef5 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_SOC_TX3927) += setup_tx3927.o irq_tx3927.o obj-$(CONFIG_SOC_TX4927) += mem_tx4927.o setup_tx4927.o irq_tx4927.o obj-$(CONFIG_SOC_TX4938) += mem_tx4927.o setup_tx4938.o irq_tx4938.o +obj-$(CONFIG_SOC_TX4939) += setup_tx4939.o irq_tx4939.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o obj-$(CONFIG_SPI) += spi_eeprom.o diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c new file mode 100644 index 00000000000..013213a8706 --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx4939.c @@ -0,0 +1,215 @@ +/* + * TX4939 irq routines + * Based on linux/arch/mips/kernel/irq_txx9.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright 2001, 2003-2005 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * source@mvista.com + * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +/* + * TX4939 defines 64 IRQs. + * Similer to irq_txx9.c but different register layouts. + */ +#include +#include +#include +#include +#include +#include + +/* IRCER : Int. Control Enable */ +#define TXx9_IRCER_ICE 0x00000001 + +/* IRCR : Int. Control */ +#define TXx9_IRCR_LOW 0x00000000 +#define TXx9_IRCR_HIGH 0x00000001 +#define TXx9_IRCR_DOWN 0x00000002 +#define TXx9_IRCR_UP 0x00000003 +#define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002) + +/* IRSCR : Int. Status Control */ +#define TXx9_IRSCR_EIClrE 0x00000100 +#define TXx9_IRSCR_EIClr_MASK 0x0000000f + +/* IRCSR : Int. Current Status */ +#define TXx9_IRCSR_IF 0x00010000 + +#define irc_dlevel 0 +#define irc_elevel 1 + +static struct { + unsigned char level; + unsigned char mode; +} tx4939irq[TX4939_NUM_IR] __read_mostly; + +static void tx4939_irq_unmask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *lvlp; + int ofs; + if (irq_nr < 32) { + irq_nr--; + lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; + } else { + irq_nr -= 32; + lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; + } + ofs = (irq_nr & 16) + (irq_nr & 1) * 8; + __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) + | (tx4939irq[irq_nr].level << ofs), + lvlp); +} + +static inline void tx4939_irq_mask(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 __iomem *lvlp; + int ofs; + if (irq_nr < 32) { + irq_nr--; + lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; + } else { + irq_nr -= 32; + lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; + } + ofs = (irq_nr & 16) + (irq_nr & 1) * 8; + __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) + | (irc_dlevel << ofs), + lvlp); + mmiowb(); +} + +static void tx4939_irq_mask_ack(unsigned int irq) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + + tx4939_irq_mask(irq); + if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) { + irq_nr--; + /* clear edge detection */ + __raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf)) + << (irq_nr & 0x10), + &tx4939_ircptr->edc.r); + } +} + +static int tx4939_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned int irq_nr = irq - TXX9_IRQ_BASE; + u32 cr; + u32 __iomem *crp; + int ofs; + int mode; + + if (flow_type & IRQF_TRIGGER_PROBE) + return 0; + switch (flow_type & IRQF_TRIGGER_MASK) { + case IRQF_TRIGGER_RISING: + mode = TXx9_IRCR_UP; + break; + case IRQF_TRIGGER_FALLING: + mode = TXx9_IRCR_DOWN; + break; + case IRQF_TRIGGER_HIGH: + mode = TXx9_IRCR_HIGH; + break; + case IRQF_TRIGGER_LOW: + mode = TXx9_IRCR_LOW; + break; + default: + return -EINVAL; + } + if (irq_nr < 32) { + irq_nr--; + crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r; + } else { + irq_nr -= 32; + crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r; + } + ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2; + cr = __raw_readl(crp); + cr &= ~(0x3 << ofs); + cr |= (mode & 0x3) << ofs; + __raw_writel(cr, crp); + tx4939irq[irq_nr].mode = mode; + return 0; +} + +static struct irq_chip tx4939_irq_chip = { + .name = "TX4939", + .ack = tx4939_irq_mask_ack, + .mask = tx4939_irq_mask, + .mask_ack = tx4939_irq_mask_ack, + .unmask = tx4939_irq_unmask, + .set_type = tx4939_irq_set_type, +}; + +static int tx4939_irq_set_pri(int irc_irq, int new_pri) +{ + int old_pri; + + if ((unsigned int)irc_irq >= TX4939_NUM_IR) + return 0; + old_pri = tx4939irq[irc_irq].level; + tx4939irq[irc_irq].level = new_pri; + return old_pri; +} + +void __init tx4939_irq_init(void) +{ + int i; + + mips_cpu_irq_init(); + /* disable interrupt control */ + __raw_writel(0, &tx4939_ircptr->den.r); + __raw_writel(0, &tx4939_ircptr->maskint.r); + __raw_writel(0, &tx4939_ircptr->maskext.r); + /* irq_base + 0 is not used */ + for (i = 1; i < TX4939_NUM_IR; i++) { + tx4939irq[i].level = 4; /* middle level */ + tx4939irq[i].mode = TXx9_IRCR_LOW; + set_irq_chip_and_handler(TXX9_IRQ_BASE + i, + &tx4939_irq_chip, handle_level_irq); + } + + /* mask all IRC interrupts */ + __raw_writel(0, &tx4939_ircptr->msk.r); + for (i = 0; i < 16; i++) + __raw_writel(0, &tx4939_ircptr->lvl[i].r); + /* setup IRC interrupt mode (Low Active) */ + for (i = 0; i < 2; i++) + __raw_writel(0, &tx4939_ircptr->dm[i].r); + for (i = 0; i < 2; i++) + __raw_writel(0, &tx4939_ircptr->dm2[i].r); + /* enable interrupt control */ + __raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r); + __raw_writel(irc_elevel, &tx4939_ircptr->msk.r); + + set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT, + handle_simple_irq); + + /* raise priority for errors, timers, sio */ + tx4939_irq_set_pri(TX4939_IR_WTOERR, 7); + tx4939_irq_set_pri(TX4939_IR_PCIERR, 7); + tx4939_irq_set_pri(TX4939_IR_PCIPME, 7); + for (i = 0; i < TX4939_NUM_IR_TMR; i++) + tx4939_irq_set_pri(TX4939_IR_TMR(i), 6); + for (i = 0; i < TX4939_NUM_IR_SIO; i++) + tx4939_irq_set_pri(TX4939_IR_SIO(i), 5); +} + +int tx4939_irq(void) +{ + u32 csr = __raw_readl(&tx4939_ircptr->cs.r); + + if (likely(!(csr & TXx9_IRCSR_IF))) + return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1)); + return -1; +} diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c new file mode 100644 index 00000000000..f14a497077d --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -0,0 +1,460 @@ +/* + * TX4939 setup routines + * Based on linux/arch/mips/txx9/generic/setup_tx4938.c, + * and RBTX49xx patch from CELF patch archive. + * + * 2003-2005 (c) MontaVista Software, Inc. + * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __init tx4939_wdr_init(void) +{ + /* report watchdog reset status */ + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST) + pr_warning("Watchdog reset detected at 0x%lx\n", + read_c0_errorepc()); + /* clear WatchDogReset (W1C) */ + tx4939_ccfg_set(TX4939_CCFG_WDRST); + /* do reset on watchdog */ + tx4939_ccfg_set(TX4939_CCFG_WR); +} + +void __init tx4939_wdt_init(void) +{ + txx9_wdt_init(TX4939_TMR_REG(2) & 0xfffffffffULL); +} + +static void tx4939_machine_restart(char *command) +{ + local_irq_disable(); + pr_emerg("Rebooting (with %s watchdog reset)...\n", + (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) ? + "external" : "internal"); + /* clear watchdog status */ + tx4939_ccfg_set(TX4939_CCFG_WDRST); /* W1C */ + txx9_wdt_now(TX4939_TMR_REG(2) & 0xfffffffffULL); + while (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST)) + ; + mdelay(10); + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) { + pr_emerg("Rebooting (with internal watchdog reset)...\n"); + /* External WDRST failed. Do internal watchdog reset */ + tx4939_ccfg_clear(TX4939_CCFG_WDREXEN); + } + /* fallback */ + (*_machine_halt)(); +} + +void show_registers(struct pt_regs *regs); +static int tx4939_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + console_verbose(); + pr_err("%cBE exception at %#lx\n", + data ? 'D' : 'I', regs->cp0_epc); + pr_err("ccfg:%llx, toea:%llx\n", + (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->toea)); +#ifdef CONFIG_PCI + tx4927_report_pcic_status(); +#endif + show_registers(regs); + panic("BusError!"); +} +static void __init tx4939_be_init(void) +{ + board_be_handler = tx4939_be_handler; +} + +static struct resource tx4939_sdram_resource[4]; +static struct resource tx4939_sram_resource; +#define TX4939_SRAM_SIZE 0x800 + +void __init tx4939_add_memory_regions(void) +{ + int i; + unsigned long start, size; + u64 win; + + for (i = 0; i < 4; i++) { + if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) + continue; + win = ____raw_readq(&tx4939_ddrcptr->win[i]); + start = (unsigned long)(win >> 48); + size = (((unsigned long)(win >> 32) & 0xffff) + 1) - start; + add_memory_region(start << 20, size << 20, BOOT_MEM_RAM); + } +} + +void __init tx4939_setup(void) +{ + int i; + __u32 divmode; + __u64 pcfg; + int cpuclk = 0; + + txx9_reg_res_init(TX4939_REV_PCODE(), TX4939_REG_BASE, + TX4939_REG_SIZE); + set_c0_config(TX49_CONF_CWFON); + + /* SDRAMC,EBUSC are configured by PROM */ + for (i = 0; i < 4; i++) { + if (!(TX4939_EBUSC_CR(i) & 0x8)) + continue; /* disabled */ + txx9_ce_res[i].start = (unsigned long)TX4939_EBUSC_BA(i); + txx9_ce_res[i].end = + txx9_ce_res[i].start + TX4939_EBUSC_SIZE(i) - 1; + request_resource(&iomem_resource, &txx9_ce_res[i]); + } + + /* clocks */ + if (txx9_master_clock) { + /* calculate cpu_clock from master_clock */ + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_MULCLK_MASK; + cpuclk = txx9_master_clock * 20 / 2; + switch (divmode) { + case TX4939_CCFG_MULCLK_8: + cpuclk = cpuclk / 3 * 4 /* / 6 * 8 */; break; + case TX4939_CCFG_MULCLK_9: + cpuclk = cpuclk / 2 * 3 /* / 6 * 9 */; break; + case TX4939_CCFG_MULCLK_10: + cpuclk = cpuclk / 3 * 5 /* / 6 * 10 */; break; + case TX4939_CCFG_MULCLK_11: + cpuclk = cpuclk / 6 * 11; break; + case TX4939_CCFG_MULCLK_12: + cpuclk = cpuclk * 2 /* / 6 * 12 */; break; + case TX4939_CCFG_MULCLK_13: + cpuclk = cpuclk / 6 * 13; break; + case TX4939_CCFG_MULCLK_14: + cpuclk = cpuclk / 3 * 7 /* / 6 * 14 */; break; + case TX4939_CCFG_MULCLK_15: + cpuclk = cpuclk / 2 * 5 /* / 6 * 15 */; break; + } + txx9_cpu_clock = cpuclk; + } else { + if (txx9_cpu_clock == 0) + txx9_cpu_clock = 400000000; /* 400MHz */ + /* calculate master_clock from cpu_clock */ + cpuclk = txx9_cpu_clock; + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_MULCLK_MASK; + switch (divmode) { + case TX4939_CCFG_MULCLK_8: + txx9_master_clock = cpuclk * 6 / 8; break; + case TX4939_CCFG_MULCLK_9: + txx9_master_clock = cpuclk * 6 / 9; break; + case TX4939_CCFG_MULCLK_10: + txx9_master_clock = cpuclk * 6 / 10; break; + case TX4939_CCFG_MULCLK_11: + txx9_master_clock = cpuclk * 6 / 11; break; + case TX4939_CCFG_MULCLK_12: + txx9_master_clock = cpuclk * 6 / 12; break; + case TX4939_CCFG_MULCLK_13: + txx9_master_clock = cpuclk * 6 / 13; break; + case TX4939_CCFG_MULCLK_14: + txx9_master_clock = cpuclk * 6 / 14; break; + case TX4939_CCFG_MULCLK_15: + txx9_master_clock = cpuclk * 6 / 15; break; + } + txx9_master_clock /= 10; /* * 2 / 20 */ + } + /* calculate gbus_clock from cpu_clock */ + divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & + TX4939_CCFG_YDIVMODE_MASK; + txx9_gbus_clock = txx9_cpu_clock; + switch (divmode) { + case TX4939_CCFG_YDIVMODE_2: + txx9_gbus_clock /= 2; break; + case TX4939_CCFG_YDIVMODE_3: + txx9_gbus_clock /= 3; break; + case TX4939_CCFG_YDIVMODE_5: + txx9_gbus_clock /= 5; break; + case TX4939_CCFG_YDIVMODE_6: + txx9_gbus_clock /= 6; break; + } + /* change default value to udelay/mdelay take reasonable time */ + loops_per_jiffy = txx9_cpu_clock / HZ / 2; + + /* CCFG */ + tx4939_wdr_init(); + /* clear BusErrorOnWrite flag (W1C) */ + tx4939_ccfg_set(TX4939_CCFG_WDRST | TX4939_CCFG_BEOW); + /* enable Timeout BusError */ + if (txx9_ccfg_toeon) + tx4939_ccfg_set(TX4939_CCFG_TOE); + + /* DMA selection */ + txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_DMASEL_ALL); + + /* Use external clock for external arbiter */ + if (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB)) + txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_PCICLKEN_ALL); + + pr_info("%s -- %dMHz(M%dMHz,G%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n", + txx9_pcode_str, + (cpuclk + 500000) / 1000000, + (txx9_master_clock + 500000) / 1000000, + (txx9_gbus_clock + 500000) / 1000000, + (__u32)____raw_readq(&tx4939_ccfgptr->crir), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg), + (unsigned long long)____raw_readq(&tx4939_ccfgptr->pcfg)); + + pr_info("%s DDRC -- EN:%08x", txx9_pcode_str, + (__u32)____raw_readq(&tx4939_ddrcptr->winen)); + for (i = 0; i < 4; i++) { + __u64 win = ____raw_readq(&tx4939_ddrcptr->win[i]); + if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) + continue; /* disabled */ + printk(KERN_CONT " #%d:%016llx", i, (unsigned long long)win); + tx4939_sdram_resource[i].name = "DDR SDRAM"; + tx4939_sdram_resource[i].start = + (unsigned long)(win >> 48) << 20; + tx4939_sdram_resource[i].end = + ((((unsigned long)(win >> 32) & 0xffff) + 1) << + 20) - 1; + tx4939_sdram_resource[i].flags = IORESOURCE_MEM; + request_resource(&iomem_resource, &tx4939_sdram_resource[i]); + } + printk(KERN_CONT "\n"); + + /* SRAM */ + if (____raw_readq(&tx4939_sramcptr->cr) & 1) { + unsigned int size = TX4939_SRAM_SIZE; + tx4939_sram_resource.name = "SRAM"; + tx4939_sram_resource.start = + (____raw_readq(&tx4939_sramcptr->cr) >> (39-11)) + & ~(size - 1); + tx4939_sram_resource.end = + tx4939_sram_resource.start + TX4939_SRAM_SIZE - 1; + tx4939_sram_resource.flags = IORESOURCE_MEM; + request_resource(&iomem_resource, &tx4939_sram_resource); + } + + /* TMR */ + /* disable all timers */ + for (i = 0; i < TX4939_NR_TMR; i++) + txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL); + + /* DMA */ + for (i = 0; i < 2; i++) + ____raw_writeq(TX4938_DMA_MCR_MSTEN, + (void __iomem *)(TX4939_DMA_REG(i) + 0x50)); + + /* set PCIC1 reset (required to prevent hangup on BIST) */ + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); + pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + if (pcfg & (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE)) { + mdelay(1); /* at least 128 cpu clock */ + /* clear PCIC1 reset */ + txx9_clear64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); + } else { + pr_info("%s: stop PCIC1\n", txx9_pcode_str); + /* stop PCIC1 */ + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1CKD); + } + if (!(pcfg & TX4939_PCFG_ET0MODE)) { + pr_info("%s: stop ETH0\n", txx9_pcode_str); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0RST); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0CKD); + } + if (!(pcfg & TX4939_PCFG_ET1MODE)) { + pr_info("%s: stop ETH1\n", txx9_pcode_str); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1RST); + txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1CKD); + } + + _machine_restart = tx4939_machine_restart; + board_be_init = tx4939_be_init; +} + +void __init tx4939_time_init(unsigned int tmrnr) +{ + if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_TINTDIS) + txx9_clockevent_init(TX4939_TMR_REG(tmrnr) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4939_IR_TMR(tmrnr), + TXX9_IMCLK); +} + +void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) +{ + int i; + unsigned int ch_mask = 0; + __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + cts_mask |= ~1; /* only SIO0 have RTS/CTS */ + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO0) + cts_mask |= 1 << 0; /* disable SIO0 RTS/CTS by PCFG setting */ + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) + ch_mask |= 1 << 2; /* disable SIO2 by PCFG setting */ + if (pcfg & TX4939_PCFG_SIO3MODE) + ch_mask |= 1 << 3; /* disable SIO3 by PCFG setting */ + for (i = 0; i < 4; i++) { + if ((1 << i) & ch_mask) + continue; + txx9_sio_init(TX4939_SIO_REG(i) & 0xfffffffffULL, + TXX9_IRQ_BASE + TX4939_IR_SIO(i), + i, sclk, (1 << i) & cts_mask); + } +} + +#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) +static int tx4939_get_eth_speed(struct net_device *dev) +{ + struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int speed = 100; /* default 100Mbps */ + int err; + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return speed; + err = dev->ethtool_ops->get_settings(dev, &cmd); + if (err < 0) + return speed; + speed = cmd.speed == SPEED_100 ? 100 : 10; + return speed; +} +static int tx4939_netdev_event(struct notifier_block *this, + unsigned long event, + void *ptr) +{ + struct net_device *dev = ptr; + if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) { + __u64 bit = 0; + if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0)) + bit = TX4939_PCFG_SPEED0; + else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1)) + bit = TX4939_PCFG_SPEED1; + if (bit) { + int speed = tx4939_get_eth_speed(dev); + if (speed == 100) + txx9_set64(&tx4939_ccfgptr->pcfg, bit); + else + txx9_clear64(&tx4939_ccfgptr->pcfg, bit); + } + } + return NOTIFY_DONE; +} + +static struct notifier_block tx4939_netdev_notifier = { + .notifier_call = tx4939_netdev_event, + .priority = 1, +}; + +void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) +{ + u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + if (addr0 && (pcfg & TX4939_PCFG_ET0MODE)) + txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(0), addr0); + if (addr1 && (pcfg & TX4939_PCFG_ET1MODE)) + txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(1), addr1); + register_netdevice_notifier(&tx4939_netdev_notifier); +} +#else +void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) +{ +} +#endif + +void __init tx4939_mtd_init(int ch) +{ + struct physmap_flash_data pdata = { + .width = TX4939_EBUSC_WIDTH(ch) / 8, + }; + unsigned long start = txx9_ce_res[ch].start; + unsigned long size = txx9_ce_res[ch].end - start + 1; + + if (!(TX4939_EBUSC_CR(ch) & 0x8)) + return; /* disabled */ + txx9_physmap_flash_init(ch, start, size, &pdata); +} + +static void __init tx4939_stop_unused_modules(void) +{ + __u64 pcfg, rst = 0, ckd = 0; + char buf[128]; + + buf[0] = '\0'; + local_irq_disable(); + pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_ACLC) { + rst |= TX4939_CLKCTR_ACLRST; + ckd |= TX4939_CLKCTR_ACLCKD; + strcat(buf, " ACLC"); + } + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_I2S && + (pcfg & TX4939_PCFG_I2SMODE_MASK) != + TX4939_PCFG_I2SMODE_I2S_ALT) { + rst |= TX4939_CLKCTR_I2SRST; + ckd |= TX4939_CLKCTR_I2SCKD; + strcat(buf, " I2S"); + } + if (!(pcfg & TX4939_PCFG_ATA0MODE)) { + rst |= TX4939_CLKCTR_ATA0RST; + ckd |= TX4939_CLKCTR_ATA0CKD; + strcat(buf, " ATA0"); + } + if (!(pcfg & TX4939_PCFG_ATA1MODE)) { + rst |= TX4939_CLKCTR_ATA1RST; + ckd |= TX4939_CLKCTR_ATA1CKD; + strcat(buf, " ATA1"); + } + if (pcfg & TX4939_PCFG_SPIMODE) { + rst |= TX4939_CLKCTR_SPIRST; + ckd |= TX4939_CLKCTR_SPICKD; + strcat(buf, " SPI"); + } + if (!(pcfg & (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE))) { + rst |= TX4939_CLKCTR_VPCRST; + ckd |= TX4939_CLKCTR_VPCCKD; + strcat(buf, " VPC"); + } + if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) { + rst |= TX4939_CLKCTR_SIO2RST; + ckd |= TX4939_CLKCTR_SIO2CKD; + strcat(buf, " SIO2"); + } + if (pcfg & TX4939_PCFG_SIO3MODE) { + rst |= TX4939_CLKCTR_SIO3RST; + ckd |= TX4939_CLKCTR_SIO3CKD; + strcat(buf, " SIO3"); + } + if (rst | ckd) { + txx9_set64(&tx4939_ccfgptr->clkctr, rst); + txx9_set64(&tx4939_ccfgptr->clkctr, ckd); + } + local_irq_enable(); + if (buf[0]) + pr_info("%s: stop%s\n", txx9_pcode_str, buf); +} + +static int __init tx4939_late_init(void) +{ + if (txx9_pcode != 0x4939) + return -ENODEV; + tx4939_stop_unused_modules(); + return 0; +} +late_initcall(tx4939_late_init); diff --git a/include/asm-mips/txx9/tx4939.h b/include/asm-mips/txx9/tx4939.h new file mode 100644 index 00000000000..7ce2dff3b7c --- /dev/null +++ b/include/asm-mips/txx9/tx4939.h @@ -0,0 +1,544 @@ +/* + * Definitions for TX4939 + * + * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_TXX9_TX4939_H +#define __ASM_TXX9_TX4939_H + +/* some controllers are compatible with 4927/4938 */ +#include + +#ifdef CONFIG_64BIT +#define TX4939_REG_BASE 0xffffffffff1f0000UL /* == TX4938_REG_BASE */ +#else +#define TX4939_REG_BASE 0xff1f0000UL /* == TX4938_REG_BASE */ +#endif +#define TX4939_REG_SIZE 0x00010000 /* == TX4938_REG_SIZE */ + +#define TX4939_ATA_REG(ch) (TX4939_REG_BASE + 0x3000 + (ch) * 0x1000) +#define TX4939_NDFMC_REG (TX4939_REG_BASE + 0x5000) +#define TX4939_SRAMC_REG (TX4939_REG_BASE + 0x6000) +#define TX4939_CRYPTO_REG (TX4939_REG_BASE + 0x6800) +#define TX4939_PCIC1_REG (TX4939_REG_BASE + 0x7000) +#define TX4939_DDRC_REG (TX4939_REG_BASE + 0x8000) +#define TX4939_EBUSC_REG (TX4939_REG_BASE + 0x9000) +#define TX4939_VPC_REG (TX4939_REG_BASE + 0xa000) +#define TX4939_DMA_REG(ch) (TX4939_REG_BASE + 0xb000 + (ch) * 0x800) +#define TX4939_PCIC_REG (TX4939_REG_BASE + 0xd000) +#define TX4939_CCFG_REG (TX4939_REG_BASE + 0xe000) +#define TX4939_IRC_REG (TX4939_REG_BASE + 0xe800) +#define TX4939_NR_TMR 6 /* 0xf000,0xf100,0xf200,0xfd00,0xfe00,0xff00 */ +#define TX4939_TMR_REG(ch) \ + (TX4939_REG_BASE + 0xf000 + ((ch) + ((ch) >= 3) * 10) * 0x100) +#define TX4939_NR_SIO 4 /* 0xf300, 0xf400, 0xf380, 0xf480 */ +#define TX4939_SIO_REG(ch) \ + (TX4939_REG_BASE + 0xf300 + (((ch) & 1) << 8) + (((ch) & 2) << 6)) +#define TX4939_ACLC_REG (TX4939_REG_BASE + 0xf700) +#define TX4939_SPI_REG (TX4939_REG_BASE + 0xf800) +#define TX4939_I2C_REG (TX4939_REG_BASE + 0xf900) +#define TX4939_I2S_REG (TX4939_REG_BASE + 0xfa00) +#define TX4939_RTC_REG (TX4939_REG_BASE + 0xfb00) +#define TX4939_CIR_REG (TX4939_REG_BASE + 0xfc00) + +struct tx4939_le_reg { + __u32 r; + __u32 unused; +}; + +struct tx4939_ddrc_reg { + struct tx4939_le_reg ctl[47]; + __u64 unused0[17]; + __u64 winen; + __u64 win[4]; +}; + +struct tx4939_ccfg_reg { + __u64 ccfg; + __u64 crir; + __u64 pcfg; + __u64 toea; + __u64 clkctr; + __u64 unused0; + __u64 garbc; + __u64 unused1[2]; + __u64 ramp; + __u64 unused2[2]; + __u64 dskwctrl; + __u64 mclkosc; + __u64 mclkctl; + __u64 unused3[17]; + struct { + __u64 mr; + __u64 dr; + } gpio[2]; +}; + +struct tx4939_irc_reg { + struct tx4939_le_reg den; + struct tx4939_le_reg scipb; + struct tx4939_le_reg dm[2]; + struct tx4939_le_reg lvl[16]; + struct tx4939_le_reg msk; + struct tx4939_le_reg edc; + struct tx4939_le_reg pnd0; + struct tx4939_le_reg cs; + struct tx4939_le_reg pnd1; + struct tx4939_le_reg dm2[2]; + struct tx4939_le_reg dbr[2]; + struct tx4939_le_reg dben; + struct tx4939_le_reg unused0[2]; + struct tx4939_le_reg flag[2]; + struct tx4939_le_reg pol; + struct tx4939_le_reg cnt; + struct tx4939_le_reg maskint; + struct tx4939_le_reg maskext; +}; + +struct tx4939_rtc_reg { + __u32 ctl; + __u32 adr; + __u32 dat; + __u32 tbc; +}; + +struct tx4939_crypto_reg { + struct tx4939_le_reg csr; + struct tx4939_le_reg idesptr; + struct tx4939_le_reg cdesptr; + struct tx4939_le_reg buserr; + struct tx4939_le_reg cip_tout; + struct tx4939_le_reg cir; + union { + struct { + struct tx4939_le_reg data[8]; + struct tx4939_le_reg ctrl; + } gen; + struct { + struct { + struct tx4939_le_reg l; + struct tx4939_le_reg u; + } key[3], ini; + struct tx4939_le_reg ctrl; + } des; + struct { + struct tx4939_le_reg key[4]; + struct tx4939_le_reg ini[4]; + struct tx4939_le_reg ctrl; + } aes; + struct { + struct { + struct tx4939_le_reg l; + struct tx4939_le_reg u; + } cnt; + struct tx4939_le_reg ini[5]; + struct tx4939_le_reg unused; + struct tx4939_le_reg ctrl; + } hash; + } cdr; + struct tx4939_le_reg unused0[7]; + struct tx4939_le_reg rcsr; + struct tx4939_le_reg rpr; + __u64 rdr; + __u64 ror[3]; + struct tx4939_le_reg unused1[2]; + struct tx4939_le_reg xorslr; + struct tx4939_le_reg xorsur; +}; + +struct tx4939_crypto_desc { + __u32 src; + __u32 dst; + __u32 next; + __u32 ctrl; + __u32 index; + __u32 xor; +}; + +struct tx4939_vpc_reg { + struct tx4939_le_reg csr; + struct { + struct tx4939_le_reg ctrlA; + struct tx4939_le_reg ctrlB; + struct tx4939_le_reg idesptr; + struct tx4939_le_reg cdesptr; + } port[3]; + struct tx4939_le_reg buserr; +}; + +struct tx4939_vpc_desc { + __u32 src; + __u32 next; + __u32 ctrl1; + __u32 ctrl2; +}; + +/* + * IRC + */ +#define TX4939_IR_NONE 0 +#define TX4939_IR_DDR 1 +#define TX4939_IR_WTOERR 2 +#define TX4939_NUM_IR_INT 3 +#define TX4939_IR_INT(n) (3 + (n)) +#define TX4939_NUM_IR_ETH 2 +#define TX4939_IR_ETH(n) ((n) ? 43 : 6) +#define TX4939_IR_VIDEO 7 +#define TX4939_IR_CIR 8 +#define TX4939_NUM_IR_SIO 4 +#define TX4939_IR_SIO(n) ((n) ? 43 + (n) : 9) /* 9,44-46 */ +#define TX4939_NUM_IR_DMA 4 +#define TX4939_IR_DMA(ch, n) (((ch) ? 22 : 10) + (n)) /* 10-13,22-25 */ +#define TX4939_IR_IRC 14 +#define TX4939_IR_PDMAC 15 +#define TX4939_NUM_IR_TMR 6 +#define TX4939_IR_TMR(n) (((n) >= 3 ? 45 : 16) + (n)) /* 16-18,48-50 */ +#define TX4939_NUM_IR_ATA 2 +#define TX4939_IR_ATA(n) (19 + (n)) +#define TX4939_IR_ACLC 21 +#define TX4939_IR_CIPHER 26 +#define TX4939_IR_INTA 27 +#define TX4939_IR_INTB 28 +#define TX4939_IR_INTC 29 +#define TX4939_IR_INTD 30 +#define TX4939_IR_I2C 33 +#define TX4939_IR_SPI 34 +#define TX4939_IR_PCIC 35 +#define TX4939_IR_PCIC1 36 +#define TX4939_IR_PCIERR 37 +#define TX4939_IR_PCIPME 38 +#define TX4939_IR_NDFMC 39 +#define TX4939_IR_ACLCPME 40 +#define TX4939_IR_RTC 41 +#define TX4939_IR_RND 42 +#define TX4939_IR_I2S 47 +#define TX4939_NUM_IR 64 + +#define TX4939_IRC_INT 2 /* IP[2] in Status register */ + +/* + * CCFG + */ +/* CCFG : Chip Configuration */ +#define TX4939_CCFG_PCIBOOT 0x0000040000000000ULL +#define TX4939_CCFG_WDRST 0x0000020000000000ULL +#define TX4939_CCFG_WDREXEN 0x0000010000000000ULL +#define TX4939_CCFG_BCFG_MASK 0x000000ff00000000ULL +#define TX4939_CCFG_GTOT_MASK 0x06000000 +#define TX4939_CCFG_GTOT_4096 0x06000000 +#define TX4939_CCFG_GTOT_2048 0x04000000 +#define TX4939_CCFG_GTOT_1024 0x02000000 +#define TX4939_CCFG_GTOT_512 0x00000000 +#define TX4939_CCFG_TINTDIS 0x01000000 +#define TX4939_CCFG_PCI66 0x00800000 +#define TX4939_CCFG_PCIMODE 0x00400000 +#define TX4939_CCFG_SSCG 0x00100000 +#define TX4939_CCFG_MULCLK_MASK 0x000e0000 +#define TX4939_CCFG_MULCLK_8 (0x7 << 17) +#define TX4939_CCFG_MULCLK_9 (0x0 << 17) +#define TX4939_CCFG_MULCLK_10 (0x1 << 17) +#define TX4939_CCFG_MULCLK_11 (0x2 << 17) +#define TX4939_CCFG_MULCLK_12 (0x3 << 17) +#define TX4939_CCFG_MULCLK_13 (0x4 << 17) +#define TX4939_CCFG_MULCLK_14 (0x5 << 17) +#define TX4939_CCFG_MULCLK_15 (0x6 << 17) +#define TX4939_CCFG_BEOW 0x00010000 +#define TX4939_CCFG_WR 0x00008000 +#define TX4939_CCFG_TOE 0x00004000 +#define TX4939_CCFG_PCIARB 0x00002000 +#define TX4939_CCFG_YDIVMODE_MASK 0x00001c00 +#define TX4939_CCFG_YDIVMODE_2 (0x0 << 10) +#define TX4939_CCFG_YDIVMODE_3 (0x1 << 10) +#define TX4939_CCFG_YDIVMODE_5 (0x6 << 10) +#define TX4939_CCFG_YDIVMODE_6 (0x7 << 10) +#define TX4939_CCFG_PTSEL 0x00000200 +#define TX4939_CCFG_BESEL 0x00000100 +#define TX4939_CCFG_SYSSP_MASK 0x000000c0 +#define TX4939_CCFG_ACKSEL 0x00000020 +#define TX4939_CCFG_ROMW 0x00000010 +#define TX4939_CCFG_ENDIAN 0x00000004 +#define TX4939_CCFG_ARMODE 0x00000002 +#define TX4939_CCFG_ACEHOLD 0x00000001 + +/* PCFG : Pin Configuration */ +#define TX4939_PCFG_SIO2MODE_MASK 0xc000000000000000ULL +#define TX4939_PCFG_SIO2MODE_GPIO 0x8000000000000000ULL +#define TX4939_PCFG_SIO2MODE_SIO2 0x4000000000000000ULL +#define TX4939_PCFG_SIO2MODE_SIO0 0x0000000000000000ULL +#define TX4939_PCFG_SPIMODE 0x2000000000000000ULL +#define TX4939_PCFG_I2CMODE 0x1000000000000000ULL +#define TX4939_PCFG_I2SMODE_MASK 0x0c00000000000000ULL +#define TX4939_PCFG_I2SMODE_GPIO 0x0c00000000000000ULL +#define TX4939_PCFG_I2SMODE_I2S 0x0800000000000000ULL +#define TX4939_PCFG_I2SMODE_I2S_ALT 0x0400000000000000ULL +#define TX4939_PCFG_I2SMODE_ACLC 0x0000000000000000ULL +#define TX4939_PCFG_SIO3MODE 0x0200000000000000ULL +#define TX4939_PCFG_DMASEL3 0x0004000000000000ULL +#define TX4939_PCFG_DMASEL3_SIO0 0x0004000000000000ULL +#define TX4939_PCFG_DMASEL3_NDFC 0x0000000000000000ULL +#define TX4939_PCFG_VSSMODE 0x0000200000000000ULL +#define TX4939_PCFG_VPSMODE 0x0000100000000000ULL +#define TX4939_PCFG_ET1MODE 0x0000080000000000ULL +#define TX4939_PCFG_ET0MODE 0x0000040000000000ULL +#define TX4939_PCFG_ATA1MODE 0x0000020000000000ULL +#define TX4939_PCFG_ATA0MODE 0x0000010000000000ULL +#define TX4939_PCFG_BP_PLL 0x0000000100000000ULL + +#define TX4939_PCFG_SYSCLKEN 0x08000000 +#define TX4939_PCFG_PCICLKEN_ALL 0x000f0000 +#define TX4939_PCFG_PCICLKEN(ch) (0x00010000<<(ch)) +#define TX4939_PCFG_SPEED1 0x00002000 +#define TX4939_PCFG_SPEED0 0x00001000 +#define TX4939_PCFG_ITMODE 0x00000300 +#define TX4939_PCFG_DMASEL_ALL (0x00000007 | TX4939_PCFG_DMASEL3) +#define TX4939_PCFG_DMASEL2 0x00000004 +#define TX4939_PCFG_DMASEL2_DRQ2 0x00000000 +#define TX4939_PCFG_DMASEL2_SIO0 0x00000004 +#define TX4939_PCFG_DMASEL1 0x00000002 +#define TX4939_PCFG_DMASEL1_DRQ1 0x00000000 +#define TX4939_PCFG_DMASEL0 0x00000001 +#define TX4939_PCFG_DMASEL0_DRQ0 0x00000000 + +/* CLKCTR : Clock Control */ +#define TX4939_CLKCTR_IOSCKD 0x8000000000000000ULL +#define TX4939_CLKCTR_SYSCKD 0x4000000000000000ULL +#define TX4939_CLKCTR_TM5CKD 0x2000000000000000ULL +#define TX4939_CLKCTR_TM4CKD 0x1000000000000000ULL +#define TX4939_CLKCTR_TM3CKD 0x0800000000000000ULL +#define TX4939_CLKCTR_CIRCKD 0x0400000000000000ULL +#define TX4939_CLKCTR_SIO3CKD 0x0200000000000000ULL +#define TX4939_CLKCTR_SIO2CKD 0x0100000000000000ULL +#define TX4939_CLKCTR_SIO1CKD 0x0080000000000000ULL +#define TX4939_CLKCTR_VPCCKD 0x0040000000000000ULL +#define TX4939_CLKCTR_EPCICKD 0x0020000000000000ULL +#define TX4939_CLKCTR_ETH1CKD 0x0008000000000000ULL +#define TX4939_CLKCTR_ATA1CKD 0x0004000000000000ULL +#define TX4939_CLKCTR_BROMCKD 0x0002000000000000ULL +#define TX4939_CLKCTR_NDCCKD 0x0001000000000000ULL +#define TX4939_CLKCTR_I2CCKD 0x0000800000000000ULL +#define TX4939_CLKCTR_ETH0CKD 0x0000400000000000ULL +#define TX4939_CLKCTR_SPICKD 0x0000200000000000ULL +#define TX4939_CLKCTR_SRAMCKD 0x0000100000000000ULL +#define TX4939_CLKCTR_PCI1CKD 0x0000080000000000ULL +#define TX4939_CLKCTR_DMA1CKD 0x0000040000000000ULL +#define TX4939_CLKCTR_ACLCKD 0x0000020000000000ULL +#define TX4939_CLKCTR_ATA0CKD 0x0000010000000000ULL +#define TX4939_CLKCTR_DMA0CKD 0x0000008000000000ULL +#define TX4939_CLKCTR_PCICCKD 0x0000004000000000ULL +#define TX4939_CLKCTR_I2SCKD 0x0000002000000000ULL +#define TX4939_CLKCTR_TM0CKD 0x0000001000000000ULL +#define TX4939_CLKCTR_TM1CKD 0x0000000800000000ULL +#define TX4939_CLKCTR_TM2CKD 0x0000000400000000ULL +#define TX4939_CLKCTR_SIO0CKD 0x0000000200000000ULL +#define TX4939_CLKCTR_CYPCKD 0x0000000100000000ULL +#define TX4939_CLKCTR_IOSRST 0x80000000 +#define TX4939_CLKCTR_SYSRST 0x40000000 +#define TX4939_CLKCTR_TM5RST 0x20000000 +#define TX4939_CLKCTR_TM4RST 0x10000000 +#define TX4939_CLKCTR_TM3RST 0x08000000 +#define TX4939_CLKCTR_CIRRST 0x04000000 +#define TX4939_CLKCTR_SIO3RST 0x02000000 +#define TX4939_CLKCTR_SIO2RST 0x01000000 +#define TX4939_CLKCTR_SIO1RST 0x00800000 +#define TX4939_CLKCTR_VPCRST 0x00400000 +#define TX4939_CLKCTR_EPCIRST 0x00200000 +#define TX4939_CLKCTR_ETH1RST 0x00080000 +#define TX4939_CLKCTR_ATA1RST 0x00040000 +#define TX4939_CLKCTR_BROMRST 0x00020000 +#define TX4939_CLKCTR_NDCRST 0x00010000 +#define TX4939_CLKCTR_I2CRST 0x00008000 +#define TX4939_CLKCTR_ETH0RST 0x00004000 +#define TX4939_CLKCTR_SPIRST 0x00002000 +#define TX4939_CLKCTR_SRAMRST 0x00001000 +#define TX4939_CLKCTR_PCI1RST 0x00000800 +#define TX4939_CLKCTR_DMA1RST 0x00000400 +#define TX4939_CLKCTR_ACLRST 0x00000200 +#define TX4939_CLKCTR_ATA0RST 0x00000100 +#define TX4939_CLKCTR_DMA0RST 0x00000080 +#define TX4939_CLKCTR_PCICRST 0x00000040 +#define TX4939_CLKCTR_I2SRST 0x00000020 +#define TX4939_CLKCTR_TM0RST 0x00000010 +#define TX4939_CLKCTR_TM1RST 0x00000008 +#define TX4939_CLKCTR_TM2RST 0x00000004 +#define TX4939_CLKCTR_SIO0RST 0x00000002 +#define TX4939_CLKCTR_CYPRST 0x00000001 + +/* + * RTC + */ +#define TX4939_RTCCTL_ALME 0x00000080 +#define TX4939_RTCCTL_ALMD 0x00000040 +#define TX4939_RTCCTL_BUSY 0x00000020 + +#define TX4939_RTCCTL_COMMAND 0x00000007 +#define TX4939_RTCCTL_COMMAND_NOP 0x00000000 +#define TX4939_RTCCTL_COMMAND_GETTIME 0x00000001 +#define TX4939_RTCCTL_COMMAND_SETTIME 0x00000002 +#define TX4939_RTCCTL_COMMAND_GETALARM 0x00000003 +#define TX4939_RTCCTL_COMMAND_SETALARM 0x00000004 + +#define TX4939_RTCTBC_PM 0x00000080 +#define TX4939_RTCTBC_COMP 0x0000007f + +#define TX4939_RTC_REG_RAMSIZE 0x00000100 +#define TX4939_RTC_REG_RWBSIZE 0x00000006 + +/* + * CRYPTO + */ +#define TX4939_CRYPTO_CSR_SAESO 0x08000000 +#define TX4939_CRYPTO_CSR_SAESI 0x04000000 +#define TX4939_CRYPTO_CSR_SDESO 0x02000000 +#define TX4939_CRYPTO_CSR_SDESI 0x01000000 +#define TX4939_CRYPTO_CSR_INDXBST_MASK 0x00700000 +#define TX4939_CRYPTO_CSR_INDXBST(n) ((n) << 20) +#define TX4939_CRYPTO_CSR_TOINT 0x00080000 +#define TX4939_CRYPTO_CSR_DCINT 0x00040000 +#define TX4939_CRYPTO_CSR_GBINT 0x00010000 +#define TX4939_CRYPTO_CSR_INDXAST_MASK 0x0000e000 +#define TX4939_CRYPTO_CSR_INDXAST(n) ((n) << 13) +#define TX4939_CRYPTO_CSR_CSWAP_MASK 0x00001800 +#define TX4939_CRYPTO_CSR_CSWAP_NONE 0x00000000 +#define TX4939_CRYPTO_CSR_CSWAP_IN 0x00000800 +#define TX4939_CRYPTO_CSR_CSWAP_OUT 0x00001000 +#define TX4939_CRYPTO_CSR_CSWAP_BOTH 0x00001800 +#define TX4939_CRYPTO_CSR_CDIV_MASK 0x00000600 +#define TX4939_CRYPTO_CSR_CDIV_DIV2 0x00000000 +#define TX4939_CRYPTO_CSR_CDIV_DIV1 0x00000200 +#define TX4939_CRYPTO_CSR_CDIV_DIV2ALT 0x00000400 +#define TX4939_CRYPTO_CSR_CDIV_DIV1ALT 0x00000600 +#define TX4939_CRYPTO_CSR_PDINT_MASK 0x000000c0 +#define TX4939_CRYPTO_CSR_PDINT_ALL 0x00000000 +#define TX4939_CRYPTO_CSR_PDINT_END 0x00000040 +#define TX4939_CRYPTO_CSR_PDINT_NEXT 0x00000080 +#define TX4939_CRYPTO_CSR_PDINT_NONE 0x000000c0 +#define TX4939_CRYPTO_CSR_GINTE 0x00000008 +#define TX4939_CRYPTO_CSR_RSTD 0x00000004 +#define TX4939_CRYPTO_CSR_RSTC 0x00000002 +#define TX4939_CRYPTO_CSR_ENCR 0x00000001 + +/* bits for tx4939_crypto_reg.cdr.gen.ctrl */ +#define TX4939_CRYPTO_CTX_ENGINE_MASK 0x00000003 +#define TX4939_CRYPTO_CTX_ENGINE_DES 0x00000000 +#define TX4939_CRYPTO_CTX_ENGINE_AES 0x00000001 +#define TX4939_CRYPTO_CTX_ENGINE_MD5 0x00000002 +#define TX4939_CRYPTO_CTX_ENGINE_SHA1 0x00000003 +#define TX4939_CRYPTO_CTX_TDMS 0x00000010 +#define TX4939_CRYPTO_CTX_CMS 0x00000020 +#define TX4939_CRYPTO_CTX_DMS 0x00000040 +#define TX4939_CRYPTO_CTX_UPDATE 0x00000080 + +/* bits for tx4939_crypto_desc.ctrl */ +#define TX4939_CRYPTO_DESC_OB_CNT_MASK 0xffe00000 +#define TX4939_CRYPTO_DESC_OB_CNT(cnt) ((cnt) << 21) +#define TX4939_CRYPTO_DESC_IB_CNT_MASK 0x001ffc00 +#define TX4939_CRYPTO_DESC_IB_CNT(cnt) ((cnt) << 10) +#define TX4939_CRYPTO_DESC_START 0x00000200 +#define TX4939_CRYPTO_DESC_END 0x00000100 +#define TX4939_CRYPTO_DESC_XOR 0x00000010 +#define TX4939_CRYPTO_DESC_LAST 0x00000008 +#define TX4939_CRYPTO_DESC_ERR_MASK 0x00000006 +#define TX4939_CRYPTO_DESC_ERR_NONE 0x00000000 +#define TX4939_CRYPTO_DESC_ERR_TOUT 0x00000002 +#define TX4939_CRYPTO_DESC_ERR_DIGEST 0x00000004 +#define TX4939_CRYPTO_DESC_OWN 0x00000001 + +/* bits for tx4939_crypto_desc.index */ +#define TX4939_CRYPTO_DESC_HASH_IDX_MASK 0x00000070 +#define TX4939_CRYPTO_DESC_HASH_IDX(idx) ((idx) << 4) +#define TX4939_CRYPTO_DESC_ENCRYPT_IDX_MASK 0x00000007 +#define TX4939_CRYPTO_DESC_ENCRYPT_IDX(idx) ((idx) << 0) + +#define TX4939_CRYPTO_NR_SET 6 + +#define TX4939_CRYPTO_RCSR_INTE 0x00000008 +#define TX4939_CRYPTO_RCSR_RST 0x00000004 +#define TX4939_CRYPTO_RCSR_FIN 0x00000002 +#define TX4939_CRYPTO_RCSR_ST 0x00000001 + +/* + * VPC + */ +#define TX4939_VPC_CSR_GBINT 0x00010000 +#define TX4939_VPC_CSR_SWAPO 0x00000020 +#define TX4939_VPC_CSR_SWAPI 0x00000010 +#define TX4939_VPC_CSR_GINTE 0x00000008 +#define TX4939_VPC_CSR_RSTD 0x00000004 +#define TX4939_VPC_CSR_RSTVPC 0x00000002 + +#define TX4939_VPC_CTRLA_VDPSN 0x00000200 +#define TX4939_VPC_CTRLA_PBUSY 0x00000100 +#define TX4939_VPC_CTRLA_DCINT 0x00000080 +#define TX4939_VPC_CTRLA_UOINT 0x00000040 +#define TX4939_VPC_CTRLA_PDINT_MASK 0x00000030 +#define TX4939_VPC_CTRLA_PDINT_ALL 0x00000000 +#define TX4939_VPC_CTRLA_PDINT_NEXT 0x00000010 +#define TX4939_VPC_CTRLA_PDINT_NONE 0x00000030 +#define TX4939_VPC_CTRLA_VDVLDP 0x00000008 +#define TX4939_VPC_CTRLA_VDMODE 0x00000004 +#define TX4939_VPC_CTRLA_VDFOR 0x00000002 +#define TX4939_VPC_CTRLA_ENVPC 0x00000001 + +/* bits for tx4939_vpc_desc.ctrl1 */ +#define TX4939_VPC_DESC_CTRL1_ERR_MASK 0x00000006 +#define TX4939_VPC_DESC_CTRL1_OWN 0x00000001 + +#define tx4939_ddrcptr ((struct tx4939_ddrc_reg __iomem *)TX4939_DDRC_REG) +#define tx4939_ebuscptr tx4938_ebuscptr +#define tx4939_ircptr \ + ((struct tx4939_irc_reg __iomem *)TX4939_IRC_REG) +#define tx4939_pcicptr tx4938_pcicptr +#define tx4939_pcic1ptr tx4938_pcic1ptr +#define tx4939_ccfgptr \ + ((struct tx4939_ccfg_reg __iomem *)TX4939_CCFG_REG) +#define tx4939_sramcptr tx4938_sramcptr +#define tx4939_rtcptr \ + ((struct tx4939_rtc_reg __iomem *)TX4939_RTC_REG) +#define tx4939_cryptoptr \ + ((struct tx4939_crypto_reg __iomem *)TX4939_CRYPTO_REG) +#define tx4939_vpcptr ((struct tx4939_vpc_reg __iomem *)TX4939_VPC_REG) + +#define TX4939_REV_MAJ_MIN() \ + ((__u32)__raw_readq(&tx4939_ccfgptr->crir) & 0x00ff) +#define TX4939_REV_PCODE() \ + ((__u32)__raw_readq(&tx4939_ccfgptr->crir) >> 16) +#define TX4939_CCFG_BCFG() \ + ((__u32)((__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_BCFG_MASK) \ + >> 32)) + +#define tx4939_ccfg_clear(bits) tx4938_ccfg_clear(bits) +#define tx4939_ccfg_set(bits) tx4938_ccfg_set(bits) +#define tx4939_ccfg_change(change, new) tx4938_ccfg_change(change, new) + +#define TX4939_EBUSC_CR(ch) TX4927_EBUSC_CR(ch) +#define TX4939_EBUSC_BA(ch) TX4927_EBUSC_BA(ch) +#define TX4939_EBUSC_SIZE(ch) TX4927_EBUSC_SIZE(ch) +#define TX4939_EBUSC_WIDTH(ch) \ + (16 >> ((__u32)(TX4939_EBUSC_CR(ch) >> 20) & 0x1)) + +/* SCLK0 = MSTCLK * 429/19 * 16/245 / 2 (14.745MHz for MST 20MHz) */ +#define TX4939_SCLK0(mst) \ + ((((mst) + 245/2) / 245UL * 429 * 16 + 19) / 19 / 2) + +void tx4939_wdt_init(void); +void tx4939_add_memory_regions(void); +void tx4939_setup(void); +void tx4939_time_init(unsigned int tmrnr); +void tx4939_sio_init(unsigned int sclk, unsigned int cts_mask); +void tx4939_spi_init(int busid); +void tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1); +int tx4939_report_pciclk(void); +void tx4939_report_pci1clk(void); +struct pci_dev; +int tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot); +int tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); +void tx4939_setup_pcierr_irq(void); +void tx4939_irq_init(void); +int tx4939_irq(void); +void tx4939_mtd_init(int ch); + +#endif /* __ASM_TXX9_TX4939_H */ -- GitLab From b27311e1cace4e296ace786c886d22f7a8ec78d6 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:40 +0900 Subject: [PATCH 3903/5416] MIPS: TXx9: Add RBTX4939 board support Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle create mode 100644 arch/mips/txx9/rbtx4939/Makefile create mode 100644 arch/mips/txx9/rbtx4939/irq.c create mode 100644 arch/mips/txx9/rbtx4939/prom.c create mode 100644 arch/mips/txx9/rbtx4939/setup.c create mode 100644 include/asm-mips/txx9/rbtx4939.h --- arch/mips/Makefile | 8 +- arch/mips/txx9/Kconfig | 8 + arch/mips/txx9/generic/setup.c | 5 + arch/mips/txx9/rbtx4939/Makefile | 3 + arch/mips/txx9/rbtx4939/irq.c | 96 ++++++++++ arch/mips/txx9/rbtx4939/prom.c | 17 ++ arch/mips/txx9/rbtx4939/setup.c | 306 +++++++++++++++++++++++++++++++ include/asm-mips/txx9/boards.h | 3 + include/asm-mips/txx9/rbtx4939.h | 133 ++++++++++++++ 9 files changed, 573 insertions(+), 6 deletions(-) create mode 100644 arch/mips/txx9/rbtx4939/Makefile create mode 100644 arch/mips/txx9/rbtx4939/irq.c create mode 100644 arch/mips/txx9/rbtx4939/prom.c create mode 100644 arch/mips/txx9/rbtx4939/setup.c create mode 100644 include/asm-mips/txx9/rbtx4939.h diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 9aab51caf16..87f67228e30 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -567,15 +567,11 @@ cflags-$(CONFIG_MIKROTIK_RB532) += -Iinclude/asm-mips/mach-rc32434 load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 # -# Toshiba RBTX4927 board or -# Toshiba RBTX4937 board +# Toshiba RBTX49XX boards # core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ - -# -# Toshiba RBTX4938 board -# core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ +core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ cflags-y += -Iinclude/asm-mips/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 58691a1fe77..17052db4161 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -45,6 +45,14 @@ config TOSHIBA_RBTX4938 This Toshiba board is based on the TX4938 processor. Say Y here to support this machine type +config TOSHIBA_RBTX4939 + bool "Toshiba RBTX4939 bobard" + depends on MACH_TX49XX + select SOC_TX4939 + help + This Toshiba board is based on the TX4939 processor. Say Y here to + support this machine type + config SOC_TX3927 bool select CEVT_TXX9 diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 1ea06553a1e..7a05c34c1de 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -371,6 +371,11 @@ static void __init select_board(void) case 0x4938: txx9_board_vec = &rbtx4938_vec; break; +#endif +#ifdef CONFIG_TOSHIBA_RBTX4939 + case 0x4939: + txx9_board_vec = &rbtx4939_vec; + break; #endif } #endif diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile new file mode 100644 index 00000000000..3232cd03a7d --- /dev/null +++ b/arch/mips/txx9/rbtx4939/Makefile @@ -0,0 +1,3 @@ +obj-y += irq.o setup.o prom.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c new file mode 100644 index 00000000000..500cc0a908e --- /dev/null +++ b/arch/mips/txx9/rbtx4939/irq.c @@ -0,0 +1,96 @@ +/* + * Toshiba RBTX4939 interrupt routines + * Based on linux/arch/mips/txx9/rbtx4938/irq.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include + +/* + * RBTX4939 IOC controller definition + */ + +static void rbtx4939_ioc_irq_unmask(unsigned int irq) +{ + int ioc_nr = irq - RBTX4939_IRQ_IOC; + + writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); +} + +static void rbtx4939_ioc_irq_mask(unsigned int irq) +{ + int ioc_nr = irq - RBTX4939_IRQ_IOC; + + writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); + mmiowb(); +} + +static struct irq_chip rbtx4939_ioc_irq_chip = { + .name = "IOC", + .ack = rbtx4939_ioc_irq_mask, + .mask = rbtx4939_ioc_irq_mask, + .mask_ack = rbtx4939_ioc_irq_mask, + .unmask = rbtx4939_ioc_irq_unmask, +}; + + +static inline int rbtx4939_ioc_irqroute(void) +{ + unsigned char istat = readb(rbtx4939_ifac2_addr); + + if (unlikely(istat == 0)) + return -1; + return RBTX4939_IRQ_IOC + __fls8(istat); +} + +static int rbtx4939_irq_dispatch(int pending) +{ + int irq; + + if (pending & CAUSEF_IP7) + return MIPS_CPU_IRQ_BASE + 7; + irq = tx4939_irq(); + if (likely(irq >= 0)) { + /* redirect IOC interrupts */ + switch (irq) { + case RBTX4939_IRQ_IOCINT: + irq = rbtx4939_ioc_irqroute(); + break; + } + } else if (pending & CAUSEF_IP0) + irq = MIPS_CPU_IRQ_BASE + 0; + else if (pending & CAUSEF_IP1) + irq = MIPS_CPU_IRQ_BASE + 1; + else + irq = -1; + return irq; +} + +void __init rbtx4939_irq_setup(void) +{ + int i; + + /* mask all IOC interrupts */ + writeb(0, rbtx4939_ien_addr); + + /* clear SoftInt interrupts */ + writeb(0, rbtx4939_softint_addr); + + txx9_irq_dispatch = rbtx4939_irq_dispatch; + + tx4939_irq_init(); + for (i = RBTX4939_IRQ_IOC; + i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++) + set_irq_chip_and_handler(i, &rbtx4939_ioc_irq_chip, + handle_level_irq); + + set_irq_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq); +} diff --git a/arch/mips/txx9/rbtx4939/prom.c b/arch/mips/txx9/rbtx4939/prom.c new file mode 100644 index 00000000000..bd277ecb4ad --- /dev/null +++ b/arch/mips/txx9/rbtx4939/prom.c @@ -0,0 +1,17 @@ +/* + * rbtx4939 specific prom routines + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +void __init rbtx4939_prom_init(void) +{ + tx4939_add_memory_regions(); + txx9_sio_putchar_init(TX4939_SIO_REG(0) & 0xfffffffffULL); +} diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c new file mode 100644 index 00000000000..277864d5e77 --- /dev/null +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -0,0 +1,306 @@ +/* + * Toshiba RBTX4939 setup routines. + * Based on linux/arch/mips/txx9/rbtx4938/setup.c, + * and RBTX49xx patch from CELF patch archive. + * + * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rbtx4939_machine_restart(char *command) +{ + local_irq_disable(); + writeb(1, rbtx4939_reseten_addr); + writeb(1, rbtx4939_softreset_addr); + while (1) + ; +} + +static void __init rbtx4939_time_init(void) +{ + tx4939_time_init(0); +} + +static void __init rbtx4939_pci_setup(void) +{ +#ifdef CONFIG_PCI + int extarb = !(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB); + struct pci_controller *c = &txx9_primary_pcic; + + register_pci_controller(c); + + tx4939_report_pciclk(); + tx4927_pcic_setup(tx4939_pcicptr, c, extarb); + if (!(__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_ATA1MODE) && + (__raw_readq(&tx4939_ccfgptr->pcfg) & + (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE))) { + tx4939_report_pci1clk(); + + /* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */ + c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000); + register_pci_controller(c); + tx4927_pcic_setup(tx4939_pcic1ptr, c, 0); + } + + tx4939_setup_pcierr_irq(); +#endif /* CONFIG_PCI */ +} + +static unsigned long long default_ebccr[] __initdata = { + 0x01c0000000007608ULL, /* 64M ROM */ + 0x017f000000007049ULL, /* 1M IOC */ + 0x0180000000408608ULL, /* ISA */ + 0, +}; + +static void __init rbtx4939_ebusc_setup(void) +{ + int i; + unsigned int sp; + + /* use user-configured speed */ + sp = TX4939_EBUSC_CR(0) & 0x30; + default_ebccr[0] |= sp; + default_ebccr[1] |= sp; + default_ebccr[2] |= sp; + /* initialise by myself */ + for (i = 0; i < ARRAY_SIZE(default_ebccr); i++) { + if (default_ebccr[i]) + ____raw_writeq(default_ebccr[i], + &tx4939_ebuscptr->cr[i]); + else + ____raw_writeq(____raw_readq(&tx4939_ebuscptr->cr[i]) + & ~8, + &tx4939_ebuscptr->cr[i]); + } +} + +static void __init rbtx4939_update_ioc_pen(void) +{ + __u64 pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); + __u64 ccfg = ____raw_readq(&tx4939_ccfgptr->ccfg); + __u8 pe1 = readb(rbtx4939_pe1_addr); + __u8 pe2 = readb(rbtx4939_pe2_addr); + __u8 pe3 = readb(rbtx4939_pe3_addr); + if (pcfg & TX4939_PCFG_ATA0MODE) + pe1 |= RBTX4939_PE1_ATA(0); + else + pe1 &= ~RBTX4939_PE1_ATA(0); + if (pcfg & TX4939_PCFG_ATA1MODE) { + pe1 |= RBTX4939_PE1_ATA(1); + pe1 &= ~(RBTX4939_PE1_RMII(0) | RBTX4939_PE1_RMII(1)); + } else { + pe1 &= ~RBTX4939_PE1_ATA(1); + if (pcfg & TX4939_PCFG_ET0MODE) + pe1 |= RBTX4939_PE1_RMII(0); + else + pe1 &= ~RBTX4939_PE1_RMII(0); + if (pcfg & TX4939_PCFG_ET1MODE) + pe1 |= RBTX4939_PE1_RMII(1); + else + pe1 &= ~RBTX4939_PE1_RMII(1); + } + if (ccfg & TX4939_CCFG_PTSEL) + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | + RBTX4939_PE3_VP_S); + else { + __u64 vmode = pcfg & + (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE); + if (vmode == 0) + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | + RBTX4939_PE3_VP_S); + else if (vmode == TX4939_PCFG_VPSMODE) { + pe3 |= RBTX4939_PE3_VP_P; + pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_S); + } else if (vmode == TX4939_PCFG_VSSMODE) { + pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_S; + pe3 &= ~RBTX4939_PE3_VP_P; + } else { + pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_P; + pe3 &= ~RBTX4939_PE3_VP_S; + } + } + if (pcfg & TX4939_PCFG_SPIMODE) { + if (pcfg & TX4939_PCFG_SIO2MODE_GPIO) + pe2 &= ~(RBTX4939_PE2_SIO2 | RBTX4939_PE2_SIO0); + else { + if (pcfg & TX4939_PCFG_SIO2MODE_SIO2) { + pe2 |= RBTX4939_PE2_SIO2; + pe2 &= ~RBTX4939_PE2_SIO0; + } else { + pe2 |= RBTX4939_PE2_SIO0; + pe2 &= ~RBTX4939_PE2_SIO2; + } + } + if (pcfg & TX4939_PCFG_SIO3MODE) + pe2 |= RBTX4939_PE2_SIO3; + else + pe2 &= ~RBTX4939_PE2_SIO3; + pe2 &= ~RBTX4939_PE2_SPI; + } else { + pe2 |= RBTX4939_PE2_SPI; + pe2 &= ~(RBTX4939_PE2_SIO3 | RBTX4939_PE2_SIO2 | + RBTX4939_PE2_SIO0); + } + if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_GPIO) + pe2 |= RBTX4939_PE2_GPIO; + else + pe2 &= ~RBTX4939_PE2_GPIO; + writeb(pe1, rbtx4939_pe1_addr); + writeb(pe2, rbtx4939_pe2_addr); + writeb(pe3, rbtx4939_pe3_addr); +} + +#define RBTX4939_MAX_7SEGLEDS 8 + +#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +static u8 led_val[RBTX4939_MAX_7SEGLEDS]; +struct rbtx4939_led_data { + struct led_classdev cdev; + char name[32]; + unsigned int num; +}; + +/* Use "dot" in 7seg LEDs */ +static void rbtx4939_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct rbtx4939_led_data *led_dat = + container_of(led_cdev, struct rbtx4939_led_data, cdev); + unsigned int num = led_dat->num; + unsigned long flags; + + local_irq_save(flags); + led_val[num] = (led_val[num] & 0x7f) | (value ? 0x80 : 0); + writeb(led_val[num], rbtx4939_7seg_addr(num / 4, num % 4)); + local_irq_restore(flags); +} + +static int __init rbtx4939_led_probe(struct platform_device *pdev) +{ + struct rbtx4939_led_data *leds_data; + int i; + static char *default_triggers[] __initdata = { + "heartbeat", + "ide-disk", + "nand-disk", + }; + + leds_data = kzalloc(sizeof(*leds_data) * RBTX4939_MAX_7SEGLEDS, + GFP_KERNEL); + if (!leds_data) + return -ENOMEM; + for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++) { + int rc; + struct rbtx4939_led_data *led_dat = &leds_data[i]; + + led_dat->num = i; + led_dat->cdev.brightness_set = rbtx4939_led_brightness_set; + sprintf(led_dat->name, "rbtx4939:amber:%u", i); + led_dat->cdev.name = led_dat->name; + if (i < ARRAY_SIZE(default_triggers)) + led_dat->cdev.default_trigger = default_triggers[i]; + rc = led_classdev_register(&pdev->dev, &led_dat->cdev); + if (rc < 0) + return rc; + led_dat->cdev.brightness_set(&led_dat->cdev, 0); + } + return 0; + +} + +static struct platform_driver rbtx4939_led_driver = { + .driver = { + .name = "rbtx4939-led", + .owner = THIS_MODULE, + }, +}; + +static void __init rbtx4939_led_setup(void) +{ + platform_device_register_simple("rbtx4939-led", -1, NULL, 0); + platform_driver_probe(&rbtx4939_led_driver, rbtx4939_led_probe); +} +#else +static inline void rbtx4939_led_setup(void) +{ +} +#endif + +static void __init rbtx4939_arch_init(void) +{ + rbtx4939_pci_setup(); +} + +static void __init rbtx4939_device_init(void) +{ +#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) + int i, j; + unsigned char ethaddr[2][6]; + for (i = 0; i < 2; i++) { + unsigned long area = CKSEG1 + 0x1fff0000 + (i * 0x10); + if (readb(rbtx4939_bdipsw_addr) & 8) { + u16 buf[3]; + area -= 0x03000000; + for (j = 0; j < 3; j++) + buf[j] = le16_to_cpup((u16 *)(area + j * 2)); + memcpy(ethaddr[i], buf, 6); + } else + memcpy(ethaddr[i], (void *)area, 6); + } + tx4939_ethaddr_init(ethaddr[0], ethaddr[1]); +#endif + rbtx4939_led_setup(); + tx4939_wdt_init(); +} + +static void __init rbtx4939_setup(void) +{ + rbtx4939_ebusc_setup(); + /* always enable ATA0 */ + txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE); + rbtx4939_update_ioc_pen(); + if (txx9_master_clock == 0) + txx9_master_clock = 20000000; + tx4939_setup(); + + _machine_restart = rbtx4939_machine_restart; + + pr_info("RBTX4939 (Rev %02x) --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", + readb(rbtx4939_board_rev_addr), readb(rbtx4939_ioc_rev_addr), + readb(rbtx4939_udipsw_addr), readb(rbtx4939_bdipsw_addr)); + +#ifdef CONFIG_PCI + txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0); + txx9_board_pcibios_setup = tx4927_pcibios_setup; +#else + set_io_port_base(RBTX4939_ETHER_BASE); +#endif + + tx4939_sio_init(TX4939_SCLK0(txx9_master_clock), 0); +} + +struct txx9_board_vec rbtx4939_vec __initdata = { + .system = "Tothiba RBTX4939", + .prom_init = rbtx4939_prom_init, + .mem_setup = rbtx4939_setup, + .irq_setup = rbtx4939_irq_setup, + .time_init = rbtx4939_time_init, + .device_init = rbtx4939_device_init, + .arch_init = rbtx4939_arch_init, +#ifdef CONFIG_PCI + .pci_map_irq = tx4939_pci_map_irq, +#endif +}; diff --git a/include/asm-mips/txx9/boards.h b/include/asm-mips/txx9/boards.h index 4abc8142fbb..cbe9476d963 100644 --- a/include/asm-mips/txx9/boards.h +++ b/include/asm-mips/txx9/boards.h @@ -8,3 +8,6 @@ BOARD_VEC(rbtx4937_vec) #ifdef CONFIG_TOSHIBA_RBTX4938 BOARD_VEC(rbtx4938_vec) #endif +#ifdef CONFIG_TOSHIBA_RBTX4939 +BOARD_VEC(rbtx4939_vec) +#endif diff --git a/include/asm-mips/txx9/rbtx4939.h b/include/asm-mips/txx9/rbtx4939.h new file mode 100644 index 00000000000..1acf428c0b4 --- /dev/null +++ b/include/asm-mips/txx9/rbtx4939.h @@ -0,0 +1,133 @@ +/* + * Definitions for RBTX4939 + * + * (C) Copyright TOSHIBA CORPORATION 2005-2006 + * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_TXX9_RBTX4939_H +#define __ASM_TXX9_RBTX4939_H + +#include +#include +#include +#include + +/* Address map */ +#define RBTX4939_IOC_REG_ADDR (IO_BASE + TXX9_CE(1) + 0x00000000) +#define RBTX4939_BOARD_REV_ADDR (IO_BASE + TXX9_CE(1) + 0x00000000) +#define RBTX4939_IOC_REV_ADDR (IO_BASE + TXX9_CE(1) + 0x00000002) +#define RBTX4939_CONFIG1_ADDR (IO_BASE + TXX9_CE(1) + 0x00000004) +#define RBTX4939_CONFIG2_ADDR (IO_BASE + TXX9_CE(1) + 0x00000006) +#define RBTX4939_CONFIG3_ADDR (IO_BASE + TXX9_CE(1) + 0x00000008) +#define RBTX4939_CONFIG4_ADDR (IO_BASE + TXX9_CE(1) + 0x0000000a) +#define RBTX4939_USTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00001000) +#define RBTX4939_UDIPSW_ADDR (IO_BASE + TXX9_CE(1) + 0x00001002) +#define RBTX4939_BDIPSW_ADDR (IO_BASE + TXX9_CE(1) + 0x00001004) +#define RBTX4939_IEN_ADDR (IO_BASE + TXX9_CE(1) + 0x00002000) +#define RBTX4939_IPOL_ADDR (IO_BASE + TXX9_CE(1) + 0x00002002) +#define RBTX4939_IFAC1_ADDR (IO_BASE + TXX9_CE(1) + 0x00002004) +#define RBTX4939_IFAC2_ADDR (IO_BASE + TXX9_CE(1) + 0x00002006) +#define RBTX4939_SOFTINT_ADDR (IO_BASE + TXX9_CE(1) + 0x00003000) +#define RBTX4939_ISASTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00004000) +#define RBTX4939_PCISTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00004002) +#define RBTX4939_ROME_ADDR (IO_BASE + TXX9_CE(1) + 0x00004004) +#define RBTX4939_SPICS_ADDR (IO_BASE + TXX9_CE(1) + 0x00004006) +#define RBTX4939_AUDI_ADDR (IO_BASE + TXX9_CE(1) + 0x00004008) +#define RBTX4939_ISAGPIO_ADDR (IO_BASE + TXX9_CE(1) + 0x0000400a) +#define RBTX4939_PE1_ADDR (IO_BASE + TXX9_CE(1) + 0x00005000) +#define RBTX4939_PE2_ADDR (IO_BASE + TXX9_CE(1) + 0x00005002) +#define RBTX4939_PE3_ADDR (IO_BASE + TXX9_CE(1) + 0x00005004) +#define RBTX4939_VP_ADDR (IO_BASE + TXX9_CE(1) + 0x00005006) +#define RBTX4939_VPRESET_ADDR (IO_BASE + TXX9_CE(1) + 0x00005008) +#define RBTX4939_VPSOUT_ADDR (IO_BASE + TXX9_CE(1) + 0x0000500a) +#define RBTX4939_VPSIN_ADDR (IO_BASE + TXX9_CE(1) + 0x0000500c) +#define RBTX4939_7SEG_ADDR(s, ch) \ + (IO_BASE + TXX9_CE(1) + 0x00006000 + (s) * 16 + ((ch) & 3) * 2) +#define RBTX4939_SOFTRESET_ADDR (IO_BASE + TXX9_CE(1) + 0x00007000) +#define RBTX4939_RESETEN_ADDR (IO_BASE + TXX9_CE(1) + 0x00007002) +#define RBTX4939_RESETSTAT_ADDR (IO_BASE + TXX9_CE(1) + 0x00007004) +#define RBTX4939_ETHER_BASE (IO_BASE + TXX9_CE(1) + 0x00020000) + +/* Ethernet port address */ +#define RBTX4939_ETHER_ADDR (RBTX4939_ETHER_BASE + 0x300) + +/* bits for IEN/IPOL/IFAC */ +#define RBTX4938_INTB_ISA0 0 +#define RBTX4938_INTB_ISA11 1 +#define RBTX4938_INTB_ISA12 2 +#define RBTX4938_INTB_ISA15 3 +#define RBTX4938_INTB_I2S 4 +#define RBTX4938_INTB_SW 5 +#define RBTX4938_INTF_ISA0 (1 << RBTX4938_INTB_ISA0) +#define RBTX4938_INTF_ISA11 (1 << RBTX4938_INTB_ISA11) +#define RBTX4938_INTF_ISA12 (1 << RBTX4938_INTB_ISA12) +#define RBTX4938_INTF_ISA15 (1 << RBTX4938_INTB_ISA15) +#define RBTX4938_INTF_I2S (1 << RBTX4938_INTB_I2S) +#define RBTX4938_INTF_SW (1 << RBTX4938_INTB_SW) + +/* bits for PE1,PE2,PE3 */ +#define RBTX4939_PE1_ATA(ch) (0x01 << (ch)) +#define RBTX4939_PE1_RMII(ch) (0x04 << (ch)) +#define RBTX4939_PE2_SIO0 0x01 +#define RBTX4939_PE2_SIO2 0x02 +#define RBTX4939_PE2_SIO3 0x04 +#define RBTX4939_PE2_CIR 0x08 +#define RBTX4939_PE2_SPI 0x10 +#define RBTX4939_PE2_GPIO 0x20 +#define RBTX4939_PE3_VP 0x01 +#define RBTX4939_PE3_VP_P 0x02 +#define RBTX4939_PE3_VP_S 0x04 + +#define rbtx4939_board_rev_addr ((u8 __iomem *)RBTX4939_BOARD_REV_ADDR) +#define rbtx4939_ioc_rev_addr ((u8 __iomem *)RBTX4939_IOC_REV_ADDR) +#define rbtx4939_config1_addr ((u8 __iomem *)RBTX4939_CONFIG1_ADDR) +#define rbtx4939_config2_addr ((u8 __iomem *)RBTX4939_CONFIG2_ADDR) +#define rbtx4939_config3_addr ((u8 __iomem *)RBTX4939_CONFIG3_ADDR) +#define rbtx4939_config4_addr ((u8 __iomem *)RBTX4939_CONFIG4_ADDR) +#define rbtx4939_ustat_addr ((u8 __iomem *)RBTX4939_USTAT_ADDR) +#define rbtx4939_udipsw_addr ((u8 __iomem *)RBTX4939_UDIPSW_ADDR) +#define rbtx4939_bdipsw_addr ((u8 __iomem *)RBTX4939_BDIPSW_ADDR) +#define rbtx4939_ien_addr ((u8 __iomem *)RBTX4939_IEN_ADDR) +#define rbtx4939_ipol_addr ((u8 __iomem *)RBTX4939_IPOL_ADDR) +#define rbtx4939_ifac1_addr ((u8 __iomem *)RBTX4939_IFAC1_ADDR) +#define rbtx4939_ifac2_addr ((u8 __iomem *)RBTX4939_IFAC2_ADDR) +#define rbtx4939_softint_addr ((u8 __iomem *)RBTX4939_SOFTINT_ADDR) +#define rbtx4939_isastat_addr ((u8 __iomem *)RBTX4939_ISASTAT_ADDR) +#define rbtx4939_pcistat_addr ((u8 __iomem *)RBTX4939_PCISTAT_ADDR) +#define rbtx4939_rome_addr ((u8 __iomem *)RBTX4939_ROME_ADDR) +#define rbtx4939_spics_addr ((u8 __iomem *)RBTX4939_SPICS_ADDR) +#define rbtx4939_audi_addr ((u8 __iomem *)RBTX4939_AUDI_ADDR) +#define rbtx4939_isagpio_addr ((u8 __iomem *)RBTX4939_ISAGPIO_ADDR) +#define rbtx4939_pe1_addr ((u8 __iomem *)RBTX4939_PE1_ADDR) +#define rbtx4939_pe2_addr ((u8 __iomem *)RBTX4939_PE2_ADDR) +#define rbtx4939_pe3_addr ((u8 __iomem *)RBTX4939_PE3_ADDR) +#define rbtx4939_vp_addr ((u8 __iomem *)RBTX4939_VP_ADDR) +#define rbtx4939_vpreset_addr ((u8 __iomem *)RBTX4939_VPRESET_ADDR) +#define rbtx4939_vpsout_addr ((u8 __iomem *)RBTX4939_VPSOUT_ADDR) +#define rbtx4939_vpsin_addr ((u8 __iomem *)RBTX4939_VPSIN_ADDR) +#define rbtx4939_7seg_addr(s, ch) \ + ((u8 __iomem *)RBTX4939_7SEG_ADDR(s, ch)) +#define rbtx4939_softreset_addr ((u8 __iomem *)RBTX4939_SOFTRESET_ADDR) +#define rbtx4939_reseten_addr ((u8 __iomem *)RBTX4939_RESETEN_ADDR) +#define rbtx4939_resetstat_addr ((u8 __iomem *)RBTX4939_RESETSTAT_ADDR) + +/* + * IRQ mappings + */ +#define RBTX4939_NR_IRQ_IOC 8 + +#define RBTX4939_IRQ_IOC (TXX9_IRQ_BASE + TX4939_NUM_IR) +#define RBTX4939_IRQ_END (RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC) + +/* IOC (ISA, etc) */ +#define RBTX4939_IRQ_IOCINT (TXX9_IRQ_BASE + TX4939_IR_INT(0)) +/* Onboard 10M Ether */ +#define RBTX4939_IRQ_ETHER (TXX9_IRQ_BASE + TX4939_IR_INT(1)) + +void rbtx4939_prom_init(void); +void rbtx4939_irq_setup(void); + +#endif /* __ASM_TXX9_RBTX4939_H */ -- GitLab From b6263ff2d6e58cc2fe615219ab2a06778b5e6cef Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 1 Sep 2008 22:22:41 +0900 Subject: [PATCH 3904/5416] MIPS: TXx9: Implement prom_free_prom_memory Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/txx9/generic/setup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 7a05c34c1de..5526375010f 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -394,6 +395,11 @@ void __init prom_init(void) void __init prom_free_prom_memory(void) { + unsigned long saddr = PAGE_SIZE; + unsigned long eaddr = __pa_symbol(&_text); + + if (saddr < eaddr) + free_init_pages("prom memory", saddr, eaddr); } const char *get_system_type(void) -- GitLab From 8d2d91e86b4153cc2305ec86fe908048f459ff7f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:50 +0100 Subject: [PATCH 3905/5416] MIPS: Optimize get_user and put_user for 64-bit A long for the error value leads to unnecessary sign extensions. This patch shrinks an ip27_defconfig kernel build with gcc 4.3.0 by 2256 bytes. Signed-off-by: Ralf Baechle --- include/asm-mips/uaccess.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h index 66523d61095..b895144d577 100644 --- a/include/asm-mips/uaccess.h +++ b/include/asm-mips/uaccess.h @@ -224,7 +224,7 @@ do { \ #define __get_user_nocheck(x, ptr, size) \ ({ \ - long __gu_err; \ + int __gu_err; \ \ __get_user_common((x), size, ptr); \ __gu_err; \ @@ -232,7 +232,7 @@ do { \ #define __get_user_check(x, ptr, size) \ ({ \ - long __gu_err = -EFAULT; \ + int __gu_err = -EFAULT; \ const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \ \ if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ @@ -304,7 +304,7 @@ do { \ #define __put_user_nocheck(x, ptr, size) \ ({ \ __typeof__(*(ptr)) __pu_val; \ - long __pu_err = 0; \ + int __pu_err = 0; \ \ __pu_val = (x); \ switch (size) { \ @@ -321,7 +321,7 @@ do { \ ({ \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ __typeof__(*(ptr)) __pu_val = (x); \ - long __pu_err = -EFAULT; \ + int __pu_err = -EFAULT; \ \ if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ switch (size) { \ -- GitLab From e8c7c482347574ecdd45c43e32c332d5fc2ece61 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 16 Sep 2008 19:12:16 +0200 Subject: [PATCH 3906/5416] MIPS: Alchemy: rename directory It's more than the au1000 these days. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/Makefile | 30 +++++++++---------- arch/mips/{au1000 => alchemy}/Kconfig | 0 arch/mips/{au1000 => alchemy}/common/Makefile | 0 .../common/au1xxx_irqmap.c | 0 arch/mips/{au1000 => alchemy}/common/clocks.c | 0 .../{au1000 => alchemy}/common/cputable.c | 0 arch/mips/{au1000 => alchemy}/common/dbdma.c | 0 arch/mips/{au1000 => alchemy}/common/dma.c | 0 arch/mips/{au1000 => alchemy}/common/gpio.c | 0 arch/mips/{au1000 => alchemy}/common/irq.c | 0 arch/mips/{au1000 => alchemy}/common/pci.c | 0 .../{au1000 => alchemy}/common/platform.c | 0 arch/mips/{au1000 => alchemy}/common/power.c | 0 arch/mips/{au1000 => alchemy}/common/prom.c | 0 arch/mips/{au1000 => alchemy}/common/puts.c | 0 arch/mips/{au1000 => alchemy}/common/reset.c | 0 arch/mips/{au1000 => alchemy}/common/setup.c | 0 .../mips/{au1000 => alchemy}/common/sleeper.S | 10 +++---- arch/mips/{au1000 => alchemy}/common/time.c | 0 arch/mips/{au1000 => alchemy}/db1x00/Makefile | 0 .../{au1000 => alchemy}/db1x00/board_setup.c | 0 arch/mips/{au1000 => alchemy}/db1x00/init.c | 0 arch/mips/{au1000 => alchemy}/db1x00/irqmap.c | 0 arch/mips/{au1000 => alchemy}/mtx-1/Makefile | 0 .../{au1000 => alchemy}/mtx-1/board_setup.c | 0 arch/mips/{au1000 => alchemy}/mtx-1/init.c | 0 arch/mips/{au1000 => alchemy}/mtx-1/irqmap.c | 0 .../mips/{au1000 => alchemy}/mtx-1/platform.c | 0 arch/mips/{au1000 => alchemy}/pb1000/Makefile | 0 .../{au1000 => alchemy}/pb1000/board_setup.c | 0 arch/mips/{au1000 => alchemy}/pb1000/init.c | 0 arch/mips/{au1000 => alchemy}/pb1000/irqmap.c | 0 arch/mips/{au1000 => alchemy}/pb1100/Makefile | 0 .../{au1000 => alchemy}/pb1100/board_setup.c | 0 arch/mips/{au1000 => alchemy}/pb1100/init.c | 0 arch/mips/{au1000 => alchemy}/pb1100/irqmap.c | 0 arch/mips/{au1000 => alchemy}/pb1200/Makefile | 0 .../{au1000 => alchemy}/pb1200/board_setup.c | 0 arch/mips/{au1000 => alchemy}/pb1200/init.c | 0 arch/mips/{au1000 => alchemy}/pb1200/irqmap.c | 0 .../{au1000 => alchemy}/pb1200/platform.c | 0 arch/mips/{au1000 => alchemy}/pb1500/Makefile | 0 .../{au1000 => alchemy}/pb1500/board_setup.c | 0 arch/mips/{au1000 => alchemy}/pb1500/init.c | 0 arch/mips/{au1000 => alchemy}/pb1500/irqmap.c | 0 arch/mips/{au1000 => alchemy}/pb1550/Makefile | 0 .../{au1000 => alchemy}/pb1550/board_setup.c | 0 arch/mips/{au1000 => alchemy}/pb1550/init.c | 0 arch/mips/{au1000 => alchemy}/pb1550/irqmap.c | 0 .../mips/{au1000 => alchemy}/xxs1500/Makefile | 0 .../{au1000 => alchemy}/xxs1500/board_setup.c | 0 arch/mips/{au1000 => alchemy}/xxs1500/init.c | 0 .../mips/{au1000 => alchemy}/xxs1500/irqmap.c | 0 54 files changed, 21 insertions(+), 21 deletions(-) rename arch/mips/{au1000 => alchemy}/Kconfig (100%) rename arch/mips/{au1000 => alchemy}/common/Makefile (100%) rename arch/mips/{au1000 => alchemy}/common/au1xxx_irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/common/clocks.c (100%) rename arch/mips/{au1000 => alchemy}/common/cputable.c (100%) rename arch/mips/{au1000 => alchemy}/common/dbdma.c (100%) rename arch/mips/{au1000 => alchemy}/common/dma.c (100%) rename arch/mips/{au1000 => alchemy}/common/gpio.c (100%) rename arch/mips/{au1000 => alchemy}/common/irq.c (100%) rename arch/mips/{au1000 => alchemy}/common/pci.c (100%) rename arch/mips/{au1000 => alchemy}/common/platform.c (100%) rename arch/mips/{au1000 => alchemy}/common/power.c (100%) rename arch/mips/{au1000 => alchemy}/common/prom.c (100%) rename arch/mips/{au1000 => alchemy}/common/puts.c (100%) rename arch/mips/{au1000 => alchemy}/common/reset.c (100%) rename arch/mips/{au1000 => alchemy}/common/setup.c (100%) rename arch/mips/{au1000 => alchemy}/common/sleeper.S (96%) rename arch/mips/{au1000 => alchemy}/common/time.c (100%) rename arch/mips/{au1000 => alchemy}/db1x00/Makefile (100%) rename arch/mips/{au1000 => alchemy}/db1x00/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/db1x00/init.c (100%) rename arch/mips/{au1000 => alchemy}/db1x00/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/mtx-1/Makefile (100%) rename arch/mips/{au1000 => alchemy}/mtx-1/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/mtx-1/init.c (100%) rename arch/mips/{au1000 => alchemy}/mtx-1/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/mtx-1/platform.c (100%) rename arch/mips/{au1000 => alchemy}/pb1000/Makefile (100%) rename arch/mips/{au1000 => alchemy}/pb1000/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/pb1000/init.c (100%) rename arch/mips/{au1000 => alchemy}/pb1000/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/pb1100/Makefile (100%) rename arch/mips/{au1000 => alchemy}/pb1100/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/pb1100/init.c (100%) rename arch/mips/{au1000 => alchemy}/pb1100/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/pb1200/Makefile (100%) rename arch/mips/{au1000 => alchemy}/pb1200/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/pb1200/init.c (100%) rename arch/mips/{au1000 => alchemy}/pb1200/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/pb1200/platform.c (100%) rename arch/mips/{au1000 => alchemy}/pb1500/Makefile (100%) rename arch/mips/{au1000 => alchemy}/pb1500/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/pb1500/init.c (100%) rename arch/mips/{au1000 => alchemy}/pb1500/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/pb1550/Makefile (100%) rename arch/mips/{au1000 => alchemy}/pb1550/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/pb1550/init.c (100%) rename arch/mips/{au1000 => alchemy}/pb1550/irqmap.c (100%) rename arch/mips/{au1000 => alchemy}/xxs1500/Makefile (100%) rename arch/mips/{au1000 => alchemy}/xxs1500/board_setup.c (100%) rename arch/mips/{au1000 => alchemy}/xxs1500/init.c (100%) rename arch/mips/{au1000 => alchemy}/xxs1500/irqmap.c (100%) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 00a23a11849..c15416c2e89 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -598,7 +598,7 @@ config WR_PPMC endchoice -source "arch/mips/au1000/Kconfig" +source "arch/mips/alchemy/Kconfig" source "arch/mips/basler/excite/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/lasat/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 87f67228e30..4401a0c1278 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -176,103 +176,103 @@ load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # # Common Alchemy Au1x00 stuff # -core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/ +core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 # # AMD Alchemy Pb1000 eval board # -libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/ +libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/ cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 # # AMD Alchemy Pb1100 eval board # -libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/ +libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/ cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 # # AMD Alchemy Pb1500 eval board # -libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ +libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/ cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 # # AMD Alchemy Pb1550 eval board # -libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ +libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/ cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # -libs-$(CONFIG_MIPS_PB1200) += arch/mips/au1000/pb1200/ +libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/ cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # AMD Alchemy Db1000 eval board # -libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # # AMD Alchemy Db1100 eval board # -libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 # # AMD Alchemy Db1500 eval board # -libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 # # AMD Alchemy Db1550 eval board # -libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # -libs-$(CONFIG_MIPS_DB1200) += arch/mips/au1000/pb1200/ +libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/ cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # AMD Alchemy Bosporus eval board # -libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 # # AMD Alchemy Mirage eval board # -libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/ +libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/ cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # # 4G-Systems eval board # -libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/ +libs-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 # # MyCable eval board # -libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/ +libs-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # diff --git a/arch/mips/au1000/Kconfig b/arch/mips/alchemy/Kconfig similarity index 100% rename from arch/mips/au1000/Kconfig rename to arch/mips/alchemy/Kconfig diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/alchemy/common/Makefile similarity index 100% rename from arch/mips/au1000/common/Makefile rename to arch/mips/alchemy/common/Makefile diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/alchemy/common/au1xxx_irqmap.c similarity index 100% rename from arch/mips/au1000/common/au1xxx_irqmap.c rename to arch/mips/alchemy/common/au1xxx_irqmap.c diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/alchemy/common/clocks.c similarity index 100% rename from arch/mips/au1000/common/clocks.c rename to arch/mips/alchemy/common/clocks.c diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/alchemy/common/cputable.c similarity index 100% rename from arch/mips/au1000/common/cputable.c rename to arch/mips/alchemy/common/cputable.c diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c similarity index 100% rename from arch/mips/au1000/common/dbdma.c rename to arch/mips/alchemy/common/dbdma.c diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/alchemy/common/dma.c similarity index 100% rename from arch/mips/au1000/common/dma.c rename to arch/mips/alchemy/common/dma.c diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/alchemy/common/gpio.c similarity index 100% rename from arch/mips/au1000/common/gpio.c rename to arch/mips/alchemy/common/gpio.c diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/alchemy/common/irq.c similarity index 100% rename from arch/mips/au1000/common/irq.c rename to arch/mips/alchemy/common/irq.c diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/alchemy/common/pci.c similarity index 100% rename from arch/mips/au1000/common/pci.c rename to arch/mips/alchemy/common/pci.c diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/alchemy/common/platform.c similarity index 100% rename from arch/mips/au1000/common/platform.c rename to arch/mips/alchemy/common/platform.c diff --git a/arch/mips/au1000/common/power.c b/arch/mips/alchemy/common/power.c similarity index 100% rename from arch/mips/au1000/common/power.c rename to arch/mips/alchemy/common/power.c diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/alchemy/common/prom.c similarity index 100% rename from arch/mips/au1000/common/prom.c rename to arch/mips/alchemy/common/prom.c diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/alchemy/common/puts.c similarity index 100% rename from arch/mips/au1000/common/puts.c rename to arch/mips/alchemy/common/puts.c diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/alchemy/common/reset.c similarity index 100% rename from arch/mips/au1000/common/reset.c rename to arch/mips/alchemy/common/reset.c diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/alchemy/common/setup.c similarity index 100% rename from arch/mips/au1000/common/setup.c rename to arch/mips/alchemy/common/setup.c diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S similarity index 96% rename from arch/mips/au1000/common/sleeper.S rename to arch/mips/alchemy/common/sleeper.S index 4b3cf021a45..3006e270c8b 100644 --- a/arch/mips/au1000/common/sleeper.S +++ b/arch/mips/alchemy/common/sleeper.S @@ -79,12 +79,12 @@ LEAF(save_and_sleep) /* Put SDRAM into self refresh. Preload instructions into cache, * issue a precharge, then auto refresh, then sleep commands to it. */ - la t0, sdsleep + la t0, sdsleep .set mips3 - cache 0x14, 0(t0) - cache 0x14, 32(t0) - cache 0x14, 64(t0) - cache 0x14, 96(t0) + cache 0x14, 0(t0) + cache 0x14, 32(t0) + cache 0x14, 64(t0) + cache 0x14, 96(t0) .set mips0 sdsleep: diff --git a/arch/mips/au1000/common/time.c b/arch/mips/alchemy/common/time.c similarity index 100% rename from arch/mips/au1000/common/time.c rename to arch/mips/alchemy/common/time.c diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/alchemy/db1x00/Makefile similarity index 100% rename from arch/mips/au1000/db1x00/Makefile rename to arch/mips/alchemy/db1x00/Makefile diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/alchemy/db1x00/board_setup.c similarity index 100% rename from arch/mips/au1000/db1x00/board_setup.c rename to arch/mips/alchemy/db1x00/board_setup.c diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/alchemy/db1x00/init.c similarity index 100% rename from arch/mips/au1000/db1x00/init.c rename to arch/mips/alchemy/db1x00/init.c diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/alchemy/db1x00/irqmap.c similarity index 100% rename from arch/mips/au1000/db1x00/irqmap.c rename to arch/mips/alchemy/db1x00/irqmap.c diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile similarity index 100% rename from arch/mips/au1000/mtx-1/Makefile rename to arch/mips/alchemy/mtx-1/Makefile diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c similarity index 100% rename from arch/mips/au1000/mtx-1/board_setup.c rename to arch/mips/alchemy/mtx-1/board_setup.c diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/alchemy/mtx-1/init.c similarity index 100% rename from arch/mips/au1000/mtx-1/init.c rename to arch/mips/alchemy/mtx-1/init.c diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/alchemy/mtx-1/irqmap.c similarity index 100% rename from arch/mips/au1000/mtx-1/irqmap.c rename to arch/mips/alchemy/mtx-1/irqmap.c diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/alchemy/mtx-1/platform.c similarity index 100% rename from arch/mips/au1000/mtx-1/platform.c rename to arch/mips/alchemy/mtx-1/platform.c diff --git a/arch/mips/au1000/pb1000/Makefile b/arch/mips/alchemy/pb1000/Makefile similarity index 100% rename from arch/mips/au1000/pb1000/Makefile rename to arch/mips/alchemy/pb1000/Makefile diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/alchemy/pb1000/board_setup.c similarity index 100% rename from arch/mips/au1000/pb1000/board_setup.c rename to arch/mips/alchemy/pb1000/board_setup.c diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/alchemy/pb1000/init.c similarity index 100% rename from arch/mips/au1000/pb1000/init.c rename to arch/mips/alchemy/pb1000/init.c diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/alchemy/pb1000/irqmap.c similarity index 100% rename from arch/mips/au1000/pb1000/irqmap.c rename to arch/mips/alchemy/pb1000/irqmap.c diff --git a/arch/mips/au1000/pb1100/Makefile b/arch/mips/alchemy/pb1100/Makefile similarity index 100% rename from arch/mips/au1000/pb1100/Makefile rename to arch/mips/alchemy/pb1100/Makefile diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/alchemy/pb1100/board_setup.c similarity index 100% rename from arch/mips/au1000/pb1100/board_setup.c rename to arch/mips/alchemy/pb1100/board_setup.c diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/alchemy/pb1100/init.c similarity index 100% rename from arch/mips/au1000/pb1100/init.c rename to arch/mips/alchemy/pb1100/init.c diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/alchemy/pb1100/irqmap.c similarity index 100% rename from arch/mips/au1000/pb1100/irqmap.c rename to arch/mips/alchemy/pb1100/irqmap.c diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/alchemy/pb1200/Makefile similarity index 100% rename from arch/mips/au1000/pb1200/Makefile rename to arch/mips/alchemy/pb1200/Makefile diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/alchemy/pb1200/board_setup.c similarity index 100% rename from arch/mips/au1000/pb1200/board_setup.c rename to arch/mips/alchemy/pb1200/board_setup.c diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/alchemy/pb1200/init.c similarity index 100% rename from arch/mips/au1000/pb1200/init.c rename to arch/mips/alchemy/pb1200/init.c diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/alchemy/pb1200/irqmap.c similarity index 100% rename from arch/mips/au1000/pb1200/irqmap.c rename to arch/mips/alchemy/pb1200/irqmap.c diff --git a/arch/mips/au1000/pb1200/platform.c b/arch/mips/alchemy/pb1200/platform.c similarity index 100% rename from arch/mips/au1000/pb1200/platform.c rename to arch/mips/alchemy/pb1200/platform.c diff --git a/arch/mips/au1000/pb1500/Makefile b/arch/mips/alchemy/pb1500/Makefile similarity index 100% rename from arch/mips/au1000/pb1500/Makefile rename to arch/mips/alchemy/pb1500/Makefile diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/alchemy/pb1500/board_setup.c similarity index 100% rename from arch/mips/au1000/pb1500/board_setup.c rename to arch/mips/alchemy/pb1500/board_setup.c diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/alchemy/pb1500/init.c similarity index 100% rename from arch/mips/au1000/pb1500/init.c rename to arch/mips/alchemy/pb1500/init.c diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/alchemy/pb1500/irqmap.c similarity index 100% rename from arch/mips/au1000/pb1500/irqmap.c rename to arch/mips/alchemy/pb1500/irqmap.c diff --git a/arch/mips/au1000/pb1550/Makefile b/arch/mips/alchemy/pb1550/Makefile similarity index 100% rename from arch/mips/au1000/pb1550/Makefile rename to arch/mips/alchemy/pb1550/Makefile diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/alchemy/pb1550/board_setup.c similarity index 100% rename from arch/mips/au1000/pb1550/board_setup.c rename to arch/mips/alchemy/pb1550/board_setup.c diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/alchemy/pb1550/init.c similarity index 100% rename from arch/mips/au1000/pb1550/init.c rename to arch/mips/alchemy/pb1550/init.c diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/alchemy/pb1550/irqmap.c similarity index 100% rename from arch/mips/au1000/pb1550/irqmap.c rename to arch/mips/alchemy/pb1550/irqmap.c diff --git a/arch/mips/au1000/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile similarity index 100% rename from arch/mips/au1000/xxs1500/Makefile rename to arch/mips/alchemy/xxs1500/Makefile diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c similarity index 100% rename from arch/mips/au1000/xxs1500/board_setup.c rename to arch/mips/alchemy/xxs1500/board_setup.c diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/alchemy/xxs1500/init.c similarity index 100% rename from arch/mips/au1000/xxs1500/init.c rename to arch/mips/alchemy/xxs1500/init.c diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/alchemy/xxs1500/irqmap.c similarity index 100% rename from arch/mips/au1000/xxs1500/irqmap.c rename to arch/mips/alchemy/xxs1500/irqmap.c -- GitLab From 384740dc49ea651ba350704d13ff6be9976e37fe Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 16 Sep 2008 19:48:51 +0200 Subject: [PATCH 3907/5416] MIPS: Move headfiles to new location below arch/mips/include Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 84 +++++++++---------- .../asm-mips => arch/mips/include/asm}/Kbuild | 0 .../mips/include/asm}/a.out.h | 0 .../asm-mips => arch/mips/include/asm}/abi.h | 0 .../mips/include/asm}/addrspace.h | 0 .../asm-mips => arch/mips/include/asm}/asm.h | 0 .../mips/include/asm}/asmmacro-32.h | 0 .../mips/include/asm}/asmmacro-64.h | 0 .../mips/include/asm}/asmmacro.h | 0 .../mips/include/asm}/atomic.h | 0 .../mips/include/asm}/auxvec.h | 0 .../mips/include/asm}/barrier.h | 0 .../mips/include/asm}/bcache.h | 0 .../mips/include/asm}/bitops.h | 0 .../mips/include/asm}/bootinfo.h | 0 .../mips/include/asm}/branch.h | 0 .../mips/include/asm}/break.h | 0 .../asm-mips => arch/mips/include/asm}/bug.h | 0 .../asm-mips => arch/mips/include/asm}/bugs.h | 0 .../mips/include/asm}/byteorder.h | 0 .../mips/include/asm}/cache.h | 0 .../mips/include/asm}/cachectl.h | 0 .../mips/include/asm}/cacheflush.h | 0 .../mips/include/asm}/cacheops.h | 0 .../mips/include/asm}/checksum.h | 0 .../asm-mips => arch/mips/include/asm}/cmp.h | 0 .../mips/include/asm}/cmpxchg.h | 0 .../mips/include/asm}/compat-signal.h | 0 .../mips/include/asm}/compat.h | 0 .../mips/include/asm}/compiler.h | 0 .../mips/include/asm}/cpu-features.h | 0 .../mips/include/asm}/cpu-info.h | 0 .../asm-mips => arch/mips/include/asm}/cpu.h | 0 .../mips/include/asm}/cputime.h | 0 .../mips/include/asm}/current.h | 0 .../mips/include/asm}/debug.h | 0 .../mips/include/asm}/dec/ecc.h | 0 .../mips/include/asm}/dec/interrupts.h | 0 .../mips/include/asm}/dec/ioasic.h | 0 .../mips/include/asm}/dec/ioasic_addrs.h | 0 .../mips/include/asm}/dec/ioasic_ints.h | 0 .../mips/include/asm}/dec/kn01.h | 0 .../mips/include/asm}/dec/kn02.h | 0 .../mips/include/asm}/dec/kn02ba.h | 0 .../mips/include/asm}/dec/kn02ca.h | 0 .../mips/include/asm}/dec/kn02xa.h | 0 .../mips/include/asm}/dec/kn03.h | 0 .../mips/include/asm}/dec/kn05.h | 0 .../mips/include/asm}/dec/kn230.h | 0 .../mips/include/asm}/dec/machtype.h | 0 .../mips/include/asm}/dec/prom.h | 0 .../mips/include/asm}/dec/system.h | 0 .../mips/include/asm}/delay.h | 0 .../mips/include/asm}/device.h | 0 .../mips/include/asm}/div64.h | 0 .../mips/include/asm}/dma-mapping.h | 0 .../asm-mips => arch/mips/include/asm}/dma.h | 0 .../mips/include/asm}/ds1286.h | 0 .../mips/include/asm}/ds1287.h | 0 .../asm-mips => arch/mips/include/asm}/dsp.h | 0 .../asm-mips => arch/mips/include/asm}/edac.h | 0 .../asm-mips => arch/mips/include/asm}/elf.h | 0 .../mips/include/asm}/emergency-restart.h | 0 .../mips/include/asm}/emma2rh/emma2rh.h | 0 .../mips/include/asm}/emma2rh/markeins.h | 0 .../mips/include/asm}/errno.h | 0 .../asm-mips => arch/mips/include/asm}/fb.h | 0 .../mips/include/asm}/fcntl.h | 0 .../mips/include/asm}/fixmap.h | 0 .../mips/include/asm}/floppy.h | 0 .../mips/include/asm}/fpregdef.h | 0 .../asm-mips => arch/mips/include/asm}/fpu.h | 0 .../mips/include/asm}/fpu_emulator.h | 0 .../mips/include/asm}/futex.h | 0 .../mips/include/asm}/fw/arc/hinv.h | 0 .../mips/include/asm}/fw/arc/types.h | 0 .../mips/include/asm}/fw/cfe/cfe_api.h | 0 .../mips/include/asm}/fw/cfe/cfe_error.h | 0 .../mips/include/asm}/gcmpregs.h | 0 .../asm-mips => arch/mips/include/asm}/gic.h | 0 .../asm-mips => arch/mips/include/asm}/gpio.h | 0 .../mips/include/asm}/gt64120.h | 0 .../mips/include/asm}/hardirq.h | 0 .../mips/include/asm}/hazards.h | 0 .../mips/include/asm}/highmem.h | 0 .../mips/include/asm}/hw_irq.h | 0 .../mips/include/asm}/i8253.h | 0 .../mips/include/asm}/i8259.h | 0 .../asm-mips => arch/mips/include/asm}/ide.h | 0 .../asm-mips => arch/mips/include/asm}/inst.h | 0 .../asm-mips => arch/mips/include/asm}/io.h | 0 .../mips/include/asm}/ioctl.h | 0 .../mips/include/asm}/ioctls.h | 0 .../mips/include/asm}/ip32/crime.h | 0 .../mips/include/asm}/ip32/ip32_ints.h | 0 .../mips/include/asm}/ip32/mace.h | 0 .../mips/include/asm}/ipcbuf.h | 0 .../asm-mips => arch/mips/include/asm}/irq.h | 0 .../mips/include/asm}/irq_cpu.h | 0 .../mips/include/asm}/irq_gt641xx.h | 0 .../mips/include/asm}/irq_regs.h | 0 .../mips/include/asm}/irqflags.h | 0 .../mips/include/asm}/isadep.h | 0 .../asm-mips => arch/mips/include/asm}/jazz.h | 0 .../mips/include/asm}/jazzdma.h | 0 .../mips/include/asm}/kdebug.h | 0 .../mips/include/asm}/kexec.h | 0 .../asm-mips => arch/mips/include/asm}/kgdb.h | 0 .../mips/include/asm}/kmap_types.h | 0 .../asm-mips => arch/mips/include/asm}/kspd.h | 0 .../mips/include/asm}/lasat/ds1603.h | 0 .../mips/include/asm}/lasat/eeprom.h | 0 .../mips/include/asm}/lasat/head.h | 0 .../mips/include/asm}/lasat/lasat.h | 0 .../mips/include/asm}/lasat/lasatint.h | 0 .../mips/include/asm}/lasat/picvue.h | 0 .../mips/include/asm}/lasat/serial.h | 0 .../mips/include/asm}/linkage.h | 0 .../mips/include/asm}/local.h | 0 .../mips/include/asm}/m48t35.h | 0 .../mips/include/asm}/m48t37.h | 0 .../mips/include/asm}/mach-au1x00/au1000.h | 0 .../include/asm}/mach-au1x00/au1000_dma.h | 0 .../include/asm}/mach-au1x00/au1000_gpio.h | 0 .../include/asm}/mach-au1x00/au1100_mmc.h | 0 .../include/asm}/mach-au1x00/au1550_spi.h | 0 .../mips/include/asm}/mach-au1x00/au1xxx.h | 0 .../include/asm}/mach-au1x00/au1xxx_dbdma.h | 0 .../include/asm}/mach-au1x00/au1xxx_ide.h | 0 .../include/asm}/mach-au1x00/au1xxx_psc.h | 0 .../mips/include/asm}/mach-au1x00/gpio.h | 0 .../mips/include/asm}/mach-au1x00/ioremap.h | 0 .../mips/include/asm}/mach-au1x00/prom.h | 0 .../mips/include/asm}/mach-au1x00/war.h | 0 .../mips/include/asm}/mach-bcm47xx/bcm47xx.h | 0 .../mips/include/asm}/mach-bcm47xx/gpio.h | 0 .../mips/include/asm}/mach-bcm47xx/war.h | 0 .../mips/include/asm}/mach-cobalt/cobalt.h | 0 .../asm}/mach-cobalt/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-cobalt/irq.h | 0 .../include/asm}/mach-cobalt/mach-gt64120.h | 0 .../mips/include/asm}/mach-cobalt/war.h | 0 .../mips/include/asm}/mach-db1x00/db1200.h | 0 .../mips/include/asm}/mach-db1x00/db1x00.h | 0 .../mips/include/asm}/mach-dec/mc146818rtc.h | 0 .../mips/include/asm}/mach-dec/war.h | 0 .../mips/include/asm}/mach-emma2rh/irq.h | 0 .../mips/include/asm}/mach-emma2rh/war.h | 0 .../asm}/mach-excite/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-excite/excite.h | 0 .../include/asm}/mach-excite/excite_fpga.h | 0 .../asm}/mach-excite/excite_nandflash.h | 0 .../mips/include/asm}/mach-excite/rm9k_eth.h | 0 .../mips/include/asm}/mach-excite/rm9k_wdt.h | 0 .../include/asm}/mach-excite/rm9k_xicap.h | 0 .../mips/include/asm}/mach-excite/war.h | 0 .../asm}/mach-generic/cpu-feature-overrides.h | 0 .../include/asm}/mach-generic/dma-coherence.h | 0 .../mips/include/asm}/mach-generic/floppy.h | 0 .../mips/include/asm}/mach-generic/gpio.h | 0 .../mips/include/asm}/mach-generic/ide.h | 0 .../mips/include/asm}/mach-generic/ioremap.h | 0 .../mips/include/asm}/mach-generic/irq.h | 0 .../asm}/mach-generic/kernel-entry-init.h | 0 .../mips/include/asm}/mach-generic/kmalloc.h | 0 .../include/asm}/mach-generic/mangle-port.h | 0 .../include/asm}/mach-generic/mc146818rtc.h | 0 .../mips/include/asm}/mach-generic/spaces.h | 0 .../mips/include/asm}/mach-generic/topology.h | 0 .../asm}/mach-ip22/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-ip22/ds1286.h | 0 .../mips/include/asm}/mach-ip22/spaces.h | 0 .../mips/include/asm}/mach-ip22/war.h | 0 .../asm}/mach-ip27/cpu-feature-overrides.h | 0 .../include/asm}/mach-ip27/dma-coherence.h | 0 .../mips/include/asm}/mach-ip27/irq.h | 0 .../asm}/mach-ip27/kernel-entry-init.h | 0 .../mips/include/asm}/mach-ip27/kmalloc.h | 0 .../mips/include/asm}/mach-ip27/mangle-port.h | 0 .../mips/include/asm}/mach-ip27/mmzone.h | 0 .../mips/include/asm}/mach-ip27/spaces.h | 0 .../mips/include/asm}/mach-ip27/topology.h | 0 .../mips/include/asm}/mach-ip27/war.h | 0 .../asm}/mach-ip28/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-ip28/ds1286.h | 0 .../mips/include/asm}/mach-ip28/spaces.h | 0 .../mips/include/asm}/mach-ip28/war.h | 0 .../asm}/mach-ip32/cpu-feature-overrides.h | 0 .../include/asm}/mach-ip32/dma-coherence.h | 0 .../mips/include/asm}/mach-ip32/kmalloc.h | 0 .../mips/include/asm}/mach-ip32/mangle-port.h | 0 .../mips/include/asm}/mach-ip32/mc146818rtc.h | 0 .../mips/include/asm}/mach-ip32/war.h | 0 .../include/asm}/mach-jazz/dma-coherence.h | 0 .../mips/include/asm}/mach-jazz/floppy.h | 0 .../mips/include/asm}/mach-jazz/mc146818rtc.h | 0 .../mips/include/asm}/mach-jazz/war.h | 0 .../mips/include/asm}/mach-lasat/irq.h | 0 .../include/asm}/mach-lasat/mach-gt64120.h | 0 .../mips/include/asm}/mach-lasat/war.h | 0 .../include/asm}/mach-lemote/dma-coherence.h | 0 .../include/asm}/mach-lemote/mc146818rtc.h | 0 .../mips/include/asm}/mach-lemote/war.h | 0 .../asm}/mach-malta/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-malta/irq.h | 0 .../asm}/mach-malta/kernel-entry-init.h | 0 .../include/asm}/mach-malta/mach-gt64120.h | 0 .../include/asm}/mach-malta/mc146818rtc.h | 0 .../mips/include/asm}/mach-malta/war.h | 0 .../asm}/mach-mipssim/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-mipssim/war.h | 0 .../include/asm}/mach-pb1x00/mc146818rtc.h | 0 .../mips/include/asm}/mach-pb1x00/pb1000.h | 0 .../mips/include/asm}/mach-pb1x00/pb1100.h | 0 .../mips/include/asm}/mach-pb1x00/pb1200.h | 0 .../mips/include/asm}/mach-pb1x00/pb1500.h | 0 .../mips/include/asm}/mach-pb1x00/pb1550.h | 0 .../mips/include/asm}/mach-pnx8550/cm.h | 0 .../mips/include/asm}/mach-pnx8550/glb.h | 0 .../mips/include/asm}/mach-pnx8550/int.h | 0 .../asm}/mach-pnx8550/kernel-entry-init.h | 0 .../mips/include/asm}/mach-pnx8550/nand.h | 0 .../mips/include/asm}/mach-pnx8550/pci.h | 0 .../mips/include/asm}/mach-pnx8550/uart.h | 0 .../mips/include/asm}/mach-pnx8550/usb.h | 0 .../mips/include/asm}/mach-pnx8550/war.h | 0 .../asm}/mach-rc32434/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-rc32434/ddr.h | 0 .../mips/include/asm}/mach-rc32434/dma.h | 0 .../mips/include/asm}/mach-rc32434/dma_v.h | 0 .../mips/include/asm}/mach-rc32434/eth.h | 0 .../mips/include/asm}/mach-rc32434/gpio.h | 0 .../mips/include/asm}/mach-rc32434/integ.h | 0 .../mips/include/asm}/mach-rc32434/irq.h | 0 .../mips/include/asm}/mach-rc32434/pci.h | 0 .../mips/include/asm}/mach-rc32434/prom.h | 0 .../mips/include/asm}/mach-rc32434/rb.h | 0 .../mips/include/asm}/mach-rc32434/rc32434.h | 0 .../mips/include/asm}/mach-rc32434/timer.h | 0 .../mips/include/asm}/mach-rc32434/war.h | 0 .../asm}/mach-rm/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-rm/mc146818rtc.h | 0 .../mips/include/asm}/mach-rm/war.h | 0 .../asm}/mach-sibyte/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-sibyte/war.h | 0 .../mips/include/asm}/mach-tx39xx/ioremap.h | 0 .../include/asm}/mach-tx39xx/mangle-port.h | 0 .../mips/include/asm}/mach-tx39xx/war.h | 0 .../asm}/mach-tx49xx/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-tx49xx/ioremap.h | 0 .../mips/include/asm}/mach-tx49xx/kmalloc.h | 0 .../mips/include/asm}/mach-tx49xx/war.h | 0 .../mips/include/asm}/mach-vr41xx/irq.h | 0 .../mips/include/asm}/mach-vr41xx/war.h | 0 .../include/asm}/mach-wrppmc/mach-gt64120.h | 0 .../mips/include/asm}/mach-wrppmc/war.h | 0 .../mach-yosemite/cpu-feature-overrides.h | 0 .../mips/include/asm}/mach-yosemite/war.h | 0 .../mips/include/asm}/mc146818-time.h | 0 .../mips/include/asm}/mc146818rtc.h | 0 .../mips/include/asm}/mips-boards/bonito64.h | 0 .../mips/include/asm}/mips-boards/generic.h | 0 .../mips/include/asm}/mips-boards/launch.h | 0 .../mips/include/asm}/mips-boards/malta.h | 0 .../mips/include/asm}/mips-boards/maltaint.h | 0 .../mips/include/asm}/mips-boards/msc01_pci.h | 0 .../mips/include/asm}/mips-boards/piix4.h | 0 .../mips/include/asm}/mips-boards/prom.h | 0 .../mips/include/asm}/mips-boards/sim.h | 0 .../mips/include/asm}/mips-boards/simint.h | 0 .../mips/include/asm}/mips_mt.h | 0 .../mips/include/asm}/mipsmtregs.h | 0 .../mips/include/asm}/mipsprom.h | 0 .../mips/include/asm}/mipsregs.h | 0 .../asm-mips => arch/mips/include/asm}/mman.h | 0 .../asm-mips => arch/mips/include/asm}/mmu.h | 0 .../mips/include/asm}/mmu_context.h | 8 +- .../mips/include/asm}/mmzone.h | 0 .../mips/include/asm}/module.h | 0 .../mips/include/asm}/msc01_ic.h | 0 .../mips/include/asm}/msgbuf.h | 0 .../mips/include/asm}/mutex.h | 0 .../mips/include/asm}/nile4.h | 0 .../mips/include/asm}/paccess.h | 0 .../asm-mips => arch/mips/include/asm}/page.h | 0 .../mips/include/asm}/param.h | 0 .../mips/include/asm}/parport.h | 0 .../asm-mips => arch/mips/include/asm}/pci.h | 0 .../mips/include/asm}/pci/bridge.h | 0 .../mips/include/asm}/percpu.h | 0 .../mips/include/asm}/pgalloc.h | 0 .../mips/include/asm}/pgtable-32.h | 0 .../mips/include/asm}/pgtable-64.h | 0 .../mips/include/asm}/pgtable-bits.h | 0 .../mips/include/asm}/pgtable.h | 0 .../include/asm}/pmc-sierra/msp71xx/gpio.h | 0 .../asm}/pmc-sierra/msp71xx/msp_cic_int.h | 0 .../include/asm}/pmc-sierra/msp71xx/msp_int.h | 0 .../include/asm}/pmc-sierra/msp71xx/msp_pci.h | 0 .../asm}/pmc-sierra/msp71xx/msp_prom.h | 0 .../asm}/pmc-sierra/msp71xx/msp_regops.h | 0 .../asm}/pmc-sierra/msp71xx/msp_regs.h | 0 .../asm}/pmc-sierra/msp71xx/msp_slp_int.h | 0 .../include/asm}/pmc-sierra/msp71xx/war.h | 0 .../asm-mips => arch/mips/include/asm}/pmon.h | 0 .../asm-mips => arch/mips/include/asm}/poll.h | 0 .../mips/include/asm}/posix_types.h | 0 .../mips/include/asm}/prefetch.h | 0 .../mips/include/asm}/processor.h | 0 .../mips/include/asm}/ptrace.h | 0 .../mips/include/asm}/r4k-timer.h | 0 .../mips/include/asm}/r4kcache.h | 0 .../mips/include/asm}/reboot.h | 0 .../asm-mips => arch/mips/include/asm}/reg.h | 0 .../mips/include/asm}/regdef.h | 0 .../mips/include/asm}/resource.h | 0 .../mips/include/asm}/rm9k-ocd.h | 0 .../asm-mips => arch/mips/include/asm}/rtlx.h | 0 .../mips/include/asm}/scatterlist.h | 0 .../mips/include/asm}/seccomp.h | 0 .../mips/include/asm}/sections.h | 0 .../mips/include/asm}/segment.h | 0 .../mips/include/asm}/sembuf.h | 0 .../mips/include/asm}/serial.h | 0 .../mips/include/asm}/setup.h | 0 .../mips/include/asm}/sgi/gio.h | 0 .../mips/include/asm}/sgi/hpc3.h | 0 .../mips/include/asm}/sgi/ioc.h | 0 .../mips/include/asm}/sgi/ip22.h | 0 .../mips/include/asm}/sgi/mc.h | 0 .../mips/include/asm}/sgi/pi1.h | 0 .../mips/include/asm}/sgi/seeq.h | 0 .../mips/include/asm}/sgi/sgi.h | 0 .../mips/include/asm}/sgi/wd.h | 0 .../mips/include/asm}/sgialib.h | 0 .../mips/include/asm}/sgiarcs.h | 0 .../mips/include/asm}/sgidefs.h | 0 .../mips/include/asm}/shmbuf.h | 0 .../mips/include/asm}/shmparam.h | 0 .../mips/include/asm}/sibyte/bcm1480_int.h | 0 .../mips/include/asm}/sibyte/bcm1480_l2c.h | 0 .../mips/include/asm}/sibyte/bcm1480_mc.h | 0 .../mips/include/asm}/sibyte/bcm1480_regs.h | 0 .../mips/include/asm}/sibyte/bcm1480_scd.h | 0 .../mips/include/asm}/sibyte/bigsur.h | 0 .../mips/include/asm}/sibyte/board.h | 0 .../mips/include/asm}/sibyte/carmel.h | 0 .../mips/include/asm}/sibyte/sb1250.h | 0 .../mips/include/asm}/sibyte/sb1250_defs.h | 0 .../mips/include/asm}/sibyte/sb1250_dma.h | 0 .../mips/include/asm}/sibyte/sb1250_genbus.h | 0 .../mips/include/asm}/sibyte/sb1250_int.h | 0 .../mips/include/asm}/sibyte/sb1250_l2c.h | 0 .../mips/include/asm}/sibyte/sb1250_ldt.h | 0 .../mips/include/asm}/sibyte/sb1250_mac.h | 0 .../mips/include/asm}/sibyte/sb1250_mc.h | 0 .../mips/include/asm}/sibyte/sb1250_regs.h | 0 .../mips/include/asm}/sibyte/sb1250_scd.h | 0 .../mips/include/asm}/sibyte/sb1250_smbus.h | 0 .../mips/include/asm}/sibyte/sb1250_syncser.h | 0 .../mips/include/asm}/sibyte/sb1250_uart.h | 0 .../mips/include/asm}/sibyte/sentosa.h | 0 .../mips/include/asm}/sibyte/swarm.h | 0 .../mips/include/asm}/sigcontext.h | 0 .../mips/include/asm}/siginfo.h | 0 .../mips/include/asm}/signal.h | 0 .../asm-mips => arch/mips/include/asm}/sim.h | 0 .../mips/include/asm}/smp-ops.h | 0 .../asm-mips => arch/mips/include/asm}/smp.h | 0 .../asm-mips => arch/mips/include/asm}/smtc.h | 0 .../mips/include/asm}/smtc_ipi.h | 0 .../mips/include/asm}/smtc_proc.h | 0 .../asm-mips => arch/mips/include/asm}/smvp.h | 0 .../mips/include/asm}/sn/addrs.h | 0 .../mips/include/asm}/sn/agent.h | 0 .../mips/include/asm}/sn/arch.h | 0 .../mips/include/asm}/sn/fru.h | 0 .../mips/include/asm}/sn/gda.h | 0 .../mips/include/asm}/sn/hub.h | 0 .../mips/include/asm}/sn/intr.h | 0 .../mips/include/asm}/sn/io.h | 0 .../mips/include/asm}/sn/ioc3.h | 0 .../mips/include/asm}/sn/klconfig.h | 36 ++++---- .../mips/include/asm}/sn/kldir.h | 0 .../mips/include/asm}/sn/klkernvars.h | 0 .../mips/include/asm}/sn/launch.h | 0 .../mips/include/asm}/sn/mapped_kernel.h | 0 .../mips/include/asm}/sn/nmi.h | 0 .../mips/include/asm}/sn/sn0/addrs.h | 0 .../mips/include/asm}/sn/sn0/arch.h | 0 .../mips/include/asm}/sn/sn0/hub.h | 0 .../mips/include/asm}/sn/sn0/hubio.h | 36 ++++---- .../mips/include/asm}/sn/sn0/hubmd.h | 0 .../mips/include/asm}/sn/sn0/hubni.h | 0 .../mips/include/asm}/sn/sn0/hubpi.h | 0 .../mips/include/asm}/sn/sn0/ip27.h | 0 .../mips/include/asm}/sn/sn_private.h | 0 .../mips/include/asm}/sn/types.h | 0 .../asm-mips => arch/mips/include/asm}/sni.h | 0 .../mips/include/asm}/socket.h | 0 .../mips/include/asm}/sockios.h | 0 .../mips/include/asm}/sparsemem.h | 0 .../mips/include/asm}/spinlock.h | 0 .../mips/include/asm}/spinlock_types.h | 0 .../mips/include/asm}/stackframe.h | 0 .../mips/include/asm}/stacktrace.h | 0 .../asm-mips => arch/mips/include/asm}/stat.h | 0 .../mips/include/asm}/statfs.h | 0 .../mips/include/asm}/string.h | 0 .../mips/include/asm}/suspend.h | 0 .../mips/include/asm}/sysmips.h | 0 .../mips/include/asm}/system.h | 0 .../mips/include/asm}/termbits.h | 0 .../mips/include/asm}/termios.h | 0 .../mips/include/asm}/thread_info.h | 0 .../asm-mips => arch/mips/include/asm}/time.h | 0 .../mips/include/asm}/timex.h | 0 .../mips/include/asm}/titan_dep.h | 0 .../asm-mips => arch/mips/include/asm}/tlb.h | 0 .../mips/include/asm}/tlbdebug.h | 0 .../mips/include/asm}/tlbflush.h | 0 .../mips/include/asm}/topology.h | 0 .../mips/include/asm}/traps.h | 0 .../mips/include/asm}/txx9/boards.h | 0 .../mips/include/asm}/txx9/generic.h | 0 .../mips/include/asm}/txx9/jmr3927.h | 0 .../mips/include/asm}/txx9/pci.h | 0 .../mips/include/asm}/txx9/rbtx4927.h | 0 .../mips/include/asm}/txx9/rbtx4938.h | 0 .../mips/include/asm}/txx9/rbtx4939.h | 0 .../mips/include/asm}/txx9/smsc_fdc37m81x.h | 0 .../mips/include/asm}/txx9/spi.h | 0 .../mips/include/asm}/txx9/tx3927.h | 0 .../mips/include/asm}/txx9/tx4927.h | 0 .../mips/include/asm}/txx9/tx4927pcic.h | 0 .../mips/include/asm}/txx9/tx4938.h | 0 .../mips/include/asm}/txx9/tx4939.h | 0 .../mips/include/asm}/txx9irq.h | 0 .../mips/include/asm}/txx9pio.h | 0 .../mips/include/asm}/txx9tmr.h | 0 .../mips/include/asm}/types.h | 0 .../mips/include/asm}/uaccess.h | 0 .../mips/include/asm}/ucontext.h | 0 .../mips/include/asm}/unaligned.h | 0 .../mips/include/asm}/unistd.h | 0 .../asm-mips => arch/mips/include/asm}/user.h | 0 .../asm-mips => arch/mips/include/asm}/vga.h | 0 .../asm-mips => arch/mips/include/asm}/vpe.h | 0 .../mips/include/asm}/vr41xx/capcella.h | 0 .../mips/include/asm}/vr41xx/giu.h | 0 .../mips/include/asm}/vr41xx/irq.h | 0 .../mips/include/asm}/vr41xx/mpc30x.h | 0 .../mips/include/asm}/vr41xx/pci.h | 0 .../mips/include/asm}/vr41xx/siu.h | 0 .../mips/include/asm}/vr41xx/tb0219.h | 0 .../mips/include/asm}/vr41xx/tb0226.h | 0 .../mips/include/asm}/vr41xx/tb0287.h | 0 .../mips/include/asm}/vr41xx/vr41xx.h | 0 .../asm-mips => arch/mips/include/asm}/war.h | 0 .../mips/include/asm}/wbflush.h | 0 .../asm-mips => arch/mips/include/asm}/xor.h | 0 .../mips/include/asm}/xtalk/xtalk.h | 0 .../mips/include/asm}/xtalk/xwidget.h | 0 463 files changed, 82 insertions(+), 82 deletions(-) rename {include/asm-mips => arch/mips/include/asm}/Kbuild (100%) rename {include/asm-mips => arch/mips/include/asm}/a.out.h (100%) rename {include/asm-mips => arch/mips/include/asm}/abi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/addrspace.h (100%) rename {include/asm-mips => arch/mips/include/asm}/asm.h (100%) rename {include/asm-mips => arch/mips/include/asm}/asmmacro-32.h (100%) rename {include/asm-mips => arch/mips/include/asm}/asmmacro-64.h (100%) rename {include/asm-mips => arch/mips/include/asm}/asmmacro.h (100%) rename {include/asm-mips => arch/mips/include/asm}/atomic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/auxvec.h (100%) rename {include/asm-mips => arch/mips/include/asm}/barrier.h (100%) rename {include/asm-mips => arch/mips/include/asm}/bcache.h (100%) rename {include/asm-mips => arch/mips/include/asm}/bitops.h (100%) rename {include/asm-mips => arch/mips/include/asm}/bootinfo.h (100%) rename {include/asm-mips => arch/mips/include/asm}/branch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/break.h (100%) rename {include/asm-mips => arch/mips/include/asm}/bug.h (100%) rename {include/asm-mips => arch/mips/include/asm}/bugs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/byteorder.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cache.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cachectl.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cacheflush.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cacheops.h (100%) rename {include/asm-mips => arch/mips/include/asm}/checksum.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cmp.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cmpxchg.h (100%) rename {include/asm-mips => arch/mips/include/asm}/compat-signal.h (100%) rename {include/asm-mips => arch/mips/include/asm}/compat.h (100%) rename {include/asm-mips => arch/mips/include/asm}/compiler.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cpu-features.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cpu-info.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cpu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/cputime.h (100%) rename {include/asm-mips => arch/mips/include/asm}/current.h (100%) rename {include/asm-mips => arch/mips/include/asm}/debug.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/ecc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/interrupts.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/ioasic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/ioasic_addrs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/ioasic_ints.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn01.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn02.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn02ba.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn02ca.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn02xa.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn03.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn05.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/kn230.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/machtype.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/prom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dec/system.h (100%) rename {include/asm-mips => arch/mips/include/asm}/delay.h (100%) rename {include/asm-mips => arch/mips/include/asm}/device.h (100%) rename {include/asm-mips => arch/mips/include/asm}/div64.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dma-mapping.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ds1286.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ds1287.h (100%) rename {include/asm-mips => arch/mips/include/asm}/dsp.h (100%) rename {include/asm-mips => arch/mips/include/asm}/edac.h (100%) rename {include/asm-mips => arch/mips/include/asm}/elf.h (100%) rename {include/asm-mips => arch/mips/include/asm}/emergency-restart.h (100%) rename {include/asm-mips => arch/mips/include/asm}/emma2rh/emma2rh.h (100%) rename {include/asm-mips => arch/mips/include/asm}/emma2rh/markeins.h (100%) rename {include/asm-mips => arch/mips/include/asm}/errno.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fcntl.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fixmap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/floppy.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fpregdef.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fpu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fpu_emulator.h (100%) rename {include/asm-mips => arch/mips/include/asm}/futex.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fw/arc/hinv.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fw/arc/types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fw/cfe/cfe_api.h (100%) rename {include/asm-mips => arch/mips/include/asm}/fw/cfe/cfe_error.h (100%) rename {include/asm-mips => arch/mips/include/asm}/gcmpregs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/gic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/gt64120.h (100%) rename {include/asm-mips => arch/mips/include/asm}/hardirq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/hazards.h (100%) rename {include/asm-mips => arch/mips/include/asm}/highmem.h (100%) rename {include/asm-mips => arch/mips/include/asm}/hw_irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/i8253.h (100%) rename {include/asm-mips => arch/mips/include/asm}/i8259.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ide.h (100%) rename {include/asm-mips => arch/mips/include/asm}/inst.h (100%) rename {include/asm-mips => arch/mips/include/asm}/io.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ioctl.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ioctls.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ip32/crime.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ip32/ip32_ints.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ip32/mace.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ipcbuf.h (100%) rename {include/asm-mips => arch/mips/include/asm}/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/irq_cpu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/irq_gt641xx.h (100%) rename {include/asm-mips => arch/mips/include/asm}/irq_regs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/irqflags.h (100%) rename {include/asm-mips => arch/mips/include/asm}/isadep.h (100%) rename {include/asm-mips => arch/mips/include/asm}/jazz.h (100%) rename {include/asm-mips => arch/mips/include/asm}/jazzdma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/kdebug.h (100%) rename {include/asm-mips => arch/mips/include/asm}/kexec.h (100%) rename {include/asm-mips => arch/mips/include/asm}/kgdb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/kmap_types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/kspd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/ds1603.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/eeprom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/head.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/lasat.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/lasatint.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/picvue.h (100%) rename {include/asm-mips => arch/mips/include/asm}/lasat/serial.h (100%) rename {include/asm-mips => arch/mips/include/asm}/linkage.h (100%) rename {include/asm-mips => arch/mips/include/asm}/local.h (100%) rename {include/asm-mips => arch/mips/include/asm}/m48t35.h (100%) rename {include/asm-mips => arch/mips/include/asm}/m48t37.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1000.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1000_dma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1000_gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1100_mmc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1550_spi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1xxx.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1xxx_dbdma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1xxx_ide.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/au1xxx_psc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/ioremap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/prom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-au1x00/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-bcm47xx/bcm47xx.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-bcm47xx/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-bcm47xx/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-cobalt/cobalt.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-cobalt/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-cobalt/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-cobalt/mach-gt64120.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-cobalt/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-db1x00/db1200.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-db1x00/db1x00.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-dec/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-dec/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-emma2rh/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-emma2rh/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/excite.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/excite_fpga.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/excite_nandflash.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/rm9k_eth.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/rm9k_wdt.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/rm9k_xicap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-excite/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/dma-coherence.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/floppy.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/ide.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/ioremap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/kernel-entry-init.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/kmalloc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/mangle-port.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/spaces.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-generic/topology.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip22/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip22/ds1286.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip22/spaces.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip22/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/dma-coherence.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/kernel-entry-init.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/kmalloc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/mangle-port.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/mmzone.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/spaces.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/topology.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip27/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip28/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip28/ds1286.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip28/spaces.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip28/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/dma-coherence.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/kmalloc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/mangle-port.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-ip32/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-jazz/dma-coherence.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-jazz/floppy.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-jazz/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-jazz/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lasat/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lasat/mach-gt64120.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lasat/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lemote/dma-coherence.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lemote/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-lemote/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/kernel-entry-init.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/mach-gt64120.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-malta/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-mipssim/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-mipssim/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/pb1000.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/pb1100.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/pb1200.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/pb1500.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pb1x00/pb1550.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/cm.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/glb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/kernel-entry-init.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/nand.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/uart.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/usb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-pnx8550/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/ddr.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/dma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/dma_v.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/eth.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/integ.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/prom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/rb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/rc32434.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/timer.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rc32434/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rm/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rm/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-rm/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-sibyte/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-sibyte/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx39xx/ioremap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx39xx/mangle-port.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx39xx/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx49xx/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx49xx/ioremap.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx49xx/kmalloc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-tx49xx/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-vr41xx/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-vr41xx/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-wrppmc/mach-gt64120.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-wrppmc/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-yosemite/cpu-feature-overrides.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mach-yosemite/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mc146818-time.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mc146818rtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/bonito64.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/generic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/launch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/malta.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/maltaint.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/msc01_pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/piix4.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/prom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/sim.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips-boards/simint.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mips_mt.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mipsmtregs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mipsprom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mipsregs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mman.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mmu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mmu_context.h (97%) rename {include/asm-mips => arch/mips/include/asm}/mmzone.h (100%) rename {include/asm-mips => arch/mips/include/asm}/module.h (100%) rename {include/asm-mips => arch/mips/include/asm}/msc01_ic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/msgbuf.h (100%) rename {include/asm-mips => arch/mips/include/asm}/mutex.h (100%) rename {include/asm-mips => arch/mips/include/asm}/nile4.h (100%) rename {include/asm-mips => arch/mips/include/asm}/paccess.h (100%) rename {include/asm-mips => arch/mips/include/asm}/page.h (100%) rename {include/asm-mips => arch/mips/include/asm}/param.h (100%) rename {include/asm-mips => arch/mips/include/asm}/parport.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pci/bridge.h (100%) rename {include/asm-mips => arch/mips/include/asm}/percpu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pgalloc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pgtable-32.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pgtable-64.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pgtable-bits.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pgtable.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/gpio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_cic_int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_prom.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_regops.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_regs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/msp_slp_int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmc-sierra/msp71xx/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/pmon.h (100%) rename {include/asm-mips => arch/mips/include/asm}/poll.h (100%) rename {include/asm-mips => arch/mips/include/asm}/posix_types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/prefetch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/processor.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ptrace.h (100%) rename {include/asm-mips => arch/mips/include/asm}/r4k-timer.h (100%) rename {include/asm-mips => arch/mips/include/asm}/r4kcache.h (100%) rename {include/asm-mips => arch/mips/include/asm}/reboot.h (100%) rename {include/asm-mips => arch/mips/include/asm}/reg.h (100%) rename {include/asm-mips => arch/mips/include/asm}/regdef.h (100%) rename {include/asm-mips => arch/mips/include/asm}/resource.h (100%) rename {include/asm-mips => arch/mips/include/asm}/rm9k-ocd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/rtlx.h (100%) rename {include/asm-mips => arch/mips/include/asm}/scatterlist.h (100%) rename {include/asm-mips => arch/mips/include/asm}/seccomp.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sections.h (100%) rename {include/asm-mips => arch/mips/include/asm}/segment.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sembuf.h (100%) rename {include/asm-mips => arch/mips/include/asm}/serial.h (100%) rename {include/asm-mips => arch/mips/include/asm}/setup.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/gio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/hpc3.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/ioc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/ip22.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/mc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/pi1.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/seeq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/sgi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgi/wd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgialib.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgiarcs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sgidefs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/shmbuf.h (100%) rename {include/asm-mips => arch/mips/include/asm}/shmparam.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bcm1480_int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bcm1480_l2c.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bcm1480_mc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bcm1480_regs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bcm1480_scd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/bigsur.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/board.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/carmel.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_defs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_dma.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_genbus.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_int.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_l2c.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_ldt.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_mac.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_mc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_regs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_scd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_smbus.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_syncser.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sb1250_uart.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/sentosa.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sibyte/swarm.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sigcontext.h (100%) rename {include/asm-mips => arch/mips/include/asm}/siginfo.h (100%) rename {include/asm-mips => arch/mips/include/asm}/signal.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sim.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smp-ops.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smp.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smtc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smtc_ipi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smtc_proc.h (100%) rename {include/asm-mips => arch/mips/include/asm}/smvp.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/addrs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/agent.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/arch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/fru.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/gda.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/hub.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/intr.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/io.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/ioc3.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/klconfig.h (96%) rename {include/asm-mips => arch/mips/include/asm}/sn/kldir.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/klkernvars.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/launch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/mapped_kernel.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/nmi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/addrs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/arch.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/hub.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/hubio.h (96%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/hubmd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/hubni.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/hubpi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn0/ip27.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/sn_private.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sn/types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sni.h (100%) rename {include/asm-mips => arch/mips/include/asm}/socket.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sockios.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sparsemem.h (100%) rename {include/asm-mips => arch/mips/include/asm}/spinlock.h (100%) rename {include/asm-mips => arch/mips/include/asm}/spinlock_types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/stackframe.h (100%) rename {include/asm-mips => arch/mips/include/asm}/stacktrace.h (100%) rename {include/asm-mips => arch/mips/include/asm}/stat.h (100%) rename {include/asm-mips => arch/mips/include/asm}/statfs.h (100%) rename {include/asm-mips => arch/mips/include/asm}/string.h (100%) rename {include/asm-mips => arch/mips/include/asm}/suspend.h (100%) rename {include/asm-mips => arch/mips/include/asm}/sysmips.h (100%) rename {include/asm-mips => arch/mips/include/asm}/system.h (100%) rename {include/asm-mips => arch/mips/include/asm}/termbits.h (100%) rename {include/asm-mips => arch/mips/include/asm}/termios.h (100%) rename {include/asm-mips => arch/mips/include/asm}/thread_info.h (100%) rename {include/asm-mips => arch/mips/include/asm}/time.h (100%) rename {include/asm-mips => arch/mips/include/asm}/timex.h (100%) rename {include/asm-mips => arch/mips/include/asm}/titan_dep.h (100%) rename {include/asm-mips => arch/mips/include/asm}/tlb.h (100%) rename {include/asm-mips => arch/mips/include/asm}/tlbdebug.h (100%) rename {include/asm-mips => arch/mips/include/asm}/tlbflush.h (100%) rename {include/asm-mips => arch/mips/include/asm}/topology.h (100%) rename {include/asm-mips => arch/mips/include/asm}/traps.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/boards.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/generic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/jmr3927.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/rbtx4927.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/rbtx4938.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/rbtx4939.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/smsc_fdc37m81x.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/spi.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/tx3927.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/tx4927.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/tx4927pcic.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/tx4938.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9/tx4939.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9pio.h (100%) rename {include/asm-mips => arch/mips/include/asm}/txx9tmr.h (100%) rename {include/asm-mips => arch/mips/include/asm}/types.h (100%) rename {include/asm-mips => arch/mips/include/asm}/uaccess.h (100%) rename {include/asm-mips => arch/mips/include/asm}/ucontext.h (100%) rename {include/asm-mips => arch/mips/include/asm}/unaligned.h (100%) rename {include/asm-mips => arch/mips/include/asm}/unistd.h (100%) rename {include/asm-mips => arch/mips/include/asm}/user.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vga.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vpe.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/capcella.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/giu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/irq.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/mpc30x.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/pci.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/siu.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/tb0219.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/tb0226.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/tb0287.h (100%) rename {include/asm-mips => arch/mips/include/asm}/vr41xx/vr41xx.h (100%) rename {include/asm-mips => arch/mips/include/asm}/war.h (100%) rename {include/asm-mips => arch/mips/include/asm}/wbflush.h (100%) rename {include/asm-mips => arch/mips/include/asm}/xor.h (100%) rename {include/asm-mips => arch/mips/include/asm}/xtalk/xtalk.h (100%) rename {include/asm-mips => arch/mips/include/asm}/xtalk/xwidget.h (100%) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4401a0c1278..7f39fd8a91f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -170,97 +170,97 @@ libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz +cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # # Common Alchemy Au1x00 stuff # core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ -cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 +cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 # # AMD Alchemy Pb1000 eval board # libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/ -cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 # # AMD Alchemy Pb1100 eval board # libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/ -cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 # # AMD Alchemy Pb1500 eval board # libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/ -cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 # # AMD Alchemy Pb1550 eval board # libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/ -cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/ -cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 +cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # AMD Alchemy Db1000 eval board # libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # # AMD Alchemy Db1100 eval board # libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 # # AMD Alchemy Db1500 eval board # libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 # # AMD Alchemy Db1550 eval board # libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/ -cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # AMD Alchemy Bosporus eval board # libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 # # AMD Alchemy Mirage eval board # libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/ -cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 +cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # @@ -279,14 +279,14 @@ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # Cobalt Server # core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -cflags-$(CONFIG_MIPS_COBALT) += -Iinclude/asm-mips/mach-cobalt +cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 # # DECstation family # core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ -cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec +cflags-$(CONFIG_MACH_DECSTATION)+= -I$(srctree)/arch/mips/include/asm/mach-dec libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 @@ -294,7 +294,7 @@ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 # Wind River PPMC Board (4KC + GT64120) # core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ -cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc +cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # @@ -302,13 +302,13 @@ load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/ load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000 -cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote +cflags-$(CONFIG_LEMOTE_FULONG) += -I$(srctree)/arch/mips/include/asm/mach-lemote # # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ -cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-malta +cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 all-$(CONFIG_MIPS_MALTA) := vmlinux.bin @@ -316,14 +316,14 @@ all-$(CONFIG_MIPS_MALTA) := vmlinux.bin # MIPS SIM # core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ -cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-mipssim +cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim load-$(CONFIG_MIPS_SIM) += 0x80100000 # # PMC-Sierra MSP SOCs # core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ -cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \ +cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ -mno-branch-likely load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 @@ -331,28 +331,28 @@ load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 # PMC-Sierra Yosemite # core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ -cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite +cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 # # Basler eXcite # core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ -cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite +cflags-$(CONFIG_BASLER_EXCITE) += -I$(srctree)/arch/mips/include/asm/mach-excite load-$(CONFIG_BASLER_EXCITE) += 0x80100000 # # LASAT platforms # core-$(CONFIG_LASAT) += arch/mips/lasat/ -cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat +cflags-$(CONFIG_LASAT) += -I$(srctree)/arch/mips/include/asm/mach-lasat load-$(CONFIG_LASAT) += 0xffffffff80000000 # # Common VR41xx # core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ -cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx +cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx # # ZAO Networks Capcella (VR4131) @@ -385,13 +385,13 @@ load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 # Common NXP PNX8550 # core-$(CONFIG_SOC_PNX8550) += arch/mips/nxp/pnx8550/common/ -cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550 +cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 # # NXP PNX8550 JBS board # libs-$(CONFIG_PNX8550_JBS) += arch/mips/nxp/pnx8550/jbs/ -#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550 +#cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 # NXP PNX8550 STB810 board @@ -402,7 +402,7 @@ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 # NEC EMMA2RH boards # core-$(CONFIG_EMMA2RH) += arch/mips/emma2rh/common/ -cflags-$(CONFIG_EMMA2RH) += -Iinclude/asm-mips/mach-emma2rh +cflags-$(CONFIG_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh # NEC EMMA2RH Mark-eins core-$(CONFIG_MARKEINS) += arch/mips/emma2rh/markeins/ @@ -418,7 +418,7 @@ load-$(CONFIG_MARKEINS) += 0xffffffff88100000 # address by 8kb. # core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22 +cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 ifdef CONFIG_32BIT load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 endif @@ -435,7 +435,7 @@ endif # ifdef CONFIG_SGI_IP27 core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ -cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 +cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 ifdef CONFIG_MAPPED_KERNEL load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 @@ -460,7 +460,7 @@ ifdef CONFIG_SGI_IP28 endif endif core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -Iinclude/asm-mips/mach-ip28 +cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -I$(srctree)/arch/mips/include/asm/mach-ip28 load-$(CONFIG_SGI_IP28) += 0xa800000020004000 # @@ -472,7 +472,7 @@ load-$(CONFIG_SGI_IP28) += 0xa800000020004000 # will break. # core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 +cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # @@ -484,22 +484,22 @@ load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM112X) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_SB1250) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x55) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM1x55) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x80) += -Iinclude/asm-mips/mach-sibyte \ +cflags-$(CONFIG_SIBYTE_BCM1x80) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL # @@ -529,14 +529,14 @@ load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 # Broadcom BCM47XX boards # core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/ -cflags-$(CONFIG_BCM47XX) += -Iinclude/asm-mips/mach-bcm47xx +cflags-$(CONFIG_BCM47XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm47xx load-$(CONFIG_BCM47XX) := 0xffffffff80001000 # # SNI RM # core-$(CONFIG_SNI_RM) += arch/mips/sni/ -cflags-$(CONFIG_SNI_RM) += -Iinclude/asm-mips/mach-rm +cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm ifdef CONFIG_CPU_LITTLE_ENDIAN load-$(CONFIG_SNI_RM) += 0xffffffff80600000 else @@ -548,10 +548,10 @@ all-$(CONFIG_SNI_RM) := vmlinux.ecoff # Common TXx9 # core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX39XX) += -Iinclude/asm-mips/mach-tx39xx +cflags-$(CONFIG_MACH_TX39XX) += -I$(srctree)/arch/mips/include/asm/mach-tx39xx load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 core-$(CONFIG_MACH_TX49XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX49XX) += -Iinclude/asm-mips/mach-tx49xx +cflags-$(CONFIG_MACH_TX49XX) += -I$(srctree)/arch/mips/include/asm/mach-tx49xx load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 # @@ -563,7 +563,7 @@ core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/ # Routerboard 532 board # core-$(CONFIG_MIKROTIK_RB532) += arch/mips/rb532/ -cflags-$(CONFIG_MIKROTIK_RB532) += -Iinclude/asm-mips/mach-rc32434 +cflags-$(CONFIG_MIKROTIK_RB532) += -I$(srctree)/arch/mips/include/asm/mach-rc32434 load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 # @@ -573,7 +573,7 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ -cflags-y += -Iinclude/asm-mips/mach-generic +cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ ifdef CONFIG_32BIT diff --git a/include/asm-mips/Kbuild b/arch/mips/include/asm/Kbuild similarity index 100% rename from include/asm-mips/Kbuild rename to arch/mips/include/asm/Kbuild diff --git a/include/asm-mips/a.out.h b/arch/mips/include/asm/a.out.h similarity index 100% rename from include/asm-mips/a.out.h rename to arch/mips/include/asm/a.out.h diff --git a/include/asm-mips/abi.h b/arch/mips/include/asm/abi.h similarity index 100% rename from include/asm-mips/abi.h rename to arch/mips/include/asm/abi.h diff --git a/include/asm-mips/addrspace.h b/arch/mips/include/asm/addrspace.h similarity index 100% rename from include/asm-mips/addrspace.h rename to arch/mips/include/asm/addrspace.h diff --git a/include/asm-mips/asm.h b/arch/mips/include/asm/asm.h similarity index 100% rename from include/asm-mips/asm.h rename to arch/mips/include/asm/asm.h diff --git a/include/asm-mips/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h similarity index 100% rename from include/asm-mips/asmmacro-32.h rename to arch/mips/include/asm/asmmacro-32.h diff --git a/include/asm-mips/asmmacro-64.h b/arch/mips/include/asm/asmmacro-64.h similarity index 100% rename from include/asm-mips/asmmacro-64.h rename to arch/mips/include/asm/asmmacro-64.h diff --git a/include/asm-mips/asmmacro.h b/arch/mips/include/asm/asmmacro.h similarity index 100% rename from include/asm-mips/asmmacro.h rename to arch/mips/include/asm/asmmacro.h diff --git a/include/asm-mips/atomic.h b/arch/mips/include/asm/atomic.h similarity index 100% rename from include/asm-mips/atomic.h rename to arch/mips/include/asm/atomic.h diff --git a/include/asm-mips/auxvec.h b/arch/mips/include/asm/auxvec.h similarity index 100% rename from include/asm-mips/auxvec.h rename to arch/mips/include/asm/auxvec.h diff --git a/include/asm-mips/barrier.h b/arch/mips/include/asm/barrier.h similarity index 100% rename from include/asm-mips/barrier.h rename to arch/mips/include/asm/barrier.h diff --git a/include/asm-mips/bcache.h b/arch/mips/include/asm/bcache.h similarity index 100% rename from include/asm-mips/bcache.h rename to arch/mips/include/asm/bcache.h diff --git a/include/asm-mips/bitops.h b/arch/mips/include/asm/bitops.h similarity index 100% rename from include/asm-mips/bitops.h rename to arch/mips/include/asm/bitops.h diff --git a/include/asm-mips/bootinfo.h b/arch/mips/include/asm/bootinfo.h similarity index 100% rename from include/asm-mips/bootinfo.h rename to arch/mips/include/asm/bootinfo.h diff --git a/include/asm-mips/branch.h b/arch/mips/include/asm/branch.h similarity index 100% rename from include/asm-mips/branch.h rename to arch/mips/include/asm/branch.h diff --git a/include/asm-mips/break.h b/arch/mips/include/asm/break.h similarity index 100% rename from include/asm-mips/break.h rename to arch/mips/include/asm/break.h diff --git a/include/asm-mips/bug.h b/arch/mips/include/asm/bug.h similarity index 100% rename from include/asm-mips/bug.h rename to arch/mips/include/asm/bug.h diff --git a/include/asm-mips/bugs.h b/arch/mips/include/asm/bugs.h similarity index 100% rename from include/asm-mips/bugs.h rename to arch/mips/include/asm/bugs.h diff --git a/include/asm-mips/byteorder.h b/arch/mips/include/asm/byteorder.h similarity index 100% rename from include/asm-mips/byteorder.h rename to arch/mips/include/asm/byteorder.h diff --git a/include/asm-mips/cache.h b/arch/mips/include/asm/cache.h similarity index 100% rename from include/asm-mips/cache.h rename to arch/mips/include/asm/cache.h diff --git a/include/asm-mips/cachectl.h b/arch/mips/include/asm/cachectl.h similarity index 100% rename from include/asm-mips/cachectl.h rename to arch/mips/include/asm/cachectl.h diff --git a/include/asm-mips/cacheflush.h b/arch/mips/include/asm/cacheflush.h similarity index 100% rename from include/asm-mips/cacheflush.h rename to arch/mips/include/asm/cacheflush.h diff --git a/include/asm-mips/cacheops.h b/arch/mips/include/asm/cacheops.h similarity index 100% rename from include/asm-mips/cacheops.h rename to arch/mips/include/asm/cacheops.h diff --git a/include/asm-mips/checksum.h b/arch/mips/include/asm/checksum.h similarity index 100% rename from include/asm-mips/checksum.h rename to arch/mips/include/asm/checksum.h diff --git a/include/asm-mips/cmp.h b/arch/mips/include/asm/cmp.h similarity index 100% rename from include/asm-mips/cmp.h rename to arch/mips/include/asm/cmp.h diff --git a/include/asm-mips/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h similarity index 100% rename from include/asm-mips/cmpxchg.h rename to arch/mips/include/asm/cmpxchg.h diff --git a/include/asm-mips/compat-signal.h b/arch/mips/include/asm/compat-signal.h similarity index 100% rename from include/asm-mips/compat-signal.h rename to arch/mips/include/asm/compat-signal.h diff --git a/include/asm-mips/compat.h b/arch/mips/include/asm/compat.h similarity index 100% rename from include/asm-mips/compat.h rename to arch/mips/include/asm/compat.h diff --git a/include/asm-mips/compiler.h b/arch/mips/include/asm/compiler.h similarity index 100% rename from include/asm-mips/compiler.h rename to arch/mips/include/asm/compiler.h diff --git a/include/asm-mips/cpu-features.h b/arch/mips/include/asm/cpu-features.h similarity index 100% rename from include/asm-mips/cpu-features.h rename to arch/mips/include/asm/cpu-features.h diff --git a/include/asm-mips/cpu-info.h b/arch/mips/include/asm/cpu-info.h similarity index 100% rename from include/asm-mips/cpu-info.h rename to arch/mips/include/asm/cpu-info.h diff --git a/include/asm-mips/cpu.h b/arch/mips/include/asm/cpu.h similarity index 100% rename from include/asm-mips/cpu.h rename to arch/mips/include/asm/cpu.h diff --git a/include/asm-mips/cputime.h b/arch/mips/include/asm/cputime.h similarity index 100% rename from include/asm-mips/cputime.h rename to arch/mips/include/asm/cputime.h diff --git a/include/asm-mips/current.h b/arch/mips/include/asm/current.h similarity index 100% rename from include/asm-mips/current.h rename to arch/mips/include/asm/current.h diff --git a/include/asm-mips/debug.h b/arch/mips/include/asm/debug.h similarity index 100% rename from include/asm-mips/debug.h rename to arch/mips/include/asm/debug.h diff --git a/include/asm-mips/dec/ecc.h b/arch/mips/include/asm/dec/ecc.h similarity index 100% rename from include/asm-mips/dec/ecc.h rename to arch/mips/include/asm/dec/ecc.h diff --git a/include/asm-mips/dec/interrupts.h b/arch/mips/include/asm/dec/interrupts.h similarity index 100% rename from include/asm-mips/dec/interrupts.h rename to arch/mips/include/asm/dec/interrupts.h diff --git a/include/asm-mips/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h similarity index 100% rename from include/asm-mips/dec/ioasic.h rename to arch/mips/include/asm/dec/ioasic.h diff --git a/include/asm-mips/dec/ioasic_addrs.h b/arch/mips/include/asm/dec/ioasic_addrs.h similarity index 100% rename from include/asm-mips/dec/ioasic_addrs.h rename to arch/mips/include/asm/dec/ioasic_addrs.h diff --git a/include/asm-mips/dec/ioasic_ints.h b/arch/mips/include/asm/dec/ioasic_ints.h similarity index 100% rename from include/asm-mips/dec/ioasic_ints.h rename to arch/mips/include/asm/dec/ioasic_ints.h diff --git a/include/asm-mips/dec/kn01.h b/arch/mips/include/asm/dec/kn01.h similarity index 100% rename from include/asm-mips/dec/kn01.h rename to arch/mips/include/asm/dec/kn01.h diff --git a/include/asm-mips/dec/kn02.h b/arch/mips/include/asm/dec/kn02.h similarity index 100% rename from include/asm-mips/dec/kn02.h rename to arch/mips/include/asm/dec/kn02.h diff --git a/include/asm-mips/dec/kn02ba.h b/arch/mips/include/asm/dec/kn02ba.h similarity index 100% rename from include/asm-mips/dec/kn02ba.h rename to arch/mips/include/asm/dec/kn02ba.h diff --git a/include/asm-mips/dec/kn02ca.h b/arch/mips/include/asm/dec/kn02ca.h similarity index 100% rename from include/asm-mips/dec/kn02ca.h rename to arch/mips/include/asm/dec/kn02ca.h diff --git a/include/asm-mips/dec/kn02xa.h b/arch/mips/include/asm/dec/kn02xa.h similarity index 100% rename from include/asm-mips/dec/kn02xa.h rename to arch/mips/include/asm/dec/kn02xa.h diff --git a/include/asm-mips/dec/kn03.h b/arch/mips/include/asm/dec/kn03.h similarity index 100% rename from include/asm-mips/dec/kn03.h rename to arch/mips/include/asm/dec/kn03.h diff --git a/include/asm-mips/dec/kn05.h b/arch/mips/include/asm/dec/kn05.h similarity index 100% rename from include/asm-mips/dec/kn05.h rename to arch/mips/include/asm/dec/kn05.h diff --git a/include/asm-mips/dec/kn230.h b/arch/mips/include/asm/dec/kn230.h similarity index 100% rename from include/asm-mips/dec/kn230.h rename to arch/mips/include/asm/dec/kn230.h diff --git a/include/asm-mips/dec/machtype.h b/arch/mips/include/asm/dec/machtype.h similarity index 100% rename from include/asm-mips/dec/machtype.h rename to arch/mips/include/asm/dec/machtype.h diff --git a/include/asm-mips/dec/prom.h b/arch/mips/include/asm/dec/prom.h similarity index 100% rename from include/asm-mips/dec/prom.h rename to arch/mips/include/asm/dec/prom.h diff --git a/include/asm-mips/dec/system.h b/arch/mips/include/asm/dec/system.h similarity index 100% rename from include/asm-mips/dec/system.h rename to arch/mips/include/asm/dec/system.h diff --git a/include/asm-mips/delay.h b/arch/mips/include/asm/delay.h similarity index 100% rename from include/asm-mips/delay.h rename to arch/mips/include/asm/delay.h diff --git a/include/asm-mips/device.h b/arch/mips/include/asm/device.h similarity index 100% rename from include/asm-mips/device.h rename to arch/mips/include/asm/device.h diff --git a/include/asm-mips/div64.h b/arch/mips/include/asm/div64.h similarity index 100% rename from include/asm-mips/div64.h rename to arch/mips/include/asm/div64.h diff --git a/include/asm-mips/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h similarity index 100% rename from include/asm-mips/dma-mapping.h rename to arch/mips/include/asm/dma-mapping.h diff --git a/include/asm-mips/dma.h b/arch/mips/include/asm/dma.h similarity index 100% rename from include/asm-mips/dma.h rename to arch/mips/include/asm/dma.h diff --git a/include/asm-mips/ds1286.h b/arch/mips/include/asm/ds1286.h similarity index 100% rename from include/asm-mips/ds1286.h rename to arch/mips/include/asm/ds1286.h diff --git a/include/asm-mips/ds1287.h b/arch/mips/include/asm/ds1287.h similarity index 100% rename from include/asm-mips/ds1287.h rename to arch/mips/include/asm/ds1287.h diff --git a/include/asm-mips/dsp.h b/arch/mips/include/asm/dsp.h similarity index 100% rename from include/asm-mips/dsp.h rename to arch/mips/include/asm/dsp.h diff --git a/include/asm-mips/edac.h b/arch/mips/include/asm/edac.h similarity index 100% rename from include/asm-mips/edac.h rename to arch/mips/include/asm/edac.h diff --git a/include/asm-mips/elf.h b/arch/mips/include/asm/elf.h similarity index 100% rename from include/asm-mips/elf.h rename to arch/mips/include/asm/elf.h diff --git a/include/asm-mips/emergency-restart.h b/arch/mips/include/asm/emergency-restart.h similarity index 100% rename from include/asm-mips/emergency-restart.h rename to arch/mips/include/asm/emergency-restart.h diff --git a/include/asm-mips/emma2rh/emma2rh.h b/arch/mips/include/asm/emma2rh/emma2rh.h similarity index 100% rename from include/asm-mips/emma2rh/emma2rh.h rename to arch/mips/include/asm/emma2rh/emma2rh.h diff --git a/include/asm-mips/emma2rh/markeins.h b/arch/mips/include/asm/emma2rh/markeins.h similarity index 100% rename from include/asm-mips/emma2rh/markeins.h rename to arch/mips/include/asm/emma2rh/markeins.h diff --git a/include/asm-mips/errno.h b/arch/mips/include/asm/errno.h similarity index 100% rename from include/asm-mips/errno.h rename to arch/mips/include/asm/errno.h diff --git a/include/asm-mips/fb.h b/arch/mips/include/asm/fb.h similarity index 100% rename from include/asm-mips/fb.h rename to arch/mips/include/asm/fb.h diff --git a/include/asm-mips/fcntl.h b/arch/mips/include/asm/fcntl.h similarity index 100% rename from include/asm-mips/fcntl.h rename to arch/mips/include/asm/fcntl.h diff --git a/include/asm-mips/fixmap.h b/arch/mips/include/asm/fixmap.h similarity index 100% rename from include/asm-mips/fixmap.h rename to arch/mips/include/asm/fixmap.h diff --git a/include/asm-mips/floppy.h b/arch/mips/include/asm/floppy.h similarity index 100% rename from include/asm-mips/floppy.h rename to arch/mips/include/asm/floppy.h diff --git a/include/asm-mips/fpregdef.h b/arch/mips/include/asm/fpregdef.h similarity index 100% rename from include/asm-mips/fpregdef.h rename to arch/mips/include/asm/fpregdef.h diff --git a/include/asm-mips/fpu.h b/arch/mips/include/asm/fpu.h similarity index 100% rename from include/asm-mips/fpu.h rename to arch/mips/include/asm/fpu.h diff --git a/include/asm-mips/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h similarity index 100% rename from include/asm-mips/fpu_emulator.h rename to arch/mips/include/asm/fpu_emulator.h diff --git a/include/asm-mips/futex.h b/arch/mips/include/asm/futex.h similarity index 100% rename from include/asm-mips/futex.h rename to arch/mips/include/asm/futex.h diff --git a/include/asm-mips/fw/arc/hinv.h b/arch/mips/include/asm/fw/arc/hinv.h similarity index 100% rename from include/asm-mips/fw/arc/hinv.h rename to arch/mips/include/asm/fw/arc/hinv.h diff --git a/include/asm-mips/fw/arc/types.h b/arch/mips/include/asm/fw/arc/types.h similarity index 100% rename from include/asm-mips/fw/arc/types.h rename to arch/mips/include/asm/fw/arc/types.h diff --git a/include/asm-mips/fw/cfe/cfe_api.h b/arch/mips/include/asm/fw/cfe/cfe_api.h similarity index 100% rename from include/asm-mips/fw/cfe/cfe_api.h rename to arch/mips/include/asm/fw/cfe/cfe_api.h diff --git a/include/asm-mips/fw/cfe/cfe_error.h b/arch/mips/include/asm/fw/cfe/cfe_error.h similarity index 100% rename from include/asm-mips/fw/cfe/cfe_error.h rename to arch/mips/include/asm/fw/cfe/cfe_error.h diff --git a/include/asm-mips/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h similarity index 100% rename from include/asm-mips/gcmpregs.h rename to arch/mips/include/asm/gcmpregs.h diff --git a/include/asm-mips/gic.h b/arch/mips/include/asm/gic.h similarity index 100% rename from include/asm-mips/gic.h rename to arch/mips/include/asm/gic.h diff --git a/include/asm-mips/gpio.h b/arch/mips/include/asm/gpio.h similarity index 100% rename from include/asm-mips/gpio.h rename to arch/mips/include/asm/gpio.h diff --git a/include/asm-mips/gt64120.h b/arch/mips/include/asm/gt64120.h similarity index 100% rename from include/asm-mips/gt64120.h rename to arch/mips/include/asm/gt64120.h diff --git a/include/asm-mips/hardirq.h b/arch/mips/include/asm/hardirq.h similarity index 100% rename from include/asm-mips/hardirq.h rename to arch/mips/include/asm/hardirq.h diff --git a/include/asm-mips/hazards.h b/arch/mips/include/asm/hazards.h similarity index 100% rename from include/asm-mips/hazards.h rename to arch/mips/include/asm/hazards.h diff --git a/include/asm-mips/highmem.h b/arch/mips/include/asm/highmem.h similarity index 100% rename from include/asm-mips/highmem.h rename to arch/mips/include/asm/highmem.h diff --git a/include/asm-mips/hw_irq.h b/arch/mips/include/asm/hw_irq.h similarity index 100% rename from include/asm-mips/hw_irq.h rename to arch/mips/include/asm/hw_irq.h diff --git a/include/asm-mips/i8253.h b/arch/mips/include/asm/i8253.h similarity index 100% rename from include/asm-mips/i8253.h rename to arch/mips/include/asm/i8253.h diff --git a/include/asm-mips/i8259.h b/arch/mips/include/asm/i8259.h similarity index 100% rename from include/asm-mips/i8259.h rename to arch/mips/include/asm/i8259.h diff --git a/include/asm-mips/ide.h b/arch/mips/include/asm/ide.h similarity index 100% rename from include/asm-mips/ide.h rename to arch/mips/include/asm/ide.h diff --git a/include/asm-mips/inst.h b/arch/mips/include/asm/inst.h similarity index 100% rename from include/asm-mips/inst.h rename to arch/mips/include/asm/inst.h diff --git a/include/asm-mips/io.h b/arch/mips/include/asm/io.h similarity index 100% rename from include/asm-mips/io.h rename to arch/mips/include/asm/io.h diff --git a/include/asm-mips/ioctl.h b/arch/mips/include/asm/ioctl.h similarity index 100% rename from include/asm-mips/ioctl.h rename to arch/mips/include/asm/ioctl.h diff --git a/include/asm-mips/ioctls.h b/arch/mips/include/asm/ioctls.h similarity index 100% rename from include/asm-mips/ioctls.h rename to arch/mips/include/asm/ioctls.h diff --git a/include/asm-mips/ip32/crime.h b/arch/mips/include/asm/ip32/crime.h similarity index 100% rename from include/asm-mips/ip32/crime.h rename to arch/mips/include/asm/ip32/crime.h diff --git a/include/asm-mips/ip32/ip32_ints.h b/arch/mips/include/asm/ip32/ip32_ints.h similarity index 100% rename from include/asm-mips/ip32/ip32_ints.h rename to arch/mips/include/asm/ip32/ip32_ints.h diff --git a/include/asm-mips/ip32/mace.h b/arch/mips/include/asm/ip32/mace.h similarity index 100% rename from include/asm-mips/ip32/mace.h rename to arch/mips/include/asm/ip32/mace.h diff --git a/include/asm-mips/ipcbuf.h b/arch/mips/include/asm/ipcbuf.h similarity index 100% rename from include/asm-mips/ipcbuf.h rename to arch/mips/include/asm/ipcbuf.h diff --git a/include/asm-mips/irq.h b/arch/mips/include/asm/irq.h similarity index 100% rename from include/asm-mips/irq.h rename to arch/mips/include/asm/irq.h diff --git a/include/asm-mips/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h similarity index 100% rename from include/asm-mips/irq_cpu.h rename to arch/mips/include/asm/irq_cpu.h diff --git a/include/asm-mips/irq_gt641xx.h b/arch/mips/include/asm/irq_gt641xx.h similarity index 100% rename from include/asm-mips/irq_gt641xx.h rename to arch/mips/include/asm/irq_gt641xx.h diff --git a/include/asm-mips/irq_regs.h b/arch/mips/include/asm/irq_regs.h similarity index 100% rename from include/asm-mips/irq_regs.h rename to arch/mips/include/asm/irq_regs.h diff --git a/include/asm-mips/irqflags.h b/arch/mips/include/asm/irqflags.h similarity index 100% rename from include/asm-mips/irqflags.h rename to arch/mips/include/asm/irqflags.h diff --git a/include/asm-mips/isadep.h b/arch/mips/include/asm/isadep.h similarity index 100% rename from include/asm-mips/isadep.h rename to arch/mips/include/asm/isadep.h diff --git a/include/asm-mips/jazz.h b/arch/mips/include/asm/jazz.h similarity index 100% rename from include/asm-mips/jazz.h rename to arch/mips/include/asm/jazz.h diff --git a/include/asm-mips/jazzdma.h b/arch/mips/include/asm/jazzdma.h similarity index 100% rename from include/asm-mips/jazzdma.h rename to arch/mips/include/asm/jazzdma.h diff --git a/include/asm-mips/kdebug.h b/arch/mips/include/asm/kdebug.h similarity index 100% rename from include/asm-mips/kdebug.h rename to arch/mips/include/asm/kdebug.h diff --git a/include/asm-mips/kexec.h b/arch/mips/include/asm/kexec.h similarity index 100% rename from include/asm-mips/kexec.h rename to arch/mips/include/asm/kexec.h diff --git a/include/asm-mips/kgdb.h b/arch/mips/include/asm/kgdb.h similarity index 100% rename from include/asm-mips/kgdb.h rename to arch/mips/include/asm/kgdb.h diff --git a/include/asm-mips/kmap_types.h b/arch/mips/include/asm/kmap_types.h similarity index 100% rename from include/asm-mips/kmap_types.h rename to arch/mips/include/asm/kmap_types.h diff --git a/include/asm-mips/kspd.h b/arch/mips/include/asm/kspd.h similarity index 100% rename from include/asm-mips/kspd.h rename to arch/mips/include/asm/kspd.h diff --git a/include/asm-mips/lasat/ds1603.h b/arch/mips/include/asm/lasat/ds1603.h similarity index 100% rename from include/asm-mips/lasat/ds1603.h rename to arch/mips/include/asm/lasat/ds1603.h diff --git a/include/asm-mips/lasat/eeprom.h b/arch/mips/include/asm/lasat/eeprom.h similarity index 100% rename from include/asm-mips/lasat/eeprom.h rename to arch/mips/include/asm/lasat/eeprom.h diff --git a/include/asm-mips/lasat/head.h b/arch/mips/include/asm/lasat/head.h similarity index 100% rename from include/asm-mips/lasat/head.h rename to arch/mips/include/asm/lasat/head.h diff --git a/include/asm-mips/lasat/lasat.h b/arch/mips/include/asm/lasat/lasat.h similarity index 100% rename from include/asm-mips/lasat/lasat.h rename to arch/mips/include/asm/lasat/lasat.h diff --git a/include/asm-mips/lasat/lasatint.h b/arch/mips/include/asm/lasat/lasatint.h similarity index 100% rename from include/asm-mips/lasat/lasatint.h rename to arch/mips/include/asm/lasat/lasatint.h diff --git a/include/asm-mips/lasat/picvue.h b/arch/mips/include/asm/lasat/picvue.h similarity index 100% rename from include/asm-mips/lasat/picvue.h rename to arch/mips/include/asm/lasat/picvue.h diff --git a/include/asm-mips/lasat/serial.h b/arch/mips/include/asm/lasat/serial.h similarity index 100% rename from include/asm-mips/lasat/serial.h rename to arch/mips/include/asm/lasat/serial.h diff --git a/include/asm-mips/linkage.h b/arch/mips/include/asm/linkage.h similarity index 100% rename from include/asm-mips/linkage.h rename to arch/mips/include/asm/linkage.h diff --git a/include/asm-mips/local.h b/arch/mips/include/asm/local.h similarity index 100% rename from include/asm-mips/local.h rename to arch/mips/include/asm/local.h diff --git a/include/asm-mips/m48t35.h b/arch/mips/include/asm/m48t35.h similarity index 100% rename from include/asm-mips/m48t35.h rename to arch/mips/include/asm/m48t35.h diff --git a/include/asm-mips/m48t37.h b/arch/mips/include/asm/m48t37.h similarity index 100% rename from include/asm-mips/m48t37.h rename to arch/mips/include/asm/m48t37.h diff --git a/include/asm-mips/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1000.h rename to arch/mips/include/asm/mach-au1x00/au1000.h diff --git a/include/asm-mips/mach-au1x00/au1000_dma.h b/arch/mips/include/asm/mach-au1x00/au1000_dma.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1000_dma.h rename to arch/mips/include/asm/mach-au1x00/au1000_dma.h diff --git a/include/asm-mips/mach-au1x00/au1000_gpio.h b/arch/mips/include/asm/mach-au1x00/au1000_gpio.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1000_gpio.h rename to arch/mips/include/asm/mach-au1x00/au1000_gpio.h diff --git a/include/asm-mips/mach-au1x00/au1100_mmc.h b/arch/mips/include/asm/mach-au1x00/au1100_mmc.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1100_mmc.h rename to arch/mips/include/asm/mach-au1x00/au1100_mmc.h diff --git a/include/asm-mips/mach-au1x00/au1550_spi.h b/arch/mips/include/asm/mach-au1x00/au1550_spi.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1550_spi.h rename to arch/mips/include/asm/mach-au1x00/au1550_spi.h diff --git a/include/asm-mips/mach-au1x00/au1xxx.h b/arch/mips/include/asm/mach-au1x00/au1xxx.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1xxx.h rename to arch/mips/include/asm/mach-au1x00/au1xxx.h diff --git a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1xxx_dbdma.h rename to arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1xxx_ide.h rename to arch/mips/include/asm/mach-au1x00/au1xxx_ide.h diff --git a/include/asm-mips/mach-au1x00/au1xxx_psc.h b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h similarity index 100% rename from include/asm-mips/mach-au1x00/au1xxx_psc.h rename to arch/mips/include/asm/mach-au1x00/au1xxx_psc.h diff --git a/include/asm-mips/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h similarity index 100% rename from include/asm-mips/mach-au1x00/gpio.h rename to arch/mips/include/asm/mach-au1x00/gpio.h diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/arch/mips/include/asm/mach-au1x00/ioremap.h similarity index 100% rename from include/asm-mips/mach-au1x00/ioremap.h rename to arch/mips/include/asm/mach-au1x00/ioremap.h diff --git a/include/asm-mips/mach-au1x00/prom.h b/arch/mips/include/asm/mach-au1x00/prom.h similarity index 100% rename from include/asm-mips/mach-au1x00/prom.h rename to arch/mips/include/asm/mach-au1x00/prom.h diff --git a/include/asm-mips/mach-au1x00/war.h b/arch/mips/include/asm/mach-au1x00/war.h similarity index 100% rename from include/asm-mips/mach-au1x00/war.h rename to arch/mips/include/asm/mach-au1x00/war.h diff --git a/include/asm-mips/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h similarity index 100% rename from include/asm-mips/mach-bcm47xx/bcm47xx.h rename to arch/mips/include/asm/mach-bcm47xx/bcm47xx.h diff --git a/include/asm-mips/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h similarity index 100% rename from include/asm-mips/mach-bcm47xx/gpio.h rename to arch/mips/include/asm/mach-bcm47xx/gpio.h diff --git a/include/asm-mips/mach-bcm47xx/war.h b/arch/mips/include/asm/mach-bcm47xx/war.h similarity index 100% rename from include/asm-mips/mach-bcm47xx/war.h rename to arch/mips/include/asm/mach-bcm47xx/war.h diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/arch/mips/include/asm/mach-cobalt/cobalt.h similarity index 100% rename from include/asm-mips/mach-cobalt/cobalt.h rename to arch/mips/include/asm/mach-cobalt/cobalt.h diff --git a/include/asm-mips/mach-cobalt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-cobalt/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-cobalt/irq.h b/arch/mips/include/asm/mach-cobalt/irq.h similarity index 100% rename from include/asm-mips/mach-cobalt/irq.h rename to arch/mips/include/asm/mach-cobalt/irq.h diff --git a/include/asm-mips/mach-cobalt/mach-gt64120.h b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h similarity index 100% rename from include/asm-mips/mach-cobalt/mach-gt64120.h rename to arch/mips/include/asm/mach-cobalt/mach-gt64120.h diff --git a/include/asm-mips/mach-cobalt/war.h b/arch/mips/include/asm/mach-cobalt/war.h similarity index 100% rename from include/asm-mips/mach-cobalt/war.h rename to arch/mips/include/asm/mach-cobalt/war.h diff --git a/include/asm-mips/mach-db1x00/db1200.h b/arch/mips/include/asm/mach-db1x00/db1200.h similarity index 100% rename from include/asm-mips/mach-db1x00/db1200.h rename to arch/mips/include/asm/mach-db1x00/db1200.h diff --git a/include/asm-mips/mach-db1x00/db1x00.h b/arch/mips/include/asm/mach-db1x00/db1x00.h similarity index 100% rename from include/asm-mips/mach-db1x00/db1x00.h rename to arch/mips/include/asm/mach-db1x00/db1x00.h diff --git a/include/asm-mips/mach-dec/mc146818rtc.h b/arch/mips/include/asm/mach-dec/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-dec/mc146818rtc.h rename to arch/mips/include/asm/mach-dec/mc146818rtc.h diff --git a/include/asm-mips/mach-dec/war.h b/arch/mips/include/asm/mach-dec/war.h similarity index 100% rename from include/asm-mips/mach-dec/war.h rename to arch/mips/include/asm/mach-dec/war.h diff --git a/include/asm-mips/mach-emma2rh/irq.h b/arch/mips/include/asm/mach-emma2rh/irq.h similarity index 100% rename from include/asm-mips/mach-emma2rh/irq.h rename to arch/mips/include/asm/mach-emma2rh/irq.h diff --git a/include/asm-mips/mach-emma2rh/war.h b/arch/mips/include/asm/mach-emma2rh/war.h similarity index 100% rename from include/asm-mips/mach-emma2rh/war.h rename to arch/mips/include/asm/mach-emma2rh/war.h diff --git a/include/asm-mips/mach-excite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-excite/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-excite/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-excite/excite.h b/arch/mips/include/asm/mach-excite/excite.h similarity index 100% rename from include/asm-mips/mach-excite/excite.h rename to arch/mips/include/asm/mach-excite/excite.h diff --git a/include/asm-mips/mach-excite/excite_fpga.h b/arch/mips/include/asm/mach-excite/excite_fpga.h similarity index 100% rename from include/asm-mips/mach-excite/excite_fpga.h rename to arch/mips/include/asm/mach-excite/excite_fpga.h diff --git a/include/asm-mips/mach-excite/excite_nandflash.h b/arch/mips/include/asm/mach-excite/excite_nandflash.h similarity index 100% rename from include/asm-mips/mach-excite/excite_nandflash.h rename to arch/mips/include/asm/mach-excite/excite_nandflash.h diff --git a/include/asm-mips/mach-excite/rm9k_eth.h b/arch/mips/include/asm/mach-excite/rm9k_eth.h similarity index 100% rename from include/asm-mips/mach-excite/rm9k_eth.h rename to arch/mips/include/asm/mach-excite/rm9k_eth.h diff --git a/include/asm-mips/mach-excite/rm9k_wdt.h b/arch/mips/include/asm/mach-excite/rm9k_wdt.h similarity index 100% rename from include/asm-mips/mach-excite/rm9k_wdt.h rename to arch/mips/include/asm/mach-excite/rm9k_wdt.h diff --git a/include/asm-mips/mach-excite/rm9k_xicap.h b/arch/mips/include/asm/mach-excite/rm9k_xicap.h similarity index 100% rename from include/asm-mips/mach-excite/rm9k_xicap.h rename to arch/mips/include/asm/mach-excite/rm9k_xicap.h diff --git a/include/asm-mips/mach-excite/war.h b/arch/mips/include/asm/mach-excite/war.h similarity index 100% rename from include/asm-mips/mach-excite/war.h rename to arch/mips/include/asm/mach-excite/war.h diff --git a/include/asm-mips/mach-generic/cpu-feature-overrides.h b/arch/mips/include/asm/mach-generic/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-generic/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-generic/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h similarity index 100% rename from include/asm-mips/mach-generic/dma-coherence.h rename to arch/mips/include/asm/mach-generic/dma-coherence.h diff --git a/include/asm-mips/mach-generic/floppy.h b/arch/mips/include/asm/mach-generic/floppy.h similarity index 100% rename from include/asm-mips/mach-generic/floppy.h rename to arch/mips/include/asm/mach-generic/floppy.h diff --git a/include/asm-mips/mach-generic/gpio.h b/arch/mips/include/asm/mach-generic/gpio.h similarity index 100% rename from include/asm-mips/mach-generic/gpio.h rename to arch/mips/include/asm/mach-generic/gpio.h diff --git a/include/asm-mips/mach-generic/ide.h b/arch/mips/include/asm/mach-generic/ide.h similarity index 100% rename from include/asm-mips/mach-generic/ide.h rename to arch/mips/include/asm/mach-generic/ide.h diff --git a/include/asm-mips/mach-generic/ioremap.h b/arch/mips/include/asm/mach-generic/ioremap.h similarity index 100% rename from include/asm-mips/mach-generic/ioremap.h rename to arch/mips/include/asm/mach-generic/ioremap.h diff --git a/include/asm-mips/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h similarity index 100% rename from include/asm-mips/mach-generic/irq.h rename to arch/mips/include/asm/mach-generic/irq.h diff --git a/include/asm-mips/mach-generic/kernel-entry-init.h b/arch/mips/include/asm/mach-generic/kernel-entry-init.h similarity index 100% rename from include/asm-mips/mach-generic/kernel-entry-init.h rename to arch/mips/include/asm/mach-generic/kernel-entry-init.h diff --git a/include/asm-mips/mach-generic/kmalloc.h b/arch/mips/include/asm/mach-generic/kmalloc.h similarity index 100% rename from include/asm-mips/mach-generic/kmalloc.h rename to arch/mips/include/asm/mach-generic/kmalloc.h diff --git a/include/asm-mips/mach-generic/mangle-port.h b/arch/mips/include/asm/mach-generic/mangle-port.h similarity index 100% rename from include/asm-mips/mach-generic/mangle-port.h rename to arch/mips/include/asm/mach-generic/mangle-port.h diff --git a/include/asm-mips/mach-generic/mc146818rtc.h b/arch/mips/include/asm/mach-generic/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-generic/mc146818rtc.h rename to arch/mips/include/asm/mach-generic/mc146818rtc.h diff --git a/include/asm-mips/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h similarity index 100% rename from include/asm-mips/mach-generic/spaces.h rename to arch/mips/include/asm/mach-generic/spaces.h diff --git a/include/asm-mips/mach-generic/topology.h b/arch/mips/include/asm/mach-generic/topology.h similarity index 100% rename from include/asm-mips/mach-generic/topology.h rename to arch/mips/include/asm/mach-generic/topology.h diff --git a/include/asm-mips/mach-ip22/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-ip22/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-ip22/ds1286.h b/arch/mips/include/asm/mach-ip22/ds1286.h similarity index 100% rename from include/asm-mips/mach-ip22/ds1286.h rename to arch/mips/include/asm/mach-ip22/ds1286.h diff --git a/include/asm-mips/mach-ip22/spaces.h b/arch/mips/include/asm/mach-ip22/spaces.h similarity index 100% rename from include/asm-mips/mach-ip22/spaces.h rename to arch/mips/include/asm/mach-ip22/spaces.h diff --git a/include/asm-mips/mach-ip22/war.h b/arch/mips/include/asm/mach-ip22/war.h similarity index 100% rename from include/asm-mips/mach-ip22/war.h rename to arch/mips/include/asm/mach-ip22/war.h diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-ip27/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h similarity index 100% rename from include/asm-mips/mach-ip27/dma-coherence.h rename to arch/mips/include/asm/mach-ip27/dma-coherence.h diff --git a/include/asm-mips/mach-ip27/irq.h b/arch/mips/include/asm/mach-ip27/irq.h similarity index 100% rename from include/asm-mips/mach-ip27/irq.h rename to arch/mips/include/asm/mach-ip27/irq.h diff --git a/include/asm-mips/mach-ip27/kernel-entry-init.h b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h similarity index 100% rename from include/asm-mips/mach-ip27/kernel-entry-init.h rename to arch/mips/include/asm/mach-ip27/kernel-entry-init.h diff --git a/include/asm-mips/mach-ip27/kmalloc.h b/arch/mips/include/asm/mach-ip27/kmalloc.h similarity index 100% rename from include/asm-mips/mach-ip27/kmalloc.h rename to arch/mips/include/asm/mach-ip27/kmalloc.h diff --git a/include/asm-mips/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h similarity index 100% rename from include/asm-mips/mach-ip27/mangle-port.h rename to arch/mips/include/asm/mach-ip27/mangle-port.h diff --git a/include/asm-mips/mach-ip27/mmzone.h b/arch/mips/include/asm/mach-ip27/mmzone.h similarity index 100% rename from include/asm-mips/mach-ip27/mmzone.h rename to arch/mips/include/asm/mach-ip27/mmzone.h diff --git a/include/asm-mips/mach-ip27/spaces.h b/arch/mips/include/asm/mach-ip27/spaces.h similarity index 100% rename from include/asm-mips/mach-ip27/spaces.h rename to arch/mips/include/asm/mach-ip27/spaces.h diff --git a/include/asm-mips/mach-ip27/topology.h b/arch/mips/include/asm/mach-ip27/topology.h similarity index 100% rename from include/asm-mips/mach-ip27/topology.h rename to arch/mips/include/asm/mach-ip27/topology.h diff --git a/include/asm-mips/mach-ip27/war.h b/arch/mips/include/asm/mach-ip27/war.h similarity index 100% rename from include/asm-mips/mach-ip27/war.h rename to arch/mips/include/asm/mach-ip27/war.h diff --git a/include/asm-mips/mach-ip28/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-ip28/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-ip28/ds1286.h b/arch/mips/include/asm/mach-ip28/ds1286.h similarity index 100% rename from include/asm-mips/mach-ip28/ds1286.h rename to arch/mips/include/asm/mach-ip28/ds1286.h diff --git a/include/asm-mips/mach-ip28/spaces.h b/arch/mips/include/asm/mach-ip28/spaces.h similarity index 100% rename from include/asm-mips/mach-ip28/spaces.h rename to arch/mips/include/asm/mach-ip28/spaces.h diff --git a/include/asm-mips/mach-ip28/war.h b/arch/mips/include/asm/mach-ip28/war.h similarity index 100% rename from include/asm-mips/mach-ip28/war.h rename to arch/mips/include/asm/mach-ip28/war.h diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-ip32/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h similarity index 100% rename from include/asm-mips/mach-ip32/dma-coherence.h rename to arch/mips/include/asm/mach-ip32/dma-coherence.h diff --git a/include/asm-mips/mach-ip32/kmalloc.h b/arch/mips/include/asm/mach-ip32/kmalloc.h similarity index 100% rename from include/asm-mips/mach-ip32/kmalloc.h rename to arch/mips/include/asm/mach-ip32/kmalloc.h diff --git a/include/asm-mips/mach-ip32/mangle-port.h b/arch/mips/include/asm/mach-ip32/mangle-port.h similarity index 100% rename from include/asm-mips/mach-ip32/mangle-port.h rename to arch/mips/include/asm/mach-ip32/mangle-port.h diff --git a/include/asm-mips/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-ip32/mc146818rtc.h rename to arch/mips/include/asm/mach-ip32/mc146818rtc.h diff --git a/include/asm-mips/mach-ip32/war.h b/arch/mips/include/asm/mach-ip32/war.h similarity index 100% rename from include/asm-mips/mach-ip32/war.h rename to arch/mips/include/asm/mach-ip32/war.h diff --git a/include/asm-mips/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h similarity index 100% rename from include/asm-mips/mach-jazz/dma-coherence.h rename to arch/mips/include/asm/mach-jazz/dma-coherence.h diff --git a/include/asm-mips/mach-jazz/floppy.h b/arch/mips/include/asm/mach-jazz/floppy.h similarity index 100% rename from include/asm-mips/mach-jazz/floppy.h rename to arch/mips/include/asm/mach-jazz/floppy.h diff --git a/include/asm-mips/mach-jazz/mc146818rtc.h b/arch/mips/include/asm/mach-jazz/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-jazz/mc146818rtc.h rename to arch/mips/include/asm/mach-jazz/mc146818rtc.h diff --git a/include/asm-mips/mach-jazz/war.h b/arch/mips/include/asm/mach-jazz/war.h similarity index 100% rename from include/asm-mips/mach-jazz/war.h rename to arch/mips/include/asm/mach-jazz/war.h diff --git a/include/asm-mips/mach-lasat/irq.h b/arch/mips/include/asm/mach-lasat/irq.h similarity index 100% rename from include/asm-mips/mach-lasat/irq.h rename to arch/mips/include/asm/mach-lasat/irq.h diff --git a/include/asm-mips/mach-lasat/mach-gt64120.h b/arch/mips/include/asm/mach-lasat/mach-gt64120.h similarity index 100% rename from include/asm-mips/mach-lasat/mach-gt64120.h rename to arch/mips/include/asm/mach-lasat/mach-gt64120.h diff --git a/include/asm-mips/mach-lasat/war.h b/arch/mips/include/asm/mach-lasat/war.h similarity index 100% rename from include/asm-mips/mach-lasat/war.h rename to arch/mips/include/asm/mach-lasat/war.h diff --git a/include/asm-mips/mach-lemote/dma-coherence.h b/arch/mips/include/asm/mach-lemote/dma-coherence.h similarity index 100% rename from include/asm-mips/mach-lemote/dma-coherence.h rename to arch/mips/include/asm/mach-lemote/dma-coherence.h diff --git a/include/asm-mips/mach-lemote/mc146818rtc.h b/arch/mips/include/asm/mach-lemote/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-lemote/mc146818rtc.h rename to arch/mips/include/asm/mach-lemote/mc146818rtc.h diff --git a/include/asm-mips/mach-lemote/war.h b/arch/mips/include/asm/mach-lemote/war.h similarity index 100% rename from include/asm-mips/mach-lemote/war.h rename to arch/mips/include/asm/mach-lemote/war.h diff --git a/include/asm-mips/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-malta/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-malta/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h similarity index 100% rename from include/asm-mips/mach-malta/irq.h rename to arch/mips/include/asm/mach-malta/irq.h diff --git a/include/asm-mips/mach-malta/kernel-entry-init.h b/arch/mips/include/asm/mach-malta/kernel-entry-init.h similarity index 100% rename from include/asm-mips/mach-malta/kernel-entry-init.h rename to arch/mips/include/asm/mach-malta/kernel-entry-init.h diff --git a/include/asm-mips/mach-malta/mach-gt64120.h b/arch/mips/include/asm/mach-malta/mach-gt64120.h similarity index 100% rename from include/asm-mips/mach-malta/mach-gt64120.h rename to arch/mips/include/asm/mach-malta/mach-gt64120.h diff --git a/include/asm-mips/mach-malta/mc146818rtc.h b/arch/mips/include/asm/mach-malta/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-malta/mc146818rtc.h rename to arch/mips/include/asm/mach-malta/mc146818rtc.h diff --git a/include/asm-mips/mach-malta/war.h b/arch/mips/include/asm/mach-malta/war.h similarity index 100% rename from include/asm-mips/mach-malta/war.h rename to arch/mips/include/asm/mach-malta/war.h diff --git a/include/asm-mips/mach-mipssim/cpu-feature-overrides.h b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-mipssim/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-mipssim/war.h b/arch/mips/include/asm/mach-mipssim/war.h similarity index 100% rename from include/asm-mips/mach-mipssim/war.h rename to arch/mips/include/asm/mach-mipssim/war.h diff --git a/include/asm-mips/mach-pb1x00/mc146818rtc.h b/arch/mips/include/asm/mach-pb1x00/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-pb1x00/mc146818rtc.h rename to arch/mips/include/asm/mach-pb1x00/mc146818rtc.h diff --git a/include/asm-mips/mach-pb1x00/pb1000.h b/arch/mips/include/asm/mach-pb1x00/pb1000.h similarity index 100% rename from include/asm-mips/mach-pb1x00/pb1000.h rename to arch/mips/include/asm/mach-pb1x00/pb1000.h diff --git a/include/asm-mips/mach-pb1x00/pb1100.h b/arch/mips/include/asm/mach-pb1x00/pb1100.h similarity index 100% rename from include/asm-mips/mach-pb1x00/pb1100.h rename to arch/mips/include/asm/mach-pb1x00/pb1100.h diff --git a/include/asm-mips/mach-pb1x00/pb1200.h b/arch/mips/include/asm/mach-pb1x00/pb1200.h similarity index 100% rename from include/asm-mips/mach-pb1x00/pb1200.h rename to arch/mips/include/asm/mach-pb1x00/pb1200.h diff --git a/include/asm-mips/mach-pb1x00/pb1500.h b/arch/mips/include/asm/mach-pb1x00/pb1500.h similarity index 100% rename from include/asm-mips/mach-pb1x00/pb1500.h rename to arch/mips/include/asm/mach-pb1x00/pb1500.h diff --git a/include/asm-mips/mach-pb1x00/pb1550.h b/arch/mips/include/asm/mach-pb1x00/pb1550.h similarity index 100% rename from include/asm-mips/mach-pb1x00/pb1550.h rename to arch/mips/include/asm/mach-pb1x00/pb1550.h diff --git a/include/asm-mips/mach-pnx8550/cm.h b/arch/mips/include/asm/mach-pnx8550/cm.h similarity index 100% rename from include/asm-mips/mach-pnx8550/cm.h rename to arch/mips/include/asm/mach-pnx8550/cm.h diff --git a/include/asm-mips/mach-pnx8550/glb.h b/arch/mips/include/asm/mach-pnx8550/glb.h similarity index 100% rename from include/asm-mips/mach-pnx8550/glb.h rename to arch/mips/include/asm/mach-pnx8550/glb.h diff --git a/include/asm-mips/mach-pnx8550/int.h b/arch/mips/include/asm/mach-pnx8550/int.h similarity index 100% rename from include/asm-mips/mach-pnx8550/int.h rename to arch/mips/include/asm/mach-pnx8550/int.h diff --git a/include/asm-mips/mach-pnx8550/kernel-entry-init.h b/arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h similarity index 100% rename from include/asm-mips/mach-pnx8550/kernel-entry-init.h rename to arch/mips/include/asm/mach-pnx8550/kernel-entry-init.h diff --git a/include/asm-mips/mach-pnx8550/nand.h b/arch/mips/include/asm/mach-pnx8550/nand.h similarity index 100% rename from include/asm-mips/mach-pnx8550/nand.h rename to arch/mips/include/asm/mach-pnx8550/nand.h diff --git a/include/asm-mips/mach-pnx8550/pci.h b/arch/mips/include/asm/mach-pnx8550/pci.h similarity index 100% rename from include/asm-mips/mach-pnx8550/pci.h rename to arch/mips/include/asm/mach-pnx8550/pci.h diff --git a/include/asm-mips/mach-pnx8550/uart.h b/arch/mips/include/asm/mach-pnx8550/uart.h similarity index 100% rename from include/asm-mips/mach-pnx8550/uart.h rename to arch/mips/include/asm/mach-pnx8550/uart.h diff --git a/include/asm-mips/mach-pnx8550/usb.h b/arch/mips/include/asm/mach-pnx8550/usb.h similarity index 100% rename from include/asm-mips/mach-pnx8550/usb.h rename to arch/mips/include/asm/mach-pnx8550/usb.h diff --git a/include/asm-mips/mach-pnx8550/war.h b/arch/mips/include/asm/mach-pnx8550/war.h similarity index 100% rename from include/asm-mips/mach-pnx8550/war.h rename to arch/mips/include/asm/mach-pnx8550/war.h diff --git a/include/asm-mips/mach-rc32434/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-rc32434/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-rc32434/ddr.h b/arch/mips/include/asm/mach-rc32434/ddr.h similarity index 100% rename from include/asm-mips/mach-rc32434/ddr.h rename to arch/mips/include/asm/mach-rc32434/ddr.h diff --git a/include/asm-mips/mach-rc32434/dma.h b/arch/mips/include/asm/mach-rc32434/dma.h similarity index 100% rename from include/asm-mips/mach-rc32434/dma.h rename to arch/mips/include/asm/mach-rc32434/dma.h diff --git a/include/asm-mips/mach-rc32434/dma_v.h b/arch/mips/include/asm/mach-rc32434/dma_v.h similarity index 100% rename from include/asm-mips/mach-rc32434/dma_v.h rename to arch/mips/include/asm/mach-rc32434/dma_v.h diff --git a/include/asm-mips/mach-rc32434/eth.h b/arch/mips/include/asm/mach-rc32434/eth.h similarity index 100% rename from include/asm-mips/mach-rc32434/eth.h rename to arch/mips/include/asm/mach-rc32434/eth.h diff --git a/include/asm-mips/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h similarity index 100% rename from include/asm-mips/mach-rc32434/gpio.h rename to arch/mips/include/asm/mach-rc32434/gpio.h diff --git a/include/asm-mips/mach-rc32434/integ.h b/arch/mips/include/asm/mach-rc32434/integ.h similarity index 100% rename from include/asm-mips/mach-rc32434/integ.h rename to arch/mips/include/asm/mach-rc32434/integ.h diff --git a/include/asm-mips/mach-rc32434/irq.h b/arch/mips/include/asm/mach-rc32434/irq.h similarity index 100% rename from include/asm-mips/mach-rc32434/irq.h rename to arch/mips/include/asm/mach-rc32434/irq.h diff --git a/include/asm-mips/mach-rc32434/pci.h b/arch/mips/include/asm/mach-rc32434/pci.h similarity index 100% rename from include/asm-mips/mach-rc32434/pci.h rename to arch/mips/include/asm/mach-rc32434/pci.h diff --git a/include/asm-mips/mach-rc32434/prom.h b/arch/mips/include/asm/mach-rc32434/prom.h similarity index 100% rename from include/asm-mips/mach-rc32434/prom.h rename to arch/mips/include/asm/mach-rc32434/prom.h diff --git a/include/asm-mips/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h similarity index 100% rename from include/asm-mips/mach-rc32434/rb.h rename to arch/mips/include/asm/mach-rc32434/rb.h diff --git a/include/asm-mips/mach-rc32434/rc32434.h b/arch/mips/include/asm/mach-rc32434/rc32434.h similarity index 100% rename from include/asm-mips/mach-rc32434/rc32434.h rename to arch/mips/include/asm/mach-rc32434/rc32434.h diff --git a/include/asm-mips/mach-rc32434/timer.h b/arch/mips/include/asm/mach-rc32434/timer.h similarity index 100% rename from include/asm-mips/mach-rc32434/timer.h rename to arch/mips/include/asm/mach-rc32434/timer.h diff --git a/include/asm-mips/mach-rc32434/war.h b/arch/mips/include/asm/mach-rc32434/war.h similarity index 100% rename from include/asm-mips/mach-rc32434/war.h rename to arch/mips/include/asm/mach-rc32434/war.h diff --git a/include/asm-mips/mach-rm/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-rm/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-rm/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-rm/mc146818rtc.h b/arch/mips/include/asm/mach-rm/mc146818rtc.h similarity index 100% rename from include/asm-mips/mach-rm/mc146818rtc.h rename to arch/mips/include/asm/mach-rm/mc146818rtc.h diff --git a/include/asm-mips/mach-rm/war.h b/arch/mips/include/asm/mach-rm/war.h similarity index 100% rename from include/asm-mips/mach-rm/war.h rename to arch/mips/include/asm/mach-rm/war.h diff --git a/include/asm-mips/mach-sibyte/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-sibyte/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-sibyte/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-sibyte/war.h b/arch/mips/include/asm/mach-sibyte/war.h similarity index 100% rename from include/asm-mips/mach-sibyte/war.h rename to arch/mips/include/asm/mach-sibyte/war.h diff --git a/include/asm-mips/mach-tx39xx/ioremap.h b/arch/mips/include/asm/mach-tx39xx/ioremap.h similarity index 100% rename from include/asm-mips/mach-tx39xx/ioremap.h rename to arch/mips/include/asm/mach-tx39xx/ioremap.h diff --git a/include/asm-mips/mach-tx39xx/mangle-port.h b/arch/mips/include/asm/mach-tx39xx/mangle-port.h similarity index 100% rename from include/asm-mips/mach-tx39xx/mangle-port.h rename to arch/mips/include/asm/mach-tx39xx/mangle-port.h diff --git a/include/asm-mips/mach-tx39xx/war.h b/arch/mips/include/asm/mach-tx39xx/war.h similarity index 100% rename from include/asm-mips/mach-tx39xx/war.h rename to arch/mips/include/asm/mach-tx39xx/war.h diff --git a/include/asm-mips/mach-tx49xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-tx49xx/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-tx49xx/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-tx49xx/ioremap.h b/arch/mips/include/asm/mach-tx49xx/ioremap.h similarity index 100% rename from include/asm-mips/mach-tx49xx/ioremap.h rename to arch/mips/include/asm/mach-tx49xx/ioremap.h diff --git a/include/asm-mips/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h similarity index 100% rename from include/asm-mips/mach-tx49xx/kmalloc.h rename to arch/mips/include/asm/mach-tx49xx/kmalloc.h diff --git a/include/asm-mips/mach-tx49xx/war.h b/arch/mips/include/asm/mach-tx49xx/war.h similarity index 100% rename from include/asm-mips/mach-tx49xx/war.h rename to arch/mips/include/asm/mach-tx49xx/war.h diff --git a/include/asm-mips/mach-vr41xx/irq.h b/arch/mips/include/asm/mach-vr41xx/irq.h similarity index 100% rename from include/asm-mips/mach-vr41xx/irq.h rename to arch/mips/include/asm/mach-vr41xx/irq.h diff --git a/include/asm-mips/mach-vr41xx/war.h b/arch/mips/include/asm/mach-vr41xx/war.h similarity index 100% rename from include/asm-mips/mach-vr41xx/war.h rename to arch/mips/include/asm/mach-vr41xx/war.h diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h similarity index 100% rename from include/asm-mips/mach-wrppmc/mach-gt64120.h rename to arch/mips/include/asm/mach-wrppmc/mach-gt64120.h diff --git a/include/asm-mips/mach-wrppmc/war.h b/arch/mips/include/asm/mach-wrppmc/war.h similarity index 100% rename from include/asm-mips/mach-wrppmc/war.h rename to arch/mips/include/asm/mach-wrppmc/war.h diff --git a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h similarity index 100% rename from include/asm-mips/mach-yosemite/cpu-feature-overrides.h rename to arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h diff --git a/include/asm-mips/mach-yosemite/war.h b/arch/mips/include/asm/mach-yosemite/war.h similarity index 100% rename from include/asm-mips/mach-yosemite/war.h rename to arch/mips/include/asm/mach-yosemite/war.h diff --git a/include/asm-mips/mc146818-time.h b/arch/mips/include/asm/mc146818-time.h similarity index 100% rename from include/asm-mips/mc146818-time.h rename to arch/mips/include/asm/mc146818-time.h diff --git a/include/asm-mips/mc146818rtc.h b/arch/mips/include/asm/mc146818rtc.h similarity index 100% rename from include/asm-mips/mc146818rtc.h rename to arch/mips/include/asm/mc146818rtc.h diff --git a/include/asm-mips/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h similarity index 100% rename from include/asm-mips/mips-boards/bonito64.h rename to arch/mips/include/asm/mips-boards/bonito64.h diff --git a/include/asm-mips/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h similarity index 100% rename from include/asm-mips/mips-boards/generic.h rename to arch/mips/include/asm/mips-boards/generic.h diff --git a/include/asm-mips/mips-boards/launch.h b/arch/mips/include/asm/mips-boards/launch.h similarity index 100% rename from include/asm-mips/mips-boards/launch.h rename to arch/mips/include/asm/mips-boards/launch.h diff --git a/include/asm-mips/mips-boards/malta.h b/arch/mips/include/asm/mips-boards/malta.h similarity index 100% rename from include/asm-mips/mips-boards/malta.h rename to arch/mips/include/asm/mips-boards/malta.h diff --git a/include/asm-mips/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h similarity index 100% rename from include/asm-mips/mips-boards/maltaint.h rename to arch/mips/include/asm/mips-boards/maltaint.h diff --git a/include/asm-mips/mips-boards/msc01_pci.h b/arch/mips/include/asm/mips-boards/msc01_pci.h similarity index 100% rename from include/asm-mips/mips-boards/msc01_pci.h rename to arch/mips/include/asm/mips-boards/msc01_pci.h diff --git a/include/asm-mips/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h similarity index 100% rename from include/asm-mips/mips-boards/piix4.h rename to arch/mips/include/asm/mips-boards/piix4.h diff --git a/include/asm-mips/mips-boards/prom.h b/arch/mips/include/asm/mips-boards/prom.h similarity index 100% rename from include/asm-mips/mips-boards/prom.h rename to arch/mips/include/asm/mips-boards/prom.h diff --git a/include/asm-mips/mips-boards/sim.h b/arch/mips/include/asm/mips-boards/sim.h similarity index 100% rename from include/asm-mips/mips-boards/sim.h rename to arch/mips/include/asm/mips-boards/sim.h diff --git a/include/asm-mips/mips-boards/simint.h b/arch/mips/include/asm/mips-boards/simint.h similarity index 100% rename from include/asm-mips/mips-boards/simint.h rename to arch/mips/include/asm/mips-boards/simint.h diff --git a/include/asm-mips/mips_mt.h b/arch/mips/include/asm/mips_mt.h similarity index 100% rename from include/asm-mips/mips_mt.h rename to arch/mips/include/asm/mips_mt.h diff --git a/include/asm-mips/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h similarity index 100% rename from include/asm-mips/mipsmtregs.h rename to arch/mips/include/asm/mipsmtregs.h diff --git a/include/asm-mips/mipsprom.h b/arch/mips/include/asm/mipsprom.h similarity index 100% rename from include/asm-mips/mipsprom.h rename to arch/mips/include/asm/mipsprom.h diff --git a/include/asm-mips/mipsregs.h b/arch/mips/include/asm/mipsregs.h similarity index 100% rename from include/asm-mips/mipsregs.h rename to arch/mips/include/asm/mipsregs.h diff --git a/include/asm-mips/mman.h b/arch/mips/include/asm/mman.h similarity index 100% rename from include/asm-mips/mman.h rename to arch/mips/include/asm/mman.h diff --git a/include/asm-mips/mmu.h b/arch/mips/include/asm/mmu.h similarity index 100% rename from include/asm-mips/mmu.h rename to arch/mips/include/asm/mmu.h diff --git a/include/asm-mips/mmu_context.h b/arch/mips/include/asm/mmu_context.h similarity index 97% rename from include/asm-mips/mmu_context.h rename to arch/mips/include/asm/mmu_context.h index 0c4f245eaeb..d7f3eb03ad1 100644 --- a/include/asm-mips/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -220,8 +220,8 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next) oldasid = read_c0_entryhi() & ASID_MASK; if(smtc_live_asid[mytlb][oldasid]) { smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); - if(smtc_live_asid[mytlb][oldasid] == 0) - smtc_flush_tlb_asid(oldasid); + if(smtc_live_asid[mytlb][oldasid] == 0) + smtc_flush_tlb_asid(oldasid); } /* See comments for similar code above */ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | @@ -285,8 +285,8 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu) /* SMTC shares the TLB (and ASIDs) across VPEs */ for_each_online_cpu(i) { - if((smtc_status & SMTC_TLB_SHARED) - || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) + if((smtc_status & SMTC_TLB_SHARED) + || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) cpu_context(i, mm) = 0; } #endif /* CONFIG_MIPS_MT_SMTC */ diff --git a/include/asm-mips/mmzone.h b/arch/mips/include/asm/mmzone.h similarity index 100% rename from include/asm-mips/mmzone.h rename to arch/mips/include/asm/mmzone.h diff --git a/include/asm-mips/module.h b/arch/mips/include/asm/module.h similarity index 100% rename from include/asm-mips/module.h rename to arch/mips/include/asm/module.h diff --git a/include/asm-mips/msc01_ic.h b/arch/mips/include/asm/msc01_ic.h similarity index 100% rename from include/asm-mips/msc01_ic.h rename to arch/mips/include/asm/msc01_ic.h diff --git a/include/asm-mips/msgbuf.h b/arch/mips/include/asm/msgbuf.h similarity index 100% rename from include/asm-mips/msgbuf.h rename to arch/mips/include/asm/msgbuf.h diff --git a/include/asm-mips/mutex.h b/arch/mips/include/asm/mutex.h similarity index 100% rename from include/asm-mips/mutex.h rename to arch/mips/include/asm/mutex.h diff --git a/include/asm-mips/nile4.h b/arch/mips/include/asm/nile4.h similarity index 100% rename from include/asm-mips/nile4.h rename to arch/mips/include/asm/nile4.h diff --git a/include/asm-mips/paccess.h b/arch/mips/include/asm/paccess.h similarity index 100% rename from include/asm-mips/paccess.h rename to arch/mips/include/asm/paccess.h diff --git a/include/asm-mips/page.h b/arch/mips/include/asm/page.h similarity index 100% rename from include/asm-mips/page.h rename to arch/mips/include/asm/page.h diff --git a/include/asm-mips/param.h b/arch/mips/include/asm/param.h similarity index 100% rename from include/asm-mips/param.h rename to arch/mips/include/asm/param.h diff --git a/include/asm-mips/parport.h b/arch/mips/include/asm/parport.h similarity index 100% rename from include/asm-mips/parport.h rename to arch/mips/include/asm/parport.h diff --git a/include/asm-mips/pci.h b/arch/mips/include/asm/pci.h similarity index 100% rename from include/asm-mips/pci.h rename to arch/mips/include/asm/pci.h diff --git a/include/asm-mips/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h similarity index 100% rename from include/asm-mips/pci/bridge.h rename to arch/mips/include/asm/pci/bridge.h diff --git a/include/asm-mips/percpu.h b/arch/mips/include/asm/percpu.h similarity index 100% rename from include/asm-mips/percpu.h rename to arch/mips/include/asm/percpu.h diff --git a/include/asm-mips/pgalloc.h b/arch/mips/include/asm/pgalloc.h similarity index 100% rename from include/asm-mips/pgalloc.h rename to arch/mips/include/asm/pgalloc.h diff --git a/include/asm-mips/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h similarity index 100% rename from include/asm-mips/pgtable-32.h rename to arch/mips/include/asm/pgtable-32.h diff --git a/include/asm-mips/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h similarity index 100% rename from include/asm-mips/pgtable-64.h rename to arch/mips/include/asm/pgtable-64.h diff --git a/include/asm-mips/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h similarity index 100% rename from include/asm-mips/pgtable-bits.h rename to arch/mips/include/asm/pgtable-bits.h diff --git a/include/asm-mips/pgtable.h b/arch/mips/include/asm/pgtable.h similarity index 100% rename from include/asm-mips/pgtable.h rename to arch/mips/include/asm/pgtable.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/gpio.h b/arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/gpio.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/gpio.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_cic_int.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_int.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_int.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_pci.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_pci.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_prom.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_regops.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_regs.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/msp_slp_int.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/war.h b/arch/mips/include/asm/pmc-sierra/msp71xx/war.h similarity index 100% rename from include/asm-mips/pmc-sierra/msp71xx/war.h rename to arch/mips/include/asm/pmc-sierra/msp71xx/war.h diff --git a/include/asm-mips/pmon.h b/arch/mips/include/asm/pmon.h similarity index 100% rename from include/asm-mips/pmon.h rename to arch/mips/include/asm/pmon.h diff --git a/include/asm-mips/poll.h b/arch/mips/include/asm/poll.h similarity index 100% rename from include/asm-mips/poll.h rename to arch/mips/include/asm/poll.h diff --git a/include/asm-mips/posix_types.h b/arch/mips/include/asm/posix_types.h similarity index 100% rename from include/asm-mips/posix_types.h rename to arch/mips/include/asm/posix_types.h diff --git a/include/asm-mips/prefetch.h b/arch/mips/include/asm/prefetch.h similarity index 100% rename from include/asm-mips/prefetch.h rename to arch/mips/include/asm/prefetch.h diff --git a/include/asm-mips/processor.h b/arch/mips/include/asm/processor.h similarity index 100% rename from include/asm-mips/processor.h rename to arch/mips/include/asm/processor.h diff --git a/include/asm-mips/ptrace.h b/arch/mips/include/asm/ptrace.h similarity index 100% rename from include/asm-mips/ptrace.h rename to arch/mips/include/asm/ptrace.h diff --git a/include/asm-mips/r4k-timer.h b/arch/mips/include/asm/r4k-timer.h similarity index 100% rename from include/asm-mips/r4k-timer.h rename to arch/mips/include/asm/r4k-timer.h diff --git a/include/asm-mips/r4kcache.h b/arch/mips/include/asm/r4kcache.h similarity index 100% rename from include/asm-mips/r4kcache.h rename to arch/mips/include/asm/r4kcache.h diff --git a/include/asm-mips/reboot.h b/arch/mips/include/asm/reboot.h similarity index 100% rename from include/asm-mips/reboot.h rename to arch/mips/include/asm/reboot.h diff --git a/include/asm-mips/reg.h b/arch/mips/include/asm/reg.h similarity index 100% rename from include/asm-mips/reg.h rename to arch/mips/include/asm/reg.h diff --git a/include/asm-mips/regdef.h b/arch/mips/include/asm/regdef.h similarity index 100% rename from include/asm-mips/regdef.h rename to arch/mips/include/asm/regdef.h diff --git a/include/asm-mips/resource.h b/arch/mips/include/asm/resource.h similarity index 100% rename from include/asm-mips/resource.h rename to arch/mips/include/asm/resource.h diff --git a/include/asm-mips/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h similarity index 100% rename from include/asm-mips/rm9k-ocd.h rename to arch/mips/include/asm/rm9k-ocd.h diff --git a/include/asm-mips/rtlx.h b/arch/mips/include/asm/rtlx.h similarity index 100% rename from include/asm-mips/rtlx.h rename to arch/mips/include/asm/rtlx.h diff --git a/include/asm-mips/scatterlist.h b/arch/mips/include/asm/scatterlist.h similarity index 100% rename from include/asm-mips/scatterlist.h rename to arch/mips/include/asm/scatterlist.h diff --git a/include/asm-mips/seccomp.h b/arch/mips/include/asm/seccomp.h similarity index 100% rename from include/asm-mips/seccomp.h rename to arch/mips/include/asm/seccomp.h diff --git a/include/asm-mips/sections.h b/arch/mips/include/asm/sections.h similarity index 100% rename from include/asm-mips/sections.h rename to arch/mips/include/asm/sections.h diff --git a/include/asm-mips/segment.h b/arch/mips/include/asm/segment.h similarity index 100% rename from include/asm-mips/segment.h rename to arch/mips/include/asm/segment.h diff --git a/include/asm-mips/sembuf.h b/arch/mips/include/asm/sembuf.h similarity index 100% rename from include/asm-mips/sembuf.h rename to arch/mips/include/asm/sembuf.h diff --git a/include/asm-mips/serial.h b/arch/mips/include/asm/serial.h similarity index 100% rename from include/asm-mips/serial.h rename to arch/mips/include/asm/serial.h diff --git a/include/asm-mips/setup.h b/arch/mips/include/asm/setup.h similarity index 100% rename from include/asm-mips/setup.h rename to arch/mips/include/asm/setup.h diff --git a/include/asm-mips/sgi/gio.h b/arch/mips/include/asm/sgi/gio.h similarity index 100% rename from include/asm-mips/sgi/gio.h rename to arch/mips/include/asm/sgi/gio.h diff --git a/include/asm-mips/sgi/hpc3.h b/arch/mips/include/asm/sgi/hpc3.h similarity index 100% rename from include/asm-mips/sgi/hpc3.h rename to arch/mips/include/asm/sgi/hpc3.h diff --git a/include/asm-mips/sgi/ioc.h b/arch/mips/include/asm/sgi/ioc.h similarity index 100% rename from include/asm-mips/sgi/ioc.h rename to arch/mips/include/asm/sgi/ioc.h diff --git a/include/asm-mips/sgi/ip22.h b/arch/mips/include/asm/sgi/ip22.h similarity index 100% rename from include/asm-mips/sgi/ip22.h rename to arch/mips/include/asm/sgi/ip22.h diff --git a/include/asm-mips/sgi/mc.h b/arch/mips/include/asm/sgi/mc.h similarity index 100% rename from include/asm-mips/sgi/mc.h rename to arch/mips/include/asm/sgi/mc.h diff --git a/include/asm-mips/sgi/pi1.h b/arch/mips/include/asm/sgi/pi1.h similarity index 100% rename from include/asm-mips/sgi/pi1.h rename to arch/mips/include/asm/sgi/pi1.h diff --git a/include/asm-mips/sgi/seeq.h b/arch/mips/include/asm/sgi/seeq.h similarity index 100% rename from include/asm-mips/sgi/seeq.h rename to arch/mips/include/asm/sgi/seeq.h diff --git a/include/asm-mips/sgi/sgi.h b/arch/mips/include/asm/sgi/sgi.h similarity index 100% rename from include/asm-mips/sgi/sgi.h rename to arch/mips/include/asm/sgi/sgi.h diff --git a/include/asm-mips/sgi/wd.h b/arch/mips/include/asm/sgi/wd.h similarity index 100% rename from include/asm-mips/sgi/wd.h rename to arch/mips/include/asm/sgi/wd.h diff --git a/include/asm-mips/sgialib.h b/arch/mips/include/asm/sgialib.h similarity index 100% rename from include/asm-mips/sgialib.h rename to arch/mips/include/asm/sgialib.h diff --git a/include/asm-mips/sgiarcs.h b/arch/mips/include/asm/sgiarcs.h similarity index 100% rename from include/asm-mips/sgiarcs.h rename to arch/mips/include/asm/sgiarcs.h diff --git a/include/asm-mips/sgidefs.h b/arch/mips/include/asm/sgidefs.h similarity index 100% rename from include/asm-mips/sgidefs.h rename to arch/mips/include/asm/sgidefs.h diff --git a/include/asm-mips/shmbuf.h b/arch/mips/include/asm/shmbuf.h similarity index 100% rename from include/asm-mips/shmbuf.h rename to arch/mips/include/asm/shmbuf.h diff --git a/include/asm-mips/shmparam.h b/arch/mips/include/asm/shmparam.h similarity index 100% rename from include/asm-mips/shmparam.h rename to arch/mips/include/asm/shmparam.h diff --git a/include/asm-mips/sibyte/bcm1480_int.h b/arch/mips/include/asm/sibyte/bcm1480_int.h similarity index 100% rename from include/asm-mips/sibyte/bcm1480_int.h rename to arch/mips/include/asm/sibyte/bcm1480_int.h diff --git a/include/asm-mips/sibyte/bcm1480_l2c.h b/arch/mips/include/asm/sibyte/bcm1480_l2c.h similarity index 100% rename from include/asm-mips/sibyte/bcm1480_l2c.h rename to arch/mips/include/asm/sibyte/bcm1480_l2c.h diff --git a/include/asm-mips/sibyte/bcm1480_mc.h b/arch/mips/include/asm/sibyte/bcm1480_mc.h similarity index 100% rename from include/asm-mips/sibyte/bcm1480_mc.h rename to arch/mips/include/asm/sibyte/bcm1480_mc.h diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/arch/mips/include/asm/sibyte/bcm1480_regs.h similarity index 100% rename from include/asm-mips/sibyte/bcm1480_regs.h rename to arch/mips/include/asm/sibyte/bcm1480_regs.h diff --git a/include/asm-mips/sibyte/bcm1480_scd.h b/arch/mips/include/asm/sibyte/bcm1480_scd.h similarity index 100% rename from include/asm-mips/sibyte/bcm1480_scd.h rename to arch/mips/include/asm/sibyte/bcm1480_scd.h diff --git a/include/asm-mips/sibyte/bigsur.h b/arch/mips/include/asm/sibyte/bigsur.h similarity index 100% rename from include/asm-mips/sibyte/bigsur.h rename to arch/mips/include/asm/sibyte/bigsur.h diff --git a/include/asm-mips/sibyte/board.h b/arch/mips/include/asm/sibyte/board.h similarity index 100% rename from include/asm-mips/sibyte/board.h rename to arch/mips/include/asm/sibyte/board.h diff --git a/include/asm-mips/sibyte/carmel.h b/arch/mips/include/asm/sibyte/carmel.h similarity index 100% rename from include/asm-mips/sibyte/carmel.h rename to arch/mips/include/asm/sibyte/carmel.h diff --git a/include/asm-mips/sibyte/sb1250.h b/arch/mips/include/asm/sibyte/sb1250.h similarity index 100% rename from include/asm-mips/sibyte/sb1250.h rename to arch/mips/include/asm/sibyte/sb1250.h diff --git a/include/asm-mips/sibyte/sb1250_defs.h b/arch/mips/include/asm/sibyte/sb1250_defs.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_defs.h rename to arch/mips/include/asm/sibyte/sb1250_defs.h diff --git a/include/asm-mips/sibyte/sb1250_dma.h b/arch/mips/include/asm/sibyte/sb1250_dma.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_dma.h rename to arch/mips/include/asm/sibyte/sb1250_dma.h diff --git a/include/asm-mips/sibyte/sb1250_genbus.h b/arch/mips/include/asm/sibyte/sb1250_genbus.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_genbus.h rename to arch/mips/include/asm/sibyte/sb1250_genbus.h diff --git a/include/asm-mips/sibyte/sb1250_int.h b/arch/mips/include/asm/sibyte/sb1250_int.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_int.h rename to arch/mips/include/asm/sibyte/sb1250_int.h diff --git a/include/asm-mips/sibyte/sb1250_l2c.h b/arch/mips/include/asm/sibyte/sb1250_l2c.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_l2c.h rename to arch/mips/include/asm/sibyte/sb1250_l2c.h diff --git a/include/asm-mips/sibyte/sb1250_ldt.h b/arch/mips/include/asm/sibyte/sb1250_ldt.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_ldt.h rename to arch/mips/include/asm/sibyte/sb1250_ldt.h diff --git a/include/asm-mips/sibyte/sb1250_mac.h b/arch/mips/include/asm/sibyte/sb1250_mac.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_mac.h rename to arch/mips/include/asm/sibyte/sb1250_mac.h diff --git a/include/asm-mips/sibyte/sb1250_mc.h b/arch/mips/include/asm/sibyte/sb1250_mc.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_mc.h rename to arch/mips/include/asm/sibyte/sb1250_mc.h diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/arch/mips/include/asm/sibyte/sb1250_regs.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_regs.h rename to arch/mips/include/asm/sibyte/sb1250_regs.h diff --git a/include/asm-mips/sibyte/sb1250_scd.h b/arch/mips/include/asm/sibyte/sb1250_scd.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_scd.h rename to arch/mips/include/asm/sibyte/sb1250_scd.h diff --git a/include/asm-mips/sibyte/sb1250_smbus.h b/arch/mips/include/asm/sibyte/sb1250_smbus.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_smbus.h rename to arch/mips/include/asm/sibyte/sb1250_smbus.h diff --git a/include/asm-mips/sibyte/sb1250_syncser.h b/arch/mips/include/asm/sibyte/sb1250_syncser.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_syncser.h rename to arch/mips/include/asm/sibyte/sb1250_syncser.h diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/arch/mips/include/asm/sibyte/sb1250_uart.h similarity index 100% rename from include/asm-mips/sibyte/sb1250_uart.h rename to arch/mips/include/asm/sibyte/sb1250_uart.h diff --git a/include/asm-mips/sibyte/sentosa.h b/arch/mips/include/asm/sibyte/sentosa.h similarity index 100% rename from include/asm-mips/sibyte/sentosa.h rename to arch/mips/include/asm/sibyte/sentosa.h diff --git a/include/asm-mips/sibyte/swarm.h b/arch/mips/include/asm/sibyte/swarm.h similarity index 100% rename from include/asm-mips/sibyte/swarm.h rename to arch/mips/include/asm/sibyte/swarm.h diff --git a/include/asm-mips/sigcontext.h b/arch/mips/include/asm/sigcontext.h similarity index 100% rename from include/asm-mips/sigcontext.h rename to arch/mips/include/asm/sigcontext.h diff --git a/include/asm-mips/siginfo.h b/arch/mips/include/asm/siginfo.h similarity index 100% rename from include/asm-mips/siginfo.h rename to arch/mips/include/asm/siginfo.h diff --git a/include/asm-mips/signal.h b/arch/mips/include/asm/signal.h similarity index 100% rename from include/asm-mips/signal.h rename to arch/mips/include/asm/signal.h diff --git a/include/asm-mips/sim.h b/arch/mips/include/asm/sim.h similarity index 100% rename from include/asm-mips/sim.h rename to arch/mips/include/asm/sim.h diff --git a/include/asm-mips/smp-ops.h b/arch/mips/include/asm/smp-ops.h similarity index 100% rename from include/asm-mips/smp-ops.h rename to arch/mips/include/asm/smp-ops.h diff --git a/include/asm-mips/smp.h b/arch/mips/include/asm/smp.h similarity index 100% rename from include/asm-mips/smp.h rename to arch/mips/include/asm/smp.h diff --git a/include/asm-mips/smtc.h b/arch/mips/include/asm/smtc.h similarity index 100% rename from include/asm-mips/smtc.h rename to arch/mips/include/asm/smtc.h diff --git a/include/asm-mips/smtc_ipi.h b/arch/mips/include/asm/smtc_ipi.h similarity index 100% rename from include/asm-mips/smtc_ipi.h rename to arch/mips/include/asm/smtc_ipi.h diff --git a/include/asm-mips/smtc_proc.h b/arch/mips/include/asm/smtc_proc.h similarity index 100% rename from include/asm-mips/smtc_proc.h rename to arch/mips/include/asm/smtc_proc.h diff --git a/include/asm-mips/smvp.h b/arch/mips/include/asm/smvp.h similarity index 100% rename from include/asm-mips/smvp.h rename to arch/mips/include/asm/smvp.h diff --git a/include/asm-mips/sn/addrs.h b/arch/mips/include/asm/sn/addrs.h similarity index 100% rename from include/asm-mips/sn/addrs.h rename to arch/mips/include/asm/sn/addrs.h diff --git a/include/asm-mips/sn/agent.h b/arch/mips/include/asm/sn/agent.h similarity index 100% rename from include/asm-mips/sn/agent.h rename to arch/mips/include/asm/sn/agent.h diff --git a/include/asm-mips/sn/arch.h b/arch/mips/include/asm/sn/arch.h similarity index 100% rename from include/asm-mips/sn/arch.h rename to arch/mips/include/asm/sn/arch.h diff --git a/include/asm-mips/sn/fru.h b/arch/mips/include/asm/sn/fru.h similarity index 100% rename from include/asm-mips/sn/fru.h rename to arch/mips/include/asm/sn/fru.h diff --git a/include/asm-mips/sn/gda.h b/arch/mips/include/asm/sn/gda.h similarity index 100% rename from include/asm-mips/sn/gda.h rename to arch/mips/include/asm/sn/gda.h diff --git a/include/asm-mips/sn/hub.h b/arch/mips/include/asm/sn/hub.h similarity index 100% rename from include/asm-mips/sn/hub.h rename to arch/mips/include/asm/sn/hub.h diff --git a/include/asm-mips/sn/intr.h b/arch/mips/include/asm/sn/intr.h similarity index 100% rename from include/asm-mips/sn/intr.h rename to arch/mips/include/asm/sn/intr.h diff --git a/include/asm-mips/sn/io.h b/arch/mips/include/asm/sn/io.h similarity index 100% rename from include/asm-mips/sn/io.h rename to arch/mips/include/asm/sn/io.h diff --git a/include/asm-mips/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h similarity index 100% rename from include/asm-mips/sn/ioc3.h rename to arch/mips/include/asm/sn/ioc3.h diff --git a/include/asm-mips/sn/klconfig.h b/arch/mips/include/asm/sn/klconfig.h similarity index 96% rename from include/asm-mips/sn/klconfig.h rename to arch/mips/include/asm/sn/klconfig.h index 96cfd2ab1bc..09e590daca1 100644 --- a/include/asm-mips/sn/klconfig.h +++ b/arch/mips/include/asm/sn/klconfig.h @@ -425,7 +425,7 @@ typedef struct lboard_s { unsigned char brd_sversion; /* version of this structure */ unsigned char brd_brevision; /* board revision */ unsigned char brd_promver; /* board prom version, if any */ - unsigned char brd_flags; /* Enabled, Disabled etc */ + unsigned char brd_flags; /* Enabled, Disabled etc */ unsigned char brd_slot; /* slot number */ unsigned short brd_debugsw; /* Debug switches */ moduleid_t brd_module; /* module to which it belongs */ @@ -595,9 +595,9 @@ typedef struct klcpu_s { /* CPU */ klinfo_t cpu_info; unsigned short cpu_prid; /* Processor PRID value */ unsigned short cpu_fpirr; /* FPU IRR value */ - unsigned short cpu_speed; /* Speed in MHZ */ - unsigned short cpu_scachesz; /* secondary cache size in MB */ - unsigned short cpu_scachespeed;/* secondary cache speed in MHz */ + unsigned short cpu_speed; /* Speed in MHZ */ + unsigned short cpu_scachesz; /* secondary cache size in MB */ + unsigned short cpu_scachespeed;/* secondary cache speed in MHz */ } klcpu_t ; #define CPU_STRUCT_VERSION 2 @@ -621,7 +621,7 @@ typedef struct klhub_uart_s { /* HUB */ typedef struct klmembnk_s { /* MEMORY BANK */ klinfo_t membnk_info; - short membnk_memsz; /* Total memory in megabytes */ + short membnk_memsz; /* Total memory in megabytes */ short membnk_dimm_select; /* bank to physical addr mapping*/ short membnk_bnksz[MD_MEM_BANKS]; /* Memory bank sizes */ short membnk_attr; @@ -657,7 +657,7 @@ typedef struct klmod_serial_num_s { typedef struct klxbow_s { /* XBOW */ klinfo_t xbow_info ; - klport_t xbow_port_info[MAX_XBOW_LINKS] ; /* Module number */ + klport_t xbow_port_info[MAX_XBOW_LINKS] ; /* Module number */ int xbow_master_hub_link; /* type of brd connected+component struct ptr+flags */ } klxbow_t ; @@ -673,9 +673,9 @@ typedef struct klpci_device_s { typedef struct klbri_s { /* BRIDGE */ klinfo_t bri_info ; - unsigned char bri_eprominfo ; /* IO6prom connected to bridge */ - unsigned char bri_bustype ; /* PCI/VME BUS bridge/GIO */ - pci_t pci_specific ; /* PCI Board config info */ + unsigned char bri_eprominfo ; /* IO6prom connected to bridge */ + unsigned char bri_bustype ; /* PCI/VME BUS bridge/GIO */ + pci_t pci_specific ; /* PCI Board config info */ klpci_device_t bri_devices[MAX_PCI_DEVS] ; /* PCI IDs */ klconf_off_t bri_mfg_nic ; } klbri_t ; @@ -684,9 +684,9 @@ typedef struct klbri_s { /* BRIDGE */ typedef struct klioc3_s { /* IOC3 */ klinfo_t ioc3_info ; - unsigned char ioc3_ssram ; /* Info about ssram */ - unsigned char ioc3_nvram ; /* Info about nvram */ - klinfo_t ioc3_superio ; /* Info about superio */ + unsigned char ioc3_ssram ; /* Info about ssram */ + unsigned char ioc3_nvram ; /* Info about nvram */ + klinfo_t ioc3_superio ; /* Info about superio */ klconf_off_t ioc3_tty_off ; klinfo_t ioc3_enet ; klconf_off_t ioc3_enet_off ; @@ -698,13 +698,13 @@ typedef struct klioc3_s { /* IOC3 */ typedef struct klvmeb_s { /* VME BRIDGE - PCI CTLR */ klinfo_t vmeb_info ; vmeb_t vmeb_specific ; - klconf_off_t vmeb_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ + klconf_off_t vmeb_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ } klvmeb_t ; typedef struct klvmed_s { /* VME DEVICE - VME BOARD */ klinfo_t vmed_info ; vmed_t vmed_specific ; - klconf_off_t vmed_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ + klconf_off_t vmed_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ } klvmed_t ; #define ROUTER_VECTOR_VERS 2 @@ -714,7 +714,7 @@ typedef struct klrou_s { /* ROUTER */ klinfo_t rou_info ; unsigned int rou_flags ; /* PCFG_ROUTER_xxx flags */ nic_t rou_box_nic ; /* nic of the containing module */ - klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */ + klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */ klconf_off_t rou_mfg_nic ; /* MFG NIC string */ u64 rou_vector; /* vector from master node */ } klrou_t ; @@ -769,7 +769,7 @@ typedef struct klgsn_s { /* GSN board */ typedef struct klscsi_s { /* SCSI Controller */ klinfo_t scsi_info ; - scsi_t scsi_specific ; + scsi_t scsi_specific ; unsigned char scsi_numdevs ; klconf_off_t scsi_devinfo[MAX_SCSI_DEVS] ; } klscsi_t ; @@ -803,13 +803,13 @@ typedef struct klmsdev_s { /* mouse device */ typedef struct klfddi_s { /* FDDI */ klinfo_t fddi_info ; - fddi_t fddi_specific ; + fddi_t fddi_specific ; klconf_off_t fddi_devinfo[MAX_FDDI_DEVS] ; } klfddi_t ; typedef struct klmio_s { /* MIO */ klinfo_t mio_info ; - mio_t mio_specific ; + mio_t mio_specific ; } klmio_t ; diff --git a/include/asm-mips/sn/kldir.h b/arch/mips/include/asm/sn/kldir.h similarity index 100% rename from include/asm-mips/sn/kldir.h rename to arch/mips/include/asm/sn/kldir.h diff --git a/include/asm-mips/sn/klkernvars.h b/arch/mips/include/asm/sn/klkernvars.h similarity index 100% rename from include/asm-mips/sn/klkernvars.h rename to arch/mips/include/asm/sn/klkernvars.h diff --git a/include/asm-mips/sn/launch.h b/arch/mips/include/asm/sn/launch.h similarity index 100% rename from include/asm-mips/sn/launch.h rename to arch/mips/include/asm/sn/launch.h diff --git a/include/asm-mips/sn/mapped_kernel.h b/arch/mips/include/asm/sn/mapped_kernel.h similarity index 100% rename from include/asm-mips/sn/mapped_kernel.h rename to arch/mips/include/asm/sn/mapped_kernel.h diff --git a/include/asm-mips/sn/nmi.h b/arch/mips/include/asm/sn/nmi.h similarity index 100% rename from include/asm-mips/sn/nmi.h rename to arch/mips/include/asm/sn/nmi.h diff --git a/include/asm-mips/sn/sn0/addrs.h b/arch/mips/include/asm/sn/sn0/addrs.h similarity index 100% rename from include/asm-mips/sn/sn0/addrs.h rename to arch/mips/include/asm/sn/sn0/addrs.h diff --git a/include/asm-mips/sn/sn0/arch.h b/arch/mips/include/asm/sn/sn0/arch.h similarity index 100% rename from include/asm-mips/sn/sn0/arch.h rename to arch/mips/include/asm/sn/sn0/arch.h diff --git a/include/asm-mips/sn/sn0/hub.h b/arch/mips/include/asm/sn/sn0/hub.h similarity index 100% rename from include/asm-mips/sn/sn0/hub.h rename to arch/mips/include/asm/sn/sn0/hub.h diff --git a/include/asm-mips/sn/sn0/hubio.h b/arch/mips/include/asm/sn/sn0/hubio.h similarity index 96% rename from include/asm-mips/sn/sn0/hubio.h rename to arch/mips/include/asm/sn/sn0/hubio.h index 0187895e556..d0c29d4de08 100644 --- a/include/asm-mips/sn/sn0/hubio.h +++ b/arch/mips/include/asm/sn/sn0/hubio.h @@ -175,10 +175,10 @@ typedef union hubii_wid_u { u64 wid_reg_value; struct { u64 wid_rsvd: 32, /* unused */ - wid_rev_num: 4, /* revision number */ - wid_part_num: 16, /* the widget type: hub=c101 */ - wid_mfg_num: 11, /* Manufacturer id (IBM) */ - wid_rsvd1: 1; /* Reserved */ + wid_rev_num: 4, /* revision number */ + wid_part_num: 16, /* the widget type: hub=c101 */ + wid_mfg_num: 11, /* Manufacturer id (IBM) */ + wid_rsvd1: 1; /* Reserved */ } wid_fields_s; } hubii_wid_t; @@ -187,13 +187,13 @@ typedef union hubii_wcr_u { u64 wcr_reg_value; struct { u64 wcr_rsvd: 41, /* unused */ - wcr_e_thresh: 5, /* elasticity threshold */ + wcr_e_thresh: 5, /* elasticity threshold */ wcr_dir_con: 1, /* widget direct connect */ - wcr_f_bad_pkt: 1, /* Force bad llp pkt enable */ - wcr_xbar_crd: 3, /* LLP crossbar credit */ - wcr_rsvd1: 8, /* Reserved */ + wcr_f_bad_pkt: 1, /* Force bad llp pkt enable */ + wcr_xbar_crd: 3, /* LLP crossbar credit */ + wcr_rsvd1: 8, /* Reserved */ wcr_tag_mode: 1, /* Tag mode */ - wcr_widget_id: 4; /* LLP crossbar credit */ + wcr_widget_id: 4; /* LLP crossbar credit */ } wcr_fields_s; } hubii_wcr_t; @@ -220,14 +220,14 @@ typedef union hubii_ilcsr_u { u64 icsr_reg_value; struct { u64 icsr_rsvd: 22, /* unused */ - icsr_max_burst: 10, /* max burst */ + icsr_max_burst: 10, /* max burst */ icsr_rsvd4: 6, /* reserved */ - icsr_max_retry: 10, /* max retry */ + icsr_max_retry: 10, /* max retry */ icsr_rsvd3: 2, /* reserved */ icsr_lnk_stat: 2, /* link status */ icsr_bm8: 1, /* Bit mode 8 */ icsr_llp_en: 1, /* LLP enable bit */ - icsr_rsvd2: 1, /* reserver */ + icsr_rsvd2: 1, /* reserver */ icsr_wrm_reset: 1, /* Warm reset bit */ icsr_rsvd1: 2, /* Data ready offset */ icsr_null_to: 6; /* Null timeout */ @@ -240,9 +240,9 @@ typedef union hubii_iowa_u { u64 iowa_reg_value; struct { u64 iowa_rsvd: 48, /* unused */ - iowa_wxoac: 8, /* xtalk widget access bits */ - iowa_rsvd1: 7, /* xtalk widget access bits */ - iowa_w0oac: 1; /* xtalk widget access bits */ + iowa_wxoac: 8, /* xtalk widget access bits */ + iowa_rsvd1: 7, /* xtalk widget access bits */ + iowa_w0oac: 1; /* xtalk widget access bits */ } iowa_fields_s; } hubii_iowa_t; @@ -261,7 +261,7 @@ typedef union hubii_illr_u { struct { u64 illr_rsvd: 32, /* unused */ illr_cb_cnt: 16, /* checkbit error count */ - illr_sn_cnt: 16; /* sequence number count */ + illr_sn_cnt: 16; /* sequence number count */ } illr_fields_s; } hubii_illr_t; @@ -275,7 +275,7 @@ typedef union io_perf_sel { struct { u64 perf_rsvd : 48, perf_icct : 8, - perf_ippr1 : 4, + perf_ippr1 : 4, perf_ippr0 : 4; } perf_sel_bits; } io_perf_sel_t; @@ -733,7 +733,7 @@ typedef union hubii_ifdr_u { u64 ifdr_rsvd: 49, ifdr_maxrp: 7, ifdr_rsvd1: 1, - ifdr_maxrq: 7; + ifdr_maxrq: 7; } hi_ifdr_fields; } hubii_ifdr_t; diff --git a/include/asm-mips/sn/sn0/hubmd.h b/arch/mips/include/asm/sn/sn0/hubmd.h similarity index 100% rename from include/asm-mips/sn/sn0/hubmd.h rename to arch/mips/include/asm/sn/sn0/hubmd.h diff --git a/include/asm-mips/sn/sn0/hubni.h b/arch/mips/include/asm/sn/sn0/hubni.h similarity index 100% rename from include/asm-mips/sn/sn0/hubni.h rename to arch/mips/include/asm/sn/sn0/hubni.h diff --git a/include/asm-mips/sn/sn0/hubpi.h b/arch/mips/include/asm/sn/sn0/hubpi.h similarity index 100% rename from include/asm-mips/sn/sn0/hubpi.h rename to arch/mips/include/asm/sn/sn0/hubpi.h diff --git a/include/asm-mips/sn/sn0/ip27.h b/arch/mips/include/asm/sn/sn0/ip27.h similarity index 100% rename from include/asm-mips/sn/sn0/ip27.h rename to arch/mips/include/asm/sn/sn0/ip27.h diff --git a/include/asm-mips/sn/sn_private.h b/arch/mips/include/asm/sn/sn_private.h similarity index 100% rename from include/asm-mips/sn/sn_private.h rename to arch/mips/include/asm/sn/sn_private.h diff --git a/include/asm-mips/sn/types.h b/arch/mips/include/asm/sn/types.h similarity index 100% rename from include/asm-mips/sn/types.h rename to arch/mips/include/asm/sn/types.h diff --git a/include/asm-mips/sni.h b/arch/mips/include/asm/sni.h similarity index 100% rename from include/asm-mips/sni.h rename to arch/mips/include/asm/sni.h diff --git a/include/asm-mips/socket.h b/arch/mips/include/asm/socket.h similarity index 100% rename from include/asm-mips/socket.h rename to arch/mips/include/asm/socket.h diff --git a/include/asm-mips/sockios.h b/arch/mips/include/asm/sockios.h similarity index 100% rename from include/asm-mips/sockios.h rename to arch/mips/include/asm/sockios.h diff --git a/include/asm-mips/sparsemem.h b/arch/mips/include/asm/sparsemem.h similarity index 100% rename from include/asm-mips/sparsemem.h rename to arch/mips/include/asm/sparsemem.h diff --git a/include/asm-mips/spinlock.h b/arch/mips/include/asm/spinlock.h similarity index 100% rename from include/asm-mips/spinlock.h rename to arch/mips/include/asm/spinlock.h diff --git a/include/asm-mips/spinlock_types.h b/arch/mips/include/asm/spinlock_types.h similarity index 100% rename from include/asm-mips/spinlock_types.h rename to arch/mips/include/asm/spinlock_types.h diff --git a/include/asm-mips/stackframe.h b/arch/mips/include/asm/stackframe.h similarity index 100% rename from include/asm-mips/stackframe.h rename to arch/mips/include/asm/stackframe.h diff --git a/include/asm-mips/stacktrace.h b/arch/mips/include/asm/stacktrace.h similarity index 100% rename from include/asm-mips/stacktrace.h rename to arch/mips/include/asm/stacktrace.h diff --git a/include/asm-mips/stat.h b/arch/mips/include/asm/stat.h similarity index 100% rename from include/asm-mips/stat.h rename to arch/mips/include/asm/stat.h diff --git a/include/asm-mips/statfs.h b/arch/mips/include/asm/statfs.h similarity index 100% rename from include/asm-mips/statfs.h rename to arch/mips/include/asm/statfs.h diff --git a/include/asm-mips/string.h b/arch/mips/include/asm/string.h similarity index 100% rename from include/asm-mips/string.h rename to arch/mips/include/asm/string.h diff --git a/include/asm-mips/suspend.h b/arch/mips/include/asm/suspend.h similarity index 100% rename from include/asm-mips/suspend.h rename to arch/mips/include/asm/suspend.h diff --git a/include/asm-mips/sysmips.h b/arch/mips/include/asm/sysmips.h similarity index 100% rename from include/asm-mips/sysmips.h rename to arch/mips/include/asm/sysmips.h diff --git a/include/asm-mips/system.h b/arch/mips/include/asm/system.h similarity index 100% rename from include/asm-mips/system.h rename to arch/mips/include/asm/system.h diff --git a/include/asm-mips/termbits.h b/arch/mips/include/asm/termbits.h similarity index 100% rename from include/asm-mips/termbits.h rename to arch/mips/include/asm/termbits.h diff --git a/include/asm-mips/termios.h b/arch/mips/include/asm/termios.h similarity index 100% rename from include/asm-mips/termios.h rename to arch/mips/include/asm/termios.h diff --git a/include/asm-mips/thread_info.h b/arch/mips/include/asm/thread_info.h similarity index 100% rename from include/asm-mips/thread_info.h rename to arch/mips/include/asm/thread_info.h diff --git a/include/asm-mips/time.h b/arch/mips/include/asm/time.h similarity index 100% rename from include/asm-mips/time.h rename to arch/mips/include/asm/time.h diff --git a/include/asm-mips/timex.h b/arch/mips/include/asm/timex.h similarity index 100% rename from include/asm-mips/timex.h rename to arch/mips/include/asm/timex.h diff --git a/include/asm-mips/titan_dep.h b/arch/mips/include/asm/titan_dep.h similarity index 100% rename from include/asm-mips/titan_dep.h rename to arch/mips/include/asm/titan_dep.h diff --git a/include/asm-mips/tlb.h b/arch/mips/include/asm/tlb.h similarity index 100% rename from include/asm-mips/tlb.h rename to arch/mips/include/asm/tlb.h diff --git a/include/asm-mips/tlbdebug.h b/arch/mips/include/asm/tlbdebug.h similarity index 100% rename from include/asm-mips/tlbdebug.h rename to arch/mips/include/asm/tlbdebug.h diff --git a/include/asm-mips/tlbflush.h b/arch/mips/include/asm/tlbflush.h similarity index 100% rename from include/asm-mips/tlbflush.h rename to arch/mips/include/asm/tlbflush.h diff --git a/include/asm-mips/topology.h b/arch/mips/include/asm/topology.h similarity index 100% rename from include/asm-mips/topology.h rename to arch/mips/include/asm/topology.h diff --git a/include/asm-mips/traps.h b/arch/mips/include/asm/traps.h similarity index 100% rename from include/asm-mips/traps.h rename to arch/mips/include/asm/traps.h diff --git a/include/asm-mips/txx9/boards.h b/arch/mips/include/asm/txx9/boards.h similarity index 100% rename from include/asm-mips/txx9/boards.h rename to arch/mips/include/asm/txx9/boards.h diff --git a/include/asm-mips/txx9/generic.h b/arch/mips/include/asm/txx9/generic.h similarity index 100% rename from include/asm-mips/txx9/generic.h rename to arch/mips/include/asm/txx9/generic.h diff --git a/include/asm-mips/txx9/jmr3927.h b/arch/mips/include/asm/txx9/jmr3927.h similarity index 100% rename from include/asm-mips/txx9/jmr3927.h rename to arch/mips/include/asm/txx9/jmr3927.h diff --git a/include/asm-mips/txx9/pci.h b/arch/mips/include/asm/txx9/pci.h similarity index 100% rename from include/asm-mips/txx9/pci.h rename to arch/mips/include/asm/txx9/pci.h diff --git a/include/asm-mips/txx9/rbtx4927.h b/arch/mips/include/asm/txx9/rbtx4927.h similarity index 100% rename from include/asm-mips/txx9/rbtx4927.h rename to arch/mips/include/asm/txx9/rbtx4927.h diff --git a/include/asm-mips/txx9/rbtx4938.h b/arch/mips/include/asm/txx9/rbtx4938.h similarity index 100% rename from include/asm-mips/txx9/rbtx4938.h rename to arch/mips/include/asm/txx9/rbtx4938.h diff --git a/include/asm-mips/txx9/rbtx4939.h b/arch/mips/include/asm/txx9/rbtx4939.h similarity index 100% rename from include/asm-mips/txx9/rbtx4939.h rename to arch/mips/include/asm/txx9/rbtx4939.h diff --git a/include/asm-mips/txx9/smsc_fdc37m81x.h b/arch/mips/include/asm/txx9/smsc_fdc37m81x.h similarity index 100% rename from include/asm-mips/txx9/smsc_fdc37m81x.h rename to arch/mips/include/asm/txx9/smsc_fdc37m81x.h diff --git a/include/asm-mips/txx9/spi.h b/arch/mips/include/asm/txx9/spi.h similarity index 100% rename from include/asm-mips/txx9/spi.h rename to arch/mips/include/asm/txx9/spi.h diff --git a/include/asm-mips/txx9/tx3927.h b/arch/mips/include/asm/txx9/tx3927.h similarity index 100% rename from include/asm-mips/txx9/tx3927.h rename to arch/mips/include/asm/txx9/tx3927.h diff --git a/include/asm-mips/txx9/tx4927.h b/arch/mips/include/asm/txx9/tx4927.h similarity index 100% rename from include/asm-mips/txx9/tx4927.h rename to arch/mips/include/asm/txx9/tx4927.h diff --git a/include/asm-mips/txx9/tx4927pcic.h b/arch/mips/include/asm/txx9/tx4927pcic.h similarity index 100% rename from include/asm-mips/txx9/tx4927pcic.h rename to arch/mips/include/asm/txx9/tx4927pcic.h diff --git a/include/asm-mips/txx9/tx4938.h b/arch/mips/include/asm/txx9/tx4938.h similarity index 100% rename from include/asm-mips/txx9/tx4938.h rename to arch/mips/include/asm/txx9/tx4938.h diff --git a/include/asm-mips/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h similarity index 100% rename from include/asm-mips/txx9/tx4939.h rename to arch/mips/include/asm/txx9/tx4939.h diff --git a/include/asm-mips/txx9irq.h b/arch/mips/include/asm/txx9irq.h similarity index 100% rename from include/asm-mips/txx9irq.h rename to arch/mips/include/asm/txx9irq.h diff --git a/include/asm-mips/txx9pio.h b/arch/mips/include/asm/txx9pio.h similarity index 100% rename from include/asm-mips/txx9pio.h rename to arch/mips/include/asm/txx9pio.h diff --git a/include/asm-mips/txx9tmr.h b/arch/mips/include/asm/txx9tmr.h similarity index 100% rename from include/asm-mips/txx9tmr.h rename to arch/mips/include/asm/txx9tmr.h diff --git a/include/asm-mips/types.h b/arch/mips/include/asm/types.h similarity index 100% rename from include/asm-mips/types.h rename to arch/mips/include/asm/types.h diff --git a/include/asm-mips/uaccess.h b/arch/mips/include/asm/uaccess.h similarity index 100% rename from include/asm-mips/uaccess.h rename to arch/mips/include/asm/uaccess.h diff --git a/include/asm-mips/ucontext.h b/arch/mips/include/asm/ucontext.h similarity index 100% rename from include/asm-mips/ucontext.h rename to arch/mips/include/asm/ucontext.h diff --git a/include/asm-mips/unaligned.h b/arch/mips/include/asm/unaligned.h similarity index 100% rename from include/asm-mips/unaligned.h rename to arch/mips/include/asm/unaligned.h diff --git a/include/asm-mips/unistd.h b/arch/mips/include/asm/unistd.h similarity index 100% rename from include/asm-mips/unistd.h rename to arch/mips/include/asm/unistd.h diff --git a/include/asm-mips/user.h b/arch/mips/include/asm/user.h similarity index 100% rename from include/asm-mips/user.h rename to arch/mips/include/asm/user.h diff --git a/include/asm-mips/vga.h b/arch/mips/include/asm/vga.h similarity index 100% rename from include/asm-mips/vga.h rename to arch/mips/include/asm/vga.h diff --git a/include/asm-mips/vpe.h b/arch/mips/include/asm/vpe.h similarity index 100% rename from include/asm-mips/vpe.h rename to arch/mips/include/asm/vpe.h diff --git a/include/asm-mips/vr41xx/capcella.h b/arch/mips/include/asm/vr41xx/capcella.h similarity index 100% rename from include/asm-mips/vr41xx/capcella.h rename to arch/mips/include/asm/vr41xx/capcella.h diff --git a/include/asm-mips/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h similarity index 100% rename from include/asm-mips/vr41xx/giu.h rename to arch/mips/include/asm/vr41xx/giu.h diff --git a/include/asm-mips/vr41xx/irq.h b/arch/mips/include/asm/vr41xx/irq.h similarity index 100% rename from include/asm-mips/vr41xx/irq.h rename to arch/mips/include/asm/vr41xx/irq.h diff --git a/include/asm-mips/vr41xx/mpc30x.h b/arch/mips/include/asm/vr41xx/mpc30x.h similarity index 100% rename from include/asm-mips/vr41xx/mpc30x.h rename to arch/mips/include/asm/vr41xx/mpc30x.h diff --git a/include/asm-mips/vr41xx/pci.h b/arch/mips/include/asm/vr41xx/pci.h similarity index 100% rename from include/asm-mips/vr41xx/pci.h rename to arch/mips/include/asm/vr41xx/pci.h diff --git a/include/asm-mips/vr41xx/siu.h b/arch/mips/include/asm/vr41xx/siu.h similarity index 100% rename from include/asm-mips/vr41xx/siu.h rename to arch/mips/include/asm/vr41xx/siu.h diff --git a/include/asm-mips/vr41xx/tb0219.h b/arch/mips/include/asm/vr41xx/tb0219.h similarity index 100% rename from include/asm-mips/vr41xx/tb0219.h rename to arch/mips/include/asm/vr41xx/tb0219.h diff --git a/include/asm-mips/vr41xx/tb0226.h b/arch/mips/include/asm/vr41xx/tb0226.h similarity index 100% rename from include/asm-mips/vr41xx/tb0226.h rename to arch/mips/include/asm/vr41xx/tb0226.h diff --git a/include/asm-mips/vr41xx/tb0287.h b/arch/mips/include/asm/vr41xx/tb0287.h similarity index 100% rename from include/asm-mips/vr41xx/tb0287.h rename to arch/mips/include/asm/vr41xx/tb0287.h diff --git a/include/asm-mips/vr41xx/vr41xx.h b/arch/mips/include/asm/vr41xx/vr41xx.h similarity index 100% rename from include/asm-mips/vr41xx/vr41xx.h rename to arch/mips/include/asm/vr41xx/vr41xx.h diff --git a/include/asm-mips/war.h b/arch/mips/include/asm/war.h similarity index 100% rename from include/asm-mips/war.h rename to arch/mips/include/asm/war.h diff --git a/include/asm-mips/wbflush.h b/arch/mips/include/asm/wbflush.h similarity index 100% rename from include/asm-mips/wbflush.h rename to arch/mips/include/asm/wbflush.h diff --git a/include/asm-mips/xor.h b/arch/mips/include/asm/xor.h similarity index 100% rename from include/asm-mips/xor.h rename to arch/mips/include/asm/xor.h diff --git a/include/asm-mips/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h similarity index 100% rename from include/asm-mips/xtalk/xtalk.h rename to arch/mips/include/asm/xtalk/xtalk.h diff --git a/include/asm-mips/xtalk/xwidget.h b/arch/mips/include/asm/xtalk/xwidget.h similarity index 100% rename from include/asm-mips/xtalk/xwidget.h rename to arch/mips/include/asm/xtalk/xwidget.h -- GitLab From d86a8123b11a9a40d850f6e88b89c948c2477da3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: [PATCH 3908/5416] MIPS: IP checksums: Remove unncessary folding of sum to 16 bit. Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index edac9892c51..201d82ee4c7 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -276,11 +276,6 @@ LEAF(csum_partial) dsra32 sum, sum, 0 addu sum, v1 #endif - sll v1, sum, 16 - addu sum, v1 - sltu v1, sum, v1 - srl sum, sum, 16 - addu sum, v1 /* odd buffer alignment? */ beqz t7, 1f @@ -678,11 +673,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) dsra32 sum, sum, 0 addu sum, v1 #endif - sll v1, sum, 16 - addu sum, v1 - sltu v1, sum, v1 - srl sum, sum, 16 - addu sum, v1 /* odd buffer alignment? */ beqz odd, 1f -- GitLab From 60724ca59eda766a30be57aec6b49bc3e2bead91 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: [PATCH 3909/5416] MIPS: IP checksums: Remove unncessary .set pseudos They possibly silence meaningful warnings ... Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 201d82ee4c7..84d5e6a1e76 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -55,20 +55,14 @@ #define UNIT(unit) ((unit)*NBYTES) #define ADDC(sum,reg) \ - .set push; \ - .set noat; \ ADD sum, reg; \ sltu v1, sum, reg; \ ADD sum, v1; \ - .set pop #define ADDC32(sum,reg) \ - .set push; \ - .set noat; \ addu sum, reg; \ sltu v1, sum, reg; \ addu sum, v1; \ - .set pop #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ @@ -267,8 +261,6 @@ LEAF(csum_partial) 1: ADDC(sum, t1) /* fold checksum */ - .set push - .set noat #ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 @@ -284,7 +276,6 @@ LEAF(csum_partial) srl sum, sum, 8 or sum, v1 andi sum, 0xffff - .set pop 1: .set reorder /* Add the passed partial csum. */ @@ -664,8 +655,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) ADDC(sum, t2) .Ldone: /* fold checksum */ - .set push - .set noat #ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 @@ -681,7 +670,6 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) srl sum, sum, 8 or sum, v1 andi sum, 0xffff - .set pop 1: .set reorder ADDC32(sum, psum) -- GitLab From b65a75b8c91c0f05047399401407371678fe9549 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:53 +0100 Subject: [PATCH 3910/5416] MIPS: IP checksums: Optimize adjust of sum on buffers of odd alignment. Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 84d5e6a1e76..6b876ca299e 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -270,13 +270,20 @@ LEAF(csum_partial) #endif /* odd buffer alignment? */ - beqz t7, 1f - nop - sll v1, sum, 8 +#ifdef CPU_MIPSR2 + wsbh v1, sum + movn sum, v1, t7 +#else + beqz t7, 1f /* odd buffer alignment? */ + lui v1, 0x00ff + addu v1, 0x00ff + and t0, sum, v1 + sll t0, t0, 8 srl sum, sum, 8 - or sum, v1 - andi sum, 0xffff + and sum, sum, v1 + or sum, sum, t0 1: +#endif .set reorder /* Add the passed partial csum. */ ADDC32(sum, a2) @@ -663,14 +670,20 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) addu sum, v1 #endif - /* odd buffer alignment? */ - beqz odd, 1f - nop - sll v1, sum, 8 +#ifdef CPU_MIPSR2 + wsbh v1, sum + movn sum, v1, odd +#else + beqz odd, 1f /* odd buffer alignment? */ + lui v1, 0x00ff + addu v1, 0x00ff + and t0, sum, v1 + sll t0, t0, 8 srl sum, sum, 8 - or sum, v1 - andi sum, 0xffff + and sum, sum, v1 + or sum, sum, t0 1: +#endif .set reorder ADDC32(sum, psum) jr ra -- GitLab From 2a31b03335e570dce5fdd082e0d71d48b2cb4290 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 28 Aug 2008 15:17:49 +0100 Subject: [PATCH 3911/5416] MIPS: Rewrite spinlocks to ticket locks. Based on patch by Chad Reese of Cavium Networks. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 5 - arch/mips/include/asm/spinlock.h | 253 ++++++++++++++++++------- arch/mips/include/asm/spinlock_types.h | 7 +- 3 files changed, 188 insertions(+), 77 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c15416c2e89..16097a8f5c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -610,11 +610,6 @@ source "arch/mips/vr41xx/Kconfig" endmenu -config GENERIC_LOCKBREAK - bool - default y - depends on SMP && PREEMPT - config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index bb897016c49..5d98a3cb85b 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -9,62 +9,125 @@ #ifndef _ASM_SPINLOCK_H #define _ASM_SPINLOCK_H +#include + #include #include /* * Your basic SMP spinlocks, allowing only a single CPU anywhere + * + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * These are fair FIFO ticket locks + * + * (the type definitions are in asm/spinlock_types.h) */ -#define __raw_spin_is_locked(x) ((x)->lock != 0) -#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) -#define __raw_spin_unlock_wait(x) \ - do { cpu_relax(); } while ((x)->lock) /* - * Simple spin lock operations. There are two variants, one clears IRQ's - * on the local processor, one does not. - * - * We make no fairness assumptions. They have a cost. + * Ticket locks are conceptually two parts, one indicating the current head of + * the queue, and the other indicating the current tail. The lock is acquired + * by atomically noting the tail and incrementing it by one (thus adding + * ourself to the queue and noting our position), then waiting until the head + * becomes equal to the the initial value of the tail. */ +static inline int __raw_spin_is_locked(raw_spinlock_t *lock) +{ + unsigned int counters = ACCESS_ONCE(lock->lock); + + return ((counters >> 14) ^ counters) & 0x1fff; +} + +#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) +#define __raw_spin_unlock_wait(x) \ + while (__raw_spin_is_locked(x)) { cpu_relax(); } + +static inline int __raw_spin_is_contended(raw_spinlock_t *lock) +{ + unsigned int counters = ACCESS_ONCE(lock->lock); + + return (((counters >> 14) - counters) & 0x1fff) > 1; +} + static inline void __raw_spin_lock(raw_spinlock_t *lock) { - unsigned int tmp; + int my_ticket; + int tmp; if (R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set noreorder # __raw_spin_lock \n" - "1: ll %1, %2 \n" - " bnez %1, 1b \n" - " li %1, 1 \n" - " sc %1, %0 \n" - " beqzl %1, 1b \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_lock \n" + " .set noreorder \n" + " \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " addiu %[my_ticket], %[ticket], 0x4000 \n" + " sc %[my_ticket], %[ticket_ptr] \n" + " beqzl %[my_ticket], 1b \n" " nop \n" - " .set reorder \n" - : "=m" (lock->lock), "=&r" (tmp) - : "m" (lock->lock) - : "memory"); + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " bne %[ticket], %[my_ticket], 4f \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + "2: \n" + " .subsection 2 \n" + "4: andi %[ticket], %[ticket], 0x1fff \n" + "5: sll %[ticket], 5 \n" + " \n" + "6: bnez %[ticket], 6b \n" + " subu %[ticket], 1 \n" + " \n" + " lw %[ticket], %[ticket_ptr] \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " beq %[ticket], %[my_ticket], 2b \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + " b 5b \n" + " subu %[ticket], %[ticket], 1 \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (my_ticket)); } else { - __asm__ __volatile__( - " .set noreorder # __raw_spin_lock \n" - "1: ll %1, %2 \n" - " bnez %1, 2f \n" - " li %1, 1 \n" - " sc %1, %0 \n" - " beqz %1, 2f \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_lock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: addiu %[my_ticket], %[ticket], 0x4000 \n" + " sc %[my_ticket], %[ticket_ptr] \n" + " beqz %[my_ticket], 3f \n" " nop \n" + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " bne %[ticket], %[my_ticket], 4f \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + "2: \n" " .subsection 2 \n" - "2: ll %1, %2 \n" - " bnez %1, 2b \n" - " li %1, 1 \n" - " b 1b \n" - " nop \n" + "3: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" + " \n" + "4: andi %[ticket], %[ticket], 0x1fff \n" + "5: sll %[ticket], 5 \n" + " \n" + "6: bnez %[ticket], 6b \n" + " subu %[ticket], 1 \n" + " \n" + " lw %[ticket], %[ticket_ptr] \n" + " andi %[ticket], %[ticket], 0x1fff \n" + " beq %[ticket], %[my_ticket], 2b \n" + " subu %[ticket], %[my_ticket], %[ticket] \n" + " b 5b \n" + " subu %[ticket], %[ticket], 1 \n" " .previous \n" - " .set reorder \n" - : "=m" (lock->lock), "=&r" (tmp) - : "m" (lock->lock) - : "memory"); + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (my_ticket)); } smp_llsc_mb(); @@ -72,55 +135,103 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) static inline void __raw_spin_unlock(raw_spinlock_t *lock) { - smp_mb(); + int tmp; - __asm__ __volatile__( - " .set noreorder # __raw_spin_unlock \n" - " sw $0, %0 \n" - " .set\treorder \n" - : "=m" (lock->lock) - : "m" (lock->lock) - : "memory"); + smp_llsc_mb(); + + if (R10000_LLSC_WAR) { + __asm__ __volatile__ ( + " # __raw_spin_unlock \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " addiu %[ticket], %[ticket], 1 \n" + " ori %[ticket], %[ticket], 0x2000 \n" + " xori %[ticket], %[ticket], 0x2000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqzl %[ticket], 2f \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp)); + } else { + __asm__ __volatile__ ( + " .set push # __raw_spin_unlock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: addiu %[ticket], %[ticket], 1 \n" + " ori %[ticket], %[ticket], 0x2000 \n" + " xori %[ticket], %[ticket], 0x2000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqz %[ticket], 2f \n" + " nop \n" + " \n" + " .subsection 2 \n" + "2: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp)); + } } static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock) { - unsigned int temp, res; + int tmp, tmp2, tmp3; if (R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set noreorder # __raw_spin_trylock \n" - "1: ll %0, %3 \n" - " ori %2, %0, 1 \n" - " sc %2, %1 \n" - " beqzl %2, 1b \n" - " nop \n" - " andi %2, %0, 1 \n" - " .set reorder" - : "=&r" (temp), "=m" (lock->lock), "=&r" (res) - : "m" (lock->lock) - : "memory"); + __asm__ __volatile__ ( + " .set push # __raw_spin_trylock \n" + " .set noreorder \n" + " \n" + "1: ll %[ticket], %[ticket_ptr] \n" + " srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[now_serving], %[ticket], 0x1fff \n" + " bne %[my_ticket], %[now_serving], 3f \n" + " addiu %[ticket], %[ticket], 0x4000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqzl %[ticket], 1b \n" + " li %[ticket], 1 \n" + "2: \n" + " .subsection 2 \n" + "3: b 2b \n" + " li %[ticket], 0 \n" + " .previous \n" + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (tmp2), + [now_serving] "=&r" (tmp3)); } else { - __asm__ __volatile__( - " .set noreorder # __raw_spin_trylock \n" - "1: ll %0, %3 \n" - " ori %2, %0, 1 \n" - " sc %2, %1 \n" - " beqz %2, 2f \n" - " andi %2, %0, 1 \n" + __asm__ __volatile__ ( + " .set push # __raw_spin_trylock \n" + " .set noreorder \n" + " \n" + " ll %[ticket], %[ticket_ptr] \n" + "1: srl %[my_ticket], %[ticket], 14 \n" + " andi %[my_ticket], %[my_ticket], 0x1fff \n" + " andi %[now_serving], %[ticket], 0x1fff \n" + " bne %[my_ticket], %[now_serving], 3f \n" + " addiu %[ticket], %[ticket], 0x4000 \n" + " sc %[ticket], %[ticket_ptr] \n" + " beqz %[ticket], 4f \n" + " li %[ticket], 1 \n" + "2: \n" " .subsection 2 \n" - "2: b 1b \n" - " nop \n" + "3: b 2b \n" + " li %[ticket], 0 \n" + "4: b 1b \n" + " ll %[ticket], %[ticket_ptr] \n" " .previous \n" - " .set reorder" - : "=&r" (temp), "=m" (lock->lock), "=&r" (res) - : "m" (lock->lock) - : "memory"); + " .set pop \n" + : [ticket_ptr] "+m" (lock->lock), + [ticket] "=&r" (tmp), + [my_ticket] "=&r" (tmp2), + [now_serving] "=&r" (tmp3)); } smp_llsc_mb(); - return res == 0; + return tmp; } /* diff --git a/arch/mips/include/asm/spinlock_types.h b/arch/mips/include/asm/spinlock_types.h index ce26c5048b1..adeedaa116c 100644 --- a/arch/mips/include/asm/spinlock_types.h +++ b/arch/mips/include/asm/spinlock_types.h @@ -6,7 +6,12 @@ #endif typedef struct { - volatile unsigned int lock; + /* + * bits 0..13: serving_now + * bits 14 : junk data + * bits 15..28: ticket + */ + unsigned int lock; } raw_spinlock_t; #define __RAW_SPIN_LOCK_UNLOCKED { 0 } -- GitLab From 4bacc68766b11c191ee1567f54103f109c002f4f Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 18 Sep 2008 00:13:58 +0900 Subject: [PATCH 3912/5416] MIPS: TXx9: Add TX4939 ATA support (v2) Add a helper routine to register tx4939ide driver and use it on RBTX4939 board. Signed-off-by: Atsushi Nemoto Acked-by: Sergei Shtylyov Signed-off-by: Ralf Baechle --- arch/mips/include/asm/txx9/tx4939.h | 1 + arch/mips/txx9/generic/setup_tx4939.c | 46 +++++++++++++++++++++++++++ arch/mips/txx9/rbtx4939/setup.c | 1 + 3 files changed, 48 insertions(+) diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h index 7ce2dff3b7c..88badb42301 100644 --- a/arch/mips/include/asm/txx9/tx4939.h +++ b/arch/mips/include/asm/txx9/tx4939.h @@ -540,5 +540,6 @@ void tx4939_setup_pcierr_irq(void); void tx4939_irq_init(void); int tx4939_irq(void); void tx4939_mtd_init(int ch); +void tx4939_ata_init(void); #endif /* __ASM_TXX9_TX4939_H */ diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index f14a497077d..6c0049a5bbc 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -389,6 +390,51 @@ void __init tx4939_mtd_init(int ch) txx9_physmap_flash_init(ch, start, size, &pdata); } +#define TX4939_ATA_REG_PHYS(ch) (TX4939_ATA_REG(ch) & 0xfffffffffULL) +void __init tx4939_ata_init(void) +{ + static struct resource ata0_res[] = { + { + .start = TX4939_ATA_REG_PHYS(0), + .end = TX4939_ATA_REG_PHYS(0) + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = TXX9_IRQ_BASE + TX4939_IR_ATA(0), + .flags = IORESOURCE_IRQ, + }, + }; + static struct resource ata1_res[] = { + { + .start = TX4939_ATA_REG_PHYS(1), + .end = TX4939_ATA_REG_PHYS(1) + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = TXX9_IRQ_BASE + TX4939_IR_ATA(1), + .flags = IORESOURCE_IRQ, + }, + }; + static struct platform_device ata0_dev = { + .name = "tx4939ide", + .id = 0, + .num_resources = ARRAY_SIZE(ata0_res), + .resource = ata0_res, + }; + static struct platform_device ata1_dev = { + .name = "tx4939ide", + .id = 1, + .num_resources = ARRAY_SIZE(ata1_res), + .resource = ata1_res, + }; + __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); + + if (pcfg & TX4939_PCFG_ATA0MODE) + platform_device_register(&ata0_dev); + if ((pcfg & (TX4939_PCFG_ATA1MODE | + TX4939_PCFG_ET1MODE | + TX4939_PCFG_ET0MODE)) == TX4939_PCFG_ATA1MODE) + platform_device_register(&ata1_dev); +} + static void __init tx4939_stop_unused_modules(void) { __u64 pcfg, rst = 0, ckd = 0; diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c index 277864d5e77..9855d7bccc2 100644 --- a/arch/mips/txx9/rbtx4939/setup.c +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -264,6 +264,7 @@ static void __init rbtx4939_device_init(void) #endif rbtx4939_led_setup(); tx4939_wdt_init(); + tx4939_ata_init(); } static void __init rbtx4939_setup(void) -- GitLab From 71ec6ccfdc2706e767189d40016fc802305067bb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 02:52:56 +0000 Subject: [PATCH 3913/5416] MIPS: Replace use of with native implementations. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/uaccess.h | 264 +++++++++++++++++++++++++++++++- 1 file changed, 263 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index b895144d577..09ff5bb1744 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -13,7 +13,6 @@ #include #include #include -#include /* * The fs value determines whether argument validity checking should be @@ -373,6 +372,269 @@ do { \ extern void __put_user_unknown(void); +/* + * put_user_unaligned: - Write a simple value into user space. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Returns zero on success, or -EFAULT on error. + */ +#define put_user_unaligned(x,ptr) \ + __put_user_unaligned_check((x),(ptr),sizeof(*(ptr))) + +/* + * get_user_unaligned: - Get a simple variable from user space. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define get_user_unaligned(x,ptr) \ + __get_user_unaligned_check((x),(ptr),sizeof(*(ptr))) + +/* + * __put_user_unaligned: - Write a simple value into user space, with less checking. + * @x: Value to copy to user space. + * @ptr: Destination address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple value from kernel space to user + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and @x must be assignable + * to the result of dereferencing @ptr. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + */ +#define __put_user_unaligned(x,ptr) \ + __put_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr))) + +/* + * __get_user_unaligned: - Get a simple variable from user space, with less checking. + * @x: Variable to store result. + * @ptr: Source address, in user space. + * + * Context: User context only. This function may sleep. + * + * This macro copies a single simple variable from user space to kernel + * space. It supports simple types like char and int, but not larger + * data types like structures or arrays. + * + * @ptr must have pointer-to-simple-variable type, and the result of + * dereferencing @ptr must be assignable to @x without a cast. + * + * Caller must check the pointer with access_ok() before calling this + * function. + * + * Returns zero on success, or -EFAULT on error. + * On error, the variable @x is set to zero. + */ +#define __get_user_unaligned(x,ptr) \ + __get_user__unalignednocheck((x),(ptr),sizeof(*(ptr))) + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __GET_USER_UNALIGNED_DW(val, ptr) \ + __get_user_unaligned_asm_ll32(val, ptr) +#endif +#ifdef CONFIG_64BIT +#define __GET_USER_UNALIGNED_DW(val, ptr) \ + __get_user_unaligned_asm(val, "uld", ptr) +#endif + +extern void __get_user_unaligned_unknown(void); + +#define __get_user_unaligned_common(val, size, ptr) \ +do { \ + switch (size) { \ + case 1: __get_user_asm(val, "lb", ptr); break; \ + case 2: __get_user_unaligned_asm(val, "ulh", ptr); break; \ + case 4: __get_user_unaligned_asm(val, "ulw", ptr); break; \ + case 8: __GET_USER_UNALIGNED_DW(val, ptr); break; \ + default: __get_user_unaligned_unknown(); break; \ + } \ +} while (0) + +#define __get_user_unaligned_nocheck(x,ptr,size) \ +({ \ + int __gu_err; \ + \ + __get_user_unaligned_common((x), size, ptr); \ + __gu_err; \ +}) + +#define __get_user_unaligned_check(x,ptr,size) \ +({ \ + int __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \ + \ + if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ + __get_user_unaligned_common((x), size, __gu_ptr); \ + \ + __gu_err; \ +}) + +#define __get_user_unaligned_asm(val, insn, addr) \ +{ \ + long __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: " insn " %1, %3 \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 3b \n" \ + " "__UA_ADDR "\t1b + 4, 3b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=r" (__gu_tmp) \ + : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ + \ + (val) = (__typeof__(*(addr))) __gu_tmp; \ +} + +/* + * Get a long long 64 using 32 bit registers. + */ +#define __get_user_unaligned_asm_ll32(val, addr) \ +{ \ + unsigned long long __gu_tmp; \ + \ + __asm__ __volatile__( \ + "1: ulw %1, (%3) \n" \ + "2: ulw %D1, 4(%3) \n" \ + " move %0, $0 \n" \ + "3: .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " move %1, $0 \n" \ + " move %D1, $0 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 1b + 4, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " " __UA_ADDR " 2b + 4, 4b \n" \ + " .previous \n" \ + : "=r" (__gu_err), "=&r" (__gu_tmp) \ + : "0" (0), "r" (addr), "i" (-EFAULT)); \ + (val) = (__typeof__(*(addr))) __gu_tmp; \ +} + +/* + * Yuck. We need two variants, one for 64bit operation and one + * for 32 bit mode and old iron. + */ +#ifdef CONFIG_32BIT +#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm_ll32(ptr) +#endif +#ifdef CONFIG_64BIT +#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm("usd", ptr) +#endif + +#define __put_user_unaligned_nocheck(x,ptr,size) \ +({ \ + __typeof__(*(ptr)) __pu_val; \ + int __pu_err = 0; \ + \ + __pu_val = (x); \ + switch (size) { \ + case 1: __put_user_asm("sb", ptr); break; \ + case 2: __put_user_unaligned_asm("ush", ptr); break; \ + case 4: __put_user_unaligned_asm("usw", ptr); break; \ + case 8: __PUT_USER_UNALIGNED_DW(ptr); break; \ + default: __put_user_unaligned_unknown(); break; \ + } \ + __pu_err; \ +}) + +#define __put_user_unaligned_check(x,ptr,size) \ +({ \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + int __pu_err = -EFAULT; \ + \ + if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ + switch (size) { \ + case 1: __put_user_asm("sb", __pu_addr); break; \ + case 2: __put_user_unaligned_asm("ush", __pu_addr); break; \ + case 4: __put_user_unaligned_asm("usw", __pu_addr); break; \ + case 8: __PUT_USER_UNALGINED_DW(__pu_addr); break; \ + default: __put_user_unaligned_unknown(); break; \ + } \ + } \ + __pu_err; \ +}) + +#define __put_user_unaligned_asm(insn, ptr) \ +{ \ + __asm__ __volatile__( \ + "1: " insn " %z2, %3 # __put_user_unaligned_asm\n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + "3: li %0, %4 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 3b \n" \ + " .previous \n" \ + : "=r" (__pu_err) \ + : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)), \ + "i" (-EFAULT)); \ +} + +#define __put_user_unaligned_asm_ll32(ptr) \ +{ \ + __asm__ __volatile__( \ + "1: sw %2, (%3) # __put_user_unaligned_asm_ll32 \n" \ + "2: sw %D2, 4(%3) \n" \ + "3: \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %4 \n" \ + " j 3b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " " __UA_ADDR " 1b, 4b \n" \ + " " __UA_ADDR " 1b + 4, 4b \n" \ + " " __UA_ADDR " 2b, 4b \n" \ + " " __UA_ADDR " 2b + 4, 4b \n" \ + " .previous" \ + : "=r" (__pu_err) \ + : "0" (0), "r" (__pu_val), "r" (ptr), \ + "i" (-EFAULT)); \ +} + +extern void __put_user_unaligned_unknown(void); + /* * We're generating jump to subroutines which will be outside the range of * jump instructions -- GitLab From 8192c9ea9ac44213d1266ecb64615519443979b3 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:04:26 -0700 Subject: [PATCH 3914/5416] MIPS: Add HARDWARE_WATCHPOINTS configure option. This is automatically set for all MIPS32 and MIPS64 processors. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 16097a8f5c5..cd5fbf6f078 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1268,6 +1268,13 @@ config CPU_SUPPORTS_32BIT_KERNEL config CPU_SUPPORTS_64BIT_KERNEL bool +# +# Set to y for ptrace access to watch registers. +# +config HARDWARE_WATCHPOINTS + bool + default y if CPU_MIPS32 || CPU_MIPS64 + menu "Kernel type" choice -- GitLab From 6aa3524c182c01b8b8b7c21c4da20c742a9b4d86 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:05:54 -0700 Subject: [PATCH 3915/5416] MIPS: Add HARDWARE_WATCHPOINTS definitions and support code. This is the main support code for the patch. Here we just add the code, the following patches hook it up. Signed-off-by: David Daney Signed-off-by: Ralf Baechle create mode 100644 arch/mips/include/asm/watch.h create mode 100644 arch/mips/kernel/watch.c --- arch/mips/include/asm/cpu-info.h | 6 + arch/mips/include/asm/processor.h | 20 +++ arch/mips/include/asm/thread_info.h | 2 + arch/mips/include/asm/watch.h | 32 +++++ arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/watch.c | 188 ++++++++++++++++++++++++++++ 6 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 arch/mips/include/asm/watch.h create mode 100644 arch/mips/kernel/watch.c diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 2de73dbb2e9..744cd8fb107 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -12,6 +12,8 @@ #ifndef __ASM_CPU_INFO_H #define __ASM_CPU_INFO_H +#include + #include /* @@ -69,6 +71,10 @@ struct cpuinfo_mips { int tc_id; /* Thread Context number */ #endif void *data; /* Additional data */ + unsigned int watch_reg_count; /* Number that exist */ + unsigned int watch_reg_use_cnt; /* Usable by ptrace */ +#define NUM_WATCH_REGS 4 + u16 watch_reg_masks[NUM_WATCH_REGS]; } __attribute__((aligned(SMP_CACHE_BYTES))); extern struct cpuinfo_mips cpu_data[]; diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index a1e4453469f..18ee58e3944 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -105,6 +105,19 @@ struct mips_dsp_state { {0,} \ } +struct mips3264_watch_reg_state { + /* The width of watchlo is 32 in a 32 bit kernel and 64 in a + 64 bit kernel. We use unsigned long as it has the same + property. */ + unsigned long watchlo[NUM_WATCH_REGS]; + /* Only the mask and IRW bits from watchhi. */ + u16 watchhi[NUM_WATCH_REGS]; +}; + +union mips_watch_reg_state { + struct mips3264_watch_reg_state mips3264; +}; + typedef struct { unsigned long seg; } mm_segment_t; @@ -137,6 +150,9 @@ struct thread_struct { /* Saved state of the DSP ASE, if available. */ struct mips_dsp_state dsp; + /* Saved watch register state, if available. */ + union mips_watch_reg_state watch; + /* Other stuff associated with the thread. */ unsigned long cp0_badvaddr; /* Last user fault */ unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ @@ -192,6 +208,10 @@ struct thread_struct { .dspr = {0, }, \ .dspcontrol = 0, \ }, \ + /* \ + * saved watch register stuff \ + */ \ + .watch = {{{0,},},}, \ /* \ * Other stuff associated with the process \ */ \ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index bb3060699df..3f76de73c94 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -124,6 +124,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ #define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */ #define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */ +#define TIF_LOAD_WATCH 25 /* If set, load watch registers */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ #define _TIF_SYSCALL_TRACE (1< + +#include + +void mips_install_watch_registers(void); +void mips_read_watch_registers(void); +void mips_clear_watch_registers(void); +void mips_probe_watch_registers(struct cpuinfo_mips *c); + +#ifdef CONFIG_HARDWARE_WATCHPOINTS +#define __restore_watch() do { \ + if (unlikely(test_bit(TIF_LOAD_WATCH, \ + ¤t_thread_info()->flags))) { \ + mips_install_watch_registers(); \ + } \ +} while (0) + +#else +#define __restore_watch() do {} while (0) +#endif + +#endif /* _ASM_WATCH_H */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 25775cb5400..d9da7112aaf 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ ptrace.o reset.o setup.o signal.o syscall.o \ - time.o topology.o traps.o unaligned.o + time.o topology.o traps.o unaligned.o watch.o obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c new file mode 100644 index 00000000000..c1540696803 --- /dev/null +++ b/arch/mips/kernel/watch.c @@ -0,0 +1,188 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 David Daney + */ + +#include + +#include +#include + +/* + * Install the watch registers for the current thread. A maximum of + * four registers are installed although the machine may have more. + */ +void mips_install_watch_registers(void) +{ + struct mips3264_watch_reg_state *watches = + ¤t->thread.watch.mips3264; + switch (current_cpu_data.watch_reg_use_cnt) { + default: + BUG(); + case 4: + write_c0_watchlo3(watches->watchlo[3]); + /* Write 1 to the I, R, and W bits to clear them, and + 1 to G so all ASIDs are trapped. */ + write_c0_watchhi3(0x40000007 | watches->watchhi[3]); + case 3: + write_c0_watchlo2(watches->watchlo[2]); + write_c0_watchhi2(0x40000007 | watches->watchhi[2]); + case 2: + write_c0_watchlo1(watches->watchlo[1]); + write_c0_watchhi1(0x40000007 | watches->watchhi[1]); + case 1: + write_c0_watchlo0(watches->watchlo[0]); + write_c0_watchhi0(0x40000007 | watches->watchhi[0]); + } +} + +/* + * Read back the watchhi registers so the user space debugger has + * access to the I, R, and W bits. A maximum of four registers are + * read although the machine may have more. + */ +void mips_read_watch_registers(void) +{ + struct mips3264_watch_reg_state *watches = + ¤t->thread.watch.mips3264; + switch (current_cpu_data.watch_reg_use_cnt) { + default: + BUG(); + case 4: + watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff); + case 3: + watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff); + case 2: + watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff); + case 1: + watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff); + } + if (current_cpu_data.watch_reg_use_cnt == 1 && + (watches->watchhi[0] & 7) == 0) { + /* Pathological case of release 1 architecture that + * doesn't set the condition bits. We assume that + * since we got here, the watch condition was met and + * signal that the conditions requested in watchlo + * were met. */ + watches->watchhi[0] |= (watches->watchlo[0] & 7); + } + } + +/* + * Disable all watch registers. Although only four registers are + * installed, all are cleared to eliminate the possibility of endless + * looping in the watch handler. + */ +void mips_clear_watch_registers(void) +{ + switch (current_cpu_data.watch_reg_count) { + default: + BUG(); + case 8: + write_c0_watchlo7(0); + case 7: + write_c0_watchlo6(0); + case 6: + write_c0_watchlo5(0); + case 5: + write_c0_watchlo4(0); + case 4: + write_c0_watchlo3(0); + case 3: + write_c0_watchlo2(0); + case 2: + write_c0_watchlo1(0); + case 1: + write_c0_watchlo0(0); + } +} + +__cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) +{ + unsigned int t; + + if ((c->options & MIPS_CPU_WATCH) == 0) + return; + /* + * Check which of the I,R and W bits are supported, then + * disable the register. + */ + write_c0_watchlo0(7); + t = read_c0_watchlo0(); + write_c0_watchlo0(0); + c->watch_reg_masks[0] = t & 7; + + /* Write the mask bits and read them back to determine which + * can be used. */ + c->watch_reg_count = 1; + c->watch_reg_use_cnt = 1; + t = read_c0_watchhi0(); + write_c0_watchhi0(t | 0xff8); + t = read_c0_watchhi0(); + c->watch_reg_masks[0] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo1(7); + t = read_c0_watchlo1(); + write_c0_watchlo1(0); + c->watch_reg_masks[1] = t & 7; + + c->watch_reg_count = 2; + c->watch_reg_use_cnt = 2; + t = read_c0_watchhi1(); + write_c0_watchhi1(t | 0xff8); + t = read_c0_watchhi1(); + c->watch_reg_masks[1] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo2(7); + t = read_c0_watchlo2(); + write_c0_watchlo2(0); + c->watch_reg_masks[2] = t & 7; + + c->watch_reg_count = 3; + c->watch_reg_use_cnt = 3; + t = read_c0_watchhi2(); + write_c0_watchhi2(t | 0xff8); + t = read_c0_watchhi2(); + c->watch_reg_masks[2] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + write_c0_watchlo3(7); + t = read_c0_watchlo3(); + write_c0_watchlo3(0); + c->watch_reg_masks[3] = t & 7; + + c->watch_reg_count = 4; + c->watch_reg_use_cnt = 4; + t = read_c0_watchhi3(); + write_c0_watchhi3(t | 0xff8); + t = read_c0_watchhi3(); + c->watch_reg_masks[3] |= (t & 0xff8); + if ((t & 0x80000000) == 0) + return; + + /* We use at most 4, but probe and report up to 8. */ + c->watch_reg_count = 5; + t = read_c0_watchhi4(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 6; + t = read_c0_watchhi5(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 7; + t = read_c0_watchhi6(); + if ((t & 0x80000000) == 0) + return; + + c->watch_reg_count = 8; +} -- GitLab From 654f57bfb467996fb730eae96dc30ea4de989fdc Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:07:16 -0700 Subject: [PATCH 3916/5416] MIPS: Probe watch registers and report configuration. Probe for watch register characteristics, and report them in /proc/cpuinfo. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 2 ++ arch/mips/kernel/proc.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e621fda8ab3..0cf15457eca 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, @@ -677,6 +678,7 @@ static inline void spram_config(void) {} static inline void cpu_probe_mips(struct cpuinfo_mips *c) { decode_configs(c); + mips_probe_watch_registers(c); switch (c->processor_id & 0xff00) { case PRID_IMP_4KC: c->cputype = CPU_4KC; diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 36f06539824..75bb1300dd7 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -23,6 +23,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) unsigned int version = cpu_data[n].processor_id; unsigned int fp_vers = cpu_data[n].fpu_id; char fmt [64]; + int i; #ifdef CONFIG_SMP if (!cpu_isset(n, cpu_online_map)) @@ -50,8 +51,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); seq_printf(m, "extra interrupt vector\t: %s\n", cpu_has_divec ? "yes" : "no"); - seq_printf(m, "hardware watchpoint\t: %s\n", - cpu_has_watch ? "yes" : "no"); + seq_printf(m, "hardware watchpoint\t: %s", + cpu_has_watch ? "yes, " : "no\n"); + if (cpu_has_watch) { + seq_printf(m, "count: %d, address/irw mask: [", + cpu_data[n].watch_reg_count); + for (i = 0; i < cpu_data[n].watch_reg_count; i++) + seq_printf(m, "%s0x%04x", i ? ", " : "" , + cpu_data[n].watch_reg_masks[i]); + seq_printf(m, "]\n"); + } seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n", cpu_has_mips16 ? " mips16" : "", cpu_has_mdmx ? " mdmx" : "", -- GitLab From b67b2b703047bfaf62687ca64c9486599b609ef0 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:08:45 -0700 Subject: [PATCH 3917/5416] MIPS: Watch exception handling for HARDWARE_WATCHPOINTS. Here we hook up the watch exception handler so that it sends SIGTRAP when the hardware watch registers are triggered. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/kernel/genex.S | 4 ++++ arch/mips/kernel/traps.c | 24 +++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 01dcbe38fa0..757d48f0d80 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -453,7 +453,11 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER tr tr sti silent /* #13 */ BUILD_HANDLER fpe fpe fpe silent /* #15 */ BUILD_HANDLER mdmx mdmx sti silent /* #22 */ +#ifdef CONFIG_HARDWARE_WATCHPOINTS + BUILD_HANDLER watch watch sti silent /* #23 */ +#else BUILD_HANDLER watch watch sti verbose /* #23 */ +#endif BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ BUILD_HANDLER mt mt sti silent /* #25 */ BUILD_HANDLER dsp dsp sti silent /* #26 */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b602ac6eb47..80b9e070c20 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -912,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs) asmlinkage void do_watch(struct pt_regs *regs) { + u32 cause; + /* - * We use the watch exception where available to detect stack - * overflows. + * Clear WP (bit 22) bit of cause register so we don't loop + * forever. */ - dump_tlb_all(); - show_regs(regs); - panic("Caught WATCH exception - probably caused by stack overflow."); + cause = read_c0_cause(); + cause &= ~(1 << 22); + write_c0_cause(cause); + + /* + * If the current thread has the watch registers loaded, save + * their values and send SIGTRAP. Otherwise another thread + * left the registers set, clear them and continue. + */ + if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { + mips_read_watch_registers(); + force_sig(SIGTRAP, current); + } else + mips_clear_watch_registers(); } asmlinkage void do_mcheck(struct pt_regs *regs) -- GitLab From 2c708cbaa6031b73be6b992adb3ec1811f91cdb1 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:09:51 -0700 Subject: [PATCH 3918/5416] MIPS: Scheduler support for HARDWARE_WATCHPOINTS. Here we hook up the scheduler. Whenever we switch to a new process, we check to see if the watch registers should be installed, and do it if needed. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/system.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index a944eda4faf..cd30f83235b 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -76,6 +77,7 @@ do { \ __restore_dsp(current); \ if (cpu_has_userlocal) \ write_c0_userlocal(current_thread_info()->tp_value); \ + __restore_watch(); \ } while (0) static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) -- GitLab From 0926bf953ee79b8f139741b442e5a18520f81705 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 23 Sep 2008 00:11:26 -0700 Subject: [PATCH 3919/5416] MIPS: Ptrace support for HARDWARE_WATCHPOINTS This is the final part of the watch register patch. Here we hook up ptrace so that the user space debugger (gdb), can set and read the registers. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/include/asm/ptrace.h | 46 +++++++++++++++ arch/mips/kernel/ptrace.c | 100 ++++++++++++++++++++++++++++++++- arch/mips/kernel/ptrace32.c | 10 ++++ 3 files changed, 155 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index c00cca24dae..cd5e8a47812 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -74,11 +74,57 @@ struct pt_regs { #define PTRACE_POKEDATA_3264 0xc3 #define PTRACE_GET_THREAD_AREA_3264 0xc4 +/* Read and write watchpoint registers. */ +enum pt_watch_style { + pt_watch_style_mips32, + pt_watch_style_mips64 +}; +struct mips32_watch_regs { + uint32_t watchlo[8]; + /* Lower 16 bits of watchhi. */ + uint16_t watchhi[8]; + /* Valid mask and I R W bits. + * bit 0 -- 1 if W bit is usable. + * bit 1 -- 1 if R bit is usable. + * bit 2 -- 1 if I bit is usable. + * bits 3 - 11 -- Valid watchhi mask bits. + */ + uint16_t watch_masks[8]; + /* The number of valid watch register pairs. */ + uint32_t num_valid; +} __attribute__((aligned(8))); + +struct mips64_watch_regs { + uint64_t watchlo[8]; + uint16_t watchhi[8]; + uint16_t watch_masks[8]; + uint32_t num_valid; +} __attribute__((aligned(8))); + +struct pt_watch_regs { + enum pt_watch_style style; + union { + struct mips32_watch_regs mips32; + struct mips32_watch_regs mips64; + }; +}; + +#define PTRACE_GET_WATCH_REGS 0xd0 +#define PTRACE_SET_WATCH_REGS 0xd1 + #ifdef __KERNEL__ +#include #include #include +struct task_struct; + +extern int ptrace_get_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr); +extern int ptrace_set_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr); + /* * Does the process account for user or for system time? */ diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 96ffc9c6d19..054861ccb4d 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -46,7 +46,8 @@ */ void ptrace_disable(struct task_struct *child) { - /* Nothing to do.. */ + /* Don't load the watchpoint registers for the ex-child. */ + clear_tsk_thread_flag(child, TIF_LOAD_WATCH); } /* @@ -167,6 +168,93 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) return 0; } +int ptrace_get_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr) +{ + enum pt_watch_style style; + int i; + + if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + return -EIO; + if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs))) + return -EIO; + +#ifdef CONFIG_32BIT + style = pt_watch_style_mips32; +#define WATCH_STYLE mips32 +#else + style = pt_watch_style_mips64; +#define WATCH_STYLE mips64 +#endif + + __put_user(style, &addr->style); + __put_user(current_cpu_data.watch_reg_use_cnt, + &addr->WATCH_STYLE.num_valid); + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + __put_user(child->thread.watch.mips3264.watchlo[i], + &addr->WATCH_STYLE.watchlo[i]); + __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, + &addr->WATCH_STYLE.watchhi[i]); + __put_user(current_cpu_data.watch_reg_masks[i], + &addr->WATCH_STYLE.watch_masks[i]); + } + for (; i < 8; i++) { + __put_user(0, &addr->WATCH_STYLE.watchlo[i]); + __put_user(0, &addr->WATCH_STYLE.watchhi[i]); + __put_user(0, &addr->WATCH_STYLE.watch_masks[i]); + } + + return 0; +} + +int ptrace_set_watch_regs(struct task_struct *child, + struct pt_watch_regs __user *addr) +{ + int i; + int watch_active = 0; + unsigned long lt[NUM_WATCH_REGS]; + u16 ht[NUM_WATCH_REGS]; + + if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + return -EIO; + if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) + return -EIO; + /* Check the values. */ + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]); +#ifdef CONFIG_32BIT + if (lt[i] & __UA_LIMIT) + return -EINVAL; +#else + if (test_tsk_thread_flag(child, TIF_32BIT_ADDR)) { + if (lt[i] & 0xffffffff80000000UL) + return -EINVAL; + } else { + if (lt[i] & __UA_LIMIT) + return -EINVAL; + } +#endif + __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]); + if (ht[i] & ~0xff8) + return -EINVAL; + } + /* Install them. */ + for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + if (lt[i] & 7) + watch_active = 1; + child->thread.watch.mips3264.watchlo[i] = lt[i]; + /* Set the G bit. */ + child->thread.watch.mips3264.watchhi[i] = ht[i]; + } + + if (watch_active) + set_tsk_thread_flag(child, TIF_LOAD_WATCH); + else + clear_tsk_thread_flag(child, TIF_LOAD_WATCH); + + return 0; +} + long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -440,6 +528,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) (unsigned long __user *) data); break; + case PTRACE_GET_WATCH_REGS: + ret = ptrace_get_watch_regs(child, + (struct pt_watch_regs __user *) addr); + break; + + case PTRACE_SET_WATCH_REGS: + ret = ptrace_set_watch_regs(child, + (struct pt_watch_regs __user *) addr); + break; + default: ret = ptrace_request(child, request, addr, data); break; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index cac56a8c867..e45105e3ef0 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -387,6 +387,16 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, (unsigned long __user *) (unsigned long) data); break; + case PTRACE_GET_WATCH_REGS: + ret = ptrace_get_watch_regs(child, + (struct pt_watch_regs __user *) (unsigned long) addr); + break; + + case PTRACE_SET_WATCH_REGS: + ret = ptrace_set_watch_regs(child, + (struct pt_watch_regs __user *) (unsigned long) addr); + break; + default: ret = ptrace_request(child, request, addr, data); break; -- GitLab From d302d05cf4d25f4fbbec0f9338fac13ee0c0ad89 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Oct 2008 16:18:57 +0100 Subject: [PATCH 3920/5416] MIPS: Move ptrace prototypes to ptrace.h Signed-off-by: Ralf Baechle --- arch/mips/include/asm/ptrace.h | 6 ++++++ arch/mips/kernel/ptrace32.c | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index cd5e8a47812..9c22571b160 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -120,6 +120,12 @@ struct pt_watch_regs { struct task_struct; +extern int ptrace_getregs(struct task_struct *child, __s64 __user *data); +extern int ptrace_setregs(struct task_struct *child, __s64 __user *data); + +extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data); +extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); + extern int ptrace_get_watch_regs(struct task_struct *child, struct pt_watch_regs __user *addr); extern int ptrace_set_watch_regs(struct task_struct *child, diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index e45105e3ef0..1ca34104e59 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -37,12 +37,6 @@ #include #include -int ptrace_getregs(struct task_struct *child, __s64 __user *data); -int ptrace_setregs(struct task_struct *child, __s64 __user *data); - -int ptrace_getfpregs(struct task_struct *child, __u32 __user *data); -int ptrace_setfpregs(struct task_struct *child, __u32 __user *data); - /* * Tracing a 32-bit process with a 64-bit strace and vice versa will not * work. I don't know how to fix this. -- GitLab From 9609e74093abd9f61fb1d20a8915a8ea87c77d5a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 11 Sep 2008 17:48:00 +0200 Subject: [PATCH 3921/5416] MIPS: RB532: provide GPIO_BUILTIN_NR and irq_to_gpio/gpio_to_irq This patchs defines the number of built-in the GPIOs present on the SoC as Documentation/gpio.txt recommends to do. Define irq_to_gpio/gpio_to_irq to return the right values so that it fixes a compilation error on drivers/gpio/gpiolib.c when enabling debugfs. Signed-off-by: Florian Fainelli Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-rc32434/gpio.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index 3a70b41cd7a..c8e554eafce 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -14,16 +14,16 @@ #define _RC32434_GPIO_H_ #include +#include -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value - -#define gpio_cansleep __gpio_cansleep +#define NR_BUILTIN_GPIO 32 -#define gpio_to_irq(gpio) IRQ_GPIO(gpio) -#define irq_to_gpio(irq) IRQ_TO_GPIO(irq) +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep -#include +#define gpio_to_irq(gpio) (8 + 4 * 32 + gpio) +#define irq_to_gpio(irq) (irq - (8 + 4 * 32)) struct rb532_gpio_reg { u32 gpiofunc; /* GPIO Function Register -- GitLab From 64f1b65382054f8bfd528f2c4253297c232816eb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 11 Oct 2008 09:46:24 -0700 Subject: [PATCH 3922/5416] net: fix dummy 'nf_conntrack_event_cache()' The dummy version of 'nf_conntrack_event_cache()' (used when the NF_CONNTRACK_EVENTS config option is not enabled) had not been updated when the calling convention changed. This was introduced by commit a71996fccce4b2086a26036aa3c915365ca36926 ("netfilter: netns nf_conntrack: pass conntrack to nf_conntrack_event_cache() not skb") Tssk. Cc: Alexey Dobriyan Cc: Patrick McHardy Cc: David Miller Signed-off-by: Linus Torvalds --- include/net/netfilter/nf_conntrack_ecache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 11480e633a9..1285ff26a01 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -63,7 +63,7 @@ extern void nf_conntrack_ecache_fini(struct net *net); #else /* CONFIG_NF_CONNTRACK_EVENTS */ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, - const struct sk_buff *skb) {} + struct nf_conn *ct) {} static inline void nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} -- GitLab From 5ba2f67afb02c5302b2898949ed6fc3b3d37dcf1 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 10 Oct 2008 21:16:12 -0700 Subject: [PATCH 3923/5416] security: avoid calling a NULL function pointer in drivers/video/tvaudio.c NULL function pointers are very bad security wise. This one got caught by kerneloops.org quite a few times, so it's happening in the field.... Fix is simple, check the function pointer for NULL, like 6 other places in the same function are already doing. Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 463680b1328..b59e47272ab 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1792,7 +1792,7 @@ static int chip_command(struct i2c_client *client, break; case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ - if (desc->checkmode) { + if (desc->checkmode && desc->setmode) { desc->setmode(chip,V4L2_TUNER_MODE_MONO); if (chip->prevmode != V4L2_TUNER_MODE_MONO) chip->prevmode = -1; /* reset previous mode */ -- GitLab From f901b64472fdabc72eca2b9426fa4e96972b64c4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 11 Oct 2008 12:18:04 -0700 Subject: [PATCH 3924/5416] ipvs: Add proper dependencies on IP_VS, and fix description header line. Linus noted a build failure case: net/netfilter/ipvs/ip_vs_xmit.c: In function 'ip_vs_tunnel_xmit': net/netfilter/ipvs/ip_vs_xmit.c:616: error: implicit declaration of function 'ip_select_ident' The proper include file (net/ip.h) is being included in ip_vs_xmit.c to get that declaration. So the only possible case where this can happen is if CONFIG_INET is not enabled. This seems to be purely a missing dependency in the ipvs/Kconfig file IP_VS entry. Also, while we're here, remove the out of date "EXPERIMENTAL" string in the IP_VS config help header line. IP_VS no longer depends upon CONFIG_EXPERIMENTAL Signed-off-by: David S. Miller --- net/netfilter/ipvs/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index de6004de80b..05048e40326 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig @@ -2,8 +2,8 @@ # IP Virtual Server configuration # menuconfig IP_VS - tristate "IP virtual server support (EXPERIMENTAL)" - depends on NETFILTER + tristate "IP virtual server support" + depends on NET && INET && NETFILTER ---help--- IP Virtual Server support will let you build a high-performance virtual server based on cluster of two or more real servers. This -- GitLab From 7bb82d924536cfa62db73dd381b07d9e9b084ffa Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 11 Oct 2008 12:20:15 -0700 Subject: [PATCH 3925/5416] gre: Initialise rtnl_link tunnel parameters properly Brown paper bag error of calling memset with sizeof(p) instead of sizeof(*p). Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 05ebce2881e..85c487b8572 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1345,7 +1345,7 @@ out: static void ipgre_netlink_parms(struct nlattr *data[], struct ip_tunnel_parm *parms) { - memset(parms, 0, sizeof(parms)); + memset(parms, 0, sizeof(*parms)); parms->iph.protocol = IPPROTO_GRE; -- GitLab From 20501a69818827884b4381cdcedefdb5e7892915 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 11 Oct 2008 12:25:59 -0700 Subject: [PATCH 3926/5416] e1000: allow VLAN devices to use TSO and CSUM offload This patch changes e1000 to set vlan_features so TSO and CSUM offload can be used by VLAN devices, similar as with the other Intel drivers. Signed-off-by: Patrick McHardy Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 3bafaede791..fac82152e4c 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1047,6 +1047,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_LLTX; + netdev->vlan_features |= NETIF_F_TSO; + netdev->vlan_features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_HW_CSUM; + netdev->vlan_features |= NETIF_F_SG; + adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); /* initialize eeprom parameters */ -- GitLab From f3073ac76755abd63b1d4c3d145f4c15b65b5355 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 11 Oct 2008 15:07:16 -0700 Subject: [PATCH 3927/5416] smc911x: Fix external PHY detection If an external PHY is found the driver falls through to the default case in the switch and overwrites the PHY ID. Add the missing break. Signed-off-by: Guennadi Liakhovetski Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 02cc064c2c8..3d19d00e8ee 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -722,6 +722,9 @@ static void smc911x_phy_detect(struct net_device *dev) break; } } + if (phyaddr < 32) + /* Found an external PHY */ + break; } default: /* Internal media only */ -- GitLab From e809517f6fa5803a5a1cd56026f0e2190fc13d5c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 25 Jul 2008 01:09:08 +0200 Subject: [PATCH 3928/5416] sdhci: let the controller wait for busy state to end The sdhci controllers can interrupt us when the busy state from the card has ended, saving CPU cycles and power. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index e3a8133560a..ef461274397 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) SDHCI_INT_INDEX)) host->cmd->error = -EILSEQ; - if (host->cmd->error) + if (host->cmd->error) { tasklet_schedule(&host->finish_tasklet); - else if (intmask & SDHCI_INT_RESPONSE) + return; + } + + /* + * The host can send and interrupt when the busy state has + * ended, allowing us to wait without wasting CPU cycles. + * Unfortunately this is overloaded on the "data complete" + * interrupt, so we need to take some care when handling + * it. + * + * Note: The 1.0 specification is a bit ambiguous about this + * feature so there might be some problems with older + * controllers. + */ + if (host->cmd->flags & MMC_RSP_BUSY) { + if (host->cmd->data) + DBG("Cannot wait for busy signal when also " + "doing a data transfer"); + else + return; + } + + if (intmask & SDHCI_INT_RESPONSE) sdhci_finish_command(host); } @@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (!host->data) { /* - * A data end interrupt is sent together with the response - * for the stop command. + * The "data complete" interrupt is also used to + * indicate that a busy state has ended. See comment + * above in sdhci_cmd_irq(). */ - if (intmask & SDHCI_INT_DATA_END) - return; + if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { + if (intmask & SDHCI_INT_DATA_END) { + sdhci_finish_command(host); + return; + } + } printk(KERN_ERR "%s: Got data interrupt 0x%08x even " "though no data operation was in progress.\n", -- GitLab From 04cf585d2902404ed06861c6dc27897100340dba Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 18 Aug 2008 22:18:14 +0200 Subject: [PATCH 3929/5416] sdhci: reduce card detection delay The card detection delay was added early when the behaviour of the card interrupt was still very much unknown (i.e. before there was a public specification). As it is now known that it is a debounced signal, reduce the delay to something more sensible. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ef461274397..fd2dc821e40 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param) spin_unlock_irqrestore(&host->lock, flags); - mmc_detect_change(host->mmc, msecs_to_jiffies(500)); + mmc_detect_change(host->mmc, msecs_to_jiffies(200)); } static void sdhci_tasklet_finish(unsigned long param) -- GitLab From e633b7bcec8e26991d489a11615acf7674efbaf4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 31 Aug 2008 13:38:54 +0200 Subject: [PATCH 3930/5416] sdio: make sleep on error interruptable Make sure we can be woken from the forced sleep that is done on errors. Removing a card often results in -ENOMEDIUM or -EILSEQ so we previously locked up the removal process for a second. We could completely exit on -ENOMEDIUM, but it might be a transient glitch so treat it like any other error. Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio_irq.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index c292e124107..722924cdf59 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -5,6 +5,8 @@ * Created: June 18, 2007 * Copyright: MontaVista Software Inc. * + * Copyright 2008 Pierre Ossman + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at @@ -107,11 +109,14 @@ static int sdio_irq_thread(void *_host) /* * Give other threads a chance to run in the presence of - * errors. FIXME: determine if due to card removal and - * possibly exit this thread if so. + * errors. */ - if (ret < 0) - ssleep(1); + if (ret < 0) { + set_current_state(TASK_INTERRUPTIBLE); + if (!kthread_should_stop()) + schedule_timeout(HZ); + set_current_state(TASK_RUNNING); + } /* * Adaptive polling frequency based on the assumption -- GitLab From 6501ff604a5ae18697c9b4cd40a7738d3a68e7fe Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 31 Aug 2008 13:42:00 +0200 Subject: [PATCH 3931/5416] sdio: give sdio irq thread a host specific name There is one thread per host controller so make sure they all get unique names. Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio_irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 722924cdf59..bb192f90e8e 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -159,7 +159,8 @@ static int sdio_card_irq_get(struct mmc_card *card) if (!host->sdio_irqs++) { atomic_set(&host->sdio_irq_thread_abort, 0); host->sdio_irq_thread = - kthread_run(sdio_irq_thread, host, "ksdiorqd"); + kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", + mmc_hostname(host)); if (IS_ERR(host->sdio_irq_thread)) { int err = PTR_ERR(host->sdio_irq_thread); host->sdio_irqs--; -- GitLab From f3eb0aaa0211fd804057070bee1fd067cd65cb13 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 16 Aug 2008 21:34:02 +0200 Subject: [PATCH 3932/5416] mmc_block: inform block layer about sector count restriction Make sure we consider the maximum block count when we tell the block layer about the maximum sector count. That way we don't have to chop up the request ourselves. Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 23 +---------------------- drivers/mmc/card/queue.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ebc8b9d7761..d73cac84d9f 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -215,8 +215,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; struct mmc_blk_request brq; - int ret = 1, data_size, i; - struct scatterlist *sg; + int ret = 1; mmc_claim_host(card->host); @@ -237,8 +236,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.stop.arg = 0; brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); - if (brq.data.blocks > card->host->max_blk_count) - brq.data.blocks = card->host->max_blk_count; if (brq.data.blocks > 1) { /* SPI multiblock writes terminate using a special @@ -270,24 +267,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_queue_bounce_pre(mq); - /* - * Adjust the sg list so it is the same size as the - * request. - */ - if (brq.data.blocks != - (req->nr_sectors >> (md->block_bits - 9))) { - data_size = brq.data.blocks * brq.data.blksz; - for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) { - data_size -= sg->length; - if (data_size <= 0) { - sg->length += data_size; - i++; - break; - } - } - brq.data.sg_len = i; - } - mmc_wait_for_req(card->host, &brq.mrq); mmc_queue_bounce_post(mq); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 3dee97e7d16..5c8f037dca6 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -142,12 +142,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; + if (bouncesz > (host->max_blk_count * 512)) + bouncesz = host->max_blk_count * 512; + + if (bouncesz > 512) { + mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); + if (!mq->bounce_buf) { + printk(KERN_WARNING "%s: unable to " + "allocate bounce buffer\n", + mmc_card_name(card)); + } + } - mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); - if (!mq->bounce_buf) { - printk(KERN_WARNING "%s: unable to allocate " - "bounce buffer\n", mmc_card_name(card)); - } else { + if (mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_sectors(mq->queue, bouncesz / 512); blk_queue_max_phys_segments(mq->queue, bouncesz / 512); @@ -175,7 +182,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock if (!mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, limit); - blk_queue_max_sectors(mq->queue, host->max_req_size / 512); + blk_queue_max_sectors(mq->queue, + min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); -- GitLab From 91028954119e464ae42350658d46c204d781b484 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 16 Aug 2008 21:15:50 +0200 Subject: [PATCH 3933/5416] mmc_block: indicate strict ordering The MMC block driver services requests one at a time and in strict order. Indicate this to the block layer so that it can handle barriers in an efficient manner. Signed-off-by: Pierre Ossman --- drivers/mmc/card/queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 5c8f037dca6..c25c975bdc3 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -131,6 +131,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); + blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_hw_segs == 1) { -- GitLab From d6d8de33415ca7598fe66d933b6556fa8f89afe2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 16 Aug 2008 20:43:48 +0200 Subject: [PATCH 3934/5416] mmc_block: filter out PC requests We do not support PC (SCSI) commands, so don't pretend we do by letting them through. Signed-off-by: Pierre Ossman --- drivers/mmc/card/queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c25c975bdc3..406989e992b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -31,7 +31,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) /* * We only like normal block requests. */ - if (!blk_fs_request(req) && !blk_pc_request(req)) { + if (!blk_fs_request(req)) { blk_dump_rq_flags(req, "MMC bad request"); return BLKPREP_KILL; } -- GitLab From a4b76193774b463b922cab2f92450efb20d29ef0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 16 Aug 2008 20:43:04 +0200 Subject: [PATCH 3935/5416] sdhci: force high speed capability on some controllers Some high speed capable controllers forget to set the high speed capability bit. Make sure we enable the functionality anyway. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci-pci.c | 3 ++- drivers/mmc/host/sdhci.c | 3 ++- drivers/mmc/host/sdhci.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index fcb14c2346c..0a84f10d719 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -144,7 +144,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip) SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE | SDHCI_QUIRK_RESET_AFTER_REQUEST | - SDHCI_QUIRK_BROKEN_SMALL_PIO; + SDHCI_QUIRK_BROKEN_SMALL_PIO | + SDHCI_QUIRK_FORCE_HIGHSPEED; } /* diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index fd2dc821e40..3c808d22f9d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1631,7 +1631,8 @@ int sdhci_add_host(struct sdhci_host *host) mmc->f_max = host->max_clk; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; - if (caps & SDHCI_CAN_DO_HISPD) + if ((caps & SDHCI_CAN_DO_HISPD) || + (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED)) mmc->caps |= MMC_CAP_SD_HIGHSPEED; mmc->ocr_avail = 0; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 197d4a05f4a..31f4b1528e7 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -208,6 +208,8 @@ struct sdhci_host { #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) /* Controller has an issue with buffer bits for small transfers */ #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) +/* Controller supports high speed but doesn't have the caps bit set */ +#define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14) int irq; /* Device IRQ */ void __iomem * ioaddr; /* Mapped address */ -- GitLab From 08846698703dedae6c6915eb4b4d0a36188c5635 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 31 Aug 2008 14:10:08 +0200 Subject: [PATCH 3936/5416] mmc_block: hard code 512 byte block size We use 512 byte blocks on all cards, and newer cards support nothing else, so hard code it and make the code less complex. Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index d73cac84d9f..1d1e469e08e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -57,7 +57,6 @@ struct mmc_blk_data { struct mmc_queue queue; unsigned int usage; - unsigned int block_bits; unsigned int read_only; }; @@ -231,11 +230,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) if (!mmc_card_blockaddr(card)) brq.cmd.arg <<= 9; brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - brq.data.blksz = 1 << md->block_bits; + brq.data.blksz = 512; brq.stop.opcode = MMC_STOP_TRANSMISSION; brq.stop.arg = 0; brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); + brq.data.blocks = req->nr_sectors; if (brq.data.blocks > 1) { /* SPI multiblock writes terminate using a special @@ -351,16 +350,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) if (rq_data_dir(req) != READ) { if (mmc_card_sd(card)) { u32 blocks; - unsigned int bytes; blocks = mmc_sd_num_wr_blocks(card); if (blocks != (u32)-1) { - if (card->csd.write_partial) - bytes = blocks << md->block_bits; - else - bytes = blocks << 9; spin_lock_irq(&md->lock); - ret = __blk_end_request(req, 0, bytes); + ret = __blk_end_request(req, 0, blocks << 9); spin_unlock_irq(&md->lock); } } else { @@ -410,13 +404,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) */ md->read_only = mmc_blk_readonly(card); - /* - * Both SD and MMC specifications state (although a bit - * unclearly in the MMC case) that a block size of 512 - * bytes must always be supported by the card. - */ - md->block_bits = 9; - md->disk = alloc_disk(1 << MMC_SHIFT); if (md->disk == NULL) { ret = -ENOMEM; @@ -454,7 +441,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) sprintf(md->disk->disk_name, "mmcblk%d", devidx); - blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); + blk_queue_hardsect_size(md->queue.queue, 512); if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { /* @@ -492,7 +479,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) mmc_claim_host(card->host); cmd.opcode = MMC_SET_BLOCKLEN; - cmd.arg = 1 << md->block_bits; + cmd.arg = 512; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, 5); mmc_release_host(card->host); -- GitLab From d16f57700475f670ca2828c150a34fa7102a05fc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 31 Aug 2008 17:22:46 +0200 Subject: [PATCH 3937/5416] sdio: high-speed support Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio.c | 52 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4eab79e09cc..fb99ccff908 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -164,6 +164,36 @@ static int sdio_enable_wide(struct mmc_card *card) return 0; } +/* + * Test if the card supports high-speed mode and, if so, switch to it. + */ +static int sdio_enable_hs(struct mmc_card *card) +{ + int ret; + u8 speed; + + if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) + return 0; + + if (!card->cccr.high_speed) + return 0; + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); + if (ret) + return ret; + + speed |= SDIO_SPEED_EHS; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); + if (ret) + return ret; + + mmc_card_set_highspeed(card); + mmc_set_timing(card->host, MMC_TIMING_SD_HS); + + return 0; +} + /* * Host is being removed. Free up the current card. */ @@ -333,10 +363,26 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) goto remove; /* - * No support for high-speed yet, so just set - * the card's maximum speed. + * Switch to high-speed (if supported). */ - mmc_set_clock(host, card->cis.max_dtr); + err = sdio_enable_hs(card); + if (err) + goto remove; + + /* + * Change to the card's maximum speed. + */ + if (mmc_card_highspeed(card)) { + /* + * The SDIO specification doesn't mention how + * the CIS transfer speed register relates to + * high-speed, but it seems that 50 MHz is + * mandatory. + */ + mmc_set_clock(host, 50000000); + } else { + mmc_set_clock(host, card->cis.max_dtr); + } /* * Switch to wider bus (if supported). -- GitLab From ee63a7d2287c677ed022bf3f584f5a187b6c402f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 2 Sep 2008 10:14:13 +0200 Subject: [PATCH 3938/5416] Fix comment in include/linux/mmc/host.h In include/linux/mmc/host.h, it is mentionned that the callback to know if a card is present or not is get_ro(). But it's get_cd(). Signed-off-by: Thomas Petazzoni Signed-off-by: Pierre Ossman --- include/linux/mmc/host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9c288c90987..bde891f6459 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -65,7 +65,7 @@ struct mmc_host_ops { * -ENOSYS when not supported (equal to NULL callback) * or a negative errno value when something bad happened * - * Return values for the get_ro callback should be: + * Return values for the get_cd callback should be: * 0 for a absent card * 1 for a present card * -ENOSYS when not supported (equal to NULL callback) -- GitLab From 1ea4f444f3a9721babd5d22cbd15092f9da6b51a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 7 Sep 2008 13:07:57 +0200 Subject: [PATCH 3939/5416] mmc: remove redundant "depends on" Signed-off-by: Pierre Ossman --- drivers/mmc/card/Kconfig | 1 - drivers/mmc/host/Kconfig | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index dd0f398ee2f..ffd2198e515 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -34,7 +34,6 @@ config MMC_BLOCK_BOUNCE config SDIO_UART tristate "SDIO UART/GPS class support" - depends on MMC help SDIO function driver for SDIO cards that implements the UART class, as well as the GPS class which appears like a UART. diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index ea8d7a3490d..4b81899ba5a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -142,7 +142,7 @@ config MMC_TIFM_SD config MMC_SPI tristate "MMC/SD over SPI" - depends on MMC && SPI_MASTER && !HIGHMEM && HAS_DMA + depends on SPI_MASTER && !HIGHMEM && HAS_DMA select CRC7 select CRC_ITU_T help @@ -155,7 +155,7 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" - depends on ARCH_S3C2410 && MMC + depends on ARCH_S3C2410 help This selects a driver for the MCI interface found in Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. @@ -166,7 +166,7 @@ config MMC_S3C config MMC_SDRICOH_CS tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" - depends on EXPERIMENTAL && MMC && PCI && PCMCIA + depends on EXPERIMENTAL && PCI && PCMCIA help Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA card whenever you insert a MMC or SD card into the card slot. -- GitLab From 57105737f6a0b39305a85ac176cc9fd4a236d8c2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 7 Sep 2008 13:16:58 +0200 Subject: [PATCH 3940/5416] mmc: explicitly mention SDIO support in Kconfig Signed-off-by: Pierre Ossman --- drivers/mmc/Kconfig | 9 +++++---- drivers/mmc/card/Kconfig | 2 +- drivers/mmc/host/Kconfig | 13 +++++++------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c0b41e8bcd9..f2eeb38efa6 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -3,13 +3,14 @@ # menuconfig MMC - tristate "MMC/SD card support" + tristate "MMC/SD/SDIO card support" depends on HAS_IOMEM help - MMC is the "multi-media card" bus protocol. + This selects MultiMediaCard, Secure Digital and Secure + Digital I/O support. - If you want MMC support, you should say Y here and also - to the specific driver for your MMC interface. + If you want MMC/SD/SDIO support, you should say Y here and + also to your specific host controller driver. config MMC_DEBUG bool "MMC debugging" diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index ffd2198e515..3f2a912659a 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -2,7 +2,7 @@ # MMC/SD card drivers # -comment "MMC/SD Card Drivers" +comment "MMC/SD/SDIO Card Drivers" config MMC_BLOCK tristate "MMC block device driver" diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 4b81899ba5a..38468b2bd1a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -2,7 +2,7 @@ # MMC/SD host controller drivers # -comment "MMC/SD Host Controller Drivers" +comment "MMC/SD/SDIO Host Controller Drivers" config MMC_ARMMMCI tristate "ARM AMBA Multimedia Card Interface support" @@ -141,15 +141,16 @@ config MMC_TIFM_SD module will be called tifm_sd. config MMC_SPI - tristate "MMC/SD over SPI" + tristate "MMC/SD/SDIO over SPI" depends on SPI_MASTER && !HIGHMEM && HAS_DMA select CRC7 select CRC_ITU_T help - Some systems accss MMC/SD cards using a SPI controller instead of - using a "native" MMC/SD controller. This has a disadvantage of - being relatively high overhead, but a compensating advantage of - working on many systems without dedicated MMC/SD controllers. + Some systems accss MMC/SD/SDIO cards using a SPI controller + instead of using a "native" MMC/SD/SDIO controller. This has a + disadvantage of being relatively high overhead, but a compensating + advantage of working on many systems without dedicated MMC/SD/SDIO + controllers. If unsure, or if your system has no SPI master driver, say N. -- GitLab From 7244b85bd17313d7d300ee93ec7bfbca1f4ccf3d Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Wed, 1 Oct 2008 01:50:25 -0700 Subject: [PATCH 3941/5416] sdhci: 'scratch' may be used uninitialized The variable 'scratch' is always initialized before it's used. The conditional which is responsible for initialization of 'scratch' will always evaluate 'true' when the first loop iteration occurs, and thus, it's properly initialized. GCC doesn't see this, of course, so using the uninitialized_var() macro seems to work for silencing this case. Signed-off-by: Steven Noonan Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3c808d22f9d..30f64b1f235 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) { unsigned long flags; size_t blksize, len, chunk; - u32 scratch; + u32 uninitialized_var(scratch); u8 *buf; DBG("PIO reading\n"); -- GitLab From 0d3e0460f307e84904968aad6cff97bd688583d8 Mon Sep 17 00:00:00 2001 From: Matthew Fleming Date: Thu, 2 Oct 2008 12:24:05 +0100 Subject: [PATCH 3942/5416] MMC: CSD and CID timeout values The MMC spec states that the timeout for accessing the CSD and CID registers is 64 clock cycles. Signed-off-by: Matthew Fleming Signed-off-by: Pierre Ossman --- drivers/mmc/core/mmc_ops.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 64b05c6270f..9c50e6f1c23 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -248,8 +248,12 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, sg_init_one(&sg, data_buf, len); - if (card) - mmc_set_data_timeout(&data, card); + /* + * The spec states that CSR and CID accesses have a timeout + * of 64 clock cycles. + */ + data.timeout_ns = 0; + data.timeout_clks = 64; mmc_wait_for_req(host, &mrq); -- GitLab From 162350eb75fcb81ec0ea34f042f1deddb759aea8 Mon Sep 17 00:00:00 2001 From: Matthew Fleming Date: Thu, 2 Oct 2008 12:21:42 +0100 Subject: [PATCH 3943/5416] MMC: Use timeout values from CSR Hard-coded timeout values of 250ms for writes and 100ms for reads are currently used for MMC transactions over SPI. The spec states that the timeout values from the card should be used. Signed-off-by: Matthew Fleming Signed-off-by: Pierre Ossman --- drivers/mmc/host/mmc_spi.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 7503b81374e..07faf5412a1 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -95,8 +95,6 @@ * reads which takes nowhere near that long. Older cards may be able to use * shorter timeouts ... but why bother? */ -#define readblock_timeout ktime_set(0, 100 * 1000 * 1000) -#define writeblock_timeout ktime_set(0, 250 * 1000 * 1000) #define r1b_timeout ktime_set(3, 0) @@ -220,9 +218,9 @@ mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout) return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0); } -static int mmc_spi_readtoken(struct mmc_spi_host *host) +static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout) { - return mmc_spi_skip(host, readblock_timeout, 1, 0xff); + return mmc_spi_skip(host, timeout, 1, 0xff); } @@ -605,7 +603,8 @@ mmc_spi_setup_data_message( * Return negative errno, else success. */ static int -mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) +mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, + ktime_t timeout) { struct spi_device *spi = host->spi; int status, i; @@ -673,7 +672,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) if (scratch->status[i] != 0) return 0; } - return mmc_spi_wait_unbusy(host, writeblock_timeout); + return mmc_spi_wait_unbusy(host, timeout); } /* @@ -693,7 +692,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) * STOP_TRANSMISSION command. */ static int -mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) +mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, + ktime_t timeout) { struct spi_device *spi = host->spi; int status; @@ -707,7 +707,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) return status; status = scratch->status[0]; if (status == 0xff || status == 0) - status = mmc_spi_readtoken(host); + status = mmc_spi_readtoken(host, timeout); if (status == SPI_TOKEN_SINGLE) { if (host->dma_dev) { @@ -778,6 +778,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, struct scatterlist *sg; unsigned n_sg; int multiple = (data->blocks > 1); + u32 clock_rate; + ktime_t timeout; if (data->flags & MMC_DATA_READ) direction = DMA_FROM_DEVICE; @@ -786,6 +788,14 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, mmc_spi_setup_data_message(host, multiple, direction); t = &host->t; + if (t->speed_hz) + clock_rate = t->speed_hz; + else + clock_rate = spi->max_speed_hz; + + timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns + + data->timeout_clks * 1000000 / clock_rate); + /* Handle scatterlist segments one at a time, with synch for * each 512-byte block */ @@ -832,9 +842,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, t->len); if (direction == DMA_TO_DEVICE) - status = mmc_spi_writeblock(host, t); + status = mmc_spi_writeblock(host, t, timeout); else - status = mmc_spi_readblock(host, t); + status = mmc_spi_readblock(host, t, timeout); if (status < 0) break; @@ -917,7 +927,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, if (scratch->status[tmp] != 0) return; } - tmp = mmc_spi_wait_unbusy(host, writeblock_timeout); + tmp = mmc_spi_wait_unbusy(host, timeout); if (tmp < 0 && !data->error) data->error = tmp; } -- GitLab From e1e23bb0513520035ec934fa3483507cb6648b7c Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 7 Oct 2008 14:15:11 -0700 Subject: [PATCH 3944/5416] x86: avoid dereferencing beyond stack + THREAD_SIZE It's possible for get_wchan() to dereference past task->stack + THREAD_SIZE while iterating through instruction pointers if fp equals the upper boundary, causing a kernel panic. Signed-off-by: David Rientjes Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 2a8ccb9238b..b6b508ea711 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -754,12 +754,12 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); - if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) + if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || - fp > (unsigned long)stack+THREAD_SIZE) + fp >= (unsigned long)stack+THREAD_SIZE) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) -- GitLab From c613ec1a7ff3714da11c7c48a13bab03beb5c376 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 10 Oct 2008 10:46:45 +0100 Subject: [PATCH 3945/5416] x86, early_ioremap: fix fencepost error The x86 implementation of early_ioremap has an off by one error. If we get an object which ends on the first byte of a page we undermap by one page and this causes a crash on boot with the ASUS P5QL whose DMI table happens to fit this alignment. The size computation is currently last_addr = phys_addr + size - 1; npages = (PAGE_ALIGN(last_addr) - phys_addr) (Consider a request for 1 byte at alignment 0...) Closes #11693 Debugging work by Ian Campbell/Felix Geyer Signed-off-by: Alan Cox Cc: Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 6ab3196d12b..10b52309aef 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -614,7 +614,7 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; /* * Mappings have to fit in the FIX_BTMAP area. -- GitLab From cb58ffc3889f0545628f138f849e759a331b8ddc Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Sun, 12 Oct 2008 10:51:03 +0200 Subject: [PATCH 3946/5416] x86: fix early panic on amd64 due to typo in supported CPU section Do not crash when enumerating supported CPU architectures SECURITY_INIT somehow ended up in x86_cpu_dev.init section. That caused printk in code which prints supported architectures to hit #GP due to non-canonical address being used. Signed-off-by: Petr Vandrovec Cc: thomas.petazzoni@free-electrons.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux_64.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 201e81a91a9..46e05447405 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -172,8 +172,8 @@ SECTIONS .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { *(.x86_cpu_dev.init) } - SECURITY_INIT __x86_cpu_dev_end = .; + SECURITY_INIT . = ALIGN(8); .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { -- GitLab From 325af5fb1418c79953db0954556de048e061d8b6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 8 Aug 2008 15:58:39 -0700 Subject: [PATCH 3947/5416] x86: ioperm user_regset This adds a user_regset type for the x86 io permissions bitmap. This makes it appear in core dumps (when ioperm has been used). It will also make it visible to debuggers in the future. Signed-off-by: Roland McGrath Signed-off-by: H. Peter Anvin [conflict resolutions: Signed-off-by: Ingo Molnar ] --- arch/x86/kernel/ptrace.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/elf.h | 1 + 2 files changed, 38 insertions(+) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e375b658efc..4e1ef66c2ea 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -40,7 +40,9 @@ enum x86_regset { REGSET_GENERAL, REGSET_FP, REGSET_XFP, + REGSET_IOPERM64 = REGSET_XFP, REGSET_TLS, + REGSET_IOPERM32, }; /* @@ -555,6 +557,29 @@ static int ptrace_set_debugreg(struct task_struct *child, return 0; } +/* + * These access the current or another (stopped) task's io permission + * bitmap for debugging or core dump. + */ +static int ioperm_active(struct task_struct *target, + const struct user_regset *regset) +{ + return target->thread.io_bitmap_max / regset->size; +} + +static int ioperm_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + if (!target->thread.io_bitmap_ptr) + return -ENXIO; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + target->thread.io_bitmap_ptr, + 0, IO_BITMAP_BYTES); +} + #ifdef CONFIG_X86_PTRACE_BTS /* * The configuration for a particular BTS hardware implementation. @@ -1385,6 +1410,12 @@ static const struct user_regset x86_64_regsets[] = { .size = sizeof(long), .align = sizeof(long), .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set }, + [REGSET_IOPERM64] = { + .core_note_type = NT_386_IOPERM, + .n = IO_BITMAP_LONGS, + .size = sizeof(long), .align = sizeof(long), + .active = ioperm_active, .get = ioperm_get + }, }; static const struct user_regset_view user_x86_64_view = { @@ -1431,6 +1462,12 @@ static const struct user_regset x86_32_regsets[] = { .active = regset_tls_active, .get = regset_tls_get, .set = regset_tls_set }, + [REGSET_IOPERM32] = { + .core_note_type = NT_386_IOPERM, + .n = IO_BITMAP_BYTES / sizeof(u32), + .size = sizeof(u32), .align = sizeof(u32), + .active = ioperm_active, .get = ioperm_get + }, }; static const struct user_regset_view user_x86_32_view = { diff --git a/include/linux/elf.h b/include/linux/elf.h index edc3dac3f02..0b61ca41a04 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -360,6 +360,7 @@ typedef struct elf64_shdr { #define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ #define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ /* Note header in a PT_NOTE section */ -- GitLab From b50863d6e36ec3764882f57417b5c5cfe35a9b4b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 Jul 2008 12:58:53 -0300 Subject: [PATCH 3948/5416] V4L/DVB (8553): media/video/Kconfig: get rid of a select Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3e9e0dcd217..3f945b0d52b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -822,8 +822,7 @@ config VIDEO_OVCAMCHIP config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on VIDEO_V4L1 && I2C - select VIDEO_OVCAMCHIP + depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. -- GitLab From 96f1e40431d4b0afc75474d7961f8dd98ef21112 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 Jul 2008 13:07:42 -0300 Subject: [PATCH 3949/5416] V4L/DVB (8554): media/video/Kconfig: cosmetic changes and convert select into depends on It seems cosmetically better to let USB drivers be the last one. Also, two SOC drivers were using select, instead of depends on SOC_CAMERA. Since select has some drawbacks when checking for dependencies, convert those two into depends on. Cc: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 118 ++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3f945b0d52b..1f6c9ee3afd 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -784,6 +784,64 @@ config VIDEO_CAFE_CCIC CMOS camera controller. This is the controller found on first- generation OLPC systems. +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 && HAS_DMA + select VIDEOBUF_GEN + help + SoC Camera is a common API to several cameras, not connecting + over a bus like PCI or USB. For example some i2c camera connected + directly to the data bus of an SoC. + +config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA && I2C + select GPIO_PCA953X if MT9M001_PCA9536_SWITCH + help + This driver supports MT9M001 cameras from Micron, monochrome + and colour models. + +config MT9M001_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9m001" + depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO + help + Select this if your MT9M001 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config SOC_CAMERA_MT9V022 + tristate "mt9v022 support" + depends on SOC_CAMERA && I2C + select GPIO_PCA953X if MT9V022_PCA9536_SWITCH + help + This driver supports MT9V022 cameras from Micron + +config MT9V022_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9v022" + depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO + help + Select this if your MT9V022 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config SOC_CAMERA_PLATFORM + tristate "platform camera support" + depends on SOC_CAMERA + help + This is a generic SoC camera platform driver, useful for testing + +config VIDEO_PXA27x + tristate "PXA27x Quick Capture Interface driver" + depends on VIDEO_DEV && PXA27x && SOC_CAMERA + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the PXA27x Quick Capture Interface + +config VIDEO_SH_MOBILE_CEU + tristate "SuperH Mobile CEU Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA + select VIDEOBUF_DMA_CONTIG + ---help--- + This is a v4l2 driver for the SuperH Mobile CEU Interface + # # USB Multimedia device configuration # @@ -913,64 +971,4 @@ config USB_S2255 endif # V4L_USB_DRIVERS -config SOC_CAMERA - tristate "SoC camera support" - depends on VIDEO_V4L2 && HAS_DMA - select VIDEOBUF_GEN - help - SoC Camera is a common API to several cameras, not connecting - over a bus like PCI or USB. For example some i2c camera connected - directly to the data bus of an SoC. - -config SOC_CAMERA_MT9M001 - tristate "mt9m001 support" - depends on SOC_CAMERA && I2C - select GPIO_PCA953X if MT9M001_PCA9536_SWITCH - help - This driver supports MT9M001 cameras from Micron, monochrome - and colour models. - -config MT9M001_PCA9536_SWITCH - bool "pca9536 datawidth switch for mt9m001" - depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO - help - Select this if your MT9M001 camera uses a PCA9536 I2C GPIO - extender to switch between 8 and 10 bit datawidth modes - -config SOC_CAMERA_MT9V022 - tristate "mt9v022 support" - depends on SOC_CAMERA && I2C - select GPIO_PCA953X if MT9V022_PCA9536_SWITCH - help - This driver supports MT9V022 cameras from Micron - -config MT9V022_PCA9536_SWITCH - bool "pca9536 datawidth switch for mt9v022" - depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO - help - Select this if your MT9V022 camera uses a PCA9536 I2C GPIO - extender to switch between 8 and 10 bit datawidth modes - -config SOC_CAMERA_PLATFORM - tristate "platform camera support" - depends on SOC_CAMERA - help - This is a generic SoC camera platform driver, useful for testing - -config VIDEO_PXA27x - tristate "PXA27x Quick Capture Interface driver" - depends on VIDEO_DEV && PXA27x - select SOC_CAMERA - select VIDEOBUF_DMA_SG - ---help--- - This is a v4l2 driver for the PXA27x Quick Capture Interface - -config VIDEO_SH_MOBILE_CEU - tristate "SuperH Mobile CEU Interface driver" - depends on VIDEO_DEV && HAS_DMA - select SOC_CAMERA - select VIDEOBUF_DMA_CONTIG - ---help--- - This is a v4l2 driver for the SuperH Mobile CEU Interface - endif # VIDEO_CAPTURE_DRIVERS -- GitLab From 29e66a6ce84abe04bc809ddb35634752881dec79 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 4 Sep 2008 17:24:51 -0300 Subject: [PATCH 3950/5416] V4L/DVB: follow lspci device/vendor style Use "[%04x:%04x]" for PCI vendor/device IDs to follow the format used by lspci(8). Signed-off-by: Bjorn Helgaas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- drivers/media/dvb/ttpci/av7110.c | 2 +- drivers/media/dvb/ttpci/budget-av.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttpci/budget-patch.c | 2 +- drivers/media/dvb/ttpci/budget.c | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 2 +- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 2 +- drivers/media/video/cx18/cx18-driver.c | 4 ++-- drivers/media/video/ivtv/ivtv-driver.c | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 6afbfbbef0c..48762a2b9e4 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -702,7 +702,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) } if (card->fe == NULL) - printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", card->bt->dev->vendor, card->bt->dev->device, card->bt->dev->subsystem_vendor, diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 0777e8f9544..3b641804f6c 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2256,7 +2256,7 @@ static int frontend_init(struct av7110 *av7110) if (!av7110->fe) { /* FIXME: propagate the failure code from the lower layers */ ret = -ENOMEM; - printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", av7110->dev->pci->vendor, av7110->dev->pci->device, av7110->dev->pci->subsystem_vendor, diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index b7d1f2f18d3..839c94101b4 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1049,7 +1049,7 @@ static void frontend_init(struct budget_av *budget_av) if (fe == NULL) { printk(KERN_ERR "budget-av: A frontend driver was not found " - "for device %04x/%04x subsystem %04x/%04x\n", + "for device [%04x:%04x] subsystem [%04x:%04x]\n", saa->pci->vendor, saa->pci->device, saa->pci->subsystem_vendor, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 060e7c78532..38dd5cf1aed 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1153,7 +1153,7 @@ static void frontend_init(struct budget_ci *budget_ci) } if (budget_ci->budget.dvb_frontend == NULL) { - printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", budget_ci->budget.dev->pci->vendor, budget_ci->budget.dev->pci->device, budget_ci->budget.dev->pci->subsystem_vendor, diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index aa5ed4ef19f..bbd234fe11c 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -360,7 +360,7 @@ static void frontend_init(struct budget_patch* budget) } if (budget->dvb_frontend == NULL) { - printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", budget->dev->pci->vendor, budget->dev->pci->device, budget->dev->pci->subsystem_vendor, diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index f0068996ac0..851e523fbff 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -550,7 +550,7 @@ static void frontend_init(struct budget *budget) } if (budget->dvb_frontend == NULL) { - printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", budget->dev->pci->vendor, budget->dev->pci->device, budget->dev->pci->subsystem_vendor, diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index e6c9cd2e3b9..66ab0c6e978 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1614,7 +1614,7 @@ static void frontend_init(struct ttusb* ttusb) } if (ttusb->fe == NULL) { - printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n", + printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n", le16_to_cpu(ttusb->dev->descriptor.idVendor), le16_to_cpu(ttusb->dev->descriptor.idProduct)); } else { diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index de5829b863f..ab33fec8a19 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1665,7 +1665,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, } if (dec->fe == NULL) { - printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n", + printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n", le16_to_cpu(dec->udev->descriptor.idVendor), le16_to_cpu(dec->udev->descriptor.idProduct)); } else { diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index bd18afebbf8..3419de9a5a4 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -395,9 +395,9 @@ done: if (cx->card == NULL) { cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); - CX18_ERR("Unknown card: vendor/device: %04x/%04x\n", + CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", cx->dev->vendor, cx->dev->device); - CX18_ERR(" subsystem vendor/device: %04x/%04x\n", + CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n", cx->dev->subsystem_vendor, cx->dev->subsystem_device); CX18_ERR("Defaulting to %s card\n", cx->card->name); CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 4afc7ea07e8..6b04930d127 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -655,9 +655,9 @@ done: if (itv->card == NULL) { itv->card = ivtv_get_card(IVTV_CARD_PVR_150); - IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n", + IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", itv->dev->vendor, itv->dev->device); - IVTV_ERR(" subsystem vendor/device: %04x/%04x\n", + IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", itv->dev->subsystem_vendor, itv->dev->subsystem_device); IVTV_ERR(" %s based\n", chipname); IVTV_ERR("Defaulting to %s card\n", itv->card->name); -- GitLab From 95fc2ead8406a6d0aa6d8ccf30125f4a50ae323f Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Mon, 21 Jul 2008 16:21:58 -0300 Subject: [PATCH 3951/5416] V4L/DVB (8560): replace __FUNCTION__ with __func__ v4l/drx397xD: replace __FUNCTION__ with __func__ Signed-off-by: Alexander Beregalov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drx397xD.c | 34 +++++++++++++------------- drivers/media/dvb/frontends/drx397xD.h | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index 3cbed874a6f..e19147bad17 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -96,7 +96,7 @@ static void drx_release_fw(struct drx397xD_state *s) { fw_ix_t ix = s->chip_rev; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); write_lock(&fw[ix].lock); if (fw[ix].refcnt) { @@ -113,7 +113,7 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix) size_t size, len; int i = 0, j, rc = -EINVAL; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); if (ix < 0 || ix >= ARRAY_SIZE(fw)) return -EINVAL; @@ -197,10 +197,10 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix) int len, rc = 0, i = 0; if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { - pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__); + pr_debug("%s drx_fw_ix_t out of range\n", __func__); return -EINVAL; } - pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]); + pr_debug("%s %s\n", __func__, blob_name[ix]); read_lock(&fw[s->chip_rev].lock); data = fw[s->chip_rev].data[ix]; @@ -305,7 +305,7 @@ static int PLL_Set(struct drx397xD_state *s, u32 f_tuner, f = fep->frequency; int rc; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); if ((f > s->frontend.ops.tuner_ops.info.frequency_max) || (f < s->frontend.ops.tuner_ops.info.frequency_min)) @@ -325,7 +325,7 @@ static int PLL_Set(struct drx397xD_state *s, return rc; *df_tuner = f_tuner - f; - pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f, + pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f, f_tuner); return 0; @@ -340,7 +340,7 @@ static int SC_WaitForReady(struct drx397xD_state *s) int cnt = 1000; int rc; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); while (cnt--) { rc = RD16(s, 0x820043); @@ -354,7 +354,7 @@ static int SC_SendCommand(struct drx397xD_state *s, int cmd) { int rc; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); WR16(s, 0x820043, cmd); SC_WaitForReady(s); @@ -368,7 +368,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd) { int rc, cnt = 1000; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); rc = WR16(s, 0x420032, cmd); if (rc < 0) @@ -389,7 +389,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd) static int HI_CfgCommand(struct drx397xD_state *s) { - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); WR16(s, 0x420033, 0x3973); WR16(s, 0x420034, s->config.w50); // code 4, log 4 @@ -419,7 +419,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) u16 w0C = agc->w0C; int quot, rem, i, rc = -EINVAL; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); if (agc->w04 > 0x3ff) goto exit_rc; @@ -478,7 +478,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) u16 w06 = agc->w06; int rc = -1; - pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06); + pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06); if (w04 > 0x3ff) goto exit_rc; @@ -554,7 +554,7 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s) int lockstat; u32 clk, clk_limit; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); if (s->config.d5C == 0) { EXIT_RC(WR16(s, 0x08200e8, 0x010)); @@ -598,7 +598,7 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s) if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) { s->f_osc = clk; - pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__, + pr_debug("%s: osc %d %d [Hz]\n", __func__, s->config.f_osc * 1000, clk - s->config.f_osc * 1000); } rc = WR16(s, 0x08200e8, 0); @@ -610,7 +610,7 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) { int rc, si, bp; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); si = s->config.wA0; if (s->config.w98 == 0) { @@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s, int rc, df_tuner; int a, b, c, d; - pr_debug("%s %d\n", __FUNCTION__, s->config.d60); + pr_debug("%s %d\n", __func__, s->config.d60); if (s->config.d60 != 2) goto set_tuner; @@ -1082,7 +1082,7 @@ static int drx397x_init(struct dvb_frontend *fe) struct drx397xD_state *s = fe->demodulator_priv; int rc; - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s\n", __func__); s->config.rfagc.d00 = 2; /* 0x7c */ s->config.rfagc.w04 = 0; diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h index ddc7a07971b..2ad1ea0ccfb 100644 --- a/drivers/media/dvb/frontends/drx397xD.h +++ b/drivers/media/dvb/frontends/drx397xD.h @@ -122,7 +122,7 @@ extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, struct i2c_adapter *i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif /* CONFIG_DVB_DRX397XD */ -- GitLab From 95f73c5b57990c97047c200b8746ab62a360c5bc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Jul 2008 14:20:12 -0300 Subject: [PATCH 3952/5416] V4L/DVB (8561): make ivtv_claim_stream() static ivtv_claim_stream() can now become static. Signed-off-by: Adrian Bunk Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-fileops.c | 2 +- drivers/media/video/ivtv/ivtv-fileops.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 7ec5c99f9ad..304261efc53 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -39,7 +39,7 @@ associated VBI streams are also automatically claimed. Possible error returns: -EBUSY if someone else has claimed the stream or 0 on success. */ -int ivtv_claim_stream(struct ivtv_open_id *id, int type) +static int ivtv_claim_stream(struct ivtv_open_id *id, int type) { struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[type]; diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h index 2c8d5186c9c..df81e790147 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ b/drivers/media/video/ivtv/ivtv-fileops.h @@ -38,11 +38,6 @@ void ivtv_unmute(struct ivtv *itv); /* Utilities */ -/* Try to claim a stream for the filehandle. Return 0 on success, - -EBUSY if stream already claimed. Once a stream is claimed, it - remains claimed until the associated filehandle is closed. */ -int ivtv_claim_stream(struct ivtv_open_id *id, int type); - /* Release a previously claimed stream. */ void ivtv_release_stream(struct ivtv_stream *s); -- GitLab From d56dc61265d2527a63ab5b0f03199a43cd89ca36 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 30 Jul 2008 08:43:36 -0300 Subject: [PATCH 3953/5416] V4L/DVB (8613): v4l: move BKL down to the driver level. The BKL is now moved from the video_open function in v4l2-dev.c to the various drivers. It seems about a third of the drivers already has a lock of some sort protecting the open(), another third uses video_exclusive_open (yuck!) and the last third required adding the BKL in their open function. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/dsbr100.c | 3 +++ drivers/media/radio/radio-si470x.c | 2 ++ drivers/media/video/bt8xx/bttv-driver.c | 20 +++++++++++++++---- drivers/media/video/cafe_ccic.c | 6 +++++- drivers/media/video/cx23885/cx23885-417.c | 10 ++++++++-- drivers/media/video/cx23885/cx23885-video.c | 10 ++++++++-- drivers/media/video/cx88/cx88-blackbird.c | 8 +++++++- drivers/media/video/cx88/cx88-video.c | 10 ++++++++-- drivers/media/video/em28xx/em28xx-video.c | 7 ++++++- drivers/media/video/meye.c | 7 ++++++- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 ++++++ drivers/media/video/s2255drv.c | 6 ++++++ drivers/media/video/saa5246a.c | 8 +++++++- drivers/media/video/saa5249.c | 8 +++++++- drivers/media/video/saa7134/saa7134-empress.c | 3 +++ drivers/media/video/saa7134/saa7134-video.c | 8 +++++++- drivers/media/video/se401.c | 6 +++++- drivers/media/video/stk-webcam.c | 6 +++++- drivers/media/video/stradis.c | 6 +++++- drivers/media/video/stv680.c | 2 ++ drivers/media/video/usbvideo/vicam.c | 6 ++++++ .../media/video/usbvision/usbvision-video.c | 2 ++ drivers/media/video/v4l2-dev.c | 3 --- drivers/media/video/vivi.c | 7 ++++++- drivers/media/video/zoran_driver.c | 3 +++ drivers/media/video/zr364xx.c | 8 +++++++- 26 files changed, 146 insertions(+), 25 deletions(-) diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 70c65a74592..3a4eb444a7c 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -407,15 +407,18 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) { struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + lock_kernel(); radio->users = 1; radio->muted = 1; if (dsbr100_start(radio)<0) { warn("Radio did not start up properly"); radio->users = 0; + unlock_kernel(); return -EIO; } dsbr100_setfreq(radio, radio->curfreq); + unlock_kernel(); return 0; } diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 16c7ef20265..337d5579383 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1074,6 +1074,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file) struct si470x_device *radio = video_get_drvdata(video_devdata(file)); int retval; + lock_kernel(); radio->users++; retval = usb_autopm_get_interface(radio->intf); @@ -1090,6 +1091,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file) } done: + unlock_kernel(); return retval; } diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 933eaef41ea..c3526d0258f 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3227,6 +3227,7 @@ static int bttv_open(struct inode *inode, struct file *file) dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); + lock_kernel(); for (i = 0; i < bttv_num; i++) { if (bttvs[i].video_dev && bttvs[i].video_dev->minor == minor) { @@ -3241,16 +3242,20 @@ static int bttv_open(struct inode *inode, struct file *file) break; } } - if (NULL == btv) + if (NULL == btv) { + unlock_kernel(); return -ENODEV; + } dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", btv->c.nr,v4l2_type_names[type]); /* allocate per filehandle data */ fh = kmalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; *fh = btv->init; fh->type = type; @@ -3290,6 +3295,7 @@ static int bttv_open(struct inode *inode, struct file *file) bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); bttv_field_count(btv); + unlock_kernel(); return 0; } @@ -3430,21 +3436,26 @@ static int radio_open(struct inode *inode, struct file *file) dprintk("bttv: open minor=%d\n",minor); + lock_kernel(); for (i = 0; i < bttv_num; i++) { if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { btv = &bttvs[i]; break; } } - if (NULL == btv) + if (NULL == btv) { + unlock_kernel(); return -ENODEV; + } dprintk("bttv%d: open called (radio)\n",btv->c.nr); /* allocate per filehandle data */ fh = kmalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; *fh = btv->init; v4l2_prio_open(&btv->prio, &fh->prio); @@ -3457,6 +3468,7 @@ static int radio_open(struct inode *inode, struct file *file) audio_input(btv,TVAUDIO_INPUT_RADIO); mutex_unlock(&btv->lock); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 5405c30dbb0..e9994c81df6 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1476,9 +1476,12 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) { struct cafe_camera *cam; + lock_kernel(); cam = cafe_find_dev(iminor(inode)); - if (cam == NULL) + if (cam == NULL) { + unlock_kernel(); return -ENODEV; + } filp->private_data = cam; mutex_lock(&cam->s_mutex); @@ -1490,6 +1493,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) } (cam->users)++; mutex_unlock(&cam->s_mutex); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 7b0e8c01692..93777d06d0a 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1583,6 +1583,7 @@ static int mpeg_open(struct inode *inode, struct file *file) dprintk(2, "%s()\n", __func__); + lock_kernel(); list_for_each(list, &cx23885_devlist) { h = list_entry(list, struct cx23885_dev, devlist); if (h->v4l_device->minor == minor) { @@ -1591,13 +1592,17 @@ static int mpeg_open(struct inode *inode, struct file *file) } } - if (dev == NULL) + if (dev == NULL) { + unlock_kernel(); return -ENODEV; + } /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; fh->dev = dev; @@ -1608,6 +1613,7 @@ static int mpeg_open(struct inode *inode, struct file *file) V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), fh); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 6047c78d84b..d9bef1a54d1 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -731,6 +731,7 @@ static int video_open(struct inode *inode, struct file *file) enum v4l2_buf_type type = 0; int radio = 0; + lock_kernel(); list_for_each(list, &cx23885_devlist) { h = list_entry(list, struct cx23885_dev, devlist); if (h->video_dev->minor == minor) { @@ -748,16 +749,20 @@ static int video_open(struct inode *inode, struct file *file) dev = h; } } - if (NULL == dev) + if (NULL == dev) { + unlock_kernel(); return -ENODEV; + } dprintk(1, "open minor=%d radio=%d type=%s\n", minor, radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -775,6 +780,7 @@ static int video_open(struct inode *inode, struct file *file) dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 9a1374a38ec..1b7e2e44b80 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1057,12 +1057,15 @@ static int mpeg_open(struct inode *inode, struct file *file) struct cx8802_driver *drv = NULL; int err; + lock_kernel(); dev = cx8802_get_device(inode); dprintk( 1, "%s\n", __func__); - if (dev == NULL) + if (dev == NULL) { + unlock_kernel(); return -ENODEV; + } /* Make sure we can acquire the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); @@ -1077,6 +1080,7 @@ static int mpeg_open(struct inode *inode, struct file *file) if (blackbird_initialize_codec(dev) < 0) { if (drv) drv->request_release(drv); + unlock_kernel(); return -EINVAL; } dprintk(1,"open minor=%d\n",minor); @@ -1086,6 +1090,7 @@ static int mpeg_open(struct inode *inode, struct file *file) if (NULL == fh) { if (drv) drv->request_release(drv); + unlock_kernel(); return -ENOMEM; } file->private_data = fh; @@ -1101,6 +1106,7 @@ static int mpeg_open(struct inode *inode, struct file *file) /* FIXME: locking against other video device */ cx88_set_scale(dev->core, dev->width, dev->height, fh->mpegq.field); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ef4d56ea002..61e03d4703f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -773,6 +773,7 @@ static int video_open(struct inode *inode, struct file *file) enum v4l2_buf_type type = 0; int radio = 0; + lock_kernel(); list_for_each_entry(h, &cx8800_devlist, devlist) { if (h->video_dev->minor == minor) { dev = h; @@ -788,8 +789,10 @@ static int video_open(struct inode *inode, struct file *file) dev = h; } } - if (NULL == dev) + if (NULL == dev) { + unlock_kernel(); return -ENODEV; + } core = dev->core; @@ -798,8 +801,10 @@ static int video_open(struct inode *inode, struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -832,6 +837,7 @@ static int video_open(struct inode *inode, struct file *file) cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); } + unlock_kernel(); return 0; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 49ab0629702..600b340e355 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1512,6 +1512,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) struct em28xx_fh *fh; enum v4l2_buf_type fh_type = 0; + lock_kernel(); list_for_each_entry(h, &em28xx_devlist, devlist) { if (h->vdev->minor == minor) { dev = h; @@ -1527,8 +1528,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev = h; } } - if (NULL == dev) + if (NULL == dev) { + unlock_kernel(); return -ENODEV; + } em28xx_videodbg("open minor=%d type=%s users=%d\n", minor, v4l2_type_names[fh_type], dev->users); @@ -1537,6 +1540,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); + unlock_kernel(); return -ENOMEM; } mutex_lock(&dev->lock); @@ -1573,6 +1577,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); + unlock_kernel(); return errCode; } diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index a9ef7802eb5..cdaff2fdf39 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -845,15 +845,19 @@ static int meye_open(struct inode *inode, struct file *file) { int i, err; + lock_kernel(); err = video_exclusive_open(inode, file); - if (err < 0) + if (err < 0) { + unlock_kernel(); return err; + } mchip_hic_stop(); if (mchip_dma_alloc()) { printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); video_exclusive_release(inode, file); + unlock_kernel(); return -ENOBUFS; } @@ -861,6 +865,7 @@ static int meye_open(struct inode *inode, struct file *file) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; kfifo_reset(meye.grabq); kfifo_reset(meye.doneq); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 00306faeac0..26ffaa276c5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -932,6 +932,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) unsigned int input_cnt,idx; int ret = 0; + lock_kernel(); dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); vp = dip->v4lp; @@ -942,11 +943,13 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) if (!pvr2_hdw_dev_ok(hdw)) { pvr2_trace(PVR2_TRACE_OPEN_CLOSE, "pvr2_v4l2_open: hardware not ready"); + unlock_kernel(); return -EIO; } fhp = kzalloc(sizeof(*fhp),GFP_KERNEL); if (!fhp) { + unlock_kernel(); return -ENOMEM; } @@ -976,6 +979,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) fhp); kfree(fhp); + unlock_kernel(); return ret; } @@ -992,6 +996,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) "Destroying pvr_v4l2_fh id=%p (input map failure)", fhp); kfree(fhp); + unlock_kernel(); return -ENOMEM; } input_cnt = 0; @@ -1015,6 +1020,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) v4l2_prio_open(&vp->prio,&fhp->prio); fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 92b83feae36..de39cf0890f 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1457,6 +1457,7 @@ static int s2255_open(struct inode *inode, struct file *file) int cur_channel = -1; dprintk(1, "s2255: open called (minor=%d)\n", minor); + lock_kernel(); list_for_each(list, &s2255_devlist) { h = list_entry(list, struct s2255_dev, s2255_devlist); for (i = 0; i < MAX_CHANNELS; i++) { @@ -1469,6 +1470,7 @@ static int s2255_open(struct inode *inode, struct file *file) } if ((NULL == dev) || (cur_channel == -1)) { + unlock_kernel(); dprintk(1, "s2255: openv4l no dev\n"); return -ENODEV; } @@ -1490,6 +1492,7 @@ static int s2255_open(struct inode *inode, struct file *file) printk(KERN_INFO "2255 FW load failed.\n"); dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); + unlock_kernel(); return -EFAULT; } } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) { @@ -1506,6 +1509,7 @@ static int s2255_open(struct inode *inode, struct file *file) "try again\n"); dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); + unlock_kernel(); return -EBUSY; } } @@ -1515,6 +1519,7 @@ static int s2255_open(struct inode *inode, struct file *file) if (NULL == fh) { dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); + unlock_kernel(); return -ENOMEM; } @@ -1548,6 +1553,7 @@ static int s2255_open(struct inode *inode, struct file *file) kref_get(&dev->kref); mutex_unlock(&dev->open_lock); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 6ee63e69b36..e2c538ee88f 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -737,9 +738,12 @@ static int saa5246a_open(struct inode *inode, struct file *file) struct saa5246a_device *t = vd->priv; int err; + lock_kernel(); err = video_exclusive_open(inode,file); - if (err < 0) + if (err < 0) { + unlock_kernel(); return err; + } if (t->client==NULL) { err = -ENODEV; @@ -776,11 +780,13 @@ static int saa5246a_open(struct inode *inode, struct file *file) err = -EIO; goto fail; } + unlock_kernel(); return 0; fail: video_exclusive_release(inode,file); + unlock_kernel(); return err; } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 0d639738d4e..96c0fdf1a05 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -633,9 +634,12 @@ static int saa5249_open(struct inode *inode, struct file *file) struct saa5249_device *t=vd->priv; int err,pgbuf; + lock_kernel(); err = video_exclusive_open(inode,file); - if (err < 0) + if (err < 0) { + unlock_kernel(); return err; + } if (t->client==NULL) { err = -ENODEV; @@ -664,10 +668,12 @@ static int saa5249_open(struct inode *inode, struct file *file) t->is_searching[pgbuf] = false; } t->virtual_mode = false; + unlock_kernel(); return 0; fail: video_exclusive_release(inode,file); + unlock_kernel(); return err; } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c0c5d7509c2..6f423d116fb 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -79,9 +79,11 @@ static int ts_open(struct inode *inode, struct file *file) struct saa7134_dev *dev; int err; + lock_kernel(); list_for_each_entry(dev, &saa7134_devlist, devlist) if (dev->empress_dev && dev->empress_dev->minor == minor) goto found; + unlock_kernel(); return -ENODEV; found: @@ -103,6 +105,7 @@ static int ts_open(struct inode *inode, struct file *file) done_up: mutex_unlock(&dev->empress_tsq.vb_lock); done: + unlock_kernel(); return err; } diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 68c26898186..8fd31138f9a 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1330,6 +1330,8 @@ static int video_open(struct inode *inode, struct file *file) struct saa7134_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int radio = 0; + + lock_kernel(); list_for_each_entry(dev, &saa7134_devlist, devlist) { if (dev->video_dev && (dev->video_dev->minor == minor)) goto found; @@ -1342,6 +1344,7 @@ static int video_open(struct inode *inode, struct file *file) goto found; } } + unlock_kernel(); return -ENODEV; found: @@ -1350,8 +1353,10 @@ static int video_open(struct inode *inode, struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) + if (NULL == fh) { + unlock_kernel(); return -ENOMEM; + } file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -1384,6 +1389,7 @@ static int video_open(struct inode *inode, struct file *file) /* switch to video/vbi mode */ video_mux(dev,dev->ctl_input); } + unlock_kernel(); return 0; } diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index acceed5d04a..d16bbf0d278 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -936,14 +936,18 @@ static int se401_open(struct inode *inode, struct file *file) struct usb_se401 *se401 = (struct usb_se401 *)dev; int err = 0; - if (se401->user) + lock_kernel(); + if (se401->user) { + unlock_kernel(); return -EBUSY; + } se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); if (se401->fbuf) file->private_data = dev; else err = -ENOMEM; se401->user = !err; + unlock_kernel(); return err; } diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ad36af30e09..6b1ef5dc562 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -689,11 +689,15 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) vdev = video_devdata(fp); dev = vdev_to_camera(vdev); - if (dev == NULL || !is_present(dev)) + lock_kernel(); + if (dev == NULL || !is_present(dev)) { + unlock_kernel(); return -ENXIO; + } fp->private_data = vdev; kref_get(&dev->kref); usb_autopm_get_interface(dev->interface); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 276bded06ab..a3cbe9be3c1 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1882,12 +1882,16 @@ static int saa_open(struct inode *inode, struct file *file) struct video_device *vdev = video_devdata(file); struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); + lock_kernel(); file->private_data = saa; saa->user++; - if (saa->user > 1) + if (saa->user > 1) { + unlock_kernel(); return 0; /* device open already, don't reset */ + } saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ + unlock_kernel(); return 0; } diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index dce94743945..b21a8d6827c 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1086,6 +1086,7 @@ static int stv_open (struct inode *inode, struct file *file) int err = 0; /* we are called with the BKL held */ + lock_kernel(); stv680->user = 1; err = stv_init (stv680); /* main initialization routine for camera */ @@ -1099,6 +1100,7 @@ static int stv_open (struct inode *inode, struct file *file) } if (err) stv680->user = 0; + unlock_kernel(); return err; } diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 2eb45829791..efb878a7402 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -488,20 +488,24 @@ vicam_open(struct inode *inode, struct file *file) * rely on this fact forever. */ + lock_kernel(); if (cam->open_count > 0) { printk(KERN_INFO "vicam_open called on already opened camera"); + unlock_kernel(); return -EBUSY; } cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); if (!cam->raw_image) { + unlock_kernel(); return -ENOMEM; } cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); if (!cam->framebuf) { kfree(cam->raw_image); + unlock_kernel(); return -ENOMEM; } @@ -509,6 +513,7 @@ vicam_open(struct inode *inode, struct file *file) if (!cam->cntrlbuf) { kfree(cam->raw_image); rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + unlock_kernel(); return -ENOMEM; } @@ -526,6 +531,7 @@ vicam_open(struct inode *inode, struct file *file) cam->open_count++; file->private_data = cam; + unlock_kernel(); return 0; } diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b977116a0dd..b76295a5be8 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -367,6 +367,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) PDEBUG(DBG_IO, "open"); + lock_kernel(); usbvision_reset_powerOffTimer(usbvision); if (usbvision->user) @@ -424,6 +425,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) usbvision_empty_framequeues(usbvision); PDEBUG(DBG_IO, "success"); + unlock_kernel(); return errCode; } diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 155fdec9ac7..6b9f3cb0de9 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -116,7 +116,6 @@ static int video_open(struct inode *inode, struct file *file) if (minor >= VIDEO_NUM_DEVICES) return -ENODEV; - lock_kernel(); mutex_lock(&videodev_lock); vfl = video_device[minor]; if (vfl == NULL) { @@ -126,7 +125,6 @@ static int video_open(struct inode *inode, struct file *file) vfl = video_device[minor]; if (vfl == NULL) { mutex_unlock(&videodev_lock); - unlock_kernel(); return -ENODEV; } } @@ -140,7 +138,6 @@ static int video_open(struct inode *inode, struct file *file) } fops_put(old_fops); mutex_unlock(&videodev_lock); - unlock_kernel(); return err; } diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 8ba8daafd7e..65c8af18e76 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -898,9 +898,11 @@ static int vivi_open(struct inode *inode, struct file *file) printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); + lock_kernel(); list_for_each_entry(dev, &vivi_devlist, vivi_devlist) if (dev->vfd->minor == minor) goto found; + unlock_kernel(); return -ENODEV; found: @@ -925,8 +927,10 @@ found: } unlock: mutex_unlock(&dev->mutex); - if (retval) + if (retval) { + unlock_kernel(); return retval; + } file->private_data = fh; fh->dev = dev; @@ -955,6 +959,7 @@ unlock: sizeof(struct vivi_buffer), fh); vivi_start_thread(fh); + unlock_kernel(); return 0; } diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 2dab9eea4de..4aa1a765626 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -1211,6 +1211,7 @@ zoran_open (struct inode *inode, struct zoran_fh *fh; int i, res, first_open = 0, have_module_locks = 0; + lock_kernel(); /* find the device */ for (i = 0; i < zoran_num; i++) { if (zoran[i]->video_dev->minor == minor) { @@ -1321,6 +1322,7 @@ zoran_open (struct inode *inode, file->private_data = fh; fh->zr = zr; zoran_open_init_session(file); + unlock_kernel(); return 0; @@ -1338,6 +1340,7 @@ open_unlock_and_return: if (zr) { /*mutex_unlock(&zr->resource_lock);*/ } + unlock_kernel(); return res; } diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 18d1c4ba79f..4e1ef10d22d 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -643,14 +643,18 @@ static int zr364xx_open(struct inode *inode, struct file *file) cam->skip = 2; + lock_kernel(); err = video_exclusive_open(inode, file); - if (err < 0) + if (err < 0) { + unlock_kernel(); return err; + } if (!cam->framebuf) { cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); if (!cam->framebuf) { info("vmalloc_32 failed!"); + unlock_kernel(); return -ENOMEM; } } @@ -664,6 +668,7 @@ static int zr364xx_open(struct inode *inode, struct file *file) if (err < 0) { info("error during open sequence: %d", i); mutex_unlock(&cam->lock); + unlock_kernel(); return err; } } @@ -676,6 +681,7 @@ static int zr364xx_open(struct inode *inode, struct file *file) mdelay(100); mutex_unlock(&cam->lock); + unlock_kernel(); return 0; } -- GitLab From 622ecb300345d308c8b4a983ac112b1985d7d156 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 Aug 2008 10:03:17 -0300 Subject: [PATCH 3954/5416] V4L/DVB (8625): saa7134: Add NEC prococol IR decoding capability This patch adds the capability of decoding NEC protocol, received via GPIO18 line. This GPIO port can trigger saa7134 IRQ. A future improvement would be to make it a little more generic to work also with GPIO16 line. A pure IRQ code didn't work, since some delays were introduced on the tests we did. A possible approach would be to use polling at a rate of 2.5 ms or less. If a new code were taken, a code similar to nec_task() could be used. However, this would add an extra overhead to kernel, and will consume more power. Due to that, we took an hybrid approach: an IRQ upper half to trigger when a new key is received and a bottom half to convert pulse-distance into a keycode. The bottom half is polling based, to improve performance. During the bottom half proccess, GPIO18 IRQ line is disabled, preventing IRQ reentrancy and improving performance a little bit. Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 140 +++++++++++++++++++- include/media/ir-common.h | 5 + 2 files changed, 139 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ad08d13dffd..ac6beb2df83 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) -/** rc5 functions */ +/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ static int saa7134_rc5_irq(struct saa7134_dev *dev); +static int saa7134_nec_irq(struct saa7134_dev *dev); +static void nec_task(unsigned long data); +static void saa7134_nec_timer(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ @@ -280,7 +283,9 @@ void saa7134_input_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; - if (!ir->polling && !ir->rc5_gpio) { + if (ir->nec_gpio) { + saa7134_nec_irq(dev); + } else if (!ir->polling && !ir->rc5_gpio) { build_key(dev); } else if (ir->rc5_gpio) { saa7134_rc5_irq(dev); @@ -316,6 +321,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) ir->addr = 0x17; ir->rc5_key_timeout = ir_rc5_key_timeout; ir->rc5_remote_gap = ir_rc5_remote_gap; + } else if (ir->nec_gpio) { + setup_timer(&ir->timer_keyup, saa7134_nec_timer, + (unsigned long)dev); + tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } } @@ -335,6 +344,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keyup = 0; int polling = 0; int rc5_gpio = 0; + int nec_gpio = 0; int ir_type = IR_TYPE_OTHER; int err; @@ -533,6 +543,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keyup = mask_keyup; ir->polling = polling; ir->rc5_gpio = rc5_gpio; + ir->nec_gpio = nec_gpio; /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", @@ -675,8 +686,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) return 1; } -/* ---------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: + +/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms + The first pulse (start) has 9 + 4.5 ms */ + +static void saa7134_nec_timer(unsigned long data) +{ + struct saa7134_dev *dev = (struct saa7134_dev *) data; + struct card_ir *ir = dev->remote; + + dprintk("Cancel key repeat\n"); + + ir_input_nokey(ir->dev, &ir->ir); +} + +static void nec_task(unsigned long data) +{ + struct saa7134_dev *dev = (struct saa7134_dev *) data; + struct card_ir *ir; + struct timeval tv; + int count, pulse, oldpulse, gap; + u32 ircode = 0, not_code = 0; + int ngap = 0; + + if (!data) { + printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); + /* GPIO will be kept disabled */ + return; + } + + ir = dev->remote; + + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + + oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; + pulse = oldpulse; + + do_gettimeofday(&tv); + ir->base_time = tv; + + /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. + Unfortunately, using IRQ to decode pulse didn't work, since it uses + a pulse train of 38KHz. This means one pulse on each 52 us + */ + do { + /* Wait until the end of pulse/space or 5 ms */ + for (count = 0; count < 500; count++) { + udelay(10); + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) + & ir->mask_keydown; + if (pulse != oldpulse) + break; + } + + do_gettimeofday(&tv); + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + + if (!pulse) { + /* Bit 0 has 560 us, while bit 1 has 1120 us. + Do something only if bit == 1 + */ + if (ngap && (gap > 560 + 280)) { + unsigned int shift = ngap - 1; + + /* Address first, then command */ + if (shift < 8) { + shift += 8; + ircode |= 1 << shift; + } else if (shift < 16) { + not_code |= 1 << shift; + } else if (shift < 24) { + shift -= 16; + ircode |= 1 << shift; + } else { + shift -= 24; + not_code |= 1 << shift; + } + } + ngap++; + } + + + ir->base_time = tv; + + /* TIMEOUT - Long pulse */ + if (gap >= 5000) + break; + oldpulse = pulse; + } while (ngap < 32); + + if (ngap == 32) { + /* FIXME: should check if not_code == ~ircode */ + ir->code = ir_extract_bits(ircode, ir->mask_keycode); + + dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", + ir->code, ircode, not_code); + + ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); + } else + dprintk("Repeat last key\n"); + + /* Keep repeating the last key */ + mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); + + saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); +} + +static int saa7134_nec_irq(struct saa7134_dev *dev) +{ + struct card_ir *ir = dev->remote; + + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + tasklet_schedule(&ir->tlet); + + return 1; +} diff --git a/include/media/ir-common.h b/include/media/ir-common.h index b8e8aa91905..f5566d43894 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -25,6 +25,7 @@ #include #include +#include #define IR_TYPE_RC5 1 #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ @@ -85,6 +86,10 @@ struct card_ir { u32 code; /* raw code under construction */ struct timeval base_time; /* time of last seen code */ int active; /* building raw code */ + + /* NEC decoding */ + u32 nec_gpio; + struct tasklet_struct tlet; }; void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, -- GitLab From 8f2b7b70600212f8c809a7bc2d17d33561842440 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 Aug 2008 10:11:25 -0300 Subject: [PATCH 3955/5416] V4L/DVB (8626): Add support for TCL tuner MF02GIP-5N-E Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) and CDI Brasil (www.cdibrasil.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/common/tuners/tuner-simple.c | 2 ++ drivers/media/common/tuners/tuner-types.c | 22 ++++++++++++++++++++++ include/media/tuner.h | 1 + 4 files changed, 26 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 0e2394695bb..30bbdda68d0 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -74,3 +74,4 @@ tuner=72 - Thomson FE6600 tuner=73 - Samsung TCPG 6121P30A tuner=75 - Philips TEA5761 FM Radio tuner=76 - Xceive 5000 tuner +tuner=77 - TCL tuner MF02GIP-5N-E diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index aa773a658a2..fc3a6a9d7c2 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -142,6 +142,7 @@ static inline int tuner_stereo(const int type, const int status) case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: case TUNER_LG_NTSC_TAPE: + case TUNER_TCL_MF02GIP_5N: return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); default: return status & TUNER_STEREO; @@ -494,6 +495,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) case TUNER_PHILIPS_FMD1216ME_MK3: case TUNER_LG_NTSC_TAPE: case TUNER_PHILIPS_FM1256_IH3: + case TUNER_TCL_MF02GIP_5N: buffer[3] = 0x19; break; case TUNER_TNF_5335MF: diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c index 10dddca8b5d..04961a1f44b 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/common/tuners/tuner-types.c @@ -1216,6 +1216,23 @@ static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { }, }; +/* ------------ TUNER_TCL_MF02GIP-5N-E - TCL MF02GIP-5N ------------ */ + +static struct tuner_range tuner_tcl_mf02gip_5n_ntsc_ranges[] = { + { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, +}; + +static struct tuner_params tuner_tcl_mf02gip_5n_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tcl_mf02gip_5n_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_ntsc_ranges), + .cb_first_if_lower_freq = 1, + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1641,6 +1658,11 @@ struct tunertype tuners[] = { .name = "Xceive 5000 tuner", /* see xc5000.c for details */ }, + [TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */ + .name = "TCL tuner MF02GIP-5N-E", + .params = tuner_tcl_mf02gip_5n_params, + .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params), + }, }; EXPORT_SYMBOL(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index 77068fcc86b..ba818985cc8 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -122,6 +122,7 @@ #define TUNER_TDA9887 74 /* This tuner should be used only internally */ #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ #define TUNER_XC5000 76 /* Xceive Silicon Tuner */ +#define TUNER_TCL_MF02GIP_5N 77 /* TCL MF02GIP_5N */ /* tv card specific */ #define TDA9887_PRESENT (1<<0) -- GitLab From b46a9c8b7a8a77f28773816fd2afa1186743457d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 Aug 2008 10:12:35 -0300 Subject: [PATCH 3956/5416] V4L/DVB (8627): Fix mute on bttv driver Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index c3526d0258f..035a58d1aaa 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3275,6 +3275,7 @@ static int bttv_open(struct inode *inode, struct file *file) sizeof(struct bttv_buffer), fh); set_tvnorm(btv,btv->tvnorm); + set_input(btv, btv->input, btv->tvnorm); btv->users++; @@ -3336,6 +3337,10 @@ static int bttv_release(struct inode *inode, struct file *file) btv->users--; bttv_field_count(btv); + + if (!btv->users) + audio_mute(btv, 1); + return 0; } -- GitLab From 08b1438cc2d50f559cc33ca4d9251636cec11647 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 6 Aug 2008 20:13:46 -0300 Subject: [PATCH 3957/5416] V4L/DVB (8628a): Remove duplicated include Removes duplicated #include Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 1edda456fc6..7072cdf74ed 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include -- GitLab From 7d341a6a52f115512d60b2de89b2ebde54da8eff Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 Aug 2008 10:14:13 -0300 Subject: [PATCH 3958/5416] V4L/DVB (8628): bttv: Add support for Encore ENLTV2-FM Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) and CDI Brasil (www.cdibrasil.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/common/ir-keymaps.c | 55 ++++++++++++++++++++-- drivers/media/video/bt8xx/bttv-cards.c | 27 ++++++++++- drivers/media/video/bt8xx/bttv-input.c | 62 +++++++++++++++++++++++-- drivers/media/video/bt8xx/bttv.h | 2 +- include/media/ir-common.h | 1 + 6 files changed, 140 insertions(+), 8 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f32efb6fb12..60ba6683603 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -150,3 +150,4 @@ 149 -> Typhoon TV-Tuner PCI (50684) 150 -> Geovision GV-600 [008a:763c] 151 -> Kozumi KTV-01C +152 -> Encore ENL TV-FM-2 [1000:1801] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 8fa91f846d5..aedfabd5738 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1792,12 +1792,61 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [ 0x41 ] = KEY_GREEN, /* AP2 */ [ 0x47 ] = KEY_YELLOW, /* AP3 */ [ 0x57 ] = KEY_BLUE, /* AP4 */ - - }; - EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); +/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton + Mauro Carvalho Chehab */ +IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { + [0x4c] = KEY_POWER2, + [0x4a] = KEY_TUNER, + [0x40] = KEY_1, + [0x60] = KEY_2, + [0x50] = KEY_3, + [0x70] = KEY_4, + [0x48] = KEY_5, + [0x68] = KEY_6, + [0x58] = KEY_7, + [0x78] = KEY_8, + [0x44] = KEY_9, + [0x54] = KEY_0, + + [0x64] = KEY_LAST, /* +100 */ + [0x4e] = KEY_AGAIN, /* Recall */ + + [0x6c] = KEY_SWITCHVIDEOMODE, /* Video Source */ + [0x5e] = KEY_MENU, + [0x56] = KEY_SCREEN, + [0x7a] = KEY_SETUP, + + [0x46] = KEY_MUTE, + [0x5c] = KEY_MODE, /* Stereo */ + [0x74] = KEY_INFO, + [0x7c] = KEY_CLEAR, + + [0x55] = KEY_UP, + [0x49] = KEY_DOWN, + [0x7e] = KEY_LEFT, + [0x59] = KEY_RIGHT, + [0x6a] = KEY_ENTER, + + [0x42] = KEY_VOLUMEUP, + [0x62] = KEY_VOLUMEDOWN, + [0x52] = KEY_CHANNELUP, + [0x72] = KEY_CHANNELDOWN, + + [0x41] = KEY_RECORD, + [0x51] = KEY_SHUFFLE, /* Snapshot */ + [0x75] = KEY_TIME, /* Timeshift */ + [0x71] = KEY_TV2, /* PIP */ + + [0x45] = KEY_REWIND, + [0x6f] = KEY_PAUSE, + [0x7d] = KEY_FORWARD, + [0x79] = KEY_STOP, +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); + /* for the Technotrend 1500 bundled remotes (grey and black): */ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [ 0x01 ] = KEY_POWER, diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 6081edc362d..13742b0bbe3 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -305,7 +305,7 @@ static struct CARD { { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, - + { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" }, { 0, -1, NULL } }; @@ -3037,6 +3037,31 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .has_remote = 1, }, + [BTTV_BOARD_ENLTV_FM_2] = { + /* Encore TV Tuner Pro ENL TV-FM-2 + Mauro Carvalho Chehab IR disabled + bit 18/17 = 00 -> mute + 01 -> enable external audio input + 10 -> internal audio input (mono?) + 11 -> internal audio input + */ + .gpiomask = 0x060040, + .muxsel = { 2, 3, 3 }, + .gpiomux = { 0x60000, 0x60000, 0x20000, 0x20000 }, + .gpiomute = 0, + .tuner_type = TUNER_TCL_MF02GIP_5N, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + .has_remote = 1, + } }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index a38af98f4ca..2f289d981fe 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -28,8 +28,8 @@ #include "bttvp.h" -static int debug; -module_param(debug, int, 0644); /* debug level (0,1,2) */ +static int ir_debug; +module_param(ir_debug, int, 0644); static int repeat_delay = 500; module_param(repeat_delay, int, 0644); static int repeat_period = 33; @@ -40,6 +40,12 @@ module_param(ir_rc5_remote_gap, int, 0644); static int ir_rc5_key_timeout = 200; module_param(ir_rc5_key_timeout, int, 0644); +#undef dprintk +#define dprintk(arg...) do { \ + if (ir_debug >= 1) \ + printk(arg); \ +} while (0) + #define DEVNAME "bttv-input" /* ---------------------------------------------------------------------- */ @@ -79,6 +85,45 @@ static void ir_handle_key(struct bttv *btv) } +static void ir_enltv_handle_key(struct bttv *btv) +{ + struct card_ir *ir = btv->remote; + u32 gpio, data, keyup; + + /* read gpio value */ + gpio = bttv_gpio_read(&btv->c); + + /* extract data */ + data = ir_extract_bits(gpio, ir->mask_keycode); + + /* Check if it is keyup */ + keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0; + + if ((ir->last_gpio & 0x7f) != data) { + dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n", + gpio, data, + (gpio & ir->mask_keyup) ? " up" : "up/down"); + + ir_input_keydown(ir->dev, &ir->ir, data, data); + if (keyup) + ir_input_nokey(ir->dev, &ir->ir); + } else { + if ((ir->last_gpio & 1 << 31) == keyup) + return; + + dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n", + gpio, data, + (gpio & ir->mask_keyup) ? " up" : "down"); + + if (keyup) + ir_input_nokey(ir->dev, &ir->ir); + else + ir_input_keydown(ir->dev, &ir->ir, data, data); + } + + ir->last_gpio = data | keyup; +} + void bttv_input_irq(struct bttv *btv) { struct card_ir *ir = btv->remote; @@ -92,7 +137,10 @@ static void bttv_input_timer(unsigned long data) struct bttv *btv = (struct bttv*)data; struct card_ir *ir = btv->remote; - ir_handle_key(btv); + if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) + ir_enltv_handle_key(btv); + else + ir_handle_key(btv); mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } @@ -284,6 +332,14 @@ int bttv_input_init(struct bttv *btv) ir->mask_keyup = 0x006000; ir->polling = 50; /* ms */ break; + case BTTV_BOARD_ENLTV_FM_2: + ir_codes = ir_codes_encore_enltv2; + ir->mask_keycode = 0x00fd00; + ir->mask_keyup = 0x000080; + ir->polling = 1; /* ms */ + ir->last_gpio = ir_extract_bits(bttv_gpio_read(&btv->c), + ir->mask_keycode); + break; } if (NULL == ir_codes) { dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6d93d16c96e..46cb90e0985 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -176,7 +176,7 @@ #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 #define BTTV_BOARD_GEOVISION_GV600 0x96 #define BTTV_BOARD_KOZUMI_KTV_01C 0x97 - +#define BTTV_BOARD_ENLTV_FM_2 0x98 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 diff --git a/include/media/ir-common.h b/include/media/ir-common.h index f5566d43894..6f8ef35de4a 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -144,6 +144,7 @@ extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; -- GitLab From a832781cd383e70929c0ceece23f8a5b62e2152b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 25 Jul 2008 10:31:23 -0300 Subject: [PATCH 3959/5416] V4L/DVB (8630): First mxb cleanup phase Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mxb.c | 13 ++- drivers/media/video/tda9840.c | 166 ++++++++++++--------------------- drivers/media/video/tea6415c.c | 131 ++++++++------------------ drivers/media/video/tea6420.c | 147 ++++++++++------------------- 4 files changed, 155 insertions(+), 302 deletions(-) diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8ef578caba3..7c9820c72a6 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -466,15 +466,15 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ - saa7146_vv_init(dev,&vv_data); - if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { + saa7146_vv_init(dev, &vv_data); + if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; } /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ - if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { - if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { + if (MXB_BOARD_CAN_DO_VBI(dev)) { + if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); } } @@ -486,7 +486,7 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data i2c_use_client(mxb->saa7111a); i2c_use_client(mxb->tuner); - printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num); + printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); mxb_num++; mxb_init_done(dev); @@ -737,8 +737,8 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); memset(t,0,sizeof(*t)); - strcpy(t->name, "Television"); + strlcpy(t->name, "Television", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ @@ -746,7 +746,6 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) /* FIXME: add the real signal strength here */ t->signal = 0xffff; t->afc = 0; - mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); t->audmode = mxb->cur_mode; diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 2437c1a269c..57deeb89331 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -2,6 +2,7 @@ tda9840 - i2c-driver for the tda9840 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold + Copyright (C) 2008 Hans Verkuil The tda9840 is a stereo/dual sound processor with digital identification. It can be found at address 0x84 on the i2c-bus. @@ -28,15 +29,18 @@ #include #include #include - +#include +#include #include "tda9840.h" -static int debug; /* insmod parameter */ +MODULE_AUTHOR("Michael Hunold "); +MODULE_DESCRIPTION("tda9840 driver"); +MODULE_LICENSE("GPL"); + +static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); -#define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) +MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define SWITCH 0x00 #define LEVEL_ADJUST 0x02 @@ -49,18 +53,21 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; -static struct i2c_driver driver; -static struct i2c_client client_template; +static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) +{ + if (i2c_smbus_write_byte_data(client, reg, val)) + v4l_dbg(1, debug, client, "error writing %02x to %02x\n", + val, reg); +} -static int command(struct i2c_client *client, unsigned int cmd, void *arg) +static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) { int result; int byte = *(int *)arg; switch (cmd) { case TDA9840_SWITCH: - - dprintk("TDA9840_SWITCH: 0x%02x\n", byte); + v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); if (byte != TDA9840_SET_MONO && byte != TDA9840_SET_MUTE @@ -73,14 +80,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; } - result = i2c_smbus_write_byte_data(client, SWITCH, byte); - if (result) - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + tda9840_write(client, SWITCH, byte); break; case TDA9840_LEVEL_ADJUST: - - dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte); + v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); /* check for correct range */ if (byte > 25 || byte < -20) @@ -92,15 +96,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) byte += 0x8; else byte = -byte; - - result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte); - if (result) - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + tda9840_write(client, LEVEL_ADJUST, byte); break; case TDA9840_STEREO_ADJUST: - - dprintk("TDA9840_STEREO_ADJUST: %d\n", byte); + v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte); /* check for correct range */ if (byte > 25 || byte < -24) @@ -113,9 +113,7 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) else byte = -byte; - result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte); - if (result) - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + tda9840_write(client, STEREO_ADJUST, byte); break; case TDA9840_DETECT: { @@ -123,29 +121,29 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST); if (byte == -1) { - dprintk("i2c_smbus_read_byte_data() failed\n"); + v4l_dbg(1, debug, client, + "i2c_smbus_read_byte_data() failed\n"); return -EIO; } - if (0 != (byte & 0x80)) { - dprintk("TDA9840_DETECT: register contents invalid\n"); + if (byte & 0x80) { + v4l_dbg(1, debug, client, + "TDA9840_DETECT: register contents invalid\n"); return -EINVAL; } - dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte); - *ret = ((byte & 0x60) >> 5); + v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); + *ret = (byte & 0x60) >> 5; result = 0; break; } case TDA9840_TEST: - dprintk("TDA9840_TEST: 0x%02x\n", byte); + v4l_dbg(1, debug, client, "TDA9840_TEST: 0x%02x\n", byte); /* mask out irrelevant bits */ byte &= 0x3; - result = i2c_smbus_write_byte_data(client, TEST, byte); - if (result) - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + tda9840_write(client, TEST, byte); break; default: return -ENOIOCTLCMD; @@ -157,99 +155,51 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static int detect(struct i2c_adapter *adapter, int address, int kind) +static int tda9840_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; - int result = 0; - - int byte = 0x0; + int result; + int byte; /* let's see whether this adapter can support what we need */ - if (0 == i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA | + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return 0; - } - /* allocate memory for client structure */ - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) { - printk("not enough kernel memory\n"); - return -ENOMEM; - } - - /* fill client structure */ - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->addr = address; - client->adapter = adapter; - - /* tell the i2c layer a new client has arrived */ - if (0 != (result = i2c_attach_client(client))) { - kfree(client); - return result; - } + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); /* set initial values for level & stereo - adjustment, mode */ byte = 0; - result = command(client, TDA9840_LEVEL_ADJUST, &byte); - result += command(client, TDA9840_STEREO_ADJUST, &byte); + result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); + result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); byte = TDA9840_SET_MONO; - result = command(client, TDA9840_SWITCH, &byte); + result = tda9840_command(client, TDA9840_SWITCH, &byte); if (result) { - dprintk("could not initialize tda9840\n"); + v4l_dbg(1, debug, client, "could not initialize tda9840\n"); return -ENODEV; } - - printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); return 0; } -static int attach(struct i2c_adapter *adapter) +static int tda9840_legacy_probe(struct i2c_adapter *adapter) { - /* let's see whether this is a know adapter we can attach to */ - if (adapter->id != I2C_HW_SAA7146) { - dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); - return -ENODEV; - } - - return i2c_probe(adapter, &addr_data, &detect); + /* Let's see whether this is a known adapter we can attach to. + Prevents conflicts with tvaudio.c. */ + return adapter->id == I2C_HW_SAA7146; } - -static int detach(struct i2c_client *client) -{ - int ret = i2c_detach_client(client); - kfree(client); - return ret; -} - -static struct i2c_driver driver = { - .driver = { - .name = "tda9840", - }, - .id = I2C_DRIVERID_TDA9840, - .attach_adapter = attach, - .detach_client = detach, - .command = command, +static const struct i2c_device_id tda9840_id[] = { + { "tda9840", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, tda9840_id); -static struct i2c_client client_template = { +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", - .driver = &driver, + .driverid = I2C_DRIVERID_TDA9840, + .command = tda9840_command, + .probe = tda9840_probe, + .legacy_probe = tda9840_legacy_probe, + .id_table = tda9840_id, }; - -static int __init this_module_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit this_module_exit(void) -{ - i2c_del_driver(&driver); -} - -module_init(this_module_init); -module_exit(this_module_exit); - -MODULE_AUTHOR("Michael Hunold "); -MODULE_DESCRIPTION("tda9840 driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 421c1445e96..cde092adbb5 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -2,6 +2,7 @@ tea6415c - i2c-driver for the tea6415c by SGS Thomson Copyright (C) 1998-2003 Michael Hunold + Copyright (C) 2008 Hans Verkuil The tea6415c is a bus controlled video-matrix-switch with 8 inputs and 6 outputs. @@ -30,18 +31,18 @@ #include #include #include - +#include +#include #include "tea6415c.h" -static int debug; /* insmod parameter */ -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); +MODULE_AUTHOR("Michael Hunold "); +MODULE_DESCRIPTION("tea6415c driver"); +MODULE_LICENSE("GPL"); -#define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) +static int debug; +module_param(debug, int, 0644); -#define TEA6415C_NUM_INPUTS 8 -#define TEA6415C_NUM_OUTPUTS 6 +MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; @@ -49,60 +50,6 @@ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIEN /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; -static struct i2c_driver driver; -static struct i2c_client client_template; - -/* this function is called by i2c_probe */ -static int detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client = NULL; - int err = 0; - - /* let's see whether this adapter can support what we need */ - if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { - return 0; - } - - /* allocate memory for client structure */ - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) { - return -ENOMEM; - } - - /* fill client structure */ - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->addr = address; - client->adapter = adapter; - - /* tell the i2c layer a new client has arrived */ - if (0 != (err = i2c_attach_client(client))) { - kfree(client); - return err; - } - - printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); - - return 0; -} - -static int attach(struct i2c_adapter *adapter) -{ - /* let's see whether this is a know adapter we can attach to */ - if (adapter->id != I2C_HW_SAA7146) { - dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); - return -ENODEV; - } - - return i2c_probe(adapter, &addr_data, &detect); -} - -static int detach(struct i2c_client *client) -{ - int ret = i2c_detach_client(client); - kfree(client); - return ret; -} - /* makes a connection between the input-pin 'i' and the output-pin 'o' for the tea6415c-client 'client' */ static int switch_matrix(struct i2c_client *client, int i, int o) @@ -110,7 +57,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o) u8 byte = 0; int ret; - dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); + v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o); /* check if the pins are valid */ if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) @@ -168,14 +115,14 @@ static int switch_matrix(struct i2c_client *client, int i, int o) ret = i2c_smbus_write_byte(client, byte); if (ret) { - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); + v4l_dbg(1, debug, client, + "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } - return ret; } -static int command(struct i2c_client *client, unsigned int cmd, void *arg) +static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) { struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; int result = 0; @@ -187,38 +134,40 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) default: return -ENOIOCTLCMD; } - return result; } -static struct i2c_driver driver = { - .driver = { - .name = "tea6415c", - }, - .id = I2C_DRIVERID_TEA6415C, - .attach_adapter = attach, - .detach_client = detach, - .command = command, -}; - -static struct i2c_client client_template = { - .name = "tea6415c", - .driver = &driver, -}; - -static int __init this_module_init(void) +/* this function is called by i2c_probe */ +static int tea6415c_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - return i2c_add_driver(&driver); + /* let's see whether this adapter can support what we need */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) + return 0; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + return 0; } -static void __exit this_module_exit(void) +static int tea6415c_legacy_probe(struct i2c_adapter *adapter) { - i2c_del_driver(&driver); + /* Let's see whether this is a known adapter we can attach to. + Prevents conflicts with tvaudio.c. */ + return adapter->id == I2C_HW_SAA7146; } -module_init(this_module_init); -module_exit(this_module_exit); +static const struct i2c_device_id tea6415c_id[] = { + { "tea6415c", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tea6415c_id); -MODULE_AUTHOR("Michael Hunold "); -MODULE_DESCRIPTION("tea6415c driver"); -MODULE_LICENSE("GPL"); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tea6415c", + .driverid = I2C_DRIVERID_TEA6415C, + .command = tea6415c_command, + .probe = tea6415c_probe, + .legacy_probe = tea6415c_legacy_probe, + .id_table = tea6415c_id, +}; diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index b5c8957d130..e50820969e6 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -2,6 +2,7 @@ tea6420 - i2c-driver for the tea6420 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold + Copyright (C) 2008 Hans Verkuil The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, 4 stereo outputs and gain control for each output. @@ -30,15 +31,18 @@ #include #include #include - +#include +#include #include "tea6420.h" -static int debug; /* insmod parameter */ +MODULE_AUTHOR("Michael Hunold "); +MODULE_DESCRIPTION("tea6420 driver"); +MODULE_LICENSE("GPL"); + +static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); -#define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) +MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; @@ -46,23 +50,20 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; -static struct i2c_driver driver; -static struct i2c_client client_template; - /* make a connection between the input 'i' and the output 'o' with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) { - u8 byte = 0; + u8 byte; int ret; - dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g); + v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g); /* check if the parameters are valid */ if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) return -1; - byte = ((o - 1) << 5); + byte = ((o - 1) << 5); byte |= (i - 1); /* to understand this, have a look at the tea6420-specs (p.5) */ @@ -82,40 +83,41 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) ret = i2c_smbus_write_byte(client, byte); if (ret) { - dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); + v4l_dbg(1, debug, client, + "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } - return 0; } -/* this function is called by i2c_probe */ -static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) +static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) { - struct i2c_client *client; - int err = 0, i = 0; + struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; + int result = 0; - /* let's see whether this adapter can support what we need */ - if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { - return 0; + switch (cmd) { + case TEA6420_SWITCH: + result = tea6420_switch(client, a->in, a->out, a->gain); + break; + default: + return -ENOIOCTLCMD; } - /* allocate memory for client structure */ - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) { - return -ENOMEM; - } + return result; +} - /* fill client structure */ - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->addr = address; - client->adapter = adapter; +/* this function is called by i2c_probe */ +static int tea6420_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err, i; - /* tell the i2c layer a new client has arrived */ - if (0 != (err = i2c_attach_client(client))) { - kfree(client); - return err; - } + /* let's see whether this adapter can support what we need */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) + return -EIO; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); /* set initial values: set "mute"-input to all outputs at gain 0 */ err = 0; @@ -123,78 +125,31 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) err += tea6420_switch(client, 6, i, 0); } if (err) { - dprintk("could not initialize tea6420\n"); + v4l_dbg(1, debug, client, "could not initialize tea6420\n"); kfree(client); return -ENODEV; } - - printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); - return 0; } -static int attach(struct i2c_adapter *adapter) +static int tea6420_legacy_probe(struct i2c_adapter *adapter) { - /* let's see whether this is a know adapter we can attach to */ - if (adapter->id != I2C_HW_SAA7146) { - dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); - return -ENODEV; - } - - return i2c_probe(adapter, &addr_data, &tea6420_detect); -} - -static int detach(struct i2c_client *client) -{ - int ret = i2c_detach_client(client); - kfree(client); - return ret; -} - -static int command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; - int result = 0; - - switch (cmd) { - case TEA6420_SWITCH: - result = tea6420_switch(client, a->in, a->out, a->gain); - break; - default: - return -ENOIOCTLCMD; - } - - return result; + /* Let's see whether this is a known adapter we can attach to. + Prevents conflicts with tvaudio.c. */ + return adapter->id == I2C_HW_SAA7146; } -static struct i2c_driver driver = { - .driver = { - .name = "tea6420", - }, - .id = I2C_DRIVERID_TEA6420, - .attach_adapter = attach, - .detach_client = detach, - .command = command, +static const struct i2c_device_id tea6420_id[] = { + { "tea6420", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, tea6420_id); -static struct i2c_client client_template = { +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", - .driver = &driver, + .driverid = I2C_DRIVERID_TEA6420, + .command = tea6420_command, + .probe = tea6420_probe, + .legacy_probe = tea6420_legacy_probe, + .id_table = tea6420_id, }; - -static int __init this_module_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit this_module_exit(void) -{ - i2c_del_driver(&driver); -} - -module_init(this_module_init); -module_exit(this_module_exit); - -MODULE_AUTHOR("Michael Hunold "); -MODULE_DESCRIPTION("tea6420 driver"); -MODULE_LICENSE("GPL"); -- GitLab From 188919ac57810e39138749338d5a33ba1e970e23 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 8 Aug 2008 07:21:00 -0300 Subject: [PATCH 3960/5416] V4L/DVB (8634): v4l2: extend MPEG Encoding API with AVC and AAC Adds Advanced Audio Coding (AAC) and MPEG-4 Advanced Video Coding (AVC/H.264) as audio/video codecs to the extended controls API. Updates cx2341x driver to the new values. Signed-off-by: Janne Grunau Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx2341x.c | 5 ++++- drivers/media/video/v4l2-common.c | 14 ++++++++------ include/linux/videodev2.h | 6 ++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 22847a0444f..cbbe47fb87b 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -508,7 +508,10 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, /* this setting is read-only for the cx2341x since the V4L2_CID_MPEG_STREAM_TYPE really determines the MPEG-1/2 setting */ - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); if (err == 0) qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; return err; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 88ca1310441..893ac496c4b 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -187,9 +187,10 @@ const char **v4l2_ctrl_get_menu(u32 id) NULL }; static const char *mpeg_audio_encoding[] = { - "Layer I", - "Layer II", - "Layer III", + "MPEG-1 Layer I", + "MPEG-1 Layer II", + "MPEG-1 Layer III", + "MPEG-4 AAC", NULL }; static const char *mpeg_audio_l1_bitrate[] = { @@ -271,6 +272,7 @@ const char **v4l2_ctrl_get_menu(u32 id) static const char *mpeg_video_encoding[] = { "MPEG-1", "MPEG-2", + "MPEG-4 AVC", NULL }; static const char *mpeg_video_aspect[] = { @@ -358,7 +360,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste /* MPEG controls */ case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; - case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break; + case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding"; break; case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; @@ -493,7 +495,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) case V4L2_CID_MPEG_AUDIO_ENCODING: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1, + V4L2_MPEG_AUDIO_ENCODING_AAC, 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return v4l2_ctrl_query_fill(qctrl, @@ -535,7 +537,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) case V4L2_CID_MPEG_VIDEO_ENCODING: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_VIDEO_ENCODING_MPEG_1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, V4L2_MPEG_VIDEO_ENCODING_MPEG_2); case V4L2_CID_MPEG_VIDEO_ASPECT: return v4l2_ctrl_query_fill(qctrl, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 303d93ffd6b..350aba2714f 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -910,6 +910,7 @@ enum v4l2_mpeg_audio_encoding { V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, }; #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { @@ -992,8 +993,9 @@ enum v4l2_mpeg_audio_crc { /* MPEG video */ #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) enum v4l2_mpeg_video_encoding { - V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, }; #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) enum v4l2_mpeg_video_aspect { -- GitLab From e6b5da88fb24c5c1e52707faea7c46df09da42f0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 07:38:07 -0300 Subject: [PATCH 3961/5416] V4L/DVB (8635): v4l: add AC-3 audio support to the MPEG Encoding API Some models of the saa6752hs support AC-3. Extend the API with the necessary controls for AC-3. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 42 +++++++++++++++++++++++++++---- include/linux/videodev2.h | 23 +++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 893ac496c4b..0a96cc35738 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -187,10 +187,11 @@ const char **v4l2_ctrl_get_menu(u32 id) NULL }; static const char *mpeg_audio_encoding[] = { - "MPEG-1 Layer I", - "MPEG-1 Layer II", - "MPEG-1 Layer III", - "MPEG-4 AAC", + "MPEG-1/2 Layer I", + "MPEG-1/2 Layer II", + "MPEG-1/2 Layer III", + "MPEG-2/4 AAC", + "AC-3", NULL }; static const char *mpeg_audio_l1_bitrate[] = { @@ -244,6 +245,28 @@ const char **v4l2_ctrl_get_menu(u32 id) "320 kbps", NULL }; + static const char *mpeg_audio_ac3_bitrate[] = { + "32 kbps", + "40 kbps", + "48 kbps", + "56 kbps", + "64 kbps", + "80 kbps", + "96 kbps", + "112 kbps", + "128 kbps", + "160 kbps", + "192 kbps", + "224 kbps", + "256 kbps", + "320 kbps", + "384 kbps", + "448 kbps", + "512 kbps", + "576 kbps", + "640 kbps", + NULL + }; static const char *mpeg_audio_mode[] = { "Stereo", "Joint Stereo", @@ -313,6 +336,8 @@ const char **v4l2_ctrl_get_menu(u32 id) return mpeg_audio_l2_bitrate; case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return mpeg_audio_l3_bitrate; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + return mpeg_audio_ac3_bitrate; case V4L2_CID_MPEG_AUDIO_MODE: return mpeg_audio_mode; case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: @@ -364,6 +389,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: name = "Audio AC-3 Bitrate"; break; case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; @@ -409,6 +435,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_AUDIO_L1_BITRATE: case V4L2_CID_MPEG_AUDIO_L2_BITRATE: case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: case V4L2_CID_MPEG_AUDIO_MODE: case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: case V4L2_CID_MPEG_AUDIO_EMPHASIS: @@ -495,7 +522,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) case V4L2_CID_MPEG_AUDIO_ENCODING: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_1, - V4L2_MPEG_AUDIO_ENCODING_AAC, 1, + V4L2_MPEG_AUDIO_ENCODING_AC3, 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return v4l2_ctrl_query_fill(qctrl, @@ -512,6 +539,11 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) V4L2_MPEG_AUDIO_L3_BITRATE_32K, V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, V4L2_MPEG_AUDIO_L3_BITRATE_192K); + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_AC3_BITRATE_32K, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K); case V4L2_CID_MPEG_AUDIO_MODE: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_MODE_STEREO, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 350aba2714f..9054764f4cd 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -911,6 +911,7 @@ enum v4l2_mpeg_audio_encoding { V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, }; #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { @@ -989,6 +990,28 @@ enum v4l2_mpeg_audio_crc { V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) +#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+110) +enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, +}; /* MPEG video */ #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) -- GitLab From 69028d7096a6092812f0482833f0820593f1cafd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 07:55:00 -0300 Subject: [PATCH 3962/5416] V4L/DVB (8636): v4l2: add v4l2_ctrl_get_name control support function. Add function that returns the control name. Allows this to be used in places where the normal v4l2_ctrl_query_fill() function cannot be used (e.g. uvc). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 109 ++++++++++++++++-------------- include/media/v4l2-common.h | 1 + 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 0a96cc35738..da4791de705 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -362,63 +362,72 @@ const char **v4l2_ctrl_get_menu(u32 id) } EXPORT_SYMBOL(v4l2_ctrl_get_menu); -/* Fill in a struct v4l2_queryctrl */ -int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) +/* Return the control name. */ +const char *v4l2_ctrl_get_name(u32 id) { - const char *name; - - qctrl->flags = 0; - switch (qctrl->id) { + switch (id) { /* USER controls */ - case V4L2_CID_USER_CLASS: name = "User Controls"; break; - case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break; - case V4L2_CID_AUDIO_MUTE: name = "Mute"; break; - case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break; - case V4L2_CID_AUDIO_BASS: name = "Bass"; break; - case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break; - case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break; - case V4L2_CID_BRIGHTNESS: name = "Brightness"; break; - case V4L2_CID_CONTRAST: name = "Contrast"; break; - case V4L2_CID_SATURATION: name = "Saturation"; break; - case V4L2_CID_HUE: name = "Hue"; break; + case V4L2_CID_USER_CLASS: return "User Controls"; + case V4L2_CID_AUDIO_VOLUME: return "Volume"; + case V4L2_CID_AUDIO_MUTE: return "Mute"; + case V4L2_CID_AUDIO_BALANCE: return "Balance"; + case V4L2_CID_AUDIO_BASS: return "Bass"; + case V4L2_CID_AUDIO_TREBLE: return "Treble"; + case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; + case V4L2_CID_BRIGHTNESS: return "Brightness"; + case V4L2_CID_CONTRAST: return "Contrast"; + case V4L2_CID_SATURATION: return "Saturation"; + case V4L2_CID_HUE: return "Hue"; /* MPEG controls */ - case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; - case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding"; break; - case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; - case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: name = "Audio AC-3 Bitrate"; break; - case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; - case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; - case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break; - case V4L2_CID_MPEG_AUDIO_MUTE: name = "Audio Mute"; break; - case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break; - case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break; - case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break; - case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break; - case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break; - case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break; - case V4L2_CID_MPEG_VIDEO_MUTE: name = "Video Mute"; break; - case V4L2_CID_MPEG_VIDEO_MUTE_YUV: name = "Video Mute YUV"; break; - case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break; - case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break; - case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break; - case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break; - case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break; - case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break; - case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break; - case V4L2_CID_MPEG_STREAM_VBI_FMT: name = "Stream VBI Format"; break; + case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency"; + case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding"; + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; + case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis"; + case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC"; + case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; + case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; + case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size"; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; + case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; + case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute"; + case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; + case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; + case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; + case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; + case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID"; + case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID"; + case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID"; + case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; + case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; default: - return -EINVAL; + return NULL; } +} +EXPORT_SYMBOL(v4l2_ctrl_get_name); + +/* Fill in a struct v4l2_queryctrl */ +int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) +{ + const char *name = v4l2_ctrl_get_name(qctrl->id); + + qctrl->flags = 0; + if (name == NULL) + return -EINVAL; + switch (qctrl->id) { case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_LOUDNESS: diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 07d3a9a575d..8b678e0d46e 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -76,6 +76,7 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, const char **menu_items); +const char *v4l2_ctrl_get_name(u32 id); const char **v4l2_ctrl_get_menu(u32 id); int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl); -- GitLab From 1e55126666944c83bf98243564e25302f363e2a4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 08:34:19 -0300 Subject: [PATCH 3963/5416] V4L/DVB (8637): v4l2: add v4l2_ctrl_query_menu_valid_items support function v4l2_ctrl_query_menu_valid_items() makes it easy to handle control menus that have a lot of invalid 'holes'. For example, many MPEG encoders only support a limited subset of audio bitrates. In that case a driver can specify an array listing the set of valid bitrates and pass that to this function. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 23 ++++++++++++++++++++++- include/media/v4l2-common.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index da4791de705..a523af78bdb 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -643,6 +643,7 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc { int i; + qmenu->reserved = 0; if (menu_items == NULL || (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) return -EINVAL; @@ -650,11 +651,31 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc if (menu_items[i] == NULL || menu_items[i][0] == '\0') return -EINVAL; snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); - qmenu->reserved = 0; return 0; } EXPORT_SYMBOL(v4l2_ctrl_query_menu); +/* Fill in a struct v4l2_querymenu based on the specified array of valid + menu items (terminated by V4L2_CTRL_MENU_IDS_END). + Use this if there are 'holes' in the list of valid menu items. */ +int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) +{ + const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); + + qmenu->reserved = 0; + if (menu_items == NULL || ids == NULL) + return -EINVAL; + while (*ids != V4L2_CTRL_MENU_IDS_END) { + if (*ids++ == qmenu->index) { + snprintf(qmenu->name, sizeof(qmenu->name), + menu_items[qmenu->index]); + return 0; + } + } + return -EINVAL; +} +EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); + /* ctrl_classes points to an array of u32 pointers, the last element is a NULL pointer. Each u32 array is a 0-terminated array of control IDs. Each array must be sorted low to high and belong to the same control diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 8b678e0d46e..0c195ccd45d 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -82,6 +82,8 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl); int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, const char **menu_items); +#define V4L2_CTRL_MENU_IDS_END (0xffffffff) +int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids); u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ -- GitLab From e281db5862743dbe1dab7f8fb423e699537036ee Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 12:43:59 -0300 Subject: [PATCH 3964/5416] V4L/DVB (8639): saa6752hs: cleanup and add AC-3 support Cleaned up the saa6752hs i2c driver. Add AC-3 support. Add VIDIOC_CHIP_IDENT support. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 265 +++++++++++------- drivers/media/video/saa7134/saa7134-empress.c | 22 +- drivers/media/video/v4l2-common.c | 6 +- include/media/v4l2-chip-ident.h | 4 + 4 files changed, 194 insertions(+), 103 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 707be175509..ca725a74ce6 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -1,3 +1,27 @@ + /* + saa6752hs - i2c-driver for the saa6752hs by Philips + + Copyright (C) 2004 Andrew de Quincey + + AC-3 support: + + Copyright (C) 2008 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA. + */ + #include #include #include @@ -10,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); MODULE_AUTHOR("Andrew de Quincey"); MODULE_LICENSE("GPL"); -static struct i2c_driver driver; -static struct i2c_client client_template; - enum saa6752hs_videoformat { SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ @@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params { __u16 ts_pid_pcr; /* audio */ - enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; + enum v4l2_mpeg_audio_encoding au_encoding; + enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; + enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate; /* video */ enum v4l2_mpeg_video_aspect vi_aspect; @@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] = }; struct saa6752hs_state { - struct i2c_client client; + int chip; + u32 revision; + int has_ac3; struct saa6752hs_mpeg_params params; enum saa6752hs_videoformat video_format; v4l2_std_id standard; @@ -157,7 +184,9 @@ static struct saa6752hs_mpeg_params param_defaults = .vi_bitrate_peak = 6000, .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, + .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_384K, }; /* ---------------------------------------------------------------------- */ @@ -230,8 +259,9 @@ static int saa6752hs_chip_command(struct i2c_client* client, static int saa6752hs_set_bitrate(struct i2c_client* client, - struct saa6752hs_mpeg_params* params) + struct saa6752hs_state *h) { + struct saa6752hs_mpeg_params *params = &h->params; u8 buf[3]; int tot_bitrate; @@ -263,11 +293,22 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, tot_bitrate = params->vi_bitrate; } + /* set the audio encoding */ + buf[0] = 0x93; + if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) + buf[1] = 1; + else + buf[1] = 0; + i2c_master_send(client, buf, 2); + /* set the audio bitrate */ buf[0] = 0x94; - buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; + if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) + buf[1] = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; + else + buf[1] = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; + tot_bitrate += buf[1] ? 384 : 256; i2c_master_send(client, buf, 2); - tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; /* Note: the total max bitrate is determined by adding the video and audio bitrates together and also adding an extra 768kbit/s to stay on the @@ -332,7 +373,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client, } -static int handle_ctrl(struct saa6752hs_mpeg_params *params, +static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, struct v4l2_ext_control *ctrl, unsigned int cmd) { int old = 0, new; @@ -379,8 +420,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, params->ts_pid_pcr = new; break; case V4L2_CID_MPEG_AUDIO_ENCODING: - old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; - if (set && new != old) + old = params->au_encoding; + if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && + (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) return -ERANGE; new = old; break; @@ -395,6 +437,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; params->au_l2_bitrate = new; break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (!has_ac3) + return -EINVAL; + old = params->au_ac3_bitrate; + if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && + new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) + return -ERANGE; + if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) + new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; + else + new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; + params->au_ac3_bitrate = new; + break; case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; if (set && new != old) @@ -448,17 +503,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, return 0; } -static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, +static int saa6752hs_qctrl(struct saa6752hs_state *h, struct v4l2_queryctrl *qctrl) { + struct saa6752hs_mpeg_params *params = &h->params; int err; switch (qctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return v4l2_ctrl_query_fill(qctrl, @@ -466,6 +523,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, V4L2_MPEG_AUDIO_L2_BITRATE_256K); + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (!h->has_ac3) + return -EINVAL; + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K); + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, @@ -512,38 +577,50 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, return -EINVAL; } -static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params, +static int saa6752hs_qmenu(struct saa6752hs_state *h, struct v4l2_querymenu *qmenu) { - static const char *mpeg_audio_l2_bitrate[] = { - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "256 kbps", - "", - "384 kbps", - NULL + static const u32 mpeg_audio_encoding[] = { + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_CTRL_MENU_IDS_END + }; + static const u32 mpeg_audio_ac3_encoding[] = { + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_MPEG_AUDIO_ENCODING_AC3, + V4L2_CTRL_MENU_IDS_END + }; + static u32 mpeg_audio_l2_bitrate[] = { + V4L2_MPEG_AUDIO_L2_BITRATE_256K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, + V4L2_CTRL_MENU_IDS_END + }; + static u32 mpeg_audio_ac3_bitrate[] = { + V4L2_MPEG_AUDIO_AC3_BITRATE_256K, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K, + V4L2_CTRL_MENU_IDS_END }; struct v4l2_queryctrl qctrl; int err; qctrl.id = qmenu->id; - err = saa6752hs_qctrl(params, &qctrl); + err = saa6752hs_qctrl(h, &qctrl); if (err) return err; - if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE) - return v4l2_ctrl_query_menu(qmenu, &qctrl, + switch (qmenu->id) { + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_l2_bitrate); - return v4l2_ctrl_query_menu(qmenu, &qctrl, - v4l2_ctrl_get_menu(qmenu->id)); + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (!h->has_ac3) + return -EINVAL; + return v4l2_ctrl_query_menu_valid_items(qmenu, + mpeg_audio_ac3_bitrate); + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_menu_valid_items(qmenu, + h->has_ac3 ? mpeg_audio_ac3_encoding : + mpeg_audio_encoding); + } + return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); } static int saa6752hs_init(struct i2c_client* client) @@ -569,7 +646,7 @@ static int saa6752hs_init(struct i2c_client* client) i2c_master_send(client, buf, 2); /* set bitrate */ - saa6752hs_set_bitrate(client, &h->params); + saa6752hs_set_bitrate(client, h); /* Set GOP structure {3, 13} */ buf[0] = 0x72; @@ -688,45 +765,6 @@ static int saa6752hs_init(struct i2c_client* client) return 0; } -static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct saa6752hs_state *h; - - - if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL))) - return -ENOMEM; - h->client = client_template; - h->params = param_defaults; - h->client.adapter = adap; - h->client.addr = addr; - - /* Assume 625 input lines */ - h->standard = 0; - - i2c_set_clientdata(&h->client, h); - i2c_attach_client(&h->client); - - v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); - return 0; -} - -static int saa6752hs_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, saa6752hs_attach); - return 0; -} - -static int saa6752hs_detach(struct i2c_client *client) -{ - struct saa6752hs_state *h; - - h = i2c_get_clientdata(client); - i2c_detach_client(client); - kfree(h); - return 0; -} - static int saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -752,7 +790,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; params = h->params; for (i = 0; i < ctrls->count; i++) { - if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { + err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); + if (err) { ctrls->error_idx = i; return err; } @@ -760,9 +799,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) h->params = params; break; case VIDIOC_QUERYCTRL: - return saa6752hs_qctrl(&h->params, arg); + return saa6752hs_qctrl(h, arg); case VIDIOC_QUERYMENU: - return saa6752hs_qmenu(&h->params, arg); + return saa6752hs_qmenu(h, arg); case VIDIOC_G_FMT: { struct v4l2_format *f = arg; @@ -785,6 +824,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_S_STD: h->standard = *((v4l2_std_id *) arg); break; + + case VIDIOC_G_CHIP_IDENT: + return v4l2_chip_ident_i2c_client(client, + arg, h->chip, h->revision); + default: /* nothing */ break; @@ -793,36 +837,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) return err; } -/* ----------------------------------------------------------------------- */ +static int saa6752hs_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); + u8 addr = 0x13; + u8 data[12]; -static struct i2c_driver driver = { - .driver = { - .name = "saa6752hs", - }, - .id = I2C_DRIVERID_SAA6752HS, - .attach_adapter = saa6752hs_probe, - .detach_client = saa6752hs_detach, - .command = saa6752hs_command, -}; + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + if (h == NULL) + return -ENOMEM; -static struct i2c_client client_template = -{ - .name = "saa6752hs", - .driver = &driver, -}; + i2c_master_send(client, &addr, 1); + i2c_master_recv(client, data, sizeof(data)); + h->chip = V4L2_IDENT_SAA6752HS; + h->revision = (data[8] << 8) | data[9]; + h->has_ac3 = 0; + if (h->revision == 0x0206) { + h->chip = V4L2_IDENT_SAA6752HS_AC3; + h->has_ac3 = 1; + v4l_info(client, "support AC-3\n"); + } + h->params = param_defaults; + h->standard = 0; /* Assume 625 input lines */ -static int __init saa6752hs_init_module(void) -{ - return i2c_add_driver(&driver); + i2c_set_clientdata(client, h); + return 0; } -static void __exit saa6752hs_cleanup_module(void) +static int saa6752hs_remove(struct i2c_client *client) { - i2c_del_driver(&driver); + kfree(i2c_get_clientdata(client)); + return 0; } -module_init(saa6752hs_init_module); -module_exit(saa6752hs_cleanup_module); +static const struct i2c_device_id saa6752hs_id[] = { + { "saa6752hs", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa6752hs_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa6752hs", + .driverid = I2C_DRIVERID_SAA6752HS, + .command = saa6752hs_command, + .probe = saa6752hs_probe, + .remove = saa6752hs_remove, + .id_table = saa6752hs_id, +}; /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 6f423d116fb..f5a186a13db 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -29,6 +29,7 @@ #include #include +#include /* ------------------------------------------------------------------ */ @@ -403,6 +404,25 @@ static int empress_querymenu(struct file *file, void *priv, return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); } +static int empress_g_chip_ident(struct file *file, void *fh, + struct v4l2_chip_ident *chip) +{ + struct saa7134_dev *dev = file->private_data; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (dev->mpeg_i2c_client == NULL) + return -EINVAL; + if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER && + chip->match_chip == I2C_DRIVERID_SAA6752HS) + return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); + if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR && + chip->match_chip == dev->mpeg_i2c_client->addr) + return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); + return -EINVAL; +} + + static const struct file_operations ts_fops = { .owner = THIS_MODULE, @@ -431,11 +451,11 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_enum_input = empress_enum_input, .vidioc_g_input = empress_g_input, .vidioc_s_input = empress_s_input, - .vidioc_queryctrl = empress_queryctrl, .vidioc_querymenu = empress_querymenu, .vidioc_g_ctrl = empress_g_ctrl, .vidioc_s_ctrl = empress_s_ctrl, + .vidioc_g_chip_ident = empress_g_chip_ident, }; /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index a523af78bdb..0c511839f7e 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -637,13 +637,17 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and - the menu. The qctrl pointer may be NULL, in which case it is ignored. */ + the menu. The qctrl pointer may be NULL, in which case it is ignored. + If menu_items is NULL, then the menu items are retrieved using + v4l2_ctrl_get_menu. */ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, const char **menu_items) { int i; qmenu->reserved = 0; + if (menu_items == NULL) + menu_items = v4l2_ctrl_get_menu(qmenu->id); if (menu_items == NULL || (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) return -EINVAL; diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 41b509babf3..be782d5fcfa 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -72,6 +72,10 @@ enum { /* module cs5345: just ident 5345 */ V4L2_IDENT_CS5345 = 5345, + /* module saa6752hs: reserved range 6750-6759 */ + V4L2_IDENT_SAA6752HS = 6752, + V4L2_IDENT_SAA6752HS_AC3 = 6753, + /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, -- GitLab From 3eea543b7282bea38970f20840acff9e230d0c2a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 13:27:16 -0300 Subject: [PATCH 3965/5416] V4L/DVB (8640): saa6752hs: add PMT table for AC3 The PMT table for AC3 audio is different. Thanks to Dmitry Belimov for providing the table data. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 63 ++++++++++++++++++++----- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index ca725a74ce6..28499e59192 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -172,6 +172,39 @@ static u8 PMT[] = { 0x00, 0x00, 0x00, 0x00 /* CRC32 */ }; +static u8 PMT_AC3[] = { + 0xc2, /* i2c register */ + 0x01, /* table number for encoder(1) */ + 0x47, /* sync */ + + 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */ + 0x10, /* PMT PID (0x0010) */ + 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ + + 0x00, /* PSI pointer to start of table */ + + 0x02, /* TID (2) */ + 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */ + + 0x00, 0x01, /* program_number(1) */ + + 0xc1, /* version_number(0), current_next_indicator(1) */ + + 0x00, 0x00, /* section_number(0), last_section_number(0) */ + + 0xe1, 0x04, /* PCR_PID (0x0104) */ + + 0xf0, 0x00, /* program_info_length(0) */ + + 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ + 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */ + 0x6a, /* AC3 */ + 0x01, /* Descriptor_length(1) */ + 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */ + + 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */ +}; + static struct saa6752hs_mpeg_params param_defaults = { .ts_pid_pmt = 16, @@ -186,7 +219,7 @@ static struct saa6752hs_mpeg_params param_defaults = .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, - .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_384K, + .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K, }; /* ---------------------------------------------------------------------- */ @@ -295,10 +328,7 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, /* set the audio encoding */ buf[0] = 0x93; - if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) - buf[1] = 1; - else - buf[1] = 0; + buf[1] = (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); i2c_master_send(client, buf, 2); /* set the audio bitrate */ @@ -627,6 +657,7 @@ static int saa6752hs_init(struct i2c_client* client) { unsigned char buf[9], buf2[4]; struct saa6752hs_state *h; + unsigned size; u32 crc; unsigned char localPAT[256]; unsigned char localPMT[256]; @@ -685,7 +716,13 @@ static int saa6752hs_init(struct i2c_client* client) localPAT[sizeof(PAT) - 1] = crc & 0xFF; /* compute PMT */ - memcpy(localPMT, PMT, sizeof(PMT)); + if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { + size = sizeof(PMT_AC3); + memcpy(localPMT, PMT_AC3, size); + } else { + size = sizeof(PMT); + memcpy(localPMT, PMT, size); + } localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); localPMT[4] = h->params.ts_pid_pmt & 0xff; localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); @@ -694,11 +731,11 @@ static int saa6752hs_init(struct i2c_client* client) localPMT[21] = h->params.ts_pid_video & 0xFF; localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); localPMT[26] = h->params.ts_pid_audio & 0xFF; - crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4); - localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF; - localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF; - localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; - localPMT[sizeof(PMT) - 1] = crc & 0xFF; + crc = crc32_be(~0, &localPMT[7], size - 7 - 4); + localPMT[size - 4] = (crc >> 24) & 0xFF; + localPMT[size - 3] = (crc >> 16) & 0xFF; + localPMT[size - 2] = (crc >> 8) & 0xFF; + localPMT[size - 1] = crc & 0xFF; /* Set Audio PID */ buf[0] = 0xC1; @@ -719,8 +756,8 @@ static int saa6752hs_init(struct i2c_client* client) i2c_master_send(client,buf,3); /* Send SI tables */ - i2c_master_send(client,localPAT,sizeof(PAT)); - i2c_master_send(client,localPMT,sizeof(PMT)); + i2c_master_send(client, localPAT, sizeof(PAT)); + i2c_master_send(client, localPMT, size); /* mute then unmute audio. This removes buzzing artefacts */ buf[0] = 0xa4; -- GitLab From ad4eada70b2a145aabb1814fdc080480f796decb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Aug 2008 15:47:07 -0300 Subject: [PATCH 3966/5416] V4L/DVB (8641): arv: fix compilation errors/warnings - add PCI dependency for btcx - fix compile errors (doesn't like ';' at the end of a #if 0) Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 1f6c9ee3afd..367666db5bf 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -34,6 +34,7 @@ config VIDEOBUF_DVB select VIDEOBUF_GEN config VIDEO_BTCX + depends on PCI tristate config VIDEO_IR -- GitLab From 0fbbff33fcab605b1a5c53a20c302aad24b082ef Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 4 Aug 2008 21:36:49 -0300 Subject: [PATCH 3967/5416] V4L/DVB (8642): cx23885: Factor out common cx23885 tuner callback Tuners currently hook different things to the private pointer in their callback function. Longer term we should make that private pointer consistent, but for now separate out the guts of the cx23885 tuner callback so we can reuse it. Signed-off-by: Steven Toth Signed-off-by: Anton Blanchard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 20 ++++++++++++-------- drivers/media/video/cx23885/cx23885-dvb.c | 4 ++-- drivers/media/video/cx23885/cx23885.h | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c36d3f63210..e5e688e5e4b 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -319,13 +319,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) dev->name, tv.model); } -/* Tuner callback function for cx23885 boards. Currently only needed - * for HVR1500Q, which has an xc5000 tuner. - */ -int cx23885_tuner_callback(void *priv, int command, int arg) +static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, + int command, int arg) { - struct cx23885_i2c *bus = priv; - struct cx23885_dev *dev = bus->dev; u32 bitmask = 0; if (command != 0) { @@ -345,9 +341,9 @@ int cx23885_tuner_callback(void *priv, int command, int arg) /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ - if (bus->nr == 0) + if (port == 0) bitmask = 0x01; - else if (bus->nr == 1) + else if (port == 1) bitmask = 0x04; } break; @@ -363,6 +359,14 @@ int cx23885_tuner_callback(void *priv, int command, int arg) return 0; } +int cx23885_xc5000_tuner_callback(void *priv, int command, int arg) +{ + struct cx23885_i2c *bus = priv; + struct cx23885_dev *dev = bus->dev; + + return cx23885_tuner_callback(dev, bus->nr, command, arg); +} + void cx23885_gpio_setup(struct cx23885_dev *dev) { switch(dev->board) { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 291b9d008da..bfe49df3f6d 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -188,13 +188,13 @@ static struct s5h1411_config dvico_s5h1411_config = { static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback + .tuner_callback = cx23885_xc5000_tuner_callback, }; static struct xc5000_config dvico_xc5000_tunerconfig = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback + .tuner_callback = cx23885_xc5000_tuner_callback, }; static struct tda829x_config tda829x_no_probe = { diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index e23d97c071e..c3478b24012 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -409,7 +409,7 @@ extern const unsigned int cx23885_bcount; extern struct cx23885_subid cx23885_subids[]; extern const unsigned int cx23885_idcount; -extern int cx23885_tuner_callback(void *priv, int command, int arg); +extern int cx23885_xc5000_tuner_callback(void *priv, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); -- GitLab From 90a71b1c1ab003dd4524afca44c2ad2519f4420c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 4 Aug 2008 21:38:46 -0300 Subject: [PATCH 3968/5416] V4L/DVB (8643): Switch Hauppauge HVR1400 and HVR1500 to common cx23885 tuner callback The Hauppauge HVR1400 and HVR1500 can now use the common cx23885 tuner callback. Signed-off-by: Steven Toth Signed-off-by: Anton Blanchard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 16 +++++++++- drivers/media/video/cx23885/cx23885-dvb.c | 34 ++------------------- drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index e5e688e5e4b..93ad7f8ce20 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -26,6 +26,7 @@ #include #include "cx23885.h" +#include "tuner-xc2028.h" /* ------------------------------------------------------------------ */ /* board config info */ @@ -331,8 +332,10 @@ static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, } switch(dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1400: + case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: - /* Tuner Reset Command from xc5000 */ + /* Tuner Reset Command */ if (command == 0) bitmask = 0x04; break; @@ -367,6 +370,17 @@ int cx23885_xc5000_tuner_callback(void *priv, int command, int arg) return cx23885_tuner_callback(dev, bus->nr, command, arg); } +int cx23885_xc3028_tuner_callback(void *priv, int command, int arg) +{ + struct cx23885_tsport *port = priv; + struct cx23885_dev *dev = port->dev; + + if (command == XC2028_RESET_CLK) + return 0; + + return cx23885_tuner_callback(dev, port->nr, command, arg); +} + void cx23885_gpio_setup(struct cx23885_dev *dev) { switch(dev->board) { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index bfe49df3f6d..45670051e7d 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -303,36 +303,6 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = { .output_mode = OUTMODE_MPEG2_SERIAL, }; -static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) -{ - struct cx23885_tsport *port = ptr; - struct cx23885_dev *dev = port->dev; - - switch (command) { - case XC2028_TUNER_RESET: - /* Send the tuner in then out of reset */ - /* GPIO-2 xc3028 tuner */ - dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); - - cx_set(GP0_IO, 0x00040000); - cx_clear(GP0_IO, 0x00000004); - msleep(5); - - cx_set(GP0_IO, 0x00040004); - msleep(5); - break; - case XC2028_RESET_CLK: - dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); - break; - default: - dprintk(1, "%s: unknown command %d, arg %d\n", __func__, - command, arg); - return -EINVAL; - } - - return 0; -} - static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -426,7 +396,7 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .callback = cx23885_hvr1500_xc3028_callback, + .callback = cx23885_xc3028_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", @@ -465,7 +435,7 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, - .callback = cx23885_hvr1500_xc3028_callback, + .callback = cx23885_xc3028_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028L-v36.fw", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index c3478b24012..64827fb669a 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -410,6 +410,7 @@ extern struct cx23885_subid cx23885_subids[]; extern const unsigned int cx23885_idcount; extern int cx23885_xc5000_tuner_callback(void *priv, int command, int arg); +extern int cx23885_xc3028_tuner_callback(void *priv, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); -- GitLab From aef2d186e381816733fa15d67ad63bd99254cb9e Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 4 Aug 2008 21:39:53 -0300 Subject: [PATCH 3969/5416] V4L/DVB (8644): Add support for DViCO FusionHDTV DVB-T Dual Express Add support for the DViCO FusionHDTV DVB-T Dual Express card, based on work by Chris Pascoe and Stephen Backway. Signed-off-by: Steven Toth Signed-off-by: Anton Blanchard Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 24 +++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 34 +++++++++++++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 60 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index f0e613ba55b..bccafd35785 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -9,3 +9,4 @@ 8 -> Hauppauge WinTV-HVR1700 [0070:8101] 9 -> Hauppauge WinTV-HVR1400 [0070:8010] 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618] + 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 93ad7f8ce20..7caa2465e7f 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -149,6 +149,11 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = { + .name = "DViCO FusionHDTV DVB-T Dual Express", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -220,6 +225,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x18ac, .subdevice = 0xd618, .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb78, + .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -340,6 +349,7 @@ static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, bitmask = 0x04; break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: + case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: if (command == 0) { /* Two identical tuners on two different i2c buses, @@ -476,6 +486,19 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-2 xc5000 tuner reset i2c bus 1 */ /* GPIO-3 s5h1409 demod reset i2c bus 0 */ + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x000f0000); + mdelay(20); + cx_clear(GP0_IO, 0x0000000f); + mdelay(20); + cx_set(GP0_IO, 0x000f000f); + break; + case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: + /* GPIO-0 portb xc3028 reset */ + /* GPIO-1 portb zl10353 reset */ + /* GPIO-2 portc xc3028 reset */ + /* GPIO-3 portc zl10353 reset */ + /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); mdelay(20); @@ -534,6 +557,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: + case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 45670051e7d..dbbbf5b0d2e 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -42,6 +42,7 @@ #include "tuner-simple.h" #include "dib7000p.h" #include "dibx000_common.h" +#include "zl10353.h" static unsigned int debug; @@ -303,6 +304,12 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = { .output_mode = OUTMODE_MPEG2_SERIAL, }; +static struct zl10353_config dvico_fusionhdtv_xc3028 = { + .demod_address = 0x0f, + .if2 = 45600, + .no_tuner = 1, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -465,6 +472,33 @@ static int dvb_register(struct cx23885_tsport *port) &i2c_bus->i2c_adap, &dvico_xc5000_tunerconfig, i2c_bus); break; + case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { + i2c_bus = &dev->i2c_bus[port->nr - 1]; + + port->dvb.frontend = dvb_attach(zl10353_attach, + &dvico_fusionhdtv_xc3028, + &i2c_bus->i2c_adap); + if (port->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &i2c_bus->i2c_adap, + .i2c_addr = 0x61, + .video_dev = port, + .callback = cx23885_xc3028_tuner_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028-v27.fw", + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + }; + + fe = dvb_attach(xc2028_attach, port->dvb.frontend, + &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; + } default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 64827fb669a..08b4c1390e1 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -64,6 +64,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 +#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- GitLab From 12886871ae7a6f4e2b1ea371f6604d8239dda724 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 4 Aug 2008 21:41:06 -0300 Subject: [PATCH 3970/5416] V4L/DVB (8645): Support IR remote on FusionHDTV DVB-T Dual Express From Chris Pascoe Support IR remote on FusionHDTV DVB-T Dual Express Signed-off-by: Steven Toth Signed-off-by: Anton Blanchard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 7caa2465e7f..46d70262107 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -520,6 +520,9 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1400: /* FIXME: Implement me */ break; + case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: + request_module("ir-kbd-i2c"); + break; } return 0; -- GitLab From 89ce2216e338f62c411bea12df37a2f54f2ce13a Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 4 Aug 2008 22:18:19 -0300 Subject: [PATCH 3971/5416] V4L/DVB (8646): cx23885: Convert framework to use a single tuner callback function. Code reduction. Tuner callback now assumes that tsport is passed as the void arg. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 31 ++++++--------------- drivers/media/video/cx23885/cx23885-dvb.c | 16 ++++++----- drivers/media/video/cx23885/cx23885.h | 3 +- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 46d70262107..0daffc3dbec 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -329,11 +329,15 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) dev->name, tv.model); } -static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, - int command, int arg) +int cx23885_tuner_callback(void *priv, int command, int arg) { + struct cx23885_tsport *port = priv; + struct cx23885_dev *dev = port->dev; u32 bitmask = 0; + if (command == XC2028_RESET_CLK) + return 0; + if (command != 0) { printk(KERN_ERR "%s(): Unknown command 0x%x.\n", __func__, command); @@ -354,9 +358,9 @@ static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ - if (port == 0) + if (port->nr == 0) bitmask = 0x01; - else if (port == 1) + else if (port->nr == 1) bitmask = 0x04; } break; @@ -372,25 +376,6 @@ static int cx23885_tuner_callback(struct cx23885_dev *dev, int port, return 0; } -int cx23885_xc5000_tuner_callback(void *priv, int command, int arg) -{ - struct cx23885_i2c *bus = priv; - struct cx23885_dev *dev = bus->dev; - - return cx23885_tuner_callback(dev, bus->nr, command, arg); -} - -int cx23885_xc3028_tuner_callback(void *priv, int command, int arg) -{ - struct cx23885_tsport *port = priv; - struct cx23885_dev *dev = port->dev; - - if (command == XC2028_RESET_CLK) - return 0; - - return cx23885_tuner_callback(dev, port->nr, command, arg); -} - void cx23885_gpio_setup(struct cx23885_dev *dev) { switch(dev->board) { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index dbbbf5b0d2e..f8564bb0d42 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -189,13 +189,13 @@ static struct s5h1411_config dvico_s5h1411_config = { static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, - .tuner_callback = cx23885_xc5000_tuner_callback, + .tuner_callback = cx23885_tuner_callback, }; static struct xc5000_config dvico_xc5000_tunerconfig = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx23885_xc5000_tuner_callback, + .tuner_callback = cx23885_tuner_callback, }; static struct tda829x_config tda829x_no_probe = { @@ -391,7 +391,7 @@ static int dvb_register(struct cx23885_tsport *port) if (port->dvb.frontend != NULL) dvb_attach(xc5000_attach, port->dvb.frontend, &i2c_bus->i2c_adap, - &hauppauge_hvr1500q_tunerconfig, i2c_bus); + &hauppauge_hvr1500q_tunerconfig, port); break; case CX23885_BOARD_HAUPPAUGE_HVR1500: i2c_bus = &dev->i2c_bus[1]; @@ -403,7 +403,8 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .callback = cx23885_xc3028_tuner_callback, + .video_dev = port, + .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", @@ -442,7 +443,8 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, - .callback = cx23885_xc3028_tuner_callback, + .video_dev = port, + .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028L-v36.fw", @@ -470,7 +472,7 @@ static int dvb_register(struct cx23885_tsport *port) if (port->dvb.frontend != NULL) dvb_attach(xc5000_attach, port->dvb.frontend, &i2c_bus->i2c_adap, - &dvico_xc5000_tunerconfig, i2c_bus); + &dvico_xc5000_tunerconfig, port); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { i2c_bus = &dev->i2c_bus[port->nr - 1]; @@ -484,7 +486,7 @@ static int dvb_register(struct cx23885_tsport *port) .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, .video_dev = port, - .callback = cx23885_xc3028_tuner_callback, + .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 08b4c1390e1..db52d814a97 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -410,8 +410,7 @@ extern const unsigned int cx23885_bcount; extern struct cx23885_subid cx23885_subids[]; extern const unsigned int cx23885_idcount; -extern int cx23885_xc5000_tuner_callback(void *priv, int command, int arg); -extern int cx23885_xc3028_tuner_callback(void *priv, int command, int arg); +extern int cx23885_tuner_callback(void *priv, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); -- GitLab From f723af16da8359cda47320001960609b0086082b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 9 Aug 2008 10:35:29 -0300 Subject: [PATCH 3972/5416] V4L/DVB (8649): v4l2: add AAC bitrate control If you can select AAC as audio encoder, then you should also be able to set the bitrate. Add this missing control. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 3 +++ include/linux/videodev2.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 0c511839f7e..20c3be8617e 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -386,6 +386,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; + case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; @@ -548,6 +549,8 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) V4L2_MPEG_AUDIO_L3_BITRATE_32K, V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, V4L2_MPEG_AUDIO_L3_BITRATE_192K); + case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000); case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_AC3_BITRATE_32K, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 9054764f4cd..d4b03034ee7 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -990,7 +990,8 @@ enum v4l2_mpeg_audio_crc { V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) -#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+110) +#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) +#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) enum v4l2_mpeg_audio_ac3_bitrate { V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, -- GitLab From 8d79898897f8afee182febef18b96f559d32ebc4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 9 Aug 2008 12:23:15 -0300 Subject: [PATCH 3973/5416] V4L/DVB (8654): cxusb: add support for DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2) Add support for revision 2 of the DViCO FusionHDTV DVB-T Dual Digital 4 which has new tuners and demodulators (2 x DIB7070p). With this patch both DVB reception and IR works. The dib7000p driver currently hardwires the output mode to OUTMODE_MPEG2_SERIAL regardless of what we ask for. Modify it to allow OUTMODE_MPEG2_PAR_GATED_CLK to be set. Longer term we should remove the check completely and set the output mode correctly in all the callers. Add Kconfig bits to ensure the dib7000p and dib0070 modules are enabled. It would be nice to only do this for the !DVB_FE_CUSTOMISE case, but this is what the other DIB7070 module does (there are a number of module dependencies in the attach code). Signed-off-by: Anton Blanchard Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 2 + drivers/media/dvb/dvb-usb/cxusb.c | 206 ++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/frontends/dib7000p.c | 3 +- 4 files changed, 211 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index e84152b7576..df9932368bb 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -108,6 +108,8 @@ config DVB_USB_CXUSB select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + select DVB_DIB7000P + select DVB_TUNER_DIB0070 help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 563400277a4..1de3678a294 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -36,6 +36,8 @@ #include "tuner-xc2028.h" #include "tuner-simple.h" #include "mxl5005s.h" +#include "dib7000p.h" +#include "dib0070.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -726,6 +728,157 @@ no_IR: return 0; } +static struct dibx000_agc_config dib7070_agc_config = { + .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, + + /* + * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, + * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 + */ + .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | + (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), + .inv_gain = 600, + .time_stabiliz = 10, + .alpha_level = 0, + .thlock = 118, + .wbd_inv = 0, + .wbd_ref = 3530, + .wbd_sel = 1, + .wbd_alpha = 5, + .agc1_max = 65535, + .agc1_min = 0, + .agc2_max = 65535, + .agc2_min = 0, + .agc1_pt1 = 0, + .agc1_pt2 = 40, + .agc1_pt3 = 183, + .agc1_slope1 = 206, + .agc1_slope2 = 255, + .agc2_pt1 = 72, + .agc2_pt2 = 152, + .agc2_slope1 = 88, + .agc2_slope2 = 90, + .alpha_mant = 17, + .alpha_exp = 27, + .beta_mant = 23, + .beta_exp = 51, + .perform_agc_softsplit = 0, +}; + +static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { + .internal = 60000, + .sampling = 15000, + .pll_prediv = 1, + .pll_ratio = 20, + .pll_range = 3, + .pll_reset = 1, + .pll_bypass = 0, + .enable_refdiv = 0, + .bypclk_div = 0, + .IO_CLK_en_core = 1, + .ADClkSrc = 1, + .modulo = 2, + /* refsel, sel, freq_15k */ + .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0), + .ifreq = (0 << 25) | 0, + .timf = 20452225, + .xtal_hz = 12000000, +}; + +static struct dib7000p_config cxusb_dualdig4_rev2_config = { + .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, + .output_mpeg2_in_188_bytes = 1, + + .agc_config_count = 1, + .agc = &dib7070_agc_config, + .bw = &dib7070_bw_config_12_mhz, + .tuner_is_baseband = 1, + .spur_protect = 1, + + .gpio_dir = 0xfcef, + .gpio_val = 0x0110, + + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .hostbus_diversity = 1, +}; + +static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) +{ + if (usb_set_interface(adap->dev->udev, 0, 1) < 0) + err("set interface failed"); + + cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); + + cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); + + dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &cxusb_dualdig4_rev2_config); + + if ((adap->fe = dvb_attach(dib7000p_attach, + &adap->dev->i2c_adap, 0x80, + &cxusb_dualdig4_rev2_config)) == NULL) + return -EIO; + + return 0; +} + +static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) +{ + return dib7000p_set_gpio(fe, 8, 0, !onoff); +} + +static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) +{ + return 0; +} + +static struct dib0070_config dib7070p_dib0070_config = { + .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, + .reset = dib7070_tuner_reset, + .sleep = dib7070_tuner_sleep, + .clock_khz = 12000, +}; + +struct dib0700_adapter_state { + int (*set_param_save) (struct dvb_frontend *, + struct dvb_frontend_parameters *); +}; + +static int dib7070_set_param_override(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dib0700_adapter_state *state = adap->priv; + + u16 offset; + u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); + switch (band) { + case BAND_VHF: offset = 950; break; + case BAND_UHF: + default: offset = 550; break; + } + + dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); + + return state->set_param_save(fe, fep); +} + +static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *st = adap->priv; + struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + + if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, + &dib7070p_dib0070_config) == NULL) + return -ENODEV; + + st->set_param_save = adap->fe->ops.tuner_ops.set_params; + adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; + return 0; +} + static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) { if (usb_set_interface(adap->dev->udev, 0, 1) < 0) @@ -826,6 +979,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; +static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; static struct dvb_usb_device_properties cxusb_aver_a868r_properties; @@ -852,6 +1006,9 @@ static int cxusb_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, + &cxusb_bluebird_dualdig4_rev2_properties, + THIS_MODULE, NULL, adapter_nr) || 0) return 0; @@ -876,6 +1033,7 @@ static struct usb_device_id cxusb_table [] = { { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -1321,6 +1479,54 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { } }; +static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + + .size_of_priv = sizeof(struct cxusb_state), + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, + .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, + .size_of_priv = sizeof(struct dib0700_adapter_state), + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + }, + }, + + .power_ctrl = cxusb_bluebird_power_ctrl, + + .i2c_algo = &cxusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .rc_interval = 100, + .rc_key_map = dvico_mce_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), + .rc_query = cxusb_rc_query, + + .num_device_descs = 1, + .devices = { + { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)", + { NULL }, + { &cxusb_table[17], NULL }, + }, + } +}; + static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 03dfb9f2fe3..f327a154b6c 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -171,6 +171,7 @@ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 +#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98 #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 1a0142e0d74..8217e5b38f4 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -1333,7 +1333,8 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, /* Ensure the output mode remains at the previous default if it's * not specifically set by the caller. */ - if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) + if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && + (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) st->cfg.output_mode = OUTMODE_MPEG2_FIFO; demod = &st->demod; -- GitLab From a2dc86b69dcbcbeb498c5f5169f09f4bd207de5f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 9 Aug 2008 13:06:26 -0300 Subject: [PATCH 3974/5416] V4L/DVB (8655): cxusb: fix checkpatch warnings & errors Fix the following checkpatch.pl errors and warnings: ERROR: do not use assignment in if condition 117: FILE: linux/drivers/media/dvb/dvb-usb/cxusb.c:819: + if ((adap->fe = dvb_attach(dib7000p_attach, ERROR: switch and case should be at the same indent 155: FILE: linux/drivers/media/dvb/dvb-usb/cxusb.c:857: + switch (band) { + case BAND_VHF: offset = 950; break; + case BAND_UHF: + default: offset = 550; break; WARNING: line over 80 characters 169: FILE: linux/drivers/media/dvb/dvb-usb/cxusb.c:871: + struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); WARNING: line over 80 characters 213: FILE: linux/drivers/media/dvb/dvb-usb/cxusb.c:1342: +static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { WARNING: line over 80 characters 226: FILE: linux/drivers/media/dvb/dvb-usb/cxusb.c:1355: + .size_of_priv = sizeof(struct dib0700_adapter_state), total: 2 errors, 3 warnings, 266 lines checked Signed-off-by: Michael Krufky Cc: Anton Blanchard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 1de3678a294..338c819ca73 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -816,9 +816,9 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &cxusb_dualdig4_rev2_config); - if ((adap->fe = dvb_attach(dib7000p_attach, - &adap->dev->i2c_adap, 0x80, - &cxusb_dualdig4_rev2_config)) == NULL) + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &cxusb_dualdig4_rev2_config); + if (adap->fe == NULL) return -EIO; return 0; @@ -855,9 +855,9 @@ static int dib7070_set_param_override(struct dvb_frontend *fe, u16 offset; u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); switch (band) { - case BAND_VHF: offset = 950; break; - case BAND_UHF: - default: offset = 550; break; + case BAND_VHF: offset = 950; break; + default: + case BAND_UHF: offset = 550; break; } dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); @@ -868,7 +868,9 @@ static int dib7070_set_param_override(struct dvb_frontend *fe, static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; - struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + struct i2c_adapter *tun_i2c = + dib7000p_get_i2c_master(adap->fe, + DIBX000_I2C_INTERFACE_TUNER, 1); if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config) == NULL) @@ -1479,7 +1481,8 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { } }; -static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { +static +struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, @@ -1489,10 +1492,10 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, - .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, - .size_of_priv = sizeof(struct dib0700_adapter_state), + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, + .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, + .size_of_priv = sizeof(struct dib0700_adapter_state), /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, -- GitLab From 2e06d2ff548fc6333f5b34d188646ded327187c3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 9 Aug 2008 14:21:58 -0300 Subject: [PATCH 3975/5416] V4L/DVB (8656): fix DVB_FE_CUSTOMISE for DVB_DIB7000P and DVB_TUNER_DIB0070 with dvb-usb-cxusb Allow dvb-usb-cxusb to be built without dib7000p or dib0070 selected Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 4 +-- drivers/media/dvb/frontends/dib0070.h | 8 ++++- drivers/media/dvb/frontends/dib7000p.h | 41 ++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index df9932368bb..8a54cb48322 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -108,8 +108,8 @@ config DVB_USB_CXUSB select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE - select DVB_DIB7000P - select DVB_TUNER_DIB0070 + select DVB_DIB7000P if !DVB_FE_CUSTOMISE + select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index 3eedfdf505b..21f2c5161af 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h @@ -41,6 +41,7 @@ struct dib0070_config { extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); +extern u16 dib0070_wbd_offset(struct dvb_frontend *); #else static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, @@ -49,9 +50,14 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } + +static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); -extern u16 dib0070_wbd_offset(struct dvb_frontend *); #endif diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 07c4d12ed5b..3e812685712 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -41,6 +41,14 @@ struct dib7000p_config { extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); +extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, + enum dibx000_i2c_interface, + int); +extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, + int no_of_demods, u8 default_addr, + struct dib7000p_config cfg[]); +extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); +extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); #else static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, @@ -49,13 +57,36 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -#endif -extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]); +static inline +struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, + enum dibx000_i2c_interface i, int x) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, + int no_of_demods, u8 default_addr, + struct dib7000p_config cfg[]) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} +#endif -extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); -extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); -extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); #endif -- GitLab From dfbdce04905d3196c828ca36f01ef06e6fdb2428 Mon Sep 17 00:00:00 2001 From: Timothy Lee Date: Sat, 9 Aug 2008 13:36:51 -0300 Subject: [PATCH 3976/5416] V4L/DVB (8657): cxusb: add lgs8gl5 and support for Magic-Pro DMB-TH usb stick Add support for Magic-Pro DMB-TH usb stick. DMB-TH is the HDTV broadcast standard used in Hong Kong and China. [...] I've also attached a second patch against the dvb-apps repository which adds a DMB-TH scan file for Hong Kong. Since the ProHDTV stick contains a DMB-TH decoder (lgs8gl5) onboard, it outputs MPEG-TS to the PC. Signed-off-by: Timothy Lee Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 286 ++++++++++++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 + drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/lgs8gl5.c | 480 ++++++++++++++++++++++++ drivers/media/dvb/frontends/lgs8gl5.h | 45 +++ 6 files changed, 821 insertions(+) create mode 100644 drivers/media/dvb/frontends/lgs8gl5.c create mode 100644 drivers/media/dvb/frontends/lgs8gl5.h diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 338c819ca73..bffb4438038 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -38,6 +38,7 @@ #include "mxl5005s.h" #include "dib7000p.h" #include "dib0070.h" +#include "lgs8gl5.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -111,6 +112,25 @@ static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff) cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); } +static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, + u8 addr, int onoff) +{ + u8 o[2] = {addr, onoff}; + u8 i; + int rc; + + rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); + + if (rc < 0) + return rc; + if (i == 0x01) + return 0; + else { + deb_info("gpio_write failed.\n"); + return -EIO; + } +} + /* I2C */ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) @@ -264,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) return rc; } +static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret; + u8 b; + ret = cxusb_power_ctrl(d, onoff); + if (!onoff) + return ret; + + msleep(128); + cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1); + msleep(100); + return ret; +} + static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { u8 buf[2] = { 0x03, 0x00 }; @@ -285,6 +319,67 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return 0; } +static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) +{ + int ep = d->props.generic_bulk_ctrl_endpoint; + const int timeout = 100; + const int junk_len = 32; + u8 *junk; + int rd_count; + + /* Discard remaining data in video pipe */ + junk = kmalloc(junk_len, GFP_KERNEL); + if (!junk) + return; + while (1) { + if (usb_bulk_msg(d->udev, + usb_rcvbulkpipe(d->udev, ep), + junk, junk_len, &rd_count, timeout) < 0) + break; + if (!rd_count) + break; + } + kfree(junk); +} + +static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d) +{ + struct usb_data_stream_properties *p = &d->props.adapter[0].stream; + const int timeout = 100; + const int junk_len = p->u.bulk.buffersize; + u8 *junk; + int rd_count; + + /* Discard remaining data in video pipe */ + junk = kmalloc(junk_len, GFP_KERNEL); + if (!junk) + return; + while (1) { + if (usb_bulk_msg(d->udev, + usb_rcvbulkpipe(d->udev, p->endpoint), + junk, junk_len, &rd_count, timeout) < 0) + break; + if (!rd_count) + break; + } + kfree(junk); +} + +static int cxusb_d680_dmb_streaming_ctrl( + struct dvb_usb_adapter *adap, int onoff) +{ + if (onoff) { + u8 buf[2] = { 0x03, 0x00 }; + cxusb_d680_dmb_drain_video(adap->dev); + return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, + buf, sizeof(buf), NULL, 0); + } else { + int ret = cxusb_ctrl_msg(adap->dev, + CMD_STREAMING_OFF, NULL, 0, NULL, 0); + return ret; + } +} + static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { struct dvb_usb_rc_key *keymap = d->props.rc_key_map; @@ -337,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, return 0; } +static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, + int *state) +{ + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + u8 ircode[2]; + int i; + + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + + if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) + return 0; + + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (keymap[i].custom == ircode[0] && + keymap[i].data == ircode[1]) { + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + + return 0; + } + } + + return 0; +} + static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { { 0xfe, 0x02, KEY_TV }, { 0xfe, 0x0e, KEY_MP3 }, @@ -424,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ }; +static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { + { 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */ + { 0x08, 0x0c, KEY_ZOOM }, + { 0x08, 0x00, KEY_0 }, + { 0x00, 0x01, KEY_1 }, + { 0x08, 0x02, KEY_2 }, + { 0x00, 0x03, KEY_3 }, + { 0x08, 0x04, KEY_4 }, + { 0x00, 0x05, KEY_5 }, + { 0x08, 0x06, KEY_6 }, + { 0x00, 0x07, KEY_7 }, + { 0x08, 0x08, KEY_8 }, + { 0x00, 0x09, KEY_9 }, + { 0x00, 0x0a, KEY_MUTE }, + { 0x08, 0x29, KEY_BACK }, + { 0x00, 0x12, KEY_CHANNELUP }, + { 0x08, 0x13, KEY_CHANNELDOWN }, + { 0x00, 0x2b, KEY_VOLUMEUP }, + { 0x08, 0x2c, KEY_VOLUMEDOWN }, + { 0x00, 0x20, KEY_UP }, + { 0x08, 0x21, KEY_DOWN }, + { 0x00, 0x11, KEY_LEFT }, + { 0x08, 0x10, KEY_RIGHT }, + { 0x00, 0x0d, KEY_OK }, + { 0x08, 0x1f, KEY_RECORD }, + { 0x00, 0x17, KEY_PLAYPAUSE }, + { 0x08, 0x16, KEY_PLAYPAUSE }, + { 0x00, 0x0b, KEY_STOP }, + { 0x08, 0x27, KEY_FASTFORWARD }, + { 0x00, 0x26, KEY_REWIND }, + { 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */ + { 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */ + { 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */ + { 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */ + { 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */ + { 0x00, 0x25, KEY_POWER }, +}; + static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; @@ -529,6 +688,24 @@ static struct mxl5005s_config aver_a868r_tuner = { .AgcMasterByte = 0x00, }; +/* FIXME: needs tweaking */ +static struct mxl5005s_config d680_dmb_tuner = { + .i2c_address = 0x63, + .if_freq = 36125000UL, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_C, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + /* Callbacks for DVB USB */ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) { @@ -617,6 +794,14 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_frontend *fe; + fe = dvb_attach(mxl5005s_attach, adap->fe, + &adap->dev->i2c_adap, &d680_dmb_tuner); + return (fe == NULL) ? -EIO : 0; +} + static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) { u8 b; @@ -906,6 +1091,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) return -EIO; } +static struct lgs8gl5_config lgs8gl5_cfg = { + .demod_address = 0x19, +}; + +static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap->dev; + int n; + + /* Select required USB configuration */ + if (usb_set_interface(d->udev, 0, 0) < 0) + err("set interface failed"); + + /* Unblock all USB pipes */ + usb_clear_halt(d->udev, + usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); + + /* Drain USB pipes to avoid hang after reboot */ + for (n = 0; n < 5; n++) { + cxusb_d680_dmb_drain_message(d); + cxusb_d680_dmb_drain_video(d); + msleep(200); + } + + /* Reset the tuner */ + if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { + err("clear tuner gpio failed"); + return -EIO; + } + msleep(100); + if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { + err("set tuner gpio failed"); + return -EIO; + } + msleep(100); + + /* Attach frontend */ + adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); + if (adap->fe == NULL) + return -EIO; + + return 0; +} + /* * DViCO has shipped two devices with the same USB ID, but only one of them * needs a firmware download. Check the device class details to see if they @@ -985,6 +1218,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; static struct dvb_usb_device_properties cxusb_aver_a868r_properties; +static struct dvb_usb_device_properties cxusb_d680_dmb_properties; static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1011,6 +1245,8 @@ static int cxusb_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_rev2_properties, THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, + THIS_MODULE, NULL, adapter_nr) || 0) return 0; @@ -1036,6 +1272,7 @@ static struct usb_device_id cxusb_table [] = { { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, + { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -1530,6 +1767,55 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { } }; +static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + + .size_of_priv = sizeof(struct cxusb_state), + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, + .frontend_attach = cxusb_d680_dmb_frontend_attach, + .tuner_attach = cxusb_d680_dmb_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + }, + }, + + .power_ctrl = cxusb_d680_dmb_power_ctrl, + + .i2c_algo = &cxusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .rc_interval = 100, + .rc_key_map = d680_dmb_rc_keys, + .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), + .rc_query = cxusb_d680_dmb_rc_query, + + .num_device_descs = 1, + .devices = { + { + "Conexant DMB-TH Stick", + { NULL }, + { &cxusb_table[18], NULL }, + }, + } +}; + static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index f327a154b6c..81369b79e75 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -22,6 +22,7 @@ #define USB_VID_AVERMEDIA 0x07ca #define USB_VID_COMPRO 0x185b #define USB_VID_COMPRO_UNK 0x145f +#define USB_VID_CONEXANT 0x0572 #define USB_VID_CYPRESS 0x04b4 #define USB_VID_DIBCOM 0x10b8 #define USB_VID_DPOSH 0x1498 @@ -69,6 +70,7 @@ #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 +#define USB_PID_CONEXANT_D680_DMB 0x86d6 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7dbb4a223c9..774f5c2a71e 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -385,4 +385,11 @@ config DVB_ISL6421 help An SEC control chip. +config DVB_LGS8GL5 + tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DMB-TH tuner module. Say Y when you want to support this frontend. + endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 028da55611c..262eaa429f5 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -48,3 +48,4 @@ obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o obj-$(CONFIG_DVB_AU8522) += au8522.o obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o +obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c new file mode 100644 index 00000000000..c0a223d28b0 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gl5.c @@ -0,0 +1,480 @@ +/* + Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver + + Copyright (C) 2008 Sirius International (Hong Kong) Limited + Timothy Lee + + 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 "dvb_frontend.h" +#include "lgs8gl5.h" + + +#define REG_RESET 0x02 +#define REG_RESET_OFF 0x01 +#define REG_03 0x03 +#define REG_04 0x04 +#define REG_07 0x07 +#define REG_09 0x09 +#define REG_0A 0x0a +#define REG_0B 0x0b +#define REG_0C 0x0c +#define REG_37 0x37 +#define REG_STRENGTH 0x4b +#define REG_STRENGTH_MASK 0x7f +#define REG_STRENGTH_CARRIER 0x80 +#define REG_INVERSION 0x7c +#define REG_INVERSION_ON 0x80 +#define REG_7D 0x7d +#define REG_7E 0x7e +#define REG_A2 0xa2 +#define REG_STATUS 0xa4 +#define REG_STATUS_SYNC 0x04 +#define REG_STATUS_LOCK 0x01 + + +struct lgs8gl5_state { + struct i2c_adapter *i2c; + const struct lgs8gl5_config *config; + struct dvb_frontend frontend; +}; + + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "lgs8gl5: " args); \ + } while (0) + + +/* Writes into demod's register */ +static int +lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data) +{ + int ret; + u8 buf[] = {reg, data}; + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + ret = i2c_transfer(state->i2c, &msg, 1); + if (ret != 1) + dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n", + __func__, reg, data, ret); + return (ret != 1) ? -1 : 0; +} + + +/* Reads from demod's register */ +static int +lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg) +{ + int ret, j; + u8 b0[] = {reg}; + u8 b1[] = {0}; + struct i2c_msg msg[2] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + }, + { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + if (ret != 2) + return -EIO; + + return b1[0]; +} + + +static int +lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data) +{ + lgs8gl5_read_reg(state, reg); + lgs8gl5_write_reg(state, reg, data); + return 0; +} + + +/* Writes into alternate device's register */ +/* TODO: Find out what that device is for! */ +static int +lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data) +{ + int ret, j; + u8 b0[] = {reg}; + u8 b1[] = {0}; + u8 b2[] = {reg, data}; + struct i2c_msg msg[3] = { + { + .addr = state->config->demod_address + 2, + .flags = 0, + .buf = b0, + .len = 1 + }, + { + .addr = state->config->demod_address + 2, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + }, + { + .addr = state->config->demod_address + 2, + .flags = 0, + .buf = b2, + .len = 2 + }, + }; + + ret = i2c_transfer(state->i2c, msg, 3); + return (ret != 3) ? -1 : 0; +} + + +static void +lgs8gl5_soft_reset(struct lgs8gl5_state *state) +{ + u8 val; + + dprintk("%s\n", __func__); + + val = lgs8gl5_read_reg(state, REG_RESET); + lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF); + lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF); + msleep(5); +} + + +static int +lgs8gl5_set_inversion(struct lgs8gl5_state *state, int inversion) +{ + u8 val; + + dprintk("%s\n", __func__); + + switch (inversion) { + case INVERSION_AUTO: + return -EOPNOTSUPP; + case INVERSION_ON: + val = lgs8gl5_read_reg(state, REG_INVERSION); + return lgs8gl5_write_reg(state, REG_INVERSION, + val | REG_INVERSION_ON); + case INVERSION_OFF: + val = lgs8gl5_read_reg(state, REG_INVERSION); + return lgs8gl5_write_reg(state, REG_INVERSION, + val & ~REG_INVERSION_ON); + default: + return -EINVAL; + } +} + + +/* Starts demodulation */ +static void +lgs8gl5_start_demod(struct lgs8gl5_state *state) +{ + u8 val; + int n; + + dprintk("%s\n", __func__); + + lgs8gl5_update_alt_reg(state, 0xc2, 0x28); + lgs8gl5_soft_reset(state); + lgs8gl5_update_reg(state, REG_07, 0x10); + lgs8gl5_update_reg(state, REG_07, 0x10); + lgs8gl5_write_reg(state, REG_09, 0x0e); + lgs8gl5_write_reg(state, REG_0A, 0xe5); + lgs8gl5_write_reg(state, REG_0B, 0x35); + lgs8gl5_write_reg(state, REG_0C, 0x30); + + lgs8gl5_update_reg(state, REG_03, 0x00); + lgs8gl5_update_reg(state, REG_7E, 0x01); + lgs8gl5_update_alt_reg(state, 0xc5, 0x00); + lgs8gl5_update_reg(state, REG_04, 0x02); + lgs8gl5_update_reg(state, REG_37, 0x01); + lgs8gl5_soft_reset(state); + + /* Wait for carrier */ + for (n = 0; n < 10; n++) { + val = lgs8gl5_read_reg(state, REG_STRENGTH); + dprintk("Wait for carrier[%d] 0x%02X\n", n, val); + if (val & REG_STRENGTH_CARRIER) + break; + msleep(4); + } + if (!(val & REG_STRENGTH_CARRIER)) + return; + + /* Wait for lock */ + for (n = 0; n < 20; n++) { + val = lgs8gl5_read_reg(state, REG_STATUS); + dprintk("Wait for lock[%d] 0x%02X\n", n, val); + if (val & REG_STATUS_LOCK) + break; + msleep(12); + } + if (!(val & REG_STATUS_LOCK)) + return; + + lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2)); + lgs8gl5_soft_reset(state); +} + + +static int +lgs8gl5_init(struct dvb_frontend *fe) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + lgs8gl5_update_alt_reg(state, 0xc2, 0x28); + lgs8gl5_soft_reset(state); + lgs8gl5_update_reg(state, REG_07, 0x10); + lgs8gl5_update_reg(state, REG_07, 0x10); + lgs8gl5_write_reg(state, REG_09, 0x0e); + lgs8gl5_write_reg(state, REG_0A, 0xe5); + lgs8gl5_write_reg(state, REG_0B, 0x35); + lgs8gl5_write_reg(state, REG_0C, 0x30); + + return 0; +} + + +static int +lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); + u8 flags = lgs8gl5_read_reg(state, REG_STATUS); + + *status = 0; + + if ((level & REG_STRENGTH_MASK) > 0) + *status |= FE_HAS_SIGNAL; + if (level & REG_STRENGTH_CARRIER) + *status |= FE_HAS_CARRIER; + if (flags & REG_STATUS_SYNC) + *status |= FE_HAS_SYNC; + if (flags & REG_STATUS_LOCK) + *status |= FE_HAS_LOCK; + + return 0; +} + + +static int +lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + *ber = 0; + + return 0; +} + + +static int +lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); + *signal_strength = (level & REG_STRENGTH_MASK) << 8; + + return 0; +} + + +static int +lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); + *snr = (level & REG_STRENGTH_MASK) << 8; + + return 0; +} + + +static int +lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + *ucblocks = 0; + + return 0; +} + + +static int +lgs8gl5_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ) + return -EINVAL; + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* lgs8gl5_set_inversion(state, p->inversion); */ + + lgs8gl5_start_demod(state); + + return 0; +} + + +static int +lgs8gl5_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + u8 inv = lgs8gl5_read_reg(state, REG_INVERSION); + struct dvb_ofdm_parameters *o = &p->u.ofdm; + + p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF; + + o->code_rate_HP = FEC_1_2; + o->code_rate_LP = FEC_7_8; + o->guard_interval = GUARD_INTERVAL_1_32; + o->transmission_mode = TRANSMISSION_MODE_2K; + o->constellation = QAM_64; + o->hierarchy_information = HIERARCHY_NONE; + o->bandwidth = BANDWIDTH_8_MHZ; + + return 0; +} + + +static int +lgs8gl5_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + fesettings->min_delay_ms = 240; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + + +static void +lgs8gl5_release(struct dvb_frontend *fe) +{ + struct lgs8gl5_state *state = fe->demodulator_priv; + kfree(state); +} + + +static struct dvb_frontend_ops lgs8gl5_ops; + + +struct dvb_frontend* +lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c) +{ + struct lgs8gl5_state *state = NULL; + + dprintk("%s\n", __func__); + + /* Allocate memory for the internal state */ + state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* Setup the state */ + state->config = config; + state->i2c = i2c; + + /* Check if the demod is there */ + if (lgs8gl5_read_reg(state, REG_RESET) < 0) + goto error; + + /* Create dvb_frontend */ + memcpy(&state->frontend.ops, &lgs8gl5_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(lgs8gl5_attach); + + +static struct dvb_frontend_ops lgs8gl5_ops = { + .info = { + .name = "Legend Silicon LGS-8GL5 DMB-TH", + .type = FE_OFDM, + .frequency_min = 474000000, + .frequency_max = 858000000, + .frequency_stepsize = 10000, + .frequency_tolerance = 0, + .caps = FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | + FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_BANDWIDTH_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_RECOVER + }, + + .release = lgs8gl5_release, + + .init = lgs8gl5_init, + + .set_frontend = lgs8gl5_set_frontend, + .get_frontend = lgs8gl5_get_frontend, + .get_tune_settings = lgs8gl5_get_tune_settings, + + .read_status = lgs8gl5_read_status, + .read_ber = lgs8gl5_read_ber, + .read_signal_strength = lgs8gl5_read_signal_strength, + .read_snr = lgs8gl5_read_snr, + .read_ucblocks = lgs8gl5_read_ucblocks, +}; + + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver"); +MODULE_AUTHOR("Timothy Lee"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb/frontends/lgs8gl5.h new file mode 100644 index 00000000000..d14176787a7 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gl5.h @@ -0,0 +1,45 @@ +/* + Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver + + Copyright (C) 2008 Sirius International (Hong Kong) Limited + Timothy Lee + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LGS8GL5_H +#define LGS8GL5_H + +#include + +struct lgs8gl5_config { + /* the demodulator's i2c address */ + u8 demod_address; +}; + +#if defined(CONFIG_DVB_LGS8GL5) || \ + (defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE)) +extern struct dvb_frontend *lgs8gl5_attach( + const struct lgs8gl5_config *config, struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *lgs8gl5_attach( + const struct lgs8gl5_config *config, struct i2c_adapter *i2c) { + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_LGS8GL5 */ + +#endif /* LGS8GL5_H */ -- GitLab From 3a6b974d37370e89637f870657f93fd859e09ee3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 9 Aug 2008 15:29:46 -0300 Subject: [PATCH 3977/5416] V4L/DVB (8658): lgs8gl5: fix build warnings Fix the following build warnings: lgs8gl5.c: In function 'lgs8gl5_read_reg': lgs8gl5.c:95: warning: unused variable 'j' lgs8gl5.c: In function 'lgs8gl5_update_alt_reg': lgs8gl5.c:135: warning: unused variable 'j' lgs8gl5.c: In function 'lgs8gl5_read_ber': lgs8gl5.c:300: warning: unused variable 'state' lgs8gl5.c: In function 'lgs8gl5_read_ucblocks': lgs8gl5.c:332: warning: unused variable 'state' lgs8gl5.c: At top level: lgs8gl5.c:181: warning: 'lgs8gl5_set_inversion' defined but not used Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgs8gl5.c | 30 ++------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c index c0a223d28b0..855852fddf2 100644 --- a/drivers/media/dvb/frontends/lgs8gl5.c +++ b/drivers/media/dvb/frontends/lgs8gl5.c @@ -92,7 +92,7 @@ lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data) static int lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg) { - int ret, j; + int ret; u8 b0[] = {reg}; u8 b1[] = {0}; struct i2c_msg msg[2] = { @@ -132,7 +132,7 @@ lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data) static int lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data) { - int ret, j; + int ret; u8 b0[] = {reg}; u8 b1[] = {0}; u8 b2[] = {reg, data}; @@ -176,30 +176,6 @@ lgs8gl5_soft_reset(struct lgs8gl5_state *state) } -static int -lgs8gl5_set_inversion(struct lgs8gl5_state *state, int inversion) -{ - u8 val; - - dprintk("%s\n", __func__); - - switch (inversion) { - case INVERSION_AUTO: - return -EOPNOTSUPP; - case INVERSION_ON: - val = lgs8gl5_read_reg(state, REG_INVERSION); - return lgs8gl5_write_reg(state, REG_INVERSION, - val | REG_INVERSION_ON); - case INVERSION_OFF: - val = lgs8gl5_read_reg(state, REG_INVERSION); - return lgs8gl5_write_reg(state, REG_INVERSION, - val & ~REG_INVERSION_ON); - default: - return -EINVAL; - } -} - - /* Starts demodulation */ static void lgs8gl5_start_demod(struct lgs8gl5_state *state) @@ -297,7 +273,6 @@ lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status) static int lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct lgs8gl5_state *state = fe->demodulator_priv; *ber = 0; return 0; @@ -329,7 +304,6 @@ lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr) static int lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct lgs8gl5_state *state = fe->demodulator_priv; *ucblocks = 0; return 0; -- GitLab From 05d26cc894cb42f5c71eaf667d700dd632745cd9 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 20 Aug 2008 20:44:54 -0300 Subject: [PATCH 3978/5416] V4L/DVB (8680): saa7134-core.c: fix warning drivers/media/video/saa7134/saa7134-core.c:366: warning: 'saa7134_buffer_requeue' defined but not used Signed-off-by: Alexander Beregalov Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 75d618415f4..64f20fd4631 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -359,32 +359,6 @@ void saa7134_buffer_timeout(unsigned long data) spin_unlock_irqrestore(&dev->slock,flags); } -/* resends a current buffer in queue after resume */ - -static int saa7134_buffer_requeue(struct saa7134_dev *dev, - struct saa7134_dmaqueue *q) -{ - struct saa7134_buf *buf, *next; - - assert_spin_locked(&dev->slock); - - buf = q->curr; - next = buf; - dprintk("buffer_requeue\n"); - - if (!buf) - return 0; - - dprintk("buffer_requeue : resending active buffers \n"); - - if (!list_empty(&q->queue)) - next = list_entry(q->queue.next, struct saa7134_buf, - vb.queue); - buf->activate(dev, buf, next); - - return 0; -} - /* ------------------------------------------------------------------ */ int saa7134_set_dmabits(struct saa7134_dev *dev) @@ -1139,6 +1113,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) } #ifdef CONFIG_PM + +/* resends a current buffer in queue after resume */ +static int saa7134_buffer_requeue(struct saa7134_dev *dev, + struct saa7134_dmaqueue *q) +{ + struct saa7134_buf *buf, *next; + + assert_spin_locked(&dev->slock); + + buf = q->curr; + next = buf; + dprintk("buffer_requeue\n"); + + if (!buf) + return 0; + + dprintk("buffer_requeue : resending active buffers \n"); + + if (!list_empty(&q->queue)) + next = list_entry(q->queue.next, struct saa7134_buf, + vb.queue); + buf->activate(dev, buf, next); + + return 0; +} + static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) { -- GitLab From 9cc6493d4b5b06e976e527737301d90044037b57 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 14 Aug 2008 11:36:37 -0300 Subject: [PATCH 3979/5416] V4L/DVB (8683): Add Micron mt9m111 chip ID in V4L2 identifiers Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-chip-ident.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index be782d5fcfa..d73a8e9028a 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -165,6 +165,7 @@ enum { /* Micron CMOS sensor chips: 45000-45099 */ V4L2_IDENT_MT9M001C12ST = 45000, V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9M111 = 45007, V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; -- GitLab From 77110abbfbfd7673be6d18ef0875350eabee7532 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 14 Aug 2008 12:02:51 -0300 Subject: [PATCH 3980/5416] V4L/DVB (8684): Add support for Micron MT9M111 camera. Adds support for Micron MT9M111 camera chip, with basic features : - view rectangle configurable - some output formats (bayer8, bayer10, rgb565, rgb555, ycbycr) - autoexposure - only highpower mode context used (ie. context B) create mode 100644 drivers/media/video/mt9m111.c Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/mt9m111.c | 960 ++++++++++++++++++++++++++++++++++ 3 files changed, 967 insertions(+) create mode 100644 drivers/media/video/mt9m111.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 367666db5bf..6ebe9f1aca0 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -809,6 +809,12 @@ config MT9M001_PCA9536_SWITCH Select this if your MT9M001 camera uses a PCA9536 I2C GPIO extender to switch between 8 and 10 bit datawidth modes +config SOC_CAMERA_MT9M111 + tristate "mt9m001 support" + depends on SOC_CAMERA && I2C + help + This driver supports MT9M111 cameras from Micron + config SOC_CAMERA_MT9V022 tristate "mt9v022 support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ef7c8d3ffb1..d234db7c4e0 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -137,6 +137,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c new file mode 100644 index 00000000000..0c88e5d6dc4 --- /dev/null +++ b/drivers/media/video/mt9m111.c @@ -0,0 +1,960 @@ +/* + * Driver for MT9M111 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin) + * The platform has to define i2c_board_info and call i2c_register_board_info() + */ + +/* mt9m111: Sensor register addresses */ +#define MT9M111_CHIP_VERSION 0x000 +#define MT9M111_ROW_START 0x001 +#define MT9M111_COLUMN_START 0x002 +#define MT9M111_WINDOW_HEIGHT 0x003 +#define MT9M111_WINDOW_WIDTH 0x004 +#define MT9M111_HORIZONTAL_BLANKING_B 0x005 +#define MT9M111_VERTICAL_BLANKING_B 0x006 +#define MT9M111_HORIZONTAL_BLANKING_A 0x007 +#define MT9M111_VERTICAL_BLANKING_A 0x008 +#define MT9M111_SHUTTER_WIDTH 0x009 +#define MT9M111_ROW_SPEED 0x00a +#define MT9M111_EXTRA_DELAY 0x00b +#define MT9M111_SHUTTER_DELAY 0x00c +#define MT9M111_RESET 0x00d +#define MT9M111_READ_MODE_B 0x020 +#define MT9M111_READ_MODE_A 0x021 +#define MT9M111_FLASH_CONTROL 0x023 +#define MT9M111_GREEN1_GAIN 0x02b +#define MT9M111_BLUE_GAIN 0x02c +#define MT9M111_RED_GAIN 0x02d +#define MT9M111_GREEN2_GAIN 0x02e +#define MT9M111_GLOBAL_GAIN 0x02f +#define MT9M111_CONTEXT_CONTROL 0x0c8 +#define MT9M111_PAGE_MAP 0x0f0 +#define MT9M111_BYTE_WISE_ADDR 0x0f1 + +#define MT9M111_RESET_SYNC_CHANGES (1 << 15) +#define MT9M111_RESET_RESTART_BAD_FRAME (1 << 9) +#define MT9M111_RESET_SHOW_BAD_FRAMES (1 << 8) +#define MT9M111_RESET_RESET_SOC (1 << 5) +#define MT9M111_RESET_OUTPUT_DISABLE (1 << 4) +#define MT9M111_RESET_CHIP_ENABLE (1 << 3) +#define MT9M111_RESET_ANALOG_STANDBY (1 << 2) +#define MT9M111_RESET_RESTART_FRAME (1 << 1) +#define MT9M111_RESET_RESET_MODE (1 << 0) + +#define MT9M111_RMB_MIRROR_COLS (1 << 1) +#define MT9M111_RMB_MIRROR_ROWS (1 << 0) +#define MT9M111_CTXT_CTRL_RESTART (1 << 15) +#define MT9M111_CTXT_CTRL_DEFECTCOR_B (1 << 12) +#define MT9M111_CTXT_CTRL_RESIZE_B (1 << 10) +#define MT9M111_CTXT_CTRL_CTRL2_B (1 << 9) +#define MT9M111_CTXT_CTRL_GAMMA_B (1 << 8) +#define MT9M111_CTXT_CTRL_XENON_EN (1 << 7) +#define MT9M111_CTXT_CTRL_READ_MODE_B (1 << 3) +#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2) +#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1) +#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0) +/* + * mt9m111: Colorpipe register addresses (0x100..0x1ff) + */ +#define MT9M111_OPER_MODE_CTRL 0x106 +#define MT9M111_OUTPUT_FORMAT_CTRL 0x108 +#define MT9M111_REDUCER_XZOOM_B 0x1a0 +#define MT9M111_REDUCER_XSIZE_B 0x1a1 +#define MT9M111_REDUCER_YZOOM_B 0x1a3 +#define MT9M111_REDUCER_YSIZE_B 0x1a4 +#define MT9M111_REDUCER_XZOOM_A 0x1a6 +#define MT9M111_REDUCER_XSIZE_A 0x1a7 +#define MT9M111_REDUCER_YZOOM_A 0x1a9 +#define MT9M111_REDUCER_YSIZE_A 0x1aa + +#define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a +#define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b + +#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) + + +#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) +#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) +#define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9) +#define MT9M111_OUTFMT_RGB (1 << 8) +#define MT9M111_OUTFMT_RGB565 (0x0 << 6) +#define MT9M111_OUTFMT_RGB555 (0x1 << 6) +#define MT9M111_OUTFMT_RGB444x (0x2 << 6) +#define MT9M111_OUTFMT_RGBx444 (0x3 << 6) +#define MT9M111_OUTFMT_TST_RAMP_OFF (0x0 << 4) +#define MT9M111_OUTFMT_TST_RAMP_COL (0x1 << 4) +#define MT9M111_OUTFMT_TST_RAMP_ROW (0x2 << 4) +#define MT9M111_OUTFMT_TST_RAMP_FRAME (0x3 << 4) +#define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3) +#define MT9M111_OUTFMT_AVG_CHROMA (1 << 2) +#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1) +#define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1) +#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0) +/* + * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) + */ + +#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg) +#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val)) +#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val)) +#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val)) + +#define MT9M111_MIN_DARK_ROWS 8 +#define MT9M111_MIN_DARK_COLS 24 +#define MT9M111_MAX_HEIGHT 1024 +#define MT9M111_MAX_WIDTH 1280 + +#define COL_FMT(_name, _depth, _fourcc, _colorspace) \ + { .name = _name, .depth = _depth, .fourcc = _fourcc, \ + .colorspace = _colorspace } +#define RGB_FMT(_name, _depth, _fourcc) \ + COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) + +static const struct soc_camera_data_format mt9m111_colour_formats[] = { + COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG), + RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), + RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), + RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), + RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8), +}; + +enum mt9m111_context { + HIGHPOWER = 0, + LOWPOWER, +}; + +struct mt9m111 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */ + enum mt9m111_context context; + unsigned int left, top, width, height; + u32 pixfmt; + unsigned char autoexposure; + unsigned char datawidth; + unsigned int powered:1; + unsigned int hflip:1; + unsigned int vflip:1; + unsigned int swap_rgb_even_odd:1; + unsigned int swap_rgb_red_blue:1; + unsigned int swap_yuv_y_chromas:1; + unsigned int swap_yuv_cb_cr:1; +}; + +static int reg_page_map_set(struct i2c_client *client, const u16 reg) +{ + int ret; + u16 page; + static int lastpage = -1; /* PageMap cache value */ + + page = (reg >> 8); + if (page == lastpage) + return 0; + if (page > 2) + return -EINVAL; + + ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); + if (ret >= 0) + lastpage = page; + return ret; +} + +static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = mt9m111->client; + int ret; + + ret = reg_page_map_set(client, reg); + if (!ret) + ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); + + dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret); + return ret; +} + +static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, + const u16 data) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = mt9m111->client; + int ret; + + ret = reg_page_map_set(client, reg); + if (ret >= 0) + ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), + swab16(data)); + dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); + return ret; +} + +static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg, + const u16 data) +{ + int ret; + + ret = mt9m111_reg_read(icd, reg); + if (ret >= 0) + ret = mt9m111_reg_write(icd, reg, ret | data); + return ret; +} + +static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg, + const u16 data) +{ + int ret; + + ret = mt9m111_reg_read(icd, reg); + return mt9m111_reg_write(icd, reg, ret & ~data); +} + +static int mt9m111_set_context(struct soc_camera_device *icd, + enum mt9m111_context ctxt) +{ + int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B + | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B + | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B + | MT9M111_CTXT_CTRL_VBLANK_SEL_B + | MT9M111_CTXT_CTRL_HBLANK_SEL_B; + int valA = MT9M111_CTXT_CTRL_RESTART; + + if (ctxt == HIGHPOWER) + return reg_write(CONTEXT_CONTROL, valB); + else + return reg_write(CONTEXT_CONTROL, valA); +} + +static int mt9m111_setup_rect(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret = 0, is_raw_format; + int width = mt9m111->width; + int height = mt9m111->height; + + if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) + || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) + is_raw_format = 1; + else + is_raw_format = 0; + + if (ret >= 0) + ret = reg_write(COLUMN_START, mt9m111->left); + if (ret >= 0) + ret = reg_write(ROW_START, mt9m111->top); + + if (is_raw_format) { + if (ret >= 0) + ret = reg_write(WINDOW_WIDTH, width); + if (ret >= 0) + ret = reg_write(WINDOW_HEIGHT, height); + } else { + if (ret >= 0) + ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); + if (ret >= 0) + ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT); + if (ret >= 0) + ret = reg_write(REDUCER_XSIZE_B, width); + if (ret >= 0) + ret = reg_write(REDUCER_YSIZE_B, height); + if (ret >= 0) + ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH); + if (ret >= 0) + ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT); + if (ret >= 0) + ret = reg_write(REDUCER_XSIZE_A, width); + if (ret >= 0) + ret = reg_write(REDUCER_YSIZE_A, height); + } + + return ret; +} + +static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) +{ + int ret; + + ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); + if (ret >= 0) + ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt); + return ret; +} + +static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) +{ + return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); +} + +static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) +{ + + return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); +} + +static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int val = 0; + + if (mt9m111->swap_rgb_red_blue) + val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; + if (mt9m111->swap_rgb_even_odd) + val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; + val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; + + return mt9m111_setup_pixfmt(icd, val); +} + +static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int val = 0; + + if (mt9m111->swap_rgb_red_blue) + val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; + if (mt9m111->swap_rgb_even_odd) + val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; + val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; + + return mt9m111_setup_pixfmt(icd, val); +} + +static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int val = 0; + + if (mt9m111->swap_yuv_cb_cr) + val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; + if (mt9m111->swap_yuv_y_chromas) + val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; + + return mt9m111_setup_pixfmt(icd, val); +} + +static int mt9m111_enable(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); + if (ret >= 0) + mt9m111->powered = 1; + return ret; +} + +static int mt9m111_disable(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); + if (ret >= 0) + mt9m111->powered = 0; + return ret; +} + +static int mt9m111_reset(struct soc_camera_device *icd) +{ + int ret; + + ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); + if (ret >= 0) + ret = reg_set(RESET, MT9M111_RESET_RESET_SOC); + if (ret >= 0) + ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE + | MT9M111_RESET_RESET_SOC); + return ret; +} + +static int mt9m111_start_capture(struct soc_camera_device *icd) +{ + return 0; +} + +static int mt9m111_stop_capture(struct soc_camera_device *icd) +{ + return 0; +} + +static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) +{ + return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_DATAWIDTH_8; +} + +static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) +{ + return 0; +} + +static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret = 0; + + switch (pixfmt) { + case V4L2_PIX_FMT_SBGGR8: + ret = mt9m111_setfmt_bayer8(icd); + break; + case V4L2_PIX_FMT_SBGGR16: + ret = mt9m111_setfmt_bayer10(icd); + break; + case V4L2_PIX_FMT_RGB555: + ret = mt9m111_setfmt_rgb555(icd); + break; + case V4L2_PIX_FMT_RGB565: + ret = mt9m111_setfmt_rgb565(icd); + break; + case V4L2_PIX_FMT_YUYV: + ret = mt9m111_setfmt_yuv(icd); + break; + default: + dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); + ret = -EINVAL; + } + + if (ret >= 0) + mt9m111->pixfmt = pixfmt; + + return ret; +} + +static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret = 0; + + mt9m111->left = rect->left; + mt9m111->top = rect->top; + mt9m111->width = rect->width; + mt9m111->height = rect->height; + + dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", + __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, + mt9m111->height); + + ret = mt9m111_setup_rect(icd); + if (ret >= 0) + ret = mt9m111_set_pixfmt(icd, pixfmt); + return ret < 0 ? ret : 0; +} + +static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) + f->fmt.pix.height = MT9M111_MAX_HEIGHT; + if (f->fmt.pix.width > MT9M111_MAX_WIDTH) + f->fmt.pix.width = MT9M111_MAX_WIDTH; + + return 0; +} + +static int mt9m111_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9m111->client->addr) + return -ENODEV; + + id->ident = mt9m111->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9m111_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + int val; + + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + return -EINVAL; + if (reg->match_chip != mt9m111->client->addr) + return -ENODEV; + + val = mt9m111_reg_read(icd, reg->reg); + reg->val = (u64)val; + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9m111_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + return -EINVAL; + + if (reg->match_chip != mt9m111->client->addr) + return -ENODEV; + + if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static const struct v4l2_queryctrl mt9m111_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Verticaly", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontaly", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { /* gain = 1/32*val (=>gain=1 if val==32) */ + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 63 * 2 * 2, + .step = 1, + .default_value = 32, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9m111_video_probe(struct soc_camera_device *); +static void mt9m111_video_remove(struct soc_camera_device *); +static int mt9m111_get_control(struct soc_camera_device *, + struct v4l2_control *); +static int mt9m111_set_control(struct soc_camera_device *, + struct v4l2_control *); +static int mt9m111_resume(struct soc_camera_device *icd); +static int mt9m111_init(struct soc_camera_device *icd); +static int mt9m111_release(struct soc_camera_device *icd); + +static struct soc_camera_ops mt9m111_ops = { + .owner = THIS_MODULE, + .probe = mt9m111_video_probe, + .remove = mt9m111_video_remove, + .init = mt9m111_init, + .resume = mt9m111_resume, + .release = mt9m111_release, + .start_capture = mt9m111_start_capture, + .stop_capture = mt9m111_stop_capture, + .set_fmt_cap = mt9m111_set_fmt_cap, + .try_fmt_cap = mt9m111_try_fmt_cap, + .query_bus_param = mt9m111_query_bus_param, + .set_bus_param = mt9m111_set_bus_param, + .controls = mt9m111_controls, + .num_controls = ARRAY_SIZE(mt9m111_controls), + .get_control = mt9m111_get_control, + .set_control = mt9m111_set_control, + .get_chip_id = mt9m111_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9m111_get_register, + .set_register = mt9m111_set_register, +#endif +}; + +static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + if (mt9m111->context == HIGHPOWER) { + if (flip) + ret = reg_set(READ_MODE_B, mask); + else + ret = reg_clear(READ_MODE_B, mask); + } else { + if (flip) + ret = reg_set(READ_MODE_A, mask); + else + ret = reg_clear(READ_MODE_A, mask); + } + + return ret; +} + +static int mt9m111_get_global_gain(struct soc_camera_device *icd) +{ + unsigned int data, gain; + + data = reg_read(GLOBAL_GAIN); + if (data >= 0) + gain = ((data & (1 << 10)) * 2) + | ((data & (1 << 9)) * 2) + | (data & 0x2f); + else + gain = data; + + return gain; +} +static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) +{ + u16 val; + + if (gain > 63 * 2 * 2) + return -EINVAL; + + icd->gain = gain; + if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) + val = (1 << 10) | (1 << 9) | (gain / 4); + else if ((gain >= 64) && (gain < 64 * 2)) + val = (1<<9) | (gain / 2); + else + val = gain; + + return reg_write(GLOBAL_GAIN, val); +} + +static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + if (on) + ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); + else + ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); + + if (ret >= 0) + mt9m111->autoexposure = on; + + return ret; +} +static int mt9m111_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (mt9m111->context == HIGHPOWER) + data = reg_read(READ_MODE_B); + else + data = reg_read(READ_MODE_A); + + if (data < 0) + return -EIO; + ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS); + break; + case V4L2_CID_HFLIP: + if (mt9m111->context == HIGHPOWER) + data = reg_read(READ_MODE_B); + else + data = reg_read(READ_MODE_A); + + if (data < 0) + return -EIO; + ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); + break; + case V4L2_CID_GAIN: + data = mt9m111_get_global_gain(icd); + if (data < 0) + return data; + ctrl->value = data; + break; + case V4L2_CID_EXPOSURE_AUTO: + ctrl->value = mt9m111->autoexposure; + break; + } + return 0; +} + +static int mt9m111_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + const struct v4l2_queryctrl *qctrl; + int ret = 0; + + qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + mt9m111->vflip = ctrl->value; + ret = mt9m111_set_flip(icd, ctrl->value, + MT9M111_RMB_MIRROR_ROWS); + break; + case V4L2_CID_HFLIP: + mt9m111->hflip = ctrl->value; + ret = mt9m111_set_flip(icd, ctrl->value, + MT9M111_RMB_MIRROR_COLS); + break; + case V4L2_CID_GAIN: + ret = mt9m111_set_global_gain(icd, ctrl->value); + break; + case V4L2_CID_EXPOSURE_AUTO: + ret = mt9m111_set_autoexposure(icd, ctrl->value); + break; + default: + ret = -EINVAL; + } + + return ret < 0 ? -EIO : 0; +} + +int mt9m111_restore_state(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + + mt9m111_set_context(icd, mt9m111->context); + mt9m111_set_pixfmt(icd, mt9m111->pixfmt); + mt9m111_setup_rect(icd); + mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); + mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); + mt9m111_set_global_gain(icd, icd->gain); + mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + return 0; +} + +static int mt9m111_resume(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret = 0; + + if (mt9m111->powered) { + ret = mt9m111_enable(icd); + if (ret >= 0) + mt9m111_reset(icd); + if (ret >= 0) + mt9m111_restore_state(icd); + } + return ret; +} + +static int mt9m111_init(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + mt9m111->context = HIGHPOWER; + ret = mt9m111_enable(icd); + if (ret >= 0) + mt9m111_reset(icd); + if (ret >= 0) + mt9m111_set_context(icd, mt9m111->context); + if (ret >= 0) + mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + if (ret < 0) + dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); + return ret ? -EIO : 0; +} + +static int mt9m111_release(struct soc_camera_device *icd) +{ + int ret; + + ret = mt9m111_disable(icd); + if (ret < 0) + dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); + + return ret ? -EIO : 0; +} + +/* + * Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one + */ +static int mt9m111_video_probe(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + s32 data; + int ret; + + /* + * We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. + */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + ret = mt9m111_enable(icd); + if (ret) + goto ei2c; + ret = mt9m111_reset(icd); + if (ret) + goto ei2c; + + data = reg_read(CHIP_VERSION); + + switch (data) { + case 0x143a: + mt9m111->model = V4L2_IDENT_MT9M111; + icd->formats = mt9m111_colour_formats; + icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); + break; + default: + ret = -ENODEV; + dev_err(&icd->dev, + "No MT9M111 chip detected, register read %x\n", data); + goto ei2c; + } + + dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n"); + + ret = soc_camera_video_start(icd); + if (ret) + goto eisis; + + mt9m111->autoexposure = 1; + + mt9m111->swap_rgb_even_odd = 1; + mt9m111->swap_rgb_red_blue = 1; + + return 0; +eisis: +ei2c: + return ret; +} + +static void mt9m111_video_remove(struct soc_camera_device *icd) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, + mt9m111->icd.dev.parent, mt9m111->icd.vdev); + soc_camera_video_stop(&mt9m111->icd); +} + +static int mt9m111_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct mt9m111 *mt9m111; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9M111 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL); + if (!mt9m111) + return -ENOMEM; + + mt9m111->client = client; + i2c_set_clientdata(client, mt9m111); + + /* Second stage probe - when a capture adapter is there */ + icd = &mt9m111->icd; + icd->ops = &mt9m111_ops; + icd->control = &client->dev; + icd->x_min = MT9M111_MIN_DARK_COLS; + icd->y_min = MT9M111_MIN_DARK_ROWS; + icd->x_current = icd->x_min; + icd->y_current = icd->y_min; + icd->width_min = MT9M111_MIN_DARK_ROWS; + icd->width_max = MT9M111_MAX_WIDTH; + icd->height_min = MT9M111_MIN_DARK_COLS; + icd->height_max = MT9M111_MAX_HEIGHT; + icd->y_skip_top = 0; + icd->iface = icl->bus_id; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + return 0; + +eisdr: + kfree(mt9m111); + return ret; +} + +static int mt9m111_remove(struct i2c_client *client) +{ + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + soc_camera_device_unregister(&mt9m111->icd); + kfree(mt9m111); + + return 0; +} + +static const struct i2c_device_id mt9m111_id[] = { + { "mt9m111", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9m111_id); + +static struct i2c_driver mt9m111_i2c_driver = { + .driver = { + .name = "mt9m111", + }, + .probe = mt9m111_probe, + .remove = mt9m111_remove, + .id_table = mt9m111_id, +}; + +static int __init mt9m111_mod_init(void) +{ + return i2c_add_driver(&mt9m111_i2c_driver); +} + +static void __exit mt9m111_mod_exit(void) +{ + i2c_del_driver(&mt9m111_i2c_driver); +} + +module_init(mt9m111_mod_init); +module_exit(mt9m111_mod_exit); + +MODULE_DESCRIPTION("Micron MT9M111 Camera driver"); +MODULE_AUTHOR("Robert Jarzmik"); +MODULE_LICENSE("GPL"); -- GitLab From 112116410aaab5310a9a279c71fb76605236e448 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 14 Aug 2008 12:03:18 -0300 Subject: [PATCH 3981/5416] V4L/DVB (8685): mt9m001, mt9v022: Simplify return code checking i2c_smbus_write_word_data() returns 0 or a negative error, hence no need to check for "> 0". Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 24 ++++++++++++------------ drivers/media/video/mt9v022.c | 28 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 554d2295484..3531f9352df 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -119,16 +119,16 @@ static int mt9m001_init(struct soc_camera_device *icd) { int ret; - /* Disable chip, synchronous option update */ dev_dbg(icd->vdev->parent, "%s\n", __func__); ret = reg_write(icd, MT9M001_RESET, 1); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_RESET, 0); - if (ret >= 0) + /* Disable chip, synchronous option update */ + if (!ret) ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); - return ret >= 0 ? 0 : -EIO; + return ret; } static int mt9m001_release(struct soc_camera_device *icd) @@ -267,24 +267,24 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, /* Blanking and start values - default... */ ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); /* The caller provides a supported format, as verified per * call to icd->try_fmt_cap() */ - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_ROW_START, rect->top); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, rect->height + icd->y_skip_top - 1); - if (ret >= 0 && mt9m001->autoexposure) { + if (!ret && mt9m001->autoexposure) { ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, rect->height + icd->y_skip_top + vblank); - if (ret >= 0) { + if (!ret) { const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); @@ -295,7 +295,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, } } - return ret < 0 ? ret : 0; + return ret; } static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 56808cd2f8a..0f4b204667e 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -141,22 +141,22 @@ static int mt9v022_init(struct soc_camera_device *icd) * plus snapshot mode to disable scan for now */ mt9v022->chip_control |= 0x10; ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); - if (ret >= 0) - reg_write(icd, MT9V022_READ_MODE, 0x300); + if (!ret) + ret = reg_write(icd, MT9V022_READ_MODE, 0x300); /* All defaults */ - if (ret >= 0) + if (!ret) /* AEC, AGC on */ ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); - if (ret >= 0) + if (!ret) /* default - auto */ ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); - return ret >= 0 ? 0 : -EIO; + return ret; } static int mt9v022_release(struct soc_camera_device *icd) @@ -352,21 +352,21 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, rect->height + icd->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_ROW_START, rect->top); - if (ret >= 0) + if (!ret) /* Default 94, Phytec driver says: * "width + horizontal blank >= 660" */ ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, rect->width > 660 - 43 ? 43 : 660 - rect->width); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); - if (ret >= 0) + if (!ret) ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, rect->height + icd->y_skip_top); @@ -717,7 +717,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) icd->num_formats = 1; } - if (ret >= 0) + if (!ret) ret = soc_camera_video_start(icd); if (ret < 0) goto eisis; -- GitLab From 506c629a8eb95a3232a0aafa3b80903224ccc461 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 14 Aug 2008 12:03:49 -0300 Subject: [PATCH 3982/5416] V4L/DVB (8686): mt9m111: style cleanup Fix a typo in Kconfig, simplify error checking, further minor cleanup. Tested-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/mt9m111.c | 86 +++++++++++++++++------------------ 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6ebe9f1aca0..37123ff20fc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -810,7 +810,7 @@ config MT9M001_PCA9536_SWITCH extender to switch between 8 and 10 bit datawidth modes config SOC_CAMERA_MT9M111 - tristate "mt9m001 support" + tristate "mt9m111 support" depends on SOC_CAMERA && I2C help This driver supports MT9M111 cameras from Micron diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 0c88e5d6dc4..d9993263105 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -173,7 +173,7 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg) return -EINVAL; ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); - if (ret >= 0) + if (!ret) lastpage = page; return ret; } @@ -200,7 +200,7 @@ static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, int ret; ret = reg_page_map_set(client, reg); - if (ret >= 0) + if (!ret) ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), swab16(data)); dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); @@ -246,7 +246,7 @@ static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - int ret = 0, is_raw_format; + int ret, is_raw_format; int width = mt9m111->width; int height = mt9m111->height; @@ -256,32 +256,31 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd) else is_raw_format = 0; - if (ret >= 0) - ret = reg_write(COLUMN_START, mt9m111->left); - if (ret >= 0) + ret = reg_write(COLUMN_START, mt9m111->left); + if (!ret) ret = reg_write(ROW_START, mt9m111->top); if (is_raw_format) { - if (ret >= 0) + if (!ret) ret = reg_write(WINDOW_WIDTH, width); - if (ret >= 0) + if (!ret) ret = reg_write(WINDOW_HEIGHT, height); } else { - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_XSIZE_B, width); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_YSIZE_B, height); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_XSIZE_A, width); - if (ret >= 0) + if (!ret) ret = reg_write(REDUCER_YSIZE_A, height); } @@ -293,7 +292,7 @@ static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); - if (ret >= 0) + if (!ret) ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt); return ret; } @@ -305,7 +304,6 @@ static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) { - return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); } @@ -356,7 +354,7 @@ static int mt9m111_enable(struct soc_camera_device *icd) int ret; ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); - if (ret >= 0) + if (!ret) mt9m111->powered = 1; return ret; } @@ -367,7 +365,7 @@ static int mt9m111_disable(struct soc_camera_device *icd) int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); - if (ret >= 0) + if (!ret) mt9m111->powered = 0; return ret; } @@ -377,9 +375,9 @@ static int mt9m111_reset(struct soc_camera_device *icd) int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); - if (ret >= 0) + if (!ret) ret = reg_set(RESET, MT9M111_RESET_RESET_SOC); - if (ret >= 0) + if (!ret) ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | MT9M111_RESET_RESET_SOC); return ret; @@ -410,7 +408,7 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - int ret = 0; + int ret; switch (pixfmt) { case V4L2_PIX_FMT_SBGGR8: @@ -433,7 +431,7 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) ret = -EINVAL; } - if (ret >= 0) + if (!ret) mt9m111->pixfmt = pixfmt; return ret; @@ -443,7 +441,7 @@ static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - int ret = 0; + int ret; mt9m111->left = rect->left; mt9m111->top = rect->top; @@ -455,9 +453,9 @@ static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, mt9m111->height); ret = mt9m111_setup_rect(icd); - if (ret >= 0) + if (!ret) ret = mt9m111_set_pixfmt(icd, pixfmt); - return ret < 0 ? ret : 0; + return ret; } static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, @@ -644,7 +642,7 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) val = (1 << 10) | (1 << 9) | (gain / 4); else if ((gain >= 64) && (gain < 64 * 2)) - val = (1<<9) | (gain / 2); + val = (1 << 9) | (gain / 2); else val = gain; @@ -661,7 +659,7 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) else ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); - if (ret >= 0) + if (!ret) mt9m111->autoexposure = on; return ret; @@ -711,7 +709,7 @@ static int mt9m111_set_control(struct soc_camera_device *icd, { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); const struct v4l2_queryctrl *qctrl; - int ret = 0; + int ret; qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); @@ -739,7 +737,7 @@ static int mt9m111_set_control(struct soc_camera_device *icd, ret = -EINVAL; } - return ret < 0 ? -EIO : 0; + return ret; } int mt9m111_restore_state(struct soc_camera_device *icd) @@ -763,10 +761,10 @@ static int mt9m111_resume(struct soc_camera_device *icd) if (mt9m111->powered) { ret = mt9m111_enable(icd); - if (ret >= 0) - mt9m111_reset(icd); - if (ret >= 0) - mt9m111_restore_state(icd); + if (!ret) + ret = mt9m111_reset(icd); + if (!ret) + ret = mt9m111_restore_state(icd); } return ret; } @@ -778,15 +776,15 @@ static int mt9m111_init(struct soc_camera_device *icd) mt9m111->context = HIGHPOWER; ret = mt9m111_enable(icd); - if (ret >= 0) - mt9m111_reset(icd); - if (ret >= 0) - mt9m111_set_context(icd, mt9m111->context); - if (ret >= 0) - mt9m111_set_autoexposure(icd, mt9m111->autoexposure); - if (ret < 0) + if (!ret) + ret = mt9m111_reset(icd); + if (!ret) + ret = mt9m111_set_context(icd, mt9m111->context); + if (!ret) + ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + if (ret) dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); - return ret ? -EIO : 0; + return ret; } static int mt9m111_release(struct soc_camera_device *icd) @@ -797,7 +795,7 @@ static int mt9m111_release(struct soc_camera_device *icd) if (ret < 0) dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); - return ret ? -EIO : 0; + return ret; } /* -- GitLab From 81034663159f39d005316b5c139038459cd16721 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Thu, 14 Aug 2008 12:04:11 -0300 Subject: [PATCH 3983/5416] V4L/DVB (8687): soc-camera: Move .power and .reset from soc_camera host to sensor driver Make .power and .reset callbacks per camera instead of per host, also move their invocation to camera drivers. .arch/arm/mach-pxa/include/mach/camera.h | 2 - Signed-off-by: Stefan Herbrechtsmeier Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-pxa/include/mach/camera.h | 2 -- drivers/media/video/mt9m001.c | 33 ++++++++++++++++++++-- drivers/media/video/mt9m111.c | 15 ++++++++++ drivers/media/video/mt9v022.c | 24 +++++++++++++++- drivers/media/video/pxa_camera.c | 24 ---------------- drivers/media/video/sh_mobile_ceu_camera.c | 5 ---- include/media/sh_mobile_ceu.h | 2 -- include/media/soc_camera.h | 3 ++ 8 files changed, 71 insertions(+), 37 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/camera.h b/arch/arm/mach-pxa/include/mach/camera.h index 39516ced8b1..31abe6d514b 100644 --- a/arch/arm/mach-pxa/include/mach/camera.h +++ b/arch/arm/mach-pxa/include/mach/camera.h @@ -36,8 +36,6 @@ struct pxacamera_platform_data { int (*init)(struct device *); - int (*power)(struct device *, int); - int (*reset)(struct device *, int); unsigned long flags; unsigned long mclk_10khz; diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 3531f9352df..0c524376b67 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -117,13 +117,33 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, static int mt9m001_init(struct soc_camera_device *icd) { + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; int ret; dev_dbg(icd->vdev->parent, "%s\n", __func__); - ret = reg_write(icd, MT9M001_RESET, 1); - if (!ret) - ret = reg_write(icd, MT9M001_RESET, 0); + if (icl->power) { + ret = icl->power(&mt9m001->client->dev, 1); + if (ret < 0) { + dev_err(icd->vdev->parent, + "Platform failed to power-on the camera.\n"); + return ret; + } + } + + /* The camera could have been already on, we reset it additionally */ + if (icl->reset) + ret = icl->reset(&mt9m001->client->dev); + else + ret = -ENODEV; + + if (ret < 0) { + /* Either no platform reset, or platform reset failed */ + ret = reg_write(icd, MT9M001_RESET, 1); + if (!ret) + ret = reg_write(icd, MT9M001_RESET, 0); + } /* Disable chip, synchronous option update */ if (!ret) ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); @@ -133,8 +153,15 @@ static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd) { + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + /* Disable the chip */ reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + + if (icl->power) + icl->power(&mt9m001->client->dev, 0); + return 0; } diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index d9993263105..4844486d72f 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -351,8 +351,18 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; int ret; + if (icl->power) { + ret = icl->power(&mt9m111->client->dev, 1); + if (ret < 0) { + dev_err(icd->vdev->parent, + "Platform failed to power-on the camera.\n"); + return ret; + } + } + ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); if (!ret) mt9m111->powered = 1; @@ -362,11 +372,16 @@ static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); if (!ret) mt9m111->powered = 0; + + if (icl->power) + icl->power(&mt9m111->client->dev, 0); + return ret; } diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 0f4b204667e..2584201059d 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -134,8 +134,25 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; int ret; + if (icl->power) { + ret = icl->power(&mt9v022->client->dev, 1); + if (ret < 0) { + dev_err(icd->vdev->parent, + "Platform failed to power-on the camera.\n"); + return ret; + } + } + + /* + * The camera could have been already on, we hard-reset it additionally, + * if available. Soft reset is done in video_probe(). + */ + if (icl->reset) + icl->reset(&mt9v022->client->dev); + /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ @@ -161,7 +178,12 @@ static int mt9v022_init(struct soc_camera_device *icd) static int mt9v022_release(struct soc_camera_device *icd) { - /* Nothing? */ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + + if (icl->power) + icl->power(&mt9v022->client->dev, 0); + return 0; } diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index cf96b2cc4f1..14569b59138 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -629,17 +629,6 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) pdata->init(pcdev->dev); } - if (pdata && pdata->power) { - dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__); - pdata->power(pcdev->dev, 1); - } - - if (pdata && pdata->reset) { - dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", - __func__); - pdata->reset(pcdev->dev, 1); - } - CICR0 = 0x3FF; /* disable all interrupts */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) @@ -660,20 +649,7 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) { - struct pxacamera_platform_data *board = pcdev->pdata; - clk_disable(pcdev->clk); - - if (board && board->reset) { - dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", - __func__); - board->reset(pcdev->dev, 0); - } - - if (board && board->power) { - dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__); - board->power(pcdev->dev, 0); - } } static irqreturn_t pxa_camera_irq(int irq, void *data) diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 318754e7313..76838091dc6 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -304,9 +304,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); - if (pcdev->pdata->enable_camera) - pcdev->pdata->enable_camera(); - ret = icd->ops->init(icd); if (ret) goto err; @@ -333,8 +330,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) ceu_write(pcdev, CEIER, 0); ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ icd->ops->release(icd); - if (pcdev->pdata->disable_camera) - pcdev->pdata->disable_camera(); dev_info(&icd->dev, "SuperH Mobile CEU driver detached from camera %d\n", diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index 234a4711d2e..b5dbefea374 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h @@ -5,8 +5,6 @@ struct sh_mobile_ceu_info { unsigned long flags; /* SOCAM_... */ - void (*enable_camera)(void); - void (*disable_camera)(void); }; #endif /* __ASM_SH_MOBILE_CEU_H__ */ diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index d548de32672..c5de7bb19fd 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -83,6 +83,9 @@ struct soc_camera_link { int bus_id; /* GPIO number to switch between 8 and 10 bit modes */ unsigned int gpio; + /* Optional callbacks to power on or off and reset the sensor */ + int (*power)(struct device *, int); + int (*reset)(struct device *); }; static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) -- GitLab From e0677760945585ee475c2d6a7fa4d5b0dd573cb4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 16 Aug 2008 07:50:23 -0300 Subject: [PATCH 3984/5416] V4L/DVB (8689): dpc7146: remove dpc7146 demonstration board driver Old driver for the dpc7146 demonstration board that is no longer relevant. The last time this was tested on actual hardware was probably around 2002. Since this is a driver for a demonstration board the decision was made (after discussing this with the original author, Michael Hunold) to remove it rather than spending a lot of effort continually updating this driver to stay in sync with the latest internal V4L2 or I2C API. Signed-off-by: Hans Verkuil Signed-off-by: Michael Hunold Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 15 -- drivers/media/video/Makefile | 1 - drivers/media/video/dpc7146.c | 408 ---------------------------------- 3 files changed, 424 deletions(-) delete mode 100644 drivers/media/video/dpc7146.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 37123ff20fc..2fa7418c16d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -709,21 +709,6 @@ config VIDEO_MXB To compile this driver as a module, choose M here: the module will be called mxb. -config VIDEO_DPC - tristate "Philips-Semiconductors 'dpc7146 demonstration board'" - depends on PCI && VIDEO_V4L1 && I2C - select VIDEO_SAA7146_VV - select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO - ---help--- - This is a video4linux driver for the 'dpc7146 demonstration - board' by Philips-Semiconductors. It's the reference design - for SAA7146 bases boards, so if you have some unsupported - saa7146 based, analog video card, chances are good that it - will work with this skeleton driver. - - To compile this driver as a module, choose M here: the - module will be called dpc7146. - config VIDEO_HEXIUM_ORION tristate "Hexium HV-PCI6 and Orion frame grabber" depends on PCI && VIDEO_V4L2 && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index d234db7c4e0..012bc116957 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -84,7 +84,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o -obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c deleted file mode 100644 index 88d6df71d05..00000000000 --- a/drivers/media/video/dpc7146.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - dpc7146.c - v4l2 driver for the dpc7146 demonstration board - - Copyright (C) 2000-2003 Michael Hunold - - 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. -*/ - -#define DEBUG_VARIABLE debug - -#include -#include /* for saa7111a */ - -#define I2C_SAA7111A 0x24 - -/* All unused bytes are reserverd. */ -#define SAA711X_CHIP_VERSION 0x00 -#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 -#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 -#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 -#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 -#define SAA711X_HORIZONTAL_SYNC_START 0x06 -#define SAA711X_HORIZONTAL_SYNC_STOP 0x07 -#define SAA711X_SYNC_CONTROL 0x08 -#define SAA711X_LUMINANCE_CONTROL 0x09 -#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A -#define SAA711X_LUMINANCE_CONTRAST 0x0B -#define SAA711X_CHROMA_SATURATION 0x0C -#define SAA711X_CHROMA_HUE_CONTROL 0x0D -#define SAA711X_CHROMA_CONTROL 0x0E -#define SAA711X_FORMAT_DELAY_CONTROL 0x10 -#define SAA711X_OUTPUT_CONTROL_1 0x11 -#define SAA711X_OUTPUT_CONTROL_2 0x12 -#define SAA711X_OUTPUT_CONTROL_3 0x13 -#define SAA711X_V_GATE_1_START 0x15 -#define SAA711X_V_GATE_1_STOP 0x16 -#define SAA711X_V_GATE_1_MSB 0x17 -#define SAA711X_TEXT_SLICER_STATUS 0x1A -#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B -#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C -#define SAA711X_STATUS_BYTE 0x1F - -#define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) - -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "debug verbosity"); - -static int dpc_num; - -#define DPC_INPUTS 2 -static struct v4l2_input dpc_inputs[DPC_INPUTS] = { - { 0, "Port A", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "Port B", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, -}; - -#define DPC_AUDIOS 0 - -static struct saa7146_extension_ioctls ioctls[] = { - { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_STD, SAA7146_AFTER }, - { 0, 0 } -}; - -struct dpc -{ - struct video_device *video_dev; - struct video_device *vbi_dev; - - struct i2c_adapter i2c_adapter; - struct i2c_client *saa7111a; - - int cur_input; /* current input */ -}; - -static int dpc_check_clients(struct device *dev, void *data) -{ - struct dpc* dpc = data; - struct i2c_client *client = i2c_verify_client(dev); - - if( !client ) - return 0; - - if( I2C_SAA7111A == client->addr ) - dpc->saa7111a = client; - - return 0; -} - -/* fixme: add vbi stuff here */ -static int dpc_probe(struct saa7146_dev* dev) -{ - struct dpc* dpc = NULL; - - dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); - if( NULL == dpc ) { - printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n"); - return -ENOMEM; - } - - /* FIXME: enable i2c-port pins, video-port-pins - video port pins should be enabled here ?! */ - saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - - dpc->i2c_adapter = (struct i2c_adapter) { - .class = I2C_CLASS_TV_ANALOG, - .name = "dpc7146", - }; - saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); - if(i2c_add_adapter(&dpc->i2c_adapter) < 0) { - DEB_S(("cannot register i2c-device. skipping.\n")); - kfree(dpc); - return -EFAULT; - } - - /* loop through all i2c-devices on the bus and look who is there */ - device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients); - - /* check if all devices are present */ - if (!dpc->saa7111a) { - DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); - i2c_del_adapter(&dpc->i2c_adapter); - kfree(dpc); - return -ENODEV; - } - - /* all devices are present, probe was successful */ - DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n")); - - /* we store the pointer in our private data field */ - dev->ext_priv = dpc; - - return 0; -} - -/* bring hardware to a sane state. this has to be done, just in case someone - wants to capture from this device before it has been properly initialized. - the capture engine would badly fail, because no valid signal arrives on the - saa7146, thus leading to timeouts and stuff. */ -static int dpc_init_done(struct saa7146_dev* dev) -{ - struct dpc* dpc = (struct dpc*)dev->ext_priv; - - DEB_D(("dpc_v4l2.o: dpc_init_done called.\n")); - - /* initialize the helper ics to useful values */ - i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11); - - i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03); - - i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1); - i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30); - - i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81); - - return 0; -} - -static struct saa7146_ext_vv vv_data; - -/* this function only gets called when the probing was successful */ -static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) -{ - struct dpc* dpc = (struct dpc*)dev->ext_priv; - - DEB_D(("dpc_v4l2.o: dpc_attach called.\n")); - - /* checking for i2c-devices can be omitted here, because we - already did this in "dpc_vl42_probe" */ - - saa7146_vv_init(dev,&vv_data); - if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) { - ERR(("cannot register capture v4l2 device. skipping.\n")); - return -1; - } - - /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ - if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { - if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) { - ERR(("cannot register vbi v4l2 device. skipping.\n")); - } - } - - i2c_use_client(dpc->saa7111a); - - printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num); - dpc_num++; - - /* the rest */ - dpc->cur_input = 0; - dpc_init_done(dev); - - return 0; -} - -static int dpc_detach(struct saa7146_dev* dev) -{ - struct dpc* dpc = (struct dpc*)dev->ext_priv; - - DEB_EE(("dev:%p\n",dev)); - - i2c_release_client(dpc->saa7111a); - - saa7146_unregister_device(&dpc->video_dev,dev); - if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { - saa7146_unregister_device(&dpc->vbi_dev,dev); - } - saa7146_vv_release(dev); - - dpc_num--; - - i2c_del_adapter(&dpc->i2c_adapter); - kfree(dpc); - return 0; -} - -#ifdef axa -int dpc_vbi_bypass(struct saa7146_dev* dev) -{ - struct dpc* dpc = (struct dpc*)dev->ext_priv; - - int i = 1; - - /* switch bypass in saa7111a */ - if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) { - printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n"); - return -1; - } - - return 0; -} -#endif - -static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) -{ - struct saa7146_dev *dev = fh->dev; - struct dpc* dpc = (struct dpc*)dev->ext_priv; -/* - struct saa7146_vv *vv = dev->vv_data; -*/ - switch(cmd) - { - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); - - if( i->index < 0 || i->index >= DPC_INPUTS) { - return -EINVAL; - } - - memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input)); - - DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index)); - return 0; - } - case VIDIOC_G_INPUT: - { - int *input = (int *)arg; - *input = dpc->cur_input; - - DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input)); - return 0; - } - case VIDIOC_S_INPUT: - { - int input = *(int *)arg; - - if (input < 0 || input >= DPC_INPUTS) { - return -EINVAL; - } - - dpc->cur_input = input; - - /* fixme: switch input here, switch audio, too! */ -// saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); - printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n"); - - return 0; - } - default: -/* - DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n")); -*/ - return -ENOIOCTLCMD; - } - return 0; -} - -static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) -{ - return 0; -} - -static struct saa7146_standard standard[] = { - { - .name = "PAL", .id = V4L2_STD_PAL, - .v_offset = 0x17, .v_field = 288, - .h_offset = 0x14, .h_pixels = 680, - .v_max_out = 576, .h_max_out = 768, - }, { - .name = "NTSC", .id = V4L2_STD_NTSC, - .v_offset = 0x16, .v_field = 240, - .h_offset = 0x06, .h_pixels = 708, - .v_max_out = 480, .h_max_out = 640, - }, { - .name = "SECAM", .id = V4L2_STD_SECAM, - .v_offset = 0x14, .v_field = 288, - .h_offset = 0x14, .h_pixels = 720, - .v_max_out = 576, .h_max_out = 768, - } -}; - -static struct saa7146_extension extension; - -static struct saa7146_pci_extension_data dpc = { - .ext_priv = "Multimedia eXtension Board", - .ext = &extension, -}; - -static struct pci_device_id pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x0000, - .subdevice = 0x0000, - .driver_data = (unsigned long)&dpc, - }, { - .vendor = 0, - } -}; - -MODULE_DEVICE_TABLE(pci, pci_tbl); - -static struct saa7146_ext_vv vv_data = { - .inputs = DPC_INPUTS, - .capabilities = V4L2_CAP_VBI_CAPTURE, - .stds = &standard[0], - .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = dpc_ioctl, -}; - -static struct saa7146_extension extension = { - .name = "dpc7146 demonstration board", - .flags = SAA7146_USE_I2C_IRQ, - - .pci_tbl = &pci_tbl[0], - .module = THIS_MODULE, - - .probe = dpc_probe, - .attach = dpc_attach, - .detach = dpc_detach, - - .irq_mask = 0, - .irq_func = NULL, -}; - -static int __init dpc_init_module(void) -{ - if( 0 != saa7146_register_extension(&extension)) { - DEB_S(("failed to register extension.\n")); - return -ENODEV; - } - - return 0; -} - -static void __exit dpc_cleanup_module(void) -{ - saa7146_unregister_extension(&extension); -} - -module_init(dpc_init_module); -module_exit(dpc_cleanup_module); - -MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'"); -MODULE_AUTHOR("Michael Hunold "); -MODULE_LICENSE("GPL"); -- GitLab From 45a5b872bda1a3b5a4959ce66d19381df82419c9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 16 Aug 2008 07:56:12 -0300 Subject: [PATCH 3985/5416] V4L/DVB (8690): tuner-3036: remove driver This driver is for VERY old i2c-over-parallel port teletext receiver boxes. Rather then spending effort on converting this driver to V4L2, and since it is extremely unlikely that anyone still uses one of these devices, it was decided to drop it (after discussing this as well with the original author, Phil Blundell). Signed-off-by: Hans Verkuil Signed-off-by: Phil Blundell Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 7 - drivers/media/video/Makefile | 1 - drivers/media/video/tuner-3036.c | 214 ------------------------------- 3 files changed, 222 deletions(-) delete mode 100644 drivers/media/video/tuner-3036.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2fa7418c16d..7f7482bff14 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -579,13 +579,6 @@ config VIDEO_SAA5249 To compile this driver as a module, choose M here: the module will be called saa5249. -config TUNER_3036 - tristate "SAB3036 tuner" - depends on I2C && VIDEO_V4L1 - help - Say Y here to include support for Philips SAB3036 compatible tuners. - If in doubt, say N. - config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 012bc116957..28e32572530 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -84,7 +84,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o -obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c deleted file mode 100644 index bdf506e6ae2..00000000000 --- a/drivers/media/video/tuner-3036.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Driver for Philips SAB3036 "CITAC" tuner control chip. - * - * Author: Phil Blundell - * - * The SAB3036 is just about different enough from the chips that - * tuner.c copes with to make it not worth the effort to crowbar - * the support into that file. So instead we have a separate 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -static int debug; /* insmod parameter */ -static int this_adap; - -static struct i2c_client client_template; - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END }; -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; - -/* ---------------------------------------------------------------------- */ - -static unsigned char -tuner_getstatus (struct i2c_client *c) -{ - unsigned char byte; - if (i2c_master_recv(c, &byte, 1) != 1) - printk(KERN_ERR "tuner-3036: I/O error.\n"); - return byte; -} - -#define TUNER_FL 0x80 - -static int -tuner_islocked (struct i2c_client *c) -{ - return (tuner_getstatus(c) & TUNER_FL); -} - -/* ---------------------------------------------------------------------- */ - -static void -set_tv_freq(struct i2c_client *c, int freq) -{ - u16 div = ((freq * 20) / 16); - unsigned long give_up = jiffies + HZ; - unsigned char buffer[2]; - - if (debug) - printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div); - - /* Select high tuning current */ - buffer[0] = 0x29; - buffer[1] = 0x3e; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 1\n"); - - buffer[0] = 0x80 | ((div>>8) & 0x7f); - buffer[1] = div & 0xff; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 2\n"); - - while (!tuner_islocked(c) && time_before(jiffies, give_up)) - schedule(); - - if (!tuner_islocked(c)) - printk(KERN_WARNING "tuner: failed to achieve PLL lock\n"); - - /* Select low tuning current and engage AFC */ - buffer[0] = 0x29; - buffer[1] = 0xb2; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 3\n"); - - if (debug) - printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c)); -} - -/* ---------------------------------------------------------------------- */ - -static int -tuner_attach(struct i2c_adapter *adap, int addr, int kind) -{ - static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 }; - - struct i2c_client *client; - - if (this_adap > 0) - return -1; - this_adap++; - - client_template.adapter = adap; - client_template.addr = addr; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &client_template, sizeof(struct i2c_client)); - - printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client)); - - i2c_attach_client(client); - - if (i2c_master_send(client, buffer, 2) != 2) - printk("tuner: i2c i/o error 1\n"); - if (i2c_master_send(client, buffer+2, 2) != 2) - printk("tuner: i2c i/o error 2\n"); - if (i2c_master_send(client, buffer+4, 2) != 2) - printk("tuner: i2c i/o error 3\n"); - return 0; -} - -static int -tuner_detach(struct i2c_client *c) -{ - return 0; -} - -static int -tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - int *iarg = (int*)arg; - - switch (cmd) - { - case VIDIOCSFREQ: - set_tv_freq(client, *iarg); - break; - - default: - return -EINVAL; - } - return 0; -} - -static int -tuner_probe(struct i2c_adapter *adap) -{ - this_adap = 0; - if (adap->id == I2C_HW_B_LP) - return i2c_probe(adap, &addr_data, tuner_attach); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver -i2c_driver_tuner = -{ - .driver = { - .name = "sab3036", - }, - .id = I2C_DRIVERID_SAB3036, - .attach_adapter = tuner_probe, - .detach_client = tuner_detach, - .command = tuner_command -}; - -static struct i2c_client client_template = -{ - .driver = &i2c_driver_tuner, - .name = "SAB3036", -}; - -static int __init -tuner3036_init(void) -{ - return i2c_add_driver(&i2c_driver_tuner); -} - -static void __exit -tuner3036_exit(void) -{ - i2c_del_driver(&i2c_driver_tuner); -} - -MODULE_DESCRIPTION("SAB3036 tuner driver"); -MODULE_AUTHOR("Philip Blundell "); -MODULE_LICENSE("GPL"); - -module_param(debug, int, 0); -MODULE_PARM_DESC(debug,"Enable debugging output"); - -module_init(tuner3036_init); -module_exit(tuner3036_exit); -- GitLab From 66c6bda79fdc273608e2700a0c6dd4cb82d0bac3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 16 Aug 2008 08:33:14 -0300 Subject: [PATCH 3986/5416] V4L/DVB (8691): i2c-id: remove obsolete SAB3036 driver ID Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/linux/i2c-id.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index bf34c5f4c05..493435bcdbe 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -41,7 +41,6 @@ #define I2C_DRIVERID_SAA7110 22 /* video decoder */ #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ #define I2C_DRIVERID_PCF8583 25 /* real time clock */ -#define I2C_DRIVERID_SAB3036 26 /* SAB3036 tuner */ #define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ #define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ #define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ -- GitLab From e758c6f86bc53009893dfa517b9bb3a408d7a2e2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 18 Aug 2008 04:48:42 -0300 Subject: [PATCH 3987/5416] V4L/DVB (8695): usbvideo: add proper error check and add release function Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/usbvideo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index bf1bc2f69b0..6b1b2003a65 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1006,6 +1006,10 @@ allocate_done: EXPORT_SYMBOL(usbvideo_AllocateDevice); +static void usbvideo_dummy_release(struct video_device *vfd) +{ +} + int usbvideo_RegisterVideoDevice(struct uvd *uvd) { char tmp1[20], tmp2[20]; /* Buffers for printing */ @@ -1039,7 +1043,8 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) return -EINVAL; } uvd->vdev.parent = &uvd->dev->dev; - if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + uvd->vdev.release = usbvideo_dummy_release; + if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { err("%s: video_register_device failed", __func__); return -EPIPE; } -- GitLab From 06a3f58496462f25cc031d1cb6d49cb78af1f636 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 19 Aug 2008 20:40:30 -0300 Subject: [PATCH 3988/5416] V4L/DVB (8724): dvb: drx397xD: checkpatch.pl cleanups This driver sure needs some rework. For now, let's try to clean it up a bit before start reimplementing anything. checkpatch.pl still not happy with this driver after this patch, but the most annoying errors are gone, comments now use C-style only, labels are well placed and some other minor fixes. Some more clean up patches will come as I work on this driver. Please review it carefully. Cc: Mauro Carvalho Chehab Cc: Henk Vergonet [mchehab@infradead.org: Manually fixed some conflicts with a previous patch] Signed-off-by: Felipe Balbi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drx397xD.c | 242 +++++++++++++------------ 1 file changed, 124 insertions(+), 118 deletions(-) diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index e19147bad17..77dd4f2c626 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -38,35 +38,32 @@ static const char mod_name[] = "drx397xD"; #define F_SET_0D0h 1 #define F_SET_0D4h 2 -typedef enum fw_ix { +enum fw_ix { #define _FW_ENTRY(a, b) b #include "drx397xD_fw.h" -} fw_ix_t; +}; /* chip specifics */ struct drx397xD_state { struct i2c_adapter *i2c; struct dvb_frontend frontend; struct drx397xD_config config; - fw_ix_t chip_rev; + enum fw_ix chip_rev; int flags; u32 bandwidth_parm; /* internal bandwidth conversions */ u32 f_osc; /* w90: actual osc frequency [Hz] */ }; -/******************************************************************************* - * Firmware - ******************************************************************************/ - +/* Firmware */ static const char *blob_name[] = { #define _BLOB_ENTRY(a, b) a #include "drx397xD_fw.h" }; -typedef enum blob_ix { +enum blob_ix { #define _BLOB_ENTRY(a, b) b #include "drx397xD_fw.h" -} blob_ix_t; +}; static struct { const char *name; @@ -85,7 +82,7 @@ static struct { }; /* use only with writer lock aquired */ -static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix) +static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix) { memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); if (fw[ix].file) @@ -94,7 +91,7 @@ static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix) static void drx_release_fw(struct drx397xD_state *s) { - fw_ix_t ix = s->chip_rev; + enum fw_ix ix = s->chip_rev; pr_debug("%s\n", __func__); @@ -107,7 +104,7 @@ static void drx_release_fw(struct drx397xD_state *s) write_unlock(&fw[ix].lock); } -static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix) +static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) { const u8 *data; size_t size, len; @@ -175,26 +172,28 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix) goto exit_corrupt; } } while (i < size); - exit_corrupt: + +exit_corrupt: printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name); - exit_err: +exit_err: _drx_release_fw(s, ix); fw[ix].refcnt--; - exit_ok: +exit_ok: fw[ix].refcnt++; write_unlock(&fw[ix].lock); + return rc; } -/******************************************************************************* - * i2c bus IO - ******************************************************************************/ - -static int write_fw(struct drx397xD_state *s, blob_ix_t ix) +/* i2c bus IO */ +static int write_fw(struct drx397xD_state *s, enum blob_ix ix) { - struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 }; const u8 *data; int len, rc = 0, i = 0; + struct i2c_msg msg = { + .addr = s->config.demod_address, + .flags = 0 + }; if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { pr_debug("%s drx_fw_ix_t out of range\n", __func__); @@ -229,8 +228,9 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix) goto exit_rc; } } - exit_rc: +exit_rc: read_unlock(&fw[s->chip_rev].lock); + return 0; } @@ -242,17 +242,16 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr) u16 v; struct i2c_msg msg[2] = { { - .addr = s->config.demod_address, - .flags = 0, - .buf = a, - .len = sizeof(a) - } - , { - .addr = s->config.demod_address, - .flags = I2C_M_RD, - .buf = (u8 *) & v, - .len = sizeof(v) - } + .addr = s->config.demod_address, + .flags = 0, + .buf = a, + .len = sizeof(a) + }, { + .addr = s->config.demod_address, + .flags = I2C_M_RD, + .buf = (u8 *) &v, + .len = sizeof(v) + } }; *(u32 *) a = i2c_adr; @@ -277,27 +276,27 @@ static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val) }; *(u32 *) a = i2c_adr; - *(u16 *) & a[4] = val; + *(u16 *) &a[4] = val; rc = i2c_transfer(s->i2c, &msg, 1); if (rc != 1) return -EIO; + return 0; } -#define WR16(ss,adr, val) \ +#define WR16(ss, adr, val) \ _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val)) -#define WR16_E0(ss,adr, val) \ +#define WR16_E0(ss, adr, val) \ _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val)) -#define RD16(ss,adr) \ +#define RD16(ss, adr) \ _read16(ss, I2C_ADR_C0(adr)) -#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc - -/******************************************************************************* - * Tuner callback - ******************************************************************************/ +#define EXIT_RC(cmd) \ + if ((rc = (cmd)) < 0) \ + goto exit_rc +/* Tuner callback */ static int PLL_Set(struct drx397xD_state *s, struct dvb_frontend_parameters *fep, int *df_tuner) { @@ -331,10 +330,7 @@ static int PLL_Set(struct drx397xD_state *s, return 0; } -/******************************************************************************* - * Demodulator helper functions - ******************************************************************************/ - +/* Demodulator helper functions */ static int SC_WaitForReady(struct drx397xD_state *s) { int cnt = 1000; @@ -347,6 +343,7 @@ static int SC_WaitForReady(struct drx397xD_state *s) if (rc == 0) return 0; } + return -1; } @@ -361,6 +358,7 @@ static int SC_SendCommand(struct drx397xD_state *s, int cmd) rc = RD16(s, 0x820042); if ((rc & 0xffff) == 0xffff) return -1; + return 0; } @@ -383,6 +381,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd) if (rc < 0) return rc; } while (--cnt); + return rc; } @@ -392,13 +391,14 @@ static int HI_CfgCommand(struct drx397xD_state *s) pr_debug("%s\n", __func__); WR16(s, 0x420033, 0x3973); - WR16(s, 0x420034, s->config.w50); // code 4, log 4 - WR16(s, 0x420035, s->config.w52); // code 15, log 9 + WR16(s, 0x420034, s->config.w50); /* code 4, log 4 */ + WR16(s, 0x420035, s->config.w52); /* code 15, log 9 */ WR16(s, 0x420036, s->config.demod_address << 1); - WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1 -// WR16(s, 0x420033, 0x3973); + WR16(s, 0x420037, s->config.w56); /* code (set_i2c ?? initX 1 ), log 1 */ + /* WR16(s, 0x420033, 0x3973); */ if ((s->config.w56 & 8) == 0) return HI_Command(s, 3); + return WR16(s, 0x420032, 0x3); } @@ -468,7 +468,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) i = slowIncrDecLUT_15272[rem / 28]; EXIT_RC(WR16(s, 0x0c2002b, i)); rc = WR16(s, 0x0c2002c, i); - exit_rc: +exit_rc: return rc; } @@ -498,7 +498,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) rc &= ~2; break; case 0: - // loc_8000659 + /* loc_8000659 */ s->config.w9C &= ~2; EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); EXIT_RC(RD16(s, 0x0c20010)); @@ -522,7 +522,8 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) rc |= 2; } rc = WR16(s, 0x0c20013, rc); - exit_rc: + +exit_rc: return rc; } @@ -602,7 +603,8 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s) s->config.f_osc * 1000, clk - s->config.f_osc * 1000); } rc = WR16(s, 0x08200e8, 0); - exit_rc: + +exit_rc: return rc; } @@ -620,17 +622,17 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) si &= ~1; bp = 0x200; } - if (s->config.w9A == 0) { + if (s->config.w9A == 0) si |= 0x80; - } else { + else si &= ~0x80; - } EXIT_RC(WR16(s, 0x2150045, 0)); EXIT_RC(WR16(s, 0x2150010, si)); EXIT_RC(WR16(s, 0x2150011, bp)); rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0)); - exit_rc: + +exit_rc: return rc; } @@ -658,7 +660,7 @@ static int drx_tune(struct drx397xD_state *s, rc = ConfigureMPEGOutput(s, 0); if (rc < 0) goto set_tuner; - set_tuner: +set_tuner: rc = PLL_Set(s, fep, &df_tuner); if (rc < 0) { @@ -835,16 +837,16 @@ static int drx_tune(struct drx397xD_state *s, rc = WR16(s, 0x2010012, 0); if (rc < 0) goto exit_rc; - // QPSK QAM16 QAM64 - ebx = 0x19f; // 62 - ebp = 0x1fb; // 15 - v20 = 0x16a; // 62 - v1E = 0x195; // 62 - v16 = 0x1bb; // 15 - v14 = 0x1ef; // 15 - v12 = 5; // 16 - v10 = 5; // 16 - v0E = 5; // 16 + /* QPSK QAM16 QAM64 */ + ebx = 0x19f; /* 62 */ + ebp = 0x1fb; /* 15 */ + v20 = 0x16a; /* 62 */ + v1E = 0x195; /* 62 */ + v16 = 0x1bb; /* 15 */ + v14 = 0x1ef; /* 15 */ + v12 = 5; /* 16 */ + v10 = 5; /* 16 */ + v0E = 5; /* 16 */ } switch (fep->u.ofdm.constellation) { @@ -997,17 +999,17 @@ static int drx_tune(struct drx397xD_state *s, case BANDWIDTH_8_MHZ: /* 0 */ case BANDWIDTH_AUTO: rc = WR16(s, 0x0c2003f, 0x32); - s->bandwidth_parm = ebx = 0x8b8249; // 9142857 + s->bandwidth_parm = ebx = 0x8b8249; edx = 0; break; case BANDWIDTH_7_MHZ: rc = WR16(s, 0x0c2003f, 0x3b); - s->bandwidth_parm = ebx = 0x7a1200; // 8000000 + s->bandwidth_parm = ebx = 0x7a1200; edx = 0x4807; break; case BANDWIDTH_6_MHZ: rc = WR16(s, 0x0c2003f, 0x47); - s->bandwidth_parm = ebx = 0x68a1b6; // 6857142 + s->bandwidth_parm = ebx = 0x68a1b6; edx = 0x0f07; break; }; @@ -1060,8 +1062,6 @@ static int drx_tune(struct drx397xD_state *s, WR16(s, 0x0820040, 1); SC_SendCommand(s, 1); -// rc = WR16(s, 0x2150000, 1); -// if (rc < 0) goto exit_rc; rc = WR16(s, 0x2150000, 2); rc = WR16(s, 0x2150016, a); @@ -1069,7 +1069,8 @@ static int drx_tune(struct drx397xD_state *s, rc = WR16(s, 0x2150036, 0); rc = WR16(s, 0x2150000, 1); s->config.d60 = 2; - exit_rc: + +exit_rc: return rc; } @@ -1102,18 +1103,18 @@ static int drx397x_init(struct dvb_frontend *fe) /* HI_CfgCommand */ s->config.w50 = 4; - s->config.w52 = 9; // 0xf; + s->config.w52 = 9; - s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ - s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ - s->config.w92 = 12000; // 20000; + s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ + s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ + s->config.w92 = 12000; s->config.w9C = 0x000e; s->config.w9E = 0x0000; /* ConfigureMPEGOutput params */ s->config.wA0 = 4; - s->config.w98 = 1; // 0; + s->config.w98 = 1; s->config.w9A = 1; /* get chip revision */ @@ -1248,7 +1249,7 @@ static int drx397x_init(struct dvb_frontend *fe) rc = WR16(s, 0x0c20012, 1); } - write_DRXD_InitFE_1: +write_DRXD_InitFE_1: rc = write_fw(s, DRXD_InitFE_1); if (rc < 0) @@ -1311,7 +1312,8 @@ static int drx397x_init(struct dvb_frontend *fe) s->config.d5C = 0; s->config.d60 = 1; s->config.d48 = 1; - error: + +error: return rc; } @@ -1326,7 +1328,8 @@ static int drx397x_set_frontend(struct dvb_frontend *fe, { struct drx397xD_state *s = fe->demodulator_priv; - s->config.s20d24 = 1; // 0; + s->config.s20d24 = 1; + return drx_tune(s, params); } @@ -1337,18 +1340,16 @@ static int drx397x_get_tune_settings(struct dvb_frontend *fe, fe_tune_settings->min_delay_ms = 10000; fe_tune_settings->step_size = 0; fe_tune_settings->max_drift = 0; + return 0; } -static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) +static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct drx397xD_state *s = fe->demodulator_priv; int lockstat; GetLockStatus(s, &lockstat); - /* TODO */ -// if (lockstat & 1) -// CorrectSysClockDeviation(s); *status = 0; if (lockstat & 2) { @@ -1356,9 +1357,8 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) ConfigureMPEGOutput(s, 1); *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; } - if (lockstat & 4) { + if (lockstat & 4) *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; - } return 0; } @@ -1366,16 +1366,18 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber) { *ber = 0; + return 0; } -static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr) +static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr) { *snr = 0; + return 0; } -static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength) +static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct drx397xD_state *s = fe->demodulator_priv; int rc; @@ -1401,6 +1403,7 @@ static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength) * The following does the same but with less rounding errors: */ *strength = ~(7720 + (rc * 30744 >> 10)); + return 0; } @@ -1408,6 +1411,7 @@ static int drx397x_read_ucblocks(struct dvb_frontend *fe, unsigned int *ucblocks) { *ucblocks = 0; + return 0; } @@ -1436,22 +1440,22 @@ static struct dvb_frontend_ops drx397x_ops = { .frequency_max = 855250000, .frequency_stepsize = 166667, .frequency_tolerance = 0, - .caps = /* 0x0C01B2EAE */ - FE_CAN_FEC_1_2 | // = 0x2, - FE_CAN_FEC_2_3 | // = 0x4, - FE_CAN_FEC_3_4 | // = 0x8, - FE_CAN_FEC_5_6 | // = 0x20, - FE_CAN_FEC_7_8 | // = 0x80, - FE_CAN_FEC_AUTO | // = 0x200, - FE_CAN_QPSK | // = 0x400, - FE_CAN_QAM_16 | // = 0x800, - FE_CAN_QAM_64 | // = 0x2000, - FE_CAN_QAM_AUTO | // = 0x10000, - FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000, - FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000, - FE_CAN_HIERARCHY_AUTO | // = 0x100000, - FE_CAN_RECOVER | // = 0x40000000, - FE_CAN_MUTE_TS // = 0x80000000 + .caps = /* 0x0C01B2EAE */ + FE_CAN_FEC_1_2 | /* = 0x2, */ + FE_CAN_FEC_2_3 | /* = 0x4, */ + FE_CAN_FEC_3_4 | /* = 0x8, */ + FE_CAN_FEC_5_6 | /* = 0x20, */ + FE_CAN_FEC_7_8 | /* = 0x80, */ + FE_CAN_FEC_AUTO | /* = 0x200, */ + FE_CAN_QPSK | /* = 0x400, */ + FE_CAN_QAM_16 | /* = 0x800, */ + FE_CAN_QAM_64 | /* = 0x2000, */ + FE_CAN_QAM_AUTO | /* = 0x10000, */ + FE_CAN_TRANSMISSION_MODE_AUTO | /* = 0x20000, */ + FE_CAN_GUARD_INTERVAL_AUTO | /* = 0x80000, */ + FE_CAN_HIERARCHY_AUTO | /* = 0x100000, */ + FE_CAN_RECOVER | /* = 0x40000000, */ + FE_CAN_MUTE_TS /* = 0x80000000 */ }, .release = drx397x_release, @@ -1472,33 +1476,35 @@ static struct dvb_frontend_ops drx397x_ops = { struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, struct i2c_adapter *i2c) { - struct drx397xD_state *s = NULL; + struct drx397xD_state *state; /* allocate memory for the internal state */ - s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); - if (s == NULL) + state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); + if (!state) goto error; /* setup the state */ - s->i2c = i2c; - memcpy(&s->config, config, sizeof(struct drx397xD_config)); + state->i2c = i2c; + memcpy(&state->config, config, sizeof(struct drx397xD_config)); /* check if the demod is there */ if (RD16(s, 0x2410019) < 0) goto error; /* create dvb_frontend */ - memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops)); - s->frontend.demodulator_priv = s; + memcpy(&state->frontend.ops, &drx397x_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = s; + + return &state->frontend; +error: + kfree(state); - return &s->frontend; - error: - kfree(s); return NULL; } +EXPORT_SYMBOL(drx397xD_attach); MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend"); MODULE_AUTHOR("Henk Vergonet"); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(drx397xD_attach); -- GitLab From 95908ece60443ceb188fccf021d62823de8e6f0c Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 20 Aug 2008 20:44:50 -0300 Subject: [PATCH 3989/5416] V4L/DVB (8725): drx397xD.c sparse annotations Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drx397xD.c | 14 +++++++------- drivers/media/dvb/frontends/drx397xD.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index 77dd4f2c626..0cf3af2f7da 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -235,11 +235,11 @@ exit_rc: } /* Function is not endian safe, use the RD16 wrapper below */ -static int _read16(struct drx397xD_state *s, u32 i2c_adr) +static int _read16(struct drx397xD_state *s, __le32 i2c_adr) { int rc; u8 a[4]; - u16 v; + __le16 v; struct i2c_msg msg[2] = { { .addr = s->config.demod_address, @@ -249,12 +249,12 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr) }, { .addr = s->config.demod_address, .flags = I2C_M_RD, - .buf = (u8 *) &v, + .buf = (u8 *)&v, .len = sizeof(v) } }; - *(u32 *) a = i2c_adr; + *(__le32 *) a = i2c_adr; rc = i2c_transfer(s->i2c, msg, 2); if (rc != 2) @@ -264,7 +264,7 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr) } /* Function is not endian safe, use the WR16.. wrappers below */ -static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val) +static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val) { u8 a[6]; int rc; @@ -275,8 +275,8 @@ static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val) .len = sizeof(a) }; - *(u32 *) a = i2c_adr; - *(u16 *) &a[4] = val; + *(__le32 *)a = i2c_adr; + *(__le16 *)&a[4] = val; rc = i2c_transfer(s->i2c, &msg, 1); if (rc != 1) diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h index 2ad1ea0ccfb..ba05d17290c 100644 --- a/drivers/media/dvb/frontends/drx397xD.h +++ b/drivers/media/dvb/frontends/drx397xD.h @@ -28,7 +28,7 @@ #define DRX_F_OFFSET 36000000 #define I2C_ADR_C0(x) \ -( (u32)cpu_to_le32( \ +( cpu_to_le32( \ (u32)( \ (((u32)(x) & (u32)0x000000ffUL) ) | \ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ @@ -38,7 +38,7 @@ ) #define I2C_ADR_E0(x) \ -( (u32)cpu_to_le32( \ +( cpu_to_le32( \ (u32)( \ (((u32)(x) & (u32)0x000000ffUL) ) | \ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ -- GitLab From e9e24cee67bf71b929b646387f286e907cbde5fc Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 20 Aug 2008 20:44:53 -0300 Subject: [PATCH 3990/5416] V4L/DVB (8729): Use DIV_ROUND_UP The kernel.h macro DIV_ROUND_UP performs the computation (((n) + (d) - 1) / (d)) but is perhaps more readable. An extract of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ @depends on haskernel@ expression n,d; @@ ( - (n + d - 1) / d + DIV_ROUND_UP(n,d) | - (n + (d - 1)) / d + DIV_ROUND_UP(n,d) ) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP((n),d) + DIV_ROUND_UP(n,d) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP(n,(d)) + DIV_ROUND_UP(n,d) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bw-qcam.c | 4 ++-- drivers/media/video/uvc/uvc_video.c | 2 +- drivers/media/video/zoran_device.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 6e39e253ce5..01f07707827 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -495,7 +495,7 @@ static void qc_set(struct qcam_device *q) val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * q->transfer_scale; } - val = (val + val2 - 1) / val2; + val = DIV_ROUND_UP(val, val2); qc_command(q, 0x13); qc_command(q, val); @@ -651,7 +651,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l transperline = q->width * q->bpp; divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * q->transfer_scale; - transperline = (transperline + divisor - 1) / divisor; + transperline = DIV_ROUND_UP(transperline, divisor); for (i = 0, yield = yieldlines; i < linestotrans; i++) { diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 6854ac78a16..03dc3a519e4 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -655,7 +655,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, if (size > UVC_MAX_FRAME_SIZE) return -EINVAL; - npackets = (size + psize - 1) / psize; + npackets = DIV_ROUND_UP(size, psize); if (npackets > UVC_MAX_ISO_PACKETS) npackets = UVC_MAX_ISO_PACKETS; diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 88d369708e4..2b3ca149337 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -377,7 +377,7 @@ zr36057_set_vfe (struct zoran *zr, /* horizontal */ VidWinWid = video_width; - X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; + X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa); We = (VidWinWid * 64) / X; HorDcm = 64 - X; hcrop1 = 2 * ((tvn->Wa - We) / 4); @@ -403,7 +403,7 @@ zr36057_set_vfe (struct zoran *zr, /* Vertical */ DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); VidWinHt = DispMode ? video_height : video_height / 2; - Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; + Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha); He = (VidWinHt * 64) / Y; VerDcm = 64 - Y; vcrop1 = (tvn->Ha / 2 - He) / 2; -- GitLab From 06fcadbf8b63e395d3ae8421a8c3cb2dfd0bc56b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 22 Aug 2008 13:31:59 -0300 Subject: [PATCH 3991/5416] V4L/DVB (8730): drx397xD: fix compilation error caused by changeset 71046dfb0853 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drx397xD.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index 0cf3af2f7da..b9ca5c8d2dd 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -1488,13 +1488,13 @@ struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, memcpy(&state->config, config, sizeof(struct drx397xD_config)); /* check if the demod is there */ - if (RD16(s, 0x2410019) < 0) + if (RD16(state, 0x2410019) < 0) goto error; /* create dvb_frontend */ memcpy(&state->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = s; + state->frontend.demodulator_priv = state; return &state->frontend; error: -- GitLab From 69025c934b21a9ce49a76dfef59f1ebdfbe96c78 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 18 Aug 2008 17:09:53 -0300 Subject: [PATCH 3992/5416] V4L/DVB (8731): zr364xx: remove BKL Remove the Big Kernel Lock from zr364xx driver after pushdown. Now using an internal locking mecanism on open(). Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zr364xx.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 4e1ef10d22d..9d5d5985a7e 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -641,25 +641,23 @@ static int zr364xx_open(struct inode *inode, struct file *file) DBG("zr364xx_open"); + mutex_lock(&cam->lock); + cam->skip = 2; - lock_kernel(); err = video_exclusive_open(inode, file); - if (err < 0) { - unlock_kernel(); - return err; - } + if (err < 0) + goto out; if (!cam->framebuf) { cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); if (!cam->framebuf) { info("vmalloc_32 failed!"); - unlock_kernel(); - return -ENOMEM; + err = -ENOMEM; + goto out; } } - mutex_lock(&cam->lock); for (i = 0; init[cam->method][i].size != -1; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, @@ -667,9 +665,7 @@ static int zr364xx_open(struct inode *inode, struct file *file) init[cam->method][i].size); if (err < 0) { info("error during open sequence: %d", i); - mutex_unlock(&cam->lock); - unlock_kernel(); - return err; + goto out; } } @@ -679,10 +675,11 @@ static int zr364xx_open(struct inode *inode, struct file *file) * like Ekiga does during its startup, can crash the webcam */ mdelay(100); + err = 0; +out: mutex_unlock(&cam->lock); - unlock_kernel(); - return 0; + return err; } -- GitLab From 33d27a45165ae9c3551e8d7c1186a5583371e5c4 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 18 Aug 2008 17:14:30 -0300 Subject: [PATCH 3993/5416] V4L/DVB (8732): zr364xx: handle video exclusive open internaly Count the users and do not use video_exclusive_open() anymore. Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zr364xx.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 9d5d5985a7e..93991cb9ca7 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -116,6 +116,7 @@ struct zr364xx_camera { int height; int method; struct mutex lock; + int users; }; @@ -643,11 +644,10 @@ static int zr364xx_open(struct inode *inode, struct file *file) mutex_lock(&cam->lock); - cam->skip = 2; - - err = video_exclusive_open(inode, file); - if (err < 0) + if (cam->users) { + err = -EBUSY; goto out; + } if (!cam->framebuf) { cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); @@ -669,6 +669,8 @@ static int zr364xx_open(struct inode *inode, struct file *file) } } + cam->skip = 2; + cam->users++; file->private_data = vdev; /* Added some delay here, since opening/closing the camera quickly, @@ -700,6 +702,10 @@ static int zr364xx_release(struct inode *inode, struct file *file) udev = cam->udev; mutex_lock(&cam->lock); + + cam->users--; + file->private_data = NULL; + for (i = 0; i < 2; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, @@ -707,21 +713,19 @@ static int zr364xx_release(struct inode *inode, struct file *file) init[cam->method][i].size); if (err < 0) { info("error during release sequence"); - mutex_unlock(&cam->lock); - return err; + goto out; } } - file->private_data = NULL; - video_exclusive_release(inode, file); - /* Added some delay here, since opening/closing the camera quickly, * like Ekiga does during its startup, can crash the webcam */ mdelay(100); + err = 0; +out: mutex_unlock(&cam->lock); - return 0; + return err; } -- GitLab From 8466028be7926679ff794ec2ed7a8938eafba521 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 11 Aug 2008 13:12:19 -0300 Subject: [PATCH 3994/5416] V4L/DVB (8734): Initial support for AME DTV-5100 USB2.0 DVB-T Basic support for AME DTV-5100 USB2.0 DVB-T using the qt1010 tuner and a dummy frontend. Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 7 + drivers/media/dvb/dvb-usb/Makefile | 3 + drivers/media/dvb/dvb-usb/dtv5100-fe.c | 147 +++++++++++++++++ drivers/media/dvb/dvb-usb/dtv5100.c | 217 +++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/dtv5100.h | 128 +++++++++++++++ 5 files changed, 502 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/dtv5100-fe.c create mode 100644 drivers/media/dvb/dvb-usb/dtv5100.c create mode 100644 drivers/media/dvb/dvb-usb/dtv5100.h diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 8a54cb48322..1d9e98cee9e 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -264,3 +264,10 @@ config DVB_USB_ANYSEE help Say Y here to support the Anysee E30, Anysee E30 Plus or Anysee E30 C Plus DVB USB2.0 receiver. + +config DVB_USB_DTV5100 + tristate "AME DTV-5100 USB2.0 DVB-T support" + depends on DVB_USB + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + help + Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e206f1ea002..5e170fba109 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -67,6 +67,9 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o dvb-usb-dw2102-objs = dw2102.o obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o +dvb-usb-dtv5100-objs = dtv5100.o dtv5100-fe.o +obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dvb-usb/dtv5100-fe.c b/drivers/media/dvb/dvb-usb/dtv5100-fe.c new file mode 100644 index 00000000000..08fe33bcc5d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100-fe.c @@ -0,0 +1,147 @@ +/* + * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T + * + * Copyright (C) 2008 Antoine Jacquet + * http://royale.zerezo.com/dtv5100/ + * + * Inspired by dvb_dummy_fe.c + * + * 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 "dvb-usb.h" +#include "qt1010_priv.h" + +struct dtv5100_fe_state { + struct dvb_frontend frontend; +}; + +static int dtv5100_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + *status = FE_HAS_SIGNAL + | FE_HAS_CARRIER + | FE_HAS_VITERBI + | FE_HAS_SYNC + | FE_HAS_LOCK; + + return 0; +} + +static int dtv5100_fe_read_ber(struct dvb_frontend* fe, u32* ber) +{ + *ber = 0; + return 0; +} + +static int dtv5100_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) +{ + *strength = 0; + return 0; +} + +static int dtv5100_fe_read_snr(struct dvb_frontend* fe, u16* snr) +{ + *snr = 0; + return 0; +} + +static int dtv5100_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + *ucblocks = 0; + return 0; +} + +static int dtv5100_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + return 0; +} + +static int dtv5100_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + + return 0; +} + +static int dtv5100_fe_sleep(struct dvb_frontend* fe) +{ + return 0; +} + +static int dtv5100_fe_init(struct dvb_frontend* fe) +{ + return 0; +} + +static void dtv5100_fe_release(struct dvb_frontend* fe) +{ + struct dtv5100_fe_state* state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops dtv5100_fe_ops; + +struct dvb_frontend* dtv5100_fe_attach(void) +{ + struct dtv5100_fe_state* state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct dtv5100_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &dtv5100_fe_ops, sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops dtv5100_fe_ops = { + + .info = { + .name = "Dummy DVB-T", + .type = FE_OFDM, + .frequency_min = QT1010_MIN_FREQ, + .frequency_max = QT1010_MAX_FREQ, + .frequency_stepsize = QT1010_STEP, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dtv5100_fe_release, + + .init = dtv5100_fe_init, + .sleep = dtv5100_fe_sleep, + + .set_frontend = dtv5100_fe_set_frontend, + .get_frontend = dtv5100_fe_get_frontend, + + .read_status = dtv5100_fe_read_status, + .read_ber = dtv5100_fe_read_ber, + .read_signal_strength = dtv5100_fe_read_signal_strength, + .read_snr = dtv5100_fe_read_snr, + .read_ucblocks = dtv5100_fe_read_ucblocks, +}; diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c new file mode 100644 index 00000000000..f89d01755ea --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.c @@ -0,0 +1,217 @@ +/* + * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T + * + * Copyright (C) 2008 Antoine Jacquet + * http://royale.zerezo.com/dtv5100/ + * + * Inspired by gl861.c and au6610.c drivers + * + * 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 "dtv5100.h" +#include "qt1010.h" + +/* debug */ +static int dvb_usb_dtv5100_debug; +module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static int dtv5100_read_reg(struct dvb_usb_device *d, u8 addr, u8 reg, u8 *value) +{ + return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + DTV5100_I2C_READ, USB_TYPE_VENDOR|USB_DIR_IN, + 0, (addr << 8) + reg, value, 1, + DTV5100_USB_TIMEOUT); +} + +static int dtv5100_write_reg(struct dvb_usb_device *d, u8 addr, u8 reg, u8 value) +{ + return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + DTV5100_I2C_WRITE, USB_TYPE_VENDOR|USB_DIR_OUT, + value, (addr << 8) + reg, NULL, 0, + DTV5100_USB_TIMEOUT); +} + +/* I2C */ +static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i; + + if (num > 2) + return -EINVAL; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + for (i = 0; i < num; i++) { + if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { + /* write/read request, 2 messages + * msg = { + * { reg }, + * { val }, + * } + */ + if (dtv5100_read_reg(d, msg[i].addr, msg[i].buf[0], msg[i+1].buf) < 0) + break; + i++; + } else { + /* write request, 1 message + * msg = { + * { reg, val }, + * } + */ + if (dtv5100_write_reg(d, msg[i].addr, msg[i].buf[0], msg[i].buf[1]) < 0) + break; + } + } + + mutex_unlock(&d->i2c_mutex); + return i; +} + +static u32 dtv5100_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm dtv5100_i2c_algo = { + .master_xfer = dtv5100_i2c_xfer, + .functionality = dtv5100_i2c_func, +}; + +/* Callbacks for DVB USB */ +static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap) +{ + adap->fe = dtv5100_fe_attach(); + return 0; +} + +static struct qt1010_config dtv5100_qt1010_config = { + .i2c_address = 0xc4 +}; + +static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap) +{ + return dvb_attach(qt1010_attach, + adap->fe, &adap->dev->i2c_adap, + &dtv5100_qt1010_config) == NULL ? -ENODEV : 0; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties dtv5100_properties; + +static int dtv5100_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int i, ret; + struct usb_device *udev = interface_to_usbdev(intf); + + ret = dvb_usb_device_init(intf, &dtv5100_properties, + THIS_MODULE, NULL, adapter_nr); + if (ret) + return ret; + + /* initialize frontend & non qt1010 part? */ + for (i = 0; dtv5100_init[i].request; i++) + { + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + dtv5100_init[i].request, + USB_TYPE_VENDOR|USB_DIR_OUT, + dtv5100_init[i].value, + dtv5100_init[i].index, NULL, 0, + DTV5100_USB_TIMEOUT); + if (ret) + return ret; + } + + return 0; +} + +static struct usb_device_id dtv5100_table [] = { + { USB_DEVICE(0x06be, 0xa232) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, dtv5100_table); + +static struct dvb_usb_device_properties dtv5100_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + + .size_of_priv = 0, + + .num_adapters = 1, + .adapter = {{ + .frontend_attach = dtv5100_frontend_attach, + .tuner_attach = dtv5100_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } }, + + .i2c_algo = &dtv5100_i2c_algo, + + .num_device_descs = 1, + .devices = { + { + .name = "AME DTV-5100 USB2.0 DVB-T", + .cold_ids = { NULL }, + .warm_ids = { &dtv5100_table[0], NULL }, + }, + } +}; + +static struct usb_driver dtv5100_driver = { + .name = "dvb_usb_dtv5100", + .probe = dtv5100_probe, + .disconnect = dvb_usb_device_exit, + .id_table = dtv5100_table, +}; + +/* module stuff */ +static int __init dtv5100_module_init(void) +{ + int ret; + + ret = usb_register(&dtv5100_driver); + if (ret) + err("usb_register failed. Error number %d", ret); + + return ret; +} + +static void __exit dtv5100_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&dtv5100_driver); +} + +module_init(dtv5100_module_init); +module_exit(dtv5100_module_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h new file mode 100644 index 00000000000..1aadb86f70e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.h @@ -0,0 +1,128 @@ +/* + * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T + * + * Copyright (C) 2008 Antoine Jacquet + * http://royale.zerezo.com/dtv5100/ + * + * 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 + */ + +#ifndef _DVB_USB_DTV5100_H_ +#define _DVB_USB_DTV5100_H_ + +#define DVB_USB_LOG_PREFIX "dtv5100" +#include "dvb-usb.h" + +#define DTV5100_USB_TIMEOUT 500 +#define DTV5100_I2C_WRITE 0xc7 +#define DTV5100_I2C_READ 0xc8 + +#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" +#define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T" + +static struct { + u8 request; + u8 value; + u16 index; +} dtv5100_init[] = { + { 0x000000c5, 0x00000000, 0x00000001 }, + { 0x000000c5, 0x00000001, 0x00000001 }, + { 0x000000c0, 0x0000000b, 0x00000050 }, + { 0x000000c0, 0x00000044, 0x00000051 }, + { 0x000000c0, 0x00000046, 0x00000052 }, + { 0x000000c0, 0x00000015, 0x00000053 }, + { 0x000000c0, 0x0000000f, 0x00000054 }, + { 0x000000c0, 0x00000080, 0x00000055 }, + { 0x000000c0, 0x00000001, 0x000000ea }, + { 0x000000c0, 0x00000000, 0x000000ea }, + { 0x000000c0, 0x00000075, 0x0000005c }, + { 0x000000c0, 0x000000a1, 0x0000009c }, + { 0x000000c0, 0x00000000, 0x0000008e }, + { 0x000000c0, 0x00000000, 0x00000090 }, + { 0x000000c0, 0x000000ff, 0x00000091 }, + { 0x000000c0, 0x000000ff, 0x00000092 }, + { 0x000000c0, 0x00000000, 0x00000093 }, + { 0x000000c0, 0x000000ff, 0x00000094 }, + { 0x000000c0, 0x00000000, 0x00000058 }, + { 0x000000c0, 0x0000003f, 0x00000095 }, + { 0x000000c0, 0x0000003f, 0x00000096 }, + { 0x000000c0, 0x0000000c, 0x0000005a }, + { 0x000000c0, 0x0000002b, 0x00000056 }, + { 0x000000c0, 0x00000017, 0x0000005f }, + { 0x000000c0, 0x00000040, 0x0000005e }, + { 0x000000c0, 0x00000036, 0x00000064 }, + { 0x000000c0, 0x00000067, 0x00000065 }, + { 0x000000c0, 0x000000e5, 0x00000066 }, + { 0x000000c0, 0x00000073, 0x000000cc }, + { 0x000000c0, 0x000000cd, 0x0000006c }, + { 0x000000c0, 0x0000007e, 0x0000006d }, + { 0x000000c0, 0x00000001, 0x00000071 }, + { 0x000000c0, 0x00000001, 0x00000070 }, + /**/ + { 0x000000c7, 0x00000080, 0x0000c401 }, + { 0x000000c7, 0x0000003f, 0x0000c402 }, + { 0x000000c7, 0x00000034, 0x0000c405 }, // 2 + { 0x000000c7, 0x00000044, 0x0000c406 }, + { 0x000000c7, 0x00000038, 0x0000c407 }, // 4 + { 0x000000c7, 0x00000008, 0x0000c408 }, + { 0x000000c7, 0x0000001c, 0x0000c409 }, // 6 + { 0x000000c7, 0x0000000d, 0x0000c40a }, // 7 + { 0x000000c7, 0x00000045, 0x0000c40b }, // 8 + { 0x000000c7, 0x000000e1, 0x0000c40c }, + { 0x000000c7, 0x00000078, 0x0000c41a }, // 10 + { 0x000000c7, 0x00000000, 0x0000c41b }, + { 0x000000c7, 0x00000089, 0x0000c41c }, + { 0x000000c7, 0x000000fd, 0x0000c411 }, // 13 + { 0x000000c7, 0x00000095, 0x0000c412 }, // 14 + { 0x000000c7, 0x000000d6, 0x0000c422 }, // 15 + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c7, 0x000000d0, 0x0000c41e }, + { 0x000000c8, 0x00000000, 0x0000c422 }, + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c8, 0x00000000, 0x0000c405 }, + { 0x000000c8, 0x00000000, 0x0000c422 }, + { 0x000000c7, 0x000000d0, 0x0000c423 }, + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c7, 0x000000e0, 0x0000c41e }, + { 0x000000c8, 0x00000000, 0x0000c423 }, + { 0x000000c8, 0x00000000, 0x0000c423 }, + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c7, 0x000000d0, 0x0000c424 }, + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c7, 0x000000f0, 0x0000c41e }, + { 0x000000c8, 0x00000000, 0x0000c424 }, + { 0x000000c7, 0x00000000, 0x0000c41e }, + { 0x000000c7, 0x0000007f, 0x0000c414 }, + { 0x000000c7, 0x0000007f, 0x0000c415 }, + { 0x000000c7, 0x00000030, 0x0000c405 }, + { 0x000000c7, 0x00000000, 0x0000c406 }, + { 0x000000c7, 0x0000001f, 0x0000c415 }, + { 0x000000c7, 0x000000ff, 0x0000c416 }, + { 0x000000c7, 0x000000ff, 0x0000c418 }, + { 0x000000c7, 0x00000051, 0x0000c41f }, // here + { 0x000000c7, 0x00000016, 0x0000c420 }, // here + { 0x000000c7, 0x00000053, 0x0000c421 }, + { 0x000000c7, 0x000000c1, 0x0000c425 }, // here + { 0x000000c7, 0x00000014, 0x0000c426 }, // here + { 0x000000c7, 0x00000082, 0x0000c400 }, + { 0x000000c7, 0x00000000, 0x0000c402 }, + { 0x000000c7, 0x00000000, 0x0000c401 }, + /**/ + { } /* Terminating entry */ +}; + +extern struct dvb_frontend* dtv5100_fe_attach(void); + +#endif -- GitLab From 60688d5e6e6e2ae62f29762d1e3b2aec2dbd3817 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 11 Aug 2008 19:21:33 -0300 Subject: [PATCH 3995/5416] V4L/DVB (8735): dtv5100: replace dummy frontend by zl10353 Remove the dtv5100-fe.c dummy frontend and replace it by the real frontend for the chipset. Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Makefile | 2 +- drivers/media/dvb/dvb-usb/dtv5100-fe.c | 147 ------------------------- drivers/media/dvb/dvb-usb/dtv5100.c | 94 ++++++++++------ drivers/media/dvb/dvb-usb/dtv5100.h | 91 ++------------- 4 files changed, 68 insertions(+), 266 deletions(-) delete mode 100644 drivers/media/dvb/dvb-usb/dtv5100-fe.c diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 5e170fba109..116544f4272 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -67,7 +67,7 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o dvb-usb-dw2102-objs = dw2102.o obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o -dvb-usb-dtv5100-objs = dtv5100.o dtv5100-fe.o +dvb-usb-dtv5100-objs = dtv5100.o obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/dvb-usb/dtv5100-fe.c b/drivers/media/dvb/dvb-usb/dtv5100-fe.c deleted file mode 100644 index 08fe33bcc5d..00000000000 --- a/drivers/media/dvb/dvb-usb/dtv5100-fe.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T - * - * Copyright (C) 2008 Antoine Jacquet - * http://royale.zerezo.com/dtv5100/ - * - * Inspired by dvb_dummy_fe.c - * - * 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 "dvb-usb.h" -#include "qt1010_priv.h" - -struct dtv5100_fe_state { - struct dvb_frontend frontend; -}; - -static int dtv5100_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - *status = FE_HAS_SIGNAL - | FE_HAS_CARRIER - | FE_HAS_VITERBI - | FE_HAS_SYNC - | FE_HAS_LOCK; - - return 0; -} - -static int dtv5100_fe_read_ber(struct dvb_frontend* fe, u32* ber) -{ - *ber = 0; - return 0; -} - -static int dtv5100_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - *strength = 0; - return 0; -} - -static int dtv5100_fe_read_snr(struct dvb_frontend* fe, u16* snr) -{ - *snr = 0; - return 0; -} - -static int dtv5100_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - *ucblocks = 0; - return 0; -} - -static int dtv5100_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - return 0; -} - -static int dtv5100_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - } - - return 0; -} - -static int dtv5100_fe_sleep(struct dvb_frontend* fe) -{ - return 0; -} - -static int dtv5100_fe_init(struct dvb_frontend* fe) -{ - return 0; -} - -static void dtv5100_fe_release(struct dvb_frontend* fe) -{ - struct dtv5100_fe_state* state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops dtv5100_fe_ops; - -struct dvb_frontend* dtv5100_fe_attach(void) -{ - struct dtv5100_fe_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dtv5100_fe_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* create dvb_frontend */ - memcpy(&state->frontend.ops, &dtv5100_fe_ops, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops dtv5100_fe_ops = { - - .info = { - .name = "Dummy DVB-T", - .type = FE_OFDM, - .frequency_min = QT1010_MIN_FREQ, - .frequency_max = QT1010_MAX_FREQ, - .frequency_stepsize = QT1010_STEP, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, - }, - - .release = dtv5100_fe_release, - - .init = dtv5100_fe_init, - .sleep = dtv5100_fe_sleep, - - .set_frontend = dtv5100_fe_set_frontend, - .get_frontend = dtv5100_fe_get_frontend, - - .read_status = dtv5100_fe_read_status, - .read_ber = dtv5100_fe_read_ber, - .read_signal_strength = dtv5100_fe_read_signal_strength, - .read_snr = dtv5100_fe_read_snr, - .read_ucblocks = dtv5100_fe_read_ucblocks, -}; diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c index f89d01755ea..7168a49cecf 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.c +++ b/drivers/media/dvb/dvb-usb/dtv5100.c @@ -22,6 +22,7 @@ */ #include "dtv5100.h" +#include "zl10353.h" #include "qt1010.h" /* debug */ @@ -30,25 +31,44 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static int dtv5100_read_reg(struct dvb_usb_device *d, u8 addr, u8 reg, u8 *value) +static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { - return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), - DTV5100_I2C_READ, USB_TYPE_VENDOR|USB_DIR_IN, - 0, (addr << 8) + reg, value, 1, - DTV5100_USB_TIMEOUT); -} + u8 request; + u8 type; + u16 value; + u16 index; + + switch (wlen) { + case 1: + /* write { reg }, read { value } */ + request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ : + DTV5100_TUNER_READ); + type = USB_TYPE_VENDOR|USB_DIR_IN; + value = 0; + break; + case 2: + /* write { reg, value } */ + request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE : + DTV5100_TUNER_WRITE); + type = USB_TYPE_VENDOR|USB_DIR_OUT; + value = wbuf[1]; + break; + default: + warn("wlen = %x, aborting.", wlen); + return -EINVAL; + } + index = (addr << 8) + wbuf[0]; -static int dtv5100_write_reg(struct dvb_usb_device *d, u8 addr, u8 reg, u8 value) -{ - return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), - DTV5100_I2C_WRITE, USB_TYPE_VENDOR|USB_DIR_OUT, - value, (addr << 8) + reg, NULL, 0, + msleep(1); /* avoid I2C errors */ + return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, + type, value, index, rbuf, rlen, DTV5100_USB_TIMEOUT); } /* I2C */ static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; @@ -60,25 +80,16 @@ static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], return -EAGAIN; for (i = 0; i < num; i++) { + /* write/read request */ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { - /* write/read request, 2 messages - * msg = { - * { reg }, - * { val }, - * } - */ - if (dtv5100_read_reg(d, msg[i].addr, msg[i].buf[0], msg[i+1].buf) < 0) + if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, + msg[i].len, msg[i+1].buf, + msg[i+1].len) < 0) break; i++; - } else { - /* write request, 1 message - * msg = { - * { reg, val }, - * } - */ - if (dtv5100_write_reg(d, msg[i].addr, msg[i].buf[0], msg[i].buf[1]) < 0) + } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, + msg[i].len, NULL, 0) < 0) break; - } } mutex_unlock(&d->i2c_mutex); @@ -96,14 +107,27 @@ static struct i2c_algorithm dtv5100_i2c_algo = { }; /* Callbacks for DVB USB */ +static struct zl10353_config dtv5100_zl10353_config = { + .demod_address = DTV5100_DEMOD_ADDR, + .no_tuner = 1, + .parallel_ts = 1, +}; + static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap) { - adap->fe = dtv5100_fe_attach(); + adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config, + &adap->dev->i2c_adap); + if (adap->fe == NULL) + return -EIO; + + /* disable i2c gate, or it won't work... is this safe? */ + adap->fe->ops.i2c_gate_ctrl = NULL; + return 0; } static struct qt1010_config dtv5100_qt1010_config = { - .i2c_address = 0xc4 + .i2c_address = DTV5100_TUNER_ADDR }; static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap) @@ -122,12 +146,7 @@ static int dtv5100_probe(struct usb_interface *intf, int i, ret; struct usb_device *udev = interface_to_usbdev(intf); - ret = dvb_usb_device_init(intf, &dtv5100_properties, - THIS_MODULE, NULL, adapter_nr); - if (ret) - return ret; - - /* initialize frontend & non qt1010 part? */ + /* initialize non qt1010/zl10353 part? */ for (i = 0; dtv5100_init[i].request; i++) { ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), @@ -140,6 +159,11 @@ static int dtv5100_probe(struct usb_interface *intf, return ret; } + ret = dvb_usb_device_init(intf, &dtv5100_properties, + THIS_MODULE, NULL, adapter_nr); + if (ret) + return ret; + return 0; } diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h index 1aadb86f70e..e36bf2d5c94 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.h +++ b/drivers/media/dvb/dvb-usb/dtv5100.h @@ -26,8 +26,14 @@ #include "dvb-usb.h" #define DTV5100_USB_TIMEOUT 500 -#define DTV5100_I2C_WRITE 0xc7 -#define DTV5100_I2C_READ 0xc8 + +#define DTV5100_DEMOD_ADDR 0x00 +#define DTV5100_DEMOD_WRITE 0xc0 +#define DTV5100_DEMOD_READ 0xc1 + +#define DTV5100_TUNER_ADDR 0xc4 +#define DTV5100_TUNER_WRITE 0xc7 +#define DTV5100_TUNER_READ 0xc8 #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" #define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T" @@ -39,87 +45,6 @@ static struct { } dtv5100_init[] = { { 0x000000c5, 0x00000000, 0x00000001 }, { 0x000000c5, 0x00000001, 0x00000001 }, - { 0x000000c0, 0x0000000b, 0x00000050 }, - { 0x000000c0, 0x00000044, 0x00000051 }, - { 0x000000c0, 0x00000046, 0x00000052 }, - { 0x000000c0, 0x00000015, 0x00000053 }, - { 0x000000c0, 0x0000000f, 0x00000054 }, - { 0x000000c0, 0x00000080, 0x00000055 }, - { 0x000000c0, 0x00000001, 0x000000ea }, - { 0x000000c0, 0x00000000, 0x000000ea }, - { 0x000000c0, 0x00000075, 0x0000005c }, - { 0x000000c0, 0x000000a1, 0x0000009c }, - { 0x000000c0, 0x00000000, 0x0000008e }, - { 0x000000c0, 0x00000000, 0x00000090 }, - { 0x000000c0, 0x000000ff, 0x00000091 }, - { 0x000000c0, 0x000000ff, 0x00000092 }, - { 0x000000c0, 0x00000000, 0x00000093 }, - { 0x000000c0, 0x000000ff, 0x00000094 }, - { 0x000000c0, 0x00000000, 0x00000058 }, - { 0x000000c0, 0x0000003f, 0x00000095 }, - { 0x000000c0, 0x0000003f, 0x00000096 }, - { 0x000000c0, 0x0000000c, 0x0000005a }, - { 0x000000c0, 0x0000002b, 0x00000056 }, - { 0x000000c0, 0x00000017, 0x0000005f }, - { 0x000000c0, 0x00000040, 0x0000005e }, - { 0x000000c0, 0x00000036, 0x00000064 }, - { 0x000000c0, 0x00000067, 0x00000065 }, - { 0x000000c0, 0x000000e5, 0x00000066 }, - { 0x000000c0, 0x00000073, 0x000000cc }, - { 0x000000c0, 0x000000cd, 0x0000006c }, - { 0x000000c0, 0x0000007e, 0x0000006d }, - { 0x000000c0, 0x00000001, 0x00000071 }, - { 0x000000c0, 0x00000001, 0x00000070 }, - /**/ - { 0x000000c7, 0x00000080, 0x0000c401 }, - { 0x000000c7, 0x0000003f, 0x0000c402 }, - { 0x000000c7, 0x00000034, 0x0000c405 }, // 2 - { 0x000000c7, 0x00000044, 0x0000c406 }, - { 0x000000c7, 0x00000038, 0x0000c407 }, // 4 - { 0x000000c7, 0x00000008, 0x0000c408 }, - { 0x000000c7, 0x0000001c, 0x0000c409 }, // 6 - { 0x000000c7, 0x0000000d, 0x0000c40a }, // 7 - { 0x000000c7, 0x00000045, 0x0000c40b }, // 8 - { 0x000000c7, 0x000000e1, 0x0000c40c }, - { 0x000000c7, 0x00000078, 0x0000c41a }, // 10 - { 0x000000c7, 0x00000000, 0x0000c41b }, - { 0x000000c7, 0x00000089, 0x0000c41c }, - { 0x000000c7, 0x000000fd, 0x0000c411 }, // 13 - { 0x000000c7, 0x00000095, 0x0000c412 }, // 14 - { 0x000000c7, 0x000000d6, 0x0000c422 }, // 15 - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c7, 0x000000d0, 0x0000c41e }, - { 0x000000c8, 0x00000000, 0x0000c422 }, - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c8, 0x00000000, 0x0000c405 }, - { 0x000000c8, 0x00000000, 0x0000c422 }, - { 0x000000c7, 0x000000d0, 0x0000c423 }, - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c7, 0x000000e0, 0x0000c41e }, - { 0x000000c8, 0x00000000, 0x0000c423 }, - { 0x000000c8, 0x00000000, 0x0000c423 }, - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c7, 0x000000d0, 0x0000c424 }, - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c7, 0x000000f0, 0x0000c41e }, - { 0x000000c8, 0x00000000, 0x0000c424 }, - { 0x000000c7, 0x00000000, 0x0000c41e }, - { 0x000000c7, 0x0000007f, 0x0000c414 }, - { 0x000000c7, 0x0000007f, 0x0000c415 }, - { 0x000000c7, 0x00000030, 0x0000c405 }, - { 0x000000c7, 0x00000000, 0x0000c406 }, - { 0x000000c7, 0x0000001f, 0x0000c415 }, - { 0x000000c7, 0x000000ff, 0x0000c416 }, - { 0x000000c7, 0x000000ff, 0x0000c418 }, - { 0x000000c7, 0x00000051, 0x0000c41f }, // here - { 0x000000c7, 0x00000016, 0x0000c420 }, // here - { 0x000000c7, 0x00000053, 0x0000c421 }, - { 0x000000c7, 0x000000c1, 0x0000c425 }, // here - { 0x000000c7, 0x00000014, 0x0000c426 }, // here - { 0x000000c7, 0x00000082, 0x0000c400 }, - { 0x000000c7, 0x00000000, 0x0000c402 }, - { 0x000000c7, 0x00000000, 0x0000c401 }, - /**/ { } /* Terminating entry */ }; -- GitLab From 736949862ceda7b6a9e5a867f81898e90be919d0 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Tue, 12 Aug 2008 16:56:34 -0300 Subject: [PATCH 3996/5416] V4L/DVB (8736): dtv5100: CodingStyle cleanups Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dtv5100.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c index 7168a49cecf..b2e6f7ff1a0 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.c +++ b/drivers/media/dvb/dvb-usb/dtv5100.c @@ -32,7 +32,7 @@ MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, - u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { u8 request; u8 type; @@ -44,14 +44,14 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, /* write { reg }, read { value } */ request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ : DTV5100_TUNER_READ); - type = USB_TYPE_VENDOR|USB_DIR_IN; + type = USB_TYPE_VENDOR | USB_DIR_IN; value = 0; break; case 2: /* write { reg, value } */ request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE : DTV5100_TUNER_WRITE); - type = USB_TYPE_VENDOR|USB_DIR_OUT; + type = USB_TYPE_VENDOR | USB_DIR_OUT; value = wbuf[1]; break; default: @@ -68,7 +68,7 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, /* I2C */ static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; @@ -116,7 +116,7 @@ static struct zl10353_config dtv5100_zl10353_config = { static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap) { adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config, - &adap->dev->i2c_adap); + &adap->dev->i2c_adap); if (adap->fe == NULL) return -EIO; @@ -147,11 +147,10 @@ static int dtv5100_probe(struct usb_interface *intf, struct usb_device *udev = interface_to_usbdev(intf); /* initialize non qt1010/zl10353 part? */ - for (i = 0; dtv5100_init[i].request; i++) - { + for (i = 0; dtv5100_init[i].request; i++) { ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), dtv5100_init[i].request, - USB_TYPE_VENDOR|USB_DIR_OUT, + USB_TYPE_VENDOR | USB_DIR_OUT, dtv5100_init[i].value, dtv5100_init[i].index, NULL, 0, DTV5100_USB_TIMEOUT); -- GitLab From 5ebcfa4f92ed06129d9439198f65456abe1bfe3a Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 18 Aug 2008 18:22:00 -0300 Subject: [PATCH 3997/5416] V4L/DVB (8738): dtv5100: remove old definition from header Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dtv5100.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h index e36bf2d5c94..93e96e04a82 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.h +++ b/drivers/media/dvb/dvb-usb/dtv5100.h @@ -48,6 +48,4 @@ static struct { { } /* Terminating entry */ }; -extern struct dvb_frontend* dtv5100_fe_attach(void); - #endif -- GitLab From 664b11fc725830b59265cd9ec35a4396514d2b26 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 18 Aug 2008 18:38:51 -0300 Subject: [PATCH 3998/5416] V4L/DVB (8739): dtv5100: remove prohibited space... Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dtv5100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c index b2e6f7ff1a0..078ce92ca43 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.c +++ b/drivers/media/dvb/dvb-usb/dtv5100.c @@ -166,7 +166,7 @@ static int dtv5100_probe(struct usb_interface *intf, return 0; } -static struct usb_device_id dtv5100_table [] = { +static struct usb_device_id dtv5100_table[] = { { USB_DEVICE(0x06be, 0xa232) }, { } /* Terminating entry */ }; -- GitLab From 513edce60f184d90ef4a6d33917264d49c2b07fd Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 18 Aug 2008 17:38:01 -0300 Subject: [PATCH 3999/5416] V4L/DVB (8742): pvrusb2: use proper byteorder interface ___swab32 is an internal detail of the implementation. Acked-by: Mike Isely Signed-off-by: Harvey Harrison Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f051c6aa7f1..7fa903ad26b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1314,8 +1314,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); /* Usbsnoop log shows that we must swap bytes... */ for (icnt = 0; icnt < bcnt/4 ; icnt++) - ((u32 *)fw_ptr)[icnt] = - ___swab32(((u32 *)fw_ptr)[icnt]); + ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, &actual_length, HZ); -- GitLab From 614b147b4f8f38a090f88ac02f67b01225bb5d54 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Aug 2008 17:01:45 -0300 Subject: [PATCH 4000/5416] V4L/DVB (8745): v4l2: fix a bunch of compile warnings. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_core.c | 2 +- drivers/media/dvb/b2c2/flexcop-dma.c | 2 +- drivers/media/video/btcx-risc.c | 2 +- drivers/media/video/saa7134/saa7134-core.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index d01965e9692..d599d360da3 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -234,7 +234,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) { __le32 *cpu; - dma_addr_t dma_addr; + dma_addr_t dma_addr = 0; cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); if (NULL == cpu) { diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index a91ed28f03a..26f0011a507 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c @@ -10,7 +10,7 @@ int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) { u8 *tcpu; - dma_addr_t tdma; + dma_addr_t tdma = 0; if (size % 2) { err("dma buffersize has to be even."); diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index 3324ab38f58..ac1b2687a20 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c @@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci, unsigned int size) { __le32 *cpu; - dma_addr_t dma; + dma_addr_t dma = 0; if (NULL != risc->cpu && risc->size < size) btcx_riscmem_free(pci,risc); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 64f20fd4631..148aa81dc24 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -215,7 +215,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) { __le32 *cpu; - dma_addr_t dma_addr; + dma_addr_t dma_addr = 0; cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); if (NULL == cpu) -- GitLab From eda9e4e29492aff55ceb3f719a6011bddc60a892 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Aug 2008 17:12:08 -0300 Subject: [PATCH 4001/5416] V4L/DVB (8746): v4l-dvb: fix compile warnings. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/nxt200x.c | 4 ++-- drivers/media/dvb/frontends/or51211.c | 2 +- drivers/media/video/vino.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index af298358e82..a8429ebfa8a 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -80,7 +80,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len return 0; } -static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len) +static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len) { int err; struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; @@ -111,7 +111,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, return 0; } -static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len) +static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len) { u8 reg2 [] = { reg }; diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 6afe12aaca4..16cf2fdd5d7 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -88,7 +88,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf, return 0; } -static u8 i2c_readbytes (struct or51211_state* state, u8 reg, u8* buf, int len) +static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len) { int err; struct i2c_msg msg; diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 7072cdf74ed..ca421cc84f8 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -809,7 +809,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, dprintk("vino_free_buffer_with_count(): count = %d\n", count); for (i = 0; i < count; i++) { - ClearPageReserved(virt_to_page(fb->desc_table.virtual[i])); + ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); dma_unmap_single(NULL, fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], PAGE_SIZE, DMA_FROM_DEVICE); @@ -887,7 +887,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, dma_data_addr + VINO_PAGE_SIZE * j; } - SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); + SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); } /* page_count needs to be set anyway, because the descriptor table has @@ -974,7 +974,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb, dma_data_addr + VINO_PAGE_SIZE * j; } - SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); + SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); } /* page_count needs to be set anyway, because the descriptor table has -- GitLab From ef0e3c26efe9c52de62b96fdad94de3ed70489d0 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Fri, 22 Aug 2008 17:13:05 -0300 Subject: [PATCH 4002/5416] V4L/DVB (8748): V4L: fix return value of meye probe callback The return vaule of the probe function should return -ENOMEM instead of -EBUSY if video_device_alloc() fails. Signed-off-by: Henrik Kretzschmar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index cdaff2fdf39..102a5b9cfd1 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1779,6 +1779,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outnotdev; } + ret = -ENOMEM; meye.mchip_dev = pcidev; meye.video_dev = video_device_alloc(); if (!meye.video_dev) { @@ -1786,7 +1787,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outnotdev; } - ret = -ENOMEM; meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); if (!meye.grab_temp) { printk(KERN_ERR "meye: grab buffer allocation failed\n"); -- GitLab From ee7aa9f821b27674f36fc09413914b68f7ad97ca Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Fri, 22 Aug 2008 16:41:03 -0300 Subject: [PATCH 4003/5416] V4L/DVB (8750): V4L: check inval in video_register_device_index() Better check the video_device pointer before using it. Signed-off-by: Henrik Kretzschmar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 6b9f3cb0de9..8903e41628e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -254,6 +254,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int ret; char *name_base; + if (vfd == NULL) + return -EINVAL; + if (vfd == NULL) return -EINVAL; -- GitLab From 14d962602c8bf86e63c9b9272be1f0360d0a448a Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Mon, 25 Aug 2008 13:58:55 -0300 Subject: [PATCH 4004/5416] V4L/DVB (8752): s2255drv: firmware improvement patch Fix for reloading firmware when removing and reloading driver Handshaking for firmware loading and changing modes. Removes the restriction of one user per channel at a time. JPEG capture mode added. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 535 ++++++++++++++++++--------------- 1 file changed, 297 insertions(+), 238 deletions(-) diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index de39cf0890f..af19bb346ef 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -67,20 +67,21 @@ /* USB endpoint number for configuring the device */ #define S2255_CONFIG_EP 2 /* maximum time for DSP to start responding after last FW word loaded(ms) */ -#define S2255_DSP_BOOTTIME 400 +#define S2255_DSP_BOOTTIME 800 /* maximum time to wait for firmware to load (ms) */ #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) #define S2255_DEF_BUFS 16 +#define S2255_SETMODE_TIMEOUT 500 #define MAX_CHANNELS 4 -#define FRAME_MARKER 0x2255DA4AL -#define MAX_PIPE_USBBLOCK (40 * 1024) -#define DEFAULT_PIPE_USBBLOCK (16 * 1024) +#define S2255_MARKER_FRAME 0x2255DA4AL +#define S2255_MARKER_RESPONSE 0x2255ACACL +#define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 #define MAX_PIPE_BUFFERS 1 #define SYS_FRAMES 4 /* maximum size is PAL full size plus room for the marker header(s) */ -#define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096) -#define DEF_USB_BLOCK (4096) +#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) +#define DEF_USB_BLOCK S2255_USB_XFER_SIZE #define LINE_SZ_4CIFS_NTSC 640 #define LINE_SZ_2CIFS_NTSC 640 #define LINE_SZ_1CIFS_NTSC 320 @@ -108,6 +109,9 @@ #define COLOR_YUVPL 1 /* YUV planar */ #define COLOR_YUVPK 2 /* YUV packed */ #define COLOR_Y8 4 /* monochrome */ +#define COLOR_JPG 5 /* JPEG */ +#define MASK_COLOR 0xff +#define MASK_JPG_QUALITY 0xff00 /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ #define FDEC_1 1 /* capture every frame. default */ @@ -148,16 +152,14 @@ struct s2255_mode { u32 restart; /* if DSP requires restart */ }; -/* frame structure */ -#define FRAME_STATE_UNUSED 0 -#define FRAME_STATE_FILLING 1 -#define FRAME_STATE_FULL 2 +#define S2255_READ_IDLE 0 +#define S2255_READ_FRAME 1 +/* frame structure */ struct s2255_framei { unsigned long size; - - unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */ + unsigned long ulState; /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/ void *lpvbits; /* image data */ unsigned long cur_size; /* current data copied to it */ }; @@ -188,6 +190,10 @@ struct s2255_dmaqueue { #define S2255_FW_FAILED 3 #define S2255_FW_DISCONNECTING 4 +#define S2255_FW_MARKER 0x22552f2f +/* 2255 read states */ +#define S2255_READ_IDLE 0 +#define S2255_READ_FRAME 1 struct s2255_fw { int fw_loaded; int fw_size; @@ -195,7 +201,6 @@ struct s2255_fw { atomic_t fw_state; void *pfw_data; wait_queue_head_t wait_fw; - struct timer_list dsp_wait; const struct firmware *fw; }; @@ -242,10 +247,20 @@ struct s2255_dev { int last_frame[MAX_CHANNELS]; u32 cc; /* current channel */ int b_acquire[MAX_CHANNELS]; + /* allocated image size */ unsigned long req_image_size[MAX_CHANNELS]; + /* received packet size */ + unsigned long pkt_size[MAX_CHANNELS]; int bad_payload[MAX_CHANNELS]; unsigned long frame_count[MAX_CHANNELS]; int frame_ready; + /* if JPEG image */ + int jpg_size[MAX_CHANNELS]; + /* if channel configured to default state */ + int chn_configured[MAX_CHANNELS]; + wait_queue_head_t wait_setmode[MAX_CHANNELS]; + int setmode_ready[MAX_CHANNELS]; + int chn_ready; struct kref kref; spinlock_t slock; }; @@ -306,12 +321,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev); static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, - int chn); + int chn, int jpgsize); static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, struct s2255_mode *mode); static int s2255_board_shutdown(struct s2255_dev *dev); static void s2255_exit_v4l(struct s2255_dev *dev); -static void s2255_fwload_start(struct s2255_dev *dev); +static void s2255_fwload_start(struct s2255_dev *dev, int reset); +static void s2255_destroy(struct kref *kref); +static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, + u16 index, u16 value, void *buf, + s32 buf_len, int bOut); #define dprintk(level, fmt, arg...) \ do { \ @@ -406,6 +425,10 @@ static const struct s2255_fmt formats[] = { .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16 + }, { + .name = "JPG", + .fourcc = V4L2_PIX_FMT_JPEG, + .depth = 24 }, { .name = "8bpp GREY", .fourcc = V4L2_PIX_FMT_GREY, @@ -464,6 +487,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in, return; } +void s2255_reset_dsppower(struct s2255_dev *dev) +{ + s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); + msleep(10); + s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1); + return; +} /* kickstarts the firmware loading. from probe */ @@ -480,18 +510,6 @@ static void s2255_timer(unsigned long user_data) } } -/* called when DSP is up and running. DSP is guaranteed to - be running after S2255_DSP_BOOTTIME */ -static void s2255_dsp_running(unsigned long user_data) -{ - struct s2255_fw *data = (struct s2255_fw *)user_data; - dprintk(1, "dsp running\n"); - atomic_set(&data->fw_state, S2255_FW_SUCCESS); - wake_up(&data->wait_fw); - printk(KERN_INFO "s2255: firmware loaded successfully\n"); - return; -} - /* this loads the firmware asynchronously. Originally this was done synchroously in probe. @@ -549,19 +567,14 @@ static void s2255_fwchunk_complete(struct urb *urb) } data->fw_loaded += len; } else { - init_timer(&data->dsp_wait); - data->dsp_wait.function = s2255_dsp_running; - data->dsp_wait.data = (unsigned long)data; atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); - mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME) - + jiffies); } dprintk(100, "2255 complete done\n"); return; } -static int s2255_got_frame(struct s2255_dev *dev, int chn) +static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) { struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; struct s2255_buffer *buf; @@ -586,8 +599,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn) list_del(&buf->vb.queue); do_gettimeofday(&buf->vb.ts); dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); - - s2255_fillbuff(dev, buf, dma_q->channel); + s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); wake_up(&buf->vb.done); dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); unlock: @@ -621,7 +633,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) * */ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, - int chn) + int chn, int jpgsize) { int pos = 0; struct timeval ts; @@ -649,6 +661,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, case V4L2_PIX_FMT_GREY: memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); break; + case V4L2_PIX_FMT_JPEG: + buf->vb.size = jpgsize; + memcpy(vbuf, tmpbuf, buf->vb.size); + break; case V4L2_PIX_FMT_YUV422P: memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height * 2); @@ -657,9 +673,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, printk(KERN_DEBUG "s2255: unknown format?\n"); } dev->last_frame[chn] = -1; - /* done with the frame, free it */ - frm->ulState = 0; - dprintk(4, "freeing buffer\n"); } else { printk(KERN_ERR "s2255: =======no frame\n"); return; @@ -1021,6 +1034,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, case V4L2_PIX_FMT_GREY: fh->mode.color = COLOR_Y8; break; + case V4L2_PIX_FMT_JPEG: + fh->mode.color = COLOR_JPG | (50 << 8); + break; case V4L2_PIX_FMT_YUV422P: fh->mode.color = COLOR_YUVPL; break; @@ -1139,7 +1155,7 @@ static u32 get_transfer_size(struct s2255_mode *mode) } } outImageSize = linesPerFrame * pixelsPerLine; - if (mode->color != COLOR_Y8) { + if ((mode->color & MASK_COLOR) != COLOR_Y8) { /* 2 bytes/pixel if not monochrome */ outImageSize *= 2; } @@ -1185,6 +1201,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, u32 *buffer; unsigned long chn_rev; + mutex_lock(&dev->lock); chn_rev = G_chnmap[chn]; dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], @@ -1199,6 +1216,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); + mutex_unlock(&dev->lock); return -ENOMEM; } @@ -1214,12 +1232,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, dprintk(1, "set mode done chn %lu, %d\n", chn, res); /* wait at least 3 frames before continuing */ - if (mode->restart) - msleep(125); + if (mode->restart) { + dev->setmode_ready[chn] = 0; + wait_event_timeout(dev->wait_setmode[chn], + (dev->setmode_ready[chn] != 0), + msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); + if (dev->setmode_ready[chn] != 1) { + printk(KERN_DEBUG "s2255: no set mode response\n"); + res = -EFAULT; + } + } /* clear the restart flag */ dev->mode[chn].restart = 0; - + mutex_unlock(&dev->lock); return res; } @@ -1270,7 +1296,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) dev->cur_frame[chn] = 0; dev->frame_count[chn] = 0; for (j = 0; j < SYS_FRAMES; j++) { - dev->buffer[chn].frame[j].ulState = 0; + dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE; dev->buffer[chn].frame[j].cur_size = 0; } res = videobuf_streamon(&fh->vb_vidq); @@ -1455,6 +1481,7 @@ static int s2255_open(struct inode *inode, struct file *file) enum v4l2_buf_type type = 0; int i = 0; int cur_channel = -1; + int state; dprintk(1, "s2255: open called (minor=%d)\n", minor); lock_kernel(); @@ -1471,47 +1498,77 @@ static int s2255_open(struct inode *inode, struct file *file) if ((NULL == dev) || (cur_channel == -1)) { unlock_kernel(); - dprintk(1, "s2255: openv4l no dev\n"); + printk(KERN_INFO "s2255: openv4l no dev\n"); return -ENODEV; } + if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { + unlock_kernel(); + printk(KERN_INFO "disconnecting\n"); + return -ENODEV; + } + kref_get(&dev->kref); mutex_lock(&dev->open_lock); dev->users[cur_channel]++; dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); - if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { + switch (atomic_read(&dev->fw_data->fw_state)) { + case S2255_FW_FAILED: err("2255 firmware load failed. retrying.\n"); - s2255_fwload_start(dev); + s2255_fwload_start(dev, 1); wait_event_timeout(dev->fw_data->wait_fw, - (atomic_read(&dev->fw_data->fw_state) - != S2255_FW_NOTLOADED), + ((atomic_read(&dev->fw_data->fw_state) + == S2255_FW_SUCCESS) || + (atomic_read(&dev->fw_data->fw_state) + == S2255_FW_DISCONNECTING)), msecs_to_jiffies(S2255_LOAD_TIMEOUT)); - if (atomic_read(&dev->fw_data->fw_state) - != S2255_FW_SUCCESS) { - printk(KERN_INFO "2255 FW load failed.\n"); - dev->users[cur_channel]--; - mutex_unlock(&dev->open_lock); - unlock_kernel(); - return -EFAULT; - } - } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) { + break; + case S2255_FW_NOTLOADED: + case S2255_FW_LOADED_DSPWAIT: /* give S2255_LOAD_TIMEOUT time for firmware to load in case driver loaded and then device immediately opened */ printk(KERN_INFO "%s waiting for firmware load\n", __func__); wait_event_timeout(dev->fw_data->wait_fw, - (atomic_read(&dev->fw_data->fw_state) - != S2255_FW_NOTLOADED), - msecs_to_jiffies(S2255_LOAD_TIMEOUT)); - if (atomic_read(&dev->fw_data->fw_state) - != S2255_FW_SUCCESS) { - printk(KERN_INFO "2255 firmware not loaded" - "try again\n"); - dev->users[cur_channel]--; - mutex_unlock(&dev->open_lock); - unlock_kernel(); - return -EBUSY; + ((atomic_read(&dev->fw_data->fw_state) + == S2255_FW_SUCCESS) || + (atomic_read(&dev->fw_data->fw_state) + == S2255_FW_DISCONNECTING)), + msecs_to_jiffies(S2255_LOAD_TIMEOUT)); + break; + case S2255_FW_SUCCESS: + default: + break; + } + state = atomic_read(&dev->fw_data->fw_state); + if (state != S2255_FW_SUCCESS) { + int rc; + switch (state) { + case S2255_FW_FAILED: + printk(KERN_INFO "2255 FW load failed. %d\n", state); + rc = -ENODEV; + break; + case S2255_FW_DISCONNECTING: + printk(KERN_INFO "%s: disconnecting\n", __func__); + rc = -ENODEV; + break; + case S2255_FW_LOADED_DSPWAIT: + case S2255_FW_NOTLOADED: + printk(KERN_INFO "%s: firmware not loaded yet" + "please try again later\n", + __func__); + rc = -EAGAIN; + break; + default: + printk(KERN_INFO "%s: unknown state\n", __func__); + rc = -EFAULT; + break; } + dev->users[cur_channel]--; + mutex_unlock(&dev->open_lock); + kref_put(&dev->kref, s2255_destroy); + unlock_kernel(); + return rc; } /* allocate + initialize per filehandle data */ @@ -1519,6 +1576,7 @@ static int s2255_open(struct inode *inode, struct file *file) if (NULL == fh) { dev->users[cur_channel]--; mutex_unlock(&dev->open_lock); + kref_put(&dev->kref, s2255_destroy); unlock_kernel(); return -ENOMEM; } @@ -1533,6 +1591,13 @@ static int s2255_open(struct inode *inode, struct file *file) fh->height = NUM_LINES_4CIFS_NTSC * 2; fh->channel = cur_channel; + /* configure channel to default state */ + if (!dev->chn_configured[cur_channel]) { + s2255_set_mode(dev, cur_channel, &fh->mode); + dev->chn_configured[cur_channel] = 1; + } + + /* Put all controls at a sane state */ for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) qctl_regs[i] = s2255_qctrl[i].default_value; @@ -1551,7 +1616,6 @@ static int s2255_open(struct inode *inode, struct file *file) V4L2_FIELD_INTERLACED, sizeof(struct s2255_buffer), fh); - kref_get(&dev->kref); mutex_unlock(&dev->open_lock); unlock_kernel(); return 0; @@ -1575,30 +1639,24 @@ static unsigned int s2255_poll(struct file *file, static void s2255_destroy(struct kref *kref) { struct s2255_dev *dev = to_s2255_dev(kref); + struct list_head *list; + int i; if (!dev) { printk(KERN_ERR "s2255drv: kref problem\n"); return; } - - /* - * Wake up any firmware load waiting (only done in .open, - * which holds the open_lock mutex) - */ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); wake_up(&dev->fw_data->wait_fw); - - /* prevent s2255_disconnect from racing s2255_open */ + for (i = 0; i < MAX_CHANNELS; i++) { + dev->setmode_ready[i] = 1; + wake_up(&dev->wait_setmode[i]); + } mutex_lock(&dev->open_lock); + /* reset the DSP so firmware can be reload next time */ + s2255_reset_dsppower(dev); s2255_exit_v4l(dev); - /* - * device unregistered so no longer possible to open. open_mutex - * can be unlocked and timers deleted afterwards. - */ - mutex_unlock(&dev->open_lock); - /* board shutdown stops the read pipe if it is running */ s2255_board_shutdown(dev); - /* make sure firmware still not trying to load */ del_timer(&dev->timer); /* only started in .probe and .open */ @@ -1608,23 +1666,19 @@ static void s2255_destroy(struct kref *kref) usb_free_urb(dev->fw_data->fw_urb); dev->fw_data->fw_urb = NULL; } - - /* - * delete the dsp_wait timer, which sets the firmware - * state on completion. This is done before fw_data - * is freed below. - */ - - del_timer(&dev->fw_data->dsp_wait); /* only started in .open */ - if (dev->fw_data->fw) release_firmware(dev->fw_data->fw); kfree(dev->fw_data->pfw_data); kfree(dev->fw_data); - usb_put_dev(dev->udev); dprintk(1, "%s", __func__); kfree(dev); + + while (!list_empty(&s2255_devlist)) { + list = s2255_devlist.next; + list_del(list); + } + mutex_unlock(&dev->open_lock); } static int s2255_close(struct inode *inode, struct file *file) @@ -1760,18 +1814,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev) static void s2255_exit_v4l(struct s2255_dev *dev) { - struct list_head *list; + int i; - /* unregister the video devices */ - while (!list_empty(&s2255_devlist)) { - list = s2255_devlist.next; - list_del(list); - } for (i = 0; i < MAX_CHANNELS; i++) { - if (-1 != dev->vdev[i]->minor) + if (-1 != dev->vdev[i]->minor) { video_unregister_device(dev->vdev[i]); - else + printk(KERN_INFO "s2255 unregistered\n"); + } else { video_device_release(dev->vdev[i]); + printk(KERN_INFO "s2255 released\n"); + } } } @@ -1781,134 +1833,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev) * function again). * * Received frame structure: - * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER) + * bytes 0-3: marker : 0x2255DA4AL (S2255_MARKER_FRAME) * bytes 4-7: channel: 0-3 * bytes 8-11: payload size: size of the frame * bytes 12-payloadsize+12: frame data */ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) { - static int dbgsync; /* = 0; */ char *pdest; u32 offset = 0; - int bsync = 0; - int btrunc = 0; + int bframe = 0; char *psrc; unsigned long copy_size; unsigned long size; s32 idx = -1; struct s2255_framei *frm; unsigned char *pdata; - unsigned long cur_size; - int bsearch = 0; - struct s2255_bufferi *buf; + dprintk(100, "buffer to user\n"); idx = dev->cur_frame[dev->cc]; - buf = &dev->buffer[dev->cc]; - frm = &buf->frame[idx]; - - if (frm->ulState == 0) { - frm->ulState = 1; - frm->cur_size = 0; - bsearch = 1; - } else if (frm->ulState == 2) { - /* system frame was not freed */ - dprintk(2, "sys frame not free. overrun ringbuf\n"); - bsearch = 1; - frm->ulState = 1; - frm->cur_size = 0; - } - - if (bsearch) { - if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) { - u32 jj; - if (dbgsync == 0) { - dprintk(3, "not synched, discarding all packets" - "until marker\n"); + frm = &dev->buffer[dev->cc].frame[idx]; - dbgsync++; - } - pdata = (unsigned char *)pipe_info->transfer_buffer; - for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); - jj++) { - if (*(s32 *) pdata == FRAME_MARKER) { - int cc; - dprintk(3, - "found frame marker at offset:" - " %d [%x %x]\n", jj, pdata[0], - pdata[1]); - offset = jj; - bsync = 1; - cc = *(u32 *) (pdata + sizeof(u32)); - if (cc >= MAX_CHANNELS) { - printk(KERN_ERR - "bad channel\n"); - return -EINVAL; - } - /* reverse it */ - dev->cc = G_chnmap[cc]; + if (frm->ulState == S2255_READ_IDLE) { + int jj; + unsigned int cc; + s32 *pdword; + int payload; + /* search for marker codes */ + pdata = (unsigned char *)pipe_info->transfer_buffer; + for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { + switch (*(s32 *) pdata) { + case S2255_MARKER_FRAME: + pdword = (s32 *)pdata; + dprintk(4, "found frame marker at offset:" + " %d [%x %x]\n", jj, pdata[0], + pdata[1]); + offset = jj + PREFIX_SIZE; + bframe = 1; + cc = pdword[1]; + if (cc >= MAX_CHANNELS) { + printk(KERN_ERR + "bad channel\n"); + return -EINVAL; + } + /* reverse it */ + dev->cc = G_chnmap[cc]; + payload = pdword[3]; + if (payload > dev->req_image_size[dev->cc]) { + dev->bad_payload[dev->cc]++; + /* discard the bad frame */ + return -EINVAL; + } + dev->pkt_size[dev->cc] = payload; + dev->jpg_size[dev->cc] = pdword[4]; + break; + case S2255_MARKER_RESPONSE: + pdword = (s32 *)pdata; + pdata += DEF_USB_BLOCK; + jj += DEF_USB_BLOCK; + if (pdword[1] >= MAX_CHANNELS) + break; + cc = G_chnmap[pdword[1]]; + if (!(cc >= 0 && cc < MAX_CHANNELS)) + break; + switch (pdword[2]) { + case 0x01: + /* check if channel valid */ + /* set mode ready */ + dev->setmode_ready[cc] = 1; + wake_up(&dev->wait_setmode[cc]); + dprintk(5, "setmode ready %d\n", cc); break; + case 0x10: + + dev->chn_ready |= (1 << cc); + if ((dev->chn_ready & 0x0f) != 0x0f) + break; + /* all channels ready */ + printk(KERN_INFO "s2255: fw loaded\n"); + atomic_set(&dev->fw_data->fw_state, + S2255_FW_SUCCESS); + wake_up(&dev->fw_data->wait_fw); + break; + default: + printk(KERN_INFO "s2255 unknwn resp\n"); } + default: pdata++; + break; } - if (bsync == 0) - return -EINVAL; - } else { - u32 *pword; - u32 payload; - int cc; - dbgsync = 0; - bsync = 1; - pword = (u32 *) pipe_info->transfer_buffer; - cc = pword[1]; - - if (cc >= MAX_CHANNELS) { - printk("invalid channel found. " - "throwing out data!\n"); - return -EINVAL; - } - dev->cc = G_chnmap[cc]; - payload = pword[2]; - if (payload != dev->req_image_size[dev->cc]) { - dprintk(1, "[%d][%d]unexpected payload: %d" - "required: %lu \n", cc, dev->cc, - payload, dev->req_image_size[dev->cc]); - dev->bad_payload[dev->cc]++; - /* discard the bad frame */ - return -EINVAL; - } - - } - } - /* search done. now find out if should be acquiring - on this channel */ - if (!dev->b_acquire[dev->cc]) { - frm->ulState = 0; - return -EINVAL; + if (bframe) + break; + } /* for */ + if (!bframe) + return -EINVAL; } + idx = dev->cur_frame[dev->cc]; frm = &dev->buffer[dev->cc].frame[idx]; - if (frm->ulState == 0) { - frm->ulState = 1; - frm->cur_size = 0; - } else if (frm->ulState == 2) { - /* system frame ring buffer overrun */ - dprintk(2, "sys frame overrun. overwriting frame %d %d\n", - dev->cc, idx); - frm->ulState = 1; - frm->cur_size = 0; + /* search done. now find out if should be acquiring on this channel */ + if (!dev->b_acquire[dev->cc]) { + /* we found a frame, but this channel is turned off */ + frm->ulState = S2255_READ_IDLE; + return -EINVAL; } - if (bsync) { - /* skip the marker 512 bytes (and offset if out of sync) */ - psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE; - } else { - psrc = (u8 *)pipe_info->transfer_buffer; + if (frm->ulState == S2255_READ_IDLE) { + frm->ulState = S2255_READ_FRAME; + frm->cur_size = 0; } + /* skip the marker 512 bytes (and offset if out of sync) */ + psrc = (u8 *)pipe_info->transfer_buffer + offset; + + if (frm->lpvbits == NULL) { dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d", frm, dev, dev->cc, idx); @@ -1917,33 +1958,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) pdest = frm->lpvbits + frm->cur_size; - if (bsync) { - copy_size = - (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE; - if (copy_size > pipe_info->cur_transfer_size) { - printk("invalid copy size, overflow!\n"); - return -ENOMEM; - } - } else { - copy_size = pipe_info->cur_transfer_size; - } + copy_size = (pipe_info->cur_transfer_size - offset); - cur_size = frm->cur_size; - size = dev->req_image_size[dev->cc]; + size = dev->pkt_size[dev->cc] - PREFIX_SIZE; - if ((copy_size + cur_size) > size) { - copy_size = size - cur_size; - btrunc = 1; - } + /* sanity check on pdest */ + if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc]) + memcpy(pdest, psrc, copy_size); - memcpy(pdest, psrc, copy_size); - cur_size += copy_size; frm->cur_size += copy_size; - dprintk(50, "cur_size size %lu size %lu \n", cur_size, size); + dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size); + + if (frm->cur_size >= size) { - if (cur_size >= (size - PREFIX_SIZE)) { u32 cc = dev->cc; - frm->ulState = 2; dprintk(2, "****************[%d]Buffer[%d]full*************\n", cc, idx); dev->last_frame[cc] = dev->cur_frame[cc]; @@ -1952,16 +1980,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) if ((dev->cur_frame[cc] == SYS_FRAMES) || (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) dev->cur_frame[cc] = 0; - - /* signal the semaphore for this channel */ + /* frame ready */ if (dev->b_acquire[cc]) - s2255_got_frame(dev, cc); + s2255_got_frame(dev, cc, dev->jpg_size[cc]); dev->frame_count[cc]++; - } - /* frame was truncated */ - if (btrunc) { - /* return more data to process */ - return EAGAIN; + frm->ulState = S2255_READ_IDLE; + frm->cur_size = 0; + } /* done successfully */ return 0; @@ -1980,8 +2005,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev, } /* otherwise copy to the system buffers */ res = save_frame(dev, pipe_info); - if (res == EAGAIN) - save_frame(dev, pipe_info); + if (res != 0) + dprintk(4, "s2255: read callback failed\n"); dprintk(50, "callback read video done\n"); return; @@ -2101,11 +2126,9 @@ static int s2255_board_init(struct s2255_dev *dev) memset(pipe, 0, sizeof(*pipe)); pipe->dev = dev; - pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK; - pipe->max_transfer_size = MAX_PIPE_USBBLOCK; + pipe->cur_transfer_size = S2255_USB_XFER_SIZE; + pipe->max_transfer_size = S2255_USB_XFER_SIZE; - if (pipe->cur_transfer_size > pipe->max_transfer_size) - pipe->cur_transfer_size = pipe->max_transfer_size; pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, GFP_KERNEL); if (pipe->transfer_buffer == NULL) { @@ -2329,7 +2352,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) kfree(buffer); dev->b_acquire[chn] = 0; - return 0; + return res; } static void s2255_stop_readpipe(struct s2255_dev *dev) @@ -2365,8 +2388,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) return; } -static void s2255_fwload_start(struct s2255_dev *dev) +static void s2255_fwload_start(struct s2255_dev *dev, int reset) { + if (reset) + s2255_reset_dsppower(dev); dev->fw_data->fw_size = dev->fw_data->fw->size; atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED); memcpy(dev->fw_data->pfw_data, @@ -2389,6 +2414,8 @@ static int s2255_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *endpoint; int i; int retval = -ENOMEM; + __le32 *pdata; + int fw_size; dprintk(2, "s2255: probe\n"); @@ -2443,6 +2470,8 @@ static int s2255_probe(struct usb_interface *interface, dev->timer.data = (unsigned long)dev->fw_data; init_waitqueue_head(&dev->fw_data->wait_fw); + for (i = 0; i < MAX_CHANNELS; i++) + init_waitqueue_head(&dev->wait_setmode[i]); dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2462,16 +2491,30 @@ static int s2255_probe(struct usb_interface *interface, printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); goto error; } + /* check the firmware is valid */ + fw_size = dev->fw_data->fw->size; + pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; + if (*pdata != S2255_FW_MARKER) { + printk(KERN_INFO "Firmware invalid.\n"); + retval = -ENODEV; + goto error; + } else { + /* make sure firmware is the latest */ + __le32 *pRel; + pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; + printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); + } /* loads v4l specific */ s2255_probe_v4l(dev); + usb_reset_device(dev->udev); /* load 2255 board specific */ s2255_board_init(dev); dprintk(4, "before probe done %p\n", dev); spin_lock_init(&dev->slock); - s2255_fwload_start(dev); + s2255_fwload_start(dev, 0); dev_info(&interface->dev, "Sensoray 2255 detected\n"); return 0; error: @@ -2482,14 +2525,30 @@ error: static void s2255_disconnect(struct usb_interface *interface) { struct s2255_dev *dev = NULL; + int i; dprintk(1, "s2255: disconnect interface %p\n", interface); dev = usb_get_intfdata(interface); + + /* + * wake up any of the timers to allow open_lock to be + * acquired sooner + */ + atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); + wake_up(&dev->fw_data->wait_fw); + for (i = 0; i < MAX_CHANNELS; i++) { + dev->setmode_ready[i] = 1; + wake_up(&dev->wait_setmode[i]); + } + + mutex_lock(&dev->open_lock); + usb_set_intfdata(interface, NULL); + mutex_unlock(&dev->open_lock); + if (dev) { kref_put(&dev->kref, s2255_destroy); dprintk(1, "s2255drv: disconnect\n"); dev_info(&interface->dev, "s2255usb now disconnected\n"); } - usb_set_intfdata(interface, NULL); } static struct usb_driver s2255_driver = { -- GitLab From 9b0ae867a6fd3035e97e6c33bc07a5bfd7c0f96c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 22 Aug 2008 17:25:10 -0300 Subject: [PATCH 4005/5416] V4L/DVB (8754): uvcvideo: Implement the USB power management reset_resume method. When a suspended device has been reset instead of being resumed, USB core calls the reset_resume method if available instead of unbinding and rebinding the device. This patch implements reset_resume by reusing the current resume implementation and simplifies the resume method by skipping the controls restore stage. Resuming from autosuspend should be faster. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 7e102034d38..4a2d09988fa 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) return uvc_video_suspend(&dev->video); } -static int uvc_resume(struct usb_interface *intf) +static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); int ret; @@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf) intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { - if ((ret = uvc_ctrl_resume_device(dev)) < 0) + if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) return ret; return uvc_status_resume(dev); @@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf) return uvc_video_resume(&dev->video); } +static int uvc_resume(struct usb_interface *intf) +{ + return __uvc_resume(intf, 0); +} + +static int uvc_reset_resume(struct usb_interface *intf) +{ + return __uvc_resume(intf, 1); +} + /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ @@ -1952,6 +1962,7 @@ struct uvc_driver uvc_driver = { .disconnect = uvc_disconnect, .suspend = uvc_suspend, .resume = uvc_resume, + .reset_resume = uvc_reset_resume, .id_table = uvc_ids, .supports_autosuspend = 1, }, -- GitLab From a928880a5b65aa64bbbac880cdc65de85827ba20 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 22 Aug 2008 20:46:43 -0300 Subject: [PATCH 4006/5416] V4L/DVB (8770): cx18: get rid of ununsed buffers stolen field cx18: get rid of ununsed buffers stolen field. It's an unused holdover from ivtv. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 1 - drivers/media/video/cx18/cx18-streams.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 4801bc7fb5b..db7483bea44 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -259,7 +259,6 @@ struct cx18_stream { /* Buffer Stats */ u32 buffers; u32 buf_size; - u32 buffers_stolen; /* Buffer Queues */ struct cx18_queue q_free; /* free buffers */ diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 0da57f583bf..45dc6f399ed 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -432,7 +432,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) default: return -EINVAL; } - s->buffers_stolen = 0; /* mute/unmute video */ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, -- GitLab From 59ba2b002265f2e862aa7f0df3f13c09ea99c4da Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 22 Aug 2008 20:55:54 -0300 Subject: [PATCH 4007/5416] V4L/DVB (8771): cx18: Remove redundant struct cx18_queue length member. cx18: Remove redundant struct cx18_queue length member. It can be trivially computed from queue->buffers * stream->buf_size, if ever really needed. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 1 - drivers/media/video/cx18/cx18-fileops.c | 2 +- drivers/media/video/cx18/cx18-queue.c | 6 ------ 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index db7483bea44..28c490b1b64 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -217,7 +217,6 @@ struct cx18_buffer { struct cx18_queue { struct list_head list; u32 buffers; - u32 length; u32 bytesused; }; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 1e537fe04a2..2fdbfb994dd 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -509,7 +509,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) CX18_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); - if (s->q_full.length || s->q_io.length) + if (s->q_full.buffers || s->q_io.buffers) return POLLIN | POLLRDNORM; if (eof) return POLLHUP; diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index dbe792ac300..4f3bd43ba80 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -38,7 +38,6 @@ void cx18_queue_init(struct cx18_queue *q) { INIT_LIST_HEAD(&q->list); q->buffers = 0; - q->length = 0; q->bytesused = 0; } @@ -56,7 +55,6 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, spin_lock_irqsave(&s->qlock, flags); list_add_tail(&buf->list, &q->list); q->buffers++; - q->length += s->buf_size; q->bytesused += buf->bytesused - buf->readpos; spin_unlock_irqrestore(&s->qlock, flags); } @@ -71,7 +69,6 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) buf = list_entry(q->list.next, struct cx18_buffer, list); list_del_init(q->list.next); q->buffers--; - q->length -= s->buf_size; q->bytesused -= buf->bytesused - buf->readpos; } spin_unlock_irqrestore(&s->qlock, flags); @@ -96,9 +93,7 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, they are not moved to the full queue */ if (s->type != CX18_ENC_STREAM_TYPE_TS) { s->q_free.buffers--; - s->q_free.length -= s->buf_size; s->q_full.buffers++; - s->q_full.length += s->buf_size; s->q_full.bytesused += buf->bytesused; list_move_tail(&buf->list, &s->q_full.list); } @@ -125,7 +120,6 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) list_move_tail(q->list.next, &s->q_free.list); buf->bytesused = buf->readpos = buf->b_flags = 0; s->q_free.buffers++; - s->q_free.length += s->buf_size; } cx18_queue_init(q); spin_unlock_irqrestore(&s->qlock, flags); -- GitLab From b04bce476c57ac844962462ee4c813c44fa942cf Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 22 Aug 2008 21:03:11 -0300 Subject: [PATCH 4008/5416] V4L/DVB (8772): cx18: Convert cx18_queue buffers member to atomic_t cx18: Convert cx18_queue buffers member to atomic_t. This allows safe concurrent access to check if a queue has data without having to acquire the queue spinlock. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 2 +- drivers/media/video/cx18/cx18-fileops.c | 4 ++-- drivers/media/video/cx18/cx18-ioctl.c | 3 ++- drivers/media/video/cx18/cx18-queue.c | 12 ++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 28c490b1b64..8812a5ec635 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -216,7 +216,7 @@ struct cx18_buffer { struct cx18_queue { struct list_head list; - u32 buffers; + atomic_t buffers; u32 bytesused; }; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 2fdbfb994dd..eb0144f9556 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -223,7 +223,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); /* New buffers might have become available before we were added to the waitqueue */ - if (!s->q_full.buffers) + if (!atomic_read(&s->q_full.buffers)) schedule(); finish_wait(&s->waitq, &wait); if (signal_pending(current)) { @@ -509,7 +509,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) CX18_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); - if (s->q_full.buffers || s->q_io.buffers) + if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers)) return POLLIN | POLLRDNORM; if (eof) return POLLHUP; diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index a7f839631d6..5325c7aacaf 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -731,7 +731,8 @@ static int cx18_log_status(struct file *file, void *fh) continue; CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, - (s->buffers - s->q_free.buffers) * 100 / s->buffers, + (s->buffers - atomic_read(&s->q_free.buffers)) + * 100 / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 4f3bd43ba80..a33ba04a268 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -37,7 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf) void cx18_queue_init(struct cx18_queue *q) { INIT_LIST_HEAD(&q->list); - q->buffers = 0; + atomic_set(&q->buffers, 0); q->bytesused = 0; } @@ -54,7 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, } spin_lock_irqsave(&s->qlock, flags); list_add_tail(&buf->list, &q->list); - q->buffers++; + atomic_inc(&q->buffers); q->bytesused += buf->bytesused - buf->readpos; spin_unlock_irqrestore(&s->qlock, flags); } @@ -68,7 +68,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) if (!list_empty(&q->list)) { buf = list_entry(q->list.next, struct cx18_buffer, list); list_del_init(q->list.next); - q->buffers--; + atomic_dec(&q->buffers); q->bytesused -= buf->bytesused - buf->readpos; } spin_unlock_irqrestore(&s->qlock, flags); @@ -92,8 +92,8 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, /* the transport buffers are handled differently, they are not moved to the full queue */ if (s->type != CX18_ENC_STREAM_TYPE_TS) { - s->q_free.buffers--; - s->q_full.buffers++; + atomic_dec(&s->q_free.buffers); + atomic_inc(&s->q_full.buffers); s->q_full.bytesused += buf->bytesused; list_move_tail(&buf->list, &s->q_full.list); } @@ -119,7 +119,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) buf = list_entry(q->list.next, struct cx18_buffer, list); list_move_tail(q->list.next, &s->q_free.list); buf->bytesused = buf->readpos = buf->b_flags = 0; - s->q_free.buffers++; + atomic_inc(&s->q_free.buffers); } cx18_queue_init(q); spin_unlock_irqrestore(&s->qlock, flags); -- GitLab From d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbe Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 23 Aug 2008 16:42:29 -0300 Subject: [PATCH 4009/5416] V4L/DVB (8773): cx18: Fix cx18_find_handle() and add error checking cx18: Fix cx18_find_handle() and add error checking. cx18_find_handle() did not find a good task handle and would use the invalid task handle under common conditions. Added a define for the invalid task handle and added error checking as well. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 2 ++ drivers/media/video/cx18/cx18-fileops.c | 43 +++++++++++++++++-------- drivers/media/video/cx18/cx18-ioctl.c | 17 ++++++++-- drivers/media/video/cx18/cx18-streams.c | 8 ++--- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 8812a5ec635..26359897d14 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -236,6 +236,8 @@ struct cx18_dvb { struct cx18; /* forward reference */ struct cx18_scb; /* forward reference */ +#define CX18_INVALID_TASK_HANDLE 0xffffffff + struct cx18_stream { /* These first four fields are always set, even if the stream is not actually created. */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index eb0144f9556..5f908990754 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx) u16 new_stereo_mode; const u16 stereo_mask = 0x0300; const u16 dual = 0x0200; + u32 h; new_stereo_mode = cx->params.audio_properties & stereo_mask; memset(&vt, 0, sizeof(vt)); @@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx) if (new_stereo_mode == cx->dualwatch_stereo_mode) return; - new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask); + new_bitmap = new_stereo_mode + | (cx->params.audio_properties & ~stereo_mask); - CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n", - cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); + CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. " + "new audio_bitmask=0x%ux\n", + cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); - if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2, - cx18_find_handle(cx), new_bitmap) == 0) { + h = cx18_find_handle(cx); + if (h == CX18_INVALID_TASK_HANDLE) { + CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n"); + return; + } + + if (cx18_vapi(cx, + CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) { cx->dualwatch_stereo_mode = new_stereo_mode; return; } @@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) void cx18_mute(struct cx18 *cx) { - if (atomic_read(&cx->ana_capturing)) - cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, - cx18_find_handle(cx), 1); + u32 h; + if (atomic_read(&cx->ana_capturing)) { + h = cx18_find_handle(cx); + if (h != CX18_INVALID_TASK_HANDLE) + cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1); + else + CX18_ERR("Can't find valid task handle for mute\n"); + } CX18_DEBUG_INFO("Mute\n"); } void cx18_unmute(struct cx18 *cx) { + u32 h; if (atomic_read(&cx->ana_capturing)) { - cx18_msleep_timeout(100, 0); - cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, - cx18_find_handle(cx), 12); - cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, - cx18_find_handle(cx), 0); + h = cx18_find_handle(cx); + if (h != CX18_INVALID_TASK_HANDLE) { + cx18_msleep_timeout(100, 0); + cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12); + cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0); + } else + CX18_ERR("Can't find valid task handle for unmute\n"); } CX18_DEBUG_INFO("Unmute\n"); } diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 5325c7aacaf..84507a39f2b 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -622,6 +622,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh, { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; + u32 h; switch (enc->cmd) { case V4L2_ENC_CMD_START: @@ -643,8 +644,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh, return -EPERM; if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; + h = cx18_find_handle(cx); + if (h == CX18_INVALID_TASK_HANDLE) { + CX18_ERR("Can't find valid task handle for " + "V4L2_ENC_CMD_PAUSE\n"); + return -EBADFD; + } cx18_mute(cx); - cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx)); + cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h); break; case V4L2_ENC_CMD_RESUME: @@ -654,7 +661,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh, return -EPERM; if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) return 0; - cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx)); + h = cx18_find_handle(cx); + if (h == CX18_INVALID_TASK_HANDLE) { + CX18_ERR("Can't find valid task handle for " + "V4L2_ENC_CMD_RESUME\n"); + return -EBADFD; + } + cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h); cx18_unmute(cx); break; diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 45dc6f399ed..53c5852bba3 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -119,7 +119,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; - s->handle = 0xffffffff; + s->handle = CX18_INVALID_TASK_HANDLE; s->dma = cx18_stream_info[type].dma; s->buf_size = cx->stream_buf_size[type]; @@ -548,7 +548,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) clear_bit(CX18_F_S_STREAMING, &s->s_flags); cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); - s->handle = 0xffffffff; + s->handle = CX18_INVALID_TASK_HANDLE; if (atomic_read(&cx->tot_capturing) > 0) return 0; @@ -567,8 +567,8 @@ u32 cx18_find_handle(struct cx18 *cx) for (i = 0; i < CX18_MAX_STREAMS; i++) { struct cx18_stream *s = &cx->streams[i]; - if (s->v4l2dev && s->handle) + if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE)) return s->handle; } - return 0; + return CX18_INVALID_TASK_HANDLE; } -- GitLab From 3b5df8ea40ac533c62b8e5f9f173d985665fc752 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 23 Aug 2008 18:36:50 -0300 Subject: [PATCH 4010/5416] V4L/DVB (8774): cx18: Have CX23418 release buffers at end of capture. cx18: Have CX23418 release buffers at end of capture. The CX23418 reuses task handles so we need to have it release the buffers associated with a task handle at the end of a capture. If we don't, buffer ids used for one type of stream in the driver (MPEG, TS, PCM), could be used for another type of stream by the CX23418, if a previously used handle is assigned to a different type of stream. The driver would drop valid buffers when this happened. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-mailbox.c | 1 + drivers/media/video/cx18/cx18-streams.c | 10 ++++++++++ drivers/media/video/cx18/cx23418.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 93177514e84..1b9fbf9a6bc 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -82,6 +82,7 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), + API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), API_ENTRY(0, 0, 0), }; diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 53c5852bba3..4d5b446895c 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -488,7 +488,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { CX18_DEBUG_WARN("Error starting capture!\n"); + /* Ensure we're really not capturing before releasing MDLs */ + if (s->type == CX18_ENC_STREAM_TYPE_MPG) + cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); + else + cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); + cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); + /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */ return -EINVAL; } @@ -540,6 +547,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); } + /* Tell the CX23418 it can't use our buffers anymore */ + cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); + if (s->type != CX18_ENC_STREAM_TYPE_TS) atomic_dec(&cx->ana_capturing); atomic_dec(&cx->tot_capturing); diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index e7ed053059a..668f968d776 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h @@ -351,7 +351,7 @@ Descriptor Lists to the driver IN[0] - Task handle. Handle of the task to start ReturnCode - One of the ERR_DE_... */ -/* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */ +#define CX18_CPU_DE_RELEASE_MDL (CPU_CMD_MASK_DE | 0x0006) /* Description: This command signals the cpu that the dat buffer has been consumed and ready for re-use. -- GitLab From 3ca685aae04960eaa8b2c97baf384996c20cf9ac Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 04:49:13 -0300 Subject: [PATCH 4011/5416] V4L/DVB (8776): radio: replace video_exclusive_open/release Move the video_exclusive_open/release functionality into the driver itself. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-aimslab.c | 16 ++++++++++++++-- drivers/media/radio/radio-aztech.c | 16 ++++++++++++++-- drivers/media/radio/radio-gemtek-pci.c | 18 ++++++++++++++---- drivers/media/radio/radio-gemtek.c | 16 ++++++++++++++-- drivers/media/radio/radio-maestro.c | 18 ++++++++++++++++-- drivers/media/radio/radio-maxiradio.c | 16 ++++++++++++++-- drivers/media/radio/radio-rtrack2.c | 16 ++++++++++++++-- drivers/media/radio/radio-sf16fmi.c | 16 ++++++++++++++-- drivers/media/radio/radio-sf16fmr2.c | 16 ++++++++++++++-- drivers/media/radio/radio-terratec.c | 16 ++++++++++++++-- drivers/media/radio/radio-trust.c | 16 ++++++++++++++-- drivers/media/radio/radio-typhoon.c | 20 +++++++++++++++----- drivers/media/radio/radio-zoltrix.c | 16 ++++++++++++++-- 13 files changed, 185 insertions(+), 31 deletions(-) diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 1f064f4b32d..b657c7bb47c 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -51,6 +51,7 @@ static struct mutex lock; struct rt_device { + unsigned long in_use; int port; int curvol; unsigned long curfreq; @@ -378,10 +379,21 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct rt_device rtrack_unit; +static int rtrack_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; +} + +static int rtrack_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &rtrack_unit.in_use); + return 0; +} + static const struct file_operations rtrack_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = rtrack_exclusive_open, + .release = rtrack_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 628c689e3ff..ae18a7cf0d5 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -70,6 +70,7 @@ static struct mutex lock; struct az_device { + unsigned long in_use; int curvol; unsigned long curfreq; int stereo; @@ -342,10 +343,21 @@ static int vidioc_s_ctrl (struct file *file, void *priv, static struct az_device aztech_unit; +static int aztech_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; +} + +static int aztech_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &aztech_unit.in_use); + return 0; +} + static const struct file_operations aztech_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = aztech_exclusive_open, + .release = aztech_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 5cd7f032298..a7b9a5df4ca 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -100,9 +100,8 @@ struct gemtek_pci_card { u8 mute; }; -static const char rcsid[] = "$Id: radio-gemtek-pci.c,v 1.1 2001/07/23 08:08:16 ted Exp ted $"; - static int nr_radio = -1; +static unsigned long in_use; static inline u8 gemtek_pci_out( u16 value, u32 port ) { @@ -364,10 +363,21 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); static int mx = 1; +static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &in_use) ? -EBUSY : 0; +} + +static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &in_use); + return 0; +} + static const struct file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = gemtek_pci_exclusive_open, + .release = gemtek_pci_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 0a0f956bb30..cc90329026f 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -57,6 +57,7 @@ static int shutdown = 1; static int keepmuted = 1; static int initmute = 1; static int radio_nr = -1; +static unsigned long in_use; module_param(io, int, 0444); MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " @@ -393,10 +394,21 @@ static struct v4l2_queryctrl radio_qctrl[] = { } }; +static int gemtek_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &in_use) ? -EBUSY : 0; +} + +static int gemtek_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &in_use); + return 0; +} + static const struct file_operations gemtek_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = gemtek_exclusive_open, + .release = gemtek_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 9ef0a763eeb..03c20948eef 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -75,7 +75,21 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int radio_nr = -1; module_param(radio_nr, int, 0); +static unsigned long in_use; + static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + +static int maestro_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &in_use) ? -EBUSY : 0; +} + +static int maestro_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &in_use); + return 0; +} + static void maestro_remove(struct pci_dev *pdev); static struct pci_device_id maestro_r_pci_tbl[] = { @@ -98,8 +112,8 @@ static struct pci_driver maestro_r_driver = { static const struct file_operations maestro_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = maestro_exclusive_open, + .release = maestro_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 0cc6fcb041f..263ef8b02fd 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -85,6 +85,7 @@ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ; static int radio_nr = -1; module_param(radio_nr, int, 0); +static unsigned long in_use; #define FREQ_LO 50*16000 #define FREQ_HI 150*16000 @@ -99,10 +100,21 @@ module_param(radio_nr, int, 0); #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) +static int maxiradio_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &in_use) ? -EBUSY : 0; +} + +static int maxiradio_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &in_use); + return 0; +} + static const struct file_operations maxiradio_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = maxiradio_exclusive_open, + .release = maxiradio_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 6d820e2481e..5b93b47be71 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -52,6 +52,7 @@ static spinlock_t lock; struct rt_device { + unsigned long in_use; int port; unsigned long curfreq; int muted; @@ -284,10 +285,21 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct rt_device rtrack2_unit; +static int rtrack2_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; +} + +static int rtrack2_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &rtrack2_unit.in_use); + return 0; +} + static const struct file_operations rtrack2_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = rtrack2_exclusive_open, + .release = rtrack2_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 0d478f54a90..55f8334513f 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -45,6 +45,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { struct fmi_device { + unsigned long in_use; int port; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ @@ -284,10 +285,21 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct fmi_device fmi_unit; +static int fmi_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; +} + +static int fmi_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &fmi_unit.in_use); + return 0; +} + static const struct file_operations fmi_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = fmi_exclusive_open, + .release = fmi_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 6290553d24b..14153ed939d 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -64,6 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { /* this should be static vars for module size */ struct fmr2_device { + unsigned long in_use; int port; int curvol; /* 0-15 */ int mute; @@ -400,10 +401,21 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct fmr2_device fmr2_unit; +static int fmr2_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; +} + +static int fmr2_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &fmr2_unit.in_use); + return 0; +} + static const struct file_operations fmr2_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = fmr2_exclusive_open, + .release = fmr2_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 0876fecc5f2..eed14972a94 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -79,6 +79,7 @@ static spinlock_t lock; struct tt_device { + unsigned long in_use; int port; int curvol; unsigned long curfreq; @@ -356,10 +357,21 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct tt_device terratec_unit; +static int terratec_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; +} + +static int terratec_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &terratec_unit.in_use); + return 0; +} + static const struct file_operations terratec_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = terratec_exclusive_open, + .release = terratec_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 19316195625..dd0c425ef3b 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -78,6 +78,7 @@ static __u16 curtreble; static unsigned long curfreq; static int curstereo; static int curmute; +static unsigned long in_use; /* i2c addresses */ #define TDA7318_ADDR 0x88 @@ -336,10 +337,21 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } +static int trust_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &in_use) ? -EBUSY : 0; +} + +static int trust_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &in_use); + return 0; +} + static const struct file_operations trust_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = trust_exclusive_open, + .release = trust_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index f8d62cfea77..87846850723 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -79,7 +79,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { #endif struct typhoon_device { - int users; + unsigned long in_use; int iobase; int curvol; int muted; @@ -334,10 +334,21 @@ static struct typhoon_device typhoon_unit = .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, }; +static int typhoon_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; +} + +static int typhoon_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &typhoon_unit.in_use); + return 0; +} + static const struct file_operations typhoon_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = typhoon_exclusive_open, + .release = typhoon_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, @@ -447,8 +458,7 @@ static int __init typhoon_init(void) } typhoon_radio.priv = &typhoon_unit; - if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1) - { + if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 8); return -EINVAL; } diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 51d57ed3b3e..4d76e710194 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -69,6 +69,7 @@ static int io = CONFIG_RADIO_ZOLTRIX_PORT; static int radio_nr = -1; struct zol_device { + unsigned long in_use; int port; int curvol; unsigned long curfreq; @@ -396,11 +397,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct zol_device zoltrix_unit; +static int zoltrix_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; +} + +static int zoltrix_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &zoltrix_unit.in_use); + return 0; +} + static const struct file_operations zoltrix_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = zoltrix_exclusive_open, + .release = zoltrix_exclusive_release, .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, -- GitLab From 2f3d00250ae5b1d2727e2723da805290ec408503 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 04:52:00 -0300 Subject: [PATCH 4012/5416] V4L/DVB (8777): tea575x-tuner: replace video_exclusive_open/release Move the video_exclusive_open/release functionality into the driver itself. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/sound/tea575x-tuner.h | 1 + sound/i2c/other/tea575x-tuner.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h index b62ce3e077f..b6870cbaf2b 100644 --- a/include/sound/tea575x-tuner.h +++ b/include/sound/tea575x-tuner.h @@ -43,6 +43,7 @@ struct snd_tea575x { unsigned int freq_fixup; /* crystal onboard */ unsigned int val; /* hw value */ unsigned long freq; /* frequency */ + unsigned long in_use; /* set if the device is in use */ struct snd_tea575x_ops *ops; void *private_data; }; diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 83e90057270..621d7fe3074 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -175,6 +175,23 @@ static void snd_tea575x_release(struct video_device *vfd) { } +static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct snd_tea575x *tea = video_get_drvdata(dev); + + return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; +} + +static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct snd_tea575x *tea = video_get_drvdata(dev); + + clear_bit(0, &tea->in_use); + return 0; +} + /* * initialize all the tea575x chips */ @@ -193,9 +210,10 @@ void snd_tea575x_init(struct snd_tea575x *tea) tea->vd.release = snd_tea575x_release; video_set_drvdata(&tea->vd, tea); tea->vd.fops = &tea->fops; + tea->in_use = 0; tea->fops.owner = tea->card->module; - tea->fops.open = video_exclusive_open; - tea->fops.release = video_exclusive_release; + tea->fops.open = snd_tea575x_exclusive_open; + tea->fops.release = snd_tea575x_exclusive_release; tea->fops.ioctl = snd_tea575x_ioctl; if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) { snd_printk(KERN_ERR "unable to register tea575x tuner\n"); -- GitLab From 7d43cd53c851e3cf04d73108d4e7e25a1104c6f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 05:31:47 -0300 Subject: [PATCH 4013/5416] V4L/DVB (8780): v4l: replace the last uses of video_exclusive_open/release Handle the video_exclusive_open/release functionality inside the driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/arv.c | 19 +++++++++++--- drivers/media/video/bw-qcam.c | 21 +++++++++++++-- drivers/media/video/bw-qcam.h | 1 + drivers/media/video/c-qcam.c | 22 ++++++++++++++-- drivers/media/video/meye.c | 16 ++++-------- drivers/media/video/meye.h | 1 + drivers/media/video/pms.c | 22 ++++++++++++++-- drivers/media/video/saa5246a.c | 30 ++++++---------------- drivers/media/video/saa5249.c | 47 +++++++++++++--------------------- drivers/media/video/w9966.c | 22 ++++++++++++++-- 10 files changed, 128 insertions(+), 73 deletions(-) diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 9e436ad3d34..0d4f9b68345 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -116,6 +116,7 @@ struct ar_device { int width, height; int frame_bytes, line_bytes; wait_queue_head_t wait; + unsigned long in_use; struct mutex lock; }; @@ -742,10 +743,23 @@ void ar_release(struct video_device *vfd) * Video4Linux Module functions * ****************************************************************************/ +static struct ar_device ardev; + +static int ar_exclusive_open(struct inode *inode, struct file *file) +{ + return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; +} + +static int ar_exclusive_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &ardev.in_use); + return 0; +} + static const struct file_operations ar_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = ar_exclusive_open, + .release = ar_exclusive_release, .read = ar_read, .ioctl = ar_ioctl, #ifdef CONFIG_COMPAT @@ -762,7 +776,6 @@ static struct video_device ar_template = { }; #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) -static struct ar_device ardev; static int __init ar_init(void) { diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 01f07707827..e8e1bb122b5 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -894,10 +894,27 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } +static int qcam_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct qcam_device *qcam = (struct qcam_device *)dev; + + return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; +} + +static int qcam_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct qcam_device *qcam = (struct qcam_device *)dev; + + clear_bit(0, &qcam->in_use); + return 0; +} + static const struct file_operations qcam_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = qcam_exclusive_open, + .release = qcam_exclusive_release, .ioctl = qcam_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h index 6701dafbc0d..8a60c5de093 100644 --- a/drivers/media/video/bw-qcam.h +++ b/drivers/media/video/bw-qcam.h @@ -65,4 +65,5 @@ struct qcam_device { int top, left; int status; unsigned int saved_bits; + unsigned long in_use; }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 7f6c6b4bec1..2196c1dc5ae 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -51,6 +51,7 @@ struct qcam_device { int contrast, brightness, whitebal; int top, left; unsigned int bidirectional; + unsigned long in_use; struct mutex lock; }; @@ -687,11 +688,28 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } +static int qcam_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct qcam_device *qcam = (struct qcam_device *)dev; + + return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; +} + +static int qcam_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct qcam_device *qcam = (struct qcam_device *)dev; + + clear_bit(0, &qcam->in_use); + return 0; +} + /* video device template */ static const struct file_operations qcam_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = qcam_exclusive_open, + .release = qcam_exclusive_release, .ioctl = qcam_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 102a5b9cfd1..6418f4a78f2 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -843,21 +843,16 @@ again: static int meye_open(struct inode *inode, struct file *file) { - int i, err; + int i; - lock_kernel(); - err = video_exclusive_open(inode, file); - if (err < 0) { - unlock_kernel(); - return err; - } + if (test_and_set_bit(0, &meye.in_use)) + return -EBUSY; mchip_hic_stop(); if (mchip_dma_alloc()) { printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); - video_exclusive_release(inode, file); - unlock_kernel(); + clear_bit(0, &meye.in_use); return -ENOBUFS; } @@ -865,7 +860,6 @@ static int meye_open(struct inode *inode, struct file *file) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; kfifo_reset(meye.grabq); kfifo_reset(meye.doneq); - unlock_kernel(); return 0; } @@ -873,7 +867,7 @@ static int meye_release(struct inode *inode, struct file *file) { mchip_hic_stop(); mchip_dma_free(); - video_exclusive_release(inode, file); + clear_bit(0, &meye.in_use); return 0; } diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index d535748df44..5f70a106ba2 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -311,6 +311,7 @@ struct meye { struct video_device *video_dev; /* video device parameters */ struct video_picture picture; /* video picture parameters */ struct meye_params params; /* additional parameters */ + unsigned long in_use; /* set to 1 if the device is in use */ #ifdef CONFIG_PM u8 pm_mchip_mode; /* old mchip mode */ #endif diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7c84f795db5..b39794f0baf 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -47,6 +47,7 @@ struct pms_device struct video_picture picture; int height; int width; + unsigned long in_use; struct mutex lock; }; @@ -881,10 +882,27 @@ static ssize_t pms_read(struct file *file, char __user *buf, return len; } +static int pms_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *v = video_devdata(file); + struct pms_device *pd = (struct pms_device *)v; + + return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; +} + +static int pms_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *v = video_devdata(file); + struct pms_device *pd = (struct pms_device *)v; + + clear_bit(0, &pd->in_use); + return 0; +} + static const struct file_operations pms_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = pms_exclusive_open, + .release = pms_exclusive_release, .ioctl = pms_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index e2c538ee88f..5f5aa2063e0 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -61,6 +61,7 @@ struct saa5246a_device u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; int is_searching[NUM_DAUS]; struct i2c_client *client; + unsigned long in_use; struct mutex lock; }; @@ -736,22 +737,14 @@ static int saa5246a_open(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); struct saa5246a_device *t = vd->priv; - int err; - lock_kernel(); - err = video_exclusive_open(inode,file); - if (err < 0) { - unlock_kernel(); - return err; - } + if (t->client == NULL) + return -ENODEV; - if (t->client==NULL) { - err = -ENODEV; - goto fail; - } + if (test_and_set_bit(0, &t->in_use)) + return -EBUSY; if (i2c_senddata(t, SAA5246A_REGISTER_R0, - R0_SELECT_R11 | R0_PLL_TIME_CONSTANT_LONG | R0_ENABLE_nODD_EVEN_OUTPUT | @@ -777,17 +770,10 @@ static int saa5246a_open(struct inode *inode, struct file *file) COMMAND_END)) { - err = -EIO; - goto fail; + clear_bit(0, &t->in_use); + return -EIO; } - unlock_kernel(); - return 0; - -fail: - video_exclusive_release(inode,file); - unlock_kernel(); - return err; } static int saa5246a_release(struct inode *inode, struct file *file) @@ -806,7 +792,7 @@ static int saa5246a_release(struct inode *inode, struct file *file) R1_VCS_TO_SCS, COMMAND_END); - video_exclusive_release(inode,file); + clear_bit(0, &t->in_use); return 0; } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 96c0fdf1a05..dfd8a9338c5 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -110,6 +110,7 @@ struct saa5249_device int disp_mode; int virtual_mode; struct i2c_client *client; + unsigned long in_use; struct mutex lock; }; @@ -631,34 +632,27 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, static int saa5249_open(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5249_device *t=vd->priv; - int err,pgbuf; + struct saa5249_device *t = vd->priv; + int pgbuf; - lock_kernel(); - err = video_exclusive_open(inode,file); - if (err < 0) { - unlock_kernel(); - return err; - } + if (t->client == NULL) + return -ENODEV; - if (t->client==NULL) { - err = -ENODEV; - goto fail; - } + if (test_and_set_bit(0, &t->in_use)) + return -EBUSY; - if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ - /* Turn off parity checks (we do this ourselves) */ + if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ + /* Turn off parity checks (we do this ourselves) */ i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || - /* Display TV-picture, no virtual rows */ - i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */ - + /* Display TV-picture, no virtual rows */ + i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) + /* Set display to page 4 */ { - err = -EIO; - goto fail; + clear_bit(0, &t->in_use); + return -EIO; } - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) - { + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); @@ -668,13 +662,7 @@ static int saa5249_open(struct inode *inode, struct file *file) t->is_searching[pgbuf] = false; } t->virtual_mode = false; - unlock_kernel(); return 0; - - fail: - video_exclusive_release(inode,file); - unlock_kernel(); - return err; } @@ -682,10 +670,11 @@ static int saa5249_open(struct inode *inode, struct file *file) static int saa5249_release(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5249_device *t=vd->priv; + struct saa5249_device *t = vd->priv; + i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ - video_exclusive_release(inode,file); + clear_bit(0, &t->in_use); return 0; } diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 2ff00bc5ad6..c635cffb1fb 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -113,6 +113,7 @@ struct w9966_dev { signed char contrast; signed char color; signed char hue; + unsigned long in_use; }; /* @@ -184,10 +185,27 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); +static int w9966_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct w9966_dev *cam = vdev->priv; + + return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; +} + +static int w9966_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct w9966_dev *cam = vdev->priv; + + clear_bit(0, &cam->in_use); + return 0; +} + static const struct file_operations w9966_fops = { .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, + .open = w9966_exclusive_open, + .release = w9966_exclusive_release, .ioctl = w9966_v4l_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, -- GitLab From cb353588e1946ab709be57dd8545598793acf912 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 05:34:55 -0300 Subject: [PATCH 4014/5416] V4L/DVB (8781): v4l2-dev: remove obsolete video_exclusive_open/release Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 30 ------------------------------ include/media/v4l2-dev.h | 6 ------ 2 files changed, 36 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 8903e41628e..66bd74b58b0 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -141,34 +141,6 @@ static int video_open(struct inode *inode, struct file *file) return err; } -/* - * open/release helper functions -- handle exclusive opens - * Should be removed soon - */ -int video_exclusive_open(struct inode *inode, struct file *file) -{ - struct video_device *vfl = video_devdata(file); - int retval = 0; - - mutex_lock(&vfl->lock); - if (vfl->users) - retval = -EBUSY; - else - vfl->users++; - mutex_unlock(&vfl->lock); - return retval; -} -EXPORT_SYMBOL(video_exclusive_open); - -int video_exclusive_release(struct inode *inode, struct file *file) -{ - struct video_device *vfl = video_devdata(file); - - vfl->users--; - return 0; -} -EXPORT_SYMBOL(video_exclusive_release); - /** * get_index - assign stream number based on parent device * @vdev: video_device to assign index number to, vdev->dev should be assigned @@ -320,8 +292,6 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, goto fail_minor; } - mutex_init(&vfd->lock); - /* sysfs class */ memset(&vfd->dev, 0x00, sizeof(vfd->dev)); vfd->dev.class = &video_class; diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2745e1afc72..e472b5d07a5 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -77,10 +77,6 @@ struct video_device * Or use {pci|usb}_{get|set}_drvdata() directly. */ void *priv; #endif - - /* for videodev.c internal usage -- please don't touch */ - int users; /* video_exclusive_{open|close} ... */ - struct mutex lock; /* ... helper function uses these */ }; /* Class-dev to video-device */ @@ -111,8 +107,6 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) /* Obsolete stuff - Still needed for radio devices and obsolete drivers */ extern struct video_device* video_devdata(struct file*); -extern int video_exclusive_open(struct inode *inode, struct file *file); -extern int video_exclusive_release(struct inode *inode, struct file *file); #endif #endif /* _V4L2_DEV_H */ -- GitLab From f9e86b5e9d068854a2cf40f8003ef639e80cca6c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 05:47:41 -0300 Subject: [PATCH 4015/5416] V4L/DVB (8782): v4l2-dev: add video_device_release_empty Add a second release function: video_device_release_empty It can be used by drivers that have statically allocated video_device structs. Its use usually, but not always, indicates laziness on the part of the driver programmer. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 7 +++++++ include/media/v4l2-dev.h | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 66bd74b58b0..fda48a2efda 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -73,6 +73,13 @@ void video_device_release(struct video_device *vfd) } EXPORT_SYMBOL(video_device_release); +void video_device_release_empty(struct video_device *vfd) +{ + /* Do nothing */ + /* Only valid when the video_device struct is a static. */ +} +EXPORT_SYMBOL(video_device_release_empty); + static void video_release(struct device *cd) { struct video_device *vfd = container_of(cd, struct video_device, dev); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index e472b5d07a5..30855077be4 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -91,7 +91,12 @@ void video_unregister_device(struct video_device *); /* helper functions to alloc / release struct video_device, the later can be used for video_device->release() */ struct video_device *video_device_alloc(void); +/* this release function frees the vfd pointer */ void video_device_release(struct video_device *vfd); +/* this release function does nothing, use when the video_device is a + static global struct. Note that having a static video_device is + a dubious construction at best. */ +void video_device_release_empty(struct video_device *vfd); #ifdef OBSOLETE_DEVDATA /* to be removed soon */ /* helper functions to access driver private data. */ -- GitLab From aa5e90af7d78d1711f8f4275ce3638817c0023dc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 06:23:55 -0300 Subject: [PATCH 4016/5416] V4L/DVB (8783): v4l: add all missing video_device release callbacks All drivers that call video_device_register where checked to see if they set the release callback of struct video_device. Where that callback was missing it was added. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-aimslab.c | 1 + drivers/media/radio/radio-aztech.c | 7 ++++--- drivers/media/radio/radio-cadet.c | 1 + drivers/media/radio/radio-gemtek-pci.c | 7 ++++--- drivers/media/radio/radio-gemtek.c | 7 ++++--- drivers/media/radio/radio-maestro.c | 1 + drivers/media/radio/radio-maxiradio.c | 7 ++++--- drivers/media/radio/radio-rtrack2.c | 1 + drivers/media/radio/radio-sf16fmi.c | 1 + drivers/media/radio/radio-sf16fmr2.c | 1 + drivers/media/radio/radio-terratec.c | 1 + drivers/media/radio/radio-trust.c | 1 + drivers/media/radio/radio-typhoon.c | 1 + drivers/media/radio/radio-zoltrix.c | 1 + drivers/media/video/bw-qcam.c | 1 + drivers/media/video/c-qcam.c | 1 + drivers/media/video/cpia.c | 1 + drivers/media/video/pms.c | 1 + drivers/media/video/saa5249.c | 1 + drivers/media/video/se401.c | 1 + drivers/media/video/stradis.c | 1 + drivers/media/video/usbvideo/usbvideo.c | 6 +----- drivers/media/video/usbvideo/vicam.c | 1 + drivers/media/video/w9966.c | 1 + 24 files changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index b657c7bb47c..59fdaf85e41 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -420,6 +420,7 @@ static struct video_device rtrack_radio = { .name = "RadioTrack radio", .fops = &rtrack_fops, .ioctl_ops = &rtrack_ioctl_ops, + .release = video_device_release_empty, }; static int __init rtrack_init(void) diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index ae18a7cf0d5..ddd96295a9f 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -381,9 +381,10 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { }; static struct video_device aztech_radio = { - .name = "Aztech radio", - .fops = &aztech_fops, - .ioctl_ops = &aztech_ioctl_ops, + .name = "Aztech radio", + .fops = &aztech_fops, + .ioctl_ops = &aztech_ioctl_ops, + .release = video_device_release_empty, }; module_param_named(debug,aztech_radio.debug, int, 0644); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 04c3698d32e..0490a1fa999 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -589,6 +589,7 @@ static struct video_device cadet_radio = { .name = "Cadet radio", .fops = &cadet_fops, .ioctl_ops = &cadet_ioctl_ops, + .release = video_device_release_empty, }; #ifdef CONFIG_PNP diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index a7b9a5df4ca..d65fd287bde 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -401,9 +401,10 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { }; static struct video_device vdev_template = { - .name = "Gemtek PCI Radio", - .fops = &gemtek_pci_fops, - .ioctl_ops = &gemtek_pci_ioctl_ops, + .name = "Gemtek PCI Radio", + .fops = &gemtek_pci_fops, + .ioctl_ops = &gemtek_pci_ioctl_ops, + .release = video_device_release_empty, }; static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index cc90329026f..2d991ae2f20 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -581,9 +581,10 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { }; static struct video_device gemtek_radio = { - .name = "GemTek Radio card", - .fops = &gemtek_fops, - .ioctl_ops = &gemtek_ioctl_ops, + .name = "GemTek Radio card", + .fops = &gemtek_fops, + .ioctl_ops = &gemtek_ioctl_ops, + .release = video_device_release_empty, }; /* diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 03c20948eef..182b433981c 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -388,6 +388,7 @@ static struct video_device maestro_radio = { .name = "Maestro radio", .fops = &maestro_fops, .ioctl_ops = &maestro_ioctl_ops, + .release = video_device_release, }; static int __devinit maestro_probe(struct pci_dev *pdev, diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 263ef8b02fd..4e2e8a3d9b5 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -402,9 +402,10 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { }; static struct video_device maxiradio_radio = { - .name = "Maxi Radio FM2000 radio", - .fops = &maxiradio_fops, - .ioctl_ops = &maxiradio_ioctl_ops, + .name = "Maxi Radio FM2000 radio", + .fops = &maxiradio_fops, + .ioctl_ops = &maxiradio_ioctl_ops, + .release = video_device_release_empty, }; static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 5b93b47be71..8fe820da73e 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -326,6 +326,7 @@ static struct video_device rtrack2_radio = { .name = "RadioTrack II radio", .fops = &rtrack2_fops, .ioctl_ops = &rtrack2_ioctl_ops, + .release = video_device_release_empty, }; static int __init rtrack2_init(void) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 55f8334513f..6d865a7a91e 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -326,6 +326,7 @@ static struct video_device fmi_radio = { .name = "SF16FMx radio", .fops = &fmi_fops, .ioctl_ops = &fmi_ioctl_ops, + .release = video_device_release_empty, }; /* ladis: this is my card. does any other types exist? */ diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 14153ed939d..9625d1f0194 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -442,6 +442,7 @@ static struct video_device fmr2_radio = { .name = "SF16FMR2 radio", .fops = &fmr2_fops, .ioctl_ops = &fmr2_ioctl_ops, + .release = video_device_release_empty, }; static int __init fmr2_init(void) diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index eed14972a94..de13ec81ce4 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -398,6 +398,7 @@ static struct video_device terratec_radio = { .name = "TerraTec ActiveRadio", .fops = &terratec_fops, .ioctl_ops = &terratec_ioctl_ops, + .release = video_device_release_empty, }; static int __init terratec_init(void) diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index dd0c425ef3b..e7b111fcd10 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -378,6 +378,7 @@ static struct video_device trust_radio = { .name = "Trust FM Radio", .fops = &trust_fops, .ioctl_ops = &trust_ioctl_ops, + .release = video_device_release_empty, }; static int __init trust_init(void) diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 87846850723..c2eedb7a73a 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -375,6 +375,7 @@ static struct video_device typhoon_radio = { .name = "Typhoon Radio", .fops = &typhoon_fops, .ioctl_ops = &typhoon_ioctl_ops, + .release = video_device_release_empty, }; #ifdef CONFIG_RADIO_TYPHOON_PROC_FS diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 4d76e710194..0d43e8401eb 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -439,6 +439,7 @@ static struct video_device zoltrix_radio = { .name = "Zoltrix Radio Plus", .fops = &zoltrix_fops, .ioctl_ops = &zoltrix_ioctl_ops, + .release = video_device_release_empty, }; static int __init zoltrix_init(void) diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index e8e1bb122b5..ace4ff9ea02 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -926,6 +926,7 @@ static struct video_device qcam_template= { .name = "Connectix Quickcam", .fops = &qcam_fops, + .release = video_device_release_empty, }; #define MAX_CAMS 4 diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 2196c1dc5ae..17aa0adb346 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -722,6 +722,7 @@ static struct video_device qcam_template= { .name = "Colour QuickCam", .fops = &qcam_fops, + .release = video_device_release_empty, }; /* Initialize the QuickCam driver control structure. */ diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index a661800b0e6..c0600fdbfc6 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3801,6 +3801,7 @@ static const struct file_operations cpia_fops = { static struct video_device cpia_template = { .name = "CPiA Camera", .fops = &cpia_fops, + .release = video_device_release_empty, }; /* initialise cam_data structure */ diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index b39794f0baf..994807818aa 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -915,6 +915,7 @@ static struct video_device pms_template= { .name = "Mediavision PMS", .fops = &pms_fops, + .release = video_device_release_empty, }; static struct pms_device pms_device; diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index dfd8a9338c5..225117c789c 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -708,6 +708,7 @@ static struct video_device saa_template = { .name = IF_NAME, .fops = &saa_fops, + .release = video_device_release, }; MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index d16bbf0d278..b01f25d7292 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1236,6 +1236,7 @@ static const struct file_operations se401_fops = { static struct video_device se401_template = { .name = "se401 USB camera", .fops = &se401_fops, + .release = video_device_release_empty, }; diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index a3cbe9be3c1..bbad54f85c8 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1925,6 +1925,7 @@ static struct video_device saa_template = { .name = "SAA7146A", .fops = &saa_fops, .minor = -1, + .release = video_device_release_empty, }; static int __devinit configure_saa7146(struct pci_dev *pdev, int num) diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 6b1b2003a65..9569e8ced4b 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1006,10 +1006,6 @@ allocate_done: EXPORT_SYMBOL(usbvideo_AllocateDevice); -static void usbvideo_dummy_release(struct video_device *vfd) -{ -} - int usbvideo_RegisterVideoDevice(struct uvd *uvd) { char tmp1[20], tmp2[20]; /* Buffers for printing */ @@ -1043,7 +1039,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) return -EINVAL; } uvd->vdev.parent = &uvd->dev->dev; - uvd->vdev.release = usbvideo_dummy_release; + uvd->vdev.release = video_device_release_empty; if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { err("%s: video_register_device failed", __func__); return -EPIPE; diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index efb878a7402..d7728256f29 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -801,6 +801,7 @@ static struct video_device vicam_template = { .name = "ViCam-based USB Camera", .fops = &vicam_fops, .minor = -1, + .release = video_device_release_empty, }; /* table of devices that work with this driver */ diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index c635cffb1fb..e3580119640 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -216,6 +216,7 @@ static const struct file_operations w9966_fops = { static struct video_device w9966_template = { .name = W9966_DRIVERNAME, .fops = &w9966_fops, + .release = video_device_release_empty, }; /* -- GitLab From d6e7497eaf9889d39a070f60309a9bcea1fd29f6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 06:27:59 -0300 Subject: [PATCH 4017/5416] V4L/DVB (8784): v4l2-dev: make the video_device's release callback mandatory Now that all drivers set the release callback in the video_device struct we can put in a BUG_ON in video_register_device to ensure that the callback is always there. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index fda48a2efda..ff219df4b72 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -84,11 +84,6 @@ static void video_release(struct device *cd) { struct video_device *vfd = container_of(cd, struct video_device, dev); -#if 1 - /* needed until all drivers are fixed */ - if (!vfd->release) - return; -#endif vfd->release(vfd); } @@ -233,8 +228,8 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int ret; char *name_base; - if (vfd == NULL) - return -EINVAL; + /* the release callback MUST be present */ + BUG_ON(!vfd->release); if (vfd == NULL) return -EINVAL; @@ -312,13 +307,6 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, goto fail_minor; } -#if 1 - /* needed until all drivers are fixed */ - if (!vfd->release) - printk(KERN_WARNING "videodev: \"%s\" has no release callback. " - "Please fix your driver for proper sysfs support, see " - "http://lwn.net/Articles/36850/\n", vfd->name); -#endif return 0; fail_minor: -- GitLab From e138c592b50370621653fd962b2bc3f4e25dfe78 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 06:38:11 -0300 Subject: [PATCH 4018/5416] V4L/DVB (8785): v4l2: add __must_check to v4l2_dev.h Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-dev.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 30855077be4..23df00919ae 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -83,14 +83,14 @@ struct video_device #define to_video_device(cd) container_of(cd, struct video_device, dev) /* Version 2 functions */ -extern int video_register_device(struct video_device *vfd, int type, int nr); -int video_register_device_index(struct video_device *vfd, int type, int nr, +int __must_check video_register_device(struct video_device *vfd, int type, int nr); +int __must_check video_register_device_index(struct video_device *vfd, int type, int nr, int index); void video_unregister_device(struct video_device *); /* helper functions to alloc / release struct video_device, the later can be used for video_device->release() */ -struct video_device *video_device_alloc(void); +struct video_device * __must_check video_device_alloc(void); /* this release function frees the vfd pointer */ void video_device_release(struct video_device *vfd); /* this release function does nothing, use when the video_device is a -- GitLab From 601e9444f249d219009ec05674268d90f6f1cdcb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 07:24:07 -0300 Subject: [PATCH 4019/5416] V4L/DVB (8786): v4l2: remove the priv field, use dev_get_drvdata instead Remove the priv field and let video_get/set_drvdata use dev_get_drvdata and dev_set_drvdata instead. Convert all drivers that still used priv directly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_fops.c | 2 +- drivers/media/radio/radio-aimslab.c | 12 ++++++------ drivers/media/radio/radio-aztech.c | 12 ++++++------ drivers/media/radio/radio-gemtek-pci.c | 12 ++++++------ drivers/media/radio/radio-gemtek.c | 10 +++++----- drivers/media/radio/radio-maxiradio.c | 12 ++++++------ drivers/media/radio/radio-rtrack2.c | 12 ++++++------ drivers/media/radio/radio-sf16fmi.c | 12 ++++++------ drivers/media/radio/radio-sf16fmr2.c | 12 ++++++------ drivers/media/radio/radio-terratec.c | 12 ++++++------ drivers/media/radio/radio-typhoon.c | 10 +++++----- drivers/media/radio/radio-zoltrix.c | 12 ++++++------ drivers/media/video/arv.c | 10 +++++----- drivers/media/video/cpia.c | 12 ++++++------ drivers/media/video/pwc/pwc-if.c | 12 ++++++------ drivers/media/video/pwc/pwc-v4l.c | 2 +- drivers/media/video/s2255drv.c | 2 +- drivers/media/video/saa5246a.c | 13 +++++++------ drivers/media/video/saa5249.c | 12 ++++++------ drivers/media/video/stk-webcam.c | 4 ++-- drivers/media/video/usbvideo/vicam.c | 9 ++++----- drivers/media/video/w9966.c | 10 +++++----- include/media/v4l2-dev.h | 14 +++----------- 23 files changed, 111 insertions(+), 119 deletions(-) diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index cf6a817d505..5b34c134aa2 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -533,7 +533,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, memcpy(vfd, &device_template, sizeof(struct video_device)); strlcpy(vfd->name, name, sizeof(vfd->name)); vfd->release = video_device_release; - vfd->priv = dev; + video_set_drvdata(vfd, dev); // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); if (video_register_device(vfd, type, -1) < 0) { diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 59fdaf85e41..62cc6874d63 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -247,7 +247,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -275,7 +275,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); rt->curfreq = f->frequency; rt_setfreq(rt, rt->curfreq); @@ -286,7 +286,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -312,7 +312,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -329,7 +329,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -437,7 +437,7 @@ static int __init rtrack_init(void) return -EBUSY; } - rtrack_radio.priv=&rtrack_unit; + video_set_drvdata(&rtrack_radio, &rtrack_unit); if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index ddd96295a9f..5dd5e349ef4 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -197,7 +197,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct az_device *az = dev->priv; + struct az_device *az = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -266,7 +266,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct az_device *az = dev->priv; + struct az_device *az = video_get_drvdata(dev); az->curfreq = f->frequency; az_setfreq(az, az->curfreq); @@ -277,7 +277,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct az_device *az = dev->priv; + struct az_device *az = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; @@ -304,7 +304,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct az_device *az = dev->priv; + struct az_device *az = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -324,7 +324,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct az_device *az = dev->priv; + struct az_device *az = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -405,7 +405,7 @@ static int __init aztech_init(void) } mutex_init(&lock); - aztech_radio.priv=&aztech_unit; + video_set_drvdata(&aztech_radio, &aztech_unit); if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io,2); diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index d65fd287bde..1f57f731c12 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -205,7 +205,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = dev->priv; + struct gemtek_pci_card *card = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -233,7 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = dev->priv; + struct gemtek_pci_card *card = video_get_drvdata(dev); if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) @@ -248,7 +248,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = dev->priv; + struct gemtek_pci_card *card = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; @@ -273,7 +273,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = dev->priv; + struct gemtek_pci_card *card = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -293,7 +293,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = dev->priv; + struct gemtek_pci_card *card = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -442,7 +442,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci } card->videodev = devradio; - devradio->priv = card; + video_set_drvdata(devradio, card); gemtek_pci_mute( card ); printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 2d991ae2f20..2c4c15e6d51 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -460,7 +460,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = dev->priv; + struct gemtek_device *rt = video_get_drvdata(dev); gemtek_setfreq(rt, f->frequency); @@ -471,7 +471,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = dev->priv; + struct gemtek_device *rt = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = rt->lastfreq; @@ -496,7 +496,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = dev->priv; + struct gemtek_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -516,7 +516,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = dev->priv; + struct gemtek_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -623,7 +623,7 @@ static int __init gemtek_init(void) return -EINVAL; } - gemtek_radio.priv = &gemtek_unit; + video_set_drvdata(&gemtek_radio, &gemtek_unit); if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 1); diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 4e2e8a3d9b5..9bf2acf5249 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -232,7 +232,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct radio_device *card=dev->priv; + struct radio_device *card = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -303,7 +303,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct radio_device *card=dev->priv; + struct radio_device *card = video_get_drvdata(dev); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", @@ -325,7 +325,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct radio_device *card=dev->priv; + struct radio_device *card = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = card->freq; @@ -356,7 +356,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct radio_device *card=dev->priv; + struct radio_device *card = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -371,7 +371,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct radio_device *card=dev->priv; + struct radio_device *card = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -421,7 +421,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d radio_unit.io = pci_resource_start(pdev, 0); mutex_init(&radio_unit.lock); - maxiradio_radio.priv = &radio_unit; + video_set_drvdata(&maxiradio_radio, &radio_unit); if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { printk("radio-maxiradio: can't register device!"); diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 8fe820da73e..4234f7ed0fc 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -155,7 +155,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -175,7 +175,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); rt->curfreq = f->frequency; rt_setfreq(rt, rt->curfreq); @@ -186,7 +186,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -212,7 +212,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -232,7 +232,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct rt_device *rt = dev->priv; + struct rt_device *rt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -342,7 +342,7 @@ static int __init rtrack2_init(void) return -EBUSY; } - rtrack2_radio.priv=&rtrack2_unit; + video_set_drvdata(&rtrack2_radio, &rtrack2_unit); spin_lock_init(&lock); if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 6d865a7a91e..810c366b73b 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -148,7 +148,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, { int mult; struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = dev->priv; + struct fmi_device *fmi = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -177,7 +177,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = dev->priv; + struct fmi_device *fmi = video_get_drvdata(dev); if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; @@ -195,7 +195,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = dev->priv; + struct fmi_device *fmi = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; @@ -223,7 +223,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = dev->priv; + struct fmi_device *fmi = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -237,7 +237,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = dev->priv; + struct fmi_device *fmi = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -386,7 +386,7 @@ static int __init fmi_init(void) fmi_unit.curvol = 0; fmi_unit.curfreq = 0; fmi_unit.flags = V4L2_TUNER_CAP_LOW; - fmi_radio.priv = &fmi_unit; + video_set_drvdata(&fmi_radio, &fmi_unit); mutex_init(&lock); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9625d1f0194..9f823150452 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -231,7 +231,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, { int mult; struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; + struct fmr2_device *fmr2 = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -264,7 +264,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; + struct fmr2_device *fmr2 = video_get_drvdata(dev); if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; @@ -288,7 +288,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; + struct fmr2_device *fmr2 = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; @@ -315,7 +315,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; + struct fmr2_device *fmr2 = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -332,7 +332,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; + struct fmr2_device *fmr2 = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -454,7 +454,7 @@ static int __init fmr2_init(void) fmr2_unit.stereo = 1; fmr2_unit.flags = V4L2_TUNER_CAP_LOW; fmr2_unit.card_type = 0; - fmr2_radio.priv = &fmr2_unit; + video_set_drvdata(&fmr2_radio, &fmr2_unit); mutex_init(&lock); diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index de13ec81ce4..0bc9af686ad 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -222,7 +222,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct tt_device *tt = dev->priv; + struct tt_device *tt = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -250,7 +250,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct tt_device *tt = dev->priv; + struct tt_device *tt = video_get_drvdata(dev); tt->curfreq = f->frequency; tt_setfreq(tt, tt->curfreq); @@ -261,7 +261,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct tt_device *tt = dev->priv; + struct tt_device *tt = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = tt->curfreq; @@ -287,7 +287,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct tt_device *tt = dev->priv; + struct tt_device *tt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -307,7 +307,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct tt_device *tt = dev->priv; + struct tt_device *tt = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -414,7 +414,7 @@ static int __init terratec_init(void) return -EBUSY; } - terratec_radio.priv=&terratec_unit; + video_set_drvdata(&terratec_radio, &terratec_unit); spin_lock_init(&lock); diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index c2eedb7a73a..27255d7ff1b 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -224,7 +224,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = dev->priv; + struct typhoon_device *typhoon = video_get_drvdata(dev); typhoon->curfreq = f->frequency; typhoon_setfreq(typhoon, typhoon->curfreq); @@ -235,7 +235,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = dev->priv; + struct typhoon_device *typhoon = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = typhoon->curfreq; @@ -262,7 +262,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = dev->priv; + struct typhoon_device *typhoon = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -279,7 +279,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = dev->priv; + struct typhoon_device *typhoon = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -458,7 +458,7 @@ static int __init typhoon_init(void) return -EBUSY; } - typhoon_radio.priv = &typhoon_unit; + video_set_drvdata(&typhoon_radio, &typhoon_unit); if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 8); return -EINVAL; diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 0d43e8401eb..3a9a7772ae5 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -247,7 +247,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct video_device *dev = video_devdata(file); - struct zol_device *zol = dev->priv; + struct zol_device *zol = video_get_drvdata(dev); if (v->index > 0) return -EINVAL; @@ -278,7 +278,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct zol_device *zol = dev->priv; + struct zol_device *zol = video_get_drvdata(dev); zol->curfreq = f->frequency; zol_setfreq(zol, zol->curfreq); @@ -289,7 +289,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct video_device *dev = video_devdata(file); - struct zol_device *zol = dev->priv; + struct zol_device *zol = video_get_drvdata(dev); f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; @@ -315,7 +315,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct zol_device *zol = dev->priv; + struct zol_device *zol = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -332,7 +332,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct video_device *dev = video_devdata(file); - struct zol_device *zol = dev->priv; + struct zol_device *zol = video_get_drvdata(dev); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -453,7 +453,7 @@ static int __init zoltrix_init(void) return -ENXIO; } - zoltrix_radio.priv = &zoltrix_unit; + video_set_drvdata(&zoltrix_radio, &zoltrix_unit); if (!request_region(io, 2, "zoltrix")) { printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); return -EBUSY; diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 0d4f9b68345..218754b4906 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -270,7 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line) static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) { struct video_device *v = video_devdata(file); - struct ar_device *ar = v->priv; + struct ar_device *ar = video_get_drvdata(v); long ret = ar->frame_bytes; /* return read bytes */ unsigned long arvcr1 = 0; unsigned long flags; @@ -400,7 +400,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); - struct ar_device *ar = dev->priv; + struct ar_device *ar = video_get_drvdata(dev); DEBUG(1, "ar_ioctl()\n"); switch(cmd) { @@ -626,7 +626,7 @@ static void ar_interrupt(int irq, void *dev) */ static int ar_initialize(struct video_device *dev) { - struct ar_device *ar = dev->priv; + struct ar_device *ar = video_get_drvdata(dev); unsigned long cr = 0; int i,found=0; @@ -733,7 +733,7 @@ static int ar_initialize(struct video_device *dev) void ar_release(struct video_device *vfd) { - struct ar_device *ar = vfd->priv; + struct ar_device *ar = video_get_drvdata(vfd); mutex_lock(&ar->lock); video_device_release(vfd); } @@ -815,7 +815,7 @@ static int __init ar_init(void) return -ENOMEM; } memcpy(ar->vdev, &ar_template, sizeof(ar_template)); - ar->vdev->priv = ar; + video_set_drvdata(ar->vdev, ar); if (vga) { ar->width = AR_WIDTH_VGA; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index c0600fdbfc6..b14c59c281e 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3155,7 +3155,7 @@ static void put_cam(struct cpia_camera_ops* ops) static int cpia_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct cam_data *cam = dev->priv; + struct cam_data *cam = video_get_drvdata(dev); int err; if (!cam) { @@ -3232,7 +3232,7 @@ static int cpia_open(struct inode *inode, struct file *file) static int cpia_close(struct inode *inode, struct file *file) { struct video_device *dev = file->private_data; - struct cam_data *cam = dev->priv; + struct cam_data *cam = video_get_drvdata(dev); if (cam->ops) { /* Return ownership of /proc/cpia/videoX to root */ @@ -3284,7 +3284,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *dev = file->private_data; - struct cam_data *cam = dev->priv; + struct cam_data *cam = video_get_drvdata(dev); int err; /* make this _really_ smp and multithread-safe */ @@ -3341,7 +3341,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, void *arg) { struct video_device *dev = file->private_data; - struct cam_data *cam = dev->priv; + struct cam_data *cam = video_get_drvdata(dev); int retval = 0; if (!cam || !cam->ops) @@ -3739,7 +3739,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; unsigned long page, pos; - struct cam_data *cam = dev->priv; + struct cam_data *cam = video_get_drvdata(dev); int retval; if (!cam || !cam->ops) @@ -3929,7 +3929,7 @@ static void init_camera_struct(struct cam_data *cam, cam->proc_entry = NULL; memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); - cam->vdev.priv = cam; + video_set_drvdata(&cam->vdev, cam); cam->curframe = 0; for (i = 0; i < FRAME_NUM; i++) { diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9aee7cb6f79..ab28389b4cd 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1112,7 +1112,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); - pdev = (struct pwc_device *)vdev->priv; + pdev = video_get_drvdata(vdev); BUG_ON(!pdev); if (pdev->vopen) { PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); @@ -1233,7 +1233,7 @@ static int pwc_video_close(struct inode *inode, struct file *file) PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); lock_kernel(); - pdev = (struct pwc_device *)vdev->priv; + pdev = video_get_drvdata(vdev); if (pdev->vopen == 0) PWC_DEBUG_MODULE("video_close() called on closed device?\n"); @@ -1304,7 +1304,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, vdev, buf, count); if (vdev == NULL) return -EFAULT; - pdev = vdev->priv; + pdev = video_get_drvdata(vdev); if (pdev == NULL) return -EFAULT; @@ -1386,7 +1386,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) if (vdev == NULL) return -EFAULT; - pdev = vdev->priv; + pdev = video_get_drvdata(vdev); if (pdev == NULL) return -EFAULT; @@ -1408,7 +1408,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file, if (!vdev) goto out; - pdev = vdev->priv; + pdev = video_get_drvdata(vdev); mutex_lock(&pdev->modlock); if (!pdev->unplugged) @@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) int index; PWC_DEBUG_MEMORY(">> %s\n", __func__); - pdev = vdev->priv; + pdev = video_get_drvdata(vdev); size = vma->vm_end - vma->vm_start; start = vma->vm_start; diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 1742889874d..76a1376c975 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -346,7 +346,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, if (vdev == NULL) return -EFAULT; - pdev = vdev->priv; + pdev = video_get_drvdata(vdev); if (pdev == NULL) return -EFAULT; diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index af19bb346ef..ea40f4c8b33 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1800,7 +1800,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) ret = video_register_device(dev->vdev[i], VFL_TYPE_GRABBER, cur_nr + i); - dev->vdev[i]->priv = dev; + video_set_drvdata(dev->vdev[i], dev); if (ret != 0) { dev_err(&dev->udev->dev, diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 5f5aa2063e0..0178b49da0c 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -117,7 +117,7 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); t->is_searching[pgbuf] = false; } - vd->priv=t; + video_set_drvdata(vd, t); /* @@ -151,7 +151,7 @@ static int saa5246a_detach(struct i2c_client *client) struct video_device *vd = i2c_get_clientdata(client); i2c_detach_client(client); video_unregister_device(vd); - kfree(vd->priv); + kfree(video_get_drvdata(vd)); kfree(client); return 0; } @@ -582,7 +582,8 @@ static int do_saa5246a_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *vd = video_devdata(file); - struct saa5246a_device *t=vd->priv; + struct saa5246a_device *t = video_get_drvdata(vd); + switch(cmd) { case VTXIOCGETINFO: @@ -723,7 +724,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = vd->priv; + struct saa5246a_device *t = video_get_drvdata(vd); int err; cmd = vtx_fix_command(cmd); @@ -736,7 +737,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, static int saa5246a_open(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = vd->priv; + struct saa5246a_device *t = video_get_drvdata(vd); if (t->client == NULL) return -ENODEV; @@ -779,7 +780,7 @@ static int saa5246a_open(struct inode *inode, struct file *file) static int saa5246a_release(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = vd->priv; + struct saa5246a_device *t = video_get_drvdata(vd); /* Stop all acquisition circuits. */ i2c_senddata(t, SAA5246A_REGISTER_R1, diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 225117c789c..c784715a0b0 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -186,7 +186,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) t->vdau[pgbuf].stopped = true; t->is_searching[pgbuf] = false; } - vd->priv=t; + video_set_drvdata(vd, t); /* @@ -221,7 +221,7 @@ static int saa5249_detach(struct i2c_client *client) struct video_device *vd = i2c_get_clientdata(client); i2c_detach_client(client); video_unregister_device(vd); - kfree(vd->priv); + kfree(video_get_drvdata(vd)); kfree(vd); kfree(client); return 0; @@ -320,7 +320,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, { static int virtual_mode = false; struct video_device *vd = video_devdata(file); - struct saa5249_device *t=vd->priv; + struct saa5249_device *t = video_get_drvdata(vd); switch(cmd) { @@ -619,7 +619,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vd = video_devdata(file); - struct saa5249_device *t=vd->priv; + struct saa5249_device *t = video_get_drvdata(vd); int err; cmd = vtx_fix_command(cmd); @@ -632,7 +632,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, static int saa5249_open(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5249_device *t = vd->priv; + struct saa5249_device *t = video_get_drvdata(vd); int pgbuf; if (t->client == NULL) @@ -670,7 +670,7 @@ static int saa5249_open(struct inode *inode, struct file *file) static int saa5249_release(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); - struct saa5249_device *t = vd->priv; + struct saa5249_device *t = video_get_drvdata(vd); i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 6b1ef5dc562..8dda5680094 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -72,7 +72,7 @@ static void stk_camera_cleanup(struct kref *kref) STK_INFO("Syntek USB2.0 Camera release resources" " video device /dev/video%d\n", dev->vdev.minor); video_unregister_device(&dev->vdev); - dev->vdev.priv = NULL; + video_set_drvdata(&dev->vdev, NULL); if (dev->sio_bufs != NULL || dev->isobufs != NULL) STK_ERROR("We are leaking memory\n"); @@ -1379,7 +1379,7 @@ static int stk_register_video_device(struct stk_camera *dev) dev->vdev = stk_v4l_data; dev->vdev.debug = debug; dev->vdev.parent = &dev->interface->dev; - dev->vdev.priv = dev; + video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (err) STK_ERROR("v4l registration failed\n"); diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index d7728256f29..1ffcc393fcb 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -473,8 +473,8 @@ static int vicam_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct vicam_camera *cam = - (struct vicam_camera *) dev->priv; + struct vicam_camera *cam = video_get_drvdata(dev); + DBG("open\n"); if (!cam) { @@ -866,9 +866,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) mutex_init(&cam->cam_lock); - memcpy(&cam->vdev, &vicam_template, - sizeof (vicam_template)); - cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only + memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); + video_set_drvdata(&cam->vdev, cam); cam->udev = dev; cam->bulkEndpoint = bulkEndpoint; diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index e3580119640..14ebb15837f 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -188,7 +188,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, static int w9966_exclusive_open(struct inode *inode, struct file *file) { struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = vdev->priv; + struct w9966_dev *cam = video_get_drvdata(vdev); return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; } @@ -196,7 +196,7 @@ static int w9966_exclusive_open(struct inode *inode, struct file *file) static int w9966_exclusive_release(struct inode *inode, struct file *file) { struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = vdev->priv; + struct w9966_dev *cam = video_get_drvdata(vdev); clear_bit(0, &cam->in_use); return 0; @@ -351,7 +351,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) // Fill in the video_device struct and register us to v4l memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); - cam->vdev.priv = cam; + video_set_drvdata(&cam->vdev, cam); if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) return -1; @@ -733,7 +733,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = vdev->priv; + struct w9966_dev *cam = video_get_drvdata(vdev); switch(cmd) { @@ -892,7 +892,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = vdev->priv; + struct w9966_dev *cam = video_get_drvdata(vdev); unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 23df00919ae..1d4df571060 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -69,14 +69,6 @@ struct video_device /* ioctl callbacks */ const struct v4l2_ioctl_ops *ioctl_ops; - -#ifdef OBSOLETE_DEVDATA /* to be removed soon */ - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; -#endif }; /* Class-dev to video-device */ @@ -98,18 +90,18 @@ void video_device_release(struct video_device *vfd); a dubious construction at best. */ void video_device_release_empty(struct video_device *vfd); -#ifdef OBSOLETE_DEVDATA /* to be removed soon */ /* helper functions to access driver private data. */ static inline void *video_get_drvdata(struct video_device *dev) { - return dev->priv; + return dev_get_drvdata(&dev->dev); } static inline void video_set_drvdata(struct video_device *dev, void *data) { - dev->priv = data; + dev_set_drvdata(&dev->dev, data); } +#ifdef OBSOLETE_DEVDATA /* to be removed soon */ /* Obsolete stuff - Still needed for radio devices and obsolete drivers */ extern struct video_device* video_devdata(struct file*); #endif -- GitLab From bfa8a273bb91078ea193ab94c717889928f3b925 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 07:48:38 -0300 Subject: [PATCH 4020/5416] V4L/DVB (8787): v4l2-dev: cleanups and add video_drvdata helper function Cleanup v4l2-dev.[ch], add/improve comments and add a new helper function: video_drvdata() that can get the private driver data from a file struct. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 13 ++++++------- include/media/v4l2-dev.h | 35 ++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index ff219df4b72..1ec0a1a8fb7 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -42,6 +42,7 @@ static ssize_t show_index(struct device *cd, struct device_attribute *attr, char *buf) { struct video_device *vfd = container_of(cd, struct video_device, dev); + return sprintf(buf, "%i\n", vfd->index); } @@ -49,6 +50,7 @@ static ssize_t show_name(struct device *cd, struct device_attribute *attr, char *buf) { struct video_device *vfd = container_of(cd, struct video_device, dev); + return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); } @@ -60,10 +62,7 @@ static struct device_attribute video_device_attrs[] = { struct video_device *video_device_alloc(void) { - struct video_device *vfd; - - vfd = kzalloc(sizeof(*vfd), GFP_KERNEL); - return vfd; + return kzalloc(sizeof(struct video_device), GFP_KERNEL); } EXPORT_SYMBOL(video_device_alloc); @@ -263,7 +262,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, /* pick a minor number */ mutex_lock(&videodev_lock); - if (nr >= 0 && nr < end-base) { + if (nr >= 0 && nr < end-base) { /* use the one the driver asked for */ i = base + nr; if (NULL != video_device[i]) { @@ -295,7 +294,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, } /* sysfs class */ - memset(&vfd->dev, 0x00, sizeof(vfd->dev)); + memset(&vfd->dev, 0, sizeof(vfd->dev)); vfd->dev.class = &video_class; vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); if (vfd->parent) @@ -312,8 +311,8 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, fail_minor: mutex_lock(&videodev_lock); video_device[vfd->minor] = NULL; - vfd->minor = -1; mutex_unlock(&videodev_lock); + vfd->minor = -1; return ret; } EXPORT_SYMBOL(video_register_device_index); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 1d4df571060..fb92e3d22d7 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -9,16 +9,14 @@ #ifndef _V4L2_DEV_H #define _V4L2_DEV_H -#define OBSOLETE_DEVDATA 1 /* to be removed soon */ - #include #include #include #include -#include /* need __user */ #include #define VIDEO_MAJOR 81 + /* Minor device allocation */ #define MINOR_VFL_TYPE_GRABBER_MIN 0 #define MINOR_VFL_TYPE_GRABBER_MAX 63 @@ -71,20 +69,25 @@ struct video_device const struct v4l2_ioctl_ops *ioctl_ops; }; -/* Class-dev to video-device */ +/* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) -/* Version 2 functions */ +/* Register and unregister devices. Note that if video_register_device fails, + the release() callback of the video_device structure is *not* called, so + the caller is responsible for freeing any data. Usually that means that + you call video_device_release() on failure. */ int __must_check video_register_device(struct video_device *vfd, int type, int nr); -int __must_check video_register_device_index(struct video_device *vfd, int type, int nr, - int index); -void video_unregister_device(struct video_device *); +int __must_check video_register_device_index(struct video_device *vfd, + int type, int nr, int index); +void video_unregister_device(struct video_device *vfd); -/* helper functions to alloc / release struct video_device, the - later can be used for video_device->release() */ +/* helper functions to alloc/release struct video_device, the + latter can also be used for video_device->release(). */ struct video_device * __must_check video_device_alloc(void); + /* this release function frees the vfd pointer */ void video_device_release(struct video_device *vfd); + /* this release function does nothing, use when the video_device is a static global struct. Note that having a static video_device is a dubious construction at best. */ @@ -101,9 +104,13 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) dev_set_drvdata(&dev->dev, data); } -#ifdef OBSOLETE_DEVDATA /* to be removed soon */ -/* Obsolete stuff - Still needed for radio devices and obsolete drivers */ -extern struct video_device* video_devdata(struct file*); -#endif +struct video_device *video_devdata(struct file *file); + +/* Combine video_get_drvdata and video_devdata as this is + used very often. */ +static inline void *video_drvdata(struct file *file) +{ + return video_get_drvdata(video_devdata(file)); +} #endif /* _V4L2_DEV_H */ -- GitLab From c170ecf434bceb0e188b14a6deb3bfa3ec9ef699 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 23 Aug 2008 08:32:09 -0300 Subject: [PATCH 4021/5416] V4L/DVB (8788): v4l: replace video_get_drvdata(video_devdata(filp)) with video_drvdata(filp) Use the new video_drvdata(filp) function where it is safe to do so. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/dsbr100.c | 14 +- drivers/media/radio/radio-aimslab.c | 15 +-- drivers/media/radio/radio-aztech.c | 15 +-- drivers/media/radio/radio-gemtek-pci.c | 15 +-- drivers/media/radio/radio-gemtek.c | 12 +- drivers/media/radio/radio-maestro.c | 15 +-- drivers/media/radio/radio-maxiradio.c | 15 +-- drivers/media/radio/radio-rtrack2.c | 15 +-- drivers/media/radio/radio-sf16fmi.c | 15 +-- drivers/media/radio/radio-sf16fmr2.c | 15 +-- drivers/media/radio/radio-si470x.c | 22 ++-- drivers/media/radio/radio-terratec.c | 15 +-- drivers/media/radio/radio-typhoon.c | 12 +- drivers/media/radio/radio-zoltrix.c | 15 +-- drivers/media/video/cpia2/cpia2_v4l.c | 16 +-- drivers/media/video/et61x251/et61x251_core.c | 14 +- drivers/media/video/saa5246a.c | 13 +- drivers/media/video/saa5249.c | 12 +- drivers/media/video/sn9c102/sn9c102_core.c | 14 +- drivers/media/video/usbvideo/vicam.c | 3 +- .../media/video/usbvision/usbvision-video.c | 122 +++++------------- drivers/media/video/uvc/uvc_v4l2.c | 13 +- drivers/media/video/vino.c | 18 +-- drivers/media/video/w9966.c | 12 +- drivers/media/video/zc0301/zc0301_core.c | 14 +- sound/i2c/other/tea575x-tuner.c | 9 +- 26 files changed, 160 insertions(+), 310 deletions(-) diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 3a4eb444a7c..0f06e6ffb0e 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -274,7 +274,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -306,7 +306,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); radio->curfreq = f->frequency; if (dsbr100_setfreq(radio, radio->curfreq)==-1) @@ -317,7 +317,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; @@ -342,7 +342,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -355,7 +355,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -405,7 +405,7 @@ static int vidioc_s_audio(struct file *file, void *priv, static int usb_dsbr100_open(struct inode *inode, struct file *file) { - struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); lock_kernel(); radio->users = 1; @@ -424,7 +424,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) static int usb_dsbr100_close(struct inode *inode, struct file *file) { - struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_drvdata(file); if (!radio) return -ENODEV; diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 62cc6874d63..9305e958fc6 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -246,8 +246,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -274,8 +273,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); rt->curfreq = f->frequency; rt_setfreq(rt, rt->curfreq); @@ -285,8 +283,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -311,8 +308,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -328,8 +324,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 5dd5e349ef4..d7848957323 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -196,8 +196,7 @@ static int vidioc_querycap (struct file *file, void *priv, static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct az_device *az = video_get_drvdata(dev); + struct az_device *az = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -265,8 +264,7 @@ static int vidioc_s_audio (struct file *file, void *priv, static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct az_device *az = video_get_drvdata(dev); + struct az_device *az = video_drvdata(file); az->curfreq = f->frequency; az_setfreq(az, az->curfreq); @@ -276,8 +274,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct az_device *az = video_get_drvdata(dev); + struct az_device *az = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; @@ -303,8 +300,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct az_device *az = video_get_drvdata(dev); + struct az_device *az = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -323,8 +319,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct az_device *az = video_get_drvdata(dev); + struct az_device *az = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 1f57f731c12..e15bee6d7cf 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -204,8 +204,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = video_get_drvdata(dev); + struct gemtek_pci_card *card = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -232,8 +231,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = video_get_drvdata(dev); + struct gemtek_pci_card *card = video_drvdata(file); if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) @@ -247,8 +245,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = video_get_drvdata(dev); + struct gemtek_pci_card *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; @@ -272,8 +269,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = video_get_drvdata(dev); + struct gemtek_pci_card *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -292,8 +288,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct gemtek_pci_card *card = video_get_drvdata(dev); + struct gemtek_pci_card *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 2c4c15e6d51..d131a5d3812 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -459,8 +459,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = video_get_drvdata(dev); + struct gemtek_device *rt = video_drvdata(file); gemtek_setfreq(rt, f->frequency); @@ -470,8 +469,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = video_get_drvdata(dev); + struct gemtek_device *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->lastfreq; @@ -495,8 +493,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = video_get_drvdata(dev); + struct gemtek_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -515,8 +512,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct gemtek_device *rt = video_get_drvdata(dev); + struct gemtek_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 182b433981c..4bf4d007bcf 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -210,8 +210,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -243,8 +242,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; @@ -255,8 +253,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = BITS2FREQ(radio_bits_get(card)); @@ -281,8 +278,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -295,8 +291,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); register u16 io = card->io; register u16 omask = inw(io + IO_MASK); diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 9bf2acf5249..c777a17b00b 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -231,8 +231,7 @@ static int vidioc_querycap (struct file *file, void *priv, static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -302,8 +301,7 @@ static int vidioc_s_audio (struct file *file, void *priv, static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", @@ -324,8 +322,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = card->freq; @@ -355,8 +352,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -370,8 +366,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct radio_device *card = video_get_drvdata(dev); + struct radio_device *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 4234f7ed0fc..a6707977741 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -154,8 +154,7 @@ static int rt_getsigstr(struct rt_device *dev) static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -174,8 +173,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); rt->curfreq = f->frequency; rt_setfreq(rt, rt->curfreq); @@ -185,8 +183,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -211,8 +208,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -231,8 +227,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct rt_device *rt = video_get_drvdata(dev); + struct rt_device *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 810c366b73b..329c90bddad 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -147,8 +147,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = video_get_drvdata(dev); + struct fmi_device *fmi = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -176,8 +175,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = video_get_drvdata(dev); + struct fmi_device *fmi = video_drvdata(file); if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; @@ -194,8 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = video_get_drvdata(dev); + struct fmi_device *fmi = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; @@ -222,8 +219,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = video_get_drvdata(dev); + struct fmi_device *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -236,8 +232,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct fmi_device *fmi = video_get_drvdata(dev); + struct fmi_device *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9f823150452..b1f47c322e0 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -230,8 +230,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = video_get_drvdata(dev); + struct fmr2_device *fmr2 = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -263,8 +262,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = video_get_drvdata(dev); + struct fmr2_device *fmr2 = video_drvdata(file); if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; @@ -287,8 +285,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = video_get_drvdata(dev); + struct fmr2_device *fmr2 = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; @@ -314,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = video_get_drvdata(dev); + struct fmr2_device *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -331,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = video_get_drvdata(dev); + struct fmr2_device *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 337d5579383..f6cedcd3ab9 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -986,7 +986,7 @@ static void si470x_work(struct work_struct *work) static ssize_t si470x_fops_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; unsigned int block_count = 0; @@ -1047,7 +1047,7 @@ done: static unsigned int si470x_fops_poll(struct file *file, struct poll_table_struct *pts) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* switch on rds reception */ @@ -1071,7 +1071,7 @@ static unsigned int si470x_fops_poll(struct file *file, */ static int si470x_fops_open(struct inode *inode, struct file *file) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval; lock_kernel(); @@ -1101,7 +1101,7 @@ done: */ static int si470x_fops_release(struct inode *inode, struct file *file) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety check */ @@ -1284,7 +1284,7 @@ done: static int si470x_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1320,7 +1320,7 @@ done: static int si470x_vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1407,7 +1407,7 @@ done: static int si470x_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *tuner) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1473,7 +1473,7 @@ done: static int si470x_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *tuner) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1507,7 +1507,7 @@ done: static int si470x_vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1536,7 +1536,7 @@ done: static int si470x_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ @@ -1565,7 +1565,7 @@ done: static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, struct v4l2_hw_freq_seek *seek) { - struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + struct si470x_device *radio = video_drvdata(file); int retval = 0; /* safety checks */ diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 0bc9af686ad..0abb186a947 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -221,8 +221,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct tt_device *tt = video_get_drvdata(dev); + struct tt_device *tt = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -249,8 +248,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct tt_device *tt = video_get_drvdata(dev); + struct tt_device *tt = video_drvdata(file); tt->curfreq = f->frequency; tt_setfreq(tt, tt->curfreq); @@ -260,8 +258,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct tt_device *tt = video_get_drvdata(dev); + struct tt_device *tt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = tt->curfreq; @@ -286,8 +283,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct tt_device *tt = video_get_drvdata(dev); + struct tt_device *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -306,8 +302,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct tt_device *tt = video_get_drvdata(dev); + struct tt_device *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 27255d7ff1b..952ec35a841 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -223,8 +223,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = video_get_drvdata(dev); + struct typhoon_device *typhoon = video_drvdata(file); typhoon->curfreq = f->frequency; typhoon_setfreq(typhoon, typhoon->curfreq); @@ -234,8 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = video_get_drvdata(dev); + struct typhoon_device *typhoon = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = typhoon->curfreq; @@ -261,8 +259,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = video_get_drvdata(dev); + struct typhoon_device *typhoon = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -278,8 +275,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct typhoon_device *typhoon = video_get_drvdata(dev); + struct typhoon_device *typhoon = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 3a9a7772ae5..f75da63b163 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -246,8 +246,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct video_device *dev = video_devdata(file); - struct zol_device *zol = video_get_drvdata(dev); + struct zol_device *zol = video_drvdata(file); if (v->index > 0) return -EINVAL; @@ -277,8 +276,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct zol_device *zol = video_get_drvdata(dev); + struct zol_device *zol = video_drvdata(file); zol->curfreq = f->frequency; zol_setfreq(zol, zol->curfreq); @@ -288,8 +286,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct video_device *dev = video_devdata(file); - struct zol_device *zol = video_get_drvdata(dev); + struct zol_device *zol = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; @@ -314,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct zol_device *zol = video_get_drvdata(dev); + struct zol_device *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -331,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct zol_device *zol = video_get_drvdata(dev); + struct zol_device *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index eb9f15cd4c4..897e8d1a5c3 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -241,8 +241,7 @@ static struct v4l2_queryctrl controls[] = { *****************************************************************************/ static int cpia2_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct camera_data *cam = video_get_drvdata(dev); + struct camera_data *cam = video_drvdata(file); int retval = 0; if (!cam) { @@ -357,8 +356,7 @@ static int cpia2_close(struct inode *inode, struct file *file) static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *off) { - struct video_device *dev = video_devdata(file); - struct camera_data *cam = video_get_drvdata(dev); + struct camera_data *cam = video_drvdata(file); int noblock = file->f_flags&O_NONBLOCK; struct cpia2_fh *fh = file->private_data; @@ -382,9 +380,7 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, *****************************************************************************/ static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) { - struct video_device *dev = video_devdata(filp); - struct camera_data *cam = video_get_drvdata(dev); - + struct camera_data *cam = video_drvdata(filp); struct cpia2_fh *fh = filp->private_data; if(!cam) @@ -1579,8 +1575,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) static int cpia2_do_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_nr, void *arg) { - struct video_device *dev = video_devdata(file); - struct camera_data *cam = video_get_drvdata(dev); + struct camera_data *cam = video_drvdata(file); int retval = 0; if (!cam) @@ -1860,9 +1855,8 @@ static int cpia2_ioctl(struct inode *inode, struct file *file, *****************************************************************************/ static int cpia2_mmap(struct file *file, struct vm_area_struct *area) { + struct camera_data *cam = video_drvdata(file); int retval; - struct video_device *dev = video_devdata(file); - struct camera_data *cam = video_get_drvdata(dev); /* Priority check */ struct cpia2_fh *fh = file->private_data; diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 8db2a05bf9c..7a85c41b0ee 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -1214,7 +1214,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) if (!down_read_trylock(&et61x251_dev_lock)) return -ERESTARTSYS; - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); if (wait_for_completion_interruptible(&cam->probe)) { up_read(&et61x251_dev_lock); @@ -1297,7 +1297,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) down_write(&et61x251_dev_lock); - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); et61x251_stop_transfer(cam); et61x251_release_buffers(cam); @@ -1318,7 +1318,7 @@ static ssize_t et61x251_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device *cam = video_drvdata(filp); struct et61x251_frame_t* f, * i; unsigned long lock_flags; long timeout; @@ -1426,7 +1426,7 @@ exit: static unsigned int et61x251_poll(struct file *filp, poll_table *wait) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device *cam = video_drvdata(filp); struct et61x251_frame_t* f; unsigned long lock_flags; unsigned int mask = 0; @@ -1502,7 +1502,7 @@ static struct vm_operations_struct et61x251_vm_ops = { static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device *cam = video_drvdata(filp); unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start; void *pos; @@ -2395,7 +2395,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, unsigned int cmd, void __user * arg) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device *cam = video_drvdata(filp); switch (cmd) { @@ -2490,7 +2490,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, static int et61x251_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device *cam = video_drvdata(filp); int err = 0; if (mutex_lock_interruptible(&cam->fileop_mutex)) diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 0178b49da0c..ff81049e936 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -149,6 +149,7 @@ static int saa5246a_probe(struct i2c_adapter *adap) static int saa5246a_detach(struct i2c_client *client) { struct video_device *vd = i2c_get_clientdata(client); + i2c_detach_client(client); video_unregister_device(vd); kfree(video_get_drvdata(vd)); @@ -581,8 +582,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t, static int do_saa5246a_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = video_get_drvdata(vd); + struct saa5246a_device *t = video_drvdata(file); switch(cmd) { @@ -723,8 +723,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) static int saa5246a_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = video_get_drvdata(vd); + struct saa5246a_device *t = video_drvdata(file); int err; cmd = vtx_fix_command(cmd); @@ -736,8 +735,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, static int saa5246a_open(struct inode *inode, struct file *file) { - struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = video_get_drvdata(vd); + struct saa5246a_device *t = video_drvdata(file); if (t->client == NULL) return -ENODEV; @@ -779,8 +777,7 @@ static int saa5246a_open(struct inode *inode, struct file *file) static int saa5246a_release(struct inode *inode, struct file *file) { - struct video_device *vd = video_devdata(file); - struct saa5246a_device *t = video_get_drvdata(vd); + struct saa5246a_device *t = video_drvdata(file); /* Stop all acquisition circuits. */ i2c_senddata(t, SAA5246A_REGISTER_R1, diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index c784715a0b0..8517aa4f068 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -319,8 +319,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { static int virtual_mode = false; - struct video_device *vd = video_devdata(file); - struct saa5249_device *t = video_get_drvdata(vd); + struct saa5249_device *t = video_drvdata(file); switch(cmd) { @@ -618,8 +617,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) static int saa5249_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct video_device *vd = video_devdata(file); - struct saa5249_device *t = video_get_drvdata(vd); + struct saa5249_device *t = video_drvdata(file); int err; cmd = vtx_fix_command(cmd); @@ -631,8 +629,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, static int saa5249_open(struct inode *inode, struct file *file) { - struct video_device *vd = video_devdata(file); - struct saa5249_device *t = video_get_drvdata(vd); + struct saa5249_device *t = video_drvdata(file); int pgbuf; if (t->client == NULL) @@ -669,8 +666,7 @@ static int saa5249_open(struct inode *inode, struct file *file) static int saa5249_release(struct inode *inode, struct file *file) { - struct video_device *vd = video_devdata(file); - struct saa5249_device *t = video_get_drvdata(vd); + struct saa5249_device *t = video_drvdata(file); i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 2da6938718f..4b76c45c148 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1746,7 +1746,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) if (!down_read_trylock(&sn9c102_dev_lock)) return -ERESTARTSYS; - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); if (wait_for_completion_interruptible(&cam->probe)) { up_read(&sn9c102_dev_lock); @@ -1843,7 +1843,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) down_write(&sn9c102_dev_lock); - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); sn9c102_stop_transfer(cam); sn9c102_release_buffers(cam); @@ -1863,7 +1863,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) static ssize_t sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device *cam = video_drvdata(filp); struct sn9c102_frame_t* f, * i; unsigned long lock_flags; long timeout; @@ -1987,7 +1987,7 @@ exit: static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device *cam = video_drvdata(filp); struct sn9c102_frame_t* f; unsigned long lock_flags; unsigned int mask = 0; @@ -2063,7 +2063,7 @@ static struct vm_operations_struct sn9c102_vm_ops = { static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device *cam = video_drvdata(filp); unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start; void *pos; @@ -3075,7 +3075,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, unsigned int cmd, void __user * arg) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device *cam = video_drvdata(filp); switch (cmd) { @@ -3179,7 +3179,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, static int sn9c102_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device *cam = video_drvdata(filp); int err = 0; if (mutex_lock_interruptible(&cam->fileop_mutex)) diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 1ffcc393fcb..7a127d6bfde 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -472,8 +472,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign static int vicam_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct vicam_camera *cam = video_get_drvdata(dev); + struct vicam_camera *cam = video_drvdata(file); DBG("open\n"); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b76295a5be8..782ee643601 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -360,9 +360,7 @@ static void usbvision_remove_sysfs(struct video_device *vdev) */ static int usbvision_v4l2_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; PDEBUG(DBG_IO, "open"); @@ -439,9 +437,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) */ static int usbvision_v4l2_close(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); PDEBUG(DBG_IO, "close"); mutex_lock(&usbvision->lock); @@ -486,9 +482,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) static int vidioc_g_register (struct file *file, void *priv, struct v4l2_register *reg) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int errCode; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) @@ -507,9 +501,7 @@ static int vidioc_g_register (struct file *file, void *priv, static int vidioc_s_register (struct file *file, void *priv, struct v4l2_register *reg) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int errCode; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) @@ -528,9 +520,7 @@ static int vidioc_s_register (struct file *file, void *priv, static int vidioc_querycap (struct file *file, void *priv, struct v4l2_capability *vc) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); strlcpy(vc->card, @@ -550,9 +540,7 @@ static int vidioc_querycap (struct file *file, void *priv, static int vidioc_enum_input (struct file *file, void *priv, struct v4l2_input *vi) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int chan; if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) @@ -605,9 +593,7 @@ static int vidioc_enum_input (struct file *file, void *priv, static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); *input = usbvision->ctl_input; return 0; @@ -615,9 +601,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) static int vidioc_s_input (struct file *file, void *priv, unsigned int input) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); if ((input >= usbvision->video_inputs) || (input < 0) ) return -EINVAL; @@ -634,9 +618,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); + usbvision->tvnormId=*id; mutex_lock(&usbvision->lock); @@ -652,9 +635,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) static int vidioc_g_tuner (struct file *file, void *priv, struct v4l2_tuner *vt) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); if (!usbvision->have_tuner || vt->index) // Only tuner 0 return -EINVAL; @@ -673,9 +654,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, static int vidioc_s_tuner (struct file *file, void *priv, struct v4l2_tuner *vt) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); // Only no or one tuner for now if (!usbvision->have_tuner || vt->index) @@ -689,9 +668,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, static int vidioc_g_frequency (struct file *file, void *priv, struct v4l2_frequency *freq) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); freq->tuner = 0; // Only one tuner if(usbvision->radio) { @@ -707,9 +684,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *freq) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); // Only no or one tuner for now if (!usbvision->have_tuner || freq->tuner) @@ -723,9 +698,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); memset(a,0,sizeof(*a)); if(usbvision->radio) { @@ -750,9 +723,7 @@ static int vidioc_s_audio (struct file *file, void *fh, static int vidioc_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int id=ctrl->id; memset(ctrl,0,sizeof(*ctrl)); @@ -769,9 +740,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); return 0; @@ -780,9 +749,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); return 0; @@ -791,9 +758,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *vr) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int ret; RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); @@ -821,9 +786,7 @@ static int vidioc_reqbufs (struct file *file, static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *vb) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; /* FIXME : must control @@ -859,9 +822,7 @@ static int vidioc_querybuf (struct file *file, static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; unsigned long lock_flags; @@ -898,9 +859,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int ret; struct usbvision_frame *f; unsigned long lock_flags; @@ -941,9 +900,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; usbvision->streaming = Stream_On; @@ -955,9 +912,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -990,9 +945,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *vf) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); vf->fmt.pix.width = usbvision->curwidth; vf->fmt.pix.height = usbvision->curheight; vf->fmt.pix.pixelformat = usbvision->palette.format; @@ -1008,9 +961,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *vf) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int formatIdx; /* Find requested format in available ones */ @@ -1038,9 +989,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int ret; if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { @@ -1068,9 +1017,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int noblock = file->f_flags & O_NONBLOCK; unsigned long lock_flags; @@ -1179,10 +1126,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) start = vma->vm_start; void *pos; u32 i; - - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); PDEBUG(DBG_MMAP, "mmap"); @@ -1239,9 +1183,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) */ static int usbvision_radio_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; PDEBUG(DBG_IO, "%s:", __func__); @@ -1291,9 +1233,7 @@ out: static int usbvision_radio_close(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = - (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; PDEBUG(DBG_IO, ""); diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index d7bd71be40a..d4758c8e13a 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -400,15 +400,13 @@ static int uvc_has_privileges(struct uvc_fh *handle) static int uvc_v4l2_open(struct inode *inode, struct file *file) { - struct video_device *vdev; struct uvc_video_device *video; struct uvc_fh *handle; int ret = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); mutex_lock(&uvc_driver.open_mutex); - vdev = video_devdata(file); - video = video_get_drvdata(vdev); + video = video_drvdata(file); if (video->dev->state & UVC_DEV_DISCONNECTED) { ret = -ENODEV; @@ -440,8 +438,7 @@ done: static int uvc_v4l2_release(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct uvc_video_device *video = video_get_drvdata(vdev); + struct uvc_video_device *video = video_drvdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); @@ -1031,8 +1028,7 @@ static struct vm_operations_struct uvc_vm_ops = { static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { - struct video_device *vdev = video_devdata(file); - struct uvc_video_device *video = video_get_drvdata(vdev); + struct uvc_video_device *video = video_drvdata(file); struct uvc_buffer *uninitialized_var(buffer); struct page *page; unsigned long addr, start, size; @@ -1085,8 +1081,7 @@ done: static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) { - struct video_device *vdev = video_devdata(file); - struct uvc_video_device *video = video_get_drvdata(vdev); + struct uvc_video_device *video = video_drvdata(file); uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index ca421cc84f8..8ec57df1904 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -4024,8 +4024,7 @@ out: static int vino_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); int ret = 0; dprintk("open(): channel = %c\n", (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); @@ -4056,8 +4055,7 @@ static int vino_open(struct inode *inode, struct file *file) static int vino_close(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); dprintk("close():\n"); mutex_lock(&vcs->mutex); @@ -4100,8 +4098,7 @@ static struct vm_operations_struct vino_vm_ops = { static int vino_mmap(struct file *file, struct vm_area_struct *vma) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; @@ -4206,8 +4203,7 @@ out: static unsigned int vino_poll(struct file *file, poll_table *pt) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); unsigned int outgoing; unsigned int ret = 0; @@ -4247,8 +4243,7 @@ error: static int vino_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); #ifdef VINO_DEBUG switch (_IOC_TYPE(cmd)) { @@ -4355,8 +4350,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, static int vino_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct video_device *dev = video_devdata(file); - struct vino_channel_settings *vcs = video_get_drvdata(dev); + struct vino_channel_settings *vcs = video_drvdata(file); int ret; if (mutex_lock_interruptible(&vcs->mutex)) diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 14ebb15837f..b2dbe48a92b 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -187,16 +187,14 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, static int w9966_exclusive_open(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = video_get_drvdata(vdev); + struct w9966_dev *cam = video_drvdata(file); return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; } static int w9966_exclusive_release(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = video_get_drvdata(vdev); + struct w9966_dev *cam = video_drvdata(file); clear_bit(0, &cam->in_use); return 0; @@ -732,8 +730,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = video_get_drvdata(vdev); + struct w9966_dev *cam = video_drvdata(file); switch(cmd) { @@ -891,8 +888,7 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct video_device *vdev = video_devdata(file); - struct w9966_dev *cam = video_get_drvdata(vdev); + struct w9966_dev *cam = video_drvdata(file); unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 0c3287734c9..6a0902bcba6 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -657,7 +657,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) if (!down_read_trylock(&zc0301_dev_lock)) return -EAGAIN; - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); if (wait_for_completion_interruptible(&cam->probe)) { up_read(&zc0301_dev_lock); @@ -739,7 +739,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) down_write(&zc0301_dev_lock); - cam = video_get_drvdata(video_devdata(filp)); + cam = video_drvdata(filp); zc0301_stop_transfer(cam); zc0301_release_buffers(cam); @@ -759,7 +759,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) static ssize_t zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device *cam = video_drvdata(filp); struct zc0301_frame_t* f, * i; unsigned long lock_flags; long timeout; @@ -866,7 +866,7 @@ exit: static unsigned int zc0301_poll(struct file *filp, poll_table *wait) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device *cam = video_drvdata(filp); struct zc0301_frame_t* f; unsigned long lock_flags; unsigned int mask = 0; @@ -941,7 +941,7 @@ static struct vm_operations_struct zc0301_vm_ops = { static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device *cam = video_drvdata(filp); unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start; void *pos; @@ -1796,7 +1796,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, unsigned int cmd, void __user * arg) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device *cam = video_drvdata(filp); switch (cmd) { @@ -1891,7 +1891,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, static int zc0301_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device *cam = video_drvdata(filp); int err = 0; if (mutex_lock_interruptible(&cam->fileop_mutex)) diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 621d7fe3074..c13a178383b 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -87,8 +87,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) static int snd_tea575x_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) { - struct video_device *dev = video_devdata(file); - struct snd_tea575x *tea = video_get_drvdata(dev); + struct snd_tea575x *tea = video_drvdata(file); void __user *arg = (void __user *)data; switch(cmd) { @@ -177,16 +176,14 @@ static void snd_tea575x_release(struct video_device *vfd) static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct snd_tea575x *tea = video_get_drvdata(dev); + struct snd_tea575x *tea = video_drvdata(file); return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; } static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file) { - struct video_device *dev = video_devdata(file); - struct snd_tea575x *tea = video_get_drvdata(dev); + struct snd_tea575x *tea = video_drvdata(file); clear_bit(0, &tea->in_use); return 0; -- GitLab From 9d95af9d09d537d287eea9914c0d1ca4cfa0ec7f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 24 Aug 2008 11:18:47 -0300 Subject: [PATCH 4022/5416] V4L/DVB (8791): v4l2-dev: do not clear the driver_data field The driver_data field of the device structure was zeroed, thus losing this information. Many drivers set this up before calling video_device_register, so we have to ensure that it isn't lost. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 1ec0a1a8fb7..99f7ee4bc50 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -226,6 +226,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int end; int ret; char *name_base; + void *priv = video_get_drvdata(vfd); /* the release callback MUST be present */ BUG_ON(!vfd->release); @@ -295,6 +296,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, /* sysfs class */ memset(&vfd->dev, 0, sizeof(vfd->dev)); + /* The memset above cleared the device's drvdata, so + put back the copy we made earlier. */ + video_set_drvdata(vfd, priv); vfd->dev.class = &video_class; vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); if (vfd->parent) -- GitLab From f03813e4d1900b619d4cb133506b130e535614f0 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Tue, 26 Aug 2008 13:44:40 -0300 Subject: [PATCH 4023/5416] V4L/DVB (8795): saa7134-empress: insert leading null bytes for Beholder M6 empress cards Additional code to improve the init sequence and add board type tests were done by Hans Verkuil. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 17 +++++++++++------ drivers/media/video/saa7134/saa7134-empress.c | 15 ++++++++++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 28499e59192..f40cb0b479b 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -653,7 +653,7 @@ static int saa6752hs_qmenu(struct saa6752hs_state *h, return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); } -static int saa6752hs_init(struct i2c_client* client) +static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) { unsigned char buf[9], buf2[4]; struct saa6752hs_state *h; @@ -705,6 +705,12 @@ static int saa6752hs_init(struct i2c_client* client) buf[1] = 0x05; i2c_master_send(client,buf,2); + /* Set leading null byte for TS */ + buf[0] = 0xF6; + buf[1] = (leading_null_bytes >> 8) & 0xff; + buf[2] = leading_null_bytes & 0xff; + i2c_master_send(client, buf, 3); + /* compute PAT */ memcpy(localPAT, PAT, sizeof(PAT)); localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f); @@ -812,14 +818,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) int i; switch (cmd) { + case VIDIOC_INT_INIT: + /* apply settings and start encoder */ + saa6752hs_init(client, *(u32 *)arg); + break; case VIDIOC_S_EXT_CTRLS: if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; - if (ctrls->count == 0) { - /* apply settings and start encoder */ - saa6752hs_init(client); - break; - } /* fall through */ case VIDIOC_TRY_EXT_CTRLS: case VIDIOC_G_EXT_CTRLS: diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index f5a186a13db..946edf64dc2 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -64,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev) static int ts_init_encoder(struct saa7134_dev* dev) { - struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; - + u32 leading_null_bytes = 0; + + /* If more cards start to need this, then this + should probably be added to the card definitions. */ + switch (dev->board) { + case SAA7134_BOARD_BEHOLD_M6: + case SAA7134_BOARD_BEHOLD_M63: + case SAA7134_BOARD_BEHOLD_M6_EXTRA: + leading_null_bytes = 1; + break; + } ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); + saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes); dev->empress_started = 1; return 0; } -- GitLab From 8809b9cc8658d27c17d4fc07811b0ebd3f74f20c Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Tue, 26 Aug 2008 13:47:10 -0300 Subject: [PATCH 4024/5416] V4L/DVB (8796): saa7134-empress: remove incorrect IRQ defines for TS SAA7134_IRQ1_INTE_RA2_3 and SAA7134_IRQ1_INTE_RA2_2 are used for planar video, not for TS. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 148aa81dc24..12872c042f3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -416,9 +416,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) /* TS capture -- dma 5 */ if (dev->ts_q.curr) { ctrl |= SAA7134_MAIN_CTRL_TE5; - irq |= SAA7134_IRQ1_INTE_RA2_3 | - SAA7134_IRQ1_INTE_RA2_2 | - SAA7134_IRQ1_INTE_RA2_1 | + irq |= SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; } -- GitLab From 92c36147a7fdcead94f98c0a14f30d279653fa64 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Tue, 26 Aug 2008 14:16:33 -0300 Subject: [PATCH 4025/5416] V4L/DVB (8797): A simple state machine was added to saa7134_ts. A simple state machine was added to saa7134_ts. It has three states: SAA7134_TS_STOPPED SAA7134_TS_BUFF_DONE SAA7134_TS_STARTED When buffer_setup is run we start the TS initialization: set SAA7134_TS_STOPPED. When all buffers are prepared we write data into DMA register and set SAA7134_TS_BUFF_DONE. When the first buffer is active start TS and set SAA7134_TS_STARTED. When ts_release is called stop TS and set SAA7134_TS_STOPPED. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-ts.c | 56 +++++++++++++++++++----- drivers/media/video/saa7134/saa7134.h | 8 ++++ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index eae72fd60ce..ef55a59f0cd 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev, saa7134_set_dmabits(dev); mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); + + if (dev->ts_state == SAA7134_TS_BUFF_DONE) { + /* Clear TS cache */ + dev->buff_cnt = 0; + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + saa_writeb(SAA7134_TS_SERIAL1, 0x03); + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + saa_writeb(SAA7134_TS_SERIAL1, 0x01); + + /* TS clock non-inverted */ + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + + /* Start TS stream */ + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + saa_writeb(SAA7134_TS_PARALLEL, 0xEC); + dev->ts_state = SAA7134_TS_STARTED; + } + return 0; } static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) + enum v4l2_field field) { struct saa7134_dev *dev = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); @@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, goto oops; } - /* dma: setup channel 5 (= TS) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); - - saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); - saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); - saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ - saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE); - saa_writel(SAA7134_RS_CONTROL(5),control); + dev->buff_cnt++; + + if (dev->buff_cnt == dev->ts.nr_bufs) { + dev->ts_state = SAA7134_TS_BUFF_DONE; + /* dma: setup channel 5 (= TS) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (buf->pt->dma >> 12); + + saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff); + saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff); + /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00); + saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); + saa_writel(SAA7134_RS_CONTROL(5), control); + } buf->vb.state = VIDEOBUF_PREPARED; buf->activate = buffer_activate; @@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) if (0 == *count) *count = dev->ts.nr_bufs; *count = saa7134_buffer_count(*size,*count); + dev->buff_cnt = 0; + dev->ts_state = SAA7134_TS_STOPPED; return 0; } @@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + struct saa7134_dev *dev = q->priv_data; + if (dev->ts_state == SAA7134_TS_STARTED) { + /* Stop TS transport */ + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + dev->ts_state = SAA7134_TS_STOPPED; + } saa7134_dma_free(q,buf); } @@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev) /* deactivate TS softreset */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ - saa_writeb(SAA7134_TS_PARALLEL, 0xec); + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a0884f639f6..a1e0dad1267 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -462,6 +462,12 @@ struct saa7134_mpeg_ops { void (*signal_change)(struct saa7134_dev *dev); }; +enum saa7134_ts_status { + SAA7134_TS_STOPPED, + SAA7134_TS_BUFF_DONE, + SAA7134_TS_STARTED, +}; + /* global device status */ struct saa7134_dev { struct list_head devlist; @@ -555,6 +561,8 @@ struct saa7134_dev { /* SAA7134_MPEG_* */ struct saa7134_ts ts; struct saa7134_dmaqueue ts_q; + enum saa7134_ts_status ts_state; + unsigned int buff_cnt; struct saa7134_mpeg_ops *mops; struct i2c_client *mpeg_i2c_client; -- GitLab From 28531558006d5c525b19a207a7ab4ec0643191c9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Aug 2008 15:16:31 -0300 Subject: [PATCH 4026/5416] V4L/DVB (8799): soc-camera: add API documentation Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/soc-camera.txt | 120 +++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Documentation/video4linux/soc-camera.txt diff --git a/Documentation/video4linux/soc-camera.txt b/Documentation/video4linux/soc-camera.txt new file mode 100644 index 00000000000..178ef3c5e57 --- /dev/null +++ b/Documentation/video4linux/soc-camera.txt @@ -0,0 +1,120 @@ + Soc-Camera Subsystem + ==================== + +Terminology +----------- + +The following terms are used in this document: + - camera / camera device / camera sensor - a video-camera sensor chip, capable + of connecting to a variety of systems and interfaces, typically uses i2c for + control and configuration, and a parallel or a serial bus for data. + - camera host - an interface, to which a camera is connected. Typically a + specialised interface, present on many SoCs, e.g., PXA27x and PXA3xx, SuperH, + AVR32, i.MX27, i.MX31. + - camera host bus - a connection between a camera host and a camera. Can be + parallel or serial, consists of data and control lines, e.g., clock, vertical + and horizontal synchronization signals. + +Purpose of the soc-camera subsystem +----------------------------------- + +The soc-camera subsystem provides a unified API between camera host drivers and +camera sensor drivers. It implements a V4L2 interface to the user, currently +only the mmap method is supported. + +This subsystem has been written to connect drivers for System-on-Chip (SoC) +video capture interfaces with drivers for CMOS camera sensor chips to enable +the reuse of sensor drivers with various hosts. The subsystem has been designed +to support multiple camera host interfaces and multiple cameras per interface, +although most applications have only one camera sensor. + +Existing drivers +---------------- + +As of 2.6.27-rc4 there are two host drivers in the mainline: pxa_camera.c for +PXA27x SoCs and sh_mobile_ceu_camera.c for SuperH SoCs, and four sensor drivers: +mt9m001.c, mt9m111.c, mt9v022.c and a generic soc_camera_platform.c driver. This +list is not supposed to be updated, look for more examples in your tree. + +Camera host API +--------------- + +A host camera driver is registered using the + +soc_camera_host_register(struct soc_camera_host *); + +function. The host object can be initialized as follows: + +static struct soc_camera_host pxa_soc_camera_host = { + .drv_name = PXA_CAM_DRV_NAME, + .ops = &pxa_soc_camera_host_ops, +}; + +All camera host methods are passed in a struct soc_camera_host_ops: + +static struct soc_camera_host_ops pxa_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, + .suspend = pxa_camera_suspend, + .resume = pxa_camera_resume, + .set_fmt_cap = pxa_camera_set_fmt_cap, + .try_fmt_cap = pxa_camera_try_fmt_cap, + .init_videobuf = pxa_camera_init_videobuf, + .reqbufs = pxa_camera_reqbufs, + .poll = pxa_camera_poll, + .querycap = pxa_camera_querycap, + .try_bus_param = pxa_camera_try_bus_param, + .set_bus_param = pxa_camera_set_bus_param, +}; + +.add and .remove methods are called when a sensor is attached to or detached +from the host, apart from performing host-internal tasks they shall also call +sensor driver's .init and .release methods respectively. .suspend and .resume +methods implement host's power-management functionality and its their +responsibility to call respective sensor's methods. .try_bus_param and +.set_bus_param are used to negotiate physical connection parameters between the +host and the sensor. .init_videobuf is called by soc-camera core when a +video-device is opened, further video-buffer management is implemented completely +by the specific camera host driver. The rest of the methods are called from +respective V4L2 operations. + +Camera API +---------- + +Sensor drivers can use struct soc_camera_link, typically provided by the +platform, and used to specify to which camera host bus the sensor is connected, +and arbitrarily provide platform .power and .reset methods for the camera. +soc_camera_device_register() and soc_camera_device_unregister() functions are +used to add a sensor driver to or remove one from the system. The registration +function takes a pointer to struct soc_camera_device as the only parameter. +This struct can be initialized as follows: + + /* link to driver operations */ + icd->ops = &mt9m001_ops; + /* link to the underlying physical (e.g., i2c) device */ + icd->control = &client->dev; + /* window geometry */ + icd->x_min = 20; + icd->y_min = 12; + icd->x_current = 20; + icd->y_current = 12; + icd->width_min = 48; + icd->width_max = 1280; + icd->height_min = 32; + icd->height_max = 1024; + icd->y_skip_top = 1; + /* camera bus ID, typically obtained from platform data */ + icd->iface = icl->bus_id; + +struct soc_camera_ops provides .probe and .remove methods, which are called by +the soc-camera core, when a camera is matched against or removed from a camera +host bus, .init, .release, .suspend, and .resume are called from the camera host +driver as discussed above. Other members of this struct provide respective V4L2 +functionality. + +struct soc_camera_device also links to an array of struct soc_camera_data_format, +listing pixel formats, supported by the camera. + +-- +Author: Guennadi Liakhovetski -- GitLab From ba77531f51d59a4ca4e5f9b5960301f7dc7a5390 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 27 Aug 2008 17:20:01 -0300 Subject: [PATCH 4027/5416] V4L/DVB (8800): [v4l-dvb-maintainer] [PATCH] v4l: mt9m111.c make function static drivers/media/video/mt9m111.c:758:5: warning: symbol 'mt9m111_restore_state' was not declared. Should it be static? New warning in next-20080825 Signed-off-by: Harvey Harrison Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m111.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 4844486d72f..da0b2d553fd 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -755,7 +755,7 @@ static int mt9m111_set_control(struct soc_camera_device *icd, return ret; } -int mt9m111_restore_state(struct soc_camera_device *icd) +static int mt9m111_restore_state(struct soc_camera_device *icd) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); -- GitLab From 4c56b04af67211c4311dd9961ce5aba86b96ba9c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 12 Aug 2008 13:30:03 -0300 Subject: [PATCH 4028/5416] V4L/DVB (8807): Add DVB support for the Leadtek Winfast PxDVR3200 H This patch is on behalf of Stephen Backway , and represents two patches I received (and some subsequent whitespace cleanup I had due to how I pulled the patches). From the original author: a) Add DVB support for the Leadtek Winfast PxDVR3200 H. b) The tuner callback previously checked the command 3 times: 1) To see if it was the XC2028_RESET_CLK 2) To see if it was not the XC2028_RESET_TUNER 3) To see if it was the XC2028_RESET_TUNER This patch removes the third check. Signed-off-by: Steven Toth Signed-off-by: Stephen Backway Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/Kconfig | 1 + drivers/media/video/cx23885/cx23885-cards.c | 42 +++++++++++++++------ drivers/media/video/cx23885/cx23885-dvb.c | 26 +++++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index bccafd35785..64823ccacd6 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -10,3 +10,4 @@ 9 -> Hauppauge WinTV-HVR1400 [0070:8010] 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618] 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] + 12 -> Leadtek Winfast PxDVR3200 H [107d:6681] diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e60bd31b51a..8c1b7fa47a4 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -15,6 +15,7 @@ config VIDEO_CX23885 select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 0daffc3dbec..ccea8de7c7d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -154,6 +154,10 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = { + .name = "Leadtek Winfast PxDVR3200 H", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -229,6 +233,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb78, .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP, + }, { + .subvendor = 0x107d, + .subdevice = 0x6681, + .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -348,21 +356,18 @@ int cx23885_tuner_callback(void *priv, int command, int arg) case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: + case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: /* Tuner Reset Command */ - if (command == 0) - bitmask = 0x04; + bitmask = 0x04; break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: - if (command == 0) { - - /* Two identical tuners on two different i2c buses, - * we need to reset the correct gpio. */ - if (port->nr == 0) - bitmask = 0x01; - else if (port->nr == 1) - bitmask = 0x04; - } + /* Two identical tuners on two different i2c buses, + * we need to reset the correct gpio. */ + if (port->nr == 0) + bitmask = 0x01; + else if (port->nr == 1) + bitmask = 0x04; break; } @@ -491,6 +496,19 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) mdelay(20); cx_set(GP0_IO, 0x000f000f); break; + case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + /* GPIO-2 xc3028 tuner reset */ + + /* The following GPIO's are on the internal AVCore (cx25840) */ + /* GPIO-? zl10353 demod reset */ + + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00040000); + mdelay(20); + cx_clear(GP0_IO, 0x00000004); + mdelay(20); + cx_set(GP0_IO, 0x00040004); + break; } } @@ -578,6 +596,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_HAUPPAUGE_HVR1400: + case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -591,6 +610,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1700: + case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: request_module("cx25840"); break; } diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f8564bb0d42..b85cb39b101 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -501,6 +501,32 @@ static int dvb_register(struct cx23885_tsport *port) } break; } + case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + i2c_bus = &dev->i2c_bus[0]; + + port->dvb.frontend = dvb_attach(zl10353_attach, + &dvico_fusionhdtv_xc3028, + &i2c_bus->i2c_adap); + if (port->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_bus[1].i2c_adap, + .i2c_addr = 0x61, + .video_dev = port, + .callback = cx23885_tuner_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028-v27.fw", + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + }; + + fe = dvb_attach(xc2028_attach, port->dvb.frontend, + &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index db52d814a97..4e0fcb3f7fc 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -65,6 +65,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 +#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- GitLab From abc94fc8feb1488079dd7dd46bd61d37d91c5658 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 27 Aug 2008 10:46:39 -0300 Subject: [PATCH 4029/5416] V4L/DVB (8838): CRED: Wrap task credential accesses in video input drivers Wrap access to task credentials so that they can be separated more easily from the task_struct during the introduction of COW creds. Change most current->(|e|s|fs)[ug]id to current_(|e|s|fs)[ug]id(). Change some task->e?[ug]id to task_e?[ug]id(). In some places it makes more sense to use RCU directly rather than a convenient wrapper; these will be addressed by later patches. Signed-off-by: David Howells Reviewed-by: James Morris Acked-by: Serge Hallyn Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index b14c59c281e..c325e926de8 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3202,7 +3202,7 @@ static int cpia_open(struct inode *inode, struct file *file) /* Set ownership of /proc/cpia/videoX to current user */ if(cam->proc_entry) - cam->proc_entry->uid = current->uid; + cam->proc_entry->uid = current_uid(); /* set mark for loading first frame uncompressed */ cam->first_frame = 1; -- GitLab From 22b88d48a08e334d36218ca166749c4e6d644f0c Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Fri, 29 Aug 2008 15:33:19 -0300 Subject: [PATCH 4030/5416] V4L/DVB (8845): s2255drv: adds JPEG compression quality control adds VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP ioctls for controlling JPEG compression quality. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index ea40f4c8b33..b8e10455220 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -58,6 +58,8 @@ +/* default JPEG quality */ +#define S2255_DEF_JPEG_QUAL 50 /* vendor request in */ #define S2255_VR_IN 0 /* vendor request out */ @@ -242,6 +244,8 @@ struct s2255_dev { struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; struct s2255_bufferi buffer[MAX_CHANNELS]; struct s2255_mode mode[MAX_CHANNELS]; + /* jpeg compression */ + struct v4l2_jpegcompression jc[MAX_CHANNELS]; const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; int cur_frame[MAX_CHANNELS]; int last_frame[MAX_CHANNELS]; @@ -1035,7 +1039,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->mode.color = COLOR_Y8; break; case V4L2_PIX_FMT_JPEG: - fh->mode.color = COLOR_JPG | (50 << 8); + fh->mode.color = COLOR_JPG | + (fh->dev->jc[fh->channel].quality << 8); break; case V4L2_PIX_FMT_YUV422P: fh->mode.color = COLOR_YUVPL; @@ -1208,6 +1213,10 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, dev->mode[chn].scale); dprintk(2, "mode contrast %x\n", mode->contrast); + /* if JPEG, set the quality */ + if ((mode->color & MASK_COLOR) == COLOR_JPG) + mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG; + /* save the mode */ dev->mode[chn] = *mode; dev->req_image_size[chn] = get_transfer_size(mode); @@ -1472,6 +1481,27 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } +static int vidioc_g_jpegcomp(struct file *file, void *priv, + struct v4l2_jpegcompression *jc) +{ + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; + *jc = dev->jc[fh->channel]; + dprintk(2, "getting jpegcompression, quality %d\n", jc->quality); + return 0; +} + +static int vidioc_s_jpegcomp(struct file *file, void *priv, + struct v4l2_jpegcompression *jc) +{ + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; + if (jc->quality < 0 || jc->quality > 100) + return -EINVAL; + dev->jc[fh->channel].quality = jc->quality; + dprintk(2, "setting jpeg quality %d\n", jc->quality); + return 0; +} static int s2255_open(struct inode *inode, struct file *file) { int minor = iminor(inode); @@ -1762,6 +1792,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidioc_cgmbuf, #endif + .vidioc_s_jpegcomp = vidioc_s_jpegcomp, + .vidioc_g_jpegcomp = vidioc_g_jpegcomp, }; static struct video_device template = { @@ -2148,6 +2180,7 @@ static int s2255_board_init(struct s2255_dev *dev) for (j = 0; j < MAX_CHANNELS; j++) { dev->b_acquire[j] = 0; dev->mode[j] = mode_def; + dev->jc[j].quality = S2255_DEF_JPEG_QUAL; dev->cur_fmt[j] = &formats[0]; dev->mode[j].restart = 1; dev->req_image_size[j] = get_transfer_size(&mode_def); -- GitLab From 08ebd003d90955d78b58bb348a098fee301b8a82 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 29 Aug 2008 17:37:44 -0300 Subject: [PATCH 4031/5416] V4L/DVB (8846): uvcvideo: Supress spurious "EOF in empty payload" trace message Pass the payload size instead of the header size to uvc_video_decode_end() to avoid generating an extra trace message for each frame. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 03dc3a519e4..593aebffe57 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -455,7 +455,8 @@ static void uvc_video_decode_isoc(struct urb *urb, urb->iso_frame_desc[i].actual_length - ret); /* Process the header again. */ - uvc_video_decode_end(video, buf, mem, ret); + uvc_video_decode_end(video, buf, mem, + urb->iso_frame_desc[i].actual_length); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) @@ -512,7 +513,7 @@ static void uvc_video_decode_bulk(struct urb *urb, video->bulk.payload_size >= video->bulk.max_payload_size) { if (!video->bulk.skip_payload && buf != NULL) { uvc_video_decode_end(video, buf, video->bulk.header, - video->bulk.header_size); + video->bulk.payload_size); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) buf = uvc_queue_next_buffer(&video->queue, buf); -- GitLab From 4e08caf0cb85c4f63ddaf72a67d95fba8528e04e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 29 Aug 2008 17:57:10 -0300 Subject: [PATCH 4032/5416] V4L/DVB (8847): uvcvideo: Add support for a Bison Electronics webcam found in the Fujitsu Amilo SI2636. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 4a2d09988fa..4ab4d1ebb22 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1930,6 +1930,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* Fujitsu Amilo SI2636 - Bison Electronics */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x5986, + .idProduct = 0x0202, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bison Electronics */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- GitLab From 187565c43a95bcf7798c58d518ddd765933d24da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 30 Aug 2008 06:03:09 -0300 Subject: [PATCH 4033/5416] V4L/DVB (8850): bt856: fix define conflict Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt856.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 98ee2d8feb3..ab2ce4d7b5d 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -68,8 +68,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ -#define REG_OFFSET 0xDA -#define BT856_NR_REG 6 +#define BT856_REG_OFFSET 0xDA +#define BT856_NR_REG 6 struct bt856 { unsigned char reg[BT856_NR_REG]; @@ -89,7 +89,7 @@ bt856_write (struct i2c_client *client, { struct bt856 *encoder = i2c_get_clientdata(client); - encoder->reg[reg - REG_OFFSET] = value; + encoder->reg[reg - BT856_REG_OFFSET] = value; return i2c_smbus_write_byte_data(client, reg, value); } @@ -103,7 +103,7 @@ bt856_setbit (struct i2c_client *client, return bt856_write(client, reg, (encoder-> - reg[reg - REG_OFFSET] & ~(1 << bit)) | + reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -- GitLab From 7f8ecfab7a1d256707502207c56dd4bf3e3a026e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 29 Aug 2008 17:31:35 -0300 Subject: [PATCH 4034/5416] V4L/DVB (8852): v4l2: use register_chrdev_region instead of register_chrdev Replace the old register_chrdev with the more flexible register_chrdev_region. Ensure that the release() is called when the very last chardev usage was released, and not when the sysfs devices were removed. This should simplify hotpluggable drivers considerably. Tested-by: Mike Isely Tested-by: Laurent Pinchart Signed-off-by: Hans Verkuil Acked-by: David Ellingsworth Reviewed-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 131 ++++++++++++++++----------------- include/media/v4l2-dev.h | 3 + 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 99f7ee4bc50..02b9cc76d36 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -60,6 +60,12 @@ static struct device_attribute video_device_attrs[] = { __ATTR_NULL }; +/* + * Active devices + */ +static struct video_device *video_device[VIDEO_NUM_DEVICES]; +static DEFINE_MUTEX(videodev_lock); + struct video_device *video_device_alloc(void) { return kzalloc(sizeof(struct video_device), GFP_KERNEL); @@ -79,11 +85,41 @@ void video_device_release_empty(struct video_device *vfd) } EXPORT_SYMBOL(video_device_release_empty); +/* Called when the last user of the character device is gone. */ +static void v4l2_chardev_release(struct kobject *kobj) +{ + struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); + + mutex_lock(&videodev_lock); + if (video_device[vfd->minor] != vfd) + panic("videodev: bad release"); + + /* Free up this device for reuse */ + video_device[vfd->minor] = NULL; + mutex_unlock(&videodev_lock); + + /* Release the character device */ + vfd->cdev_release(kobj); + /* Release video_device and perform other + cleanups as needed. */ + if (vfd->release) + vfd->release(vfd); +} + +/* The new kobj_type for the character device */ +static struct kobj_type v4l2_ktype_cdev_default = { + .release = v4l2_chardev_release, +}; + static void video_release(struct device *cd) { struct video_device *vfd = container_of(cd, struct video_device, dev); - vfd->release(vfd); + /* It's now safe to delete the char device. + This will either trigger the v4l2_chardev_release immediately (if + the refcount goes to 0) or later when the last user of the + character device closes it. */ + cdev_del(&vfd->cdev); } static struct class video_class = { @@ -92,56 +128,12 @@ static struct class video_class = { .dev_release = video_release, }; -/* - * Active devices - */ - -static struct video_device *video_device[VIDEO_NUM_DEVICES]; -static DEFINE_MUTEX(videodev_lock); - struct video_device *video_devdata(struct file *file) { return video_device[iminor(file->f_path.dentry->d_inode)]; } EXPORT_SYMBOL(video_devdata); -/* - * Open a video device - FIXME: Obsoleted - */ -static int video_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - int err = 0; - struct video_device *vfl; - const struct file_operations *old_fops; - - if (minor >= VIDEO_NUM_DEVICES) - return -ENODEV; - mutex_lock(&videodev_lock); - vfl = video_device[minor]; - if (vfl == NULL) { - mutex_unlock(&videodev_lock); - request_module("char-major-%d-%d", VIDEO_MAJOR, minor); - mutex_lock(&videodev_lock); - vfl = video_device[minor]; - if (vfl == NULL) { - mutex_unlock(&videodev_lock); - return -ENODEV; - } - } - old_fops = file->f_op; - file->f_op = fops_get(vfl->fops); - if (file->f_op->open) - err = file->f_op->open(inode, file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); - mutex_unlock(&videodev_lock); - return err; -} - /** * get_index - assign stream number based on parent device * @vdev: video_device to assign index number to, vdev->dev should be assigned @@ -261,6 +253,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, return -EINVAL; } + /* Initialize the character device */ + cdev_init(&vfd->cdev, vfd->fops); + vfd->cdev.owner = vfd->fops->owner; /* pick a minor number */ mutex_lock(&videodev_lock); if (nr >= 0 && nr < end-base) { @@ -294,6 +289,11 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, goto fail_minor; } + ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1); + if (ret < 0) { + printk(KERN_ERR "%s: cdev_add failed\n", __func__); + goto fail_minor; + } /* sysfs class */ memset(&vfd->dev, 0, sizeof(vfd->dev)); /* The memset above cleared the device's drvdata, so @@ -307,11 +307,17 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, ret = device_register(&vfd->dev); if (ret < 0) { printk(KERN_ERR "%s: device_register failed\n", __func__); - goto fail_minor; + goto del_cdev; } - + /* Remember the cdev's release function */ + vfd->cdev_release = vfd->cdev.kobj.ktype->release; + /* Install our own */ + vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default; return 0; +del_cdev: + cdev_del(&vfd->cdev); + fail_minor: mutex_lock(&videodev_lock); video_device[vfd->minor] = NULL; @@ -331,42 +337,29 @@ EXPORT_SYMBOL(video_register_device_index); void video_unregister_device(struct video_device *vfd) { - mutex_lock(&videodev_lock); - if (video_device[vfd->minor] != vfd) - panic("videodev: bad unregister"); - - video_device[vfd->minor] = NULL; device_unregister(&vfd->dev); - mutex_unlock(&videodev_lock); } EXPORT_SYMBOL(video_unregister_device); -/* - * Video fs operations - */ -static const struct file_operations video_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = video_open, -}; - /* * Initialise video for linux */ - static int __init videodev_init(void) { + dev_t dev = MKDEV(VIDEO_MAJOR, 0); int ret; printk(KERN_INFO "Linux video capture interface: v2.00\n"); - if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { - printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); - return -EIO; + ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME); + if (ret < 0) { + printk(KERN_WARNING "videodev: unable to get major %d\n", + VIDEO_MAJOR); + return ret; } ret = class_register(&video_class); if (ret < 0) { - unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); + unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); printk(KERN_WARNING "video_dev: class_register failed\n"); return -EIO; } @@ -376,8 +369,10 @@ static int __init videodev_init(void) static void __exit videodev_exit(void) { + dev_t dev = MKDEV(VIDEO_MAJOR, 0); + class_unregister(&video_class); - unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); + unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); } module_init(videodev_init) diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index fb92e3d22d7..d129b56e1a9 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ struct video_device /* sysfs */ struct device dev; /* v4l device */ + struct cdev cdev; /* character device */ + void (*cdev_release)(struct kobject *kobj); struct device *parent; /* device parent */ /* device info */ -- GitLab From 20c104d0a4d055cfa3df4fcbae818f8e10bd541a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 30 Aug 2008 08:21:13 -0300 Subject: [PATCH 4035/5416] V4L/DVB (8856): v4l: fix assorted compile warnings/errors BIT define conflicts on kernels < 2.6.24, byteorder/swab.h doesn't need to be included at all. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 1 - drivers/media/video/cx18/cx18-i2c.c | 2 -- drivers/media/video/ivtv/ivtv-driver.h | 1 - drivers/media/video/ivtv/ivtv-i2c.c | 2 -- drivers/media/video/vpx3220.c | 2 -- 5 files changed, 8 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 26359897d14..7bdd2fcdf20 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 6023ba3bd3a..7d8fb25baae 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -27,8 +27,6 @@ #include "cx18-av-core.h" #include "cx18-i2c.h" -#include - #define CX18_REG_I2C_1_WR 0xf15000 #define CX18_REG_I2C_1_RD 0xf15008 #define CX18_REG_I2C_2_WR 0xf25100 diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 2ceb5227637..b76a1226863 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index af154238fb9..24700c211d5 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -64,8 +64,6 @@ #include "ivtv-gpio.h" #include "ivtv-i2c.h" -#include - /* i2c implementation for cx23415/6 chip, ivtv project. * Author: Kevin Thayer (nufan_wfk at yahoo.com) */ diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 35293029da0..45be9ec8edc 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -24,8 +24,6 @@ #include #include -#include - #include #include -- GitLab From 6ea9a1829a89515c1866151b1fdca7ee612d1490 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 30 Aug 2008 09:40:47 -0300 Subject: [PATCH 4036/5416] V4L/DVB (8857): v4l2-dev: replace panic with BUG Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 02b9cc76d36..7addf2fd55d 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -91,8 +91,11 @@ static void v4l2_chardev_release(struct kobject *kobj) struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); mutex_lock(&videodev_lock); - if (video_device[vfd->minor] != vfd) - panic("videodev: bad release"); + if (video_device[vfd->minor] != vfd) { + mutex_unlock(&videodev_lock); + BUG(); + return; + } /* Free up this device for reuse */ video_device[vfd->minor] = NULL; -- GitLab From bccd7003aef20e040cef95d1216dac26199d7071 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 30 Aug 2008 12:15:54 -0300 Subject: [PATCH 4037/5416] V4L/DVB (8866): Add dummy FE to the Kconfig-file and fix it Reactivated dummy frontend driver which is extremely useful for debugging. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 6 ++++++ drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dvb_dummy_fe.c | 7 ++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 774f5c2a71e..e2444f270f0 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -392,4 +392,10 @@ config DVB_LGS8GL5 help A DMB-TH tuner module. Say Y when you want to support this frontend. +comment "Tools to develop new frontends" + +config DVB_DUMMY_FE + tristate "Dummy frontend driver" + default n + endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 262eaa429f5..ca24618d5da 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -49,3 +49,4 @@ obj-$(CONFIG_DVB_AU8522) += au8522.o obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o +obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index fed09dfb2b7..cb4d8a3b9d8 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -75,9 +75,10 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - if (fe->ops->tuner_ops->set_params) { - fe->ops->tuner_ops->set_params(fe, p); - if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } return 0; -- GitLab From eb1b27bd86db6f9f73d6db973b18f31790a3d410 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 30 Aug 2008 10:18:21 -0300 Subject: [PATCH 4038/5416] V4L/DVB (8879): bttv: Don't unmask VPRES interrupt When the input is set to tuner and no antenna is connected, the BT848 can flood VPRES interrupts. So we don't want to enable this type of interrupts when the input it set to tuner. As we don't do anything when receiving such an interrupt anyway, the easiest fix is to simply not unmask this specific interrupt. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 035a58d1aaa..ef205cd2a2a 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1367,7 +1367,7 @@ static void init_irqreg(struct bttv *btv) (btv->gpioirq ? BT848_INT_GPINT : 0) | BT848_INT_SCERR | (fdsr ? BT848_INT_FDSR : 0) | - BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| + BT848_INT_RISCI | BT848_INT_OCERR | BT848_INT_FMTCHG|BT848_INT_HLOCK| BT848_INT_I2CDONE, BT848_INT_MASK); -- GitLab From 26d2e854bc242f0134a4be7f1eed98129d96d943 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Mon, 21 Jul 2008 16:20:32 -0300 Subject: [PATCH 4039/5416] V4L/DVB (8559): replace __FUNCTION__ with __func__ v4l: replace __FUNCTION__ with __func__ Signed-off-by: Alexander Beregalov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-core.c | 2 +- include/media/saa7146.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 25fb0993874..beb3e61669a 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1442,7 +1442,7 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port) struct cx23885_dev *dev = port->dev; struct cx23885_dmaqueue *q = &port->mpegq; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); del_timer_sync(&q->timeout); cx23885_stop_dma(port); do_cancel_buffers(port, "cancel", 0); diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 2f68f4cd003..64a2ec746a3 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -30,7 +30,7 @@ extern unsigned int saa7146_debug; #define DEBUG_VARIABLE saa7146_debug #endif -#define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME,__FUNCTION__) +#define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME, __func__) #define INFO(x) { printk("%s: ",KBUILD_MODNAME); printk x; } #define ERR(x) { DEBUG_PROLOG; printk x; } -- GitLab From 81ae953b687e7cdfa094b07a6544523f3bb81aa3 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 3 Sep 2008 18:16:09 -0300 Subject: [PATCH 4040/5416] V4L/DVB (8888): budget: Support Activy DVB-T with TDHD1 tuner Support Fujitsu-Siemens Activy DVB-T card rev AL (ALPS TDHD1-204A tuner). Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tdhd1.h | 70 +++++++++++++++++++++++++++++ drivers/media/dvb/ttpci/Kconfig | 1 + drivers/media/dvb/ttpci/budget.c | 11 +++++ 3 files changed, 82 insertions(+) create mode 100644 drivers/media/dvb/frontends/tdhd1.h diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h new file mode 100644 index 00000000000..de8aac7d7ae --- /dev/null +++ b/drivers/media/dvb/frontends/tdhd1.h @@ -0,0 +1,70 @@ +/* + * tdhd1.h - ALPS TDHD1-204A tuner support + * + * Copyright (C) 2008 Oliver Endriss + * + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * The project's page is at http://www.linuxtv.org + */ + +#ifndef TDHD1_H +#define TDHD1_H + +#include "tda1004x.h" + +static struct tda1004x_config alps_tdhd1_204a_config = { + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_4M, + .agc_config = TDA10046_AGC_DEFAULT, + .if_freq = TDA10046_FREQ_3617, +}; + +static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct i2c_adapter *i2c = fe->tuner_priv; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + u32 div; + + div = (params->frequency + 36166666) / 166666; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85; + + if (params->frequency >= 174000000 && params->frequency <= 230000000) + data[3] = 0x02; + else if (params->frequency >= 470000000 && params->frequency <= 823000000) + data[3] = 0x0C; + else if (params->frequency > 823000000 && params->frequency <= 862000000) + data[3] = 0x8C; + else + return -EINVAL; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + + return 0; +} + +#endif /* TDHD1_H */ diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 41b5a988b61..867027ceab3 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -86,6 +86,7 @@ config DVB_BUDGET select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_TDA1004X if !DVB_FE_CUSTOMISE help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard MPEG2 decoder, and without diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 851e523fbff..a4664ba5ade 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -46,6 +46,7 @@ #include "lnbp21.h" #include "bsru6.h" #include "bsbe1.h" +#include "tdhd1.h" static int diseqc_method; module_param(diseqc_method, int, 0444); @@ -511,6 +512,14 @@ static void frontend_init(struct budget *budget) } break; + case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */ + budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + } + break; + case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); if (budget->dvb_frontend) { @@ -624,6 +633,7 @@ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); +MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), @@ -634,6 +644,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), + MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), { .vendor = 0, -- GitLab From 9e615eac827094147401c44c9ff955b468d4fa79 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 3 Sep 2008 19:15:27 -0300 Subject: [PATCH 4041/5416] V4L/DVB (8889): dvb-ttpci: Support full-ts hardware modification Add support for the 'full-ts' hardware modification. On full-featured cards the data throughput is limited by the hardware design. The full-ts mod removes this bottleneck, i.e. the card is able to deliver the complete transport stream of a transponder. For details see http://www.escape-edv.de/endriss/dvb-full-ts-mod Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 113 ++++++++++++++++++++++------ drivers/media/dvb/ttpci/av7110.h | 1 + drivers/media/dvb/ttpci/av7110_av.c | 3 + 3 files changed, 92 insertions(+), 25 deletions(-) diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 3b641804f6c..404108f09d7 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -88,6 +88,7 @@ static int budgetpatch; static int wss_cfg_4_3 = 0x4008; static int wss_cfg_16_9 = 0x0007; static int tv_standard; +static int full_ts; module_param_named(debug, av7110_debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); @@ -106,6 +107,8 @@ module_param(volume, int, 0444); MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); module_param(budgetpatch, int, 0444); MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); +module_param(full_ts, int, 0444); +MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable"); module_param(wss_cfg_4_3, int, 0444); MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); module_param(wss_cfg_16_9, int, 0444); @@ -116,6 +119,8 @@ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static void restart_feeds(struct av7110 *av7110); +static int budget_start_feed(struct dvb_demux_feed *feed); +static int budget_stop_feed(struct dvb_demux_feed *feed); static int av7110_num; @@ -806,6 +811,9 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) dprintk(4, "%p\n", av7110); + if (av7110->full_ts) + return 0; + if (dvbdmxfilter->type == DMX_TYPE_SEC) { if (hw_sections) { buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) | @@ -854,6 +862,9 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) dprintk(4, "%p\n", av7110); + if (av7110->full_ts) + return 0; + handle = dvbdmxfilter->hw_handle; if (handle >= 32) { printk("%s tried to stop invalid filter %04x, filter type = %x\n", @@ -913,7 +924,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) return ret; } - if ((dvbdmxfeed->ts_type & TS_PACKET)) { + if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) { if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000)) ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed); if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000)) @@ -974,7 +985,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - if (feed->pid > 0x1fff) + if (!av7110->full_ts && feed->pid > 0x1fff) return -EINVAL; if (feed->type == DMX_TYPE_TS) { @@ -1003,7 +1014,12 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) } } - else if (feed->type == DMX_TYPE_SEC) { + if (av7110->full_ts) { + budget_start_feed(feed); + return ret; + } + + if (feed->type == DMX_TYPE_SEC) { int i; for (i = 0; i < demux->filternum; i++) { @@ -1050,7 +1066,12 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed) ret = StopHWFilter(feed->filter); } - if (!ret && feed->type == DMX_TYPE_SEC) { + if (av7110->full_ts) { + budget_stop_feed(feed); + return ret; + } + + if (feed->type == DMX_TYPE_SEC) { for (i = 0; ifilternum; i++) { if (demux->filter[i].state == DMX_STATE_GO && demux->filter[i].filter.parent == &feed->feed.sec) { @@ -1074,6 +1095,7 @@ static void restart_feeds(struct av7110 *av7110) struct dvb_demux *dvbdmx = &av7110->demux; struct dvb_demux_feed *feed; int mode; + int feeding; int i, j; dprintk(4, "%p\n", av7110); @@ -1082,6 +1104,8 @@ static void restart_feeds(struct av7110 *av7110) av7110->playing = 0; av7110->rec_mode = 0; + feeding = av7110->feeding1; /* full_ts mod */ + for (i = 0; i < dvbdmx->feednum; i++) { feed = &dvbdmx->feed[i]; if (feed->state == DMX_STATE_GO) { @@ -1099,6 +1123,8 @@ static void restart_feeds(struct av7110 *av7110) } } + av7110->feeding1 = feeding; /* full_ts mod */ + if (mode) av7110_av_start_play(av7110, mode); } @@ -1197,8 +1223,9 @@ static int start_ts_capture(struct av7110 *budget) if (budget->feeding1) return ++budget->feeding1; - memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); + memset(budget->grabbing, 0x00, TS_BUFLEN); budget->ttbp = 0; + SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */ SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ return ++budget->feeding1; @@ -1239,12 +1266,8 @@ static void vpeirq(unsigned long data) u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); + struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1; - if (!budgetpatch) { - printk("av7110.c: vpeirq() called while budgetpatch disabled!" - " check saa7146 IER register\n"); - BUG(); - } /* nearest lower position divisible by 188 */ newdma -= newdma % 188; @@ -1268,11 +1291,11 @@ static void vpeirq(unsigned long data) if (newdma > olddma) /* no wraparound, dump olddma..newdma */ - dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188); + dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188); else { /* wraparound, dump olddma..buflen and 0..newdma */ - dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188); - dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188); + dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188); + dvb_dmx_swfilter_packets(demux, mem, newdma / 188); } } @@ -1294,8 +1317,8 @@ static int av7110_register(struct av7110 *av7110) for (i = 0; i < 32; i++) av7110->handle2filter[i] = NULL; - dvbdemux->filternum = 32; - dvbdemux->feednum = 32; + dvbdemux->filternum = (av7110->full_ts) ? 256 : 32; + dvbdemux->feednum = (av7110->full_ts) ? 256 : 32; dvbdemux->start_feed = av7110_start_feed; dvbdemux->stop_feed = av7110_stop_feed; dvbdemux->write_to_decoder = av7110_write_to_decoder; @@ -1305,7 +1328,7 @@ static int av7110_register(struct av7110 *av7110) dvb_dmx_init(&av7110->demux); av7110->demux.dmx.get_stc = dvb_get_stc; - av7110->dmxdev.filternum = 32; + av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32; av7110->dmxdev.demux = &dvbdemux->dmx; av7110->dmxdev.capabilities = 0; @@ -1422,7 +1445,6 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) return i2c_transfer(&av7110->i2c_adap, &msgs, 1); } -#if 0 u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) { u8 mm1[] = {0x00}; @@ -1439,7 +1461,6 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) return mm2[0]; } -#endif /**************************************************************************** * INITIALIZATION @@ -2484,7 +2505,47 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, av7110->dvb_adapter.proposed_mac); ret = -ENOMEM; - if (budgetpatch) { + /* full-ts mod? */ + if (full_ts) + av7110->full_ts = true; + + /* check for full-ts flag in eeprom */ + if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) { + u8 flags = i2c_readreg(av7110, 0xaa, 2); + if (flags != 0xff && (flags & 0x01)) + av7110->full_ts = true; + } + + if (av7110->full_ts) { + printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n"); + spin_lock_init(&av7110->feedlock1); + av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, + &av7110->pt); + if (!av7110->grabbing) + goto err_i2c_del_3; + + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, MC2, (MASK_10 | MASK_26)); + + saa7146_write(dev, DD1_INIT, 0x00000600); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + saa7146_write(dev, BRS_CTRL, 0x60000000); + saa7146_write(dev, MC2, MASK_08 | MASK_24); + + /* dma3 */ + saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); + saa7146_write(dev, BASE_ODD3, 0); + saa7146_write(dev, BASE_EVEN3, 0); + saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT); + saa7146_write(dev, PITCH3, TS_WIDTH); + saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90); + saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH); + saa7146_write(dev, MC2, MASK_04 | MASK_20); + + tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110); + + } else if (budgetpatch) { spin_lock_init(&av7110->feedlock1); av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, &av7110->pt); @@ -2710,11 +2771,13 @@ static int __devexit av7110_detach(struct saa7146_dev* saa) #if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) av7110_ir_exit(av7110); #endif - if (budgetpatch) { - /* Disable RPS1 */ - saa7146_write(saa, MC1, MASK_29); - /* VSYNC LOW (inactive) */ - saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + if (budgetpatch || av7110->full_ts) { + if (budgetpatch) { + /* Disable RPS1 */ + saa7146_write(saa, MC1, MASK_29); + /* VSYNC LOW (inactive) */ + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + } saa7146_write(saa, MC1, MASK_20); /* DMA3 off */ SAA7146_IER_DISABLE(saa, MASK_10); SAA7146_ISR_CLEAR(saa, MASK_10); @@ -2794,7 +2857,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr) tasklet_schedule(&av7110->gpio_tasklet); } - if ((*isr & MASK_10) && budgetpatch) + if (*isr & MASK_10) tasklet_schedule(&av7110->vpe_tasklet); } diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 55f23ddcb99..d85b8512ac3 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -192,6 +192,7 @@ struct av7110 { unsigned char *grabbing; struct saa7146_pgtable pt; struct tasklet_struct vpe_tasklet; + bool full_ts; int fe_synced; struct mutex pid_mutex; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 184647ad1c7..bdc62acf209 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -788,6 +788,9 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l dprintk(2, "av7110:%p, \n", av7110); + if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE) + return 0; + switch (feed->pes_type) { case 0: if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) -- GitLab From 83512e207479d0bdb83ee1e000a306af9e6e870e Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Thu, 4 Sep 2008 20:35:19 -0300 Subject: [PATCH 4042/5416] V4L/DVB (8890): budget: Add callback to load firmware for the TDHD1 tuner Supply callback to load firmware for the TDHD1 tuner (using request_firmware). Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tdhd1.h | 3 +++ drivers/media/dvb/ttpci/budget.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h index de8aac7d7ae..51f17067865 100644 --- a/drivers/media/dvb/frontends/tdhd1.h +++ b/drivers/media/dvb/frontends/tdhd1.h @@ -28,6 +28,8 @@ #include "tda1004x.h" +static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name); + static struct tda1004x_config alps_tdhd1_204a_config = { .demod_address = 0x8, .invert = 1, @@ -35,6 +37,7 @@ static struct tda1004x_config alps_tdhd1_204a_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, + .request_firmware = alps_tdhd1_204_request_firmware }; static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index a4664ba5ade..d95203d5540 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -391,6 +391,13 @@ static struct stv0299_config alps_bsbe1_config_activy = { .set_symbol_rate = alps_bsbe1_set_symbol_rate, }; +static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) +{ + struct budget *budget = (struct budget *)fe->dvb->priv; + + return request_firmware(fw, name, &budget->dev->pci->dev); +} + static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) { -- GitLab From 5f33df1443cd53283279d017b45ed1b1bc66f622 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 30 Aug 2008 15:09:31 -0300 Subject: [PATCH 4043/5416] V4L/DVB (8893): pvrusb2: Add comment elaborating on direct use of swab32() Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7fa903ad26b..c8dedbab6e3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1313,6 +1313,17 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); /* Usbsnoop log shows that we must swap bytes... */ + /* Some background info: The data being swapped here is a + firmware image destined for the mpeg encoder chip that + lives at the other end of a USB endpoint. The encoder + chip always talks in 32 bit chunks and its storage is + organized into 32 bit words. However from the file + system to the encoder chip everything is purely a byte + stream. The firmware file's contents are always 32 bit + swapped from what the encoder expects. Thus the need + always exists to swap the bytes regardless of the endian + type of the host processor and therefore swab32() makes + the most sense. */ for (icnt = 0; icnt < bcnt/4 ; icnt++) ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); -- GitLab From 157afbc0de7d99cde39a5525b4c43acd4e02ef82 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 30 Aug 2008 15:11:16 -0300 Subject: [PATCH 4044/5416] V4L/DVB (8894): pvrusb2: Remove BKL The earlier change from Hans Verkuil that pushed the BKL from video_open() down into the drivers should be unneeded for the pvrusb2 driver. This driver's implementation for open already protects its internal structures through other means, thus the BKL is not required. This change reverses Hans' previous change, for the pvrusb2 driver. It probably would have been a good idea for Hans to previously have asked for my ack before committing his change. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 26ffaa276c5..00306faeac0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -932,7 +932,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) unsigned int input_cnt,idx; int ret = 0; - lock_kernel(); dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); vp = dip->v4lp; @@ -943,13 +942,11 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) if (!pvr2_hdw_dev_ok(hdw)) { pvr2_trace(PVR2_TRACE_OPEN_CLOSE, "pvr2_v4l2_open: hardware not ready"); - unlock_kernel(); return -EIO; } fhp = kzalloc(sizeof(*fhp),GFP_KERNEL); if (!fhp) { - unlock_kernel(); return -ENOMEM; } @@ -979,7 +976,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) fhp); kfree(fhp); - unlock_kernel(); return ret; } @@ -996,7 +992,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) "Destroying pvr_v4l2_fh id=%p (input map failure)", fhp); kfree(fhp); - unlock_kernel(); return -ENOMEM; } input_cnt = 0; @@ -1020,7 +1015,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) v4l2_prio_open(&vp->prio,&fhp->prio); fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); - unlock_kernel(); return 0; } -- GitLab From fe15f13679bf52bb5c8acb8b4847e6d73ba62c17 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 30 Aug 2008 18:11:40 -0300 Subject: [PATCH 4045/5416] V4L/DVB (8895): pvrusb2: Fail gracefully if an alien USB ID is used The driver includes an internal table specifying additional information on a per device-type basis. This works great until somebody tries to run-time associate another USB ID with the driver. This change should hopefully allow the driver to fail gracefully under such a circumstance. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c8dedbab6e3..a7d636f3f9b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1915,7 +1915,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, const struct usb_device_id *devid) { unsigned int idx,cnt1,cnt2,m; - struct pvr2_hdw *hdw; + struct pvr2_hdw *hdw = NULL; int valid_std_mask; struct pvr2_ctrl *cptr; const struct pvr2_device_desc *hdw_desc; @@ -1925,6 +1925,16 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); + if (hdw_desc == NULL) { + pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:" + " No device description pointer," + " unable to continue."); + pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type," + " please contact Mike Isely " + " to get it included in the driver\n"); + goto fail; + } + hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", hdw,hdw_desc->description); -- GitLab From e784bfb93c155ba4b354452c69ac02a29d336d97 Mon Sep 17 00:00:00 2001 From: "vdb128@picaros.org" Date: Sat, 30 Aug 2008 18:26:39 -0300 Subject: [PATCH 4046/5416] V4L/DVB (8896): pvrusb2: Implement crop support Implement pvrusb2 driver plumbing to support cropping. Submitted by a pvrusb2 user. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../video/pvrusb2/pvrusb2-hdw-internal.h | 5 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 119 ++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 4 + .../video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 7 +- .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 49 ++++++++ .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 1 + 6 files changed, 183 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 657f861593b..0453244b7fa 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -319,6 +319,7 @@ struct pvr2_hdw { struct pvr2_ctl_info std_info_cur; struct v4l2_standard *std_defs; const char **std_enum_names; + struct v4l2_cropcap cropcap; // Generated string names, one per actual V4L2 standard const char *std_mask_ptrs[32]; @@ -367,6 +368,10 @@ struct pvr2_hdw { VCREATE_DATA(bass); VCREATE_DATA(treble); VCREATE_DATA(mute); + VCREATE_DATA(cropl); + VCREATE_DATA(cropt); + VCREATE_DATA(cropw); + VCREATE_DATA(croph); VCREATE_DATA(input); VCREATE_DATA(audiomode); VCREATE_DATA(res_hor); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a7d636f3f9b..68f4315201a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -402,6 +402,52 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) return 0; } +static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap; + if (cap->bounds.width > 0) { + /* This statement is present purely to shut up + checkpatch.pl */ + *left = cap->bounds.left - cap->defrect.left; + } else { + /* This statement is present purely to shut up + checkpatch.pl */ + *left = -119; + } + return 0; +} + +static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap; + if (cap->bounds.width > 0) { + *left = cap->bounds.left + cap->bounds.width + - cap->defrect.left; + *left += 3; + *left -= cptr->hdw->cropw_val; + } else { + /* This statement is present purely to shut up + checkpatch.pl */ + *left = 340; + } + return 0; +} + +static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap; + if (cap->bounds.height > 0) { + /* This statement is present purely to shut up + checkpatch.pl */ + *top = cap->bounds.top - cap->defrect.top; + } else { + /* This statement is present purely to shut up + checkpatch.pl */ + *top = -19; + } + return 0; +} + static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) { /* Actual maximum depends on the video standard in effect. */ @@ -413,6 +459,19 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) return 0; } +static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap; + if (cap->bounds.height > 0) { + *top = cap->bounds.top + cap->bounds.height - cap->defrect.top; + *top -= cptr->hdw->croph_val; + } else { + ctrl_vres_max_get(cptr, top); + *top -= 32; + } + return 0; +} + static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp) { /* Actual minimum depends on device digitizer type. */ @@ -779,6 +838,10 @@ VCREATE_FUNCS(balance) VCREATE_FUNCS(bass) VCREATE_FUNCS(treble) VCREATE_FUNCS(mute) +VCREATE_FUNCS(cropl) +VCREATE_FUNCS(cropt) +VCREATE_FUNCS(cropw) +VCREATE_FUNCS(croph) VCREATE_FUNCS(audiomode) VCREATE_FUNCS(res_hor) VCREATE_FUNCS(res_ver) @@ -849,6 +912,39 @@ static const struct pvr2_ctl_info control_defs[] = { .default_value = 0, DEFREF(mute), DEFBOOL, + }, { + .desc = "Capture left margin", + .name = "crop_left", + .internal_id = PVR2_CID_CROPL, + .default_value = 0, + DEFREF(cropl), + DEFINT(-129, 340), + .get_min_value = ctrl_cropl_min_get, + .get_max_value = ctrl_cropl_max_get, + }, { + .desc = "Capture top margin", + .name = "crop_top", + .internal_id = PVR2_CID_CROPT, + .default_value = 0, + DEFREF(cropt), + DEFINT(-35, 544), + .get_min_value = ctrl_cropt_min_get, + .get_max_value = ctrl_cropt_max_get, + }, { + .desc = "Capture width", + .name = "crop_width", + .internal_id = PVR2_CID_CROPW, + .default_value = 720, + DEFREF(cropw), + DEFINT(388, 849), /* determined empirically, any res_hor>=64 */ + }, { + .desc = "Capture height", + .name = "crop_height", + .internal_id = PVR2_CID_CROPH, + .default_value = 480, + DEFREF(croph), + DEFINT(32, 576), + .get_max_value = ctrl_vres_max_get, },{ .desc = "Video Source", .name = "input", @@ -2092,6 +2188,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, valid_std_mask; } + memset(&hdw->cropcap, 0, sizeof hdw->cropcap); hdw->eeprom_addr = -1; hdw->unit_number = -1; hdw->v4l_minor_number_video = -1; @@ -2528,6 +2625,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) /* Can't commit anything until pathway is ok. */ return 0; } + /* The broadcast decoder can only scale down, so if + * res_*_dirty && crop window < output format ==> enlarge crop. + * + * The mpeg encoder receives fields of res_hor_val dots and + * res_ver_val halflines. Limits: hor<=720, ver<=576. + */ + if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) { + hdw->cropw_val = hdw->res_hor_val; + hdw->cropw_dirty = !0; + } else if (hdw->cropw_dirty) { + hdw->res_hor_dirty = !0; /* must rescale */ + hdw->res_hor_val = min(720, hdw->cropw_val); + } + if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) { + hdw->croph_val = hdw->res_ver_val; + hdw->croph_dirty = !0; + } else if (hdw->croph_dirty) { + int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576; + hdw->res_ver_dirty = !0; + hdw->res_ver_val = min(nvres, hdw->croph_val); + } + /* If any of the below has changed, then we can't do the update while the pipeline is running. Pipeline must be paused first and decoder -> encoder connection be made quiescent before we diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index c04956d304a..b4dcda8af64 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -36,6 +36,10 @@ #define PVR2_CID_FREQUENCY 6 #define PVR2_CID_HRES 7 #define PVR2_CID_VRES 8 +#define PVR2_CID_CROPL 9 +#define PVR2_CID_CROPT 10 +#define PVR2_CID_CROPW 11 +#define PVR2_CID_CROPH 12 /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index ccdb429fc7a..94a47718e88 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -37,8 +37,9 @@ #define OP_VOLUME 3 #define OP_FREQ 4 #define OP_AUDIORATE 5 -#define OP_SIZE 6 -#define OP_LOG 7 +#define OP_CROP 6 +#define OP_SIZE 7 +#define OP_LOG 8 static const struct pvr2_i2c_op * const ops[] = { [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, @@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = { [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, + [OP_CROP] = &pvr2_i2c_op_v4l2_crop, [OP_SIZE] = &pvr2_i2c_op_v4l2_size, [OP_LOG] = &pvr2_i2c_op_v4l2_log, }; @@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) (1 << OP_BCSH) | (1 << OP_VOLUME) | (1 << OP_FREQ) | + (1 << OP_CROP) | (1 << OP_SIZE) | (1 << OP_LOG)); cp->status_poll = pvr2_v4l2_cmd_status_poll; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 55f04a0b204..440857902c9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -233,6 +233,55 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { }; +static void set_crop(struct pvr2_hdw *hdw) +{ + struct v4l2_cropcap cap; + struct v4l2_crop crop; + int stat; + + memset(&cap, 0, sizeof cap); + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + stat = pvr2_i2c_core_cmd(hdw, VIDIOC_CROPCAP, &cap); + hdw->cropcap = cap; + + memset(&crop, 0, sizeof crop); + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cap.defrect; + crop.c.left += hdw->cropl_val; + crop.c.top += hdw->cropt_val; + crop.c.height = hdw->croph_val; + crop.c.width = hdw->cropw_val; + + pvr2_trace(PVR2_TRACE_CHIPS, + "i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d" + " crop=%d:%d:%d:%d", stat, cap.bounds.width, + cap.bounds.height, cap.bounds.left, cap.bounds.top, + crop.c.width, crop.c.height, crop.c.left, crop.c.top); + + if (stat >= 0) { + /* This comment is present purely to keep + checkpatch.pl quiet */ + pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); + } +} + +static int check_crop(struct pvr2_hdw *hdw) +{ + /* The "0 +" stupidity is present only to get checkpatch.pl to + shut up. I _want_ those parantheses present so that the + two lines automatically line up in my editor. I despise + checkpatch.pl. */ + return 0 + (hdw->cropl_dirty || hdw->cropt_dirty || + hdw->cropw_dirty || hdw->croph_dirty); +} + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { + .check = check_crop, + .update = set_crop, + .name = "v4l2_crop", +}; + + static void do_log(struct pvr2_hdw *hdw) { pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 7fa38683b3b..eb744a20610 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; -- GitLab From 755879c66bb820ec27e2e02b22b13d3896583efe Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 31 Aug 2008 20:50:59 -0300 Subject: [PATCH 4047/5416] V4L/DVB (8897): pvrusb2: Mark crop window size change as being disruptive to the encoder Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 68f4315201a..e29a39ffdcc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2657,6 +2657,8 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) hdw->srate_dirty || hdw->res_ver_dirty || hdw->res_hor_dirty || + hdw->cropw_dirty || + hdw->croph_dirty || hdw->input_dirty || (hdw->active_stream_type != hdw->desired_stream_type)); if (disruptive_change && !hdw->state_pipeline_idle) { -- GitLab From 26dd1c57a05f5c6d339d55d5317d47576fd2fbc5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 31 Aug 2008 20:55:03 -0300 Subject: [PATCH 4048/5416] V4L/DVB (8898): pvrusb2: Be able to programmatically retrieve a control's default value The pvrusb2 control mechanism up until now has used a constant int to hold a control's default value. This change makes it possible to retrieve the control's default through some other means, e.g. as a result of a query from lower level software. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-ctrl.c | 10 ++++++++-- drivers/media/video/pvrusb2/pvrusb2-ctrl.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 + drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 8 +++++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 0764fbfffb7..2741c7b0b53 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -134,13 +134,19 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) /* Retrieve control's default value (any type) */ -int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr) +int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) { int ret = 0; if (!cptr) return 0; LOCK_TAKE(cptr->hdw->big_lock); do { if (cptr->info->type == pvr2_ctl_int) { - ret = cptr->info->default_value; + if (cptr->info->get_def_value) { + /* Comment to keep checkpatch.pl quiet */ + ret = cptr->info->get_def_value(cptr, valptr); + } else { + /* Comment to keep checkpatch.pl quiet */ + *valptr = cptr->info->default_value; + } } } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret; diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h index 0371ae6e6e4..794ff90121c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h @@ -49,7 +49,7 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *); int pvr2_ctrl_get_min(struct pvr2_ctrl *); /* Retrieve control's default value (any type) */ -int pvr2_ctrl_get_def(struct pvr2_ctrl *); +int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr); /* Retrieve control's enumeration count (enum only) */ int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 0453244b7fa..8bc9669733d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -82,6 +82,7 @@ struct pvr2_ctl_info { /* Control's implementation */ pvr2_ctlf_get_value get_value; /* Get its value */ + pvr2_ctlf_get_value get_def_value; /* Get its default value */ pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ pvr2_ctlf_set_value set_value; /* Set its value */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 00306faeac0..c53037a2557 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -533,7 +533,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, lmin = pvr2_ctrl_get_min(hcp); lmax = pvr2_ctrl_get_max(hcp); - ldef = pvr2_ctrl_get_def(hcp); + pvr2_ctrl_get_def(hcp, &ldef); if (w == -1) { w = ldef; } else if (w < lmin) { @@ -543,7 +543,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, } lmin = pvr2_ctrl_get_min(vcp); lmax = pvr2_ctrl_get_max(vcp); - ldef = pvr2_ctrl_get_def(vcp); + pvr2_ctrl_get_def(vcp, &ldef); if (h == -1) { h = ldef; } else if (h < lmin) { @@ -604,6 +604,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_QUERYCTRL: { struct pvr2_ctrl *cptr; + int val; struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; ret = 0; if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { @@ -627,7 +628,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, pvr2_ctrl_get_desc(cptr)); strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); vc->flags = pvr2_ctrl_get_v4lflags(cptr); - vc->default_value = pvr2_ctrl_get_def(cptr); + pvr2_ctrl_get_def(cptr, &val); + vc->default_value = val; switch (pvr2_ctrl_get_type(cptr)) { case pvr2_ctl_enum: vc->type = V4L2_CTRL_TYPE_MENU; -- GitLab From 0b7c2c9598e7447ad6a9d157491e6c5459ae56de Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 31 Aug 2008 20:57:54 -0300 Subject: [PATCH 4049/5416] V4L/DVB (8899): pvrusb2: Implement default value retrieval in sysfs interface Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 46a8c39ba03..ac01b11f7b9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -65,6 +65,7 @@ struct pvr2_sysfs_ctl_item { struct device_attribute attr_type; struct device_attribute attr_min; struct device_attribute attr_max; + struct device_attribute attr_def; struct device_attribute attr_enum; struct device_attribute attr_bits; struct device_attribute attr_val; @@ -145,6 +146,24 @@ static ssize_t show_max(struct device *class_dev, return scnprintf(buf, PAGE_SIZE, "%ld\n", val); } +static ssize_t show_def(struct device *class_dev, + struct device_attribute *attr, + char *buf) +{ + struct pvr2_sysfs_ctl_item *cip; + int val; + int ret; + cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); + ret = pvr2_ctrl_get_def(cip->cptr, &val); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d", + cip->chptr, cip->ctl_id, val, ret); + if (ret < 0) { + /* Keep checkpatch.pl quiet */ + return ret; + } + return scnprintf(buf, PAGE_SIZE, "%d\n", val); +} + static ssize_t show_val_norm(struct device *class_dev, struct device_attribute *attr, char *buf) @@ -320,6 +339,10 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_max.attr.mode = S_IRUGO; cip->attr_max.show = show_max; + cip->attr_def.attr.name = "def_val"; + cip->attr_def.attr.mode = S_IRUGO; + cip->attr_def.show = show_def; + cip->attr_val.attr.name = "cur_val"; cip->attr_val.attr.mode = S_IRUGO; @@ -343,6 +366,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_gen[acnt++] = &cip->attr_name.attr; cip->attr_gen[acnt++] = &cip->attr_type.attr; cip->attr_gen[acnt++] = &cip->attr_val.attr; + cip->attr_gen[acnt++] = &cip->attr_def.attr; cip->attr_val.show = show_val_norm; cip->attr_val.store = store_val_norm; if (pvr2_ctrl_has_custom_symbols(cptr)) { -- GitLab From 432907f750b27aa2b41e1bf398e6eb711ead448f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 31 Aug 2008 21:02:20 -0300 Subject: [PATCH 4050/5416] V4L/DVB (8900): pvrusb2: Implement cropping pass through This builds upon the previous pvrusb2 change to more formally implement full cropping support. This enables access from the driver's V4L interface, and enables access to full capabilities from sysfs as well. Note that this is only effective when in analog mode. It also will only work when the underlying digitizer's driver (saa7115 or cx25840 depending on the hardware) also implements the appropriate functions. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../video/pvrusb2/pvrusb2-hdw-internal.h | 5 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 311 +++++++++++++++--- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 9 + .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 37 +-- .../media/video/pvrusb2/pvrusb2-i2c-core.c | 2 + drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 86 +++++ 6 files changed, 383 insertions(+), 67 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 8bc9669733d..de7ee7264be 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -308,6 +308,10 @@ struct pvr2_hdw { struct v4l2_tuner tuner_signal_info; int tuner_signal_stale; + /* Cropping capability info */ + struct v4l2_cropcap cropcap_info; + int cropcap_stale; + /* Video standard handling */ v4l2_std_id std_mask_eeprom; // Hardware supported selections v4l2_std_id std_mask_avail; // Which standards we may select from @@ -320,7 +324,6 @@ struct pvr2_hdw { struct pvr2_ctl_info std_info_cur; struct v4l2_standard *std_defs; const char **std_enum_names; - struct v4l2_cropcap cropcap; // Generated string names, one per actual V4L2 standard const char *std_mask_ptrs[32]; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e29a39ffdcc..9bb59b2de91 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, void *write_data,unsigned int write_len, void *read_data,unsigned int read_len); +static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw); static void trace_stbit(const char *name,int val) @@ -404,70 +405,220 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) { - struct v4l2_cropcap *cap = &cptr->hdw->cropcap; - if (cap->bounds.width > 0) { - /* This statement is present purely to shut up - checkpatch.pl */ - *left = cap->bounds.left - cap->defrect.left; - } else { - /* This statement is present purely to shut up - checkpatch.pl */ - *left = -119; + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; } + *left = cap->bounds.left; return 0; } static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) { - struct v4l2_cropcap *cap = &cptr->hdw->cropcap; - if (cap->bounds.width > 0) { - *left = cap->bounds.left + cap->bounds.width - - cap->defrect.left; - *left += 3; - *left -= cptr->hdw->cropw_val; - } else { + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *left = cap->bounds.left; + if (cap->bounds.width > cptr->hdw->cropw_val) { /* This statement is present purely to shut up checkpatch.pl */ - *left = 340; + *left += cap->bounds.width - cptr->hdw->cropw_val; } return 0; } static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) { - struct v4l2_cropcap *cap = &cptr->hdw->cropcap; - if (cap->bounds.height > 0) { - /* This statement is present purely to shut up - checkpatch.pl */ - *top = cap->bounds.top - cap->defrect.top; - } else { - /* This statement is present purely to shut up - checkpatch.pl */ - *top = -19; + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; } + *top = cap->bounds.top; return 0; } -static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) +static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) { - /* Actual maximum depends on the video standard in effect. */ - if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) { - *vp = 480; - } else { - *vp = 576; + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *top = cap->bounds.top; + if (cap->bounds.height > cptr->hdw->croph_val) { + /* Keep checkpatch.pl quiet */ + *top += cap->bounds.height - cptr->hdw->croph_val; } return 0; } -static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) +static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val) { - struct v4l2_cropcap *cap = &cptr->hdw->cropcap; - if (cap->bounds.height > 0) { - *top = cap->bounds.top + cap->bounds.height - cap->defrect.top; - *top -= cptr->hdw->croph_val; + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = 0; + if (cap->bounds.width > cptr->hdw->cropl_val) { + /* Keep checkpatch.pl quiet */ + *val = cap->bounds.width - cptr->hdw->cropl_val; + } + return 0; +} + +static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = 0; + if (cap->bounds.height > cptr->hdw->cropt_val) { + /* Keep checkpatch.pl quiet */ + *val = cap->bounds.height - cptr->hdw->cropt_val; + } + return 0; +} + +static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->bounds.left; + return 0; +} + +static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->bounds.top; + return 0; +} + +static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->bounds.width; + return 0; +} + +static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->bounds.height; + return 0; +} + +static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->defrect.left; + return 0; +} + +static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->defrect.top; + return 0; +} + +static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->defrect.width; + return 0; +} + +static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->defrect.height; + return 0; +} + +static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->pixelaspect.numerator; + return 0; +} + +static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) +{ + struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; + int stat = pvr2_hdw_check_cropcap(cptr->hdw); + if (stat != 0) { + /* Keep checkpatch.pl quiet */ + return stat; + } + *val = cap->pixelaspect.denominator; + return 0; +} + +static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) +{ + /* Actual maximum depends on the video standard in effect. */ + if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) { + *vp = 480; } else { - ctrl_vres_max_get(cptr, top); - *top -= 32; + *vp = 576; } return 0; } @@ -913,7 +1064,7 @@ static const struct pvr2_ctl_info control_defs[] = { DEFREF(mute), DEFBOOL, }, { - .desc = "Capture left margin", + .desc = "Capture crop left margin", .name = "crop_left", .internal_id = PVR2_CID_CROPL, .default_value = 0, @@ -921,8 +1072,9 @@ static const struct pvr2_ctl_info control_defs[] = { DEFINT(-129, 340), .get_min_value = ctrl_cropl_min_get, .get_max_value = ctrl_cropl_max_get, + .get_def_value = ctrl_get_cropcapdl, }, { - .desc = "Capture top margin", + .desc = "Capture crop top margin", .name = "crop_top", .internal_id = PVR2_CID_CROPT, .default_value = 0, @@ -930,21 +1082,53 @@ static const struct pvr2_ctl_info control_defs[] = { DEFINT(-35, 544), .get_min_value = ctrl_cropt_min_get, .get_max_value = ctrl_cropt_max_get, + .get_def_value = ctrl_get_cropcapdt, }, { - .desc = "Capture width", + .desc = "Capture crop width", .name = "crop_width", .internal_id = PVR2_CID_CROPW, .default_value = 720, DEFREF(cropw), - DEFINT(388, 849), /* determined empirically, any res_hor>=64 */ + .get_max_value = ctrl_cropw_max_get, + .get_def_value = ctrl_get_cropcapdw, }, { - .desc = "Capture height", + .desc = "Capture crop height", .name = "crop_height", .internal_id = PVR2_CID_CROPH, .default_value = 480, DEFREF(croph), - DEFINT(32, 576), - .get_max_value = ctrl_vres_max_get, + .get_max_value = ctrl_croph_max_get, + .get_def_value = ctrl_get_cropcapdh, + }, { + .desc = "Capture capability pixel aspect numerator", + .name = "cropcap_pixel_numerator", + .internal_id = PVR2_CID_CROPCAPPAN, + .get_value = ctrl_get_cropcappan, + }, { + .desc = "Capture capability pixel aspect denominator", + .name = "cropcap_pixel_denominator", + .internal_id = PVR2_CID_CROPCAPPAD, + .get_value = ctrl_get_cropcappad, + }, { + .desc = "Capture capability bounds top", + .name = "cropcap_bounds_top", + .internal_id = PVR2_CID_CROPCAPBT, + .get_value = ctrl_get_cropcapbt, + }, { + .desc = "Capture capability bounds left", + .name = "cropcap_bounds_left", + .internal_id = PVR2_CID_CROPCAPBL, + .get_value = ctrl_get_cropcapbl, + }, { + .desc = "Capture capability bounds width", + .name = "cropcap_bounds_width", + .internal_id = PVR2_CID_CROPCAPBW, + .get_value = ctrl_get_cropcapbw, + }, { + .desc = "Capture capability bounds height", + .name = "cropcap_bounds_height", + .internal_id = PVR2_CID_CROPCAPBH, + .get_value = ctrl_get_cropcapbh, },{ .desc = "Video Source", .name = "input", @@ -2188,7 +2372,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, valid_std_mask; } - memset(&hdw->cropcap, 0, sizeof hdw->cropcap); + hdw->cropcap_stale = !0; hdw->eeprom_addr = -1; hdw->unit_number = -1; hdw->v4l_minor_number_video = -1; @@ -2728,6 +2912,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } hdw->state_pipeline_config = !0; + /* Hardware state may have changed in a way to cause the cropping + capabilities to have changed. So mark it stale, which will + cause a later re-fetch. */ trace_stbit("state_pipeline_config",hdw->state_pipeline_config); return !0; } @@ -2818,6 +3005,36 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) } +static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) +{ + if (!hdw->cropcap_stale) { + /* Keep checkpatch.pl quiet */ + return 0; + } + pvr2_i2c_core_status_poll(hdw); + if (hdw->cropcap_stale) { + /* Keep checkpatch.pl quiet */ + return -EIO; + } + return 0; +} + + +/* Return information about cropping capabilities */ +int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) +{ + int stat = 0; + LOCK_TAKE(hdw->big_lock); + stat = pvr2_hdw_check_cropcap(hdw); + if (!stat) { + /* Keep checkpatch.pl quiet */ + memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); + } + LOCK_GIVE(hdw->big_lock); + return stat; +} + + /* Return information about the tuner */ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index b4dcda8af64..49482d1f2b2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -40,6 +40,12 @@ #define PVR2_CID_CROPT 10 #define PVR2_CID_CROPW 11 #define PVR2_CID_CROPH 12 +#define PVR2_CID_CROPCAPPAN 13 +#define PVR2_CID_CROPCAPPAD 14 +#define PVR2_CID_CROPCAPBL 15 +#define PVR2_CID_CROPCAPBT 16 +#define PVR2_CID_CROPCAPBW 17 +#define PVR2_CID_CROPCAPBH 18 /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 @@ -174,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); /* Return information about the tuner */ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); +/* Return information about cropping capabilities */ +int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *); + /* Query device and see if it thinks it is on a high-speed USB link */ int pvr2_hdw_is_hsm(struct pvr2_hdw *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 440857902c9..543fa30b777 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); } hdw->tuner_signal_stale = !0; + hdw->cropcap_stale = !0; } @@ -235,34 +236,20 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { static void set_crop(struct pvr2_hdw *hdw) { - struct v4l2_cropcap cap; struct v4l2_crop crop; - int stat; - - memset(&cap, 0, sizeof cap); - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - stat = pvr2_i2c_core_cmd(hdw, VIDIOC_CROPCAP, &cap); - hdw->cropcap = cap; memset(&crop, 0, sizeof crop); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c = cap.defrect; - crop.c.left += hdw->cropl_val; - crop.c.top += hdw->cropt_val; + crop.c.left = hdw->cropl_val; + crop.c.top = hdw->cropt_val; crop.c.height = hdw->croph_val; crop.c.width = hdw->cropw_val; pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d" - " crop=%d:%d:%d:%d", stat, cap.bounds.width, - cap.bounds.height, cap.bounds.left, cap.bounds.top, + "i2c v4l2 set_crop crop=%d:%d:%d:%d", crop.c.width, crop.c.height, crop.c.left, crop.c.top); - if (stat >= 0) { - /* This comment is present purely to keep - checkpatch.pl quiet */ - pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); - } + pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); } static int check_crop(struct pvr2_hdw *hdw) @@ -312,7 +299,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) { - pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); + int stat; + struct pvr2_hdw *hdw = cp->hdw; + if (hdw->cropcap_stale) { + hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, + &hdw->cropcap_info); + if (stat == 0) { + /* Check was successful, so the data is no + longer considered stale. */ + hdw->cropcap_stale = 0; + } + } + pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index e600576a6c4..afb53b49b31 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) INIT_LIST_HEAD(&cp->list); cp->client = client; mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; list_add_tail(&cp->list,&hdw->i2c_clients); hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; } while (0); mutex_unlock(&hdw->i2c_list_lock); @@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client) unsigned long amask = 0; int foundfl = 0; mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { if (cp->client == client) { trace_i2c("pvr2_i2c_detach" diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index c53037a2557..f048d80b77e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -755,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, break; } + case VIDIOC_CROPCAP: + { + struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret = -EINVAL; + break; + } + ret = pvr2_hdw_get_cropcap(hdw, cap); + cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ + break; + } + case VIDIOC_G_CROP: + { + struct v4l2_crop *crop = (struct v4l2_crop *)arg; + int val = 0; + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret = -EINVAL; + break; + } + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); + if (ret != 0) { + ret = -EINVAL; + break; + } + crop->c.left = val; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); + if (ret != 0) { + ret = -EINVAL; + break; + } + crop->c.top = val; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); + if (ret != 0) { + ret = -EINVAL; + break; + } + crop->c.width = val; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); + if (ret != 0) { + ret = -EINVAL; + break; + } + crop->c.height = val; + } + case VIDIOC_S_CROP: + { + struct v4l2_crop *crop = (struct v4l2_crop *)arg; + struct v4l2_cropcap cap; + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret = -EINVAL; + break; + } + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), + crop->c.left); + if (ret != 0) { + ret = -EINVAL; + break; + } + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), + crop->c.top); + if (ret != 0) { + ret = -EINVAL; + break; + } + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), + crop->c.width); + if (ret != 0) { + ret = -EINVAL; + break; + } + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), + crop->c.height); + if (ret != 0) { + ret = -EINVAL; + break; + } + } case VIDIOC_LOG_STATUS: { pvr2_hdw_trigger_module_log(hdw); -- GitLab From 0cc118671282044b2a87621e16d7722d5e60cd08 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 31 Aug 2008 21:06:11 -0300 Subject: [PATCH 4051/5416] V4L/DVB (8901): pvrusb2: Disable virtual IR device when not needed. Disable "virtual" IR receiver on for 24xxx devices that have an internal IR blaster. In that case there's another another IR receiver present and to leave the virtual receiver available just causes confusion. This means that 24xxx users will no longer see a phantom IR chip. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../media/video/pvrusb2/pvrusb2-i2c-core.c | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index afb53b49b31..72d615a87c3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -948,22 +948,32 @@ static struct i2c_adapter pvr2_i2c_adap_template = { .client_unregister = pvr2_i2c_detach_inform, }; -static void do_i2c_scan(struct pvr2_hdw *hdw) + +/* Return true if device exists at given address */ +static int do_i2c_probe(struct pvr2_hdw *hdw, int addr) { struct i2c_msg msg[1]; - int i,rc; + int rc; msg[0].addr = 0; msg[0].flags = I2C_M_RD; msg[0].len = 0; msg[0].buf = NULL; - printk("%s: i2c scan beginning\n",hdw->name); + msg[0].addr = addr; + rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg)); + return rc == 1; +} + +static void do_i2c_scan(struct pvr2_hdw *hdw) +{ + int i; + printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name); for (i = 0; i < 128; i++) { - msg[0].addr = i; - rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg)); - if (rc != 1) continue; - printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); + if (do_i2c_probe(hdw, i)) { + printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n", + hdw->name, i); + } } - printk("%s: i2c scan done.\n",hdw->name); + printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); } void pvr2_i2c_core_init(struct pvr2_hdw *hdw) @@ -1008,6 +1018,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) mutex_init(&hdw->i2c_list_lock); hdw->i2c_linked = !0; i2c_add_adapter(&hdw->i2c_adap); + if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { + /* Probe for a different type of IR receiver on this + device. If present, disable the emulated IR receiver. */ + if (do_i2c_probe(hdw, 0x71)) { + pvr2_trace(PVR2_TRACE_INFO, + "Device has newer IR hardware;" + " disabling unneeded virtual IR device"); + hdw->i2c_func[0x18] = NULL; + } + } if (i2c_scan) do_i2c_scan(hdw); } -- GitLab From 2bb87c24d7d5639bff65b41b1306542d6d2bf7d0 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 3 Sep 2008 21:51:59 -0300 Subject: [PATCH 4052/5416] V4L/DVB (8902): pvrusb2: Remove comment lines which refer to checkpatch's behavior Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-ctrl.c | 2 -- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 24 ------------------- .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 8 ++----- .../media/video/pvrusb2/pvrusb2-i2c-core.c | 2 -- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 1 - 5 files changed, 2 insertions(+), 35 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 2741c7b0b53..203f54cd18a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -141,10 +141,8 @@ int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) LOCK_TAKE(cptr->hdw->big_lock); do { if (cptr->info->type == pvr2_ctl_int) { if (cptr->info->get_def_value) { - /* Comment to keep checkpatch.pl quiet */ ret = cptr->info->get_def_value(cptr, valptr); } else { - /* Comment to keep checkpatch.pl quiet */ *valptr = cptr->info->default_value; } } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9bb59b2de91..94265bd3d92 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -408,7 +408,6 @@ static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *left = cap->bounds.left; @@ -420,13 +419,10 @@ static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *left = cap->bounds.left; if (cap->bounds.width > cptr->hdw->cropw_val) { - /* This statement is present purely to shut up - checkpatch.pl */ *left += cap->bounds.width - cptr->hdw->cropw_val; } return 0; @@ -437,7 +433,6 @@ static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *top = cap->bounds.top; @@ -449,12 +444,10 @@ static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *top = cap->bounds.top; if (cap->bounds.height > cptr->hdw->croph_val) { - /* Keep checkpatch.pl quiet */ *top += cap->bounds.height - cptr->hdw->croph_val; } return 0; @@ -465,12 +458,10 @@ static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = 0; if (cap->bounds.width > cptr->hdw->cropl_val) { - /* Keep checkpatch.pl quiet */ *val = cap->bounds.width - cptr->hdw->cropl_val; } return 0; @@ -481,12 +472,10 @@ static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = 0; if (cap->bounds.height > cptr->hdw->cropt_val) { - /* Keep checkpatch.pl quiet */ *val = cap->bounds.height - cptr->hdw->cropt_val; } return 0; @@ -497,7 +486,6 @@ static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->bounds.left; @@ -509,7 +497,6 @@ static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->bounds.top; @@ -521,7 +508,6 @@ static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->bounds.width; @@ -533,7 +519,6 @@ static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->bounds.height; @@ -545,7 +530,6 @@ static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->defrect.left; @@ -557,7 +541,6 @@ static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->defrect.top; @@ -569,7 +552,6 @@ static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->defrect.width; @@ -581,7 +563,6 @@ static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->defrect.height; @@ -593,7 +574,6 @@ static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->pixelaspect.numerator; @@ -605,7 +585,6 @@ static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { - /* Keep checkpatch.pl quiet */ return stat; } *val = cap->pixelaspect.denominator; @@ -3008,12 +2987,10 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) { if (!hdw->cropcap_stale) { - /* Keep checkpatch.pl quiet */ return 0; } pvr2_i2c_core_status_poll(hdw); if (hdw->cropcap_stale) { - /* Keep checkpatch.pl quiet */ return -EIO; } return 0; @@ -3027,7 +3004,6 @@ int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) LOCK_TAKE(hdw->big_lock); stat = pvr2_hdw_check_cropcap(hdw); if (!stat) { - /* Keep checkpatch.pl quiet */ memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); } LOCK_GIVE(hdw->big_lock); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 543fa30b777..16bb11902a5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -254,12 +254,8 @@ static void set_crop(struct pvr2_hdw *hdw) static int check_crop(struct pvr2_hdw *hdw) { - /* The "0 +" stupidity is present only to get checkpatch.pl to - shut up. I _want_ those parantheses present so that the - two lines automatically line up in my editor. I despise - checkpatch.pl. */ - return 0 + (hdw->cropl_dirty || hdw->cropt_dirty || - hdw->cropw_dirty || hdw->croph_dirty); + return (hdw->cropl_dirty || hdw->cropt_dirty || + hdw->cropw_dirty || hdw->croph_dirty); } const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 72d615a87c3..77289a1c8cb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -992,8 +992,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_func[0x18] = i2c_black_hole; } else if (ir_mode[hdw->unit_number] == 1) { if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { - /* This comment is present PURELY to get - checkpatch.pl to STFU. Lovely, eh? */ hdw->i2c_func[0x18] = i2c_24xxx_ir; } } diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index ac01b11f7b9..733680f2131 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -158,7 +158,6 @@ static ssize_t show_def(struct device *class_dev, pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d", cip->chptr, cip->ctl_id, val, ret); if (ret < 0) { - /* Keep checkpatch.pl quiet */ return ret; } return scnprintf(buf, PAGE_SIZE, "%d\n", val); -- GitLab From d45b9b8ab43c8973a9630ac54f4ede6c3e009f9e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 4 Sep 2008 03:33:43 -0300 Subject: [PATCH 4053/5416] V4L/DVB (8906): v4l-dvb: fix assorted sparse warnings Fix sparse warnings. None are serious, but cutting down on these helps find future serious sparse warnings/errors. Redid the av7710.c patch based on a suggestion by Oliver Endriss. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9005-remote.c | 2 +- drivers/media/dvb/dvb-usb/af9005-script.h | 2 +- drivers/media/dvb/dvb-usb/af9005.c | 23 ++++++--------- drivers/media/dvb/frontends/cx24110.h | 15 ++++++---- drivers/media/dvb/frontends/dib7000m.c | 3 +- drivers/media/dvb/frontends/dvb_dummy_fe.c | 4 +-- drivers/media/dvb/frontends/sp887x.c | 3 +- drivers/media/dvb/ttpci/av7110.c | 12 ++++---- drivers/media/video/cpia2/cpia2_core.c | 10 +++---- drivers/media/video/cpia2/cpia2_usb.c | 2 +- drivers/media/video/cx23885/cx23885-417.c | 2 +- drivers/media/video/cx23885/cx23885-vbi.c | 12 +------- drivers/media/video/cx23885/cx23885-video.c | 29 +++++++------------ drivers/media/video/em28xx/em28xx-dvb.c | 2 +- drivers/media/video/em28xx/em28xx-i2c.c | 7 +++-- drivers/media/video/em28xx/em28xx.h | 4 +-- drivers/media/video/gspca/sonixb.c | 2 +- drivers/media/video/gspca/vc032x.c | 1 - .../media/video/ovcamchip/ovcamchip_core.c | 6 ---- .../media/video/ovcamchip/ovcamchip_priv.h | 6 ++++ .../media/video/pvrusb2/pvrusb2-i2c-core.c | 2 +- drivers/media/video/s2255drv.c | 2 +- drivers/media/video/sn9c102/sn9c102_core.c | 20 +++++++++++++ .../media/video/sn9c102/sn9c102_devtable.h | 20 ------------- drivers/media/video/sn9c102/sn9c102_hv7131d.c | 1 + drivers/media/video/sn9c102/sn9c102_hv7131r.c | 1 + drivers/media/video/sn9c102/sn9c102_mi0343.c | 1 + drivers/media/video/sn9c102/sn9c102_mi0360.c | 1 + drivers/media/video/sn9c102/sn9c102_mt9v111.c | 1 + drivers/media/video/sn9c102/sn9c102_ov7630.c | 1 + drivers/media/video/sn9c102/sn9c102_ov7660.c | 1 + drivers/media/video/sn9c102/sn9c102_pas106b.c | 1 + .../media/video/sn9c102/sn9c102_pas202bcb.c | 1 + .../media/video/sn9c102/sn9c102_tas5110c1b.c | 1 + .../media/video/sn9c102/sn9c102_tas5110d.c | 1 + .../media/video/sn9c102/sn9c102_tas5130d1b.c | 1 + drivers/media/video/zoran_device.c | 2 -- drivers/media/video/zoran_device.h | 8 +++++ drivers/media/video/zoran_driver.c | 6 ---- 39 files changed, 108 insertions(+), 111 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c index ff00c0e8f4a..7c596f92676 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c @@ -25,7 +25,7 @@ */ #include "af9005.h" /* debug */ -int dvb_usb_af9005_remote_debug; +static int dvb_usb_af9005_remote_debug; module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); MODULE_PARM_DESC(debug, "enable (1) or disable (0) debug messages." diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h index 6eeaae51b1c..4d69045426d 100644 --- a/drivers/media/dvb/dvb-usb/af9005-script.h +++ b/drivers/media/dvb/dvb-usb/af9005-script.h @@ -14,7 +14,7 @@ typedef struct { u8 val; } RegDesc; -RegDesc script[] = { +static RegDesc script[] = { {0xa180, 0x0, 0x8, 0xa}, {0xa181, 0x0, 0x8, 0xd7}, {0xa182, 0x0, 0x8, 0xa3}, diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index cfe71feefca..ca5a0a4d2a4 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c @@ -35,17 +35,17 @@ module_param_named(led, dvb_usb_af9005_led, bool, 0644); MODULE_PARM_DESC(led, "enable led (default: 1)."); /* eeprom dump */ -int dvb_usb_af9005_dump_eeprom = 0; +static int dvb_usb_af9005_dump_eeprom; module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* remote control decoder */ -int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event, - int *state); -void *rc_keys; -int *rc_keys_size; +static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len, + u32 *event, int *state); +static void *rc_keys; +static int *rc_keys_size; u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; @@ -54,8 +54,8 @@ struct af9005_device_state { int led_state; }; -int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, - u8 * rbuf, u16 rlen, int delay_ms) +static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, + u8 *rbuf, u16 rlen, int delay_ms) { int actlen, ret = -ENOMEM; @@ -98,12 +98,7 @@ int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, return ret; } -int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len) -{ - return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0); -} - -int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, +static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, int readwrite, int type, u8 * values, int len) { struct af9005_device_state *st = d->priv; @@ -765,7 +760,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) return 0; } -int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) +static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) { int i, packets, ret, act_len; diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index 1792adb23c4..fdcceee91f3 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h @@ -33,12 +33,17 @@ struct cx24110_config u8 demod_address; }; -static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) { - int r = 0; - u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)}; +static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) +{ + u8 buf[] = { + (u8)((val >> 24) & 0xff), + (u8)((val >> 16) & 0xff), + (u8)((val >> 8) & 0xff) + }; + if (fe->ops.write) - r = fe->ops.write(fe, buf, 3); - return r; + return fe->ops.write(fe, buf, 3); + return 0; } #if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE)) diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 5f1375e30df..4de0fa9b69a 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -1284,7 +1284,8 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di } EXPORT_SYMBOL(dib7000m_get_i2c_master); -int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) +static int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, + u8 default_addr, struct dib7000m_config cfg[]) { struct dib7000m_state st = { .i2c_adap = i2c }; int k = 0; diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index cb4d8a3b9d8..db8a937cc63 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -132,7 +132,7 @@ error: static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; -struct dvb_frontend* dvb_dummy_fe_qpsk_attach() +struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) { struct dvb_dummy_fe_state* state = NULL; @@ -152,7 +152,7 @@ error: static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; -struct dvb_frontend* dvb_dummy_fe_qam_attach() +struct dvb_frontend *dvb_dummy_fe_qam_attach(void) { struct dvb_dummy_fe_state* state = NULL; diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index 4543609e181..559509ab4da 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -337,7 +337,8 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct sp887x_state* state = fe->demodulator_priv; - int actual_freq, err; + unsigned actual_freq; + int err; u16 val, reg0xc05; if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ && diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 404108f09d7..c7c770c2898 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -381,9 +381,9 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir, irdebi(av7110, DEBISWAB, addr, 0, len); } -static void debiirq(unsigned long data) +static void debiirq(unsigned long cookie) { - struct av7110 *av7110 = (struct av7110 *) data; + struct av7110 *av7110 = (struct av7110 *)cookie; int type = av7110->debitype; int handle = (type >> 8) & 0x1f; unsigned int xfer = 0; @@ -492,9 +492,9 @@ debi_done: } /* irq from av7110 firmware writing the mailbox register in the DPRAM */ -static void gpioirq(unsigned long data) +static void gpioirq(unsigned long cookie) { - struct av7110 *av7110 = (struct av7110 *) data; + struct av7110 *av7110 = (struct av7110 *)cookie; u32 rxbuf, txbuf; int len; @@ -1260,9 +1260,9 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) return status; } -static void vpeirq(unsigned long data) +static void vpeirq(unsigned long cookie) { - struct av7110 *budget = (struct av7110 *) data; + struct av7110 *budget = (struct av7110 *)cookie; u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index af8b9ec8e35..7e791b6923f 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -1537,7 +1537,7 @@ static int config_sensor_500(struct camera_data *cam, * * This sets all user changeable properties to the values in cam->params. *****************************************************************************/ -int set_all_properties(struct camera_data *cam) +static int set_all_properties(struct camera_data *cam) { /** * Don't set target_kb here, it will be set later. @@ -1588,7 +1588,7 @@ void cpia2_save_camera_state(struct camera_data *cam) * get_color_params * *****************************************************************************/ -void get_color_params(struct camera_data *cam) +static void get_color_params(struct camera_data *cam) { cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); @@ -1881,7 +1881,7 @@ void cpia2_set_saturation(struct camera_data *cam, unsigned char value) * wake_system * *****************************************************************************/ -void wake_system(struct camera_data *cam) +static void wake_system(struct camera_data *cam) { cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); } @@ -1892,7 +1892,7 @@ void wake_system(struct camera_data *cam) * * Valid for STV500 sensor only *****************************************************************************/ -void set_lowlight_boost(struct camera_data *cam) +static void set_lowlight_boost(struct camera_data *cam) { struct cpia2_command cmd; @@ -2169,7 +2169,7 @@ void cpia2_dbg_dump_registers(struct camera_data *cam) * * Sets all values to the defaults *****************************************************************************/ -void reset_camera_struct(struct camera_data *cam) +static void reset_camera_struct(struct camera_data *cam) { /*** * The following parameter values are the defaults from the register map. diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index a8a199047cb..73511a54207 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -478,7 +478,7 @@ int cpia2_usb_change_streaming_alternate(struct camera_data *cam, * set_alternate * *****************************************************************************/ -int set_alternate(struct camera_data *cam, unsigned int alt) +static int set_alternate(struct camera_data *cam, unsigned int alt) { int ret = 0; diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 93777d06d0a..e54df8195ec 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -632,7 +632,7 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value) /* ------------------------------------------------------------------ */ /* MPEG encoder API */ -char *cmd_to_str(int cmd) +static char *cmd_to_str(int cmd) { switch (cmd) { case CX2341X_ENC_PING_FW: diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c index 35e61cd112f..5b297f0323b 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/video/cx23885/cx23885-vbi.c @@ -85,18 +85,8 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, return 0; } -int cx23885_stop_vbi_dma(struct cx23885_dev *dev) -{ - /* stop dma */ - cx_clear(VID_A_DMA_CTL, 0x00000022); - - /* disable irqs */ - cx_clear(PCI_INT_MSK, 0x000001); - cx_clear(VID_A_INT_MSK, 0x00000022); - return 0; -} -int cx23885_restart_vbi_queue(struct cx23885_dev *dev, +static int cx23885_restart_vbi_queue(struct cx23885_dev *dev, struct cx23885_dmaqueue *q) { struct cx23885_buffer *buf; diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index d9bef1a54d1..f75ed1c9b71 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -244,7 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { }; static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); -const u32 cx23885_user_ctrls[] = { +static const u32 cx23885_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, @@ -254,14 +254,13 @@ const u32 cx23885_user_ctrls[] = { V4L2_CID_AUDIO_MUTE, 0 }; -EXPORT_SYMBOL(cx23885_user_ctrls); static const u32 *ctrl_classes[] = { cx23885_user_ctrls, NULL }; -void cx23885_video_wakeup(struct cx23885_dev *dev, +static void cx23885_video_wakeup(struct cx23885_dev *dev, struct cx23885_dmaqueue *q, u32 count) { struct cx23885_buffer *buf; @@ -296,7 +295,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, __func__, bc); } -int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) +static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) { dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, @@ -314,7 +313,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) return 0; } -struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, +static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, struct pci_dev *pci, struct video_device *template, char *type) @@ -334,7 +333,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, return vfd; } -int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) +static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) { int i; @@ -351,7 +350,6 @@ int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) *qctrl = cx23885_ctls[i].v; return 0; } -EXPORT_SYMBOL(cx23885_ctrl_query); /* ------------------------------------------------------------------- */ /* resource management */ @@ -402,7 +400,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, mutex_unlock(&dev->lock); } -int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) +static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) { struct v4l2_routing route; memset(&route, 0, sizeof(route)); @@ -422,10 +420,9 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) return 0; } -EXPORT_SYMBOL(cx23885_video_mux); /* ------------------------------------------------------------------ */ -int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, +static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field) { dprintk(1, "%s()\n", __func__); @@ -890,21 +887,19 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) /* ------------------------------------------------------------------ */ /* VIDEO CTRL IOCTLS */ -int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) +static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); return 0; } -EXPORT_SYMBOL(cx23885_get_control); -int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) +static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" " (disabled - no action)\n", __func__); return 0; } -EXPORT_SYMBOL(cx23885_set_control); static void init_controls(struct cx23885_dev *dev) { @@ -1152,7 +1147,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) return 0; } -int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) +static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) { static const char *iname[] = { [CX23885_VMUX_COMPOSITE1] = "Composite1", @@ -1185,7 +1180,6 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) i->std = CX23885_NORMS; return 0; } -EXPORT_SYMBOL(cx23885_enum_input); static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) @@ -1294,7 +1288,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, return 0; } -int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) +static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) { if (unlikely(UNSET == dev->tuner_type)) return -EINVAL; @@ -1313,7 +1307,6 @@ int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) return 0; } -EXPORT_SYMBOL(cx23885_set_freq); static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d2b1a1a5268..ea4f2a97bd2 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -274,7 +274,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) /* ------------------------------------------------------------------ */ -int register_dvb(struct em28xx_dvb *dvb, +static int register_dvb(struct em28xx_dvb *dvb, struct module *module, struct em28xx *dev, struct device *device) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 97853384c94..2989a65f691 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -143,10 +143,11 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; write_timeout -= 5) { - unsigned msg = dev->em28xx_read_reg(dev, 0x5); - if (msg == 0x94) + unsigned reg = dev->em28xx_read_reg(dev, 0x5); + + if (reg == 0x94) return -ENODEV; - else if (msg == 0x84) + else if (reg == 0x84) return 0; msleep(5); } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 9a331074868..d992280613b 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -411,8 +411,8 @@ struct em28xx { /* frame properties */ int width; /* current frame width */ int height; /* current frame height */ - int hscale; /* horizontal scale factor (see datasheet) */ - int vscale; /* vertical scale factor (see datasheet) */ + unsigned hscale; /* horizontal scale factor (see datasheet) */ + unsigned vscale; /* vertical scale factor (see datasheet) */ int interlaced; /* 1=interlace fileds, 0=just top fileds */ unsigned int video_bytesread; /* Number of bytes read */ diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 12b81ae526b..4328ad44c40 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -490,7 +490,7 @@ static const __u8 tas5130_sensor_init[][8] = { {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, }; -struct sensor_data sensor_data[] = { +static struct sensor_data sensor_data[] = { SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index bd4c226c9a0..0c68f433bb9 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -80,7 +80,6 @@ static struct ctrl sd_ctrls[] = { .step = 1, #define FREQ_DEF 1 .default_value = FREQ_DEF, - .default_value = 1, }, .set = sd_setfreq, .get = sd_getfreq, diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 065c2454113..2c4acbf5a4f 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -49,12 +49,6 @@ MODULE_LICENSE("GPL"); #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ -extern struct ovcamchip_ops ov6x20_ops; -extern struct ovcamchip_ops ov6x30_ops; -extern struct ovcamchip_ops ov7x10_ops; -extern struct ovcamchip_ops ov7x20_ops; -extern struct ovcamchip_ops ov76be_ops; - static char *chip_names[NUM_CC_TYPES] = { [CC_UNKNOWN] = "Unknown chip", [CC_OV76BE] = "OV76BE", diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 9afa4fe4772..a05650faedd 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -53,6 +53,12 @@ struct ovcamchip { int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ }; +extern struct ovcamchip_ops ov6x20_ops; +extern struct ovcamchip_ops ov6x30_ops; +extern struct ovcamchip_ops ov7x10_ops; +extern struct ovcamchip_ops ov7x20_ops; +extern struct ovcamchip_ops ov76be_ops; + /* --------------------------------- */ /* I2C I/O */ /* --------------------------------- */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 77289a1c8cb..d6a35401fef 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -827,7 +827,7 @@ static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { unsigned int idx; unsigned long msk,sm; - int spcfl; + bcnt = scnprintf(buf,maxlen," ["); ccnt += bcnt; buf += bcnt; maxlen -= bcnt; sm = 0; diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index b8e10455220..5272926db73 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -491,7 +491,7 @@ static void planar422p_to_yuv_packed(const unsigned char *in, return; } -void s2255_reset_dsppower(struct s2255_dev *dev) +static void s2255_reset_dsppower(struct s2255_dev *dev) { s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); msleep(10); diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 4b76c45c148..20e30bd9364 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -116,6 +116,26 @@ MODULE_PARM_DESC(debug, "\n"); #endif +/* + Add the probe entries to this table. Be sure to add the entry in the right + place, since, on failure, the next probing routine is called according to + the order of the list below, from top to bottom. +*/ +static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = { + &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ + &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ + &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ + &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ + &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ + &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ + &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ + &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ + &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ + &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ + &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ + &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ +}; + /*****************************************************************************/ static u32 diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 90a401dc388..e23734f6d6e 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -140,24 +140,4 @@ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); -/* - Add the above entries to this table. Be sure to add the entry in the right - place, since, on failure, the next probing routine is called according to - the order of the list below, from top to bottom. -*/ -static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ - &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ - &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ - &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ - &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ - &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ - &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ - &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ - &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ -}; - #endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index eaf9ad0dc8a..db243494893 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int hv7131d_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c index 0fc401223cf..4295887ff60 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int hv7131r_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 00b134ca0a3..1f5b09bec89 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int mi0343_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c index f8d81d82e8d..d973fc1973d 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int mi0360_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c index 3b98ac3bbc3..95986eb492e 100644 --- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c +++ b/drivers/media/video/sn9c102/sn9c102_mt9v111.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int mt9v111_init(struct sn9c102_device *cam) diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index e4856fd7798..803712c29f0 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int ov7630_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index 8aae416ba8e..7977795d342 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int ov7660_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 360f2a848bc..81cd969c1b7 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -21,6 +21,7 @@ #include #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int pas106b_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index ca4a1506ed3..2782f94cf6f 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -26,6 +26,7 @@ #include #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int pas202bcb_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index e7d2de2bace..04cdfdde856 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int tas5110c1b_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c index d32fdbccdc5..9372e6f9fcf 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int tas5110d_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 56fb1d575a8..a30bbc4389f 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -20,6 +20,7 @@ ***************************************************************************/ #include "sn9c102_sensor.h" +#include "sn9c102_devtable.h" static int tas5130d1b_init(struct sn9c102_device* cam) diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 2b3ca149337..5d948ff7faf 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -58,8 +58,6 @@ ZR36057_ISR_GIRQ1 | \ ZR36057_ISR_JPEGRepIRQ ) -extern const struct zoran_format zoran_formats[]; - static int lml33dpath; /* default = 0 * 1 will use digital path in capture * mode instead of analog. It can be diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h index 37fa86a3408..74c6c8edb7d 100644 --- a/drivers/media/video/zoran_device.h +++ b/drivers/media/video/zoran_device.h @@ -78,6 +78,14 @@ extern void zoran_set_pci_master(struct zoran *zr, extern void zoran_init_hardware(struct zoran *zr); extern void zr36057_restart(struct zoran *zr); +extern const struct zoran_format zoran_formats[]; + +extern int v4l_nbufs; +extern int v4l_bufsize; +extern int jpg_nbufs; +extern int jpg_bufsize; +extern int pass_through; + /* i2c */ extern int decoder_command(struct zoran *zr, int cmd, diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 4aa1a765626..f0af9b7f8ff 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -194,12 +194,6 @@ const struct zoran_format zoran_formats[] = { // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined -extern int v4l_nbufs; -extern int v4l_bufsize; -extern int jpg_nbufs; -extern int jpg_bufsize; -extern int pass_through; - static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ module_param(lock_norm, int, 0644); MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); -- GitLab From 0be01004ddc0694d8c592fff05ab88dabd45f476 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Sep 2008 07:01:50 -0300 Subject: [PATCH 4054/5416] V4L/DVB (8910): gspca: Add support of image transfer by bulk and minor change. - image transfer by bulk - set the max number of transfer URS's to 4 (was 16) Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 115 +++++++++++++++++++++++------- drivers/media/video/gspca/gspca.h | 5 +- 2 files changed, 91 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ac95c55887d..496d58d479d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -177,6 +177,48 @@ static void isoc_irq(struct urb *urb fill_frame(gspca_dev, urb); } +/* + * bulk message interrupt from the USB device + */ +static void bulk_irq(struct urb *urb +) +{ + struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; + struct gspca_frame *frame; + int j, ret; + + PDEBUG(D_PACK, "bulk irq"); + if (!gspca_dev->streaming) + return; + if (urb->status != 0 && urb->status != -ECONNRESET) { +#ifdef CONFIG_PM + if (!gspca_dev->frozen) +#endif + PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + return; /* disconnection ? */ + } + + /* check the availability of the frame buffer */ + j = gspca_dev->fr_i; + j = gspca_dev->fr_queue[j]; + frame = &gspca_dev->frame[j]; + if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) + != V4L2_BUF_FLAG_QUEUED) { + gspca_dev->last_packet_type = DISCARD_PACKET; + } else { + PDEBUG(D_PACK, "packet l:%d", urb->actual_length); + gspca_dev->sd_desc->pkt_scan(gspca_dev, + frame, + urb->transfer_buffer, + urb->actual_length); + } + /* resubmit the URB */ + urb->status = 0; + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) + PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", ret); +} + /* * add data to the current frame * @@ -374,10 +416,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) } /* - * search an input isochronous endpoint in an alternate setting + * search an input transfer endpoint in an alternate setting */ -static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, - __u8 epaddr) +static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, + __u8 epaddr, + __u8 xfer) { struct usb_host_endpoint *ep; int i, attr; @@ -388,7 +431,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, if (ep->desc.bEndpointAddress == epaddr) { attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (attr == USB_ENDPOINT_XFER_ISOC) + if (attr == xfer) return ep; break; } @@ -397,14 +440,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, } /* - * search an input isochronous endpoint + * search an input (isoc or bulk) endpoint * * The endpoint is defined by the subdriver. * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). * This routine may be called many times when the bandwidth is too small * (the bandwidth is checked on urb submit). */ -static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) +static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) { struct usb_interface *intf; struct usb_host_endpoint *ep; @@ -414,15 +457,19 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) ep = NULL; i = gspca_dev->alt; /* previous alt setting */ while (--i > 0) { /* alt 0 is unusable */ - ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr); + ep = alt_xfer(&intf->altsetting[i], + gspca_dev->cam.epaddr, + gspca_dev->bulk + ? USB_ENDPOINT_XFER_BULK + : USB_ENDPOINT_XFER_ISOC); if (ep) break; } if (ep == NULL) { - err("no ISOC endpoint found"); + err("no transfer endpoint found"); return NULL; } - PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x", + PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { @@ -434,7 +481,7 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) } /* - * create the isochronous URBs + * create the URBs for image transfer */ static int create_urbs(struct gspca_dev *gspca_dev, struct usb_host_endpoint *ep) @@ -447,12 +494,20 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - npkt = ISO_MAX_SIZE / psize; - if (npkt > ISO_MAX_PKT) - npkt = ISO_MAX_PKT; - bsize = psize * npkt; - PDEBUG(D_STREAM, - "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); + if (!gspca_dev->bulk) { + npkt = ISO_MAX_SIZE / psize; + if (npkt > ISO_MAX_PKT) + npkt = ISO_MAX_PKT; + bsize = psize * npkt; + PDEBUG(D_STREAM, + "isoc %d pkts size %d = bsize:%d", + npkt, psize, bsize); + } else { + npkt = 0; + bsize = psize; + PDEBUG(D_STREAM, "bulk bsize:%d", bsize); + } + nurbs = DEF_NURBS; gspca_dev->nurbs = nurbs; for (n = 0; n < nurbs; n++) { @@ -476,17 +531,23 @@ static int create_urbs(struct gspca_dev *gspca_dev, gspca_dev->urb[n] = urb; urb->dev = gspca_dev->dev; urb->context = gspca_dev; - urb->pipe = usb_rcvisocpipe(gspca_dev->dev, - ep->desc.bEndpointAddress); - urb->transfer_flags = URB_ISO_ASAP - | URB_NO_TRANSFER_DMA_MAP; - urb->interval = ep->desc.bInterval; - urb->complete = isoc_irq; - urb->number_of_packets = npkt; urb->transfer_buffer_length = bsize; - for (i = 0; i < npkt; i++) { - urb->iso_frame_desc[i].length = psize; - urb->iso_frame_desc[i].offset = psize * i; + if (npkt != 0) { /* ISOC */ + urb->pipe = usb_rcvisocpipe(gspca_dev->dev, + ep->desc.bEndpointAddress); + urb->transfer_flags = URB_ISO_ASAP + | URB_NO_TRANSFER_DMA_MAP; + urb->interval = ep->desc.bInterval; + urb->complete = isoc_irq; + urb->number_of_packets = npkt; + for (i = 0; i < npkt; i++) { + urb->iso_frame_desc[i].length = psize; + urb->iso_frame_desc[i].offset = psize * i; + } + } else { /* bulk */ + urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, + ep->desc.bEndpointAddress), + urb->complete = bulk_irq; } } return 0; @@ -508,7 +569,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->alt = gspca_dev->nbalt; for (;;) { PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); - ep = get_isoc_ep(gspca_dev); + ep = get_ep(gspca_dev); if (ep == NULL) { ret = -EIO; goto out; diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index c17625cff9b..78a35a88cf9 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -49,8 +49,8 @@ extern int gspca_debug; } while (0) #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ -/* ISOC transfers */ -#define MAX_NURBS 16 /* max number of URBs */ +/* image transfers */ +#define MAX_NURBS 4 /* max number of URBs */ #define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ #define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ @@ -143,6 +143,7 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ + __u8 bulk; /* image transfer by isoc (0) or bulk (1) */ __u8 curr_mode; /* current camera mode */ __u32 pixfmt; /* current mode parameters */ __u16 width; -- GitLab From 4519064c1c7ccdd319d26181bdd12ee2df6e336e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 29 Aug 2008 16:10:21 -0300 Subject: [PATCH 4055/5416] V4L/DVB (8912): cx18: Correct CX23418 PCI configuration settings. cx18: Correct CX23418 PCI configuration settings. The CX23418 doesn't have I/O space registers, so there was no need to try and turn them on (the card ignores the attempt to set the bit anyway). Also removed incorrect config space register setting that was errantly borrowed from ivtv. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3419de9a5a4..3dfceb360b5 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -511,9 +511,9 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, return -EIO; } - /* Check for bus mastering */ + /* Enable bus mastering and memory mapped IO for the CX23418 */ pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, cmd); pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); @@ -525,11 +525,6 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); } - /* This config space value relates to DMA latencies. The - default value 0x8080 is too low however and will lead - to DMA errors. 0xffff is the max value which solves - these problems. */ - pci_write_config_dword(dev, 0x40, 0xffff); CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " "irq: %d, latency: %d, memory: 0x%lx\n", -- GitLab From b1526421eac9a912b2cda7e147f1da2aa31be278 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 30 Aug 2008 16:03:44 -0300 Subject: [PATCH 4056/5416] V4L/DVB (8913): cx18: Create cx18_ specific wrappers for all pci mmio accessesors. cx18: Create cx18_ specific wrappers for all pci mmio accessesors. This is a first step in instrumenting all CX23418 PCI bus IO, to debug problems with accessing the CX23418's PCI memory mapped IO. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/Makefile | 2 +- drivers/media/video/cx18/cx18-audio.c | 5 +- drivers/media/video/cx18/cx18-av-core.c | 12 +- drivers/media/video/cx18/cx18-av-firmware.c | 7 +- drivers/media/video/cx18/cx18-driver.c | 7 +- drivers/media/video/cx18/cx18-driver.h | 43 ------ drivers/media/video/cx18/cx18-dvb.c | 5 +- drivers/media/video/cx18/cx18-firmware.c | 140 ++++++++++--------- drivers/media/video/cx18/cx18-gpio.c | 15 ++- drivers/media/video/cx18/cx18-i2c.c | 47 ++++--- drivers/media/video/cx18/cx18-io.c | 142 ++++++++++++++++++++ drivers/media/video/cx18/cx18-io.h | 69 ++++++++++ drivers/media/video/cx18/cx18-ioctl.c | 5 +- drivers/media/video/cx18/cx18-irq.c | 43 +++--- drivers/media/video/cx18/cx18-mailbox.c | 44 +++--- drivers/media/video/cx18/cx18-queue.c | 2 + drivers/media/video/cx18/cx18-queue.h | 2 + drivers/media/video/cx18/cx18-scb.c | 131 +++++++++--------- drivers/media/video/cx18/cx18-streams.c | 10 +- 19 files changed, 468 insertions(+), 263 deletions(-) create mode 100644 drivers/media/video/cx18/cx18-io.c create mode 100644 drivers/media/video/cx18/cx18-io.h diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index b23d2e26120..f7bf0edf93f 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile @@ -2,7 +2,7 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio. cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \ cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ - cx18-dvb.o + cx18-dvb.o cx18-io.o obj-$(CONFIG_VIDEO_CX18) += cx18.o diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 6d5b94fc708..57beddf0af4 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-i2c.h" #include "cx18-cards.h" #include "cx18-audio.h" @@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx) if (err) return err; - val = read_reg(CX18_AUDIO_ENABLE) & ~0x30; + val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : (audio_input << 4); - write_reg(val | 0xb00, CX18_AUDIO_ENABLE); + cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE); cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); return 0; } diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 3b0a2c45060..d8626e35465 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -22,27 +22,29 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) { - u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); + u32 reg = 0xc40000 + (addr & ~3); u32 mask = 0xff; int shift = (addr & 3) * 8; + u32 x = cx18_read_reg(cx, reg); x = (x & ~(mask << shift)) | ((u32)value << shift); - writel(x, cx->reg_mem + 0xc40000 + (addr & ~3)); + cx18_write_reg(cx, x, reg); return 0; } int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) { - writel(value, cx->reg_mem + 0xc40000 + addr); + cx18_write_reg(cx, value, 0xc40000 + addr); return 0; } u8 cx18_av_read(struct cx18 *cx, u16 addr) { - u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); + u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3)); int shift = (addr & 3) * 8; return (x >> shift) & 0xff; @@ -50,7 +52,7 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr) u32 cx18_av_read4(struct cx18 *cx, u16 addr) { - return readl(cx->reg_mem + 0xc40000 + addr); + return cx18_read_reg(cx, 0xc40000 + addr); } int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index e996a4e3123..0488b629770 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -20,6 +20,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include #define CX18_AUDIO_ENABLE 0xc72014 @@ -119,10 +120,10 @@ int cx18_av_loadfw(struct cx18 *cx) have a name in the spec. */ cx18_av_write4(cx, 0x09CC, 1); - v = read_reg(CX18_AUDIO_ENABLE); - /* If bit 11 is 1 */ + v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); + /* If bit 11 is 1, clear bit 10 */ if (v & 0x800) - write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */ + cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3dfceb360b5..d31e1ec8d14 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-version.h" #include "cx18-cards.h" #include "cx18-i2c.h" @@ -651,7 +652,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, goto free_mem; } cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; - devtype = read_reg(0xC72028); + devtype = cx18_read_reg(cx, 0xC72028); switch (devtype & 0xff000000) { case 0xff000000: CX18_INFO("cx23418 revision %08x (A)\n", devtype); @@ -897,8 +898,8 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_stop_all_captures(cx); /* Interrupts */ - sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); - sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); + cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); + cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); cx18_halt_firmware(cx); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 7bdd2fcdf20..2cfdbe44582 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -457,47 +457,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); /* First-open initialization: load firmware, etc. */ int cx18_init_on_first_open(struct cx18 *cx); -/* This is a PCI post thing, where if the pci register is not read, then - the write doesn't always take effect right away. By reading back the - register any pending PCI writes will be performed (in order), and so - you can be sure that the writes are guaranteed to be done. - - Rarely needed, only in some timing sensitive cases. - Apparently if this is not done some motherboards seem - to kill the firmware and get into the broken state until computer is - rebooted. */ -#define write_sync(val, reg) \ - do { writel(val, reg); readl(reg); } while (0) - -#define read_reg(reg) readl(cx->reg_mem + (reg)) -#define write_reg(val, reg) writel(val, cx->reg_mem + (reg)) -#define write_reg_sync(val, reg) \ - do { write_reg(val, reg); read_reg(reg); } while (0) - -#define read_enc(addr) readl(cx->enc_mem + (u32)(addr)) -#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr)) -#define write_enc_sync(val, addr) \ - do { write_enc(val, addr); read_enc(addr); } while (0) - -#define sw1_irq_enable(val) do { \ - write_reg(val, SW1_INT_STATUS); \ - write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \ -} while (0) - -#define sw1_irq_disable(val) \ - write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI); - -#define sw2_irq_enable(val) do { \ - write_reg(val, SW2_INT_STATUS); \ - write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \ -} while (0) - -#define sw2_irq_disable(val) \ - write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI); - -#define setup_page(addr) do { \ - u32 val = read_reg(0xD000F8) & ~0x1f00; \ - write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \ -} while (0) - #endif /* CX18_DRIVER_H */ diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 1e420a804fc..afc694e7bdb 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -21,6 +21,7 @@ #include "cx18-version.h" #include "cx18-dvb.h" +#include "cx18-io.h" #include "cx18-streams.h" #include "cx18-cards.h" #include "s5h1409.h" @@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: - v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL); + v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL); v |= 0x00400000; /* Serial Mode */ v |= 0x00002000; /* Data Length - Byte */ v |= 0x00010000; /* Error - Polarity */ v |= 0x00020000; /* Error - Passthru */ v |= 0x000c0000; /* Error - Ignore */ - write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); + cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); break; default: diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 78fadd2ada5..51534428cd0 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c @@ -20,6 +20,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-scb.h" #include "cx18-irq.h" #include "cx18-firmware.h" @@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) src = (const u32 *)fw->data; for (i = 0; i < fw->size; i += 4096) { - setup_page(i); + cx18_setup_page(cx, i); for (j = i; j < fw->size && j < i + 4096; j += 4) { /* no need for endianness conversion on the ppc */ - __raw_writel(*src, dst); - if (__raw_readl(dst) != *src) { + cx18_raw_writel(cx, *src, dst); + if (cx18_raw_readl(cx, dst) != *src) { CX18_ERR("Mismatch at offset %x\n", i); release_firmware(fw); return -EIO; @@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) if (offset + seghdr.size > sz) break; for (i = 0; i < seghdr.size; i += 4096) { - setup_page(offset + i); + cx18_setup_page(cx, offset + i); for (j = i; j < seghdr.size && j < i + 4096; j += 4) { /* no need for endianness conversion on the ppc */ - __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j); - if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) { - CX18_ERR("Mismatch at offset %x\n", offset + j); + cx18_raw_writel(cx, src[(offset + j) / 4], + dst + seghdr.addr + j); + if (cx18_raw_readl(cx, dst + seghdr.addr + j) + != src[(offset + j) / 4]) { + CX18_ERR("Mismatch at offset %x\n", + offset + j); release_firmware(fw); return -EIO; } @@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) size = fw->size; release_firmware(fw); /* Clear bit0 for APU to start from 0 */ - write_reg(read_reg(0xc72030) & ~1, 0xc72030); + cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); return size; } void cx18_halt_firmware(struct cx18 *cx) { CX18_DEBUG_INFO("Preparing for firmware halt.\n"); - write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ - write_reg(0x00020002, CX18_ADEC_CONTROL); + cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ + cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL); } void cx18_init_power(struct cx18 *cx, int lowpwr) { /* power-down Spare and AOM PLLs */ /* power-up fast, slow and mpeg PLLs */ - write_reg(0x00000008, CX18_PLL_POWER_DOWN); + cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN); /* ADEC out of sleep */ - write_reg(0x00020000, CX18_ADEC_CONTROL); + cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL); /* The fast clock is at 200/245 MHz */ - write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); - write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); + cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); + cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, + CX18_FAST_CLOCK_PLL_FRAC); - write_reg(2, CX18_FAST_CLOCK_PLL_POST); - write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE); - write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); + cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST); + cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE); + cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); /* set slow clock to 125/120 MHz */ - write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); - write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC); - write_reg(4, CX18_SLOW_CLOCK_PLL_POST); + cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); + cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8, + CX18_SLOW_CLOCK_PLL_FRAC); + cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST); /* mpeg clock pll 54MHz */ - write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT); - write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); - write_reg(8, CX18_MPEG_CLOCK_PLL_POST); + cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); + cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); + cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); /* Defaults */ /* APU = SC or SC/2 = 125/62.5 */ @@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) /* VFC = disabled */ /* USB = disabled */ - write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1); - write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2); + cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004, + CX18_CLOCK_SELECT1); + cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006, + CX18_CLOCK_SELECT2); - write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1); - write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2); + cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1); + cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2); - write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1); - write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2); + cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1); + cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2); } void cx18_init_memory(struct cx18 *cx) { cx18_msleep_timeout(10, 0); - write_reg(0x10000, CX18_DDR_SOFT_RESET); + cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET); cx18_msleep_timeout(10, 0); - write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); + cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); cx18_msleep_timeout(10, 0); - write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH); - write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1); - write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2); + cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH); + cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1); + cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2); cx18_msleep_timeout(10, 0); /* Initialize DQS pad time */ - write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); - write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); + cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); + cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); cx18_msleep_timeout(10, 0); - write_reg(0x20000, CX18_DDR_SOFT_RESET); + cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET); cx18_msleep_timeout(10, 0); /* use power-down mode when idle */ - write_reg(0x00000010, CX18_DDR_POWER_REG); - - write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN); - - write_reg(0x48, CX18_DDR_MB_PER_ROW_7); - write_reg(0xE0000, CX18_DDR_BASE_63_ADDR); - - write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */ - write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */ - write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ - write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */ - write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ - write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */ - write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */ - write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */ - write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */ - write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */ + cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG); + + cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN); + + cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); + cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); + + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */ + cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */ } int cx18_firmware_init(struct cx18 *cx) { /* Allow chip to control CLKRUN */ - write_reg(0x5, CX18_DSP0_INTERRUPT_MASK); + cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); - write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ + cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ cx18_msleep_timeout(1, 0); - sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); - sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); + cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); + cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); /* Only if the processor is not running */ - if (read_reg(CX18_PROC_SOFT_RESET) & 8) { + if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx); - write_enc(0xE51FF004, 0); - write_enc(0xa00000, 4); /* todo: not hardcoded */ - write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */ + cx18_write_enc(cx, 0xE51FF004, 0); + cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */ + /* Start APU */ + cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET); cx18_msleep_timeout(500, 0); sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", @@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx) int retries = 0; /* start the CPU */ - write_reg(0x00080000, CX18_PROC_SOFT_RESET); + cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET); while (retries++ < 50) { /* Loop for max 500mS */ - if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0) + if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) + & 1) == 0) break; cx18_msleep_timeout(10, 0); } @@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx) return -EIO; } /* initialize GPIO */ - write_reg(0x14001400, 0xC78110); + cx18_write_reg(cx, 0x14001400, 0xC78110); return 0; } diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 3d495dba498..3bdffbf7a96 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-cards.h" #include "cx18-gpio.h" #include "tuner-xc2028.h" @@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx) u32 dir = cx->gpio_dir; u32 val = cx->gpio_val; - write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); - write_reg(((dir & 0xffff) << 16) | (val & 0xffff), + cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); + cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff), CX18_REG_GPIO_OUT1); - write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); - write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), + cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2); + cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16), CX18_REG_GPIO_OUT2); } @@ -141,8 +142,10 @@ void cx18_gpio_init(struct cx18 *cx) } CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", - read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), - read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); + cx18_read_reg(cx, CX18_REG_GPIO_DIR1), + cx18_read_reg(cx, CX18_REG_GPIO_DIR2), + cx18_read_reg(cx, CX18_REG_GPIO_OUT1), + cx18_read_reg(cx, CX18_REG_GPIO_OUT2)); gpio_write(cx); mutex_unlock(&cx->gpio_lock); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 7d8fb25baae..aa09e557b19 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-cards.h" #include "cx18-gpio.h" #include "cx18-av-core.h" @@ -156,12 +157,12 @@ static void cx18_setscl(void *data, int state) struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; - u32 r = read_reg(addr); + u32 r = cx18_read_reg(cx, addr); if (state) - write_reg_sync(r | SETSCL_BIT, addr); + cx18_write_reg_sync(cx, r | SETSCL_BIT, addr); else - write_reg_sync(r & ~SETSCL_BIT, addr); + cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr); } static void cx18_setsda(void *data, int state) @@ -169,12 +170,12 @@ static void cx18_setsda(void *data, int state) struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; - u32 r = read_reg(addr); + u32 r = cx18_read_reg(cx, addr); if (state) - write_reg_sync(r | SETSDL_BIT, addr); + cx18_write_reg_sync(cx, r | SETSDL_BIT, addr); else - write_reg_sync(r & ~SETSDL_BIT, addr); + cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr); } static int cx18_getscl(void *data) @@ -183,7 +184,7 @@ static int cx18_getscl(void *data) int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; - return read_reg(addr) & GETSCL_BIT; + return cx18_read_reg(cx, addr) & GETSCL_BIT; } static int cx18_getsda(void *data) @@ -192,7 +193,7 @@ static int cx18_getsda(void *data) int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; - return read_reg(addr) & GETSDL_BIT; + return cx18_read_reg(cx, addr) & GETSDL_BIT; } /* template for i2c-bit-algo */ @@ -392,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx) cx->i2c_adap[i].dev.parent = &cx->dev->dev; } - if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) { + if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) { /* Reset/Unreset I2C hardware block */ - write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */ - write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */ + /* Clock select 220MHz */ + cx18_write_reg(cx, 0x10000000, 0xc71004); + /* Clock Enable */ + cx18_write_reg_sync(cx, 0x10001000, 0xc71024); } /* courtesy of Steven Toth */ - write_reg_sync(0x00c00000, 0xc7001c); + cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); mdelay(10); - write_reg_sync(0x00c000c0, 0xc7001c); + cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c); mdelay(10); - write_reg_sync(0x00c00000, 0xc7001c); + cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); mdelay(10); - write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */ - write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */ + /* Set to edge-triggered intrs. */ + cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8); + /* Clear any stale intrs */ + cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4); /* Hw I2C1 Clock Freq ~100kHz */ - write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR); + cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR); cx18_setscl(&cx->i2c_algo_cb_data[0], 1); cx18_setsda(&cx->i2c_algo_cb_data[0], 1); /* Hw I2C2 Clock Freq ~100kHz */ - write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR); + cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR); cx18_setscl(&cx->i2c_algo_cb_data[1], 1); cx18_setsda(&cx->i2c_algo_cb_data[1], 1); @@ -428,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx) { int i; CX18_DEBUG_I2C("i2c exit\n"); - write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR); - write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR); + cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4, + CX18_REG_I2C_1_WR); + cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4, + CX18_REG_I2C_2_WR); for (i = 0; i < 2; i++) { i2c_del_adapter(&cx->i2c_adap[i]); diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c new file mode 100644 index 00000000000..c53d9b6e5e4 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.c @@ -0,0 +1,142 @@ +/* + * cx18 driver PCI memory mapped IO access routines + * + * Copyright (C) 2007 Hans Verkuil + * Copyright (C) 2008 Andy Walls + * + * 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 "cx18-driver.h" +#include "cx18-irq.h" + +void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + __raw_writel(val, addr); +} + +u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) +{ + return __raw_readl(addr); +} + +u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) +{ + writel(val, addr); + return readl(addr); +} + +void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + writel(val, addr); +} + +u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) +{ + return readl(addr); +} + + +/* Access "register" region of CX23418 memory mapped I/O */ +u32 cx18_read_reg(struct cx18 *cx, u32 reg) +{ + return readl(cx->reg_mem + reg); +} + +void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) +{ + writel(val, cx->reg_mem + reg); +} + +u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) +{ + return cx18_write_sync(cx, val, cx->reg_mem + reg); +} + +/* Access "encoder memory" region of CX23418 memory mapped I/O */ +u32 cx18_read_enc(struct cx18 *cx, u32 addr) +{ + return readl(cx->enc_mem + addr); +} + +void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) +{ + writel(val, cx->enc_mem + addr); +} + +u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) +{ + return cx18_write_sync(cx, val, cx->enc_mem + addr); +} + +void cx18_memcpy_fromio(struct cx18 *cx, void *to, + const void __iomem *from, unsigned int len) +{ + memcpy_fromio(to, from, len); +} + +void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) +{ + memset_io(addr, val, count); +} + +void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) +{ + u32 r; + cx18_write_reg(cx, val, SW1_INT_STATUS); + r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); + cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); +} + +void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) +{ + u32 r; + r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); + cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI); +} + +void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) +{ + u32 r; + cx18_write_reg(cx, val, SW2_INT_STATUS); + r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); + cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); +} + +void cx18_sw2_irq_disable(struct cx18 *cx, u32 val) +{ + u32 r; + r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); + cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI); +} + +void cx18_setup_page(struct cx18 *cx, u32 addr) +{ + u32 val; + val = cx18_read_reg(cx, 0xD000F8); + val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00); + cx18_write_reg(cx, val, 0xD000F8); +} + +/* Tries to recover from the CX23418 responding improperly on the PCI bus */ +int cx18_pci_try_recover(struct cx18 *cx) +{ + u16 status; + + pci_read_config_word(cx->dev, PCI_STATUS, &status); + pci_write_config_word(cx->dev, PCI_STATUS, status); + return 0; +} diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h new file mode 100644 index 00000000000..7c08c0add49 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.h @@ -0,0 +1,69 @@ +/* + * cx18 driver PCI memory mapped IO access routines + * + * Copyright (C) 2007 Hans Verkuil + * Copyright (C) 2008 Andy Walls + * + * 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 + */ + +#ifndef CX18_IO_H +#define CX18_IO_H + +#include "cx18-driver.h" + +/* This is a PCI post thing, where if the pci register is not read, then + the write doesn't always take effect right away. By reading back the + register any pending PCI writes will be performed (in order), and so + you can be sure that the writes are guaranteed to be done. + + Rarely needed, only in some timing sensitive cases. + Apparently if this is not done some motherboards seem + to kill the firmware and get into the broken state until computer is + rebooted. */ +u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr); + +void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr); +u32 cx18_readl(struct cx18 *cx, const void __iomem *addr); + +/* No endiannes conversion calls */ +void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr); +u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr); + +/* Access "register" region of CX23418 memory mapped I/O */ +u32 cx18_read_reg(struct cx18 *cx, u32 reg); +void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg); +u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg); + +/* Access "encoder memory" region of CX23418 memory mapped I/O */ +u32 cx18_read_enc(struct cx18 *cx, u32 addr); +void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr); +u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr); + +void cx18_memcpy_fromio(struct cx18 *cx, void *to, + const void __iomem *from, unsigned int len); +void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); + +void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); +void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); +void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); +void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); +void cx18_setup_page(struct cx18 *cx, u32 addr); + +/* Tries to recover from the CX23418 responding improperly on the PCI bus */ +int cx18_pci_try_recover(struct cx18 *cx); + +#endif /* CX18_IO_H */ diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 84507a39f2b..8b26b3fefb1 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-version.h" #include "cx18-mailbox.h" #include "cx18-i2c.h" @@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) spin_lock_irqsave(&cx18_cards_lock, flags); if (cmd == VIDIOC_DBG_G_REGISTER) - regs->val = read_enc(regs->reg); + regs->val = cx18_read_enc(cx, regs->reg); else - write_enc(regs->val, regs->reg); + cx18_write_enc(cx, regs->val, regs->reg); spin_unlock_irqrestore(&cx18_cards_lock, flags); return 0; } diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index ab218315c84..55a50a2b048 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -20,6 +20,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-firmware.h" #include "cx18-fileops.h" #include "cx18-queue.h" @@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) if (mb->args[2] != 1) CX18_WARN("Ack struct = %d for %s\n", mb->args[2], s->name); - id = read_enc(off); - buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4)); + id = cx18_read_enc(cx, off); + buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4)); CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); if (buf) { cx18_buf_sync_for_cpu(s, buf); @@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); } else { CX18_WARN("Could not find buf %d for stream %s\n", - read_enc(off), s->name); + cx18_read_enc(cx, off), s->name); } mb->error = 0; mb->cmd = 0; @@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) char *p; if (mb->args[1]) { - setup_page(mb->args[1]); - memcpy_fromio(str, cx->enc_mem + mb->args[1], 252); + cx18_setup_page(cx, mb->args[1]); + cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252); str[252] = 0; } cx18_mb_ack(cx, mb); @@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) struct cx18_mailbox mb; if (sw1 & IRQ_CPU_TO_EPU) { - memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb)); + cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb)); mb.error = 0; switch (mb.cmd) { @@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) spin_lock(&cx->dma_reg_lock); - hw2_mask = read_reg(HW2_INT_MASK5_PCI); - hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask; - sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; - sw2 = read_reg(SW2_INT_STATUS) & sw2_mask; - sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; - sw1 = read_reg(SW1_INT_STATUS) & sw1_mask; + hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); + hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; + sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; + sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; + sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; + sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; - write_reg(sw2&sw2_mask, SW2_INT_STATUS); - write_reg(sw1&sw1_mask, SW1_INT_STATUS); - write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS); + cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); + cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); + cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); if (sw1 || sw2 || hw2) CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); @@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) */ if (sw2) { - if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | - readl(&cx->scb->cpu2epu_irq_ack))) + if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | + cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) wake_up(&cx->mb_cpu_waitq); - if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | - readl(&cx->scb->apu2epu_irq_ack))) + if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | + cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) wake_up(&cx->mb_apu_waitq); - if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) + if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) wake_up(&cx->mb_epu_waitq); - if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) + if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) wake_up(&cx->mb_hpu_waitq); } diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 1b9fbf9a6bc..9d18dd22de7 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -22,6 +22,7 @@ #include #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-scb.h" #include "cx18-irq.h" #include "cx18-mailbox.h" @@ -106,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu switch (rpu) { case APU: mb = &cx->scb->epu2apu_mb; - *state = readl(&cx->scb->apu_state); - *irq = readl(&cx->scb->epu2apu_irq); + *state = cx18_readl(cx, &cx->scb->apu_state); + *irq = cx18_readl(cx, &cx->scb->epu2apu_irq); break; case CPU: mb = &cx->scb->epu2cpu_mb; - *state = readl(&cx->scb->cpu_state); - *irq = readl(&cx->scb->epu2cpu_irq); + *state = cx18_readl(cx, &cx->scb->cpu_state); + *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq); break; case HPU: mb = &cx->scb->epu2hpu_mb; - *state = readl(&cx->scb->hpu_state); - *irq = readl(&cx->scb->epu2hpu_irq); + *state = cx18_readl(cx, &cx->scb->hpu_state); + *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq); break; } @@ -127,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu return mb; do { - *req = readl(&mb->request); - ack = readl(&mb->ack); + *req = cx18_readl(cx, &mb->request); + ack = cx18_readl(cx, &mb->ack); wait_count++; } while (*req != ack && wait_count < 600); @@ -173,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) return -EINVAL; } - setup_page(SCB_OFFSET); - write_sync(mb->request, &ack_mb->ack); - write_reg(ack_irq, SW2_INT_SET); + cx18_setup_page(cx, SCB_OFFSET); + cx18_write_sync(cx, mb->request, &ack_mb->ack); + cx18_write_reg(cx, ack_irq, SW2_INT_SET); return 0; } @@ -200,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) CX18_DEBUG_HI_API("%s\n", info->name); else CX18_DEBUG_API("%s\n", info->name); - setup_page(SCB_OFFSET); + cx18_setup_page(cx, SCB_OFFSET); mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); if (mb == NULL) { @@ -209,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) } oldreq = req - 1; - writel(cmd, &mb->cmd); + cx18_writel(cx, cmd, &mb->cmd); for (i = 0; i < args; i++) - writel(data[i], &mb->args[i]); - writel(0, &mb->error); - writel(req, &mb->request); + cx18_writel(cx, data[i], &mb->args[i]); + cx18_writel(cx, 0, &mb->error); + cx18_writel(cx, req, &mb->request); switch (info->rpu) { case APU: waitq = &cx->mb_apu_waitq; break; @@ -224,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) } if (info->flags & API_FAST) timeout /= 2; - write_reg(irq, SW1_INT_SET); + cx18_write_reg(cx, irq, SW1_INT_SET); - while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) { + while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) + && cnt < 660) { if (cnt > 200 && !in_atomic()) sig = cx18_msleep_timeout(10, 1); cnt++; @@ -234,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) if (sig) return -EINTR; if (cnt == 660) { - writel(oldreq, &mb->request); + cx18_writel(cx, oldreq, &mb->request); CX18_ERR("mb %s failed\n", info->name); return -EINVAL; } for (i = 0; i < MAX_MB_ARGUMENTS; i++) - data[i] = readl(&mb->args[i]); - err = readl(&mb->error); + data[i] = cx18_readl(cx, &mb->args[i]); + err = cx18_readl(cx, &mb->error); if (!in_atomic() && (info->flags & API_SLOW)) cx18_msleep_timeout(300, 0); if (err) diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index a33ba04a268..48976833e23 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -170,6 +170,7 @@ int cx18_stream_alloc(struct cx18_stream *s) } buf->id = cx->buffer_id++; INIT_LIST_HEAD(&buf->list); + /* FIXME - check for mmio */ buf->dma_handle = pci_map_single(s->cx->dev, buf->buf, s->buf_size, s->dma); cx18_buf_sync_for_cpu(s, buf); @@ -193,6 +194,7 @@ void cx18_stream_free(struct cx18_stream *s) /* empty q_free */ while ((buf = cx18_dequeue(s, &s->q_free))) { + /* FIXME - check for mmio */ pci_unmap_single(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); kfree(buf->buf); diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 7f93bb13c09..0c7df932d17 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -28,6 +28,7 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, struct cx18_buffer *buf) { + /* FIXME check IO transfers */ pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); } @@ -35,6 +36,7 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, static inline void cx18_buf_sync_for_device(struct cx18_stream *s, struct cx18_buffer *buf) { + /* FIXME check IO transfers */ pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); } diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c index 30bc803e30d..f56d3772aa6 100644 --- a/drivers/media/video/cx18/cx18-scb.c +++ b/drivers/media/video/cx18/cx18-scb.c @@ -20,102 +20,103 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-scb.h" void cx18_init_scb(struct cx18 *cx) { - setup_page(SCB_OFFSET); - memset_io(cx->scb, 0, 0x10000); + cx18_setup_page(cx, SCB_OFFSET); + cx18_memset_io(cx, cx->scb, 0, 0x10000); - writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); - writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); - writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); - writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); - writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); - writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); - writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); - writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); + cx18_writel(cx, IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); + cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); + cx18_writel(cx, IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); + cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); + cx18_writel(cx, IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); + cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); + cx18_writel(cx, IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); + cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); - writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); - writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); - writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); - writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); - writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); - writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); - writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); - writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); + cx18_writel(cx, IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); + cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); + cx18_writel(cx, IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); + cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); + cx18_writel(cx, IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); + cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); + cx18_writel(cx, IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); + cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); - writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); - writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); - writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); - writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); - writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); - writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); - writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); - writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); + cx18_writel(cx, IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); + cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); + cx18_writel(cx, IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); + cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); + cx18_writel(cx, IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); + cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); + cx18_writel(cx, IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); + cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); - writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); - writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); - writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); - writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); - writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); - writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); - writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); - writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); + cx18_writel(cx, IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); + cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); + cx18_writel(cx, IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); + cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); + cx18_writel(cx, IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); + cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); + cx18_writel(cx, IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); + cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); - writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); - writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); - writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); - writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); - writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); - writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); - writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); - writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); + cx18_writel(cx, IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); + cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); + cx18_writel(cx, IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); + cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); + cx18_writel(cx, IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); + cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); + cx18_writel(cx, IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); + cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); - writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), &cx->scb->apu2cpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), &cx->scb->hpu2cpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), &cx->scb->ppu2cpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), &cx->scb->epu2cpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), &cx->scb->cpu2apu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), &cx->scb->hpu2apu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), &cx->scb->ppu2apu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), &cx->scb->epu2apu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), &cx->scb->cpu2hpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), &cx->scb->apu2hpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), &cx->scb->ppu2hpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), &cx->scb->epu2hpu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), &cx->scb->cpu2ppu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), &cx->scb->apu2ppu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), &cx->scb->hpu2ppu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), &cx->scb->epu2ppu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), &cx->scb->cpu2epu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), &cx->scb->apu2epu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), &cx->scb->hpu2epu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), &cx->scb->ppu2epu_mb_offset); - writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), + cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), &cx->scb->ipc_offset); - writel(1, &cx->scb->hpu_state); - writel(1, &cx->scb->epu_state); + cx18_writel(cx, 1, &cx->scb->hpu_state); + cx18_writel(cx, 1, &cx->scb->epu_state); } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 4d5b446895c..c752a6a4dbd 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -22,6 +22,7 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-fileops.h" #include "cx18-mailbox.h" #include "cx18-i2c.h" @@ -469,7 +470,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) if (atomic_read(&cx->tot_capturing) == 0) { clear_bit(CX18_F_I_EOS, &cx->i_flags); - write_reg(7, CX18_DSP0_INTERRUPT_MASK); + cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK); } cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, @@ -479,8 +480,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) list_for_each(p, &s->q_free.list) { struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); - writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); - writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); + cx18_writel(cx, buf->dma_handle, + &cx->scb->cpu_mdl[buf->id].paddr); + cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1, buf->id, s->buf_size); @@ -563,7 +565,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) if (atomic_read(&cx->tot_capturing) > 0) return 0; - write_reg(5, CX18_DSP0_INTERRUPT_MASK); + cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); wake_up(&s->waitq); return 0; -- GitLab From c641d09c60bfa36c7cf70444f24265090e51f5ce Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 1 Sep 2008 00:40:41 -0300 Subject: [PATCH 4057/5416] V4L/DVB (8914): cx18: Throttle mmio to/from the CX23418 so boards work in older systems cx18: Throttle mmio to/from the CX23418 so boards work in older systems. The CX23418 couldn't reliably handle mmio at the rate at which the cx18 driver was attempting to access the chip. The PCI bridge arrangements and settings on modern motherboards still allowed the CX23418 to work OK, but it didn't work well on many older motherboards: mysterious I2C errors, firmware loading errors, etc. This patch adds a throttle to *all* mmio access to the CX23418. It defaults to a delay of 31 ns, but is adjustable by the mmio_ndelay module parm. My HVR-1600 and Raptor PAL/SECAM card now function for analog capture on a motherboard with an Intel 82810E Northbridge and 82801AA Southbridge. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 18 +++- drivers/media/video/cx18/cx18-driver.h | 4 + drivers/media/video/cx18/cx18-io.c | 115 ++++++++++++------------- drivers/media/video/cx18/cx18-io.h | 115 ++++++++++++++++++++----- drivers/media/video/cx18/cx18-queue.c | 2 - drivers/media/video/cx18/cx18-queue.h | 2 - 6 files changed, 168 insertions(+), 88 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index d31e1ec8d14..202b2819014 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -4,6 +4,7 @@ * Derived from ivtv-driver.c * * Copyright (C) 2007 Hans Verkuil + * Copyright (C) 2008 Andy Walls * * 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 @@ -74,10 +75,14 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - +static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; static unsigned cardtype_c = 1; static unsigned tuner_c = 1; static unsigned radio_c = 1; +static int mmio_ndelay_c = 1; static char pal[] = "--"; static char secam[] = "--"; static char ntsc[] = "-"; @@ -96,6 +101,7 @@ int cx18_debug; module_param_array(tuner, int, &tuner_c, 0644); module_param_array(radio, bool, &radio_c, 0644); module_param_array(cardtype, int, &cardtype_c, 0644); +module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644); module_param_string(pal, pal, sizeof(pal), 0644); module_param_string(secam, secam, sizeof(secam), 0644); module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); @@ -141,6 +147,11 @@ MODULE_PARM_DESC(debug, MODULE_PARM_DESC(cx18_pci_latency, "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" "\t\t\tDefault: Yes"); +MODULE_PARM_DESC(mmio_ndelay, + "Delay (ns) for each CX23418 memory mapped IO access.\n" + "\t\t\tTry larger values that are close to a multiple of the\n" + "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY)); MODULE_PARM_DESC(enc_mpg_buffers, "Encoder MPG Buffers (in MB)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); @@ -357,6 +368,11 @@ static void cx18_process_options(struct cx18 *cx) cx->options.tuner = tuner[cx->num]; cx->options.radio = radio[cx->num]; + if (mmio_ndelay[cx->num] < 0) + cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY; + else + cx->options.mmio_ndelay = mmio_ndelay[cx->num]; + cx->std = cx18_parse_std(cx); if (cx->options.cardtype == -1) { CX18_INFO("Ignore card\n"); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 2cfdbe44582..cc6f288a6da 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -63,6 +63,9 @@ # error "This driver requires kernel PCI support." #endif +/* Default delay to throttle mmio access to the CX23418 so it doesn't choke */ +#define CX18_DEFAULT_MMIO_NDELAY 31 /* 30.3 ns = 1 PCI clock(s) / 33 MHz */ + #define CX18_MEM_OFFSET 0x00000000 #define CX18_MEM_SIZE 0x04000000 #define CX18_REG_OFFSET 0x02000000 @@ -176,6 +179,7 @@ struct cx18_options { int cardtype; /* force card type on load */ int tuner; /* set tuner on load */ int radio; /* enable/disable radio */ + unsigned long mmio_ndelay; /* delay in ns after every PCI mmio access */ }; /* per-buffer bit flags */ diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index c53d9b6e5e4..d92f627d35e 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -21,76 +21,69 @@ */ #include "cx18-driver.h" +#include "cx18-io.h" #include "cx18-irq.h" -void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) -{ - __raw_writel(val, addr); -} - -u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) -{ - return __raw_readl(addr); -} - -u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) -{ - writel(val, addr); - return readl(addr); -} - -void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) -{ - writel(val, addr); -} - -u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) -{ - return readl(addr); -} - - -/* Access "register" region of CX23418 memory mapped I/O */ -u32 cx18_read_reg(struct cx18 *cx, u32 reg) -{ - return readl(cx->reg_mem + reg); -} - -void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) -{ - writel(val, cx->reg_mem + reg); -} - -u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) -{ - return cx18_write_sync(cx, val, cx->reg_mem + reg); -} - -/* Access "encoder memory" region of CX23418 memory mapped I/O */ -u32 cx18_read_enc(struct cx18 *cx, u32 addr) -{ - return readl(cx->enc_mem + addr); -} - -void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) -{ - writel(val, cx->enc_mem + addr); -} - -u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) -{ - return cx18_write_sync(cx, val, cx->enc_mem + addr); -} - void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len) { - memcpy_fromio(to, from, len); + /* Align reads on the CX23418's addresses */ + if ((len > 0) && ((unsigned)from & 1)) { + *((u8 *)to) = cx18_readb(cx, from); + len--; + to++; + from++; + } + if ((len > 1) && ((unsigned)from & 2)) { + *((u16 *)to) = cx18_raw_readw(cx, from); + len -= 2; + to += 2; + from += 2; + } + while (len > 3) { + *((u32 *)to) = cx18_raw_readl(cx, from); + len -= 4; + to += 4; + from += 4; + } + if (len > 1) { + *((u16 *)to) = cx18_raw_readw(cx, from); + len -= 2; + to += 2; + from += 2; + } + if (len > 0) + *((u8 *)to) = cx18_readb(cx, from); } void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) { - memset_io(addr, val, count); + u16 val2 = val | (val << 8); + u32 val4 = val2 | (val2 << 16); + + /* Align writes on the CX23418's addresses */ + if ((count > 0) && ((unsigned)addr & 1)) { + cx18_writeb(cx, (u8) val, addr); + count--; + addr++; + } + if ((count > 1) && ((unsigned)addr & 2)) { + cx18_writew(cx, val2, addr); + count -= 2; + addr += 2; + } + while (count > 3) { + cx18_writel(cx, val4, addr); + count -= 4; + addr += 4; + } + if (count > 1) { + cx18_writew(cx, val2, addr); + count -= 2; + addr += 2; + } + if (count > 0) + cx18_writeb(cx, (u8) val, addr); } void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 7c08c0add49..7ab7be2531c 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h @@ -25,38 +25,109 @@ #include "cx18-driver.h" -/* This is a PCI post thing, where if the pci register is not read, then - the write doesn't always take effect right away. By reading back the - register any pending PCI writes will be performed (in order), and so - you can be sure that the writes are guaranteed to be done. +static inline void cx18_io_delay(struct cx18 *cx) +{ + if (cx->options.mmio_ndelay) + ndelay(cx->options.mmio_ndelay); +} - Rarely needed, only in some timing sensitive cases. - Apparently if this is not done some motherboards seem - to kill the firmware and get into the broken state until computer is - rebooted. */ -u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr); +/* Non byteswapping memory mapped IO */ +static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + __raw_writel(val, addr); + cx18_io_delay(cx); +} -void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr); -u32 cx18_readl(struct cx18 *cx, const void __iomem *addr); +static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) +{ + u32 ret = __raw_readl(addr); + cx18_io_delay(cx); + return ret; +} -/* No endiannes conversion calls */ -void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr); -u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr); +static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) +{ + u16 ret = __raw_readw(addr); + cx18_io_delay(cx); + return ret; +} -/* Access "register" region of CX23418 memory mapped I/O */ -u32 cx18_read_reg(struct cx18 *cx, u32 reg); -void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg); -u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg); +/* Normal memory mapped IO */ +static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + writel(val, addr); + cx18_io_delay(cx); +} -/* Access "encoder memory" region of CX23418 memory mapped I/O */ -u32 cx18_read_enc(struct cx18 *cx, u32 addr); -void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr); -u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr); +static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) +{ + writew(val, addr); + cx18_io_delay(cx); +} + +static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) +{ + writeb(val, addr); + cx18_io_delay(cx); +} + +static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) +{ + u32 ret = readl(addr); + cx18_io_delay(cx); + return ret; +} + +static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) +{ + u8 ret = readb(addr); + cx18_io_delay(cx); + return ret; +} + +static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) +{ + cx18_writel(cx, val, addr); + return cx18_readl(cx, addr); +} void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len); void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); +/* Access "register" region of CX23418 memory mapped I/O */ +static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) +{ + cx18_writel(cx, val, cx->reg_mem + reg); +} + +static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) +{ + return cx18_readl(cx, cx->reg_mem + reg); +} + +static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) +{ + return cx18_write_sync(cx, val, cx->reg_mem + reg); +} + +/* Access "encoder memory" region of CX23418 memory mapped I/O */ +static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) +{ + cx18_writel(cx, val, cx->enc_mem + addr); +} + +static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) +{ + return cx18_readl(cx, cx->enc_mem + addr); +} + +static inline u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) +{ + return cx18_write_sync(cx, val, cx->enc_mem + addr); +} + + void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 48976833e23..a33ba04a268 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -170,7 +170,6 @@ int cx18_stream_alloc(struct cx18_stream *s) } buf->id = cx->buffer_id++; INIT_LIST_HEAD(&buf->list); - /* FIXME - check for mmio */ buf->dma_handle = pci_map_single(s->cx->dev, buf->buf, s->buf_size, s->dma); cx18_buf_sync_for_cpu(s, buf); @@ -194,7 +193,6 @@ void cx18_stream_free(struct cx18_stream *s) /* empty q_free */ while ((buf = cx18_dequeue(s, &s->q_free))) { - /* FIXME - check for mmio */ pci_unmap_single(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); kfree(buf->buf); diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 0c7df932d17..7f93bb13c09 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -28,7 +28,6 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, struct cx18_buffer *buf) { - /* FIXME check IO transfers */ pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); } @@ -36,7 +35,6 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, static inline void cx18_buf_sync_for_device(struct cx18_stream *s, struct cx18_buffer *buf) { - /* FIXME check IO transfers */ pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle, s->buf_size, s->dma); } -- GitLab From ac2b97b13e5627127b8e29dc0e1e1d7be03eaae4 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 4 Sep 2008 13:16:40 -0300 Subject: [PATCH 4058/5416] V4L/DVB (8915): cx18: Increment u8 pointers not void pointers. cx18: Increment u8 pointers not void pointers. Incrementing void pointers is dubious and the real intent in cx18_memcpy_fromio() and cx18_memset_io() is to increment by bytes, so use u8 pointers instead. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-io.c | 56 ++++++++++++++++-------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index d92f627d35e..5d07b0fd8a1 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -27,63 +27,67 @@ void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len) { + const u8 *src = from; + u8 *dst = to; + /* Align reads on the CX23418's addresses */ - if ((len > 0) && ((unsigned)from & 1)) { - *((u8 *)to) = cx18_readb(cx, from); + if ((len > 0) && ((unsigned long) src & 1)) { + *dst = cx18_readb(cx, src); len--; - to++; - from++; + dst++; + src++; } - if ((len > 1) && ((unsigned)from & 2)) { - *((u16 *)to) = cx18_raw_readw(cx, from); + if ((len > 1) && ((unsigned long) src & 2)) { + *((u16 *)dst) = cx18_raw_readw(cx, src); len -= 2; - to += 2; - from += 2; + dst += 2; + src += 2; } while (len > 3) { - *((u32 *)to) = cx18_raw_readl(cx, from); + *((u32 *)dst) = cx18_raw_readl(cx, src); len -= 4; - to += 4; - from += 4; + dst += 4; + src += 4; } if (len > 1) { - *((u16 *)to) = cx18_raw_readw(cx, from); + *((u16 *)dst) = cx18_raw_readw(cx, src); len -= 2; - to += 2; - from += 2; + dst += 2; + src += 2; } if (len > 0) - *((u8 *)to) = cx18_readb(cx, from); + *dst = cx18_readb(cx, src); } void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) { + u8 *dst = addr; u16 val2 = val | (val << 8); u32 val4 = val2 | (val2 << 16); /* Align writes on the CX23418's addresses */ - if ((count > 0) && ((unsigned)addr & 1)) { - cx18_writeb(cx, (u8) val, addr); + if ((count > 0) && ((unsigned long)dst & 1)) { + cx18_writeb(cx, (u8) val, dst); count--; - addr++; + dst++; } - if ((count > 1) && ((unsigned)addr & 2)) { - cx18_writew(cx, val2, addr); + if ((count > 1) && ((unsigned long)dst & 2)) { + cx18_writew(cx, val2, dst); count -= 2; - addr += 2; + dst += 2; } while (count > 3) { - cx18_writel(cx, val4, addr); + cx18_writel(cx, val4, dst); count -= 4; - addr += 4; + dst += 4; } if (count > 1) { - cx18_writew(cx, val2, addr); + cx18_writew(cx, val2, dst); count -= 2; - addr += 2; + dst += 2; } if (count > 0) - cx18_writeb(cx, (u8) val, addr); + cx18_writeb(cx, (u8) val, dst); } void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) -- GitLab From 9afb7377ef16a73d1ae7b089aa853e00a3facea8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 06:34:44 -0300 Subject: [PATCH 4059/5416] V4L/DVB (8917): saa7134-empress: fix changing the capture standard for non-tuner inputs When changing the standard the saa6752hs was not updated unless the input was the TV tuner. The saa6752hs should be updated regardless of the input. In addition the S_STD and G_STD ioctls for the mpeg video device didn't do anything. This is now fixed: they behave just like S_STD and G_STD on the video0 device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-empress.c | 25 +++++++---- drivers/media/video/saa7134/saa7134-i2c.c | 10 +++++ drivers/media/video/saa7134/saa7134-video.c | 42 +++++++++++++++---- drivers/media/video/saa7134/saa7134.h | 3 ++ 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 946edf64dc2..9a8766a78a0 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -303,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv, return videobuf_streamoff(&dev->empress_tsq); } -static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, - unsigned int cmd, void *arg) -{ - if (dev->mpeg_i2c_client == NULL) - return -EINVAL; - return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, - cmd, arg); -} - static int empress_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { @@ -431,6 +422,20 @@ static int empress_g_chip_ident(struct file *file, void *fh, return -EINVAL; } +static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_dev *dev = file->private_data; + + return saa7134_s_std_internal(dev, NULL, id); +} + +static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_dev *dev = file->private_data; + + *id = dev->tvnorm->id; + return 0; +} static const struct file_operations ts_fops = { @@ -465,6 +470,8 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_g_ctrl = empress_g_ctrl, .vidioc_s_ctrl = empress_s_ctrl, .vidioc_g_chip_ident = empress_g_chip_ident, + .vidioc_s_std = empress_s_std, + .vidioc_g_std = empress_g_std, }; /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 5f713e63768..b02965c5247 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -427,6 +427,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, i2c_clients_command(&dev->i2c_adap, cmd, arg); } +int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, + unsigned int cmd, void *arg) +{ + if (dev->mpeg_i2c_client == NULL) + return -EINVAL; + return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, + cmd, arg); +} +EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752); + int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 8fd31138f9a..9aafd584419 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) if (card_in(dev, dev->ctl_input).tv) saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); + /* Set the correct norm for the saa6752hs. This function + does nothing if there is no saa6752hs. */ + saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id); } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) @@ -1796,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void *priv, return 0; } -static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) +int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id) { - struct saa7134_fh *fh = priv; - struct saa7134_dev *dev = fh->dev; unsigned long flags; unsigned int i; v4l2_std_id fixup; int err; - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + /* When called from the empress code fh == NULL. + That needs to be fixed somehow, but for now this is + good enough. */ + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } else if (res_locked(dev, RESOURCE_OVERLAY)) { + /* Don't change the std from the mpeg device + if overlay is active. */ + return -EBUSY; + } for (i = 0; i < TVNORMS; i++) if (*id == tvnorms[i].id) @@ -1840,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) *id = tvnorms[i].id; mutex_lock(&dev->lock); - if (res_check(fh, RESOURCE_OVERLAY)) { + if (fh && res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock, flags); stop_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); @@ -1857,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) mutex_unlock(&dev->lock); return 0; } +EXPORT_SYMBOL_GPL(saa7134_s_std_internal); + +static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_fh *fh = priv; + + return saa7134_s_std_internal(fh->dev, fh, id); +} + +static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; + + *id = dev->tvnorm->id; + return 0; +} static int saa7134_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap) @@ -2397,6 +2424,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_qbuf = saa7134_qbuf, .vidioc_dqbuf = saa7134_dqbuf, .vidioc_s_std = saa7134_s_std, + .vidioc_g_std = saa7134_g_std, .vidioc_enum_input = saa7134_enum_input, .vidioc_g_input = saa7134_g_input, .vidioc_s_input = saa7134_s_input, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a1e0dad1267..5e7fc731fab 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -662,6 +662,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev); int saa7134_i2c_unregister(struct saa7134_dev *dev); void saa7134_i2c_call_clients(struct saa7134_dev *dev, unsigned int cmd, void *arg); +int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, + unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ @@ -674,6 +676,7 @@ extern struct video_device saa7134_radio_template; int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); +int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id); int saa7134_videoport_init(struct saa7134_dev *dev); void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); -- GitLab From ff5f26b40ab43a6c263834665bfa10d6114a27cd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 07:00:24 -0300 Subject: [PATCH 4060/5416] V4L/DVB (8918): saa6752hs: simplify writing to registers Add some utility functions to set registers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 127 +++++++++--------------- 1 file changed, 49 insertions(+), 78 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index f40cb0b479b..1fb6eccdade 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -224,7 +224,7 @@ static struct saa6752hs_mpeg_params param_defaults = /* ---------------------------------------------------------------------- */ -static int saa6752hs_chip_command(struct i2c_client* client, +static int saa6752hs_chip_command(struct i2c_client *client, enum saa6752hs_command command) { unsigned char buf[3]; @@ -291,54 +291,61 @@ static int saa6752hs_chip_command(struct i2c_client* client, } -static int saa6752hs_set_bitrate(struct i2c_client* client, +static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val) +{ + u8 buf[2]; + + buf[0] = reg; + buf[1] = val; + i2c_master_send(client, buf, 2); +} + +static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val) +{ + u8 buf[3]; + + buf[0] = reg; + buf[1] = val >> 8; + buf[2] = val & 0xff; + i2c_master_send(client, buf, 3); +} + +static int saa6752hs_set_bitrate(struct i2c_client *client, struct saa6752hs_state *h) { struct saa6752hs_mpeg_params *params = &h->params; - u8 buf[3]; int tot_bitrate; + int is_384k; /* set the bitrate mode */ - buf[0] = 0x71; - buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x71, + params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); /* set the video bitrate */ if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { /* set the target bitrate */ - buf[0] = 0x80; - buf[1] = params->vi_bitrate >> 8; - buf[2] = params->vi_bitrate & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x80, params->vi_bitrate); /* set the max bitrate */ - buf[0] = 0x81; - buf[1] = params->vi_bitrate_peak >> 8; - buf[2] = params->vi_bitrate_peak & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x81, params->vi_bitrate_peak); tot_bitrate = params->vi_bitrate_peak; } else { /* set the target bitrate (no max bitrate for CBR) */ - buf[0] = 0x81; - buf[1] = params->vi_bitrate >> 8; - buf[2] = params->vi_bitrate & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x81, params->vi_bitrate); tot_bitrate = params->vi_bitrate; } /* set the audio encoding */ - buf[0] = 0x93; - buf[1] = (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); - i2c_master_send(client, buf, 2); + set_reg8(client, 0x93, + params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); /* set the audio bitrate */ - buf[0] = 0x94; if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) - buf[1] = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; + is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; else - buf[1] = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; - tot_bitrate += buf[1] ? 384 : 256; - i2c_master_send(client, buf, 2); + is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; + set_reg8(client, 0x94, is_384k); + tot_bitrate += is_384k ? 384 : 256; /* Note: the total max bitrate is determined by adding the video and audio bitrates together and also adding an extra 768kbit/s to stay on the @@ -349,16 +356,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; /* set the total bitrate */ - buf[0] = 0xb1; - buf[1] = tot_bitrate >> 8; - buf[2] = tot_bitrate & 0xff; - i2c_master_send(client, buf, 3); - + set_reg16(client, 0xb1, tot_bitrate); return 0; } -static void saa6752hs_set_subsampling(struct i2c_client* client, - struct v4l2_format* f) +static void saa6752hs_set_subsampling(struct i2c_client *client, + struct v4l2_format *f) { struct saa6752hs_state *h = i2c_get_clientdata(client); int dist_352, dist_480, dist_720; @@ -665,51 +668,31 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) h = i2c_get_clientdata(client); /* Set video format - must be done first as it resets other settings */ - buf[0] = 0x41; - buf[1] = h->video_format; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x41, h->video_format); /* Set number of lines in input signal */ - buf[0] = 0x40; - buf[1] = 0x00; - if (h->standard & V4L2_STD_525_60) - buf[1] = 0x01; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0); /* set bitrate */ saa6752hs_set_bitrate(client, h); /* Set GOP structure {3, 13} */ - buf[0] = 0x72; - buf[1] = 0x03; - buf[2] = 0x0D; - i2c_master_send(client,buf,3); + set_reg16(client, 0x72, 0x030d); /* Set minimum Q-scale {4} */ - buf[0] = 0x82; - buf[1] = 0x04; - i2c_master_send(client,buf,2); + set_reg8(client, 0x82, 0x04); /* Set maximum Q-scale {12} */ - buf[0] = 0x83; - buf[1] = 0x0C; - i2c_master_send(client,buf,2); + set_reg8(client, 0x83, 0x0c); /* Set Output Protocol */ - buf[0] = 0xD0; - buf[1] = 0x81; - i2c_master_send(client,buf,2); + set_reg8(client, 0xd0, 0x81); /* Set video output stream format {TS} */ - buf[0] = 0xB0; - buf[1] = 0x05; - i2c_master_send(client,buf,2); + set_reg8(client, 0xb0, 0x05); /* Set leading null byte for TS */ - buf[0] = 0xF6; - buf[1] = (leading_null_bytes >> 8) & 0xff; - buf[2] = leading_null_bytes & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0xf6, leading_null_bytes); /* compute PAT */ memcpy(localPAT, PAT, sizeof(PAT)); @@ -744,33 +727,21 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) localPMT[size - 1] = crc & 0xFF; /* Set Audio PID */ - buf[0] = 0xC1; - buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; - buf[2] = h->params.ts_pid_audio & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc1, h->params.ts_pid_audio); /* Set Video PID */ - buf[0] = 0xC0; - buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; - buf[2] = h->params.ts_pid_video & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc0, h->params.ts_pid_video); /* Set PCR PID */ - buf[0] = 0xC4; - buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; - buf[2] = h->params.ts_pid_pcr & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc4, h->params.ts_pid_pcr); /* Send SI tables */ i2c_master_send(client, localPAT, sizeof(PAT)); i2c_master_send(client, localPMT, size); /* mute then unmute audio. This removes buzzing artefacts */ - buf[0] = 0xa4; - buf[1] = 1; - i2c_master_send(client, buf, 2); - buf[1] = 0; - i2c_master_send(client, buf, 2); + set_reg8(client, 0xa4, 1); + set_reg8(client, 0xa4, 0); /* start it going */ saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); -- GitLab From effc3466d32108bec7da19aa23c1fddee9cafbab Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 08:24:37 -0300 Subject: [PATCH 4061/5416] V4L/DVB (8920): cx18/ivtv: fix check of window boundaries for VIDIOC_S_FMT It was possible to set out-of-bounds windows sizes, this is now fixed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 6 +++--- drivers/media/video/ivtv/ivtv-ioctl.c | 29 ++++++++++----------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 8b26b3fefb1..4a47f61d948 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -171,7 +171,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; - int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; @@ -203,8 +202,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; + int w, h; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) @@ -213,6 +211,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, ret = cx18_try_fmt_vid_cap(file, fh, fmt); if (ret) return ret; + w = fmt->fmt.pix.width; + h = fmt->fmt.pix.height; if (cx->params.width == w && cx->params.height == h) return 0; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 61030309d0a..e67bf1b15cf 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -512,27 +512,20 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct ivtv_open_id *id = fh; - s32 w, h; - int field; - int ret; + s32 w = fmt->fmt.pix.width; + s32 h = fmt->fmt.pix.height; + int field = fmt->fmt.pix.field; + int ret = ivtv_g_fmt_vid_out(file, fh, fmt); - w = fmt->fmt.pix.width; - h = fmt->fmt.pix.height; - field = fmt->fmt.pix.field; - ret = ivtv_g_fmt_vid_out(file, fh, fmt); - fmt->fmt.pix.width = w; - fmt->fmt.pix.height = h; if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) { fmt->fmt.pix.field = field; - if (fmt->fmt.pix.width < 2) - fmt->fmt.pix.width = 2; - if (fmt->fmt.pix.width > 720) - fmt->fmt.pix.width = 720; - if (fmt->fmt.pix.height < 2) - fmt->fmt.pix.height = 2; - if (fmt->fmt.pix.height > 576) - fmt->fmt.pix.height = 576; + w = min(w, 720); + w = max(w, 2); + h = min(h, 576); + h = max(h, 2); } + fmt->fmt.pix.width = w; + fmt->fmt.pix.height = h; return ret; } @@ -560,9 +553,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct cx2341x_mpeg_params *p = &itv->params; + int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; - int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); if (ret) return ret; -- GitLab From 854ad9abcc7c1aa143d1a18409d4f366d4326a80 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 09:56:17 -0300 Subject: [PATCH 4062/5416] V4L/DVB (8921): ivtv: fix incorrect capability and assorted sliced vbi and video out fmt fixes - V4L2_CAP_VBI_OUTPUT is not supported by ivtv, remove it. - ivtv_try_fmt_vid_out also needed to constrain the width/height of MPEG decoder window sizes. - allow empty sliced services. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.h | 2 +- drivers/media/video/ivtv/ivtv-ioctl.c | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 381af1bceef..0b8fe85fb69 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -154,7 +154,7 @@ #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ V4L2_CAP_SLICED_VBI_CAPTURE) -#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ +#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) struct ivtv_card_video_input { diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index e67bf1b15cf..f00854ad64e 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } -static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) +static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { int f, l; - u16 set = 0; for (f = 0; f < 2; f++) { for (l = 0; l < 24; l++) { fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); - set |= fmt->service_lines[f][l]; } } - return set != 0; } u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) @@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format int h = fmt->fmt.pix.height; w = min(w, 720); - w = max(w, 1); + w = max(w, 2); h = min(h, itv->is_50hz ? 576 : 480); h = max(h, 2); ivtv_g_fmt_vid_cap(file, fh, fmt); @@ -512,18 +509,18 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct ivtv_open_id *id = fh; + struct ivtv *itv = id->itv; s32 w = fmt->fmt.pix.width; s32 h = fmt->fmt.pix.height; int field = fmt->fmt.pix.field; int ret = ivtv_g_fmt_vid_out(file, fh, fmt); - if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) { + w = min(w, 720); + w = max(w, 2); + h = min(h, itv->is_out_50hz ? 576 : 480); + h = max(h, 2); + if (id->type == IVTV_DEC_STREAM_TYPE_YUV) fmt->fmt.pix.field = field; - w = min(w, 720); - w = max(w, 2); - h = min(h, 576); - h = max(h, 2); - } fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; return ret; @@ -593,8 +590,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) return ret; - if (check_service_set(vbifmt, itv->is_50hz) == 0) - return -EINVAL; + check_service_set(vbifmt, itv->is_50hz); if (atomic_read(&itv->capturing) > 0) return -EBUSY; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); -- GitLab From 446f245977e9c2ac4507c3543c7e2a587f46beab Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 6 Sep 2008 16:43:59 -0300 Subject: [PATCH 4063/5416] V4L/DVB (8924): cx18: Set mmio throttling delay default to 0 nsec. cx18: Set mmio throttling delay default to 0 nsec. Not doing so makes analog tuner audio not work on some mahcines. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index cc6f288a6da..66cb748875c 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -63,8 +63,8 @@ # error "This driver requires kernel PCI support." #endif -/* Default delay to throttle mmio access to the CX23418 so it doesn't choke */ -#define CX18_DEFAULT_MMIO_NDELAY 31 /* 30.3 ns = 1 PCI clock(s) / 33 MHz */ +/* Default delay to throttle mmio access to the CX23418 */ +#define CX18_DEFAULT_MMIO_NDELAY 0 /* 0 ns = 0 PCI clock(s) / 33 MHz */ #define CX18_MEM_OFFSET 0x00000000 #define CX18_MEM_SIZE 0x04000000 -- GitLab From d654dca7bca79dd3981267e398b6a7df34d3d047 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 6 Sep 2008 04:18:48 -0300 Subject: [PATCH 4064/5416] V4L/DVB (8927): gspca: PAC 207 webcam 093a:2476 added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/pac207.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 9a3e4d797fa..89fed5c5add 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -181,6 +181,7 @@ pac207 093a:2468 PAC207 pac207 093a:2470 Genius GF112 pac207 093a:2471 Genius VideoCam ge111 pac207 093a:2472 Genius VideoCam ge110 +pac207 093a:2476 Genius e-Messenger 112 pac7311 093a:2600 PAC7311 Typhoon pac7311 093a:2601 Philips SPC 610 NC pac7311 093a:2603 PAC7312 diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 83b5f740c94..34e923d00b7 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -534,6 +534,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2470)}, {USB_DEVICE(0x093a, 0x2471)}, {USB_DEVICE(0x093a, 0x2472)}, + {USB_DEVICE(0x093a, 0x2476)}, {USB_DEVICE(0x2001, 0xf115)}, {} }; -- GitLab From 3371bcc328c7345fe8d69b7a828890b62fb21744 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 6 Sep 2008 04:21:08 -0300 Subject: [PATCH 4065/5416] V4L/DVB (8928): gspca: Version change to 2.3.0. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 496d58d479d..ce5498527fc 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -43,7 +43,7 @@ MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 2, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0) static int video_nr = -1; -- GitLab From 7b537391dde35d7f412417a95f02f89af08dd2d3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 7 Sep 2008 11:56:49 -0300 Subject: [PATCH 4066/5416] V4L/DVB (8929): gspca: sonixj webcam 0458:702e added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/sonixj.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 89fed5c5add..308ce4ee23d 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -42,6 +42,7 @@ zc3xx 0458:7007 Genius VideoCam V2 zc3xx 0458:700c Genius VideoCam V3 zc3xx 0458:700f Genius VideoCam Web V2 sonixj 0458:7025 Genius Eye 311Q +sonixj 0458:702e Genius Slim 310 NB sonixj 045e:00f5 MicroSoft VX3000 sonixj 045e:00f7 MicroSoft VX1000 ov519 045e:028c Micro$oft xbox cam diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 572b0f363b6..cd961cad4f9 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1567,6 +1567,7 @@ static const struct sd_desc sd_desc = { static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, + {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)}, {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, -- GitLab From 51977a8daab6775b91986b566056eb2a2f10202d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Sep 2008 03:22:42 -0300 Subject: [PATCH 4067/5416] V4L/DVB (8930): gspca: The image transfer by bulk is started by the subdrivers. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ce5498527fc..58761d9809f 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -185,7 +185,7 @@ static void bulk_irq(struct urb *urb { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; struct gspca_frame *frame; - int j, ret; + int j; PDEBUG(D_PACK, "bulk irq"); if (!gspca_dev->streaming) @@ -212,11 +212,6 @@ static void bulk_irq(struct urb *urb urb->transfer_buffer, urb->actual_length); } - /* resubmit the URB */ - urb->status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", ret); } /* @@ -502,13 +497,14 @@ static int create_urbs(struct gspca_dev *gspca_dev, PDEBUG(D_STREAM, "isoc %d pkts size %d = bsize:%d", npkt, psize, bsize); + nurbs = DEF_NURBS; } else { npkt = 0; bsize = psize; PDEBUG(D_STREAM, "bulk bsize:%d", bsize); + nurbs = 1; } - nurbs = DEF_NURBS; gspca_dev->nurbs = nurbs; for (n = 0; n < nurbs; n++) { urb = usb_alloc_urb(npkt, GFP_KERNEL); @@ -583,6 +579,10 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; atomic_set(&gspca_dev->nevent, 0); + /* start the bulk transfer is done by the subdriver */ + if (gspca_dev->bulk) + break; + /* submit the URBs */ for (n = 0; n < gspca_dev->nurbs; n++) { ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); -- GitLab From 6c86274fcdf4b3893ee22c1e39ddfb5b05bf0362 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Sep 2008 04:57:26 -0300 Subject: [PATCH 4068/5416] V4L/DVB (8931): gspca: Vflip added for sonixj - ov7630. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 50 +++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index cd961cad4f9..1d6f2ee1eec 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -39,6 +39,7 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + __u8 vflip; /* ov7630 only */ signed char ag_cnt; #define AG_CNT_START 13 @@ -70,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { { @@ -131,6 +134,22 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, +/* ov7630 only */ +#define VFLIP_IDX 4 + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vflip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define VFLIP_DEF 0 + .default_value = VFLIP_DEF, + }, + .set = sd_setvflip, + .get = sd_getvflip, + }, }; static struct v4l2_pix_format vga_mode[] = { @@ -434,7 +453,8 @@ static const __u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, /*fixme: + 0x12, 0x04*/ - {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, +/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN + * set by setvflip */ {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, @@ -949,6 +969,8 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); break; } + if (sd->sensor != SENSOR_OV7630) + gspca_dev->ctrl_dis |= (1 << VFLIP_IDX); return 0; } @@ -1172,6 +1194,14 @@ static void setautogain(struct gspca_dev *gspca_dev) sd->ag_cnt = -1; } +static void setvflip(struct sd *sd) +{ + if (sd->sensor != SENSOR_OV7630) + return; + i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ + sd->vflip ? 0x82 : 0x02); +} + /* -- start the camera -- */ static void sd_start(struct gspca_dev *gspca_dev) { @@ -1263,6 +1293,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_OV7630: ov7630_InitSensor(gspca_dev); + setvflip(sd); reg17 = 0xe2; reg1 = 0x44; break; @@ -1546,6 +1577,23 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->vflip = val; + setvflip(sd); + return 0; +} + +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->vflip; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, -- GitLab From a50f4a444a14a116e2eb077e01c2eaf58ddb7c6a Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 8 Sep 2008 03:23:55 -0300 Subject: [PATCH 4069/5416] V4L/DVB (8936): em28xx-cards: Add vendor/product id for EM2820_BOARD_PROLINK_PLAYTV_USB2 Added vendor/product id for EM2820_BOARD_PROLINK_PLAYTV_USB2 Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 4 ++-- drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 53449cb99b1..187cc48d092 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] @@ -12,7 +12,7 @@ 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] - 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) + 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) [eb1a:2821] 15 -> V-Gear PocketTV (em2800) 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b,2040:651f] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index de943cf6c16..01804fac6aa 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1101,7 +1101,7 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2821), - .driver_info = EM2820_BOARD_UNKNOWN }, + .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 }, { USB_DEVICE(0xeb1a, 0x2860), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2861), -- GitLab From f2a01a0027b29f682c3833d582e2827a4690f661 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 8 Sep 2008 03:27:20 -0300 Subject: [PATCH 4070/5416] V4L/DVB (8937): em28xx: Fix and add some validations Fixed and Added some validations Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-i2c.c | 28 +++++++++++--- drivers/media/video/em28xx/em28xx-video.c | 45 ++++++++++++++++++++--- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2989a65f691..3bab56b997f 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -336,8 +336,11 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) /* Check if board has eeprom */ err = i2c_master_recv(&dev->i2c_client, &buf, 0); - if (err < 0) - return -1; + if (err < 0) { + em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", + __func__, err); + return err; + } buf = 0; @@ -345,7 +348,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) if (err != 1) { printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", dev->name, err); - return -1; + return err; } while (size > 0) { if (size > 16) @@ -358,7 +361,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n", dev->name, err); - return -1; + return err; } size -= block; p += block; @@ -586,18 +589,31 @@ void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) */ int em28xx_i2c_register(struct em28xx *dev) { + int retval; + BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); dev->i2c_adap = em28xx_adap_template; dev->i2c_adap.dev.parent = &dev->udev->dev; strcpy(dev->i2c_adap.name, dev->name); dev->i2c_adap.algo_data = dev; - i2c_add_adapter(&dev->i2c_adap); + + retval = i2c_add_adapter(&dev->i2c_adap); + if (retval < 0) { + em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", + __func__, retval); + return retval; + } dev->i2c_client = em28xx_client_template; dev->i2c_client.adapter = &dev->i2c_adap; - em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); + retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); + if (retval < 0) { + em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", + __func__, retval); + return retval; + } if (i2c_scan) em28xx_do_i2c_scan(dev); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 600b340e355..50d2c7a9b3c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -513,10 +513,17 @@ static struct videobuf_queue_ops em28xx_video_qops = { */ static int em28xx_config(struct em28xx *dev) { + int retval; /* Sets I2C speed to 100 KHz */ - if (!dev->is_em2800) - em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + if (!dev->is_em2800) { + retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + if (retval < 0) { + em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", + __func__, retval); + return retval; + } + } /* enable vbi capturing */ @@ -1953,13 +1960,23 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } /* register i2c bus */ - em28xx_i2c_register(dev); + errCode = em28xx_i2c_register(dev); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", + __func__, errCode); + return errCode; + } /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); /* Configure audio */ - em28xx_audio_analog_set(dev); + errCode = em28xx_audio_analog_set(dev); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n", + __func__, errCode); + return errCode; + } /* configure the device */ em28xx_config_i2c(dev); @@ -1979,6 +1996,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->ctl_input = 2; errCode = em28xx_config(dev); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_config - errCode [%d]!\n", + __func__, errCode); + return errCode; + } list_add_tail(&dev->devlist, &em28xx_devlist); @@ -2031,9 +2053,20 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ - em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); + errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", + __func__, errCode); + return errCode; + } msleep(3); - em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); + + errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", + __func__, errCode); + return errCode; + } msleep(3); } -- GitLab From 2796073a3d9cc4f610f1e68b3f62c197d86577ab Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 14:02:43 -0300 Subject: [PATCH 4071/5416] V4L/DVB (8939): cx18: fix sparse warnings Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 2 +- drivers/media/video/cx18/cx18-io.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 202b2819014..4de7b501f20 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -82,7 +82,7 @@ static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, static unsigned cardtype_c = 1; static unsigned tuner_c = 1; static unsigned radio_c = 1; -static int mmio_ndelay_c = 1; +static unsigned mmio_ndelay_c = 1; static char pal[] = "--"; static char secam[] = "--"; static char ntsc[] = "-"; diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 5d07b0fd8a1..55d1df93292 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -27,7 +27,7 @@ void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len) { - const u8 *src = from; + const u8 __iomem *src = from; u8 *dst = to; /* Align reads on the CX23418's addresses */ @@ -61,7 +61,7 @@ void cx18_memcpy_fromio(struct cx18 *cx, void *to, void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) { - u8 *dst = addr; + u8 __iomem *dst = addr; u16 val2 = val | (val << 8); u32 val4 = val2 | (val2 << 16); -- GitLab From 6bd6dff6318397b1127dd256b65dde007306b8ea Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 15:26:44 -0300 Subject: [PATCH 4072/5416] V4L/DVB (8940): saa7115: fix saa7111(a) support The saa7111 support in saa7115.c was missing some features and did not properly take some of the differences into account. With this patch saa7115 can be used in the mxb driver instead of saa7111.c. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 34 +++++++++++++++++++++++++++++----- include/media/saa7115.h | 19 +++++++++++++------ include/media/v4l2-common.h | 12 ++++++++---- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index ad733caec72..4ed7d65dd63 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1309,10 +1309,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar case VIDIOC_INT_S_VIDEO_ROUTING: { struct v4l2_routing *route = arg; + u32 input = route->input; + u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); - /* saa7113 does not have these inputs */ - if (state->ident == V4L2_IDENT_SAA7113 && + /* saa7111/3 does not have these inputs */ + if ((state->ident == V4L2_IDENT_SAA7113 || + state->ident == V4L2_IDENT_SAA7111) && (route->input == SAA7115_COMPOSITE4 || route->input == SAA7115_COMPOSITE5)) { return -EINVAL; @@ -1327,10 +1330,23 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); state->input = route->input; + /* saa7111 has slightly different input numbering */ + if (state->ident == V4L2_IDENT_SAA7111) { + if (input >= SAA7115_COMPOSITE4) + input -= 2; + /* saa7111 specific */ + saa711x_write(client, R_10_CHROMA_CNTL_2, + (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) | + ((route->output & 0xc0) ^ 0x40)); + saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL, + (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | + ((route->output & 2) ? 0x0a : 0)); + } + /* select mode */ saa711x_write(client, R_02_INPUT_CNTL_1, - (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) | - state->input); + (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) | + input); /* bypass chrominance trap for S-Video modes */ saa711x_write(client, R_09_LUMA_CNTL, @@ -1384,6 +1400,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar saa711x_writeregs(client, saa7115_cfg_reset_scaler); break; + case VIDIOC_INT_S_GPIO: + if (state->ident != V4L2_IDENT_SAA7111) + return -EINVAL; + saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) | + (*(u32 *)arg ? 0x80 : 0)); + break; + case VIDIOC_INT_G_VBI_DATA: { struct v4l2_sliced_vbi_data *data = arg; @@ -1539,7 +1562,8 @@ static int saa7115_probe(struct i2c_client *client, state->crystal_freq = SAA7115_FREQ_32_11_MHZ; saa711x_writeregs(client, saa7115_init_auto_input); } - saa711x_writeregs(client, saa7115_init_misc); + if (state->ident != V4L2_IDENT_SAA7111) + saa711x_writeregs(client, saa7115_init_misc); saa711x_set_v4lstd(client, V4L2_STD_NTSC); v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", diff --git a/include/media/saa7115.h b/include/media/saa7115.h index f677dfb9d37..bab21271959 100644 --- a/include/media/saa7115.h +++ b/include/media/saa7115.h @@ -1,5 +1,5 @@ /* - saa7115.h - definition for saa7113/4/5 inputs and frequency flags + saa7115.h - definition for saa7111/3/4/5 inputs and frequency flags Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) @@ -21,13 +21,13 @@ #ifndef _SAA7115_H_ #define _SAA7115_H_ -/* SAA7113/4/5 HW inputs */ +/* SAA7111/3/4/5 HW inputs */ #define SAA7115_COMPOSITE0 0 #define SAA7115_COMPOSITE1 1 #define SAA7115_COMPOSITE2 2 #define SAA7115_COMPOSITE3 3 -#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */ -#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */ +#define SAA7115_COMPOSITE4 4 /* not available for the saa7111/3 */ +#define SAA7115_COMPOSITE5 5 /* not available for the saa7111/3 */ #define SAA7115_SVIDEO0 6 #define SAA7115_SVIDEO1 7 #define SAA7115_SVIDEO2 8 @@ -42,8 +42,15 @@ #define SAA7115_FREQ_FL_CGCDIV (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */ #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ -#define SAA7115_IPORT_ON 1 -#define SAA7115_IPORT_OFF 0 +#define SAA7115_IPORT_ON 1 +#define SAA7115_IPORT_OFF 0 + +/* SAA7111 specific output flags */ +#define SAA7111_VBI_BYPASS 2 +#define SAA7111_FMT_YUV422 0x00 +#define SAA7111_FMT_RGB 0x40 +#define SAA7111_FMT_CCIR 0x80 +#define SAA7111_FMT_YUV411 0xc0 #endif diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 0c195ccd45d..2f8719abf5c 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -225,18 +225,22 @@ struct v4l2_crystal_freq { An extra flags field allows device specific configuration regarding clock frequency dividers, etc. If not used, then set flags to 0. If the frequency is not supported, then -EINVAL is returned. */ -#define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq) +#define VIDIOC_INT_S_CRYSTAL_FREQ _IOW('d', 113, struct v4l2_crystal_freq) /* Initialize the sensor registors to some sort of reasonable default values. */ -#define VIDIOC_INT_INIT _IOW ('d', 114, u32) +#define VIDIOC_INT_INIT _IOW('d', 114, u32) /* Set v4l2_std_id for video OUTPUT devices. This is ignored by video input devices. */ -#define VIDIOC_INT_S_STD_OUTPUT _IOW ('d', 115, v4l2_std_id) +#define VIDIOC_INT_S_STD_OUTPUT _IOW('d', 115, v4l2_std_id) /* Get v4l2_std_id for video OUTPUT devices. This is ignored by video input devices. */ -#define VIDIOC_INT_G_STD_OUTPUT _IOW ('d', 116, v4l2_std_id) +#define VIDIOC_INT_G_STD_OUTPUT _IOW('d', 116, v4l2_std_id) + +/* Set GPIO pins. Very simple right now, might need to be extended with + a v4l2_gpio struct if a direction is also needed. */ +#define VIDIOC_INT_S_GPIO _IOW('d', 117, u32) #endif /* V4L2_COMMON_H_ */ -- GitLab From 707ecf4603a9439dcf409e13c5e9ed4e164ddfff Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 15:40:25 -0300 Subject: [PATCH 4073/5416] V4L/DVB (8941): mxb/tda9840: cleanups, use module saa7115 instead of saa7111. Cleanup tda9840 and use a v4l2 API to get the tuner subchannels. Do some cleanups in mxb and switch to saa7115 instead of the saa7111 module. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/mxb.c | 213 +++++++++------------------------- drivers/media/video/tda9840.c | 112 +++++++++++------- drivers/media/video/tda9840.h | 21 ---- 4 files changed, 122 insertions(+), 226 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 7f7482bff14..e28e292fe20 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -691,7 +691,7 @@ config VIDEO_MXB depends on PCI && VIDEO_V4L1 && I2C select VIDEO_SAA7146_VV select VIDEO_TUNER - select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 7c9820c72a6..621d1740829 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "mxb.h" #include "tea6415c.h" @@ -122,6 +123,8 @@ static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, + { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE }, + { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE }, { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ { 0, 0 } @@ -154,20 +157,20 @@ static int mxb_check_clients(struct device *dev, void *data) struct mxb* mxb = data; struct i2c_client *client = i2c_verify_client(dev); - if( !client ) + if (!client) return 0; - if( I2C_ADDR_TEA6420_1 == client->addr ) + if (I2C_ADDR_TEA6420_1 == client->addr) mxb->tea6420_1 = client; - if( I2C_ADDR_TEA6420_2 == client->addr ) + if (I2C_ADDR_TEA6420_2 == client->addr) mxb->tea6420_2 = client; - if( I2C_TEA6415C_2 == client->addr ) + if (I2C_TEA6415C_2 == client->addr) mxb->tea6415c = client; - if( I2C_ADDR_TDA9840 == client->addr ) + if (I2C_ADDR_TDA9840 == client->addr) mxb->tda9840 = client; - if( I2C_SAA7111 == client->addr ) + if (I2C_SAA7111 == client->addr) mxb->saa7111a = client; - if( 0x60 == client->addr ) + if (0x60 == client->addr) mxb->tuner = client; return 0; @@ -178,23 +181,28 @@ static int mxb_probe(struct saa7146_dev* dev) struct mxb* mxb = NULL; int result; - if ((result = request_module("saa7111")) < 0) { + result = request_module("saa7115"); + if (result < 0) { printk("mxb: saa7111 i2c module not available.\n"); return -ENODEV; } - if ((result = request_module("tea6420")) < 0) { + result = request_module("tea6420"); + if (result < 0) { printk("mxb: tea6420 i2c module not available.\n"); return -ENODEV; } - if ((result = request_module("tea6415c")) < 0) { + result = request_module("tea6415c"); + if (result < 0) { printk("mxb: tea6415c i2c module not available.\n"); return -ENODEV; } - if ((result = request_module("tda9840")) < 0) { + result = request_module("tda9840"); + if (result < 0) { printk("mxb: tda9840 i2c module not available.\n"); return -ENODEV; } - if ((result = request_module("tuner")) < 0) { + result = request_module("tuner"); + if (result < 0) { printk("mxb: tuner i2c module not available.\n"); return -ENODEV; } @@ -293,37 +301,6 @@ static struct { {-1, { 0} } }; -static const unsigned char mxb_saa7111_init[] = { - 0x00, 0x00, /* 00 - ID byte */ - 0x01, 0x00, /* 01 - reserved */ - - /*front end */ - 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ - 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x00, /* 04 - GAI1=256 */ - 0x05, 0x00, /* 05 - GAI2=256 */ - - /* decoder */ - 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ - 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ - 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ - 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x47, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ - 0x0f, 0x00, /* 0f - reserved */ - 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ - 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ - 0x12, 0x80, /* 12 - xx output control 2 */ - 0x13, 0x30, /* 13 - xx output control 3 */ - 0x14, 0x00, /* 14 - reserved */ - 0x15, 0x15, /* 15 - VBI */ - 0x16, 0x04, /* 16 - VBI */ - 0x17, 0x00, /* 17 - VBI */ -}; - /* bring hardware to a sane state. this has to be done, just in case someone wants to capture from this device before it has been properly initialized. the capture engine would badly fail, because no valid signal arrives on the @@ -331,37 +308,29 @@ static const unsigned char mxb_saa7111_init[] = { static int mxb_init_done(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - struct video_decoder_init init; struct i2c_msg msg; struct tuner_setup tun_setup; v4l2_std_id std = V4L2_STD_PAL_BG; + struct v4l2_routing route; int i = 0, err = 0; struct tea6415c_multiplex vm; /* select video mode in saa7111a */ - i = VIDEO_MODE_PAL; /* fixme: currently pointless: gets overwritten by configuration below */ - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); - - /* write configuration to saa7111a */ - init.data = mxb_saa7111_init; - init.len = sizeof(mxb_saa7111_init); - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init); + mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); /* select tuner-output on saa7111a */ i = 0; - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i); - - /* enable vbi bypass */ - i = 1; - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i); + route.input = SAA7115_COMPOSITE0; + route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; + mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* select a tuner type */ tun_setup.mode_mask = T_ANALOG_TV; tun_setup.addr = ADDR_UNSET; tun_setup.type = TUNER_PHILIPS_PAL; - mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup); + mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup); /* tune in some frequency on tuner */ mxb->cur_freq.tuner = 0; mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; @@ -393,7 +362,6 @@ static int mxb_init_done(struct saa7146_dev* dev) mxb->cur_mute = 1; mxb->cur_mode = V4L2_TUNER_MODE_STEREO; - mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode); /* check if the saa7740 (aka 'sound arena module') is present on the mxb. if so, we must initialize it. due to lack of @@ -626,7 +594,8 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { int input = *(int *)arg; - struct tea6415c_multiplex vm; + struct tea6415c_multiplex vm; + struct v4l2_routing route; int i = 0; DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); @@ -635,19 +604,6 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) return -EINVAL; } - /* fixme: locke das setzen des inputs mit hilfe des mutexes - mutex_lock(&dev->lock); - video_mux(dev,*i); - mutex_unlock(&dev->lock); - */ - - /* fixme: check if streaming capture - if ( 0 != dev->streaming ) { - DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n")); - return -EPERM; - } - */ - mxb->cur_input = input; saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); @@ -658,7 +614,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case TUNER: { - i = 0; + i = SAA7115_COMPOSITE0; vm.in = 3; vm.out = 17; @@ -675,19 +631,19 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { /* nothing to be done here. aux3_yc is directly connected to the saa711a */ - i = 5; + i = SAA7115_SVIDEO1; break; } case AUX3: { /* nothing to be done here. aux3 is directly connected to the saa711a */ - i = 1; + i = SAA7115_COMPOSITE1; break; } case AUX1: { - i = 0; + i = SAA7115_COMPOSITE0; vm.in = 1; vm.out = 17; break; @@ -712,9 +668,10 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) } /* switch video in saa7111a */ - if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { + route.input = i; + route.output = 0; + if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); - } /* switch the audio-source only if necessary */ if( 0 == mxb->cur_mute ) { @@ -727,105 +684,35 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; - int byte = 0; - if( 0 != t->index ) { + if (t->index) { DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); return -EINVAL; } DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); - memset(t,0,sizeof(*t)); + memset(t, 0, sizeof(*t)); + i2c_clients_command(&mxb->i2c_adapter, cmd, arg); - strlcpy(t->name, "Television", sizeof(t->name)); + strlcpy(t->name, "TV Tuner", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ - t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ - /* FIXME: add the real signal strength here */ - t->signal = 0xffff; - t->afc = 0; - mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); + t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \ + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->audmode = mxb->cur_mode; - - if( byte < 0 ) { - t->rxsubchans = V4L2_TUNER_SUB_MONO; - } else { - switch(byte) { - case TDA9840_MONO_DETECT: { - t->rxsubchans = V4L2_TUNER_SUB_MONO; - DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n")); - break; - } - case TDA9840_DUAL_DETECT: { - t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n")); - break; - } - case TDA9840_STEREO_DETECT: { - t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n")); - break; - } - default: { /* TDA9840_INCORRECT_DETECT */ - t->rxsubchans = V4L2_TUNER_MODE_MONO; - DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n")); - break; - } - } - } - return 0; } case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; - int result = 0; - int byte = 0; - if( 0 != t->index ) { + if (t->index) { DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); return -EINVAL; } - switch(t->audmode) { - case V4L2_TUNER_MODE_STEREO: { - mxb->cur_mode = V4L2_TUNER_MODE_STEREO; - byte = TDA9840_SET_STEREO; - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); - break; - } - case V4L2_TUNER_MODE_LANG1_LANG2: { - mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2; - byte = TDA9840_SET_BOTH; - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n")); - break; - } - case V4L2_TUNER_MODE_LANG1: { - mxb->cur_mode = V4L2_TUNER_MODE_LANG1; - byte = TDA9840_SET_LANG1; - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); - break; - } - case V4L2_TUNER_MODE_LANG2: { - mxb->cur_mode = V4L2_TUNER_MODE_LANG2; - byte = TDA9840_SET_LANG2; - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); - break; - } - default: { /* case V4L2_TUNER_MODE_MONO: {*/ - mxb->cur_mode = V4L2_TUNER_MODE_MONO; - byte = TDA9840_SET_MONO; - DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); - break; - } - } - - if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { - printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); - } - + mxb->cur_mode = t->audmode; + i2c_clients_command(&mxb->i2c_adapter, cmd, arg); return 0; } case VIDIOC_G_FREQUENCY: @@ -852,8 +739,8 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; - if(0 != mxb->cur_input) { - DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); + if (mxb->cur_input) { + DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input)); return -EINVAL; } @@ -921,6 +808,10 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); return 0; } + case VIDIOC_DBG_S_REGISTER: + case VIDIOC_DBG_G_REGISTER: + i2c_clients_command(&mxb->i2c_adapter, cmd, arg); + break; default: /* DEB2(printk("does not handle this ioctl.\n")); @@ -943,7 +834,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero); + mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } else { v4l2_std_id std = V4L2_STD_PAL_BG; @@ -952,7 +843,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one); + mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } return 0; diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 57deeb89331..77bfd24ecfa 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -47,6 +47,15 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define STEREO_ADJUST 0x03 #define TEST 0x04 +#define TDA9840_SET_MUTE 0x00 +#define TDA9840_SET_MONO 0x10 +#define TDA9840_SET_STEREO 0x2a +#define TDA9840_SET_LANG1 0x12 +#define TDA9840_SET_LANG2 0x1e +#define TDA9840_SET_BOTH 0x1a +#define TDA9840_SET_BOTH_R 0x16 +#define TDA9840_SET_EXTERNAL 0x7a + /* addresses to scan, found only at 0x42 (7-Bit) */ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; @@ -62,26 +71,74 @@ static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) { - int result; + int result = 0; int byte = *(int *)arg; switch (cmd) { - case TDA9840_SWITCH: + case VIDIOC_S_TUNER: { + struct v4l2_tuner *t = arg; + int byte; + + if (t->index) + return -EINVAL; + + switch (t->audmode) { + case V4L2_TUNER_MODE_STEREO: + byte = TDA9840_SET_STEREO; + break; + case V4L2_TUNER_MODE_LANG1_LANG2: + byte = TDA9840_SET_BOTH; + break; + case V4L2_TUNER_MODE_LANG1: + byte = TDA9840_SET_LANG1; + break; + case V4L2_TUNER_MODE_LANG2: + byte = TDA9840_SET_LANG2; + break; + default: + byte = TDA9840_SET_MONO; + break; + } v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); + tda9840_write(client, SWITCH, byte); + break; + } + + case VIDIOC_G_TUNER: { + struct v4l2_tuner *t = arg; + u8 byte; - if (byte != TDA9840_SET_MONO - && byte != TDA9840_SET_MUTE - && byte != TDA9840_SET_STEREO - && byte != TDA9840_SET_LANG1 - && byte != TDA9840_SET_LANG2 - && byte != TDA9840_SET_BOTH - && byte != TDA9840_SET_BOTH_R - && byte != TDA9840_SET_EXTERNAL) { + t->rxsubchans = V4L2_TUNER_SUB_MONO; + if (1 != i2c_master_recv(client, &byte, 1)) { + v4l_dbg(1, debug, client, + "i2c_master_recv() failed\n"); + return -EIO; + } + + if (byte & 0x80) { + v4l_dbg(1, debug, client, + "TDA9840_DETECT: register contents invalid\n"); return -EINVAL; } - tda9840_write(client, SWITCH, byte); + v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); + + switch (byte & 0x60) { + case 0x00: + t->rxsubchans = V4L2_TUNER_SUB_MONO; + break; + case 0x20: + t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + break; + case 0x40: + t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + break; + default: /* Incorrect detect */ + t->rxsubchans = V4L2_TUNER_MODE_MONO; + break; + } break; + } case TDA9840_LEVEL_ADJUST: v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); @@ -115,36 +172,6 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) tda9840_write(client, STEREO_ADJUST, byte); break; - - case TDA9840_DETECT: { - int *ret = (int *)arg; - - byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST); - if (byte == -1) { - v4l_dbg(1, debug, client, - "i2c_smbus_read_byte_data() failed\n"); - return -EIO; - } - - if (byte & 0x80) { - v4l_dbg(1, debug, client, - "TDA9840_DETECT: register contents invalid\n"); - return -EINVAL; - } - - v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); - *ret = (byte & 0x60) >> 5; - result = 0; - break; - } - case TDA9840_TEST: - v4l_dbg(1, debug, client, "TDA9840_TEST: 0x%02x\n", byte); - - /* mask out irrelevant bits */ - byte &= 0x3; - - tda9840_write(client, TEST, byte); - break; default: return -ENOIOCTLCMD; } @@ -174,8 +201,7 @@ static int tda9840_probe(struct i2c_client *client, byte = 0; result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); - byte = TDA9840_SET_MONO; - result = tda9840_command(client, TDA9840_SWITCH, &byte); + tda9840_write(client, SWITCH, TDA9840_SET_STEREO); if (result) { v4l_dbg(1, debug, client, "could not initialize tda9840\n"); return -ENODEV; diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h index 7da8432cdca..dc12ae7caf6 100644 --- a/drivers/media/video/tda9840.h +++ b/drivers/media/video/tda9840.h @@ -3,24 +3,6 @@ #define I2C_ADDR_TDA9840 0x42 -#define TDA9840_DETECT _IOR('v',1,int) -/* return values for TDA9840_DETCT */ -#define TDA9840_MONO_DETECT 0x0 -#define TDA9840_DUAL_DETECT 0x1 -#define TDA9840_STEREO_DETECT 0x2 -#define TDA9840_INCORRECT_DETECT 0x3 - -#define TDA9840_SWITCH _IOW('v',2,int) -/* modes than can be set with TDA9840_SWITCH */ -#define TDA9840_SET_MUTE 0x00 -#define TDA9840_SET_MONO 0x10 -#define TDA9840_SET_STEREO 0x2a -#define TDA9840_SET_LANG1 0x12 -#define TDA9840_SET_LANG2 0x1e -#define TDA9840_SET_BOTH 0x1a -#define TDA9840_SET_BOTH_R 0x16 -#define TDA9840_SET_EXTERNAL 0x7a - /* values may range between +2.5 and -2.0; the value has to be multiplied with 10 */ #define TDA9840_LEVEL_ADJUST _IOW('v',3,int) @@ -29,7 +11,4 @@ the value has to be multiplied with 10 */ #define TDA9840_STEREO_ADJUST _IOW('v',4,int) -/* currently not implemented */ -#define TDA9840_TEST _IOW('v',5,int) - #endif -- GitLab From 2633812f897cc354071699e86ea82e3bfd77cddc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Sep 2008 17:24:30 -0300 Subject: [PATCH 4074/5416] V4L/DVB (8942): mxb: coding style cleanups Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mxb.c | 252 ++++++++++++++++++-------------------- 1 file changed, 119 insertions(+), 133 deletions(-) diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 621d1740829..b2dae5062e6 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -137,12 +137,12 @@ struct mxb struct i2c_adapter i2c_adapter; - struct i2c_client* saa7111a; - struct i2c_client* tda9840; - struct i2c_client* tea6415c; - struct i2c_client* tuner; - struct i2c_client* tea6420_1; - struct i2c_client* tea6420_2; + struct i2c_client *saa7111a; + struct i2c_client *tda9840; + struct i2c_client *tea6415c; + struct i2c_client *tuner; + struct i2c_client *tea6420_1; + struct i2c_client *tea6420_2; int cur_mode; /* current audio mode (mono, stereo, ...) */ int cur_input; /* current input */ @@ -154,7 +154,7 @@ static struct saa7146_extension extension; static int mxb_check_clients(struct device *dev, void *data) { - struct mxb* mxb = data; + struct mxb *mxb = data; struct i2c_client *client = i2c_verify_client(dev); if (!client) @@ -298,7 +298,7 @@ static struct { { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, { 3, { 0x80, 0xb3, 0x0a } }, - {-1, { 0} } + {-1, { 0 } } }; /* bring hardware to a sane state. this has to be done, just in case someone @@ -314,10 +314,9 @@ static int mxb_init_done(struct saa7146_dev* dev) struct v4l2_routing route; int i = 0, err = 0; - struct tea6415c_multiplex vm; + struct tea6415c_multiplex vm; /* select video mode in saa7111a */ - /* fixme: currently pointless: gets overwritten by configuration below */ mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); /* select tuner-output on saa7111a */ @@ -342,20 +341,20 @@ static int mxb_init_done(struct saa7146_dev* dev) mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); /* mute audio on tea6420s */ - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]); + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]); + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]); /* switch to tuner-channel on tea6415c*/ vm.out = 17; vm.in = 3; - mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); + mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); /* select tuner-output on multicable on tea6415c*/ vm.in = 3; vm.out = 13; - mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); + mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); /* the rest for mxb */ mxb->cur_input = 0; @@ -372,21 +371,22 @@ static int mxb_init_done(struct saa7146_dev* dev) msg.len = mxb_saa7740_init[0].length; msg.buf = &mxb_saa7740_init[0].data[0]; - if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { + err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); + if (err == 1) { /* the sound arena module is a pos, that's probably the reason philips refuses to hand out a datasheet for the saa7740... it seems to screw up the i2c bus, so we disable fast irq based i2c transactions here and rely on the slow and safe polling method ... */ extension.flags &= ~SAA7146_USE_I2C_IRQ; - for(i = 1;;i++) { - if( -1 == mxb_saa7740_init[i].length ) { + for (i = 1; ; i++) { + if (-1 == mxb_saa7740_init[i].length) break; - } msg.len = mxb_saa7740_init[i].length; msg.buf = &mxb_saa7740_init[i].data[0]; - if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { + err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); + if (err != 1) { DEB_D(("failed to initialize 'sound arena module'.\n")); goto err; } @@ -400,7 +400,8 @@ err: /* ext->saa has been filled by the core driver */ /* some stuff is done via variables */ - saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync); + saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, + input_port_selection[mxb->cur_input].hps_sync); /* some stuff is done via direct write to the registers */ @@ -425,11 +426,11 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) static struct saa7146_ext_vv vv_data; /* this function only gets called when the probing was successful */ -static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { - struct mxb* mxb = (struct mxb*)dev->ext_priv; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - DEB_EE(("dev:%p\n",dev)); + DEB_EE(("dev:%p\n", dev)); /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ @@ -461,11 +462,11 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data return 0; } -static int mxb_detach(struct saa7146_dev* dev) +static int mxb_detach(struct saa7146_dev *dev) { - struct mxb* mxb = (struct mxb*)dev->ext_priv; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - DEB_EE(("dev:%p\n",dev)); + DEB_EE(("dev:%p\n", dev)); i2c_release_client(mxb->tea6420_1); i2c_release_client(mxb->tea6420_2); @@ -475,9 +476,8 @@ static int mxb_detach(struct saa7146_dev* dev) i2c_release_client(mxb->tuner); saa7146_unregister_device(&mxb->video_dev,dev); - if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { - saa7146_unregister_device(&mxb->vbi_dev,dev); - } + if (MXB_BOARD_CAN_DO_VBI(dev)) + saa7146_unregister_device(&mxb->vbi_dev, dev); saa7146_vv_release(dev); mxb_num--; @@ -491,7 +491,7 @@ static int mxb_detach(struct saa7146_dev* dev) static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; - struct mxb* mxb = (struct mxb*)dev->ext_priv; + struct mxb *mxb = (struct mxb *)dev->ext_priv; struct saa7146_vv *vv = dev->vv_data; switch(cmd) { @@ -500,11 +500,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct v4l2_input *i = arg; DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); - if( i->index < 0 || i->index >= MXB_INPUTS) { + if (i->index < 0 || i->index >= MXB_INPUTS) return -EINVAL; - } memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); - return 0; } /* the saa7146 provides some controls (brightness, contrast, saturation) @@ -518,7 +516,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == qc->id) { *qc = mxb_controls[i]; - DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id)); + DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); return 0; } } @@ -530,56 +528,51 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) int i; for (i = MAXCONTROLS - 1; i >= 0; i--) { - if (mxb_controls[i].id == vc->id) { + if (mxb_controls[i].id == vc->id) break; - } } - if( i < 0 ) { + if (i < 0) return -EAGAIN; - } - switch (vc->id ) { - case V4L2_CID_AUDIO_MUTE: { - vc->value = mxb->cur_mute; - DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); - return 0; - } + if (vc->id == V4L2_CID_AUDIO_MUTE) { + vc->value = mxb->cur_mute; + DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); + return 0; } - DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); + DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); return 0; } case VIDIOC_S_CTRL: { - struct v4l2_control *vc = arg; + struct v4l2_control *vc = arg; int i = 0; for (i = MAXCONTROLS - 1; i >= 0; i--) { - if (mxb_controls[i].id == vc->id) { + if (mxb_controls[i].id == vc->id) break; - } } - if( i < 0 ) { + if (i < 0) return -EAGAIN; - } - switch (vc->id ) { - case V4L2_CID_AUDIO_MUTE: { - mxb->cur_mute = vc->value; - if( 0 == vc->value ) { - /* switch the audio-source */ - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); - } else { - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); - } - DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value)); - break; + if (vc->id == V4L2_CID_AUDIO_MUTE) { + mxb->cur_mute = vc->value; + if (!vc->value) { + /* switch the audio-source */ + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); + } else { + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[6][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[6][1]); } + DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); } return 0; } @@ -588,7 +581,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) int *input = (int *)arg; *input = mxb->cur_input; - DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); + DEB_EE(("VIDIOC_G_INPUT %d.\n", *input)); return 0; } case VIDIOC_S_INPUT: @@ -598,73 +591,60 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct v4l2_routing route; int i = 0; - DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); - if (input < 0 || input >= MXB_INPUTS) { + if (input < 0 || input >= MXB_INPUTS) return -EINVAL; - } mxb->cur_input = input; - saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); + saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, + input_port_selection[input].hps_sync); /* prepare switching of tea6415c and saa7111a; have a look at the 'background'-file for further informations */ - switch( input ) { - - case TUNER: - { - i = SAA7115_COMPOSITE0; - vm.in = 3; - vm.out = 17; - - if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { - printk("VIDIOC_S_INPUT: could not address tea6415c #1\n"); - return -EFAULT; - } - /* connect tuner-output always to multicable */ - vm.in = 3; - vm.out = 13; - break; - } - case AUX3_YC: - { - /* nothing to be done here. aux3_yc is - directly connected to the saa711a */ - i = SAA7115_SVIDEO1; - break; - } - case AUX3: - { - /* nothing to be done here. aux3 is - directly connected to the saa711a */ - i = SAA7115_COMPOSITE1; - break; - } - case AUX1: - { - i = SAA7115_COMPOSITE0; - vm.in = 1; - vm.out = 17; - break; + switch (input) { + case TUNER: + i = SAA7115_COMPOSITE0; + vm.in = 3; + vm.out = 17; + + if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); + return -EFAULT; } + /* connect tuner-output always to multicable */ + vm.in = 3; + vm.out = 13; + break; + case AUX3_YC: + /* nothing to be done here. aux3_yc is + directly connected to the saa711a */ + i = SAA7115_SVIDEO1; + break; + case AUX3: + /* nothing to be done here. aux3 is + directly connected to the saa711a */ + i = SAA7115_COMPOSITE1; + break; + case AUX1: + i = SAA7115_COMPOSITE0; + vm.in = 1; + vm.out = 17; + break; } /* switch video in tea6415c only if necessary */ - switch( input ) { - case TUNER: - case AUX1: - { - if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { - printk("VIDIOC_S_INPUT: could not address tea6415c #3\n"); - return -EFAULT; - } - break; - } - default: - { - break; + switch (input) { + case TUNER: + case AUX1: + if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); + return -EFAULT; } + break; + default: + break; } /* switch video in saa7111a */ @@ -675,8 +655,10 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) /* switch the audio-source only if necessary */ if( 0 == mxb->cur_mute ) { - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]); + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[input]][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[input]][1]); } return 0; @@ -719,8 +701,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct v4l2_frequency *f = arg; - if(0 != mxb->cur_input) { - DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); + if (mxb->cur_input) { + DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", + mxb->cur_input)); return -EINVAL; } @@ -733,7 +716,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct v4l2_frequency *f = arg; - if (0 != f->tuner) + if (f->tuner) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) @@ -761,7 +744,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { int i = *(int*)arg; - if( i < 0 || i >= MXB_AUDIOS ) { + if (i < 0 || i >= MXB_AUDIOS) { DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); return -EINVAL; } @@ -777,7 +760,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { int i = *(int*)arg; - if( i < 0 || i >= MXB_AUDIOS ) { + if (i < 0 || i >= MXB_AUDIOS) { DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); return -EINVAL; } @@ -792,12 +775,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct v4l2_audio *a = arg; - if( a->index < 0 || a->index > MXB_INPUTS ) { - DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); + if (a->index < 0 || a->index > MXB_INPUTS) { + DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); return -EINVAL; } - DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); + DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); return 0; @@ -805,13 +788,16 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case VIDIOC_S_AUDIO: { struct v4l2_audio *a = arg; - DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); + + DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index)); return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: i2c_clients_command(&mxb->i2c_adapter, cmd, arg); - break; + return 0; +#endif default: /* DEB2(printk("does not handle this ioctl.\n")); @@ -919,7 +905,7 @@ static struct saa7146_extension extension = { static int __init mxb_init_module(void) { - if( 0 != saa7146_register_extension(&extension)) { + if (saa7146_register_extension(&extension)) { DEB_S(("failed to register extension.\n")); return -ENODEV; } -- GitLab From 71ef85c7e0f431467c2e18314ff0cb8fa2b84e5f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 7 Sep 2008 08:31:13 -0300 Subject: [PATCH 4075/5416] V4L/DVB (8943): saa5246a: convert i2c driver for new i2c API - Convert to use v4l2-i2c-drv-legacy.h to be able to handle the new i2c API - Cleanups - Use v4l_dbg/v4l_info to have uniform kernel messages Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa5246a.c | 520 +++++++++++++++++++++++++-------- drivers/media/video/saa5246a.h | 359 ----------------------- 2 files changed, 400 insertions(+), 479 deletions(-) delete mode 100644 drivers/media/video/saa5246a.h diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index ff81049e936..4a21b8a6a70 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -43,138 +43,363 @@ #include #include #include -#include #include +#include +#include #include #include #include -#include - -#include "saa5246a.h" +#include MODULE_AUTHOR("Michael Geng "); MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); MODULE_LICENSE("GPL"); -struct saa5246a_device -{ - u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; - int is_searching[NUM_DAUS]; - struct i2c_client *client; - unsigned long in_use; - struct mutex lock; -}; +#define MAJOR_VERSION 1 /* driver major version number */ +#define MINOR_VERSION 8 /* driver minor version number */ + +/* Number of DAUs = number of pages that can be searched at the same time. */ +#define NUM_DAUS 4 + +#define NUM_ROWS_PER_PAGE 40 + +/* first column is 0 (not 1) */ +#define POS_TIME_START 32 +#define POS_TIME_END 39 + +#define POS_HEADER_START 7 +#define POS_HEADER_END 31 + +/* Returns 'true' if the part of the videotext page described with req contains + (at least parts of) the time field */ +#define REQ_CONTAINS_TIME(p_req) \ + ((p_req)->start <= POS_TIME_END && \ + (p_req)->end >= POS_TIME_START) + +/* Returns 'true' if the part of the videotext page described with req contains + (at least parts of) the page header */ +#define REQ_CONTAINS_HEADER(p_req) \ + ((p_req)->start <= POS_HEADER_END && \ + (p_req)->end >= POS_HEADER_START) + +/*****************************************************************************/ +/* Mode register numbers of the SAA5246A */ +/*****************************************************************************/ +#define SAA5246A_REGISTER_R0 0 +#define SAA5246A_REGISTER_R1 1 +#define SAA5246A_REGISTER_R2 2 +#define SAA5246A_REGISTER_R3 3 +#define SAA5246A_REGISTER_R4 4 +#define SAA5246A_REGISTER_R5 5 +#define SAA5246A_REGISTER_R6 6 +#define SAA5246A_REGISTER_R7 7 +#define SAA5246A_REGISTER_R8 8 +#define SAA5246A_REGISTER_R9 9 +#define SAA5246A_REGISTER_R10 10 +#define SAA5246A_REGISTER_R11 11 +#define SAA5246A_REGISTER_R11B 11 + +/* SAA5246A mode registers often autoincrement to the next register. + Therefore we use variable argument lists. The following macro indicates + the end of a command list. */ +#define COMMAND_END (-1) + +/*****************************************************************************/ +/* Contents of the mode registers of the SAA5246A */ +/*****************************************************************************/ +/* Register R0 (Advanced Control) */ +#define R0_SELECT_R11 0x00 +#define R0_SELECT_R11B 0x01 + +#define R0_PLL_TIME_CONSTANT_LONG 0x00 +#define R0_PLL_TIME_CONSTANT_SHORT 0x02 + +#define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 +#define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 + +#define R0_ENABLE_HDR_POLL 0x00 +#define R0_DISABLE_HDR_POLL 0x10 + +#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 +#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 + +#define R0_NO_FREE_RUN_PLL 0x00 +#define R0_FREE_RUN_PLL 0x40 + +#define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 +#define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 + +/* Register R1 (Mode) */ +#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 +#define R1_NON_INTERLACED_312_313_LINES 0x01 +#define R1_NON_INTERLACED_312_312_LINES 0x02 +#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 +#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 + +#define R1_DEW 0x00 +#define R1_FULL_FIELD 0x08 + +#define R1_EXTENDED_PACKET_DISABLE 0x00 +#define R1_EXTENDED_PACKET_ENABLE 0x10 + +#define R1_DAUS_ALL_ON 0x00 +#define R1_DAUS_ALL_OFF 0x20 + +#define R1_7_BITS_PLUS_PARITY 0x00 +#define R1_8_BITS_NO_PARITY 0x40 + +#define R1_VCS_TO_SCS 0x00 +#define R1_NO_VCS_TO_SCS 0x80 + +/* Register R2 (Page request address) */ +#define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 +#define R2_IN_R3_SELECT_PAGE_TENS 0x01 +#define R2_IN_R3_SELECT_PAGE_UNITS 0x02 +#define R2_IN_R3_SELECT_HOURS_TENS 0x03 +#define R2_IN_R3_SELECT_HOURS_UNITS 0x04 +#define R2_IN_R3_SELECT_MINUTES_TENS 0x05 +#define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 + +#define R2_DAU_0 0x00 +#define R2_DAU_1 0x10 +#define R2_DAU_2 0x20 +#define R2_DAU_3 0x30 + +#define R2_BANK_0 0x00 +#define R2_BANK 1 0x40 + +#define R2_HAMMING_CHECK_ON 0x80 +#define R2_HAMMING_CHECK_OFF 0x00 + +/* Register R3 (Page request data) */ +#define R3_PAGE_HUNDREDS_0 0x00 +#define R3_PAGE_HUNDREDS_1 0x01 +#define R3_PAGE_HUNDREDS_2 0x02 +#define R3_PAGE_HUNDREDS_3 0x03 +#define R3_PAGE_HUNDREDS_4 0x04 +#define R3_PAGE_HUNDREDS_5 0x05 +#define R3_PAGE_HUNDREDS_6 0x06 +#define R3_PAGE_HUNDREDS_7 0x07 -static struct video_device saa_template; /* Declared near bottom */ +#define R3_HOLD_PAGE 0x00 +#define R3_UPDATE_PAGE 0x08 -/* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; +#define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 +#define R3_PAGE_HUNDREDS_DO_CARE 0x10 -I2C_CLIENT_INSMOD; +#define R3_PAGE_TENS_DO_NOT_CARE 0x00 +#define R3_PAGE_TENS_DO_CARE 0x10 -static struct i2c_client client_template; +#define R3_PAGE_UNITS_DO_NOT_CARE 0x00 +#define R3_PAGE_UNITS_DO_CARE 0x10 -static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) -{ - int pgbuf; - int err; - struct i2c_client *client; - struct video_device *vd; - struct saa5246a_device *t; +#define R3_HOURS_TENS_DO_NOT_CARE 0x00 +#define R3_HOURS_TENS_DO_CARE 0x10 - printk(KERN_INFO "saa5246a: teletext chip found.\n"); - client=kmalloc(sizeof(*client), GFP_KERNEL); - if(client==NULL) - return -ENOMEM; - client_template.adapter = adap; - client_template.addr = addr; - memcpy(client, &client_template, sizeof(*client)); - t = kzalloc(sizeof(*t), GFP_KERNEL); - if(t==NULL) - { - kfree(client); - return -ENOMEM; - } - strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - mutex_init(&t->lock); +#define R3_HOURS_UNITS_DO_NOT_CARE 0x00 +#define R3_HOURS_UNITS_DO_CARE 0x10 - /* - * Now create a video4linux device - */ +#define R3_MINUTES_TENS_DO_NOT_CARE 0x00 +#define R3_MINUTES_TENS_DO_CARE 0x10 - vd = video_device_alloc(); - if(vd==NULL) - { - kfree(t); - kfree(client); - return -ENOMEM; - } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); +#define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 +#define R3_MINUTES_UNITS_DO_CARE 0x10 - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) - { - memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); - t->is_searching[pgbuf] = false; - } - video_set_drvdata(vd, t); +/* Register R4 (Display chapter) */ +#define R4_DISPLAY_PAGE_0 0x00 +#define R4_DISPLAY_PAGE_1 0x01 +#define R4_DISPLAY_PAGE_2 0x02 +#define R4_DISPLAY_PAGE_3 0x03 +#define R4_DISPLAY_PAGE_4 0x04 +#define R4_DISPLAY_PAGE_5 0x05 +#define R4_DISPLAY_PAGE_6 0x06 +#define R4_DISPLAY_PAGE_7 0x07 +/* Register R5 (Normal display control) */ +#define R5_PICTURE_INSIDE_BOXING_OFF 0x00 +#define R5_PICTURE_INSIDE_BOXING_ON 0x01 - /* - * Register it - */ +#define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 +#define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 - if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) - { - kfree(t); - kfree(client); - video_device_release(vd); - return err; - } - t->client = client; - i2c_attach_client(client); - return 0; -} +#define R5_TEXT_INSIDE_BOXING_OFF 0x00 +#define R5_TEXT_INSIDE_BOXING_ON 0x04 -/* - * We do most of the hard work when we become a device on the i2c. - */ -static int saa5246a_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, saa5246a_attach); - return 0; -} +#define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 +#define R5_TEXT_OUTSIDE_BOXING_ON 0x08 -static int saa5246a_detach(struct i2c_client *client) -{ - struct video_device *vd = i2c_get_clientdata(client); +#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 +#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 - i2c_detach_client(client); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); - kfree(client); - return 0; -} +#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 +#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 -/* - * I2C interfaces - */ +#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 +#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 + +#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 +#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 + +/* Register R6 (Newsflash display) */ +#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 + +#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 + +#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 + +#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 + +#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 + +#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 + +#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 + +#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 + +/* Register R7 (Display mode) */ +#define R7_BOX_OFF_ROW_0 0x00 +#define R7_BOX_ON_ROW_0 0x01 + +#define R7_BOX_OFF_ROW_1_TO_23 0x00 +#define R7_BOX_ON_ROW_1_TO_23 0x02 + +#define R7_BOX_OFF_ROW_24 0x00 +#define R7_BOX_ON_ROW_24 0x04 + +#define R7_SINGLE_HEIGHT 0x00 +#define R7_DOUBLE_HEIGHT 0x08 + +#define R7_TOP_HALF 0x00 +#define R7_BOTTOM_HALF 0x10 + +#define R7_REVEAL_OFF 0x00 +#define R7_REVEAL_ON 0x20 + +#define R7_CURSER_OFF 0x00 +#define R7_CURSER_ON 0x40 + +#define R7_STATUS_BOTTOM 0x00 +#define R7_STATUS_TOP 0x80 + +/* Register R8 (Active chapter) */ +#define R8_ACTIVE_CHAPTER_0 0x00 +#define R8_ACTIVE_CHAPTER_1 0x01 +#define R8_ACTIVE_CHAPTER_2 0x02 +#define R8_ACTIVE_CHAPTER_3 0x03 +#define R8_ACTIVE_CHAPTER_4 0x04 +#define R8_ACTIVE_CHAPTER_5 0x05 +#define R8_ACTIVE_CHAPTER_6 0x06 +#define R8_ACTIVE_CHAPTER_7 0x07 -static struct i2c_driver i2c_driver_videotext = +#define R8_CLEAR_MEMORY 0x08 +#define R8_DO_NOT_CLEAR_MEMORY 0x00 + +/* Register R9 (Curser row) */ +#define R9_CURSER_ROW_0 0x00 +#define R9_CURSER_ROW_1 0x01 +#define R9_CURSER_ROW_2 0x02 +#define R9_CURSER_ROW_25 0x19 + +/* Register R10 (Curser column) */ +#define R10_CURSER_COLUMN_0 0x00 +#define R10_CURSER_COLUMN_6 0x06 +#define R10_CURSER_COLUMN_8 0x08 + +/*****************************************************************************/ +/* Row 25 control data in column 0 to 9 */ +/*****************************************************************************/ +#define ROW25_COLUMN0_PAGE_UNITS 0x0F + +#define ROW25_COLUMN1_PAGE_TENS 0x0F + +#define ROW25_COLUMN2_MINUTES_UNITS 0x0F + +#define ROW25_COLUMN3_MINUTES_TENS 0x07 +#define ROW25_COLUMN3_DELETE_PAGE 0x08 + +#define ROW25_COLUMN4_HOUR_UNITS 0x0F + +#define ROW25_COLUMN5_HOUR_TENS 0x03 +#define ROW25_COLUMN5_INSERT_HEADLINE 0x04 +#define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 + +#define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 +#define ROW25_COLUMN6_UPDATE_PAGE 0x02 +#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 +#define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 + +#define ROW25_COLUMN7_SERIAL_MODE 0x01 +#define ROW25_COLUMN7_CHARACTER_SET 0x0E + +#define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 +#define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 + +#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 + +#define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 + +/*****************************************************************************/ +/* Helper macros for extracting page, hour and minute digits */ +/*****************************************************************************/ +/* BYTE_POS 0 is at row 0, column 0, + BYTE_POS 1 is at row 0, column 1, + BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) + BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), + ... */ +#define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) +#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) + +/*****************************************************************************/ +/* Helper macros for extracting page, hour and minute digits */ +/*****************************************************************************/ +/* Macros for extracting hundreds, tens and units of a page number which + must be in the range 0 ... 0x799. + Note that page is coded in hexadecimal, i.e. 0x123 means page 123. + page 0x.. means page 8.. */ +#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) +#define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) +#define UNITS_OF_PAGE(page) ((page) & 0xF) + +/* Macros for extracting tens and units of a hour information which + must be in the range 0 ... 0x24. + Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ +#define TENS_OF_HOUR(hour) ((hour) / 0x10) +#define UNITS_OF_HOUR(hour) ((hour) & 0xF) + +/* Macros for extracting tens and units of a minute information which + must be in the range 0 ... 0x59. + Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ +#define TENS_OF_MINUTE(minute) ((minute) / 0x10) +#define UNITS_OF_MINUTE(minute) ((minute) & 0xF) + +#define HOUR_MAX 0x23 +#define MINUTE_MAX 0x59 +#define PAGE_MAX 0x8FF + + +struct saa5246a_device { - .driver = { - .name = IF_NAME, /* name */ - }, - .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ - .attach_adapter = saa5246a_probe, - .detach_client = saa5246a_detach, + u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; + int is_searching[NUM_DAUS]; + struct i2c_client *client; + unsigned long in_use; + struct mutex lock; }; -static struct i2c_client client_template = { - .driver = &i2c_driver_videotext, - .name = "(unset)", -}; +static struct video_device saa_template; /* Declared near bottom */ + +/* + * I2C interfaces + */ static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) { @@ -794,22 +1019,6 @@ static int saa5246a_release(struct inode *inode, struct file *file) return 0; } -static int __init init_saa_5246a (void) -{ - printk(KERN_INFO - "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n", - MAJOR_VERSION, MINOR_VERSION); - return i2c_add_driver(&i2c_driver_videotext); -} - -static void __exit cleanup_saa_5246a (void) -{ - i2c_del_driver(&i2c_driver_videotext); -} - -module_init(init_saa_5246a); -module_exit(cleanup_saa_5246a); - static const struct file_operations saa_fops = { .owner = THIS_MODULE, .open = saa5246a_open, @@ -820,8 +1029,79 @@ static const struct file_operations saa_fops = { static struct video_device saa_template = { - .name = IF_NAME, + .name = "saa5246a", .fops = &saa_fops, .release = video_device_release, .minor = -1, }; + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + +static int saa5246a_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int pgbuf; + int err; + struct video_device *vd; + struct saa5246a_device *t; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + v4l_info(client, "VideoText version %d.%d\n", + MAJOR_VERSION, MINOR_VERSION); + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (t == NULL) + return -ENOMEM; + mutex_init(&t->lock); + + /* Now create a video4linux device */ + vd = video_device_alloc(); + if (vd == NULL) { + kfree(t); + return -ENOMEM; + } + i2c_set_clientdata(client, vd); + memcpy(vd, &saa_template, sizeof(*vd)); + + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { + memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); + t->is_searching[pgbuf] = false; + } + video_set_drvdata(vd, t); + + /* Register it */ + err = video_register_device(vd, VFL_TYPE_VTX, -1); + if (err < 0) { + kfree(t); + video_device_release(vd); + return err; + } + t->client = client; + return 0; +} + +static int saa5246a_remove(struct i2c_client *client) +{ + struct video_device *vd = i2c_get_clientdata(client); + + video_unregister_device(vd); + kfree(video_get_drvdata(vd)); + return 0; +} + +static const struct i2c_device_id saa5246a_id[] = { + { "saa5246a", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa5246a_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa5246a", + .driverid = I2C_DRIVERID_SAA5249, + .probe = saa5246a_probe, + .remove = saa5246a_remove, + .id_table = saa5246a_id, +}; diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h deleted file mode 100644 index 64394c036c6..00000000000 --- a/drivers/media/video/saa5246a.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from - Philips. - - Copyright (C) 2004 Michael Geng (linux@MichaelGeng.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ -#ifndef __SAA5246A_H__ -#define __SAA5246A_H__ - -#define MAJOR_VERSION 1 /* driver major version number */ -#define MINOR_VERSION 8 /* driver minor version number */ - -#define IF_NAME "SAA5246A" - -#define I2C_ADDRESS 17 - -/* Number of DAUs = number of pages that can be searched at the same time. */ -#define NUM_DAUS 4 - -#define NUM_ROWS_PER_PAGE 40 - -/* first column is 0 (not 1) */ -#define POS_TIME_START 32 -#define POS_TIME_END 39 - -#define POS_HEADER_START 7 -#define POS_HEADER_END 31 - -/* Returns 'true' if the part of the videotext page described with req contains - (at least parts of) the time field */ -#define REQ_CONTAINS_TIME(p_req) \ - ((p_req)->start <= POS_TIME_END && \ - (p_req)->end >= POS_TIME_START) - -/* Returns 'true' if the part of the videotext page described with req contains - (at least parts of) the page header */ -#define REQ_CONTAINS_HEADER(p_req) \ - ((p_req)->start <= POS_HEADER_END && \ - (p_req)->end >= POS_HEADER_START) - -/*****************************************************************************/ -/* Mode register numbers of the SAA5246A */ -/*****************************************************************************/ -#define SAA5246A_REGISTER_R0 0 -#define SAA5246A_REGISTER_R1 1 -#define SAA5246A_REGISTER_R2 2 -#define SAA5246A_REGISTER_R3 3 -#define SAA5246A_REGISTER_R4 4 -#define SAA5246A_REGISTER_R5 5 -#define SAA5246A_REGISTER_R6 6 -#define SAA5246A_REGISTER_R7 7 -#define SAA5246A_REGISTER_R8 8 -#define SAA5246A_REGISTER_R9 9 -#define SAA5246A_REGISTER_R10 10 -#define SAA5246A_REGISTER_R11 11 -#define SAA5246A_REGISTER_R11B 11 - -/* SAA5246A mode registers often autoincrement to the next register. - Therefore we use variable argument lists. The following macro indicates - the end of a command list. */ -#define COMMAND_END (- 1) - -/*****************************************************************************/ -/* Contents of the mode registers of the SAA5246A */ -/*****************************************************************************/ -/* Register R0 (Advanced Control) */ -#define R0_SELECT_R11 0x00 -#define R0_SELECT_R11B 0x01 - -#define R0_PLL_TIME_CONSTANT_LONG 0x00 -#define R0_PLL_TIME_CONSTANT_SHORT 0x02 - -#define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 -#define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 - -#define R0_ENABLE_HDR_POLL 0x00 -#define R0_DISABLE_HDR_POLL 0x10 - -#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 -#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 - -#define R0_NO_FREE_RUN_PLL 0x00 -#define R0_FREE_RUN_PLL 0x40 - -#define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 -#define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 - -/* Register R1 (Mode) */ -#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 -#define R1_NON_INTERLACED_312_313_LINES 0x01 -#define R1_NON_INTERLACED_312_312_LINES 0x02 -#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 -#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 - -#define R1_DEW 0x00 -#define R1_FULL_FIELD 0x08 - -#define R1_EXTENDED_PACKET_DISABLE 0x00 -#define R1_EXTENDED_PACKET_ENABLE 0x10 - -#define R1_DAUS_ALL_ON 0x00 -#define R1_DAUS_ALL_OFF 0x20 - -#define R1_7_BITS_PLUS_PARITY 0x00 -#define R1_8_BITS_NO_PARITY 0x40 - -#define R1_VCS_TO_SCS 0x00 -#define R1_NO_VCS_TO_SCS 0x80 - -/* Register R2 (Page request address) */ -#define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 -#define R2_IN_R3_SELECT_PAGE_TENS 0x01 -#define R2_IN_R3_SELECT_PAGE_UNITS 0x02 -#define R2_IN_R3_SELECT_HOURS_TENS 0x03 -#define R2_IN_R3_SELECT_HOURS_UNITS 0x04 -#define R2_IN_R3_SELECT_MINUTES_TENS 0x05 -#define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 - -#define R2_DAU_0 0x00 -#define R2_DAU_1 0x10 -#define R2_DAU_2 0x20 -#define R2_DAU_3 0x30 - -#define R2_BANK_0 0x00 -#define R2_BANK 1 0x40 - -#define R2_HAMMING_CHECK_ON 0x80 -#define R2_HAMMING_CHECK_OFF 0x00 - -/* Register R3 (Page request data) */ -#define R3_PAGE_HUNDREDS_0 0x00 -#define R3_PAGE_HUNDREDS_1 0x01 -#define R3_PAGE_HUNDREDS_2 0x02 -#define R3_PAGE_HUNDREDS_3 0x03 -#define R3_PAGE_HUNDREDS_4 0x04 -#define R3_PAGE_HUNDREDS_5 0x05 -#define R3_PAGE_HUNDREDS_6 0x06 -#define R3_PAGE_HUNDREDS_7 0x07 - -#define R3_HOLD_PAGE 0x00 -#define R3_UPDATE_PAGE 0x08 - -#define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 -#define R3_PAGE_HUNDREDS_DO_CARE 0x10 - -#define R3_PAGE_TENS_DO_NOT_CARE 0x00 -#define R3_PAGE_TENS_DO_CARE 0x10 - -#define R3_PAGE_UNITS_DO_NOT_CARE 0x00 -#define R3_PAGE_UNITS_DO_CARE 0x10 - -#define R3_HOURS_TENS_DO_NOT_CARE 0x00 -#define R3_HOURS_TENS_DO_CARE 0x10 - -#define R3_HOURS_UNITS_DO_NOT_CARE 0x00 -#define R3_HOURS_UNITS_DO_CARE 0x10 - -#define R3_MINUTES_TENS_DO_NOT_CARE 0x00 -#define R3_MINUTES_TENS_DO_CARE 0x10 - -#define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 -#define R3_MINUTES_UNITS_DO_CARE 0x10 - -/* Register R4 (Display chapter) */ -#define R4_DISPLAY_PAGE_0 0x00 -#define R4_DISPLAY_PAGE_1 0x01 -#define R4_DISPLAY_PAGE_2 0x02 -#define R4_DISPLAY_PAGE_3 0x03 -#define R4_DISPLAY_PAGE_4 0x04 -#define R4_DISPLAY_PAGE_5 0x05 -#define R4_DISPLAY_PAGE_6 0x06 -#define R4_DISPLAY_PAGE_7 0x07 - -/* Register R5 (Normal display control) */ -#define R5_PICTURE_INSIDE_BOXING_OFF 0x00 -#define R5_PICTURE_INSIDE_BOXING_ON 0x01 - -#define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 -#define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 - -#define R5_TEXT_INSIDE_BOXING_OFF 0x00 -#define R5_TEXT_INSIDE_BOXING_ON 0x04 - -#define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 -#define R5_TEXT_OUTSIDE_BOXING_ON 0x08 - -#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 -#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 - -#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 -#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 - -#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 -#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 - -#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 -#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 - -/* Register R6 (Newsflash display) */ -#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 - -#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 - -#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 - -#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 - -#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 - -#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 - -#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 - -#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 -#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 - -/* Register R7 (Display mode) */ -#define R7_BOX_OFF_ROW_0 0x00 -#define R7_BOX_ON_ROW_0 0x01 - -#define R7_BOX_OFF_ROW_1_TO_23 0x00 -#define R7_BOX_ON_ROW_1_TO_23 0x02 - -#define R7_BOX_OFF_ROW_24 0x00 -#define R7_BOX_ON_ROW_24 0x04 - -#define R7_SINGLE_HEIGHT 0x00 -#define R7_DOUBLE_HEIGHT 0x08 - -#define R7_TOP_HALF 0x00 -#define R7_BOTTOM_HALF 0x10 - -#define R7_REVEAL_OFF 0x00 -#define R7_REVEAL_ON 0x20 - -#define R7_CURSER_OFF 0x00 -#define R7_CURSER_ON 0x40 - -#define R7_STATUS_BOTTOM 0x00 -#define R7_STATUS_TOP 0x80 - -/* Register R8 (Active chapter) */ -#define R8_ACTIVE_CHAPTER_0 0x00 -#define R8_ACTIVE_CHAPTER_1 0x01 -#define R8_ACTIVE_CHAPTER_2 0x02 -#define R8_ACTIVE_CHAPTER_3 0x03 -#define R8_ACTIVE_CHAPTER_4 0x04 -#define R8_ACTIVE_CHAPTER_5 0x05 -#define R8_ACTIVE_CHAPTER_6 0x06 -#define R8_ACTIVE_CHAPTER_7 0x07 - -#define R8_CLEAR_MEMORY 0x08 -#define R8_DO_NOT_CLEAR_MEMORY 0x00 - -/* Register R9 (Curser row) */ -#define R9_CURSER_ROW_0 0x00 -#define R9_CURSER_ROW_1 0x01 -#define R9_CURSER_ROW_2 0x02 -#define R9_CURSER_ROW_25 0x19 - -/* Register R10 (Curser column) */ -#define R10_CURSER_COLUMN_0 0x00 -#define R10_CURSER_COLUMN_6 0x06 -#define R10_CURSER_COLUMN_8 0x08 - -/*****************************************************************************/ -/* Row 25 control data in column 0 to 9 */ -/*****************************************************************************/ -#define ROW25_COLUMN0_PAGE_UNITS 0x0F - -#define ROW25_COLUMN1_PAGE_TENS 0x0F - -#define ROW25_COLUMN2_MINUTES_UNITS 0x0F - -#define ROW25_COLUMN3_MINUTES_TENS 0x07 -#define ROW25_COLUMN3_DELETE_PAGE 0x08 - -#define ROW25_COLUMN4_HOUR_UNITS 0x0F - -#define ROW25_COLUMN5_HOUR_TENS 0x03 -#define ROW25_COLUMN5_INSERT_HEADLINE 0x04 -#define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 - -#define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 -#define ROW25_COLUMN6_UPDATE_PAGE 0x02 -#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 -#define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 - -#define ROW25_COLUMN7_SERIAL_MODE 0x01 -#define ROW25_COLUMN7_CHARACTER_SET 0x0E - -#define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 -#define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 - -#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 - -#define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 - -/*****************************************************************************/ -/* Helper macros for extracting page, hour and minute digits */ -/*****************************************************************************/ -/* BYTE_POS 0 is at row 0, column 0, - BYTE_POS 1 is at row 0, column 1, - BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) - BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), - ... */ -#define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) -#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) - -/*****************************************************************************/ -/* Helper macros for extracting page, hour and minute digits */ -/*****************************************************************************/ -/* Macros for extracting hundreds, tens and units of a page number which - must be in the range 0 ... 0x799. - Note that page is coded in hexadecimal, i.e. 0x123 means page 123. - page 0x.. means page 8.. */ -#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) -#define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) -#define UNITS_OF_PAGE(page) ((page) & 0xF) - -/* Macros for extracting tens and units of a hour information which - must be in the range 0 ... 0x24. - Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ -#define TENS_OF_HOUR(hour) ((hour) / 0x10) -#define UNITS_OF_HOUR(hour) ((hour) & 0xF) - -/* Macros for extracting tens and units of a minute information which - must be in the range 0 ... 0x59. - Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ -#define TENS_OF_MINUTE(minute) ((minute) / 0x10) -#define UNITS_OF_MINUTE(minute) ((minute) & 0xF) - -#define HOUR_MAX 0x23 -#define MINUTE_MAX 0x59 -#define PAGE_MAX 0x8FF - -#endif /* __SAA5246A_H__ */ -- GitLab From 96af9880c0d38fa6f331d1dd4cd39c5f5227fbbf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 7 Sep 2008 08:31:38 -0300 Subject: [PATCH 4076/5416] V4L/DVB (8944): saa5249: convert i2c driver for new i2c API - Convert to use v4l2-i2c-drv-legacy.h to be able to handle the new i2c API - Cleanups - Use v4l_dbg/v4l_info to have uniform kernel messages Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa5249.c | 653 +++++++++++++++------------------- 1 file changed, 289 insertions(+), 364 deletions(-) diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 8517aa4f068..421071cc99b 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -15,8 +15,6 @@ * * Copyright (c) 1998 Richard Guenther * - * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $ - * * Derived From * * vtx.c: @@ -45,34 +43,27 @@ #include #include -#include #include -#include -#include -#include -#include #include -#include -#include #include +#include +#include #include #include #include #include -#include - +#include -#include -#include +MODULE_AUTHOR("Michael Geng "); +MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); +MODULE_LICENSE("GPL"); #define VTX_VER_MAJ 1 #define VTX_VER_MIN 8 - #define NUM_DAUS 4 #define NUM_BUFS 8 -#define IF_NAME "SAA5249" static const int disp_modes[8][3] = { @@ -125,125 +116,8 @@ struct saa5249_device #define VTX_DEV_MINOR 0 -/* General defines and debugging support */ - -#define RESCHED do { cond_resched(); } while(0) - static struct video_device saa_template; /* Declared near bottom */ -/* Addresses to scan */ -static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; - -I2C_CLIENT_INSMOD; - -static struct i2c_client client_template; - -static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) -{ - int pgbuf; - int err; - struct i2c_client *client; - struct video_device *vd; - struct saa5249_device *t; - - printk(KERN_INFO "saa5249: teletext chip found.\n"); - client=kmalloc(sizeof(*client), GFP_KERNEL); - if(client==NULL) - return -ENOMEM; - client_template.adapter = adap; - client_template.addr = addr; - memcpy(client, &client_template, sizeof(*client)); - t = kzalloc(sizeof(*t), GFP_KERNEL); - if(t==NULL) - { - kfree(client); - return -ENOMEM; - } - strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - mutex_init(&t->lock); - - /* - * Now create a video4linux device - */ - - vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); - if(vd==NULL) - { - kfree(t); - kfree(client); - return -ENOMEM; - } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); - - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) - { - memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); - memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); - memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); - t->vdau[pgbuf].expire = 0; - t->vdau[pgbuf].clrfound = true; - t->vdau[pgbuf].stopped = true; - t->is_searching[pgbuf] = false; - } - video_set_drvdata(vd, t); - - - /* - * Register it - */ - - if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) - { - kfree(t); - kfree(vd); - kfree(client); - return err; - } - t->client = client; - i2c_attach_client(client); - return 0; -} - -/* - * We do most of the hard work when we become a device on the i2c. - */ - -static int saa5249_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, saa5249_attach); - return 0; -} - -static int saa5249_detach(struct i2c_client *client) -{ - struct video_device *vd = i2c_get_clientdata(client); - i2c_detach_client(client); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); - kfree(vd); - kfree(client); - return 0; -} - -/* new I2C driver support */ - -static struct i2c_driver i2c_driver_videotext = -{ - .driver = { - .name = IF_NAME, /* name */ - }, - .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ - .attach_adapter = saa5249_probe, - .detach_client = saa5249_detach, -}; - -static struct i2c_client client_template = { - .driver = &i2c_driver_videotext, - .name = "(unset)", -}; - /* * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual * delay may be longer. @@ -277,7 +151,7 @@ static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) buf[0] = reg; memcpy(buf+1, data, count); - if(i2c_master_send(t->client, buf, count+1)==count+1) + if (i2c_master_send(t->client, buf, count + 1) == count + 1) return 0; return -1; } @@ -321,243 +195,234 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, static int virtual_mode = false; struct saa5249_device *t = video_drvdata(file); - switch(cmd) + switch (cmd) { + case VTXIOCGETINFO: { - case VTXIOCGETINFO: - { - vtx_info_t *info = arg; - info->version_major = VTX_VER_MAJ; - info->version_minor = VTX_VER_MIN; - info->numpages = NUM_DAUS; - /*info->cct_type = CCT_TYPE;*/ - return 0; - } + vtx_info_t *info = arg; + info->version_major = VTX_VER_MAJ; + info->version_minor = VTX_VER_MIN; + info->numpages = NUM_DAUS; + /*info->cct_type = CCT_TYPE;*/ + return 0; + } - case VTXIOCCLRPAGE: - { - vtx_pagereq_t *req = arg; + case VTXIOCCLRPAGE: + { + vtx_pagereq_t *req = arg; - if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) - return -EINVAL; - memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); - t->vdau[req->pgbuf].clrfound = true; - return 0; - } + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); + t->vdau[req->pgbuf].clrfound = true; + return 0; + } - case VTXIOCCLRFOUND: - { - vtx_pagereq_t *req = arg; + case VTXIOCCLRFOUND: + { + vtx_pagereq_t *req = arg; - if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req->pgbuf].clrfound = true; - return 0; - } + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + t->vdau[req->pgbuf].clrfound = true; + return 0; + } - case VTXIOCPAGEREQ: - { - vtx_pagereq_t *req = arg; - if (!(req->pagemask & PGMASK_PAGE)) - req->page = 0; - if (!(req->pagemask & PGMASK_HOUR)) - req->hour = 0; - if (!(req->pagemask & PGMASK_MINUTE)) - req->minute = 0; - if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ - return -EINVAL; - req->page &= 0x7ff; - if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || - req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); - t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); - t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); - t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); - t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); - t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); - t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); - t->vdau[req->pgbuf].stopped = false; - t->vdau[req->pgbuf].clrfound = true; - t->is_searching[req->pgbuf] = true; - return 0; - } + case VTXIOCPAGEREQ: + { + vtx_pagereq_t *req = arg; + if (!(req->pagemask & PGMASK_PAGE)) + req->page = 0; + if (!(req->pagemask & PGMASK_HOUR)) + req->hour = 0; + if (!(req->pagemask & PGMASK_MINUTE)) + req->minute = 0; + if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ + return -EINVAL; + req->page &= 0x7ff; + if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || + req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); + t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); + t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); + t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); + t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); + t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); + t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); + t->vdau[req->pgbuf].stopped = false; + t->vdau[req->pgbuf].clrfound = true; + t->is_searching[req->pgbuf] = true; + return 0; + } - case VTXIOCGETSTAT: - { - vtx_pagereq_t *req = arg; - u8 infobits[10]; - vtx_pageinfo_t info; - int a; - - if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) - return -EINVAL; - if (!t->vdau[req->pgbuf].stopped) - { - if (i2c_senddata(t, 2, 0, -1) || - i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || - i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || - i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || - i2c_senddata(t, 8, 0, 25, 0, -1)) - return -EIO; - jdelay(PAGE_WAIT); - if (i2c_getdata(t, 10, infobits)) - return -EIO; + case VTXIOCGETSTAT: + { + vtx_pagereq_t *req = arg; + u8 infobits[10]; + vtx_pageinfo_t info; + int a; + + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + if (!t->vdau[req->pgbuf].stopped) { + if (i2c_senddata(t, 2, 0, -1) || + i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || + i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || + i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || + i2c_senddata(t, 8, 0, 25, 0, -1)) + return -EIO; + jdelay(PAGE_WAIT); + if (i2c_getdata(t, 10, infobits)) + return -EIO; - if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ - (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || - time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) - { /* check if new page arrived */ - if (i2c_senddata(t, 8, 0, 0, 0, -1) || - i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) + if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ + (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || + time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) + { /* check if new page arrived */ + if (i2c_senddata(t, 8, 0, 0, 0, -1) || + i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) + return -EIO; + t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; + memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); + if (t->virtual_mode) { + /* Packet X/24 */ + if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || + i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) + return -EIO; + /* Packet X/27/0 */ + if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || + i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) + return -EIO; + /* Packet 8/30/0...8/30/15 + * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, + * so we should undo this here. + */ + if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || + i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) return -EIO; - t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; - memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); - if (t->virtual_mode) - { - /* Packet X/24 */ - if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || - i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) - return -EIO; - /* Packet X/27/0 */ - if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || - i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) - return -EIO; - /* Packet 8/30/0...8/30/15 - * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, - * so we should undo this here. - */ - if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || - i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) - return -EIO; - } - t->vdau[req->pgbuf].clrfound = false; - memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); - } - else - { - memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); } - } - else - { + t->vdau[req->pgbuf].clrfound = false; + memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); + } else { memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); } + } else { + memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); + } - info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); - if (info.pagenum < 0x100) - info.pagenum += 0x800; - info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); - info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); - info.charset = ((infobits[7] >> 1) & 7); - info.delete = !!(infobits[3] & 8); - info.headline = !!(infobits[5] & 4); - info.subtitle = !!(infobits[5] & 8); - info.supp_header = !!(infobits[6] & 1); - info.update = !!(infobits[6] & 2); - info.inter_seq = !!(infobits[6] & 4); - info.dis_disp = !!(infobits[6] & 8); - info.serial = !!(infobits[7] & 1); - info.notfound = !!(infobits[8] & 0x10); - info.pblf = !!(infobits[9] & 0x20); - info.hamming = 0; - for (a = 0; a <= 7; a++) - { - if (infobits[a] & 0xf0) - { - info.hamming = 1; - break; - } - } - if (t->vdau[req->pgbuf].clrfound) - info.notfound = 1; - if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) - return -EFAULT; - if (!info.hamming && !info.notfound) - { - t->is_searching[req->pgbuf] = false; + info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); + if (info.pagenum < 0x100) + info.pagenum += 0x800; + info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); + info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); + info.charset = ((infobits[7] >> 1) & 7); + info.delete = !!(infobits[3] & 8); + info.headline = !!(infobits[5] & 4); + info.subtitle = !!(infobits[5] & 8); + info.supp_header = !!(infobits[6] & 1); + info.update = !!(infobits[6] & 2); + info.inter_seq = !!(infobits[6] & 4); + info.dis_disp = !!(infobits[6] & 8); + info.serial = !!(infobits[7] & 1); + info.notfound = !!(infobits[8] & 0x10); + info.pblf = !!(infobits[9] & 0x20); + info.hamming = 0; + for (a = 0; a <= 7; a++) { + if (infobits[a] & 0xf0) { + info.hamming = 1; + break; } - return 0; } + if (t->vdau[req->pgbuf].clrfound) + info.notfound = 1; + if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) + return -EFAULT; + if (!info.hamming && !info.notfound) + t->is_searching[req->pgbuf] = false; + return 0; + } - case VTXIOCGETPAGE: - { - vtx_pagereq_t *req = arg; - int start, end; - - if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || - req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) - return -EINVAL; - if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) + case VTXIOCGETPAGE: + { + vtx_pagereq_t *req = arg; + int start, end; + + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || + req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) + return -EINVAL; + if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) + return -EFAULT; + + /* + * Always read the time directly from SAA5249 + */ + + if (req->start <= 39 && req->end >= 32) { + int len; + char buf[16]; + start = max(req->start, 32); + end = min(req->end, 39); + len = end - start + 1; + if (i2c_senddata(t, 8, 0, 0, start, -1) || + i2c_getdata(t, len, buf)) + return -EIO; + if (copy_to_user(req->buffer + start - req->start, buf, len)) + return -EFAULT; + } + /* Insert the current header if DAU is still searching for a page */ + if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) { + char buf[32]; + int len; + + start = max(req->start, 7); + end = min(req->end, 31); + len = end - start + 1; + if (i2c_senddata(t, 8, 0, 0, start, -1) || + i2c_getdata(t, len, buf)) + return -EIO; + if (copy_to_user(req->buffer + start - req->start, buf, len)) return -EFAULT; - - /* - * Always read the time directly from SAA5249 - */ - - if (req->start <= 39 && req->end >= 32) - { - int len; - char buf[16]; - start = max(req->start, 32); - end = min(req->end, 39); - len=end-start+1; - if (i2c_senddata(t, 8, 0, 0, start, -1) || - i2c_getdata(t, len, buf)) - return -EIO; - if(copy_to_user(req->buffer+start-req->start, buf, len)) - return -EFAULT; - } - /* Insert the current header if DAU is still searching for a page */ - if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) - { - char buf[32]; - int len; - start = max(req->start, 7); - end = min(req->end, 31); - len=end-start+1; - if (i2c_senddata(t, 8, 0, 0, start, -1) || - i2c_getdata(t, len, buf)) - return -EIO; - if(copy_to_user(req->buffer+start-req->start, buf, len)) - return -EFAULT; - } - return 0; } + return 0; + } - case VTXIOCSTOPDAU: - { - vtx_pagereq_t *req = arg; + case VTXIOCSTOPDAU: + { + vtx_pagereq_t *req = arg; - if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req->pgbuf].stopped = true; - t->is_searching[req->pgbuf] = false; - return 0; - } + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + t->vdau[req->pgbuf].stopped = true; + t->is_searching[req->pgbuf] = false; + return 0; + } - case VTXIOCPUTPAGE: - case VTXIOCSETDISP: - case VTXIOCPUTSTAT: - return 0; + case VTXIOCPUTPAGE: + case VTXIOCSETDISP: + case VTXIOCPUTSTAT: + return 0; - case VTXIOCCLRCACHE: - { - if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, - ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', - ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1)) - return -EIO; - if (i2c_senddata(t, 3, 0x20, -1)) - return -EIO; - jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ - return 0; - } + case VTXIOCCLRCACHE: + { + if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, + ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', + -1)) + return -EIO; + if (i2c_senddata(t, 3, 0x20, -1)) + return -EIO; + jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ + return 0; + } - case VTXIOCSETVIRT: - { - /* The SAA5249 has virtual-row reception turned on always */ - t->virtual_mode = (int)(long)arg; - return 0; - } + case VTXIOCSETVIRT: + { + /* The SAA5249 has virtual-row reception turned on always */ + t->virtual_mode = (int)(long)arg; + return 0; + } } return -EINVAL; } @@ -674,21 +539,6 @@ static int saa5249_release(struct inode *inode, struct file *file) return 0; } -static int __init init_saa_5249 (void) -{ - printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n", - VTX_VER_MAJ, VTX_VER_MIN); - return i2c_add_driver(&i2c_driver_videotext); -} - -static void __exit cleanup_saa_5249 (void) -{ - i2c_del_driver(&i2c_driver_videotext); -} - -module_init(init_saa_5249); -module_exit(cleanup_saa_5249); - static const struct file_operations saa_fops = { .owner = THIS_MODULE, .open = saa5249_open, @@ -702,9 +552,84 @@ static const struct file_operations saa_fops = { static struct video_device saa_template = { - .name = IF_NAME, + .name = "saa5249", .fops = &saa_fops, .release = video_device_release, }; -MODULE_LICENSE("GPL"); +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + +static int saa5249_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int pgbuf; + int err; + struct video_device *vd; + struct saa5249_device *t; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + v4l_info(client, "VideoText version %d.%d\n", + VTX_VER_MAJ, VTX_VER_MIN); + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (t == NULL) + return -ENOMEM; + mutex_init(&t->lock); + + /* Now create a video4linux device */ + vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); + if (vd == NULL) { + kfree(client); + return -ENOMEM; + } + i2c_set_clientdata(client, vd); + memcpy(vd, &saa_template, sizeof(*vd)); + + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { + memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); + memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); + memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); + t->vdau[pgbuf].expire = 0; + t->vdau[pgbuf].clrfound = true; + t->vdau[pgbuf].stopped = true; + t->is_searching[pgbuf] = false; + } + video_set_drvdata(vd, t); + + /* Register it */ + err = video_register_device(vd, VFL_TYPE_VTX, -1); + if (err < 0) { + kfree(t); + kfree(vd); + return err; + } + t->client = client; + return 0; +} + +static int saa5249_remove(struct i2c_client *client) +{ + struct video_device *vd = i2c_get_clientdata(client); + + video_unregister_device(vd); + kfree(video_get_drvdata(vd)); + kfree(vd); + return 0; +} + +static const struct i2c_device_id saa5249_id[] = { + { "saa5249", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa5249_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa5249", + .driverid = I2C_DRIVERID_SAA5249, + .probe = saa5249_probe, + .remove = saa5249_remove, + .id_table = saa5249_id, +}; -- GitLab From 9ebeae5641b141a71ed442e9fcb4993f6c0cd04f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 7 Sep 2008 08:32:44 -0300 Subject: [PATCH 4077/5416] V4L/DVB (8945): mxb: use unique i2c adapter name Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mxb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index b2dae5062e6..7f130284b5c 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -215,9 +215,10 @@ static int mxb_probe(struct saa7146_dev* dev) mxb->i2c_adapter = (struct i2c_adapter) { .class = I2C_CLASS_TV_ANALOG, - .name = "mxb", }; + snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); + saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); -- GitLab From 942648af36e4d4b91e52b3e1a87d4cafd6f7aa46 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 7 Sep 2008 08:38:50 -0300 Subject: [PATCH 4078/5416] V4L/DVB (8946): dib7000m: fix powerpc build error The dib7000m_i2c_enumeration() function is not used by any public drivers, however some prototype board use it. So '#if 0' for now, but don't remove it. Thanks to Patrick Boettcher for clarifying this. Cc: Patrick Boettcher Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib7000m.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 4de0fa9b69a..0109720353b 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -1284,7 +1284,9 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di } EXPORT_SYMBOL(dib7000m_get_i2c_master); -static int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, +#if 0 +/* used with some prototype boards */ +int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) { struct dib7000m_state st = { .i2c_adap = i2c }; @@ -1330,6 +1332,7 @@ static int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, return 0; } EXPORT_SYMBOL(dib7000m_i2c_enumeration); +#endif static struct dvb_frontend_ops dib7000m_ops; struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) -- GitLab From ffb412346bcebf143d0f43ab4c6a61c4270a9266 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 6 Sep 2008 10:52:30 -0300 Subject: [PATCH 4079/5416] V4L/DVB (8948): xc5000: kill xc5000_priv.h move struct xc5000_priv into xc5000.c and delete xc5000_priv.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 13 +++++++- drivers/media/common/tuners/xc5000_priv.h | 37 ----------------------- 2 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 drivers/media/common/tuners/xc5000_priv.h diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index dcddfa803a7..50d42c8db4e 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -30,7 +30,6 @@ #include "dvb_frontend.h" #include "xc5000.h" -#include "xc5000_priv.h" static int debug; module_param(debug, int, 0644); @@ -46,6 +45,18 @@ MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 +struct xc5000_priv { + struct xc5000_config *cfg; + struct i2c_adapter *i2c; + + u32 freq_hz; + u32 bandwidth; + u8 video_standard; + u8 rf_mode; + + void *devptr; +}; + /* Misc Defines */ #define MAX_TV_STANDARD 23 #define XC_MAX_I2C_WRITE_LENGTH 64 diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h deleted file mode 100644 index b2a0074c99c..00000000000 --- a/drivers/media/common/tuners/xc5000_priv.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" - * - * Copyright (c) 2007 Steven Toth - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef XC5000_PRIV_H -#define XC5000_PRIV_H - -struct xc5000_priv { - struct xc5000_config *cfg; - struct i2c_adapter *i2c; - - u32 freq_hz; - u32 bandwidth; - u8 video_standard; - u8 rf_mode; - - void *devptr; -}; - -#endif -- GitLab From 89fd28545c7390eb6c63d3d9e6faac78942dd1a4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 6 Sep 2008 11:44:53 -0300 Subject: [PATCH 4080/5416] V4L/DVB (8949): xc5000: allow multiple driver instances for the same hardware to share state Convert xc5000 to use the hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 87 +++++++++++++++++++--------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 50d42c8db4e..1850f7b7d96 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -30,6 +30,7 @@ #include "dvb_frontend.h" #include "xc5000.h" +#include "tuner-i2c.h" static int debug; module_param(debug, int, 0644); @@ -39,6 +40,9 @@ static int xc5000_load_fw_on_attach; module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); +static DEFINE_MUTEX(xc5000_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); + #define dprintk(level,fmt, arg...) if (debug >= level) \ printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) @@ -47,7 +51,9 @@ MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); struct xc5000_priv { struct xc5000_config *cfg; - struct i2c_adapter *i2c; + + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; u32 freq_hz; u32 bandwidth; @@ -520,13 +526,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) u8 buf[2] = { reg >> 8, reg & 0xff }; u8 bval[2] = { 0, 0 }; struct i2c_msg msg[2] = { - { .addr = priv->cfg->i2c_address, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf[0], .len = 2 }, - { .addr = priv->cfg->i2c_address, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, }; - if (i2c_transfer(priv->i2c, msg, 2) != 2) { + if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) { printk(KERN_WARNING "xc5000: I2C read failed\n"); return -EREMOTEIO; } @@ -537,10 +543,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) { - struct i2c_msg msg = { .addr = priv->cfg->i2c_address, + struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = len }; - if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", (int)len); return -EREMOTEIO; @@ -550,10 +556,10 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) { - struct i2c_msg msg = { .addr = priv->cfg->i2c_address, + struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = buf, .len = len }; - if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); return -EREMOTEIO; } @@ -570,7 +576,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe) printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", XC5000_DEFAULT_FIRMWARE); - ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); + ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev); if (ret) { printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); ret = XC_RESULT_RESET_FAILURE; @@ -908,9 +914,19 @@ static int xc5000_init(struct dvb_frontend *fe) static int xc5000_release(struct dvb_frontend *fe) { + struct xc5000_priv *priv = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); - kfree(fe->tuner_priv); + + mutex_lock(&xc5000_list_mutex); + + if (priv) + hybrid_tuner_release_state(priv); + + mutex_unlock(&xc5000_list_mutex); + fe->tuner_priv = NULL; + return 0; } @@ -938,26 +954,41 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, struct xc5000_config *cfg, void *devptr) { struct xc5000_priv *priv = NULL; + int instance; u16 id = 0; - dprintk(1, "%s()\n", __func__); + dprintk(1, "%s(%d-%04x)\n", __func__, + i2c ? i2c_adapter_id(i2c) : -1, + cfg ? cfg->i2c_address : -1); - priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; + mutex_lock(&xc5000_list_mutex); - priv->cfg = cfg; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->i2c = i2c; - priv->devptr = devptr; + instance = hybrid_tuner_request_state(struct xc5000_priv, priv, + hybrid_tuner_instance_list, + i2c, cfg->i2c_address, "xc5000"); + switch (instance) { + case 0: + goto fail; + break; + case 1: + /* new tuner instance */ + priv->cfg = cfg; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->devptr = devptr; + + fe->tuner_priv = priv; + break; + default: + /* existing tuner instance */ + fe->tuner_priv = priv; + break; + } /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ - if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { - kfree(priv); - return NULL; - } + if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) + goto fail; switch(id) { case XC_PRODUCT_ID_FW_LOADED: @@ -978,19 +1009,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, printk(KERN_ERR "xc5000: Device not found at addr 0x%02x (0x%x)\n", cfg->i2c_address, id); - kfree(priv); - return NULL; + goto fail; } + mutex_unlock(&xc5000_list_mutex); + memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, sizeof(struct dvb_tuner_ops)); - fe->tuner_priv = priv; - if (xc5000_load_fw_on_attach) xc5000_init(fe); return fe; +fail: + mutex_unlock(&xc5000_list_mutex); + + xc5000_release(fe); + return NULL; } EXPORT_SYMBOL(xc5000_attach); -- GitLab From 2a6003c20771ca16fc6386b5fd258df2f2fa8232 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 6 Sep 2008 13:54:45 -0300 Subject: [PATCH 4081/5416] V4L/DVB (8950): xc5000: prevent an OOPS if analog driver is unloaded while digital is in use Prevent an OOPS if xc5000_attach was called by tuner.ko before being called by the DVB adapter driver. The OOPS occurs when a digital tune request is made after tuner.ko is unloaded. When tuner.ko is unloaded, it takes the xc5000_config structure with it. Rather than storing a pointer to the xc5000_config structure, just store the if_khz and tuner_callback inside the xc5000_priv internal state structure. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 1850f7b7d96..72efc656ad0 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -50,17 +50,17 @@ static LIST_HEAD(hybrid_tuner_instance_list); #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 struct xc5000_priv { - struct xc5000_config *cfg; - struct tuner_i2c_props i2c_props; struct list_head hybrid_tuner_instance_list; + u32 if_khz; u32 freq_hz; u32 bandwidth; u8 video_standard; u8 rf_mode; void *devptr; + int (*tuner_callback) (void *priv, int command, int arg); }; /* Misc Defines */ @@ -233,9 +233,8 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); - if (priv->cfg->tuner_callback) { - ret = priv->cfg->tuner_callback(priv->devptr, - XC5000_TUNER_RESET, 0); + if (priv->tuner_callback) { + ret = priv->tuner_callback(priv->devptr, XC5000_TUNER_RESET, 0); if (ret) printk(KERN_ERR "xc5000: reset failed\n"); } else @@ -692,10 +691,10 @@ static int xc5000_set_params(struct dvb_frontend *fe, return -EREMOTEIO; } - ret = xc_set_IF_frequency(priv, priv->cfg->if_khz); + ret = xc_set_IF_frequency(priv, priv->if_khz); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", - priv->cfg->if_khz); + priv->if_khz); return -EIO; } @@ -972,9 +971,10 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, break; case 1: /* new tuner instance */ - priv->cfg = cfg; priv->bandwidth = BANDWIDTH_6_MHZ; priv->devptr = devptr; + priv->if_khz = cfg->if_khz; + priv->tuner_callback = cfg->tuner_callback; fe->tuner_priv = priv; break; -- GitLab From 30650961907368b1077cade35455fe931b14da6b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 6 Sep 2008 14:56:58 -0300 Subject: [PATCH 4082/5416] V4L/DVB (8951): xc5000: dont pass devptr in xc5000_attach() Dont pass devptr in xc5000_attach, dont store it in xc5000_priv. This pointer is passed into the tuner_callback function, which always expects a pointer to fe->dvb->priv or i2c_adapter->algo_data. This prevents future possible bugs in new drivers, such as using a "devptr" other that the standard fe->dvb->priv in a DVB driver. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 9 +++++---- drivers/media/common/tuners/xc5000.h | 6 ++---- drivers/media/video/au0828/au0828-dvb.c | 5 ++--- drivers/media/video/cx23885/cx23885-dvb.c | 8 ++++---- drivers/media/video/cx88/cx88-dvb.c | 12 ++---------- drivers/media/video/tuner-core.c | 3 +-- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 72efc656ad0..ccc4dae4126 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -59,7 +59,6 @@ struct xc5000_priv { u8 video_standard; u8 rf_mode; - void *devptr; int (*tuner_callback) (void *priv, int command, int arg); }; @@ -234,7 +233,10 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); if (priv->tuner_callback) { - ret = priv->tuner_callback(priv->devptr, XC5000_TUNER_RESET, 0); + ret = priv->tuner_callback(((fe->dvb) && (fe->dvb->priv)) ? + fe->dvb->priv : + priv->i2c_props.adap->algo_data, + XC5000_TUNER_RESET, 0); if (ret) printk(KERN_ERR "xc5000: reset failed\n"); } else @@ -950,7 +952,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg, void *devptr) + struct xc5000_config *cfg) { struct xc5000_priv *priv = NULL; int instance; @@ -972,7 +974,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, case 1: /* new tuner instance */ priv->bandwidth = BANDWIDTH_6_MHZ; - priv->devptr = devptr; priv->if_khz = cfg->if_khz; priv->tuner_callback = cfg->tuner_callback; diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index 5389f740945..fa0321cfd17 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -49,13 +49,11 @@ struct xc5000_config { (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg, - void *devptr); + struct xc5000_config *cfg); #else static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg, - void *devptr) + struct xc5000_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index ba94be7e0ac..96246959dce 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -358,9 +358,8 @@ int au0828_dvb_register(struct au0828_dev *dev) &hauppauge_hvr950q_config, &dev->i2c_adap); if (dvb->frontend != NULL) - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_hvr950q_tunerconfig, dev); + dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, + &hauppauge_hvr950q_tunerconfig); break; case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: dvb->frontend = dvb_attach(au8522_attach, diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index b85cb39b101..f462efde72a 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -390,8 +390,8 @@ static int dvb_register(struct cx23885_tsport *port) &dev->i2c_bus[0].i2c_adap); if (port->dvb.frontend != NULL) dvb_attach(xc5000_attach, port->dvb.frontend, - &i2c_bus->i2c_adap, - &hauppauge_hvr1500q_tunerconfig, port); + &i2c_bus->i2c_adap, + &hauppauge_hvr1500q_tunerconfig); break; case CX23885_BOARD_HAUPPAUGE_HVR1500: i2c_bus = &dev->i2c_bus[1]; @@ -471,8 +471,8 @@ static int dvb_register(struct cx23885_tsport *port) &i2c_bus->i2c_adap); if (port->dvb.frontend != NULL) dvb_attach(xc5000_attach, port->dvb.frontend, - &i2c_bus->i2c_adap, - &dvico_xc5000_tunerconfig, port); + &i2c_bus->i2c_adap, + &dvico_xc5000_tunerconfig); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { i2c_bus = &dev->i2c_bus[port->nr - 1]; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index d96173ff1db..07270b77ed8 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -813,13 +813,9 @@ static int dvb_register(struct cx8802_dev *dev) &pinnacle_pctv_hd_800i_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { - /* tuner_config.video_dev must point to - * i2c_adap.algo_data - */ if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, - &pinnacle_pctv_hd_800i_tuner_config, - core->i2c_adap.algo_data)) + &pinnacle_pctv_hd_800i_tuner_config)) goto frontend_detach; } break; @@ -874,13 +870,9 @@ static int dvb_register(struct cx8802_dev *dev) &dvico_fusionhdtv7_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { - /* tuner_config.video_dev must point to - * i2c_adap.algo_data - */ if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, - &dvico_fusionhdtv7_tuner_config, - core->i2c_adap.algo_data)) + &dvico_fusionhdtv7_tuner_config)) goto frontend_detach; } break; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index d806a3556ee..39c7b9b835a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -452,8 +452,7 @@ static void set_type(struct i2c_client *c, unsigned int type, xc5000_cfg.if_khz = 5380; xc5000_cfg.tuner_callback = t->tuner_callback; if (!dvb_attach(xc5000_attach, - &t->fe, t->i2c->adapter, &xc5000_cfg, - c->adapter->algo_data)) + &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; xc_tuner_ops = &t->fe.ops.tuner_ops; -- GitLab From c9166977efdb6480dbac13df226113eb75026606 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Tue, 9 Sep 2008 10:10:52 -0300 Subject: [PATCH 4083/5416] V4L/DVB: remove unused #include The file(s) below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/media/video/pwc/pwc-ctrl.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-ctrl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index dbc56074255..c6653021019 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -41,7 +41,6 @@ #include #endif #include -#include #include "pwc.h" #include "pwc-uncompress.h" -- GitLab From c87994db017a5a28af2edd043669a371d800919e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 11 Sep 2008 09:33:26 -0300 Subject: [PATCH 4084/5416] V4L/DVB (8954): common/tuners: Drop code after return or goto The break after the return or goto serves no purpose. Signed-off-by: Julia Lawall Reviewed-by: Richard Genoud Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5007t.c | 1 - drivers/media/common/tuners/tda18271-fe.c | 1 - drivers/media/common/tuners/tda9887.c | 1 - drivers/media/common/tuners/tuner-simple.c | 1 - 4 files changed, 4 deletions(-) diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index cb25e43502f..64379f2bf23 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -979,7 +979,6 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe, switch (instance) { case 0: goto fail; - break; case 1: /* new tuner instance */ state->config = cfg; diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 93063c6fbbf..1b48b5d0bf1 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1155,7 +1155,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, switch (instance) { case 0: goto fail; - break; case 1: /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c index 72abf0b7348..ff1788cc5d4 100644 --- a/drivers/media/common/tuners/tda9887.c +++ b/drivers/media/common/tuners/tda9887.c @@ -686,7 +686,6 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, case 0: mutex_unlock(&tda9887_list_mutex); return NULL; - break; case 1: fe->analog_demod_priv = priv; priv->mode = T_STANDBY; diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index fc3a6a9d7c2..2a1aac1cc75 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -1040,7 +1040,6 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, case 0: mutex_unlock(&tuner_simple_list_mutex); return NULL; - break; case 1: fe->tuner_priv = priv; -- GitLab From 176c2f34157a8d8b252c8f0bc242457c971b06a1 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 7 Sep 2008 12:49:59 -0300 Subject: [PATCH 4085/5416] V4L/DVB (8956): bttv: Turn video_nr, vbi_nr and radio_nr into arrays With video_nr, vbi_nr and radio_nr being simple integers, it is not possible to use these parameters on a system with multiple bttv adapters (which happens to be my case.) video_register_device() will always fail on the second and later adapters. Turn these parameters into arrays, as many other V4L drivers are already doing, so that they can be used on such systems. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 26 +++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index ef205cd2a2a..9bb247cdc28 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -76,9 +76,9 @@ static unsigned int gbuffers = 8; static unsigned int gbufsize = 0x208000; static unsigned int reset_crop = 1; -static int video_nr = -1; -static int radio_nr = -1; -static int vbi_nr = -1; +static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; +static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; +static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; static int debug_latency; static unsigned int fdsr; @@ -108,9 +108,6 @@ module_param(irq_debug, int, 0644); module_param(debug_latency, int, 0644); module_param(fdsr, int, 0444); -module_param(video_nr, int, 0444); -module_param(radio_nr, int, 0444); -module_param(vbi_nr, int, 0444); module_param(gbuffers, int, 0444); module_param(gbufsize, int, 0444); module_param(reset_crop, int, 0444); @@ -130,7 +127,10 @@ module_param(uv_ratio, int, 0444); module_param(full_luma_range, int, 0444); module_param(coring, int, 0444); -module_param_array(radio, int, NULL, 0444); +module_param_array(radio, int, NULL, 0444); +module_param_array(video_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); @@ -152,6 +152,9 @@ MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); +MODULE_PARM_DESC(video_nr, "video device numbers"); +MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); +MODULE_PARM_DESC(radio_nr, "radio device numbers"); MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); @@ -4252,7 +4255,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (NULL == btv->video_dev) goto err; - if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) + if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, + video_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", btv->c.nr,btv->video_dev->minor & 0x1f); @@ -4268,7 +4272,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (NULL == btv->vbi_dev) goto err; - if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, + vbi_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", btv->c.nr,btv->vbi_dev->minor & 0x1f); @@ -4279,7 +4284,8 @@ static int __devinit bttv_register_video(struct bttv *btv) btv->radio_dev = vdev_init(btv, &radio_template, "radio"); if (NULL == btv->radio_dev) goto err; - if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) + if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, + radio_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device radio%d\n", btv->c.nr,btv->radio_dev->minor & 0x1f); -- GitLab From 4c522e74902a1fa15a7ec5e5a3325b250afa54ab Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Wed, 10 Sep 2008 08:22:06 -0300 Subject: [PATCH 4086/5416] V4L/DVB (8959): include into linux/ivtv.h linux/videodev2.h defines enum v4l2_buf_type and struct v4l2_rect Signed-off-by: Kirill A. Shutemov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/linux/ivtv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/ivtv.h b/include/linux/ivtv.h index 17ca64b5a66..f2720280b9e 100644 --- a/include/linux/ivtv.h +++ b/include/linux/ivtv.h @@ -23,6 +23,7 @@ #include #include +#include /* ivtv knows several distinct output modes: MPEG streaming, YUV streaming, YUV updates through user DMA and the passthrough -- GitLab From 8ca4dae3e601b527cb099ef72d821d7af075f8ae Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 7 Sep 2008 05:58:54 -0300 Subject: [PATCH 4087/5416] V4L/DVB (8962): zr36067: VIDIOC_S_FMT returns the colorspace value Ioctl VIDIOC_S_FMT is supposed to fill the colorspace value in the returned buffer. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index f0af9b7f8ff..25de7631443 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -2917,6 +2917,8 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.pix.bytesperline = 0; fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size; + fmt->fmt.pix.colorspace = + V4L2_COLORSPACE_SMPTE170M; /* we hereby abuse this variable to show that * we're gonna do mjpeg capture */ @@ -2976,6 +2978,8 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; + fmt->fmt.pix.colorspace = + fh->v4l_settings.format->colorspace; if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) fmt->fmt.pix.field = -- GitLab From 26dc4d0487bb8b8de32d09c18a83c63d622156f2 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sun, 21 Sep 2008 20:50:11 -0300 Subject: [PATCH 4088/5416] V4L/DVB (8964): dvb/budget: push adapter_nr mod option down to individual drivers adapter_nr mod option does not make sense for budget-core since it is only common code shared by all budget drivers Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 6 +++++- drivers/media/dvb/ttpci/budget-ci.c | 5 ++++- drivers/media/dvb/ttpci/budget-core.c | 6 ++---- drivers/media/dvb/ttpci/budget-patch.c | 7 +++++-- drivers/media/dvb/ttpci/budget.c | 5 ++++- drivers/media/dvb/ttpci/budget.h | 2 +- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 839c94101b4..1032ea77837 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -57,6 +57,8 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct budget_av { struct budget budget; struct video_device *vd; @@ -1127,7 +1129,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio dev->ext_priv = budget_av; - if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) { + err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE, + adapter_nr); + if (err) { kfree(budget_av); return err; } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 38dd5cf1aed..0a5aad45435 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -92,6 +92,8 @@ static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct budget_ci_ir { struct input_dev *dev; struct tasklet_struct msp430_irq_tasklet; @@ -1183,7 +1185,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio dev->ext_priv = budget_ci; - err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); + err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE, + adapter_nr); if (err) goto out2; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 6f4ddb643fe..ba18e56d5f1 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -57,8 +57,6 @@ module_param_named(bufsize, dma_buffer_size, int, 0444); MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - /**************************************************************************** * TT budget / WinTV Nova ****************************************************************************/ @@ -411,7 +409,7 @@ static void budget_unregister(struct budget *budget) int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, - struct module *owner) + struct module *owner, short *adapter_nums) { int ret = 0; struct budget_info *bi = info->ext_priv; @@ -474,7 +472,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, - owner, &budget->dev->pci->dev, adapter_nr); + owner, &budget->dev->pci->dev, adapter_nums); if (ret < 0) return ret; diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index bbd234fe11c..60136688a9a 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -39,6 +39,8 @@ #include "bsru6.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define budget_patch budget static struct saa7146_extension budget_extension; @@ -592,8 +594,9 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte dprintk(2, "budget: %p\n", budget); - if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { - kfree (budget); + err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); + if (err) { + kfree(budget); return err; } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index d95203d5540..1638e1d9f53 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -52,6 +52,8 @@ static int diseqc_method; module_param(diseqc_method, int, 0444); MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static void Set22K (struct budget *budget, int state) { struct saa7146_dev *dev=budget->dev; @@ -598,7 +600,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ dev->ext_priv = budget; - if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { + err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); + if (err) { printk("==> failed\n"); kfree (budget); return err; diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index dd450b739bf..86435bf1626 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -109,7 +109,7 @@ static struct saa7146_pci_extension_data x_var = { \ extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, - struct module *owner); + struct module *owner, short *adapter_nums); extern void ttpci_budget_init_hooks(struct budget *budget); extern int ttpci_budget_deinit(struct budget *budget); extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); -- GitLab From de3e3b82a6d15264798d4e36f42abaa69f53ca06 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Thu, 18 Sep 2008 17:50:15 -0300 Subject: [PATCH 4089/5416] V4L/DVB: pxa-camera: Unsigned dma_chans[] cannot be negative Unsigned dma_chans[] cannot be negative Also the third time dma_chans[0] < 0 was tested instead of dma_chans[2] Signed-off-by: Roel Kluin Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 14569b59138..eb6be580292 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -1120,31 +1120,31 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->dev = &pdev->dev; /* request dma */ - pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, - pxa_camera_dma_irq_y, pcdev); - if (pcdev->dma_chans[0] < 0) { + err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, + pxa_camera_dma_irq_y, pcdev); + if (err < 0) { dev_err(pcdev->dev, "Can't request DMA for Y\n"); - err = -ENOMEM; goto exit_iounmap; } + pcdev->dma_chans[0] = err; dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); - pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH, - pxa_camera_dma_irq_u, pcdev); - if (pcdev->dma_chans[1] < 0) { + err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, + pxa_camera_dma_irq_u, pcdev); + if (err < 0) { dev_err(pcdev->dev, "Can't request DMA for U\n"); - err = -ENOMEM; goto exit_free_dma_y; } + pcdev->dma_chans[1] = err; dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); - pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH, - pxa_camera_dma_irq_v, pcdev); - if (pcdev->dma_chans[0] < 0) { + err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, + pxa_camera_dma_irq_v, pcdev); + if (err < 0) { dev_err(pcdev->dev, "Can't request DMA for V\n"); - err = -ENOMEM; goto exit_free_dma_u; } + pcdev->dma_chans[2] = err; dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; -- GitLab From ef80bfeb30f82fb718731a3323a75ae08396a4ea Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 16 Sep 2008 02:15:30 -0300 Subject: [PATCH 4090/5416] V4L/DVB (8968): replace xc3028 firmware filenames with defined default firmware names Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 2 +- drivers/media/video/cx23885/cx23885-dvb.c | 8 ++++---- drivers/media/video/cx88/cx88-dvb.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index bffb4438038..1a746127cbd 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -773,7 +773,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) .callback = dvico_bluebird_xc2028_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028-v27.fw", + .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f462efde72a..3b54f139180 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -407,7 +407,7 @@ static int dvb_register(struct cx23885_tsport *port) .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028-v27.fw", + .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .scode_table = XC3028_FE_OREN538, }; @@ -447,7 +447,7 @@ static int dvb_register(struct cx23885_tsport *port) .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028L-v36.fw", + .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = 5000, .d2633 = 1 @@ -489,7 +489,7 @@ static int dvb_register(struct cx23885_tsport *port) .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028-v27.fw", + .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; @@ -516,7 +516,7 @@ static int dvb_register(struct cx23885_tsport *port) .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028-v27.fw", + .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 07270b77ed8..9f0e5b3c515 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -831,7 +831,7 @@ static int dvb_register(struct cx8802_dev *dev) .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { - .fname = "xc3028-v27.fw", + .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .scode_table = XC3028_FE_OREN538, }; -- GitLab From 6e623433f7f566d8aca64c519a19c2f7bbb686be Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Sep 2008 14:34:31 -0300 Subject: [PATCH 4091/5416] V4L/DVB (8970): mt2060: implement I2C-gate control - implement I2C-gate control Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mt2060.c | 38 ++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c index 1305b0e63ce..12206d75dd4 100644 --- a/drivers/media/common/tuners/mt2060.c +++ b/drivers/media/common/tuners/mt2060.c @@ -170,6 +170,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame b[0] = REG_LO1B1; b[1] = 0xFF; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + mt2060_writeregs(priv,b,2); freq = params->frequency / 1000; // Hz -> kHz @@ -233,6 +236,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame i++; } while (i<10); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + return ret; } @@ -296,13 +302,35 @@ static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) static int mt2060_init(struct dvb_frontend *fe) { struct mt2060_priv *priv = fe->tuner_priv; - return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33); + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = mt2060_writereg(priv, REG_VGAG, + (priv->cfg->clock_out << 6) | 0x33); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return ret; } static int mt2060_sleep(struct dvb_frontend *fe) { struct mt2060_priv *priv = fe->tuner_priv; - return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30); + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = mt2060_writereg(priv, REG_VGAG, + (priv->cfg->clock_out << 6) | 0x30); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return ret; } static int mt2060_release(struct dvb_frontend *fe) @@ -344,6 +372,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter priv->i2c = i2c; priv->if1_freq = if1; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) { kfree(priv); return NULL; @@ -360,6 +391,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter mt2060_calibrate(priv); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + return fe; } EXPORT_SYMBOL(mt2060_attach); -- GitLab From 825b96708054ca16d6e4d56a29326d3b2cdd697d Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Sep 2008 15:01:52 -0300 Subject: [PATCH 4092/5416] V4L/DVB (8971): initial driver for af9013 demodulator - initial driver for the Afatech AF9013 demodulator Signed-off-by: Antti Palosaari [mchehab.redhat.com: having a global var called 'debug' is not a good idea. rename it to af9013_debug] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 6 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/af9013.c | 1691 +++++++++++++++++++++ drivers/media/dvb/frontends/af9013.h | 107 ++ drivers/media/dvb/frontends/af9013_priv.h | 869 +++++++++++ 5 files changed, 2674 insertions(+) create mode 100644 drivers/media/dvb/frontends/af9013.c create mode 100644 drivers/media/dvb/frontends/af9013.h create mode 100644 drivers/media/dvb/frontends/af9013_priv.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index e2444f270f0..097d9f00144 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -398,4 +398,10 @@ config DVB_DUMMY_FE tristate "Dummy frontend driver" default n +config DVB_AF9013 + tristate "Afatech AF9013 demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index ca24618d5da..1b547888624 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -50,3 +50,4 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o +obj-$(CONFIG_DVB_AF9013) += af9013.o diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c new file mode 100644 index 00000000000..9f2129d544c --- /dev/null +++ b/drivers/media/dvb/frontends/af9013.c @@ -0,0 +1,1691 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 "dvb_frontend.h" +#include "af9013_priv.h" +#include "af9013.h" + +int af9013_debug; + +struct af9013_state { + struct i2c_adapter *i2c; + struct dvb_frontend frontend; + + struct af9013_config config; + + u16 signal_strength; + u32 ber; + u32 ucblocks; + u16 snr; + u32 frequency; + unsigned long next_statistics_check; +}; + +static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; + +static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg, + u8 *val, u8 len) +{ + u8 buf[3+len]; + struct i2c_msg msg = { + .addr = state->config.demod_address, + .flags = 0, + .len = sizeof(buf), + .buf = buf }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = mbox; + memcpy(&buf[3], val, len); + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + warn("I2C write failed reg:%04x len:%d", reg, len); + return -EREMOTEIO; + } + return 0; +} + +static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val, + u8 len) +{ + u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7); + return af9013_write_regs(state, mbox, reg, val, len); +} + +static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val, + u8 len) +{ + u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7); + return af9013_write_regs(state, mbox, reg, val, len); +} + +/* write single register */ +static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val) +{ + return af9013_write_ofdm_regs(state, reg, &val, 1); +} + +/* read single register */ +static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val) +{ + u8 obuf[3] = { reg >> 8, reg & 0xff, 0 }; + u8 ibuf[1]; + struct i2c_msg msg[2] = { + { + .addr = state->config.demod_address, + .flags = 0, + .len = sizeof(obuf), + .buf = obuf + }, { + .addr = state->config.demod_address, + .flags = I2C_M_RD, + .len = sizeof(ibuf), + .buf = ibuf + } + }; + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + warn("I2C read failed reg:%04x", reg); + return -EREMOTEIO; + } + *val = ibuf[0]; + return 0; +} + +static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos, + u8 len, u8 val) +{ + int ret; + u8 tmp, mask; + + ret = af9013_read_reg(state, reg, &tmp); + if (ret) + return ret; + + mask = regmask[len - 1] << pos; + tmp = (tmp & ~mask) | ((val << pos) & mask); + + return af9013_write_reg(state, reg, tmp); +} + +static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos, + u8 len, u8 *val) +{ + int ret; + u8 tmp; + + ret = af9013_read_reg(state, reg, &tmp); + if (ret) + return ret; + *val = (tmp >> pos) & regmask[len - 1]; + return 0; +} + +static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) +{ + int ret; + u8 pos; + u16 addr; + deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval); + +/* GPIO0 & GPIO1 0xd735 + GPIO2 & GPIO3 0xd736 */ + + switch (gpio) { + case 0: + case 1: + addr = 0xd735; + break; + case 2: + case 3: + addr = 0xd736; + break; + + default: + err("invalid gpio:%d\n", gpio); + ret = -EINVAL; + goto error; + }; + + switch (gpio) { + case 0: + case 2: + pos = 0; + break; + case 1: + case 3: + default: + pos = 4; + break; + }; + + ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval); + +error: + return ret; +} + +static u32 af913_div(u32 a, u32 b, u32 x) +{ + u32 r = 0, c = 0, i; + deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x); + + if (a > b) { + c = a / b; + a = a - c * b; + } + + for (i = 0; i < x; i++) { + if (a >= b) { + r += 1; + a -= b; + } + a <<= 1; + r <<= 1; + } + r = (c << (u32)x) + r; + + deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r); + return r; +} + +static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw) +{ + int ret = 0; + u8 i = 0; + u8 buf[24]; + u32 ns_coeff1_2048nu; + u32 ns_coeff1_8191nu; + u32 ns_coeff1_8192nu; + u32 ns_coeff1_8193nu; + u32 ns_coeff2_2k; + u32 ns_coeff2_8k; + + deb_info("%s: adc_clock:%d bw:%d\n", __func__, + state->config.adc_clock, bw); + + switch (state->config.adc_clock) { + case 28800: /* 28.800 MHz */ + switch (bw) { + case BANDWIDTH_6_MHZ: + ns_coeff1_2048nu = 0x01e79e7a; + ns_coeff1_8191nu = 0x0079eb6e; + ns_coeff1_8192nu = 0x0079e79e; + ns_coeff1_8193nu = 0x0079e3cf; + ns_coeff2_2k = 0x00f3cf3d; + ns_coeff2_8k = 0x003cf3cf; + break; + case BANDWIDTH_7_MHZ: + ns_coeff1_2048nu = 0x0238e38e; + ns_coeff1_8191nu = 0x008e3d55; + ns_coeff1_8192nu = 0x008e38e4; + ns_coeff1_8193nu = 0x008e3472; + ns_coeff2_2k = 0x011c71c7; + ns_coeff2_8k = 0x00471c72; + break; + case BANDWIDTH_8_MHZ: + ns_coeff1_2048nu = 0x028a28a3; + ns_coeff1_8191nu = 0x00a28f3d; + ns_coeff1_8192nu = 0x00a28a29; + ns_coeff1_8193nu = 0x00a28514; + ns_coeff2_2k = 0x01451451; + ns_coeff2_8k = 0x00514514; + break; + default: + ret = -EINVAL; + } + break; + case 20480: /* 20.480 MHz */ + switch (bw) { + case BANDWIDTH_6_MHZ: + ns_coeff1_2048nu = 0x02adb6dc; + ns_coeff1_8191nu = 0x00ab7313; + ns_coeff1_8192nu = 0x00ab6db7; + ns_coeff1_8193nu = 0x00ab685c; + ns_coeff2_2k = 0x0156db6e; + ns_coeff2_8k = 0x0055b6dc; + break; + case BANDWIDTH_7_MHZ: + ns_coeff1_2048nu = 0x03200001; + ns_coeff1_8191nu = 0x00c80640; + ns_coeff1_8192nu = 0x00c80000; + ns_coeff1_8193nu = 0x00c7f9c0; + ns_coeff2_2k = 0x01900000; + ns_coeff2_8k = 0x00640000; + break; + case BANDWIDTH_8_MHZ: + ns_coeff1_2048nu = 0x03924926; + ns_coeff1_8191nu = 0x00e4996e; + ns_coeff1_8192nu = 0x00e49249; + ns_coeff1_8193nu = 0x00e48b25; + ns_coeff2_2k = 0x01c92493; + ns_coeff2_8k = 0x00724925; + break; + default: + ret = -EINVAL; + } + break; + case 28000: /* 28.000 MHz */ + switch (bw) { + case BANDWIDTH_6_MHZ: + ns_coeff1_2048nu = 0x01f58d10; + ns_coeff1_8191nu = 0x007d672f; + ns_coeff1_8192nu = 0x007d6344; + ns_coeff1_8193nu = 0x007d5f59; + ns_coeff2_2k = 0x00fac688; + ns_coeff2_8k = 0x003eb1a2; + break; + case BANDWIDTH_7_MHZ: + ns_coeff1_2048nu = 0x02492492; + ns_coeff1_8191nu = 0x00924db7; + ns_coeff1_8192nu = 0x00924925; + ns_coeff1_8193nu = 0x00924492; + ns_coeff2_2k = 0x01249249; + ns_coeff2_8k = 0x00492492; + break; + case BANDWIDTH_8_MHZ: + ns_coeff1_2048nu = 0x029cbc15; + ns_coeff1_8191nu = 0x00a7343f; + ns_coeff1_8192nu = 0x00a72f05; + ns_coeff1_8193nu = 0x00a729cc; + ns_coeff2_2k = 0x014e5e0a; + ns_coeff2_8k = 0x00539783; + break; + default: + ret = -EINVAL; + } + break; + case 25000: /* 25.000 MHz */ + switch (bw) { + case BANDWIDTH_6_MHZ: + ns_coeff1_2048nu = 0x0231bcb5; + ns_coeff1_8191nu = 0x008c7391; + ns_coeff1_8192nu = 0x008c6f2d; + ns_coeff1_8193nu = 0x008c6aca; + ns_coeff2_2k = 0x0118de5b; + ns_coeff2_8k = 0x00463797; + break; + case BANDWIDTH_7_MHZ: + ns_coeff1_2048nu = 0x028f5c29; + ns_coeff1_8191nu = 0x00a3dc29; + ns_coeff1_8192nu = 0x00a3d70a; + ns_coeff1_8193nu = 0x00a3d1ec; + ns_coeff2_2k = 0x0147ae14; + ns_coeff2_8k = 0x0051eb85; + break; + case BANDWIDTH_8_MHZ: + ns_coeff1_2048nu = 0x02ecfb9d; + ns_coeff1_8191nu = 0x00bb44c1; + ns_coeff1_8192nu = 0x00bb3ee7; + ns_coeff1_8193nu = 0x00bb390d; + ns_coeff2_2k = 0x01767dce; + ns_coeff2_8k = 0x005d9f74; + break; + default: + ret = -EINVAL; + } + break; + default: + err("invalid xtal"); + return -EINVAL; + } + if (ret) { + err("invalid bandwidth"); + return ret; + } + + buf[i++] = (u8) ((ns_coeff1_2048nu & 0x03000000) >> 24); + buf[i++] = (u8) ((ns_coeff1_2048nu & 0x00ff0000) >> 16); + buf[i++] = (u8) ((ns_coeff1_2048nu & 0x0000ff00) >> 8); + buf[i++] = (u8) ((ns_coeff1_2048nu & 0x000000ff)); + buf[i++] = (u8) ((ns_coeff2_2k & 0x01c00000) >> 22); + buf[i++] = (u8) ((ns_coeff2_2k & 0x003fc000) >> 14); + buf[i++] = (u8) ((ns_coeff2_2k & 0x00003fc0) >> 6); + buf[i++] = (u8) ((ns_coeff2_2k & 0x0000003f)); + buf[i++] = (u8) ((ns_coeff1_8191nu & 0x03000000) >> 24); + buf[i++] = (u8) ((ns_coeff1_8191nu & 0x00ffc000) >> 16); + buf[i++] = (u8) ((ns_coeff1_8191nu & 0x0000ff00) >> 8); + buf[i++] = (u8) ((ns_coeff1_8191nu & 0x000000ff)); + buf[i++] = (u8) ((ns_coeff1_8192nu & 0x03000000) >> 24); + buf[i++] = (u8) ((ns_coeff1_8192nu & 0x00ffc000) >> 16); + buf[i++] = (u8) ((ns_coeff1_8192nu & 0x0000ff00) >> 8); + buf[i++] = (u8) ((ns_coeff1_8192nu & 0x000000ff)); + buf[i++] = (u8) ((ns_coeff1_8193nu & 0x03000000) >> 24); + buf[i++] = (u8) ((ns_coeff1_8193nu & 0x00ffc000) >> 16); + buf[i++] = (u8) ((ns_coeff1_8193nu & 0x0000ff00) >> 8); + buf[i++] = (u8) ((ns_coeff1_8193nu & 0x000000ff)); + buf[i++] = (u8) ((ns_coeff2_8k & 0x01c00000) >> 22); + buf[i++] = (u8) ((ns_coeff2_8k & 0x003fc000) >> 14); + buf[i++] = (u8) ((ns_coeff2_8k & 0x00003fc0) >> 6); + buf[i++] = (u8) ((ns_coeff2_8k & 0x0000003f)); + + deb_info("%s: coeff:", __func__); + debug_dump(buf, sizeof(buf), deb_info); + + /* program */ + for (i = 0; i < sizeof(buf); i++) { + ret = af9013_write_reg(state, 0xae00 + i, buf[i]); + if (ret) + break; + } + + return ret; +} + +static int af9013_set_adc_ctrl(struct af9013_state *state) +{ + int ret; + u8 buf[3], tmp, i; + u32 adc_cw; + + deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock); + + /* adc frequency type */ + switch (state->config.adc_clock) { + case 28800: /* 28.800 MHz */ + tmp = 0; + break; + case 20480: /* 20.480 MHz */ + tmp = 1; + break; + case 28000: /* 28.000 MHz */ + tmp = 2; + break; + case 25000: /* 25.000 MHz */ + tmp = 3; + break; + default: + err("invalid xtal"); + return -EINVAL; + } + + adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul); + + buf[0] = (u8) ((adc_cw & 0x000000ff)); + buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8); + buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16); + + deb_info("%s: adc_cw:", __func__); + debug_dump(buf, sizeof(buf), deb_info); + + /* program */ + for (i = 0; i < sizeof(buf); i++) { + ret = af9013_write_reg(state, 0xd180 + i, buf[i]); + if (ret) + goto error; + } + ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp); +error: + return ret; +} + +static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw) +{ + int ret; + u16 addr; + u8 buf[3], i, j; + u32 adc_freq, freq_cw; + s8 bfs_spec_inv; + int if_sample_freq; + + for (j = 0; j < 3; j++) { + if (j == 0) { + addr = 0xd140; /* fcw normal */ + bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1; + } else if (j == 1) { + addr = 0x9be7; /* fcw dummy ram */ + bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1; + } else { + addr = 0x9bea; /* fcw inverted */ + bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1; + } + + adc_freq = state->config.adc_clock * 1000; + if_sample_freq = state->config.tuner_if * 1000; + + /* TDA18271 uses different sampling freq for every bw */ + if (state->config.tuner == AF9013_TUNER_TDA18271) { + switch (bw) { + case BANDWIDTH_6_MHZ: + if_sample_freq = 3300000; /* 3.3 MHz */ + break; + case BANDWIDTH_7_MHZ: + if_sample_freq = 3800000; /* 3.8 MHz */ + break; + case BANDWIDTH_8_MHZ: + default: + if_sample_freq = 4300000; /* 4.3 MHz */ + break; + } + } + + while (if_sample_freq > (adc_freq / 2)) + if_sample_freq = if_sample_freq - adc_freq; + + if (if_sample_freq >= 0) + bfs_spec_inv = bfs_spec_inv * (-1); + else + if_sample_freq = if_sample_freq * (-1); + + freq_cw = af913_div(if_sample_freq, adc_freq, 23ul); + + if (bfs_spec_inv == -1) + freq_cw = 0x00800000 - freq_cw; + + buf[0] = (u8) ((freq_cw & 0x000000ff)); + buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8); + buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16); + + + deb_info("%s: freq_cw:", __func__); + debug_dump(buf, sizeof(buf), deb_info); + + /* program */ + for (i = 0; i < sizeof(buf); i++) { + ret = af9013_write_reg(state, addr++, buf[i]); + if (ret) + goto error; + } + } +error: + return ret; +} + +static int af9013_set_ofdm_params(struct af9013_state *state, + struct dvb_ofdm_parameters *params, u8 *auto_mode) +{ + int ret; + u8 i, buf[3] = {0, 0, 0}; + *auto_mode = 0; /* set if parameters are requested to auto set */ + + switch (params->transmission_mode) { + case TRANSMISSION_MODE_AUTO: + *auto_mode = 1; + case TRANSMISSION_MODE_2K: + break; + case TRANSMISSION_MODE_8K: + buf[0] |= (1 << 0); + break; + default: + return -EINVAL; + } + + switch (params->guard_interval) { + case GUARD_INTERVAL_AUTO: + *auto_mode = 1; + case GUARD_INTERVAL_1_32: + break; + case GUARD_INTERVAL_1_16: + buf[0] |= (1 << 2); + break; + case GUARD_INTERVAL_1_8: + buf[0] |= (2 << 2); + break; + case GUARD_INTERVAL_1_4: + buf[0] |= (3 << 2); + break; + default: + return -EINVAL; + } + + switch (params->hierarchy_information) { + case HIERARCHY_AUTO: + *auto_mode = 1; + case HIERARCHY_NONE: + break; + case HIERARCHY_1: + buf[0] |= (1 << 4); + break; + case HIERARCHY_2: + buf[0] |= (2 << 4); + break; + case HIERARCHY_4: + buf[0] |= (3 << 4); + break; + default: + return -EINVAL; + }; + + switch (params->constellation) { + case QAM_AUTO: + *auto_mode = 1; + case QPSK: + break; + case QAM_16: + buf[1] |= (1 << 6); + break; + case QAM_64: + buf[1] |= (2 << 6); + break; + default: + return -EINVAL; + } + + /* Use HP. How and which case we can switch to LP? */ + buf[1] |= (1 << 4); + + switch (params->code_rate_HP) { + case FEC_AUTO: + *auto_mode = 1; + case FEC_1_2: + break; + case FEC_2_3: + buf[2] |= (1 << 0); + break; + case FEC_3_4: + buf[2] |= (2 << 0); + break; + case FEC_5_6: + buf[2] |= (3 << 0); + break; + case FEC_7_8: + buf[2] |= (4 << 0); + break; + default: + return -EINVAL; + } + + switch (params->code_rate_LP) { + case FEC_AUTO: + /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO + by dvb_frontend.c for compatibility */ + if (params->hierarchy_information != HIERARCHY_NONE) + *auto_mode = 1; + case FEC_1_2: + break; + case FEC_2_3: + buf[2] |= (1 << 3); + break; + case FEC_3_4: + buf[2] |= (2 << 3); + break; + case FEC_5_6: + buf[2] |= (3 << 3); + break; + case FEC_7_8: + buf[2] |= (4 << 3); + break; + case FEC_NONE: + if (params->hierarchy_information == HIERARCHY_AUTO) + break; + default: + return -EINVAL; + } + + switch (params->bandwidth) { + case BANDWIDTH_6_MHZ: + break; + case BANDWIDTH_7_MHZ: + buf[1] |= (1 << 2); + break; + case BANDWIDTH_8_MHZ: + buf[1] |= (2 << 2); + break; + default: + return -EINVAL; + } + + /* program */ + for (i = 0; i < sizeof(buf); i++) { + ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]); + if (ret) + break; + } + + return ret; +} + +static int af9013_reset(struct af9013_state *state, u8 sleep) +{ + int ret; + u8 tmp, i; + deb_info("%s\n", __func__); + + /* enable OFDM reset */ + ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1); + if (ret) + goto error; + + /* start reset mechanism */ + ret = af9013_write_reg(state, 0xaeff, 1); + if (ret) + goto error; + + /* reset is done when bit 1 is set */ + for (i = 0; i < 150; i++) { + ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp); + if (ret) + goto error; + if (tmp) + break; /* reset done */ + msleep(10); + } + if (!tmp) + return -ETIMEDOUT; + + /* don't clear reset when going to sleep */ + if (!sleep) { + /* clear OFDM reset */ + ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0); + if (ret) + goto error; + + /* disable OFDM reset */ + ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0); + } +error: + return ret; +} + +static int af9013_power_ctrl(struct af9013_state *state, u8 onoff) +{ + int ret; + deb_info("%s: onoff:%d\n", __func__, onoff); + + if (onoff) { + /* power on */ + ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0); + if (ret) + goto error; + ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0); + if (ret) + goto error; + ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0); + } else { + /* power off */ + ret = af9013_reset(state, 1); + if (ret) + goto error; + ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1); + } +error: + return ret; +} + +static int af9013_lock_led(struct af9013_state *state, u8 onoff) +{ + deb_info("%s: onoff:%d\n", __func__, onoff); + + return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff); +} + +static int af9013_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + u8 auto_mode; /* auto set TPS */ + + deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency, + params->u.ofdm.bandwidth); + + state->frequency = params->frequency; + + /* program CFOE coefficients */ + ret = af9013_set_coeff(state, params->u.ofdm.bandwidth); + if (ret) + goto error; + + /* program frequency control */ + ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth); + if (ret) + goto error; + + /* clear TPS lock flag (inverted flag) */ + ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1); + if (ret) + goto error; + + /* clear MPEG2 lock flag */ + ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0); + if (ret) + goto error; + + /* empty channel function */ + ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0); + if (ret) + goto error; + + /* empty DVB-T channel function */ + ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0); + if (ret) + goto error; + + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, params); + + /* program TPS and bandwidth, check if auto mode needed */ + ret = af9013_set_ofdm_params(state, ¶ms->u.ofdm, &auto_mode); + if (ret) + goto error; + + if (auto_mode) { + /* clear easy mode flag */ + ret = af9013_write_reg(state, 0xaefd, 0); + deb_info("%s: auto TPS\n", __func__); + } else { + /* set easy mode flag */ + ret = af9013_write_reg(state, 0xaefd, 1); + if (ret) + goto error; + ret = af9013_write_reg(state, 0xaefe, 0); + deb_info("%s: manual TPS\n", __func__); + } + if (ret) + goto error; + + /* everything is set, lets try to receive channel - OFSM GO! */ + ret = af9013_write_reg(state, 0xffff, 0); + if (ret) + goto error; + +error: + return ret; +} + +static int af9013_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + u8 i, buf[3]; + deb_info("%s\n", __func__); + + /* read TPS registers */ + for (i = 0; i < 3; i++) { + ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]); + if (ret) + goto error; + } + + switch ((buf[1] >> 6) & 3) { + case 0: + p->u.ofdm.constellation = QPSK; + break; + case 1: + p->u.ofdm.constellation = QAM_16; + break; + case 2: + p->u.ofdm.constellation = QAM_64; + break; + } + + switch ((buf[0] >> 0) & 3) { + case 0: + p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; + break; + case 1: + p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; + } + + switch ((buf[0] >> 2) & 3) { + case 0: + p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; + break; + } + + switch ((buf[0] >> 4) & 7) { + case 0: + p->u.ofdm.hierarchy_information = HIERARCHY_NONE; + break; + case 1: + p->u.ofdm.hierarchy_information = HIERARCHY_1; + break; + case 2: + p->u.ofdm.hierarchy_information = HIERARCHY_2; + break; + case 3: + p->u.ofdm.hierarchy_information = HIERARCHY_4; + break; + } + + switch ((buf[2] >> 0) & 7) { + case 0: + p->u.ofdm.code_rate_HP = FEC_1_2; + break; + case 1: + p->u.ofdm.code_rate_HP = FEC_2_3; + break; + case 2: + p->u.ofdm.code_rate_HP = FEC_3_4; + break; + case 3: + p->u.ofdm.code_rate_HP = FEC_5_6; + break; + case 4: + p->u.ofdm.code_rate_HP = FEC_7_8; + break; + } + + switch ((buf[2] >> 3) & 7) { + case 0: + p->u.ofdm.code_rate_LP = FEC_1_2; + break; + case 1: + p->u.ofdm.code_rate_LP = FEC_2_3; + break; + case 2: + p->u.ofdm.code_rate_LP = FEC_3_4; + break; + case 3: + p->u.ofdm.code_rate_LP = FEC_5_6; + break; + case 4: + p->u.ofdm.code_rate_LP = FEC_7_8; + break; + } + + switch ((buf[1] >> 2) & 3) { + case 0: + p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + break; + case 1: + p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + break; + case 2: + p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + break; + } + + p->inversion = INVERSION_AUTO; + p->frequency = state->frequency; + +error: + return ret; +} + +static int af9013_update_ber_unc(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + u8 buf[3], i; + u32 error_bit_count = 0; + u32 total_bit_count = 0; + u32 abort_packet_count = 0; + u64 numerator, denominator; + + state->ber = 0; + + /* check if error bit count is ready */ + ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]); + if (ret) + goto error; + if (!buf[0]) + goto exit; + + /* get RSD packet abort count */ + for (i = 0; i < 2; i++) { + ret = af9013_read_reg(state, 0xd38a + i, &buf[i]); + if (ret) + goto error; + } + abort_packet_count = (buf[1] << 8) + buf[0]; + + /* get error bit count */ + for (i = 0; i < 3; i++) { + ret = af9013_read_reg(state, 0xd387 + i, &buf[i]); + if (ret) + goto error; + } + error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0]; + error_bit_count = error_bit_count - abort_packet_count * 8 * 8; + + /* get used RSD counting period (10000 RSD packets used) */ + for (i = 0; i < 2; i++) { + ret = af9013_read_reg(state, 0xd385 + i, &buf[i]); + if (ret) + goto error; + } + total_bit_count = (buf[1] << 8) + buf[0]; + total_bit_count = total_bit_count - abort_packet_count; + total_bit_count = total_bit_count * 204 * 8; + + if (total_bit_count) { + numerator = error_bit_count * 1000000000; + denominator = total_bit_count; + state->ber = numerator / denominator; + } + + state->ucblocks += abort_packet_count; + + deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__, + error_bit_count, total_bit_count, abort_packet_count); + + /* set BER counting range */ + ret = af9013_write_reg(state, 0xd385, 10000 & 0xff); + if (ret) + goto error; + ret = af9013_write_reg(state, 0xd386, 10000 >> 8); + if (ret) + goto error; + /* reset and start BER counter */ + ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1); + if (ret) + goto error; + +exit: +error: + return ret; +} + +static int af9013_update_snr(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + u8 buf[3], i, len; + u32 quant = 0; + struct snr_table *snr_table; + + /* check if quantizer ready (for snr) */ + ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]); + if (ret) + goto error; + if (buf[0]) { + /* quantizer ready - read it */ + for (i = 0; i < 3; i++) { + ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]); + if (ret) + goto error; + } + quant = (buf[2] << 16) + (buf[1] << 8) + buf[0]; + + /* read current constellation */ + ret = af9013_read_reg(state, 0xd3c1, &buf[0]); + if (ret) + goto error; + + switch ((buf[0] >> 6) & 3) { + case 0: + len = ARRAY_SIZE(qpsk_snr_table); + snr_table = qpsk_snr_table; + break; + case 1: + len = ARRAY_SIZE(qam16_snr_table); + snr_table = qam16_snr_table; + break; + case 2: + len = ARRAY_SIZE(qam64_snr_table); + snr_table = qam64_snr_table; + break; + default: + len = 0; + break; + } + + if (len) { + for (i = 0; i < len; i++) { + if (quant < snr_table[i].val) { + state->snr = snr_table[i].snr * 10; + break; + } + } + } + + /* set quantizer super frame count */ + ret = af9013_write_reg(state, 0xd2e2, 1); + if (ret) + goto error; + + /* check quantizer availability */ + for (i = 0; i < 10; i++) { + msleep(10); + ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1, + &buf[0]); + if (ret) + goto error; + if (!buf[0]) + break; + } + + /* reset quantizer */ + ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1); + if (ret) + goto error; + } + +error: + return ret; +} + +static int af9013_update_signal_strength(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + u8 tmp0; + u8 rf_gain, rf_50, rf_80, if_gain, if_50, if_80; + int signal_strength; + + deb_info("%s\n", __func__); + + state->signal_strength = 0; + + ret = af9013_read_reg_bits(state, 0x9bee, 0, 1, &tmp0); + if (ret) + goto error; + if (tmp0) { + ret = af9013_read_reg(state, 0x9bbd, &rf_50); + if (ret) + goto error; + ret = af9013_read_reg(state, 0x9bd0, &rf_80); + if (ret) + goto error; + ret = af9013_read_reg(state, 0x9be2, &if_50); + if (ret) + goto error; + ret = af9013_read_reg(state, 0x9be4, &if_80); + if (ret) + goto error; + ret = af9013_read_reg(state, 0xd07c, &rf_gain); + if (ret) + goto error; + ret = af9013_read_reg(state, 0xd07d, &if_gain); + if (ret) + goto error; + signal_strength = (0xffff / (9 * (rf_50 + if_50) - \ + 11 * (rf_80 + if_80))) * (10 * (rf_gain + if_gain) - \ + 11 * (rf_80 + if_80)); + if (signal_strength < 0) + signal_strength = 0; + else if (signal_strength > 0xffff) + signal_strength = 0xffff; + + state->signal_strength = signal_strength; + } + +error: + return ret; +} + +static int af9013_update_statistics(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + + if (time_before(jiffies, state->next_statistics_check)) + return 0; + + /* set minimum statistic update interval */ + state->next_statistics_check = jiffies + msecs_to_jiffies(1200); + + ret = af9013_update_signal_strength(fe); + if (ret) + goto error; + ret = af9013_update_snr(fe); + if (ret) + goto error; + ret = af9013_update_ber_unc(fe); + if (ret) + goto error; + +error: + return ret; +} + +static int af9013_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + fesettings->min_delay_ms = 800; + fesettings->step_size = 0; + fesettings->max_drift = 0; + + return 0; +} + +static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret = 0; + u8 tmp; + *status = 0; + + /* TPS lock */ + ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; + + /* MPEG2 lock */ + ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + + if (!*status & FE_HAS_SIGNAL) { + /* AGC lock */ + ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_SIGNAL; + } + + if (!*status & FE_HAS_CARRIER) { + /* CFO lock */ + ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_CARRIER; + } + + if (!*status & FE_HAS_CARRIER) { + /* SFOE lock */ + ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); + if (ret) + goto error; + if (tmp) + *status |= FE_HAS_CARRIER; + } + + ret = af9013_update_statistics(fe); + +error: + return ret; +} + + +static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + ret = af9013_update_statistics(fe); + *ber = state->ber; + return ret; +} + +static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + ret = af9013_update_statistics(fe); + *strength = state->signal_strength; + return ret; +} + +static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + ret = af9013_update_statistics(fe); + *snr = state->snr; + return ret; +} + +static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + ret = af9013_update_statistics(fe); + *ucblocks = state->ucblocks; + return ret; +} + +static int af9013_sleep(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret; + deb_info("%s\n", __func__); + + ret = af9013_lock_led(state, 0); + if (ret) + goto error; + + ret = af9013_power_ctrl(state, 0); +error: + return ret; +} + +static int af9013_init(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + int ret, i, len; + u8 tmp0, tmp1; + struct regdesc *init; + deb_info("%s\n", __func__); + + /* reset OFDM */ + ret = af9013_reset(state, 0); + if (ret) + goto error; + + /* power on */ + ret = af9013_power_ctrl(state, 1); + if (ret) + goto error; + + /* enable ADC */ + ret = af9013_write_reg(state, 0xd73a, 0xa4); + if (ret) + goto error; + + /* write API version to firmware */ + for (i = 0; i < sizeof(state->config.api_version); i++) { + ret = af9013_write_reg(state, 0x9bf2 + i, + state->config.api_version[i]); + if (ret) + goto error; + } + + /* program ADC control */ + ret = af9013_set_adc_ctrl(state); + if (ret) + goto error; + + /* set I2C master clock */ + ret = af9013_write_reg(state, 0xd416, 0x14); + if (ret) + goto error; + + /* set 16 embx */ + ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1); + if (ret) + goto error; + + /* set no trigger */ + ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0); + if (ret) + goto error; + + /* set read-update bit for constellation */ + ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1); + if (ret) + goto error; + + /* enable FEC monitor */ + ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1); + if (ret) + goto error; + + /* load OFSM settings */ + deb_info("%s: load ofsm settings\n", __func__); + len = ARRAY_SIZE(ofsm_init); + init = ofsm_init; + for (i = 0; i < len; i++) { + ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, + init[i].len, init[i].val); + if (ret) + goto error; + } + + /* load tuner specific settings */ + deb_info("%s: load tuner specific settings\n", __func__); + switch (state->config.tuner) { + case AF9013_TUNER_MXL5003D: + len = ARRAY_SIZE(tuner_init_mxl5003d); + init = tuner_init_mxl5003d; + break; + case AF9013_TUNER_MXL5005D: + case AF9013_TUNER_MXL5005R: + len = ARRAY_SIZE(tuner_init_mxl5005); + init = tuner_init_mxl5005; + break; + case AF9013_TUNER_ENV77H11D5: + len = ARRAY_SIZE(tuner_init_env77h11d5); + init = tuner_init_env77h11d5; + break; + case AF9013_TUNER_MT2060: + len = ARRAY_SIZE(tuner_init_mt2060); + init = tuner_init_mt2060; + break; + case AF9013_TUNER_MC44S803: + len = ARRAY_SIZE(tuner_init_mc44s803); + init = tuner_init_mc44s803; + break; + case AF9013_TUNER_QT1010: + case AF9013_TUNER_QT1010A: + len = ARRAY_SIZE(tuner_init_qt1010); + init = tuner_init_qt1010; + break; + case AF9013_TUNER_MT2060_2: + len = ARRAY_SIZE(tuner_init_mt2060_2); + init = tuner_init_mt2060_2; + break; + case AF9013_TUNER_TDA18271: + len = ARRAY_SIZE(tuner_init_tda18271); + init = tuner_init_tda18271; + break; + case AF9013_TUNER_UNKNOWN: + default: + len = ARRAY_SIZE(tuner_init_unknown); + init = tuner_init_unknown; + break; + } + + for (i = 0; i < len; i++) { + ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, + init[i].len, init[i].val); + if (ret) + goto error; + } + + /* set TS mode */ + deb_info("%s: setting ts mode\n", __func__); + tmp0 = 0; /* parallel mode */ + tmp1 = 0; /* serial mode */ + switch (state->config.output_mode) { + case AF9013_OUTPUT_MODE_PARALLEL: + tmp0 = 1; + break; + case AF9013_OUTPUT_MODE_SERIAL: + tmp1 = 1; + break; + case AF9013_OUTPUT_MODE_USB: + /* usb mode for AF9015 */ + default: + break; + } + ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */ + if (ret) + goto error; + ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */ + if (ret) + goto error; + + /* enable lock led */ + ret = af9013_lock_led(state, 1); + if (ret) + goto error; + +error: + return ret; +} + +static struct dvb_frontend_ops af9013_ops; + +static int af9013_download_firmware(struct af9013_state *state) +{ + int i, len, packets, remainder, ret; + const struct firmware *fw; + u16 addr = 0x5100; /* firmware start address */ + u16 checksum = 0; + u8 val; + u8 fw_params[4]; + u8 *data; + u8 *fw_file = AF9013_DEFAULT_FIRMWARE; + + msleep(100); + /* check whether firmware is already running */ + ret = af9013_read_reg(state, 0x98be, &val); + if (ret) + goto error; + else + deb_info("%s: firmware status:%02x\n", __func__, val); + + if (val == 0x0c) /* fw is running, no need for download */ + goto exit; + + info("found a '%s' in cold state, will try to load a firmware", + af9013_ops.info.name); + + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_file, &state->i2c->dev); + if (ret) { + err("did not find the firmware file. (%s) " + "Please see linux/Documentation/dvb/ for more details" \ + " on firmware-problems. (%d)", + fw_file, ret); + goto error; + } + + info("downloading firmware from file '%s'", fw_file); + + /* calc checksum */ + for (i = 0; i < fw->size; i++) + checksum += fw->data[i]; + + fw_params[0] = checksum >> 8; + fw_params[1] = checksum & 0xff; + fw_params[2] = fw->size >> 8; + fw_params[3] = fw->size & 0xff; + + /* write fw checksum & size */ + ret = af9013_write_ofsm_regs(state, 0x50fc, + fw_params, sizeof(fw_params)); + if (ret) + goto error_release; + + #define FW_PACKET_MAX_DATA 16 + + packets = fw->size / FW_PACKET_MAX_DATA; + remainder = fw->size % FW_PACKET_MAX_DATA; + len = FW_PACKET_MAX_DATA; + for (i = 0; i <= packets; i++) { + if (i == packets) /* set size of the last packet */ + len = remainder; + + data = (fw->data + i * FW_PACKET_MAX_DATA); + ret = af9013_write_ofsm_regs(state, addr, data, len); + addr += FW_PACKET_MAX_DATA; + + if (ret) { + err("firmware download failed at %d with %d", i, ret); + goto error_release; + } + } + + #undef FW_PACKET_MAX_DATA + + /* request boot firmware */ + ret = af9013_write_reg(state, 0xe205, 1); + if (ret) + goto error_release; + + for (i = 0; i < 15; i++) { + msleep(100); + + /* check firmware status */ + ret = af9013_read_reg(state, 0x98be, &val); + if (ret) + goto error_release; + + deb_info("%s: firmware status:%02x\n", __func__, val); + + if (val == 0x0c || val == 0x04) /* success or fail */ + break; + } + + if (val == 0x04) { + err("firmware did not run"); + ret = -1; + } else if (val != 0x0c) { + err("firmware boot timeout"); + ret = -1; + } + +error_release: + release_firmware(fw); +error: +exit: + if (!ret) + info("found a '%s' in warm state.", af9013_ops.info.name); + return ret; +} + +static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + int ret; + struct af9013_state *state = fe->demodulator_priv; + deb_info("%s: enable:%d\n", __func__, enable); + + if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) + ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable); + else + ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable); + + return ret; +} + +static void af9013_release(struct dvb_frontend *fe) +{ + struct af9013_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops af9013_ops; + +struct dvb_frontend *af9013_attach(const struct af9013_config *config, + struct i2c_adapter *i2c) +{ + int ret; + struct af9013_state *state = NULL; + u8 buf[3], i; + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->i2c = i2c; + memcpy(&state->config, config, sizeof(struct af9013_config)); + + /* chip version */ + ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]); + if (ret) + goto error; + + /* ROM version */ + for (i = 0; i < 2; i++) { + ret = af9013_read_reg(state, 0x116b + i, &buf[i]); + if (ret) + goto error; + } + deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__, + buf[2], buf[0], buf[1]); + + /* download firmware */ + if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) { + ret = af9013_download_firmware(state); + if (ret) + goto error; + } + + /* firmware version */ + for (i = 0; i < 3; i++) { + ret = af9013_read_reg(state, 0x5103 + i, &buf[i]); + if (ret) + goto error; + } + info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]); + + /* settings for mp2if */ + if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) { + /* AF9015 split PSB to 1.5k + 0.5k */ + ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1); + } else { + /* AF9013 change the output bit to data7 */ + ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1); + if (ret) + goto error; + /* AF9013 set mpeg to full speed */ + ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1); + } + if (ret) + goto error; + ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1); + if (ret) + goto error; + + /* set GPIOs */ + for (i = 0; i < sizeof(state->config.gpio); i++) { + ret = af9013_set_gpio(state, i, state->config.gpio[i]); + if (ret) + goto error; + } + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &af9013_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + return &state->frontend; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(af9013_attach); + +static struct dvb_frontend_ops af9013_ops = { + .info = { + .name = "Afatech AF9013 DVB-T", + .type = FE_OFDM, + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 250000, + .frequency_tolerance = 0, + .caps = + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | + FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = af9013_release, + .init = af9013_init, + .sleep = af9013_sleep, + .i2c_gate_ctrl = af9013_i2c_gate_ctrl, + + .set_frontend = af9013_set_frontend, + .get_frontend = af9013_get_frontend, + + .get_tune_settings = af9013_get_tune_settings, + + .read_status = af9013_read_status, + .read_ber = af9013_read_ber, + .read_signal_strength = af9013_read_signal_strength, + .read_snr = af9013_read_snr, + .read_ucblocks = af9013_read_ucblocks, +}; + +module_param_named(debug, af9013_debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h new file mode 100644 index 00000000000..28b90c91c76 --- /dev/null +++ b/drivers/media/dvb/frontends/af9013.h @@ -0,0 +1,107 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _AF9013_H_ +#define _AF9013_H_ + +#include + +enum af9013_ts_mode { + AF9013_OUTPUT_MODE_PARALLEL, + AF9013_OUTPUT_MODE_SERIAL, + AF9013_OUTPUT_MODE_USB, /* only for AF9015 */ +}; + +enum af9013_tuner { + AF9013_TUNER_MXL5003D = 3, /* MaxLinear */ + AF9013_TUNER_MXL5005D = 13, /* MaxLinear */ + AF9013_TUNER_MXL5005R = 30, /* MaxLinear */ + AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */ + AF9013_TUNER_MT2060 = 130, /* Microtune */ + AF9013_TUNER_MC44S803 = 133, /* Freescale */ + AF9013_TUNER_QT1010 = 134, /* Quantek */ + AF9013_TUNER_UNKNOWN = 140, /* for can tuners ? */ + AF9013_TUNER_MT2060_2 = 147, /* Microtune */ + AF9013_TUNER_TDA18271 = 156, /* NXP */ + AF9013_TUNER_QT1010A = 162, /* Quantek */ +}; + +/* AF9013/5 GPIOs (mostly guessed) + demod#1-gpio#0 - set demod#2 i2c-addr for dual devices + demod#1-gpio#1 - xtal setting (?) + demod#1-gpio#3 - tuner#1 + demod#2-gpio#0 - tuner#2 + demod#2-gpio#1 - xtal setting (?) +*/ +#define AF9013_GPIO_ON (1 << 0) +#define AF9013_GPIO_EN (1 << 1) +#define AF9013_GPIO_O (1 << 2) +#define AF9013_GPIO_I (1 << 3) + +#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN) +#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O) + +#define AF9013_GPIO_TUNER_ON (AF9013_GPIO_ON|AF9013_GPIO_EN) +#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O) + +struct af9013_config { + /* demodulator's I2C address */ + u8 demod_address; + + /* frequencies in kHz */ + u32 adc_clock; + + /* tuner ID */ + u8 tuner; + + /* tuner IF */ + u16 tuner_if; + + /* TS data output mode */ + u8 output_mode:2; + + /* RF spectrum inversion */ + u8 rf_spec_inv:1; + + /* API version */ + u8 api_version[4]; + + /* GPIOs */ + u8 gpio[4]; +}; + + +#if defined(CONFIG_DVB_AF9013) || \ + (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE)) +extern struct dvb_frontend *af9013_attach(const struct af9013_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *af9013_attach( +const struct af9013_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_AF9013 */ + +#endif /* _AF9013_H_ */ diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h new file mode 100644 index 00000000000..163e251d0b7 --- /dev/null +++ b/drivers/media/dvb/frontends/af9013_priv.h @@ -0,0 +1,869 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _AF9013_PRIV_ +#define _AF9013_PRIV_ + +#define LOG_PREFIX "af9013" +extern int af9013_debug; + +#define dprintk(var, level, args...) \ + do { if ((var & level)) printk(args); } while (0) + +#define debug_dump(b, l, func) {\ + int loop_; \ + for (loop_ = 0; loop_ < l; loop_++) \ + func("%02x ", b[loop_]); \ + func("\n");\ +} + +#define deb_info(args...) dprintk(af9013_debug, 0x01, args) + +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +#define AF9013_DEFAULT_FIRMWARE "dvb-fe-af9013.fw" + +struct regdesc { + u16 addr; + u8 pos:4; + u8 len:4; + u8 val; +}; + +struct snr_table { + u32 val; + u8 snr; +}; + +/* QPSK SNR lookup table */ +static struct snr_table qpsk_snr_table[] = { + { 0x0b4771, 0 }, + { 0x0c1aed, 1 }, + { 0x0d0d27, 2 }, + { 0x0e4d19, 3 }, + { 0x0e5da8, 4 }, + { 0x107097, 5 }, + { 0x116975, 6 }, + { 0x1252d9, 7 }, + { 0x131fa4, 8 }, + { 0x13d5e1, 9 }, + { 0x148e53, 10 }, + { 0x15358b, 11 }, + { 0x15dd29, 12 }, + { 0x168112, 13 }, + { 0x170b61, 14 }, + { 0xffffff, 15 }, +}; + +/* QAM16 SNR lookup table */ +static struct snr_table qam16_snr_table[] = { + { 0x05eb62, 5 }, + { 0x05fecf, 6 }, + { 0x060b80, 7 }, + { 0x062501, 8 }, + { 0x064865, 9 }, + { 0x069604, 10 }, + { 0x06f356, 11 }, + { 0x07706a, 12 }, + { 0x0804d3, 13 }, + { 0x089d1a, 14 }, + { 0x093e3d, 15 }, + { 0x09e35d, 16 }, + { 0x0a7c3c, 17 }, + { 0x0afaf8, 18 }, + { 0x0b719d, 19 }, + { 0xffffff, 20 }, +}; + +/* QAM64 SNR lookup table */ +static struct snr_table qam64_snr_table[] = { + { 0x03109b, 12 }, + { 0x0310d4, 13 }, + { 0x031920, 14 }, + { 0x0322d0, 15 }, + { 0x0339fc, 16 }, + { 0x0364a1, 17 }, + { 0x038bcc, 18 }, + { 0x03c7d3, 19 }, + { 0x0408cc, 20 }, + { 0x043bed, 21 }, + { 0x048061, 22 }, + { 0x04be95, 23 }, + { 0x04fa7d, 24 }, + { 0x052405, 25 }, + { 0x05570d, 26 }, + { 0xffffff, 27 }, +}; + +static struct regdesc ofsm_init[] = { + { 0xd73a, 0, 8, 0xa1 }, + { 0xd73b, 0, 8, 0x1f }, + { 0xd73c, 4, 4, 0x0a }, + { 0xd732, 3, 1, 0x00 }, + { 0xd731, 4, 2, 0x03 }, + { 0xd73d, 7, 1, 0x01 }, + { 0xd740, 0, 1, 0x00 }, + { 0xd740, 1, 1, 0x00 }, + { 0xd740, 2, 1, 0x00 }, + { 0xd740, 3, 1, 0x01 }, + { 0xd3c1, 4, 1, 0x01 }, + { 0xd3a2, 0, 8, 0x00 }, + { 0xd3a3, 0, 8, 0x04 }, + { 0xd305, 0, 8, 0x32 }, + { 0xd306, 0, 8, 0x10 }, + { 0xd304, 0, 8, 0x04 }, + { 0x9112, 0, 1, 0x01 }, + { 0x911d, 0, 1, 0x01 }, + { 0x911a, 0, 1, 0x01 }, + { 0x911b, 0, 1, 0x01 }, + { 0x9bce, 0, 4, 0x02 }, + { 0x9116, 0, 1, 0x01 }, + { 0x9bd1, 0, 1, 0x01 }, + { 0xd2e0, 0, 8, 0xd0 }, + { 0xd2e9, 0, 4, 0x0d }, + { 0xd38c, 0, 8, 0xfc }, + { 0xd38d, 0, 8, 0x00 }, + { 0xd38e, 0, 8, 0x7e }, + { 0xd38f, 0, 8, 0x00 }, + { 0xd390, 0, 8, 0x2f }, + { 0xd145, 4, 1, 0x01 }, + { 0xd1a9, 4, 1, 0x01 }, + { 0xd158, 5, 3, 0x01 }, + { 0xd159, 0, 6, 0x06 }, + { 0xd167, 0, 8, 0x00 }, + { 0xd168, 0, 4, 0x07 }, + { 0xd1c3, 5, 3, 0x00 }, + { 0xd1c4, 0, 6, 0x00 }, + { 0xd1c5, 0, 7, 0x10 }, + { 0xd1c6, 0, 3, 0x02 }, + { 0xd080, 2, 5, 0x03 }, + { 0xd081, 4, 4, 0x09 }, + { 0xd098, 4, 4, 0x0f }, + { 0xd098, 0, 4, 0x03 }, + { 0xdbc0, 3, 1, 0x01 }, + { 0xdbc0, 4, 1, 0x01 }, + { 0xdbc7, 0, 8, 0x08 }, + { 0xdbc8, 4, 4, 0x00 }, + { 0xdbc9, 0, 5, 0x01 }, + { 0xd280, 0, 8, 0xe0 }, + { 0xd281, 0, 8, 0xff }, + { 0xd282, 0, 8, 0xff }, + { 0xd283, 0, 8, 0xc3 }, + { 0xd284, 0, 8, 0xff }, + { 0xd285, 0, 4, 0x01 }, + { 0xd0f0, 0, 7, 0x1a }, + { 0xd0f1, 4, 1, 0x01 }, + { 0xd0f2, 0, 8, 0x0c }, + { 0xd103, 0, 4, 0x08 }, + { 0xd0f8, 0, 7, 0x20 }, + { 0xd111, 5, 1, 0x00 }, + { 0xd111, 6, 1, 0x00 }, + { 0x910b, 0, 8, 0x0a }, + { 0x9115, 0, 8, 0x02 }, + { 0x910c, 0, 8, 0x02 }, + { 0x910d, 0, 8, 0x08 }, + { 0x910e, 0, 8, 0x0a }, + { 0x9bf6, 0, 8, 0x06 }, + { 0x9bf8, 0, 8, 0x02 }, + { 0x9bf7, 0, 8, 0x05 }, + { 0x9bf9, 0, 8, 0x0f }, + { 0x9bfc, 0, 8, 0x13 }, + { 0x9bd3, 0, 8, 0xff }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, +}; + +/* Panasonic ENV77H11D5 tuner init + AF9013_TUNER_ENV77H11D5 = 129 */ +static struct regdesc tuner_init_env77h11d5[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x03 }, + { 0x9bbe, 0, 8, 0x01 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x00 }, + { 0x9be3, 0, 8, 0x00 }, + { 0xd015, 0, 8, 0x50 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0xdf }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x44 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0xeb }, + { 0xd00d, 0, 2, 0x02 }, + { 0xd00a, 0, 8, 0xf4 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bba, 0, 8, 0xf9 }, + { 0x9bc3, 0, 8, 0xdf }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0xeb }, + { 0x9bc6, 0, 8, 0x02 }, + { 0x9bc9, 0, 8, 0x52 }, + { 0xd011, 0, 8, 0x3c }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0xf7 }, + { 0xd014, 0, 2, 0x02 }, + { 0xd040, 0, 8, 0x0b }, + { 0xd041, 0, 2, 0x02 }, + { 0xd042, 0, 8, 0x4d }, + { 0xd043, 0, 2, 0x00 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, +}; + +/* Microtune MT2060 tuner init + AF9013_TUNER_MT2060 = 130 */ +static struct regdesc tuner_init_mt2060[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x07 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x00 }, + { 0x9be3, 0, 8, 0x00 }, + { 0x9bbe, 0, 1, 0x00 }, + { 0x9bcc, 0, 1, 0x00 }, + { 0x9bb9, 0, 8, 0x75 }, + { 0x9bcd, 0, 8, 0x24 }, + { 0x9bff, 0, 8, 0x30 }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0x0f }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x32 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0x36 }, + { 0xd00d, 0, 2, 0x03 }, + { 0xd00a, 0, 8, 0x35 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x07 }, + { 0x9bc8, 0, 8, 0x90 }, + { 0x9bc3, 0, 8, 0x0f }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x36 }, + { 0x9bc6, 0, 8, 0x03 }, + { 0x9bba, 0, 8, 0xc9 }, + { 0x9bc9, 0, 8, 0x79 }, + { 0xd011, 0, 8, 0x10 }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0x45 }, + { 0xd014, 0, 2, 0x03 }, + { 0xd040, 0, 8, 0x98 }, + { 0xd041, 0, 2, 0x00 }, + { 0xd042, 0, 8, 0xcf }, + { 0xd043, 0, 2, 0x03 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, + { 0x9bd0, 0, 8, 0xcc }, + { 0x9be4, 0, 8, 0xa0 }, + { 0x9bbd, 0, 8, 0x8e }, + { 0x9be2, 0, 8, 0x4d }, + { 0x9bee, 0, 1, 0x01 }, +}; + +/* Microtune MT2060 tuner init + AF9013_TUNER_MT2060_2 = 147 */ +static struct regdesc tuner_init_mt2060_2[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x06 }, + { 0x9bbe, 0, 8, 0x01 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0x0f }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x32 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0x36 }, + { 0xd00d, 0, 2, 0x03 }, + { 0xd00a, 0, 8, 0x35 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x07 }, + { 0x9bc8, 0, 8, 0x90 }, + { 0x9bc3, 0, 8, 0x0f }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x36 }, + { 0x9bc6, 0, 8, 0x03 }, + { 0x9bba, 0, 8, 0xc9 }, + { 0x9bc9, 0, 8, 0x79 }, + { 0xd011, 0, 8, 0x10 }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0x45 }, + { 0xd014, 0, 2, 0x03 }, + { 0xd040, 0, 8, 0x98 }, + { 0xd041, 0, 2, 0x00 }, + { 0xd042, 0, 8, 0xcf }, + { 0xd043, 0, 2, 0x03 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 8, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x96 }, + { 0xd054, 0, 8, 0x46 }, + { 0xd045, 7, 1, 0x00 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, +}; + +/* MaxLinear MXL5003 tuner init + AF9013_TUNER_MXL5003D = 3 */ +static struct regdesc tuner_init_mxl5003d[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x09 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x00 }, + { 0x9be3, 0, 8, 0x00 }, + { 0x9bfc, 0, 8, 0x0f }, + { 0x9bf6, 0, 8, 0x01 }, + { 0x9bbe, 0, 1, 0x01 }, + { 0xd015, 0, 8, 0x33 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x40 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0x0f }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x6c }, + { 0xd007, 0, 2, 0x00 }, + { 0xd00c, 0, 8, 0x3d }, + { 0xd00d, 0, 2, 0x00 }, + { 0xd00a, 0, 8, 0x45 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x07 }, + { 0x9bc8, 0, 8, 0x52 }, + { 0x9bc3, 0, 8, 0x0f }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x3d }, + { 0x9bc6, 0, 8, 0x00 }, + { 0x9bba, 0, 8, 0xa2 }, + { 0x9bc9, 0, 8, 0xa0 }, + { 0xd011, 0, 8, 0x56 }, + { 0xd012, 0, 2, 0x00 }, + { 0xd013, 0, 8, 0x50 }, + { 0xd014, 0, 2, 0x00 }, + { 0xd040, 0, 8, 0x56 }, + { 0xd041, 0, 2, 0x00 }, + { 0xd042, 0, 8, 0x50 }, + { 0xd043, 0, 2, 0x00 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 8, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, +}; + +/* MaxLinear MXL5005 tuner init + AF9013_TUNER_MXL5005D = 13 + AF9013_TUNER_MXL5005R = 30 */ +static struct regdesc tuner_init_mxl5005[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x07 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x01 }, + { 0x9be3, 0, 8, 0x01 }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, + { 0x9bb9, 0, 8, 0x00 }, + { 0x9bcd, 0, 8, 0x28 }, + { 0x9bff, 0, 8, 0x24 }, + { 0xd015, 0, 8, 0x40 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x40 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0x0f }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x73 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0xfa }, + { 0xd00d, 0, 2, 0x01 }, + { 0xd00a, 0, 8, 0xff }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x23 }, + { 0x9bc8, 0, 8, 0x55 }, + { 0x9bc3, 0, 8, 0x01 }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0xfa }, + { 0x9bc6, 0, 8, 0x01 }, + { 0x9bba, 0, 8, 0xff }, + { 0x9bc9, 0, 8, 0xff }, + { 0x9bd3, 0, 8, 0x95 }, + { 0xd011, 0, 8, 0x70 }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0xfb }, + { 0xd014, 0, 2, 0x01 }, + { 0xd040, 0, 8, 0x70 }, + { 0xd041, 0, 2, 0x01 }, + { 0xd042, 0, 8, 0xfb }, + { 0xd043, 0, 2, 0x01 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, + { 0x9bd0, 0, 8, 0x93 }, + { 0x9be4, 0, 8, 0xfe }, + { 0x9bbd, 0, 8, 0x63 }, + { 0x9be2, 0, 8, 0xfe }, + { 0x9bee, 0, 1, 0x01 }, +}; + +/* Quantek QT1010 tuner init + AF9013_TUNER_QT1010 = 134 + AF9013_TUNER_QT1010A = 162 */ +static struct regdesc tuner_init_qt1010[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x09 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x01 }, + { 0x9be3, 0, 8, 0x01 }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, + { 0x9bb9, 0, 8, 0x00 }, + { 0x9bcd, 0, 8, 0x28 }, + { 0x9bff, 0, 8, 0x20 }, + { 0xd008, 0, 8, 0x0f }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x99 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0x0f }, + { 0xd00d, 0, 2, 0x02 }, + { 0xd00a, 0, 8, 0x50 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x00 }, + { 0x9bc8, 0, 8, 0x00 }, + { 0x9bc3, 0, 8, 0x0f }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x0f }, + { 0x9bc6, 0, 8, 0x02 }, + { 0x9bba, 0, 8, 0xc5 }, + { 0x9bc9, 0, 8, 0xff }, + { 0xd011, 0, 8, 0x58 }, + { 0xd012, 0, 2, 0x02 }, + { 0xd013, 0, 8, 0x89 }, + { 0xd014, 0, 2, 0x01 }, + { 0xd040, 0, 8, 0x58 }, + { 0xd041, 0, 2, 0x02 }, + { 0xd042, 0, 8, 0x89 }, + { 0xd043, 0, 2, 0x01 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, + { 0x9bd0, 0, 8, 0xcd }, + { 0x9be4, 0, 8, 0xbb }, + { 0x9bbd, 0, 8, 0x93 }, + { 0x9be2, 0, 8, 0x80 }, + { 0x9bee, 0, 1, 0x01 }, +}; + +/* Freescale MC44S803 tuner init + AF9013_TUNER_MC44S803 = 133 */ +static struct regdesc tuner_init_mc44s803[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x06 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x00 }, + { 0x9be3, 0, 8, 0x00 }, + { 0x9bf6, 0, 8, 0x01 }, + { 0x9bf8, 0, 8, 0x02 }, + { 0x9bf9, 0, 8, 0x02 }, + { 0x9bfc, 0, 8, 0x1f }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, + { 0x9bb9, 0, 8, 0x00 }, + { 0x9bcd, 0, 8, 0x24 }, + { 0x9bff, 0, 8, 0x24 }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0x01 }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x7b }, + { 0xd007, 0, 2, 0x00 }, + { 0xd00c, 0, 8, 0x7c }, + { 0xd00d, 0, 2, 0x02 }, + { 0xd00a, 0, 8, 0xfe }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bc7, 0, 8, 0x08 }, + { 0x9bc8, 0, 8, 0x9a }, + { 0x9bc3, 0, 8, 0x01 }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x7c }, + { 0x9bc6, 0, 8, 0x02 }, + { 0x9bba, 0, 8, 0xfc }, + { 0x9bc9, 0, 8, 0xaa }, + { 0xd011, 0, 8, 0x6b }, + { 0xd012, 0, 2, 0x00 }, + { 0xd013, 0, 8, 0x88 }, + { 0xd014, 0, 2, 0x02 }, + { 0xd040, 0, 8, 0x6b }, + { 0xd041, 0, 2, 0x00 }, + { 0xd042, 0, 8, 0x7c }, + { 0xd043, 0, 2, 0x02 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, + { 0x9bd0, 0, 8, 0x9e }, + { 0x9be4, 0, 8, 0xff }, + { 0x9bbd, 0, 8, 0x9e }, + { 0x9be2, 0, 8, 0x25 }, + { 0x9bee, 0, 1, 0x01 }, + { 0xd73b, 3, 1, 0x00 }, +}; + +/* unknown, probably for tin can tuner, tuner init + AF9013_TUNER_UNKNOWN = 140 */ +static struct regdesc tuner_init_unknown[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x02 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x01 }, + { 0x9be3, 0, 8, 0x01 }, + { 0xd1a0, 1, 1, 0x00 }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, + { 0x9bb9, 0, 8, 0x00 }, + { 0x9bcd, 0, 8, 0x18 }, + { 0x9bff, 0, 8, 0x2c }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0xdf }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x44 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0x00 }, + { 0xd00d, 0, 2, 0x02 }, + { 0xd00a, 0, 8, 0xf6 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bba, 0, 8, 0xf9 }, + { 0x9bc8, 0, 8, 0xaa }, + { 0x9bc3, 0, 8, 0xdf }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x00 }, + { 0x9bc6, 0, 8, 0x02 }, + { 0x9bc9, 0, 8, 0xf0 }, + { 0xd011, 0, 8, 0x3c }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0xf7 }, + { 0xd014, 0, 2, 0x02 }, + { 0xd040, 0, 8, 0x0b }, + { 0xd041, 0, 2, 0x02 }, + { 0xd042, 0, 8, 0x4d }, + { 0xd043, 0, 2, 0x00 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, +}; + +/* NXP TDA18271 tuner init + AF9013_TUNER_TDA18271 = 156 */ +static struct regdesc tuner_init_tda18271[] = { + { 0x9bd5, 0, 8, 0x01 }, + { 0x9bd6, 0, 8, 0x04 }, + { 0xd1a0, 1, 1, 0x01 }, + { 0xd000, 0, 1, 0x01 }, + { 0xd000, 1, 1, 0x00 }, + { 0xd001, 1, 1, 0x01 }, + { 0xd001, 0, 1, 0x00 }, + { 0xd001, 5, 1, 0x00 }, + { 0xd002, 0, 5, 0x19 }, + { 0xd003, 0, 5, 0x1a }, + { 0xd004, 0, 5, 0x19 }, + { 0xd005, 0, 5, 0x1a }, + { 0xd00e, 0, 5, 0x10 }, + { 0xd00f, 0, 3, 0x04 }, + { 0xd00f, 3, 3, 0x05 }, + { 0xd010, 0, 3, 0x04 }, + { 0xd010, 3, 3, 0x05 }, + { 0xd016, 4, 4, 0x03 }, + { 0xd01f, 0, 6, 0x0a }, + { 0xd020, 0, 6, 0x0a }, + { 0x9bda, 0, 8, 0x01 }, + { 0x9be3, 0, 8, 0x01 }, + { 0xd1a0, 1, 1, 0x00 }, + { 0x9bbe, 0, 1, 0x01 }, + { 0x9bcc, 0, 1, 0x01 }, + { 0x9bb9, 0, 8, 0x00 }, + { 0x9bcd, 0, 8, 0x18 }, + { 0x9bff, 0, 8, 0x2c }, + { 0xd015, 0, 8, 0x46 }, + { 0xd016, 0, 1, 0x00 }, + { 0xd044, 0, 8, 0x46 }, + { 0xd045, 0, 1, 0x00 }, + { 0xd008, 0, 8, 0xdf }, + { 0xd009, 0, 2, 0x02 }, + { 0xd006, 0, 8, 0x44 }, + { 0xd007, 0, 2, 0x01 }, + { 0xd00c, 0, 8, 0x00 }, + { 0xd00d, 0, 2, 0x02 }, + { 0xd00a, 0, 8, 0xf6 }, + { 0xd00b, 0, 2, 0x01 }, + { 0x9bba, 0, 8, 0xf9 }, + { 0x9bc8, 0, 8, 0xaa }, + { 0x9bc3, 0, 8, 0xdf }, + { 0x9bc4, 0, 8, 0x02 }, + { 0x9bc5, 0, 8, 0x00 }, + { 0x9bc6, 0, 8, 0x02 }, + { 0x9bc9, 0, 8, 0xf0 }, + { 0xd011, 0, 8, 0x3c }, + { 0xd012, 0, 2, 0x01 }, + { 0xd013, 0, 8, 0xf7 }, + { 0xd014, 0, 2, 0x02 }, + { 0xd040, 0, 8, 0x0b }, + { 0xd041, 0, 2, 0x02 }, + { 0xd042, 0, 8, 0x4d }, + { 0xd043, 0, 2, 0x00 }, + { 0xd045, 1, 1, 0x00 }, + { 0x9bcf, 0, 1, 0x01 }, + { 0xd045, 2, 1, 0x01 }, + { 0xd04f, 0, 8, 0x9a }, + { 0xd050, 0, 1, 0x01 }, + { 0xd051, 0, 8, 0x5a }, + { 0xd052, 0, 1, 0x01 }, + { 0xd053, 0, 8, 0x50 }, + { 0xd054, 0, 8, 0x46 }, + { 0x9bd7, 0, 8, 0x0a }, + { 0x9bd8, 0, 8, 0x14 }, + { 0x9bd9, 0, 8, 0x08 }, + { 0x9bd0, 0, 8, 0xa8 }, + { 0x9be4, 0, 8, 0x7f }, + { 0x9bbd, 0, 8, 0xa8 }, + { 0x9be2, 0, 8, 0x20 }, + { 0x9bee, 0, 1, 0x01 }, +}; + +#endif /* _AF9013_PRIV_ */ -- GitLab From 80619de8117701cad1fb5526be6fcfe6fc2a6cc2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Sep 2008 17:18:09 -0300 Subject: [PATCH 4093/5416] V4L/DVB (8972): initial driver for af9015 chipset - initial driver for the Afatech AF9015 chipset Thanks-to: Mark Spieth Thanks-to: Lee Essen Thanks-to: Luca Olivetti Thanks-to: Andrew Leech Thanks-to: Nick Andrew Thanks-to: Rafael Antoniello Thanks-to: Jarryd Beck Thanks-to: Jose Alberto Reguero Thanks-to: Benjamin Larsson Thanks-to: Wolfgang Breyha Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 12 + drivers/media/dvb/dvb-usb/Makefile | 3 + drivers/media/dvb/dvb-usb/af9015.c | 1459 +++++++++++++++++++++++ drivers/media/dvb/dvb-usb/af9015.h | 524 ++++++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 17 +- 5 files changed, 2014 insertions(+), 1 deletion(-) create mode 100644 drivers/media/dvb/dvb-usb/af9015.c create mode 100644 drivers/media/dvb/dvb-usb/af9015.h diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 1d9e98cee9e..b35d7f0db9a 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -271,3 +271,15 @@ config DVB_USB_DTV5100 select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. + +config DVB_USB_AF9015 + tristate "Afatech AF9015 DVB-T USB2.0 support" + depends on DVB_USB && EXPERIMENTAL + select DVB_AF9013 + select DVB_PLL if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + help + Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 116544f4272..ece8c9dfed1 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -70,6 +70,9 @@ obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o dvb-usb-dtv5100-objs = dtv5100.o obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o +dvb-usb-af9015-objs = af9015.o +obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c new file mode 100644 index 00000000000..a284648094c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -0,0 +1,1459 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 "af9015.h" +#include "af9013.h" +#include "mt2060.h" +#include "qt1010.h" +#include "tda18271.h" +#include "mxl5005s.h" +#if 0 +#include "mc44s80x.h" +#endif + +int dvb_usb_af9015_debug; +module_param_named(debug, dvb_usb_af9015_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); +int dvb_usb_af9015_remote; +module_param_named(remote, dvb_usb_af9015_remote, int, 0644); +MODULE_PARM_DESC(remote, "select remote"); +int dvb_usb_af9015_dual_mode; +module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); +MODULE_PARM_DESC(dual_mode, "enable dual mode"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static DEFINE_MUTEX(af9015_usb_mutex); + +static struct af9015_config af9015_config; +static struct dvb_usb_device_properties af9015_properties[2]; +int af9015_properties_count = ARRAY_SIZE(af9015_properties); + +static struct af9013_config af9015_af9013_config[] = { + { + .demod_address = AF9015_I2C_DEMOD, + .output_mode = AF9013_OUTPUT_MODE_USB, + .api_version = { 0, 1, 9, 0 }, + .gpio[0] = AF9013_GPIO_HI, + .gpio[1] = AF9013_GPIO_LO, + .gpio[3] = AF9013_GPIO_TUNER_ON, + + }, { + .output_mode = AF9013_OUTPUT_MODE_SERIAL, + .api_version = { 0, 1, 9, 0 }, + .gpio[0] = AF9013_GPIO_TUNER_ON, + .gpio[1] = AF9013_GPIO_LO, + } +}; + +static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) +{ + int act_len, ret; + u8 buf[64]; + u8 write = 1; + u8 msg_len = 8; + static u8 seq; /* packet sequence number */ + + if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) + return -EAGAIN; + + buf[0] = req->cmd; + buf[1] = seq++; + buf[2] = req->i2c_addr; + buf[3] = req->addr >> 8; + buf[4] = req->addr & 0xff; + buf[5] = req->mbox; + buf[6] = req->addr_len; + buf[7] = req->data_len; + + switch (req->cmd) { + case GET_CONFIG: + case BOOT: + case READ_MEMORY: + case RECONNECT_USB: + case GET_IR_CODE: + write = 0; + break; + case READ_I2C: + write = 0; + buf[2] |= 0x01; /* set I2C direction */ + case WRITE_I2C: + buf[0] = READ_WRITE_I2C; + break; + case WRITE_MEMORY: + if (((req->addr & 0xff00) == 0xff00) || + ((req->addr & 0xae00) == 0xae00)) + buf[0] = WRITE_VIRTUAL_MEMORY; + case WRITE_VIRTUAL_MEMORY: + case COPY_FIRMWARE: + case DOWNLOAD_FIRMWARE: + break; + default: + err("unknown command:%d", req->cmd); + ret = -1; + goto error_unlock; + } + + /* write requested */ + if (write) { + memcpy(&buf[8], req->data, req->data_len); + msg_len += req->data_len; + } + deb_xfer(">>> "); + debug_dump(buf, msg_len, deb_xfer); + + /* send req */ + ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, + &act_len, AF9015_USB_TIMEOUT); + if (ret) + err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); + else + if (act_len != msg_len) + ret = -1; /* all data is not send */ + if (ret) + goto error_unlock; + + /* no ack for those packets */ + if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) + goto exit_unlock; + + /* receive ack and data if read req */ + msg_len = 1 + 1 + req->data_len; /* seq + status + data len */ + ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, + &act_len, AF9015_USB_TIMEOUT); + if (ret) { + err("recv bulk message failed:%d", ret); + ret = -1; + goto error_unlock; + } + + deb_xfer("<<< "); + debug_dump(buf, act_len, deb_xfer); + + /* remote controller query status is 1 if remote code is not received */ + if (req->cmd == GET_IR_CODE && buf[1] == 1) { + buf[1] = 0; /* clear command "error" status */ + memset(&buf[2], 0, req->data_len); + buf[3] = 1; /* no remote code received mark */ + } + + /* check status */ + if (buf[1]) { + err("command failed:%d", buf[1]); + ret = -1; + goto error_unlock; + } + + /* read request, copy returned data to return buf */ + if (!write) + memcpy(req->data, &buf[2], req->data_len); + +error_unlock: +exit_unlock: + mutex_unlock(&af9015_usb_mutex); + + return ret; +} + +static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) +{ + return af9015_rw_udev(d->udev, req); +} + +static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, + u8 len) +{ + struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, + val}; + return af9015_ctrl_msg(d, &req); +} + +static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) +{ + return af9015_write_regs(d, addr, &val, 1); +} + +static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) +{ + struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val}; + return af9015_ctrl_msg(d, &req); +} + +static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, + u8 val) +{ + struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; + + if (addr == af9015_af9013_config[0].demod_address || + addr == af9015_af9013_config[1].demod_address) + req.addr_len = 3; + + return af9015_ctrl_msg(d, &req); +} + +static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, + u8 *val) +{ + struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; + + if (addr == af9015_af9013_config[0].demod_address || + addr == af9015_af9013_config[1].demod_address) + req.addr_len = 3; + + return af9015_ctrl_msg(d, &req); +} + +static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0, i = 0; + u16 addr; + u8 mbox, addr_len; + struct req_t req; + +/* TODO: implement bus lock + +The bus lock is needed because there is two tuners both using same I2C-address. +Due to that the only way to select correct tuner is use demodulator I2C-gate. + +................................................ +. AF9015 includes integrated AF9013 demodulator. +. ____________ ____________ . ____________ +.| uC | | demod | . | tuner | +.|------------| |------------| . |------------| +.| AF9015 | | AF9013/5 | . | MXL5003 | +.| |--+----I2C-------|-----/ -----|-.-----I2C-------| | +.| | | | addr 0x38 | . | addr 0xc6 | +.|____________| | |____________| . |____________| +.................|.............................. + | ____________ ____________ + | | demod | | tuner | + | |------------| |------------| + | | AF9013 | | MXL5003 | + +----I2C-------|-----/ -----|-------I2C-------| | + | addr 0x3a | | addr 0xc6 | + |____________| |____________| +*/ + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + while (i < num) { + if (msg[i].addr == af9015_af9013_config[0].demod_address || + msg[i].addr == af9015_af9013_config[1].demod_address) { + addr = msg[i].buf[0] << 8; + addr += msg[i].buf[1]; + mbox = msg[i].buf[2]; + addr_len = 3; + } else { + addr = msg[i].buf[0]; + addr_len = 1; + mbox = 0; + } + + if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { + if (msg[i].addr == + af9015_af9013_config[0].demod_address) + req.cmd = READ_MEMORY; + else + req.cmd = READ_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i+1].len; + req.data = &msg[i+1].buf[0]; + ret = af9015_ctrl_msg(d, &req); + i += 2; + } else { + if (msg[i].addr == + af9015_af9013_config[0].demod_address) + req.cmd = WRITE_MEMORY; + else + req.cmd = WRITE_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i].len-addr_len; + req.data = &msg[i].buf[addr_len]; + ret = af9015_ctrl_msg(d, &req); + i += 1; + } + if (ret) + goto error; + + } + ret = i; + +error: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static u32 af9015_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm af9015_i2c_algo = { + .master_xfer = af9015_i2c_xfer, + .functionality = af9015_i2c_func, +}; + +static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) +{ + int ret; + u8 val, mask = 0x01; + + ret = af9015_read_reg(d, addr, &val); + if (ret) + return ret; + + mask <<= bit; + if (op) { + /* set bit */ + val |= mask; + } else { + /* clear bit */ + mask ^= 0xff; + val &= mask; + } + + return af9015_write_reg(d, addr, val); +} + +static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) +{ + return af9015_do_reg_bit(d, addr, bit, 1); +} + +static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) +{ + return af9015_do_reg_bit(d, addr, bit, 0); +} + +static int af9015_init_endpoint(struct dvb_usb_device *d) +{ + int ret; + u16 frame_size; + u8 packet_size; + deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); + +#define TS_PACKET_SIZE 188 + +#define TS_USB20_PACKET_COUNT 348 +#define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) + +#define TS_USB11_PACKET_COUNT 21 +#define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) + +#define TS_USB20_MAX_PACKET_SIZE 512 +#define TS_USB11_MAX_PACKET_SIZE 64 + + if (d->udev->speed == USB_SPEED_FULL) { + frame_size = TS_USB11_FRAME_SIZE/4; + packet_size = TS_USB11_MAX_PACKET_SIZE/4; + } else { + frame_size = TS_USB20_FRAME_SIZE/4; + packet_size = TS_USB20_MAX_PACKET_SIZE/4; + } + + ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ + if (ret) + goto error; + ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ + if (ret) + goto error; + ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ + if (ret) + goto error; + if (af9015_config.dual_mode) { + ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ + if (ret) + goto error; + } + ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ + if (ret) + goto error; + if (af9015_config.dual_mode) { + ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ + if (ret) + goto error; + } + /* EP4 xfer length */ + ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); + if (ret) + goto error; + /* EP5 xfer length */ + ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ + if (ret) + goto error; + if (af9015_config.dual_mode) { + ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ + if (ret) + goto error; + } + + /* enable / disable mp2if2 */ + if (af9015_config.dual_mode) + ret = af9015_set_reg_bit(d, 0xd50b, 0); + else + ret = af9015_clear_reg_bit(d, 0xd50b, 0); +error: + if (ret) + err("endpoint init failed:%d", ret); + return ret; +} + +static int af9015_copy_firmware(struct dvb_usb_device *d) +{ + int ret; + u8 fw_params[4]; + u8 val, i; + struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), + fw_params }; + deb_info("%s:\n", __func__); + + fw_params[0] = af9015_config.firmware_size >> 8; + fw_params[1] = af9015_config.firmware_size & 0xff; + fw_params[2] = af9015_config.firmware_checksum >> 8; + fw_params[3] = af9015_config.firmware_checksum & 0xff; + + /* wait 2nd demodulator ready */ + msleep(100); + + ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val); + if (ret) + goto error; + else + deb_info("%s: firmware status:%02x\n", __func__, val); + + if (val == 0x0c) /* fw is running, no need for download */ + goto exit; + + /* set I2C master clock to fast (to speed up firmware copy) */ + ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ + if (ret) + goto error; + + msleep(50); + + /* copy firmware */ + ret = af9015_ctrl_msg(d, &req); + if (ret) + err("firmware copy cmd failed:%d", ret); + deb_info("%s: firmware copy done\n", __func__); + + /* set I2C master clock back to normal */ + ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ + if (ret) + goto error; + + /* request boot firmware */ + ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address, + 0xe205, 1); + deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); + if (ret) + goto error; + + for (i = 0; i < 15; i++) { + msleep(100); + + /* check firmware status */ + ret = af9015_read_reg_i2c(d, + af9015_af9013_config[1].demod_address, 0x98be, &val); + deb_info("%s: firmware status cmd status:%d fw status:%02x\n", + __func__, ret, val); + if (ret) + goto error; + + if (val == 0x0c || val == 0x04) /* success or fail */ + break; + } + + if (val == 0x04) { + err("firmware did not run"); + ret = -1; + } else if (val != 0x0c) { + err("firmware boot timeout"); + ret = -1; + } + +error: +exit: + return ret; +} + +/* dump eeprom */ +static int af9015_eeprom_dump(struct dvb_usb_device *d) +{ + char buf[52], buf2[4]; + u8 reg, val; + + for (reg = 0; ; reg++) { + if (reg % 16 == 0) { + if (reg) + deb_info("%s\n", buf); + sprintf(buf, "%02x: ", reg); + } + if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) + sprintf(buf2, "%02x ", val); + else + strcpy(buf2, "-- "); + strcat(buf, buf2); + if (reg == 0xff) + break; + } + deb_info("%s\n", buf); + return 0; +} + +int af9015_download_ir_table(struct dvb_usb_device *d) +{ + int i, packets = 0, ret; + u16 addr = 0x9a56; /* ir-table start address */ + struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL}; + u8 *data = NULL; + deb_info("%s:\n", __func__); + + data = af9015_config.ir_table; + packets = af9015_config.ir_table_size; + + /* no remote */ + if (!packets) + goto exit; + + /* load remote ir-table */ + for (i = 0; i < packets; i++) { + req.addr = addr + i; + req.data = &data[i]; + ret = af9015_ctrl_msg(d, &req); + if (ret) { + err("ir-table download failed at packet %d with " \ + "code %d", i, ret); + return ret; + } + } + +exit: + return 0; +} + +static int af9015_init(struct dvb_usb_device *d) +{ + int ret; + deb_info("%s:\n", __func__); + + ret = af9015_init_endpoint(d); + if (ret) + goto error; + + ret = af9015_download_ir_table(d); + if (ret) + goto error; + +error: + return ret; +} + +static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + int ret; + deb_info("%s: onoff:%d\n", __func__, onoff); + + if (onoff) + ret = af9015_set_reg_bit(adap->dev, 0xd503, 0); + else + ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0); + + return ret; +} + +static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + int onoff) +{ + int ret; + u8 idx; + + deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", + __func__, index, pid, onoff); + + ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff)); + if (ret) + goto error; + + ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8)); + if (ret) + goto error; + + idx = ((index & 0x1f) | (1 << 5)); + ret = af9015_write_reg(adap->dev, 0xd504, idx); + +error: + return ret; +} + +static int af9015_download_firmware(struct usb_device *udev, + const struct firmware *fw) +{ + int i, len, packets, remainder, ret; + struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; + u16 addr = 0x5100; /* firmware start address */ + u16 checksum = 0; + + deb_info("%s:\n", __func__); + + /* calc checksum */ + for (i = 0; i < fw->size; i++) + checksum += fw->data[i]; + + af9015_config.firmware_size = fw->size; + af9015_config.firmware_checksum = checksum; + + #define FW_PACKET_MAX_DATA 55 + + packets = fw->size / FW_PACKET_MAX_DATA; + remainder = fw->size % FW_PACKET_MAX_DATA; + len = FW_PACKET_MAX_DATA; + for (i = 0; i <= packets; i++) { + if (i == packets) /* set size of the last packet */ + len = remainder; + + req.data_len = len; + req.data = (fw->data + i * FW_PACKET_MAX_DATA); + req.addr = addr; + addr += FW_PACKET_MAX_DATA; + + ret = af9015_rw_udev(udev, &req); + if (ret) { + err("firmware download failed at packet %d with " \ + "code %d", i, ret); + goto error; + } + } + #undef FW_PACKET_MAX_DATA + + /* firmware loaded, request boot */ + req.cmd = BOOT; + ret = af9015_rw_udev(udev, &req); + if (ret) { + err("firmware boot failed:%d", ret); + goto error; + } + + /* firmware is running, reconnect device in the usb bus */ + req.cmd = RECONNECT_USB; + ret = af9015_rw_udev(udev, &req); + if (ret) + err("reconnect failed: %d", ret); + +error: + return ret; +} + +static int af9015_read_config(struct usb_device *udev) +{ + int ret; + u8 val, i, offset = 0; + struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; + char manufacturer[10]; + + /* IR remote controller */ + req.addr = AF9015_EEPROM_IR_MODE; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + deb_info("%s: IR mode:%d\n", __func__, val); + for (i = 0; i < af9015_properties_count; i++) { + if (val == AF9015_IR_MODE_DISABLED || val == 0x04) { + af9015_properties[i].rc_key_map = NULL; + af9015_properties[i].rc_key_map_size = 0; + } else if (dvb_usb_af9015_remote) { + /* load remote defined as module param */ + switch (dvb_usb_af9015_remote) { + case AF9015_REMOTE_A_LINK_DTU_M: + af9015_properties[i].rc_key_map = + af9015_rc_keys_a_link; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_a_link); + af9015_config.ir_table = af9015_ir_table_a_link; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_a_link); + break; + case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: + af9015_properties[i].rc_key_map = + af9015_rc_keys_msi; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi); + af9015_config.ir_table = af9015_ir_table_msi; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi); + break; + case AF9015_REMOTE_MYGICTV_U718: + af9015_properties[i].rc_key_map = + af9015_rc_keys_mygictv; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_mygictv); + af9015_config.ir_table = + af9015_ir_table_mygictv; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_mygictv); + break; + } + } else { + switch (udev->descriptor.idVendor) { + case cpu_to_le16(USB_VID_LEADTEK): + af9015_properties[i].rc_key_map = + af9015_rc_keys_leadtek; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_leadtek); + af9015_config.ir_table = + af9015_ir_table_leadtek; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_leadtek); + break; + case cpu_to_le16(USB_VID_VISIONPLUS): + if (udev->descriptor.idProduct == + cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) { + af9015_properties[i].rc_key_map = + af9015_rc_keys_twinhan; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_twinhan); + af9015_config.ir_table = + af9015_ir_table_twinhan; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_twinhan); + } + break; + case cpu_to_le16(USB_VID_KWORLD_2): + /* TODO: use correct rc keys */ + af9015_properties[i].rc_key_map = + af9015_rc_keys_twinhan; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_twinhan); + af9015_config.ir_table = af9015_ir_table_kworld; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_kworld); + break; + /* Check USB manufacturer and product strings and try + to determine correct remote in case of chip vendor + reference IDs are used. */ + case cpu_to_le16(USB_VID_AFATECH): + memset(manufacturer, 0, sizeof(manufacturer)); + usb_string(udev, udev->descriptor.iManufacturer, + manufacturer, sizeof(manufacturer)); + if (!strcmp("Geniatech", manufacturer)) { + /* iManufacturer 1 Geniatech + iProduct 2 AF9015 */ + af9015_properties[i].rc_key_map = + af9015_rc_keys_mygictv; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_mygictv); + af9015_config.ir_table = + af9015_ir_table_mygictv; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_mygictv); + } else if (!strcmp("MSI", manufacturer)) { + /* iManufacturer 1 MSI + iProduct 2 MSI K-VOX */ + af9015_properties[i].rc_key_map = + af9015_rc_keys_msi; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi); + af9015_config.ir_table = + af9015_ir_table_msi; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi); + } + break; + } + } + } + + /* TS mode - one or two receivers */ + req.addr = AF9015_EEPROM_TS_MODE; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_config.dual_mode = val; + deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode); + /* disable dual mode by default because it is buggy */ + if (!dvb_usb_af9015_dual_mode) + af9015_config.dual_mode = 0; + + /* set buffer size according to USB port speed */ + for (i = 0; i < af9015_properties_count; i++) { + /* USB1.1 set smaller buffersize and disable 2nd adapter */ + if (udev->speed == USB_SPEED_FULL) { + af9015_properties[i].adapter->stream.u.bulk.buffersize = + TS_USB11_MAX_PACKET_SIZE; + /* disable 2nd adapter because we don't have + PID-filters */ + af9015_config.dual_mode = 0; + } else { + af9015_properties[i].adapter->stream.u.bulk.buffersize = + TS_USB20_MAX_PACKET_SIZE; + } + } + + if (af9015_config.dual_mode) { + /* read 2nd demodulator I2C address */ + req.addr = AF9015_EEPROM_DEMOD2_I2C; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_af9013_config[1].demod_address = val; + + /* enable 2nd adapter */ + for (i = 0; i < af9015_properties_count; i++) + af9015_properties[i].num_adapters = 2; + + } else { + /* disable 2nd adapter */ + for (i = 0; i < af9015_properties_count; i++) + af9015_properties[i].num_adapters = 1; + } + + for (i = 0; i < af9015_properties[0].num_adapters; i++) { + if (i == 1) + offset = AF9015_EEPROM_OFFSET; + /* xtal */ + req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + switch (val) { + case 0: + af9015_af9013_config[i].adc_clock = 28800; + break; + case 1: + af9015_af9013_config[i].adc_clock = 20480; + break; + case 2: + af9015_af9013_config[i].adc_clock = 28000; + break; + case 3: + af9015_af9013_config[i].adc_clock = 25000; + break; + }; + deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i, + val, af9015_af9013_config[i].adc_clock); + + /* tuner IF */ + req.addr = AF9015_EEPROM_IF1H + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_af9013_config[i].tuner_if = val << 8; + req.addr = AF9015_EEPROM_IF1L + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_af9013_config[i].tuner_if += val; + deb_info("%s: [%d] IF1:%d\n", __func__, i, + af9015_af9013_config[0].tuner_if); + + /* MT2060 IF1 */ + req.addr = AF9015_EEPROM_MT2060_IF1H + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_config.mt2060_if1[i] = val << 8; + req.addr = AF9015_EEPROM_MT2060_IF1L + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + af9015_config.mt2060_if1[i] += val; + deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i, + af9015_config.mt2060_if1[i]); + + /* tuner */ + req.addr = AF9015_EEPROM_TUNER_ID1 + offset; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto error; + switch (val) { + case AF9013_TUNER_ENV77H11D5: + case AF9013_TUNER_MT2060: + case AF9013_TUNER_MC44S803: + case AF9013_TUNER_QT1010: + case AF9013_TUNER_UNKNOWN: + case AF9013_TUNER_MT2060_2: + case AF9013_TUNER_TDA18271: + case AF9013_TUNER_QT1010A: + af9015_af9013_config[i].rf_spec_inv = 1; + break; + case AF9013_TUNER_MXL5003D: + case AF9013_TUNER_MXL5005D: + case AF9013_TUNER_MXL5005R: + af9015_af9013_config[i].rf_spec_inv = 0; + break; + default: + warn("tuner id:%d not supported, please report!", val); + return -ENODEV; + }; + + af9015_af9013_config[i].tuner = val; + deb_info("%s: [%d] tuner id:%d\n", __func__, i, val); + } + +error: + if (ret) + err("eeprom read failed:%d", ret); + + return ret; +} + +static int af9015_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + int ret; + u8 reply; + struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; + + ret = af9015_rw_udev(udev, &req); + if (ret) + return ret; + + deb_info("%s: reply:%02x\n", __func__, reply); + if (reply == 0x02) + *cold = 0; + else + *cold = 1; + + return ret; +} + +static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + u8 buf[8]; + struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf}; + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + int i, ret; + + memset(buf, 0, sizeof(buf)); + + ret = af9015_ctrl_msg(d, &req); + if (ret) + return ret; + + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (!buf[1] && keymap[i].custom == buf[0] && + keymap[i].data == buf[2]) { + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + break; + } + } + if (!buf[1]) + deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", + __func__, buf[0], buf[1], buf[2], buf[3], buf[4], + buf[5], buf[6], buf[7]); + + return 0; +} + +/* init 2nd I2C adapter */ +int af9015_i2c_init(struct dvb_usb_device *d) +{ + int ret; + struct af9015_state *state = d->priv; + deb_info("%s:\n", __func__); + + strncpy(state->i2c_adap.name, d->desc->name, + sizeof(state->i2c_adap.name)); +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + state->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, +#else + state->i2c_adap.class = I2C_CLASS_TV_DIGITAL, +#endif + state->i2c_adap.algo = d->props.i2c_algo; + state->i2c_adap.algo_data = NULL; + state->i2c_adap.dev.parent = &d->udev->dev; + + i2c_set_adapdata(&state->i2c_adap, d); + + ret = i2c_add_adapter(&state->i2c_adap); + if (ret < 0) + err("could not add i2c adapter"); + + return ret; +} + +static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct af9015_state *state = adap->dev->priv; + struct i2c_adapter *i2c_adap; + + if (adap->id == 0) { + /* select I2C adapter */ + i2c_adap = &adap->dev->i2c_adap; + + deb_info("%s: init I2C\n", __func__); + ret = af9015_i2c_init(adap->dev); + + /* dump eeprom (debug) */ + ret = af9015_eeprom_dump(adap->dev); + if (ret) + return ret; + } else { + /* select I2C adapter */ + i2c_adap = &state->i2c_adap; + + /* copy firmware to 2nd demodulator */ + if (af9015_config.dual_mode) { + ret = af9015_copy_firmware(adap->dev); + if (ret) { + err("firmware copy to 2nd frontend " \ + "failed, will disable it"); + af9015_config.dual_mode = 0; + return -ENODEV; + } + } else { + return -ENODEV; + } + } + + /* attach demodulator */ + adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], + i2c_adap); + + return adap->fe == NULL ? -ENODEV : 0; +} + +static struct mt2060_config af9015_mt2060_config = { + .i2c_address = 0xc0, + .clock_out = 0, +}; + +static struct qt1010_config af9015_qt1010_config = { + .i2c_address = 0xc4, +}; + +static struct tda18271_config af9015_tda18271_config = { + .gate = TDA18271_GATE_DIGITAL, + .small_i2c = 1, +}; + +static struct mxl5005s_config af9015_mxl5003_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_DEFAULT, + .rssi_enable = MXL_RSSI_DISABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static struct mxl5005s_config af9015_mxl5005_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_OFF, + .rssi_enable = MXL_RSSI_DISABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static int af9015_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct af9015_state *state = adap->dev->priv; + struct i2c_adapter *i2c_adap; + int ret; + deb_info("%s: \n", __func__); + + /* select I2C adapter */ + if (adap->id == 0) + i2c_adap = &adap->dev->i2c_adap; + else + i2c_adap = &state->i2c_adap; + + switch (af9015_af9013_config[adap->id].tuner) { + case AF9013_TUNER_MT2060: + case AF9013_TUNER_MT2060_2: + ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap, + &af9015_mt2060_config, + af9015_config.mt2060_if1[adap->id]) + == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_QT1010: + case AF9013_TUNER_QT1010A: + ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap, + &af9015_qt1010_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_TDA18271: + ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap, + &af9015_tda18271_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MXL5003D: + ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, + &af9015_mxl5003_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MXL5005D: + case AF9013_TUNER_MXL5005R: + ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, + &af9015_mxl5005_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_ENV77H11D5: + ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap, + DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MC44S803: +#if 0 + ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap) + == NULL ? -ENODEV : 0; +#else + ret = -ENODEV; + info("Freescale MC44S803 tuner found but no driver for that" \ + "tuner. Look at the Linuxtv.org for tuner driver" \ + "status."); +#endif + break; + case AF9013_TUNER_UNKNOWN: + default: + ret = -ENODEV; + err("Unknown tuner id:%d", + af9015_af9013_config[adap->id].tuner); + } + return ret; +} + +static struct usb_device_id af9015_usb_table[] = { +/* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)}, + {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)}, + {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)}, + {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)}, +/* 5 */{USB_DEVICE(USB_VID_VISIONPLUS, + USB_PID_TINYTWIN)}, + {USB_DEVICE(USB_VID_VISIONPLUS, + USB_PID_AZUREWAVE_AD_TU700)}, + {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)}, +/* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, + {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, + {0}, +}; +MODULE_DEVICE_TABLE(usb, af9015_usb_table); + +static struct dvb_usb_device_properties af9015_properties[] = { + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9015_download_firmware, + .firmware = "dvb-usb-af9015.fw", + + .size_of_priv = sizeof(struct af9015_state), \ + + .num_adapters = 2, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter = af9015_pid_filter, + .pid_filter_ctrl = af9015_pid_filter_ctrl, + + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + }, + }, + { + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x85, + }, + } + }, + + .identify_state = af9015_identify_state, + + .rc_query = af9015_rc_query, + .rc_interval = 150, + + .i2c_algo = &af9015_i2c_algo, + + .num_device_descs = 9, + .devices = { + { + .name = "Afatech AF9015 DVB-T USB2.0 stick", + .cold_ids = {&af9015_usb_table[0], + &af9015_usb_table[1], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "Leadtek WinFast DTV Dongle Gold", + .cold_ids = {&af9015_usb_table[2], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "Pinnacle PCTV 71e", + .cold_ids = {&af9015_usb_table[3], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "KWorld PlusTV Dual DVB-T Stick " \ + "(DVB-T 399U)", + .cold_ids = {&af9015_usb_table[4], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "DigitalNow TinyTwin DVB-T Receiver", + .cold_ids = {&af9015_usb_table[5], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "TwinHan AzureWave AD-TU700(704J)", + .cold_ids = {&af9015_usb_table[6], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "TerraTec Cinergy T USB XE", + .cold_ids = {&af9015_usb_table[7], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "KWorld PlusTV Dual DVB-T PCI " \ + "(DVB-T PC160-2T)", + .cold_ids = {&af9015_usb_table[8], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "AVerMedia AVerTV DVB-T Volar X", + .cold_ids = {&af9015_usb_table[9], NULL}, + .warm_ids = {NULL}, + }, + } + }, { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9015_download_firmware, + .firmware = "dvb-usb-af9015.fw", + + .size_of_priv = sizeof(struct af9015_state), \ + + .num_adapters = 2, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter = af9015_pid_filter, + .pid_filter_ctrl = af9015_pid_filter_ctrl, + + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + }, + }, + { + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x85, + }, + } + }, + + .identify_state = af9015_identify_state, + + .rc_query = af9015_rc_query, + .rc_interval = 150, + + .i2c_algo = &af9015_i2c_algo, + + .num_device_descs = 3, + .devices = { + { + .name = "Xtensions XD-380", + .cold_ids = {&af9015_usb_table[10], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "MSI DIGIVOX Duo", + .cold_ids = {&af9015_usb_table[11], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "Fujitsu-Siemens Slim Mobile USB DVB-T", + .cold_ids = {&af9015_usb_table[12], NULL}, + .warm_ids = {NULL}, + }, + } + } +}; +#undef AF9015_DEFAULT_PROPERTIES + +static int af9015_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret = 0; + struct dvb_usb_device *d = NULL; + struct usb_device *udev = interface_to_usbdev(intf); + u8 i; + + deb_info("%s: interface:%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + /* interface 0 is used by DVB-T receiver and + interface 1 is for remote controller (HID) */ + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { + ret = af9015_read_config(udev); + if (ret) + return ret; + + for (i = 0; i < af9015_properties_count; i++) { + ret = dvb_usb_device_init(intf, &af9015_properties[i], + THIS_MODULE, &d, adapter_nr); + if (!ret) + break; + if (ret != -ENODEV) + return ret; + } + if (ret) + return ret; + + if (d) + ret = af9015_init(d); + } + + return ret; +} + +void af9015_i2c_exit(struct dvb_usb_device *d) +{ + struct af9015_state *state = d->priv; + deb_info("%s: \n", __func__); + + /* remove 2nd I2C adapter */ + if (d->state & DVB_USB_STATE_I2C) + i2c_del_adapter(&state->i2c_adap); +} + +static void af9015_usb_device_exit(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + deb_info("%s: \n", __func__); + + /* remove 2nd I2C adapter */ + if (d != NULL && d->desc != NULL) + af9015_i2c_exit(d); + + dvb_usb_device_exit(intf); +} + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver af9015_usb_driver = { + .name = "dvb_usb_af9015", + .probe = af9015_usb_probe, + .disconnect = af9015_usb_device_exit, + .id_table = af9015_usb_table, +}; + +/* module stuff */ +static int __init af9015_usb_module_init(void) +{ + int ret; + ret = usb_register(&af9015_usb_driver); + if (ret) + err("module init failed:%d", ret); + + return ret; +} + +static void __exit af9015_usb_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&af9015_usb_driver); +} + +module_init(af9015_usb_module_init); +module_exit(af9015_usb_module_exit); + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h new file mode 100644 index 00000000000..882e8a4b368 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -0,0 +1,524 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _DVB_USB_AF9015_H_ +#define _DVB_USB_AF9015_H_ + +#define DVB_USB_LOG_PREFIX "af9015" +#include "dvb-usb.h" + +extern int dvb_usb_af9015_debug; +#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) +#define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) +#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) +#define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args) +#define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args) +#define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args) + +#define AF9015_I2C_EEPROM 0xa0 +#define AF9015_I2C_DEMOD 0x38 +#define AF9015_USB_TIMEOUT 2000 + +/* EEPROM locations */ +#define AF9015_EEPROM_IR_MODE 0x18 +#define AF9015_EEPROM_IR_REMOTE_TYPE 0x34 +#define AF9015_EEPROM_TS_MODE 0x31 +#define AF9015_EEPROM_DEMOD2_I2C 0x32 + +#define AF9015_EEPROM_SAW_BW1 0x35 +#define AF9015_EEPROM_XTAL_TYPE1 0x36 +#define AF9015_EEPROM_SPEC_INV1 0x37 +#define AF9015_EEPROM_IF1L 0x38 +#define AF9015_EEPROM_IF1H 0x39 +#define AF9015_EEPROM_MT2060_IF1L 0x3a +#define AF9015_EEPROM_MT2060_IF1H 0x3b +#define AF9015_EEPROM_TUNER_ID1 0x3c + +#define AF9015_EEPROM_SAW_BW2 0x45 +#define AF9015_EEPROM_XTAL_TYPE2 0x46 +#define AF9015_EEPROM_SPEC_INV2 0x47 +#define AF9015_EEPROM_IF2L 0x48 +#define AF9015_EEPROM_IF2H 0x49 +#define AF9015_EEPROM_MT2060_IF2L 0x4a +#define AF9015_EEPROM_MT2060_IF2H 0x4b +#define AF9015_EEPROM_TUNER_ID2 0x4c + +#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) + +#define AF9015_GPIO_ON (1 << 0) +#define AF9015_GPIO_EN (1 << 1) +#define AF9015_GPIO_O (1 << 2) +#define AF9015_GPIO_I (1 << 3) + +#define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN) +#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O) + +struct req_t { + u8 cmd; /* [0] */ + /* seq */ /* [1] */ + u8 i2c_addr; /* [2] */ + u16 addr; /* [3|4] */ + u8 mbox; /* [5] */ + u8 addr_len; /* [6] */ + u8 data_len; /* [7] */ + u8 *data; +}; + +enum af9015_cmd { + GET_CONFIG = 0x10, + DOWNLOAD_FIRMWARE = 0x11, + BOOT = 0x13, + READ_MEMORY = 0x20, + WRITE_MEMORY = 0x21, + READ_WRITE_I2C = 0x22, + COPY_FIRMWARE = 0x23, + RECONNECT_USB = 0x5a, + WRITE_VIRTUAL_MEMORY = 0x26, + GET_IR_CODE = 0x27, + READ_I2C, + WRITE_I2C, +}; + +enum af9015_ir_mode { + AF9015_IR_MODE_DISABLED = 0, + AF9015_IR_MODE_HID, + AF9015_IR_MODE_RLC, + AF9015_IR_MODE_RC6, +}; + +struct af9015_state { + struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */ +}; + +struct af9015_config { + u8 dual_mode:1; + u16 mt2060_if1[2]; + u16 firmware_size; + u16 firmware_checksum; + u8 *ir_table; + u16 ir_table_size; +}; + +enum af9015_remote { + AF9015_REMOTE_NONE = 0, + AF9015_REMOTE_A_LINK_DTU_M, + AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, + AF9015_REMOTE_MYGICTV_U718, +}; + +/* Leadtek WinFast DTV Dongle Gold */ +static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { + { 0x00, 0x1e, KEY_1 }, + { 0x00, 0x1f, KEY_2 }, + { 0x00, 0x20, KEY_3 }, + { 0x00, 0x21, KEY_4 }, + { 0x00, 0x22, KEY_5 }, + { 0x00, 0x23, KEY_6 }, + { 0x00, 0x24, KEY_7 }, + { 0x00, 0x25, KEY_8 }, + { 0x00, 0x26, KEY_9 }, + { 0x00, 0x27, KEY_0 }, + { 0x00, 0x28, KEY_ENTER }, + { 0x00, 0x4f, KEY_VOLUMEUP }, + { 0x00, 0x50, KEY_VOLUMEDOWN }, + { 0x00, 0x51, KEY_CHANNELDOWN }, + { 0x00, 0x52, KEY_CHANNELUP }, +}; + +static u8 af9015_ir_table_leadtek[] = { + 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00, + 0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00, + 0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00, + 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00, + 0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00, + 0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00, + 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00, + 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00, + 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00, + 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00, + 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00, + 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00, + 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00, + 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00, + 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00, + 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00, + 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00, + 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00, + 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00, + 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00, + 0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00, + 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00, + 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00, + 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00, + 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00, + 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00, + 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00, + 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00, + 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00, + 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00, + 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00, + 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00, + 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00, + 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00, + 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00, + 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00, + 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00, + 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00, + 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, + 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00, + 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00, + 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00, + 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00, + 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00, + 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00, + 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00, + 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00, + 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00, + 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00, + 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00, +}; + +/* TwinHan AzureWave AD-TU700(704J) */ +static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { + { 0x05, 0x3f, KEY_POWER }, + { 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */ + { 0x00, 0x04, KEY_TEXT }, /* Teletext */ + { 0x00, 0x0e, KEY_POWER }, + { 0x00, 0x0e, KEY_INFO }, /* Preview */ + { 0x00, 0x08, KEY_EPG }, /* Info/EPG */ + { 0x00, 0x0f, KEY_LIST }, /* Record List */ + { 0x00, 0x1e, KEY_1 }, + { 0x00, 0x1f, KEY_2 }, + { 0x00, 0x20, KEY_3 }, + { 0x00, 0x21, KEY_4 }, + { 0x00, 0x22, KEY_5 }, + { 0x00, 0x23, KEY_6 }, + { 0x00, 0x24, KEY_7 }, + { 0x00, 0x25, KEY_8 }, + { 0x00, 0x26, KEY_9 }, + { 0x00, 0x27, KEY_0 }, + { 0x00, 0x29, KEY_CANCEL }, /* Cancel */ + { 0x00, 0x4c, KEY_CLEAR }, /* Clear */ + { 0x00, 0x2a, KEY_BACK }, /* Back */ + { 0x00, 0x2b, KEY_TAB }, /* Tab */ + { 0x00, 0x52, KEY_UP }, /* up arrow */ + { 0x00, 0x51, KEY_DOWN }, /* down arrow */ + { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ + { 0x00, 0x50, KEY_LEFT }, /* left arrow */ + { 0x00, 0x28, KEY_ENTER }, /* Enter / ok */ + { 0x02, 0x52, KEY_VOLUMEUP }, + { 0x02, 0x51, KEY_VOLUMEDOWN }, + { 0x00, 0x4e, KEY_CHANNELDOWN }, + { 0x00, 0x4b, KEY_CHANNELUP }, + { 0x00, 0x4a, KEY_RECORD }, + { 0x01, 0x11, KEY_PLAY }, + { 0x00, 0x17, KEY_PAUSE }, + { 0x00, 0x0c, KEY_REWIND }, /* FR << */ + { 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */ + { 0x01, 0x15, KEY_PREVIOUS }, /* Replay */ + { 0x01, 0x0e, KEY_NEXT }, /* Skip */ + { 0x00, 0x13, KEY_CAMERA }, /* Capture */ + { 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */ + { 0x01, 0x13, KEY_TV2 }, /* PIP */ + { 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */ + { 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */ + { 0x00, 0x10, KEY_MUTE }, + { 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */ + { 0x01, 0x16, KEY_SLEEP }, /* Hibernate */ + { 0x01, 0x16, KEY_SWITCHVIDEOMODE }, + /* A/V */ /* TODO does not work */ + { 0x00, 0x06, KEY_AGAIN }, /* Recall */ + { 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ + { 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ + { 0x02, 0x15, KEY_RED }, + { 0x02, 0x0a, KEY_GREEN }, + { 0x02, 0x1c, KEY_YELLOW }, + { 0x02, 0x05, KEY_BLUE }, +}; + +static u8 af9015_ir_table_twinhan[] = { + 0x00, 0xff, 0x16, 0xe9, 0x3f, 0x05, 0x00, + 0x00, 0xff, 0x07, 0xf8, 0x16, 0x01, 0x00, + 0x00, 0xff, 0x14, 0xeb, 0x11, 0x01, 0x00, + 0x00, 0xff, 0x1a, 0xe5, 0x4d, 0x00, 0x00, + 0x00, 0xff, 0x4c, 0xb3, 0x17, 0x00, 0x00, + 0x00, 0xff, 0x12, 0xed, 0x11, 0x00, 0x00, + 0x00, 0xff, 0x40, 0xbf, 0x0c, 0x00, 0x00, + 0x00, 0xff, 0x11, 0xee, 0x4a, 0x00, 0x00, + 0x00, 0xff, 0x54, 0xab, 0x13, 0x00, 0x00, + 0x00, 0xff, 0x41, 0xbe, 0x15, 0x01, 0x00, + 0x00, 0xff, 0x42, 0xbd, 0x0e, 0x01, 0x00, + 0x00, 0xff, 0x43, 0xbc, 0x17, 0x01, 0x00, + 0x00, 0xff, 0x50, 0xaf, 0x0f, 0x01, 0x00, + 0x00, 0xff, 0x4d, 0xb2, 0x1d, 0x00, 0x00, + 0x00, 0xff, 0x47, 0xb8, 0x13, 0x01, 0x00, + 0x00, 0xff, 0x05, 0xfa, 0x4b, 0x00, 0x00, + 0x00, 0xff, 0x02, 0xfd, 0x4e, 0x00, 0x00, + 0x00, 0xff, 0x0e, 0xf1, 0x06, 0x00, 0x00, + 0x00, 0xff, 0x1e, 0xe1, 0x52, 0x02, 0x00, + 0x00, 0xff, 0x0a, 0xf5, 0x51, 0x02, 0x00, + 0x00, 0xff, 0x10, 0xef, 0x10, 0x00, 0x00, + 0x00, 0xff, 0x49, 0xb6, 0x19, 0x01, 0x00, + 0x00, 0xff, 0x15, 0xea, 0x27, 0x00, 0x00, + 0x00, 0xff, 0x03, 0xfc, 0x1e, 0x00, 0x00, + 0x00, 0xff, 0x01, 0xfe, 0x1f, 0x00, 0x00, + 0x00, 0xff, 0x06, 0xf9, 0x20, 0x00, 0x00, + 0x00, 0xff, 0x09, 0xf6, 0x21, 0x00, 0x00, + 0x00, 0xff, 0x1d, 0xe2, 0x22, 0x00, 0x00, + 0x00, 0xff, 0x1f, 0xe0, 0x23, 0x00, 0x00, + 0x00, 0xff, 0x0d, 0xf2, 0x24, 0x00, 0x00, + 0x00, 0xff, 0x19, 0xe6, 0x25, 0x00, 0x00, + 0x00, 0xff, 0x1b, 0xe4, 0x26, 0x00, 0x00, + 0x00, 0xff, 0x00, 0xff, 0x2b, 0x00, 0x00, + 0x00, 0xff, 0x4a, 0xb5, 0x4c, 0x00, 0x00, + 0x00, 0xff, 0x4b, 0xb4, 0x52, 0x00, 0x00, + 0x00, 0xff, 0x51, 0xae, 0x51, 0x00, 0x00, + 0x00, 0xff, 0x52, 0xad, 0x4f, 0x00, 0x00, + 0x00, 0xff, 0x4e, 0xb1, 0x50, 0x00, 0x00, + 0x00, 0xff, 0x0c, 0xf3, 0x29, 0x00, 0x00, + 0x00, 0xff, 0x4f, 0xb0, 0x28, 0x00, 0x00, + 0x00, 0xff, 0x13, 0xec, 0x2a, 0x00, 0x00, + 0x00, 0xff, 0x17, 0xe8, 0x19, 0x00, 0x00, + 0x00, 0xff, 0x04, 0xfb, 0x0f, 0x00, 0x00, + 0x00, 0xff, 0x48, 0xb7, 0x0e, 0x00, 0x00, + 0x00, 0xff, 0x0f, 0xf0, 0x04, 0x00, 0x00, + 0x00, 0xff, 0x1c, 0xe3, 0x08, 0x00, 0x00, + 0x00, 0xff, 0x18, 0xe7, 0x15, 0x02, 0x00, + 0x00, 0xff, 0x53, 0xac, 0x0a, 0x02, 0x00, + 0x00, 0xff, 0x5e, 0xa1, 0x1c, 0x02, 0x00, + 0x00, 0xff, 0x5f, 0xa0, 0x05, 0x02, 0x00, +}; + +/* A-Link DTU(m) */ +static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { + { 0x00, 0x1e, KEY_1 }, + { 0x00, 0x1f, KEY_2 }, + { 0x00, 0x20, KEY_3 }, + { 0x00, 0x21, KEY_4 }, + { 0x00, 0x22, KEY_5 }, + { 0x00, 0x23, KEY_6 }, + { 0x00, 0x24, KEY_7 }, + { 0x00, 0x25, KEY_8 }, + { 0x00, 0x26, KEY_9 }, + { 0x00, 0x27, KEY_0 }, + { 0x00, 0x2e, KEY_CHANNELUP }, + { 0x00, 0x2d, KEY_CHANNELDOWN }, + { 0x04, 0x28, KEY_ZOOM }, + { 0x00, 0x41, KEY_MUTE }, + { 0x00, 0x42, KEY_VOLUMEDOWN }, + { 0x00, 0x43, KEY_VOLUMEUP }, + { 0x00, 0x44, KEY_GOTO }, /* jump */ + { 0x05, 0x45, KEY_POWER }, +}; + +static u8 af9015_ir_table_a_link[] = { + 0x08, 0xf7, 0x12, 0xed, 0x45, 0x05, 0x00, /* power */ + 0x08, 0xf7, 0x1a, 0xe5, 0x41, 0x00, 0x00, /* mute */ + 0x08, 0xf7, 0x01, 0xfe, 0x1e, 0x00, 0x00, /* 1 */ + 0x08, 0xf7, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ + 0x08, 0xf7, 0x03, 0xfc, 0x24, 0x00, 0x00, /* 7 */ + 0x08, 0xf7, 0x05, 0xfa, 0x28, 0x04, 0x00, /* zoom */ + 0x08, 0xf7, 0x00, 0xff, 0x43, 0x00, 0x00, /* volume up */ + 0x08, 0xf7, 0x16, 0xe9, 0x42, 0x00, 0x00, /* volume down */ + 0x08, 0xf7, 0x0f, 0xf0, 0x1f, 0x00, 0x00, /* 2 */ + 0x08, 0xf7, 0x0d, 0xf2, 0x22, 0x00, 0x00, /* 5 */ + 0x08, 0xf7, 0x1b, 0xe4, 0x25, 0x00, 0x00, /* 8 */ + 0x08, 0xf7, 0x06, 0xf9, 0x27, 0x00, 0x00, /* 0 */ + 0x08, 0xf7, 0x14, 0xeb, 0x2e, 0x00, 0x00, /* channel up */ + 0x08, 0xf7, 0x1d, 0xe2, 0x2d, 0x00, 0x00, /* channel down */ + 0x08, 0xf7, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ + 0x08, 0xf7, 0x18, 0xe7, 0x23, 0x00, 0x00, /* 6 */ + 0x08, 0xf7, 0x04, 0xfb, 0x26, 0x00, 0x00, /* 9 */ + 0x08, 0xf7, 0x07, 0xf8, 0x44, 0x00, 0x00, /* jump */ +}; + +/* MSI DIGIVOX mini II V3.0 */ +static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { + { 0x00, 0x1e, KEY_1 }, + { 0x00, 0x1f, KEY_2 }, + { 0x00, 0x20, KEY_3 }, + { 0x00, 0x21, KEY_4 }, + { 0x00, 0x22, KEY_5 }, + { 0x00, 0x23, KEY_6 }, + { 0x00, 0x24, KEY_7 }, + { 0x00, 0x25, KEY_8 }, + { 0x00, 0x26, KEY_9 }, + { 0x00, 0x27, KEY_0 }, + { 0x03, 0x0f, KEY_CHANNELUP }, + { 0x03, 0x0e, KEY_CHANNELDOWN }, + { 0x00, 0x42, KEY_VOLUMEDOWN }, + { 0x00, 0x43, KEY_VOLUMEUP }, + { 0x05, 0x45, KEY_POWER }, + { 0x00, 0x52, KEY_UP }, /* up */ + { 0x00, 0x51, KEY_DOWN }, /* down */ + { 0x00, 0x28, KEY_ENTER }, +}; + +static u8 af9015_ir_table_msi[] = { + 0x03, 0xfc, 0x17, 0xe8, 0x45, 0x05, 0x00, /* power */ + 0x03, 0xfc, 0x0d, 0xf2, 0x51, 0x00, 0x00, /* down */ + 0x03, 0xfc, 0x03, 0xfc, 0x52, 0x00, 0x00, /* up */ + 0x03, 0xfc, 0x1a, 0xe5, 0x1e, 0x00, 0x00, /* 1 */ + 0x03, 0xfc, 0x02, 0xfd, 0x1f, 0x00, 0x00, /* 2 */ + 0x03, 0xfc, 0x04, 0xfb, 0x20, 0x00, 0x00, /* 3 */ + 0x03, 0xfc, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ + 0x03, 0xfc, 0x08, 0xf7, 0x22, 0x00, 0x00, /* 5 */ + 0x03, 0xfc, 0x1d, 0xe2, 0x23, 0x00, 0x00, /* 6 */ + 0x03, 0xfc, 0x11, 0xee, 0x24, 0x00, 0x00, /* 7 */ + 0x03, 0xfc, 0x0b, 0xf4, 0x25, 0x00, 0x00, /* 8 */ + 0x03, 0xfc, 0x10, 0xef, 0x26, 0x00, 0x00, /* 9 */ + 0x03, 0xfc, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ + 0x03, 0xfc, 0x14, 0xeb, 0x43, 0x00, 0x00, /* volume up */ + 0x03, 0xfc, 0x1f, 0xe0, 0x42, 0x00, 0x00, /* volume down */ + 0x03, 0xfc, 0x15, 0xea, 0x0f, 0x03, 0x00, /* channel up */ + 0x03, 0xfc, 0x05, 0xfa, 0x0e, 0x03, 0x00, /* channel down */ + 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* enter */ +}; + +/* MYGICTV U718 */ +static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { + { 0x00, 0x3d, KEY_SWITCHVIDEOMODE }, + /* TV / AV */ + { 0x05, 0x45, KEY_POWER }, + { 0x00, 0x1e, KEY_1 }, + { 0x00, 0x1f, KEY_2 }, + { 0x00, 0x20, KEY_3 }, + { 0x00, 0x21, KEY_4 }, + { 0x00, 0x22, KEY_5 }, + { 0x00, 0x23, KEY_6 }, + { 0x00, 0x24, KEY_7 }, + { 0x00, 0x25, KEY_8 }, + { 0x00, 0x26, KEY_9 }, + { 0x00, 0x27, KEY_0 }, + { 0x00, 0x41, KEY_MUTE }, + { 0x00, 0x2a, KEY_ESC }, /* Esc */ + { 0x00, 0x2e, KEY_CHANNELUP }, + { 0x00, 0x2d, KEY_CHANNELDOWN }, + { 0x00, 0x42, KEY_VOLUMEDOWN }, + { 0x00, 0x43, KEY_VOLUMEUP }, + { 0x00, 0x52, KEY_UP }, /* up arrow */ + { 0x00, 0x51, KEY_DOWN }, /* down arrow */ + { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ + { 0x00, 0x50, KEY_LEFT }, /* left arrow */ + { 0x00, 0x28, KEY_ENTER }, /* ok */ + { 0x01, 0x15, KEY_RECORD }, + { 0x03, 0x13, KEY_PLAY }, + { 0x01, 0x13, KEY_PAUSE }, + { 0x01, 0x16, KEY_STOP }, + { 0x03, 0x07, KEY_REWIND }, /* FR << */ + { 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */ + { 0x00, 0x3b, KEY_TIME }, /* TimeShift */ + { 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */ + { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */ + { 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */ + { 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */ + { 0x03, 0x45, KEY_POWER }, +}; + +static u8 af9015_ir_table_mygictv[] = { + 0x02, 0xbd, 0x0c, 0xf3, 0x3d, 0x00, 0x00, /* TV / AV */ + 0x02, 0xbd, 0x14, 0xeb, 0x45, 0x05, 0x00, /* power */ + 0x02, 0xbd, 0x00, 0xff, 0x1e, 0x00, 0x00, /* 1 */ + 0x02, 0xbd, 0x01, 0xfe, 0x1f, 0x00, 0x00, /* 2 */ + 0x02, 0xbd, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ + 0x02, 0xbd, 0x03, 0xfc, 0x21, 0x00, 0x00, /* 4 */ + 0x02, 0xbd, 0x04, 0xfb, 0x22, 0x00, 0x00, /* 5 */ + 0x02, 0xbd, 0x05, 0xfa, 0x23, 0x00, 0x00, /* 6 */ + 0x02, 0xbd, 0x06, 0xf9, 0x24, 0x00, 0x00, /* 7 */ + 0x02, 0xbd, 0x07, 0xf8, 0x25, 0x00, 0x00, /* 8 */ + 0x02, 0xbd, 0x08, 0xf7, 0x26, 0x00, 0x00, /* 9 */ + 0x02, 0xbd, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ + 0x02, 0xbd, 0x0a, 0xf5, 0x41, 0x00, 0x00, /* mute */ + 0x02, 0xbd, 0x1c, 0xe3, 0x2a, 0x00, 0x00, /* esc */ + 0x02, 0xbd, 0x1f, 0xe0, 0x43, 0x00, 0x00, /* volume up */ + 0x02, 0xbd, 0x12, 0xed, 0x52, 0x00, 0x00, /* up arrow */ + 0x02, 0xbd, 0x11, 0xee, 0x50, 0x00, 0x00, /* left arrow */ + 0x02, 0xbd, 0x15, 0xea, 0x28, 0x00, 0x00, /* ok */ + 0x02, 0xbd, 0x10, 0xef, 0x4f, 0x00, 0x00, /* right arrow */ + 0x02, 0xbd, 0x13, 0xec, 0x51, 0x00, 0x00, /* down arrow */ + 0x02, 0xbd, 0x0e, 0xf1, 0x42, 0x00, 0x00, /* volume down */ + 0x02, 0xbd, 0x19, 0xe6, 0x15, 0x01, 0x00, /* record */ + 0x02, 0xbd, 0x1e, 0xe1, 0x13, 0x03, 0x00, /* play */ + 0x02, 0xbd, 0x16, 0xe9, 0x16, 0x01, 0x00, /* stop */ + 0x02, 0xbd, 0x0b, 0xf4, 0x28, 0x04, 0x00, /* yellow, min / max */ + 0x02, 0xbd, 0x0f, 0xf0, 0x3b, 0x00, 0x00, /* time shift */ + 0x02, 0xbd, 0x18, 0xe7, 0x2e, 0x00, 0x00, /* channel up */ + 0x02, 0xbd, 0x1a, 0xe5, 0x2d, 0x00, 0x00, /* channel down */ + 0x02, 0xbd, 0x17, 0xe8, 0x3e, 0x00, 0x00, /* snapshot */ + 0x02, 0xbd, 0x40, 0xbf, 0x13, 0x01, 0x00, /* pause */ + 0x02, 0xbd, 0x41, 0xbe, 0x09, 0x03, 0x00, /* FF >> */ + 0x02, 0xbd, 0x42, 0xbd, 0x07, 0x03, 0x00, /* FR << */ + 0x02, 0xbd, 0x43, 0xbc, 0x00, 0x00, 0x00, /* 'select' (?) */ + 0x02, 0xbd, 0x44, 0xbb, 0x16, 0x03, 0x00, /* shuffle */ + 0x02, 0xbd, 0x45, 0xba, 0x45, 0x03, 0x00, /* power */ +}; + +/* KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) */ +static u8 af9015_ir_table_kworld[] = { + 0x86, 0x6b, 0x0c, 0xf3, 0x2e, 0x07, 0x00, + 0x86, 0x6b, 0x16, 0xe9, 0x2d, 0x07, 0x00, + 0x86, 0x6b, 0x1d, 0xe2, 0x37, 0x07, 0x00, + 0x86, 0x6b, 0x00, 0xff, 0x1e, 0x07, 0x00, + 0x86, 0x6b, 0x01, 0xfe, 0x1f, 0x07, 0x00, + 0x86, 0x6b, 0x02, 0xfd, 0x20, 0x07, 0x00, + 0x86, 0x6b, 0x03, 0xfc, 0x21, 0x07, 0x00, + 0x86, 0x6b, 0x04, 0xfb, 0x22, 0x07, 0x00, + 0x86, 0x6b, 0x05, 0xfa, 0x23, 0x07, 0x00, + 0x86, 0x6b, 0x06, 0xf9, 0x24, 0x07, 0x00, + 0x86, 0x6b, 0x07, 0xf8, 0x25, 0x07, 0x00, + 0x86, 0x6b, 0x08, 0xf7, 0x26, 0x07, 0x00, + 0x86, 0x6b, 0x09, 0xf6, 0x4d, 0x07, 0x00, + 0x86, 0x6b, 0x0a, 0xf5, 0x4e, 0x07, 0x00, + 0x86, 0x6b, 0x14, 0xeb, 0x4f, 0x07, 0x00, + 0x86, 0x6b, 0x1e, 0xe1, 0x50, 0x07, 0x00, + 0x86, 0x6b, 0x17, 0xe8, 0x52, 0x07, 0x00, + 0x86, 0x6b, 0x1f, 0xe0, 0x51, 0x07, 0x00, + 0x86, 0x6b, 0x0e, 0xf1, 0x0b, 0x07, 0x00, + 0x86, 0x6b, 0x20, 0xdf, 0x0c, 0x07, 0x00, + 0x86, 0x6b, 0x42, 0xbd, 0x0d, 0x07, 0x00, + 0x86, 0x6b, 0x0b, 0xf4, 0x0e, 0x07, 0x00, + 0x86, 0x6b, 0x43, 0xbc, 0x0f, 0x07, 0x00, + 0x86, 0x6b, 0x10, 0xef, 0x10, 0x07, 0x00, + 0x86, 0x6b, 0x21, 0xde, 0x11, 0x07, 0x00, + 0x86, 0x6b, 0x13, 0xec, 0x12, 0x07, 0x00, + 0x86, 0x6b, 0x11, 0xee, 0x13, 0x07, 0x00, + 0x86, 0x6b, 0x12, 0xed, 0x14, 0x07, 0x00, + 0x86, 0x6b, 0x19, 0xe6, 0x15, 0x07, 0x00, + 0x86, 0x6b, 0x1a, 0xe5, 0x16, 0x07, 0x00, + 0x86, 0x6b, 0x1b, 0xe4, 0x17, 0x07, 0x00, + 0x86, 0x6b, 0x4b, 0xb4, 0x18, 0x07, 0x00, + 0x86, 0x6b, 0x40, 0xbf, 0x19, 0x07, 0x00, + 0x86, 0x6b, 0x44, 0xbb, 0x1a, 0x07, 0x00, + 0x86, 0x6b, 0x41, 0xbe, 0x1b, 0x07, 0x00, + 0x86, 0x6b, 0x22, 0xdd, 0x1c, 0x07, 0x00, + 0x86, 0x6b, 0x15, 0xea, 0x1d, 0x07, 0x00, + 0x86, 0x6b, 0x0f, 0xf0, 0x3f, 0x07, 0x00, + 0x86, 0x6b, 0x1c, 0xe3, 0x40, 0x07, 0x00, + 0x86, 0x6b, 0x4a, 0xb5, 0x41, 0x07, 0x00, + 0x86, 0x6b, 0x48, 0xb7, 0x42, 0x07, 0x00, + 0x86, 0x6b, 0x49, 0xb6, 0x43, 0x07, 0x00, + 0x86, 0x6b, 0x18, 0xe7, 0x44, 0x07, 0x00, + 0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00, +}; + +#endif diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 81369b79e75..2558f2b51c2 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -34,12 +34,14 @@ #define USB_VID_HAUPPAUGE 0x2040 #define USB_VID_HYPER_PALTEK 0x1025 #define USB_VID_KWORLD 0xeb2a +#define USB_VID_KWORLD_2 0x1b80 #define USB_VID_KYE 0x0458 #define USB_VID_LEADTEK 0x0413 #define USB_VID_LITEON 0x04ca #define USB_VID_MEDION 0x1660 #define USB_VID_MIGLIA 0x18f3 #define USB_VID_MSI 0x0db0 +#define USB_VID_MSI_2 0x1462 #define USB_VID_OPERA1 0x695c #define USB_VID_PINNACLE 0x2304 #define USB_VID_TECHNOTREND 0x0b48 @@ -51,15 +53,18 @@ #define USB_VID_WIDEVIEW 0x14aa #define USB_VID_GIGABYTE 0x1044 #define USB_VID_YUAN 0x1164 - +#define USB_VID_XTENSIONS 0x1ae7 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 #define USB_PID_ADSTECH_USB2_WARM 0xa334 #define USB_PID_AFATECH_AF9005 0x9020 +#define USB_PID_AFATECH_AF9015_9015 0x9015 +#define USB_PID_AFATECH_AF9015_9016 0x9016 #define USB_VID_ALINK_DTU 0xf170 #define USB_PID_ANSONIC_DVBT_USB 0x6000 #define USB_PID_ANYSEE 0x861f +#define USB_PID_AZUREWAVE_AD_TU700 0x3237 #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 @@ -89,9 +94,12 @@ #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 +#define USB_PID_KWORLD_399U 0xe399 +#define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 +#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 #define USB_PID_TWINHAN_VP7041_COLD 0x3201 #define USB_PID_TWINHAN_VP7041_WARM 0x3202 #define USB_PID_TWINHAN_VP7020_COLD 0x3203 @@ -100,6 +108,7 @@ #define USB_PID_TWINHAN_VP7045_WARM 0x3206 #define USB_PID_TWINHAN_VP7021_COLD 0x3207 #define USB_PID_TWINHAN_VP7021_WARM 0x3208 +#define USB_PID_TINYTWIN 0x3226 #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 @@ -146,6 +155,8 @@ #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 +#define USB_PID_AVERMEDIA_VOLAR_X 0xa815 +#define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 @@ -155,6 +166,7 @@ #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 +#define USB_PID_PINNACLE_PCTV71E 0x022b #define USB_PID_PINNACLE_PCTV72E 0x0236 #define USB_PID_PINNACLE_PCTV73E 0x0237 #define USB_PID_PCTV_200E 0x020e @@ -193,6 +205,7 @@ #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 +#define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 #define USB_PID_GENPIX_8PSK_REV_2 0x0202 @@ -200,6 +213,7 @@ #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 #define USB_PID_SIGMATEK_DVB_110 0x6610 #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 +#define USB_PID_MSI_DIGIVOX_DUO 0x8801 #define USB_PID_OPERA1_COLD 0x2830 #define USB_PID_OPERA1_WARM 0x3829 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 @@ -209,5 +223,6 @@ #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_DW2102 0x2102 +#define USB_PID_XTENSIONS_XD_380 0x0381 #endif -- GitLab From 28f947a95386861c54de2bf7753dda011c8e15c3 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Sep 2008 14:22:43 -0300 Subject: [PATCH 4094/5416] V4L/DVB (8973): af9013: fix compile error coming from u64 div - fix compile error coming from u64 div Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/af9013.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 9f2129d544c..50e1e3f300a 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -941,7 +941,6 @@ static int af9013_update_ber_unc(struct dvb_frontend *fe) u32 error_bit_count = 0; u32 total_bit_count = 0; u32 abort_packet_count = 0; - u64 numerator, denominator; state->ber = 0; @@ -979,11 +978,8 @@ static int af9013_update_ber_unc(struct dvb_frontend *fe) total_bit_count = total_bit_count - abort_packet_count; total_bit_count = total_bit_count * 204 * 8; - if (total_bit_count) { - numerator = error_bit_count * 1000000000; - denominator = total_bit_count; - state->ber = numerator / denominator; - } + if (total_bit_count) + state->ber = error_bit_count * 1000000000 / total_bit_count; state->ucblocks += abort_packet_count; -- GitLab From 111f9ecf174655f3da2b266602f20f11e6a6a4c7 Mon Sep 17 00:00:00 2001 From: Mikko Ohtamaa Date: Fri, 19 Sep 2008 18:26:05 -0300 Subject: [PATCH 4095/5416] V4L/DVB (8974): af9015: Add USB ID for Telestar Starstick 2 - Add USB ID for Telestar Starstick 2 (10b9:8000) Signed-off-by: Mikko Ohtamaa Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 8 +++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index a284648094c..505432b10b8 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1196,6 +1196,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, + {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1346,7 +1347,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { .name = "Xtensions XD-380", @@ -1363,6 +1364,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[12], NULL}, .warm_ids = {NULL}, }, + { + .name = "Telestar USB DVB-T", + .cold_ids = {&af9015_usb_table[13], NULL}, + .warm_ids = {NULL}, + }, } } }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 2558f2b51c2..60c241e0236 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -46,6 +46,7 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_TECHNOTREND 0x0b48 #define USB_VID_TERRATEC 0x0ccd +#define USB_VID_TELESTAR 0x10b9 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 @@ -224,5 +225,6 @@ #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 +#define USB_PID_TELESTAR 0x8000 #endif -- GitLab From a3765888a7edc4efe54293d8f7c6676cae61057e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 19 Sep 2008 18:34:06 -0300 Subject: [PATCH 4096/5416] V4L/DVB (8975): af9015: cleanup - cleanup Telestar Starstick 2 patch Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 4 ++-- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 505432b10b8..f962d89db13 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1196,7 +1196,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, - {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR)}, + {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1365,7 +1365,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .warm_ids = {NULL}, }, { - .name = "Telestar USB DVB-T", + .name = "Telestar Starstick 2", .cold_ids = {&af9015_usb_table[13], NULL}, .warm_ids = {NULL}, }, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 60c241e0236..66dc000d4e4 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -225,6 +225,6 @@ #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 -#define USB_PID_TELESTAR 0x8000 +#define USB_PID_TELESTAR_STARSTICK_2 0x8000 #endif -- GitLab From 05c1cab55c282199b85138dc1900b5d9bd6fb32a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 22 Sep 2008 12:32:37 -0300 Subject: [PATCH 4097/5416] V4L/DVB (8976): af9015: Add USB ID for AVerMedia A309 - AVerMedia A309 Mini Card (07ca:a309) Thanks-to: Dirk Vornheder Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 8 +++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index f962d89db13..3f6217bd063 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1197,6 +1197,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1347,7 +1348,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 4, + .num_device_descs = 5, .devices = { { .name = "Xtensions XD-380", @@ -1369,6 +1370,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[13], NULL}, .warm_ids = {NULL}, }, + { + .name = "AVerMedia A309", + .cold_ids = {&af9015_usb_table[14], NULL}, + .warm_ids = {NULL}, + }, } } }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 66dc000d4e4..7ae262e08f8 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -158,6 +158,7 @@ #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 +#define USB_PID_AVERMEDIA_A309 0xa309 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 -- GitLab From 6b73eeafbc856c0cef7166242f0e55403407f355 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 4 Sep 2008 01:12:25 -0300 Subject: [PATCH 4098/5416] V4L/DVB (8985): S2API: Added dvb frontend changes to support a newer tuning API This is an experimental patch to add a new tuning mechanism for dvb frontends. Rather than passing fixed structures across the user/kernel boundary, which need to be revised for each new modulation type (or feature the kernel developers want to add), this implements a simpler message based approach, allowing fe commands to be broken down into a series of small fixed size transactions, presented in an array. The goal is to avoid changing the user/kernel ABI in the future, by simply creating new frontend commands (and sequencies of commands) that help us add support for brand new demodulator, delivery system or statistics related commmands. known issues: checkpatch voilations feedback from various developers yet to be implemented, relating to namespace conventions, variable length array passing conventions, and generally some optimization. This patch should support all existing tuning mechanisms through the new API, as well as adding 8PSK, DVB-S2 NBC-QPSK and ISDB-T API support. For testing and exercise purposes, see the latest tune.c tool available from http://www.steventoth.net/linux/s2 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 571 +++++++++++++++++++++- drivers/media/dvb/dvb-core/dvb_frontend.h | 44 ++ include/linux/dvb/frontend.h | 130 ++++- 3 files changed, 737 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 3526e3ee948..e68974b2fee 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -755,6 +755,535 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, return 0; } +struct tv_cmds_h tv_cmds[] = { + [TV_SEQ_UNDEFINED] = { + .name = "TV_SEQ_UNDEFINED", + .cmd = TV_SEQ_UNDEFINED, + .set = 1, + }, + [TV_SEQ_START] = { + .name = "TV_SEQ_START", + .cmd = TV_SEQ_START, + .set = 1, + }, + [TV_SEQ_CONTINUE] = { + .name = "TV_SEQ_CONTINUE", + .cmd = TV_SEQ_CONTINUE, + .set = 1, + }, + [TV_SEQ_COMPLETE] = { + .name = "TV_SEQ_COMPLETE", + .cmd = TV_SEQ_COMPLETE, + .set = 1, + }, + [TV_SEQ_TERMINATE] = { + .name = "TV_SEQ_TERMINATE", + .cmd = TV_SEQ_TERMINATE, + .set = 1, + }, + + /* Set */ + [TV_SET_FREQUENCY] = { + .name = "TV_SET_FREQUENCY", + .cmd = TV_SET_FREQUENCY, + .set = 1, + }, + [TV_SET_BANDWIDTH] = { + .name = "TV_SET_BANDWIDTH", + .cmd = TV_SET_BANDWIDTH, + .set = 1, + }, + [TV_SET_MODULATION] = { + .name = "TV_SET_MODULATION", + .cmd = TV_SET_MODULATION, + .set = 1, + }, + [TV_SET_INVERSION] = { + .name = "TV_SET_INVERSION", + .cmd = TV_SET_INVERSION, + .set = 1, + }, + [TV_SET_DISEQC_MASTER] = { + .name = "TV_SET_DISEQC_MASTER", + .cmd = TV_SET_DISEQC_MASTER, + .set = 1, + .buffer = 1, + }, + [TV_SET_SYMBOLRATE] = { + .name = "TV_SET_SYMBOLRATE", + .cmd = TV_SET_SYMBOLRATE, + .set = 1, + }, + [TV_SET_INNERFEC] = { + .name = "TV_SET_INNERFEC", + .cmd = TV_SET_INNERFEC, + .set = 1, + }, + [TV_SET_VOLTAGE] = { + .name = "TV_SET_VOLTAGE", + .cmd = TV_SET_VOLTAGE, + .set = 1, + }, + [TV_SET_TONE] = { + .name = "TV_SET_TONE", + .cmd = TV_SET_TONE, + .set = 1, + }, + [TV_SET_PILOT] = { + .name = "TV_SET_PILOT", + .cmd = TV_SET_PILOT, + .set = 1, + }, + [TV_SET_ROLLOFF] = { + .name = "TV_SET_ROLLOFF", + .cmd = TV_SET_ROLLOFF, + .set = 1, + }, + [TV_SET_DELIVERY_SYSTEM] = { + .name = "TV_SET_DELIVERY_SYSTEM", + .cmd = TV_SET_DELIVERY_SYSTEM, + .set = 1, + }, + [TV_SET_ISDB_SEGMENT_NUM] = { + .name = "TV_SET_ISDB_SEGMENT_NUM", + .cmd = TV_SET_ISDB_SEGMENT_NUM, + .set = 1, + }, + [TV_SET_ISDB_SEGMENT_WIDTH] = { + .name = "TV_SET_ISDB_SEGMENT_WIDTH", + .cmd = TV_SET_ISDB_SEGMENT_WIDTH, + .set = 1, + }, + + /* Get */ + [TV_GET_FREQUENCY] = { + .name = "TV_GET_FREQUENCY", + .cmd = TV_GET_FREQUENCY, + .set = 0, + }, + [TV_GET_BANDWIDTH] = { + .name = "TV_GET_BANDWIDTH", + .cmd = TV_GET_BANDWIDTH, + .set = 0, + }, + [TV_GET_MODULATION] = { + .name = "TV_GET_MODULATION", + .cmd = TV_GET_MODULATION, + .set = 0, + }, + [TV_GET_INVERSION] = { + .name = "TV_GET_INVERSION", + .cmd = TV_GET_INVERSION, + .set = 0, + }, + [TV_GET_DISEQC_SLAVE_REPLY] = { + .name = "TV_GET_DISEQC_SLAVE_REPLY", + .cmd = TV_GET_DISEQC_SLAVE_REPLY, + .set = 0, + .buffer = 1, + }, + [TV_GET_SYMBOLRATE] = { + .name = "TV_GET_SYMBOLRATE", + .cmd = TV_GET_SYMBOLRATE, + .set = 0, + }, + [TV_GET_INNERFEC] = { + .name = "TV_GET_INNERFEC", + .cmd = TV_GET_INNERFEC, + .set = 0, + }, + [TV_GET_VOLTAGE] = { + .name = "TV_GET_VOLTAGE", + .cmd = TV_GET_VOLTAGE, + .set = 0, + }, + [TV_GET_TONE] = { + .name = "TV_GET_TONE", + .cmd = TV_GET_TONE, + .set = 0, + }, + [TV_GET_PILOT] = { + .name = "TV_GET_PILOT", + .cmd = TV_GET_PILOT, + .set = 0, + }, + [TV_GET_ROLLOFF] = { + .name = "TV_GET_ROLLOFF", + .cmd = TV_GET_ROLLOFF, + .set = 0, + }, + [TV_GET_DELIVERY_SYSTEM] = { + .name = "TV_GET_DELIVERY_SYSTEM", + .cmd = TV_GET_DELIVERY_SYSTEM, + .set = 0, + }, + [TV_GET_ISDB_SEGMENT_NUM] = { + .name = "TV_GET_ISDB_SEGMENT_NUM", + .cmd = TV_GET_ISDB_SEGMENT_NUM, + .set = 0, + }, + [TV_GET_ISDB_SEGMENT_WIDTH] = { + .name = "TV_GET_ISDB_SEGMENT_WIDTH", + .cmd = TV_GET_ISDB_SEGMENT_WIDTH, + .set = 0, + }, + [TV_GET_ISDB_LAYERA_FEC] = { + .name = "TV_GET_ISDB_LAYERA_FEC", + .cmd = TV_GET_ISDB_LAYERA_FEC, + .set = 0, + }, + [TV_GET_ISDB_LAYERA_MODULATION] = { + .name = "TV_GET_ISDB_LAYERA_MODULATION", + .cmd = TV_GET_ISDB_LAYERA_MODULATION, + .set = 0, + }, + [TV_GET_ISDB_LAYERA_SEGMENT_WIDTH] = { + .name = "TV_GET_ISDB_LAYERA_SEGMENT_WIDTH", + .cmd = TV_GET_ISDB_LAYERA_SEGMENT_WIDTH, + .set = 0, + }, + [TV_GET_ISDB_LAYERB_FEC] = { + .name = "TV_GET_ISDB_LAYERB_FEC", + .cmd = TV_GET_ISDB_LAYERB_FEC, + .set = 0, + }, + [TV_GET_ISDB_LAYERB_MODULATION] = { + .name = "TV_GET_ISDB_LAYERB_MODULATION", + .cmd = TV_GET_ISDB_LAYERB_MODULATION, + .set = 0, + }, + [TV_GET_ISDB_LAYERB_SEGMENT_WIDTH] = { + .name = "TV_GET_ISDB_LAYERB_SEGMENT_WIDTH", + .cmd = TV_GET_ISDB_LAYERB_SEGMENT_WIDTH, + .set = 0, + }, + [TV_GET_ISDB_LAYERC_FEC] = { + .name = "TV_GET_ISDB_LAYERC_FEC", + .cmd = TV_GET_ISDB_LAYERC_FEC, + .set = 0, + }, + [TV_GET_ISDB_LAYERC_MODULATION] = { + .name = "TV_GET_ISDB_LAYERC_MODULATION", + .cmd = TV_GET_ISDB_LAYERC_MODULATION, + .set = 0, + }, + [TV_GET_ISDB_LAYERC_SEGMENT_WIDTH] = { + .name = "TV_GET_ISDB_LAYERC_SEGMENT_WIDTH", + .cmd = TV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + .set = 0, + }, +}; + +void tv_property_dump(tv_property_t *tvp) +{ + int i; + + printk("%s() tvp.cmd = 0x%08x (%s)\n" + ,__FUNCTION__ + ,tvp->cmd + ,tv_cmds[ tvp->cmd ].name); + + if(tv_cmds[ tvp->cmd ].buffer) { + + printk("%s() tvp.u.buffer.len = 0x%02x\n" + ,__FUNCTION__ + ,tvp->u.buffer.len); + + for(i = 0; i < tvp->u.buffer.len; i++) + printk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" + ,__FUNCTION__ + ,i + ,tvp->u.buffer.data[i]); + + } else + printk("%s() tvp.u.data = 0x%08x\n", __FUNCTION__, tvp->u.data); +} + +int is_legacy_delivery_system(fe_delivery_system_t s) +{ + if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || + (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS)) + return 1; + + return 0; +} + +int tv_property_cache_submit(struct dvb_frontend *fe) +{ + + /* We have to do one of two things: + * To support legacy devices using the new API we take values from + * the tv_cache and generate a legacy truning structure. + * + * Or, + * + * To support advanced tuning devices with the new API we + * notify the new advance driver type that a tuning operation is required + * and let it pull values from the cache as is, we don't need to + * pass structures. + * + * We'll use the modulation type to assess how this is handled. as the API + * progresses we'll probably want to have a flag in dvb_frontend_ops + * to allow the frontend driver to dictate how it likes to be tuned. + * + * Because of how this is attached to the ioctl handler for legacy support, + * it's important to return an appropriate result code with atleast the following + * three meanings: + * < 0 = processing error + * 0 = lecagy ioctl handler to submit a traditional set_frontend() call. + * 1 = lecagy ioctl handler should NOT submit a traditional set_frontend() call. + */ + + int r; + + struct tv_frontend_properties *c = &fe->tv_property_cache; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dvb_frontend_parameters p; + + printk("%s()\n", __FUNCTION__); + + /* For legacy delivery systems we don't need the delivery_system to be specified */ + if(is_legacy_delivery_system(c->delivery_system)) { + switch(c->modulation) { + case QPSK: + printk("%s() Preparing QPSK req\n", __FUNCTION__); + p.frequency = c->frequency; + p.inversion = c->inversion; + p.u.qpsk.symbol_rate = c->symbol_rate; + p.u.qpsk.fec_inner = c->fec_inner; + memcpy(&fepriv->parameters, &p, + sizeof (struct dvb_frontend_parameters)); + + /* Call the traditional tuning mechanisms. */ + + r = 0; + break; + case QAM_16: + case QAM_32: + case QAM_64: + case QAM_128: + case QAM_256: + case QAM_AUTO: + printk("%s() Preparing QAM req\n", __FUNCTION__); + p.frequency = c->frequency; + p.inversion = c->inversion; + p.u.qam.symbol_rate = c->symbol_rate; + p.u.vsb.modulation = c->modulation; + printk("%s() frequency = %d\n", __FUNCTION__, p.frequency); + printk("%s() QAM = %d\n", __FUNCTION__, p.u.vsb.modulation); + memcpy(&fepriv->parameters, &p, + sizeof (struct dvb_frontend_parameters)); + + /* At this point we're fully formed for backwards + * compatability and we need to return this + * via the ioctl handler as SET_FRONTEND (arg). + * We've already patched the new values into the + * frontends tuning structures so the ioctl code just + * continues as if a legacy tune structure was passed + * from userspace. + */ + + r = 0; + break; + case VSB_8: + case VSB_16: + printk("%s() Preparing VSB req\n", __FUNCTION__); + p.frequency = c->frequency; + p.u.vsb.modulation = c->modulation; + memcpy(&fepriv->parameters, &p, + sizeof (struct dvb_frontend_parameters)); + + /* Call the traditional tuning mechanisms. */ + + r = 0; + break; + /* TODO: Add any missing modulation types */ + default: + r = -1; + } + } else { + /* For advanced delivery systems / modulation types ... + * we seed the lecacy dvb_frontend_parameters structure + * so that the sanity checking code later in the IOCTL processing + * can validate our basic frequency ranges, symbolrates, modulation + * etc. + */ + r = -1; + + switch(c->modulation) { + case _8PSK: + case _16APSK: + case NBC_QPSK: + /* Just post a notification to the demod driver and let it pull + * the specific values it wants from its tv_property_cache. + * It can decide how best to use those parameters. + * IOCTL will call set_frontend (by default) due to zigzag + * support etc. + */ + if (fe->ops.set_params) + r = fe->ops.set_params(fe); + + p.frequency = c->frequency; + p.inversion = c->inversion; + p.u.qpsk.symbol_rate = c->symbol_rate; + p.u.qpsk.fec_inner = c->fec_inner; + memcpy(&fepriv->parameters, &p, + sizeof (struct dvb_frontend_parameters)); + + r = 0; + break; + default: + r = -1; + } + + if(c->delivery_system == SYS_ISDBT) { + /* Fake out a generic DVB-T request so we pass validation in the ioctl */ + p.frequency = c->frequency; + p.inversion = INVERSION_AUTO; + p.u.ofdm.constellation = QAM_AUTO; + p.u.ofdm.code_rate_HP = FEC_AUTO; + p.u.ofdm.code_rate_LP = FEC_AUTO; + p.u.ofdm.bandwidth = BANDWIDTH_AUTO; + p.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + p.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + p.u.ofdm.hierarchy_information = HIERARCHY_AUTO; + memcpy(&fepriv->parameters, &p, + sizeof (struct dvb_frontend_parameters)); + + r = 0; + } + } + return r; +} + +int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp) +{ + int r = 0; + printk("%s()\n", __FUNCTION__); + tv_property_dump(tvp); + + switch(tvp->cmd) { + case TV_SEQ_START: + case TV_SEQ_TERMINATE: + /* Reset a cache of data specific to the frontend here. This does + * not effect hardware. + */ + printk("%s() Flushing property cache\n", __FUNCTION__); + memset(&fe->tv_property_cache, 0, sizeof(struct tv_frontend_properties)); + fe->tv_property_cache.state = TV_SEQ_START; + fe->tv_property_cache.delivery_system = SYS_UNDEFINED; + break; + case TV_SEQ_COMPLETE: + /* interpret the cache of data, build either a traditional frontend + * tunerequest and submit it to a subset of the ioctl handler, + * or, call a new undefined method on the frontend to deal with + * all new tune requests. + */ + fe->tv_property_cache.state = TV_SEQ_COMPLETE; + printk("%s() Finalised property cache\n", __FUNCTION__); + r = tv_property_cache_submit(fe); + break; + case TV_SET_FREQUENCY: + fe->tv_property_cache.frequency = tvp->u.data; + break; + case TV_GET_FREQUENCY: + tvp->u.data = fe->tv_property_cache.frequency; + break; + case TV_SET_MODULATION: + fe->tv_property_cache.modulation = tvp->u.data; + break; + case TV_GET_MODULATION: + tvp->u.data = fe->tv_property_cache.modulation; + break; + case TV_SET_BANDWIDTH: + fe->tv_property_cache.bandwidth = tvp->u.data; + break; + case TV_GET_BANDWIDTH: + tvp->u.data = fe->tv_property_cache.bandwidth; + break; + case TV_SET_INVERSION: + fe->tv_property_cache.inversion = tvp->u.data; + break; + case TV_GET_INVERSION: + tvp->u.data = fe->tv_property_cache.inversion; + break; + case TV_SET_SYMBOLRATE: + fe->tv_property_cache.symbol_rate = tvp->u.data; + break; + case TV_GET_SYMBOLRATE: + tvp->u.data = fe->tv_property_cache.symbol_rate; + break; + case TV_SET_INNERFEC: + fe->tv_property_cache.fec_inner = tvp->u.data; + break; + case TV_GET_INNERFEC: + tvp->u.data = fe->tv_property_cache.fec_inner; + break; + case TV_SET_PILOT: + fe->tv_property_cache.pilot = tvp->u.data; + break; + case TV_GET_PILOT: + tvp->u.data = fe->tv_property_cache.pilot; + break; + case TV_SET_ROLLOFF: + fe->tv_property_cache.rolloff = tvp->u.data; + break; + case TV_GET_ROLLOFF: + tvp->u.data = fe->tv_property_cache.rolloff; + break; + case TV_SET_DELIVERY_SYSTEM: + fe->tv_property_cache.delivery_system = tvp->u.data; + break; + case TV_GET_DELIVERY_SYSTEM: + tvp->u.data = fe->tv_property_cache.delivery_system; + break; + + /* ISDB-T Support here */ + case TV_SET_ISDB_SEGMENT_NUM: + fe->tv_property_cache.isdb_segment_num = tvp->u.data; + break; + case TV_GET_ISDB_SEGMENT_NUM: + tvp->u.data = fe->tv_property_cache.isdb_segment_num; + break; + case TV_SET_ISDB_SEGMENT_WIDTH: + fe->tv_property_cache.isdb_segment_width = tvp->u.data; + break; + case TV_GET_ISDB_SEGMENT_WIDTH: + tvp->u.data = fe->tv_property_cache.isdb_segment_width; + break; + case TV_GET_ISDB_LAYERA_FEC: + tvp->u.data = fe->tv_property_cache.isdb_layera_fec; + break; + case TV_GET_ISDB_LAYERA_MODULATION: + tvp->u.data = fe->tv_property_cache.isdb_layera_modulation; + break; + case TV_GET_ISDB_LAYERA_SEGMENT_WIDTH: + tvp->u.data = fe->tv_property_cache.isdb_layera_segment_width; + break; + case TV_GET_ISDB_LAYERB_FEC: + tvp->u.data = fe->tv_property_cache.isdb_layerb_fec; + break; + case TV_GET_ISDB_LAYERB_MODULATION: + tvp->u.data = fe->tv_property_cache.isdb_layerb_modulation; + break; + case TV_GET_ISDB_LAYERB_SEGMENT_WIDTH: + tvp->u.data = fe->tv_property_cache.isdb_layerb_segment_width; + break; + case TV_GET_ISDB_LAYERC_FEC: + tvp->u.data = fe->tv_property_cache.isdb_layerc_fec; + break; + case TV_GET_ISDB_LAYERC_MODULATION: + tvp->u.data = fe->tv_property_cache.isdb_layerc_modulation; + break; + case TV_GET_ISDB_LAYERC_SEGMENT_WIDTH: + tvp->u.data = fe->tv_property_cache.isdb_layerc_segment_width; + break; + + } + + return 0; +} + static int dvb_frontend_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { @@ -762,6 +1291,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = -EOPNOTSUPP; + tv_property_t* tvp; dprintk ("%s\n", __func__); @@ -776,6 +1306,27 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, if (down_interruptible (&fepriv->sem)) return -ERESTARTSYS; + if(cmd == FE_SET_PROPERTY) { + printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); + + /* TODO: basic property validation here */ + + /* TODO: ioctl userdata out of range check here */ + tvp = parg; + while(tvp->cmd != TV_SEQ_UNDEFINED) { + tv_property_process(fe, tvp); + if( (tvp->cmd == TV_SEQ_TERMINATE) || (tvp->cmd == TV_SEQ_COMPLETE) ) + break; + tvp++; + } + + if(fe->tv_property_cache.state == TV_SEQ_COMPLETE) { + printk("%s() Property cache is full, tuning\n", __FUNCTION__); + cmd = FE_SET_FRONTEND; + } + err = 0; + } + switch (cmd) { case FE_GET_INFO: { struct dvb_frontend_info* info = parg; @@ -942,13 +1493,20 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_SET_FRONTEND: { struct dvb_frontend_tune_settings fetunesettings; - if (dvb_frontend_check_parameters(fe, parg) < 0) { - err = -EINVAL; - break; - } + if(fe->tv_property_cache.state == TV_SEQ_COMPLETE) { + if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { + err = -EINVAL; + break; + } + } else { + if (dvb_frontend_check_parameters(fe, parg) < 0) { + err = -EINVAL; + break; + } - memcpy (&fepriv->parameters, parg, - sizeof (struct dvb_frontend_parameters)); + memcpy (&fepriv->parameters, parg, + sizeof (struct dvb_frontend_parameters)); + } memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); memcpy(&fetunesettings.parameters, parg, @@ -1031,6 +1589,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, return err; } + static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) { struct dvb_device *dvbdev = file->private_data; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index aa4133f0bd1..61d53ee70f2 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -169,6 +169,10 @@ struct dvb_frontend_ops { struct dvb_tuner_ops tuner_ops; struct analog_demod_ops analog_ops; + + int (*set_property)(struct dvb_frontend* fe, tv_property_t* tvp); + int (*get_property)(struct dvb_frontend* fe, tv_property_t* tvp); + int (*set_params)(struct dvb_frontend* fe); }; #define MAX_EVENT 8 @@ -182,6 +186,45 @@ struct dvb_fe_events { struct mutex mtx; }; +struct tv_frontend_properties { + + /* Cache State */ + u32 state; + + u32 frequency; + fe_modulation_t modulation; + + fe_sec_voltage_t voltage; + fe_sec_tone_mode_t sectone; + fe_spectral_inversion_t inversion; + fe_code_rate_t fec_inner; + fe_transmit_mode_t transmission_mode; + fe_bandwidth_t bandwidth; + fe_guard_interval_t guard_interval; + fe_hierarchy_t hierarchy; + u32 symbol_rate; + fe_code_rate_t code_rate_HP; + fe_code_rate_t code_rate_LP; + + fe_pilot_t pilot; + fe_rolloff_t rolloff; + + fe_delivery_system_t delivery_system; + + /* ISDB-T specifics */ + u32 isdb_segment_num; + u32 isdb_segment_width; + fe_code_rate_t isdb_layera_fec; + fe_modulation_t isdb_layera_modulation; + u32 isdb_layera_segment_width; + fe_code_rate_t isdb_layerb_fec; + fe_modulation_t isdb_layerb_modulation; + u32 isdb_layerb_segment_width; + fe_code_rate_t isdb_layerc_fec; + fe_modulation_t isdb_layerc_modulation; + u32 isdb_layerc_segment_width; +}; + struct dvb_frontend { struct dvb_frontend_ops ops; struct dvb_adapter *dvb; @@ -190,6 +233,7 @@ struct dvb_frontend { void *frontend_priv; void *sec_priv; void *analog_demod_priv; + struct tv_frontend_properties tv_property_cache; }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index c8cbd90ba37..4d377002173 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -62,6 +62,7 @@ typedef enum fe_caps { FE_CAN_HIERARCHY_AUTO = 0x100000, FE_CAN_8VSB = 0x200000, FE_CAN_16VSB = 0x400000, + FE_HAS_EXTENDED_CAPS = 0x800000, // We need more bitspace for newer APIs, indicate this. FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output @@ -147,7 +148,9 @@ typedef enum fe_code_rate { FEC_6_7, FEC_7_8, FEC_8_9, - FEC_AUTO + FEC_AUTO, + FEC_3_5, + FEC_9_10, } fe_code_rate_t; @@ -160,7 +163,11 @@ typedef enum fe_modulation { QAM_256, QAM_AUTO, VSB_8, - VSB_16 + VSB_16, + _8PSK, + _16APSK, + NBC_QPSK, + DQPSK, } fe_modulation_t; typedef enum fe_transmit_mode { @@ -239,6 +246,125 @@ struct dvb_frontend_event { struct dvb_frontend_parameters parameters; }; +/* TODO: Turn this into a series of defines, so future maintainers + * don't insert random new commands and break backwards + * binary compatability. + */ +typedef enum tv_cmd_types { + TV_SEQ_UNDEFINED, + TV_SEQ_START, + TV_SEQ_CONTINUE, + TV_SEQ_COMPLETE, + TV_SEQ_TERMINATE, + + TV_SET_FREQUENCY, + TV_SET_MODULATION, + TV_SET_BANDWIDTH, + TV_SET_INVERSION, + TV_SET_DISEQC_MASTER, + TV_SET_SYMBOLRATE, + TV_SET_INNERFEC, + TV_SET_VOLTAGE, + TV_SET_TONE, + TV_SET_PILOT, + TV_SET_ROLLOFF, + + TV_GET_FREQUENCY, + TV_GET_MODULATION, + TV_GET_BANDWIDTH, + TV_GET_INVERSION, + TV_GET_DISEQC_SLAVE_REPLY, + TV_GET_SYMBOLRATE, + TV_GET_INNERFEC, + TV_GET_VOLTAGE, + TV_GET_TONE, + TV_GET_PILOT, + TV_GET_ROLLOFF, + + /* Basic enumeration set for querying unlimited capabilities */ + TV_GET_FE_CAPABILITY_COUNT, + TV_GET_FE_CAPABILITY, + + /* New commands are always appended */ + TV_SET_DELIVERY_SYSTEM, + TV_GET_DELIVERY_SYSTEM, + + /* ISDB-T */ + TV_SET_ISDB_SEGMENT_NUM, + TV_GET_ISDB_SEGMENT_NUM, + TV_SET_ISDB_SEGMENT_WIDTH, + TV_GET_ISDB_SEGMENT_WIDTH, + TV_GET_ISDB_LAYERA_FEC, + TV_GET_ISDB_LAYERA_MODULATION, + TV_GET_ISDB_LAYERA_SEGMENT_WIDTH, + TV_GET_ISDB_LAYERB_FEC, + TV_GET_ISDB_LAYERB_MODULATION, + TV_GET_ISDB_LAYERB_SEGMENT_WIDTH, + TV_GET_ISDB_LAYERC_FEC, + TV_GET_ISDB_LAYERC_MODULATION, + TV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + +} tv_cmd_types_t; + +typedef enum fe_pilot { + PILOT_ON, + PILOT_OFF, + PILOT_AUTO, +} fe_pilot_t; + +typedef enum fe_rolloff { + ROLLOFF_20, + ROLLOFF_25, + ROLLOFF_35, + ROLLOFF_AUTO, +} fe_rolloff_t; + +typedef enum fe_delivery_system { + SYS_UNDEFINED, + SYS_DVBC_ANNEX_AC, + SYS_DVBC_ANNEX_B, + SYS_DVBT, + SYS_DVBS, + SYS_DVBS2, + SYS_DVBH, + SYS_ISDBT, + SYS_ISDBS, + SYS_ISDBC, + SYS_ATSC, + SYS_ATSCMH, + SYS_DMBTH, + SYS_CMMB, + SYS_DAB, +} fe_delivery_system_t; + +struct tv_cmds_h { + char *name; /* A display name for debugging purposes */ + + __u32 cmd; /* A unique ID */ + + /* Flags */ + __u32 set:1; /* Either a set or get property */ + __u32 buffer:1; /* Does this property use the buffer? */ + __u32 reserved:30; /* Align */ +}; + +typedef struct { + __u32 cmd; + union { + __u32 data; + struct { + __u8 data[32]; + __u32 len; + } buffer; + } u; +} tv_property_t; + +/* No more than 16 properties during any given ioctl */ +typedef tv_property_t tv_properties_t[16]; + +#define FE_SET_PROPERTY _IOW('o', 82, tv_properties_t) +#define FE_GET_PROPERTY _IOR('o', 83, tv_properties_t) + /** * When set, this flag will disable any zigzagging or other "normal" tuning -- GitLab From 0d46748c3f874defbbbf98bcf40c7b18964abbc0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 4 Sep 2008 01:14:43 -0300 Subject: [PATCH 4099/5416] V4L/DVB (8986): cx24116: Adding DVB-S2 demodulator support Adds support for the COnexant cx24116 DVB-S2 demodulator. TODO: checkpatch cleanup. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/cx24116.c | 950 ++++++++++++++++++++++++++ drivers/media/dvb/frontends/cx24116.h | 50 ++ 4 files changed, 1008 insertions(+) create mode 100644 drivers/media/dvb/frontends/cx24116.c create mode 100644 drivers/media/dvb/frontends/cx24116.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 097d9f00144..d2f31da26cb 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -92,6 +92,13 @@ config DVB_TUA6100 help A DVB-S PLL chip. +config DVB_CX24116 + tristate "Conexant CX24116 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S/S2 tuner module. Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 1b547888624..5deb8a542ab 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -51,3 +51,4 @@ obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o +obj-$(CONFIG_DVB_CX24116) += cx24116.o diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c new file mode 100644 index 00000000000..1402086a5c4 --- /dev/null +++ b/drivers/media/dvb/frontends/cx24116.c @@ -0,0 +1,950 @@ +/* + Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver + + Copyright (C) 2006-2008 Steven Toth + + 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. +*/ + +/* + * Updates by Darron Broad 2007. + * + * March + * Fixed some bugs. + * Added diseqc support. + * Added corrected signal strength support. + * + * August + * Sync with legacy version. + * Some clean ups. + */ + +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "cx24116.h" + +/* + * Fetch firmware in the following manner. + * + * #!/bin/sh + * wget ftp://167.206.143.11/outgoing/Oxford/88x_2_117_24275_1_INF.zip + * unzip 88x_2_117_24275_1_INF.zip + * dd if=Driver88/hcw88bda.sys of=dvb-fe-cx24116.fw skip=81768 bs=1 count=32522 + */ +#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" +#define CX24116_SEARCH_RANGE_KHZ 5000 + +/* registers (TO BE COMPLETED) */ +#define CX24116_REG_SIGNAL (0xd5) + +/* arg buffer size */ +#define CX24116_ARGLEN (0x1e) + +/* arg offset for DiSEqC */ +#define CX24116_DISEQC_BURST (1) +#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */ +#define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */ +#define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */ +#define CX24116_DISEQC_MSGLEN (5) +#define CX24116_DISEQC_MSGOFS (6) + +/* DiSEqC burst */ +#define CX24116_DISEQC_MINI_A (0) +#define CX24116_DISEQC_MINI_B (1) + +static int debug = 0; +#define dprintk(args...) \ + do { \ + if (debug) printk ("cx24116: " args); \ + } while (0) + +enum cmds +{ + CMD_INIT_CMD10 = 0x10, + CMD_TUNEREQUEST = 0x11, + CMD_INIT_CMD13 = 0x13, + CMD_INIT_CMD14 = 0x14, + CMD_SEND_DISEQC = 0x21, + CMD_SET_TONEPRE = 0x22, + CMD_SET_TONE = 0x23, +}; + +/* The Demod/Tuner can't easily provide these, we cache them */ +struct cx24116_tuning +{ + u32 frequency; + u32 symbol_rate; + fe_spectral_inversion_t inversion; + fe_code_rate_t fec; + + fe_modulation_t modulation; + + /* Demod values */ + u8 fec_val; + u8 fec_mask; + u8 inversion_val; +}; + +/* Basic commands that are sent to the firmware */ +struct cx24116_cmd +{ + u8 len; + u8 args[CX24116_ARGLEN]; +}; + +struct cx24116_state +{ + struct i2c_adapter* i2c; + const struct cx24116_config* config; + + struct dvb_frontend frontend; + + struct cx24116_tuning dcur; + struct cx24116_tuning dnxt; + + u8 skip_fw_load; + u8 burst; +}; + +static int cx24116_writereg(struct cx24116_state* state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = 0, .buf = buf, .len = 2 }; + int err; + + if (debug>1) + printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n", + __func__,reg, data); + + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { + printk("%s: writereg error(err == %i, reg == 0x%02x," + " value == 0x%02x)\n", __func__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + +/* Bulk byte writes to a single I2C address, for 32k firmware load */ +static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len) +{ + int ret = -EREMOTEIO; + struct i2c_msg msg; + u8 *buf; + + buf = kmalloc(len + 1, GFP_KERNEL); + if (buf == NULL) { + printk("Unable to kmalloc\n"); + ret = -ENOMEM; + goto error; + } + + *(buf) = reg; + memcpy(buf + 1, data, len); + + msg.addr = state->config->demod_address; + msg.flags = 0; + msg.buf = buf; + msg.len = len + 1; + + if (debug>1) + printk("cx24116: %s: write regN 0x%02x, len = %d\n", + __func__,reg, len); + + if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { + printk("%s: writereg error(err == %i, reg == 0x%02x\n", + __func__, ret, reg); + ret = -EREMOTEIO; + } + +error: + kfree(buf); + + return ret; +} + +static int cx24116_readreg(struct cx24116_state* state, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret); + return ret; + } + + if (debug>1) + printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]); + + return b1[0]; +} + +static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion) +{ + dprintk("%s(%d)\n", __func__, inversion); + + switch (inversion) { + case INVERSION_OFF: + state->dnxt.inversion_val = 0x00; + break; + case INVERSION_ON: + state->dnxt.inversion_val = 0x04; + break; + case INVERSION_AUTO: + state->dnxt.inversion_val = 0x0C; + break; + default: + return -EINVAL; + } + + state->dnxt.inversion = inversion; + + return 0; +} + +/* A table of modulation, fec and configuration bytes for the demod. + * Not all S2 mmodulation schemes are support and not all rates with + * a scheme are support. Especially, no auto detect when in S2 mode. + */ +struct cx24116_modfec { + fe_modulation_t modulation; + fe_code_rate_t fec; + u8 mask; /* In DVBS mode this is used to autodetect */ + u8 val; /* Passed to the firmware to indicate mode selection */ +} CX24116_MODFEC_MODES[] = { + /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */ + { QPSK, FEC_NONE, 0xfe, 0x30 }, + { QPSK, FEC_1_2, 0x02, 0x2e }, + { QPSK, FEC_2_3, 0x04, 0x2f }, + { QPSK, FEC_3_4, 0x08, 0x30 }, + { QPSK, FEC_4_5, 0xfe, 0x30 }, + { QPSK, FEC_5_6, 0x20, 0x31 }, + { QPSK, FEC_6_7, 0xfe, 0x30 }, + { QPSK, FEC_7_8, 0x80, 0x32 }, + { QPSK, FEC_8_9, 0xfe, 0x30 }, + { QPSK, FEC_AUTO, 0xfe, 0x30 }, + /* NBC-QPSK */ + { NBC_QPSK, FEC_1_2, 0x00, 0x04 }, + { NBC_QPSK, FEC_3_5, 0x00, 0x05 }, + { NBC_QPSK, FEC_2_3, 0x00, 0x06 }, + { NBC_QPSK, FEC_3_4, 0x00, 0x07 }, + { NBC_QPSK, FEC_4_5, 0x00, 0x08 }, + { NBC_QPSK, FEC_5_6, 0x00, 0x09 }, + { NBC_QPSK, FEC_8_9, 0x00, 0x0a }, + { NBC_QPSK, FEC_9_10, 0x00, 0x0b }, + /* 8PSK */ + { _8PSK, FEC_3_5, 0x00, 0x0c }, + { _8PSK, FEC_2_3, 0x00, 0x0d }, + { _8PSK, FEC_3_4, 0x00, 0x0e }, + { _8PSK, FEC_5_6, 0x00, 0x0f }, + { _8PSK, FEC_9_10, 0x00, 0x11 }, +}; + +static int cx24116_lookup_fecmod(struct cx24116_state* state, + fe_modulation_t m, fe_code_rate_t f) +{ + int i, ret = -EOPNOTSUPP; + + for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) + { + if( (m == CX24116_MODFEC_MODES[i].modulation) && + (f == CX24116_MODFEC_MODES[i].fec) ) + { + ret = i; + break; + } + } + + return ret; +} + +static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec) +{ + int ret = 0; + dprintk("%s()\n", __func__); + + ret = cx24116_lookup_fecmod(state, mod, fec); + + if(ret < 0) + return ret; + + state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val; + state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask; + dprintk("%s() fec_val/mask = 0x%02x/0x%02x\n", __func__, + state->dnxt.fec_val, state->dnxt.fec_mask); + + return 0; +} + +static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) +{ + int ret = 0; + + dprintk("%s()\n", __func__); + + state->dnxt.symbol_rate = rate; + + dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate); + + /* check if symbol rate is within limits */ + if ((state->dnxt.symbol_rate > state->frontend.ops.info.symbol_rate_max) || + (state->dnxt.symbol_rate < state->frontend.ops.info.symbol_rate_min)) + ret = -EOPNOTSUPP; + + return ret; +} + +static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); + +static int cx24116_firmware_ondemand(struct dvb_frontend* fe) +{ + struct cx24116_state *state = fe->demodulator_priv; + const struct firmware *fw; + int ret = 0; + + dprintk("%s()\n",__func__); + + if (cx24116_readreg(state, 0x20) > 0) + { + + if (state->skip_fw_load) + return 0; + + /* Load firmware */ + /* request the firmware, this will block until someone uploads it */ + printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev); + printk("%s: Waiting for firmware upload(2)...\n", __func__); + if (ret) { + printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__); + return ret; + } + + /* Make sure we don't recurse back through here during loading */ + state->skip_fw_load = 1; + + ret = cx24116_load_firmware(fe, fw); + if (ret) + printk("%s: Writing firmware to device failed\n", __func__); + + release_firmware(fw); + + printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed"); + + /* Ensure firmware is always loaded if required */ + state->skip_fw_load = 0; + } + + return ret; +} + +/* Take a basic firmware command structure, format it and forward it for processing */ +static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) +{ + struct cx24116_state *state = fe->demodulator_priv; + int i, ret; + + dprintk("%s()\n", __func__); + + /* Load the firmware if required */ + if ( (ret = cx24116_firmware_ondemand(fe)) != 0) + { + printk("%s(): Unable initialise the firmware\n", __func__); + return ret; + } + + /* Write the command */ + for(i = 0; i < cmd->len ; i++) + { + dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]); + cx24116_writereg(state, i, cmd->args[i]); + } + + /* Start execution and wait for cmd to terminate */ + cx24116_writereg(state, 0x1f, 0x01); + while( cx24116_readreg(state, 0x1f) ) + { + msleep(10); + if(i++ > 64) + { + /* Avoid looping forever if the firmware does no respond */ + printk("%s() Firmware not responding\n", __func__); + return -EREMOTEIO; + } + } + return 0; +} + +static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) +{ + struct cx24116_state* state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int ret; + + dprintk("%s\n", __func__); + dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" + ,fw->size + ,fw->data[0] + ,fw->data[1] + ,fw->data[ fw->size-2 ] + ,fw->data[ fw->size-1 ] + ); + + /* Toggle 88x SRST pin to reset demod */ + if (state->config->reset_device) + state->config->reset_device(fe); + + /* Begin the firmware load process */ + /* Prepare the demod, load the firmware, cleanup after load */ + cx24116_writereg(state, 0xF1, 0x08); + cx24116_writereg(state, 0xF2, cx24116_readreg(state, 0xF2) | 0x03); + cx24116_writereg(state, 0xF3, 0x46); + cx24116_writereg(state, 0xF9, 0x00); + + cx24116_writereg(state, 0xF0, 0x03); + cx24116_writereg(state, 0xF4, 0x81); + cx24116_writereg(state, 0xF5, 0x00); + cx24116_writereg(state, 0xF6, 0x00); + + /* write the entire firmware as one transaction */ + cx24116_writeregN(state, 0xF7, fw->data, fw->size); + + cx24116_writereg(state, 0xF4, 0x10); + cx24116_writereg(state, 0xF0, 0x00); + cx24116_writereg(state, 0xF8, 0x06); + + /* Firmware CMD 10: Chip config? */ + cmd.args[0x00] = CMD_INIT_CMD10; + cmd.args[0x01] = 0x05; + cmd.args[0x02] = 0xdc; + cmd.args[0x03] = 0xda; + cmd.args[0x04] = 0xae; + cmd.args[0x05] = 0xaa; + cmd.args[0x06] = 0x04; + cmd.args[0x07] = 0x9d; + cmd.args[0x08] = 0xfc; + cmd.args[0x09] = 0x06; + cmd.len= 0x0a; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + + cx24116_writereg(state, 0x9d, 0x00); + + /* Firmware CMD 14: Unknown */ + cmd.args[0x00] = CMD_INIT_CMD14; + cmd.args[0x01] = 0x00; + cmd.args[0x02] = 0x00; + cmd.len= 0x03; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + + cx24116_writereg(state, 0xe5, 0x00); + + /* Firmware CMD 13: Unknown - Firmware config? */ + cmd.args[0x00] = CMD_INIT_CMD13; + cmd.args[0x01] = 0x01; + cmd.args[0x02] = 0x75; + cmd.args[0x03] = 0x00; + cmd.args[0x04] = 0x02; + cmd.args[0x05] = 0x00; + cmd.len= 0x06; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + + return 0; +} + +static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + /* The isl6421 module will override this function in the fops. */ + dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__); + + return -EOPNOTSUPP; +} + +static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct cx24116_state *state = fe->demodulator_priv; + + int lock = cx24116_readreg(state, 0x9d); + + dprintk("%s: status = 0x%02x\n", __func__, lock); + + *status = 0; + + if (lock & 0x01) + *status |= FE_HAS_SIGNAL; + if (lock & 0x02) + *status |= FE_HAS_CARRIER; + if (lock & 0x04) + *status |= FE_HAS_VITERBI; + if (lock & 0x08) + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + + return 0; +} + +/* TODO: Not clear how we do this */ +static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) +{ + //struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); + *ber = 0; + + return 0; +} + +/* Signal strength (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */ +static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) +{ + struct cx24116_state *state = fe->demodulator_priv; + u8 strength_reg; + static const u32 strength_tab[] = { /* 10 x Table (rounded up) */ + 0x00000,0x0199A,0x03333,0x04ccD,0x06667,0x08000,0x0999A,0x0b333,0x0cccD,0x0e667, + 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; + + dprintk("%s()\n", __func__); + + strength_reg = cx24116_readreg(state, CX24116_REG_SIGNAL); + + if(strength_reg < 0xa0) + *signal_strength = strength_tab [ ( strength_reg & 0xf0 ) >> 4 ] + + ( strength_tab [ ( strength_reg & 0x0f ) ] >> 4 ); + else + *signal_strength = 0xffff; + + dprintk("%s: Signal strength (raw / cooked) = (0x%02x / 0x%04x)\n", + __func__,strength_reg,*signal_strength); + + return 0; +} + +/* TODO: Not clear how we do this */ +static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr) +{ + //struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); + *snr = 0; + + return 0; +} + +/* TODO: Not clear how we do this */ +static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + //struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); + *ucblocks = 0; + + return 0; +} + +/* Overwrite the current tuning params, we are about to tune */ +static void cx24116_clone_params(struct dvb_frontend* fe) +{ + struct cx24116_state *state = fe->demodulator_priv; + memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); +} + +static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct cx24116_cmd cmd; + int ret; + + dprintk("%s(%d)\n", __func__, tone); + if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) { + printk("%s: Invalid, tone=%d\n", __func__, tone); + return -EINVAL; + } + + /* This is always done before the tone is set */ + cmd.args[0x00] = CMD_SET_TONEPRE; + cmd.args[0x01] = 0x00; + cmd.len= 0x02; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + + /* Now we set the tone */ + cmd.args[0x00] = CMD_SET_TONE; + cmd.args[0x01] = 0x00; + cmd.args[0x02] = 0x00; + + switch (tone) { + case SEC_TONE_ON: + dprintk("%s: setting tone on\n", __func__); + cmd.args[0x03] = 0x01; + break; + case SEC_TONE_OFF: + dprintk("%s: setting tone off\n",__func__); + cmd.args[0x03] = 0x00; + break; + } + cmd.len= 0x04; + + return cx24116_cmd_execute(fe, &cmd); +} + +/* Initialise DiSEqC */ +static int cx24116_diseqc_init(struct dvb_frontend* fe) +{ + struct cx24116_state *state = fe->demodulator_priv; + + /* Default DiSEqC burst state */ + state->burst = CX24116_DISEQC_MINI_A; + + return 0; +} + +/* Send DiSEqC message with derived burst (hack) || previous burst */ +static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) +{ + struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int i, ret; + + /* Dump DiSEqC message */ + if (debug) { + printk("cx24116: %s(", __func__); + for(i = 0 ; i < d->msg_len ;) { + printk("0x%02x", d->msg[i]); + if(++i < d->msg_len) + printk(", "); + } + printk(")\n"); + } + + if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) + return -EINVAL; + + cmd.args[0x00] = CMD_SEND_DISEQC; + cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; + cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; + cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; + + /* DiSEqC message */ + for (i = 0; i < d->msg_len; i++) + cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; + + /* Hack: Derive burst from command else use previous burst */ + if(d->msg_len >= 4 && d->msg[2] == 0x38) + cmd.args[CX24116_DISEQC_BURST] = (d->msg[3] >> 2) & 1; + else + cmd.args[CX24116_DISEQC_BURST] = state->burst; + + cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; + cmd.len = CX24116_DISEQC_MSGOFS + d->msg_len; + + ret = cx24116_cmd_execute(fe, &cmd); + + /* Firmware command duration is unknown, so guess... + * + * Eutelsat spec: + * >15ms delay + + * 13.5ms per byte + + * >15ms delay + + * 12.5ms burst + + * >15ms delay + */ + if(ret == 0) + msleep( (cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 ); + + return ret; +} + +/* Send DiSEqC burst */ +static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) +{ + struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int ret; + + dprintk("%s(%d)\n",__func__,(int)burst); + + cmd.args[0x00] = CMD_SEND_DISEQC; + cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; + cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; + cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; + + if (burst == SEC_MINI_A) + cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; + else if(burst == SEC_MINI_B) + cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; + else + return -EINVAL; + + /* Cache as previous burst state */ + state->burst= cmd.args[CX24116_DISEQC_BURST]; + + cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; + cmd.len= CX24116_DISEQC_MSGOFS; + + ret= cx24116_cmd_execute(fe, &cmd); + + /* Firmware command duration is unknown, so guess... */ + if(ret == 0) + msleep(60); + + return ret; +} + +static void cx24116_release(struct dvb_frontend* fe) +{ + struct cx24116_state* state = fe->demodulator_priv; + dprintk("%s\n",__func__); + kfree(state); +} + +static struct dvb_frontend_ops cx24116_ops; + +struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, + struct i2c_adapter* i2c) +{ + struct cx24116_state* state = NULL; + int ret; + + dprintk("%s\n",__func__); + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); + if (state == NULL) { + printk("Unable to kmalloc\n"); + goto error; + } + + /* setup the state */ + memset(state, 0, sizeof(struct cx24116_state)); + + state->config = config; + state->i2c = i2c; + + /* check if the demod is present */ + ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); + if (ret != 0x0501) { + printk("Invalid probe, probably not a CX24116 device\n"); + goto error; + } + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + + return NULL; +} + +static int cx24116_get_params(struct dvb_frontend* fe) +{ + struct cx24116_state *state = fe->demodulator_priv; + struct tv_frontend_properties *cache = &fe->tv_property_cache; + + dprintk("%s()\n",__func__); + + cache->frequency = state->dcur.frequency; + cache->inversion = state->dcur.inversion; + cache->modulation = state->dcur.modulation; + cache->fec_inner = state->dcur.fec; + cache->symbol_rate = state->dcur.symbol_rate; + + return 0; +} + +static int cx24116_initfe(struct dvb_frontend* fe) +{ + dprintk("%s()\n",__func__); + + return cx24116_diseqc_init(fe); +} + +static int cx24116_set_property(struct dvb_frontend *fe, tv_property_t* tvp) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int cx24116_set_params(struct dvb_frontend *fe) +{ + dprintk("%s(..) We were notified that a tune request may occur\n", __func__); + return 0; +} + +/* dvb-core told us to tune, the tv property cache will be complete, + * it's safe for is to pull values and use them for tuning purposes. + */ +static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct cx24116_state *state = fe->demodulator_priv; + struct tv_frontend_properties *c = &fe->tv_property_cache; + struct cx24116_cmd cmd; + fe_status_t tunerstat; + int ret; + u8 retune=4; + + dprintk("%s()\n",__func__); + + state->dnxt.modulation = c->modulation; + state->dnxt.frequency = c->frequency; + + if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) + return ret; + + if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0) + return ret; + + if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0) + return ret; + + /* discard the 'current' tuning parameters and prepare to tune */ + cx24116_clone_params(fe); + + dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); + dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); + dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__, + state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val); + dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__, + state->dcur.inversion, state->dcur.inversion_val); + + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + + /* Prepare a tune request */ + cmd.args[0x00] = CMD_TUNEREQUEST; + + /* Frequency */ + cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16; + cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8; + cmd.args[0x03] = (state->dcur.frequency & 0x0000ff); + + /* Symbol Rate */ + cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8; + cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff); + + /* Automatic Inversion */ + cmd.args[0x06] = state->dcur.inversion_val; + + /* Modulation / FEC & Pilot Off */ + cmd.args[0x07] = state->dcur.fec_val; + + if (c->pilot == PILOT_ON) + cmd.args[0x07] |= 0x40; + + cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8; + cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff; + cmd.args[0x0a] = 0x00; + cmd.args[0x0b] = 0x00; + cmd.args[0x0c] = 0x02; + cmd.args[0x0d] = state->dcur.fec_mask; + cmd.args[0x0e] = 0x06; + cmd.args[0x0f] = 0x00; + cmd.args[0x10] = 0x00; + cmd.args[0x11] = 0xFA; + cmd.args[0x12] = 0x24; + cmd.len= 0x13; + + /* We need to support pilot and non-pilot tuning in the + * driver automatically. This is a workaround for because + * the demod does not support autodetect. + */ + do { + /* Reset status register? */ + cx24116_writereg(state, 0x9d, 0xc1); + + /* Tune */ + ret = cx24116_cmd_execute(fe, &cmd); + if( ret != 0 ) + break; + + /* The hardware can take time to lock, wait a while */ + msleep(500); + + cx24116_read_status(fe, &tunerstat); + if(tunerstat & FE_HAS_SIGNAL) { + if(tunerstat & FE_HAS_SYNC) + /* Tuned */ + break; + else if(c->pilot == PILOT_AUTO) + /* Toggle pilot bit */ + cmd.args[0x07] ^= 0x40; + } + } + while(--retune); + + return ret; +} + +static struct dvb_frontend_ops cx24116_ops = { + + .info = { + .name = "Conexant CX24116/CX24118", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends */ + .frequency_tolerance = 5000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_RECOVER + }, + + .release = cx24116_release, + + .init = cx24116_initfe, + .read_status = cx24116_read_status, + .read_ber = cx24116_read_ber, + .read_signal_strength = cx24116_read_signal_strength, + .read_snr = cx24116_read_snr, + .read_ucblocks = cx24116_read_ucblocks, + .set_tone = cx24116_set_tone, + .set_voltage = cx24116_set_voltage, + .diseqc_send_master_cmd = cx24116_send_diseqc_msg, + .diseqc_send_burst = cx24116_diseqc_send_burst, + + .set_property = cx24116_set_property, + .set_params = cx24116_set_params, + .set_frontend = cx24116_set_frontend, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(cx24116_attach); diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h new file mode 100644 index 00000000000..27896725204 --- /dev/null +++ b/drivers/media/dvb/frontends/cx24116.h @@ -0,0 +1,50 @@ +/* + Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver + + Copyright (C) 2006 Steven Toth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CX24116_H +#define CX24116_H + +#include + +struct cx24116_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* Need to set device param for start_dma */ + int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); + + /* Need to reset device during firmware loading */ + int (*reset_device)(struct dvb_frontend* fe); +}; + +#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) +extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, + struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_CX24116 + +#endif /* CX24116_H */ -- GitLab From 5bd1b66359437864e6b46420ba6770c2b1c4362c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 4 Sep 2008 01:17:33 -0300 Subject: [PATCH 4100/5416] V4L/DVB (8987): cx88: Add support for the Hauppauge HVR4000 and HVR4000-LITE (S2) boards Adding support for Hauppauge's cx88 S2 based products, based on the cx24116 DVB-S2 demodulator. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 + drivers/media/video/cx88/cx88-cards.c | 79 +++++++++++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 42 +++++++++++++ drivers/media/video/cx88/cx88-input.c | 4 ++ drivers/media/video/cx88/cx88.h | 2 + 5 files changed, 129 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7cf5685d364..c95a2fb70c3 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -66,3 +66,5 @@ 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] + 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid [0070:6900,0070:6904,0070:6902] + 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2 [0070:6905,0070:6906] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index de199a206a1..538967e3228 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1664,6 +1664,51 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_HAUPPAUGE_HVR4000] = { + .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + /* + * GPIO0 (WINTV2000) + * + * Analogue SAT DVB-T + * Antenna 0xc4bf 0xc4bb + * Composite 0xc4bf 0xc4bb + * S-Video 0xc4bf 0xc4bb + * Composite1 0xc4ff 0xc4fb + * S-Video1 0xc4ff 0xc4fb + */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0xc4bf, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0xc4bf, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0xc4bf, + } }, + /* fixme: Add radio support */ + .mpeg = CX88_MPEG_DVB, + }, + [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { + .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2013,6 +2058,26 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x17de, .subdevice = 0x08c1, .card = CX88_BOARD_KWORLD_ATSC_120, + }, { + .subvendor = 0x0070, + .subdevice = 0x6900, + .card = CX88_BOARD_HAUPPAUGE_HVR4000, + }, { + .subvendor = 0x0070, + .subdevice = 0x6904, + .card = CX88_BOARD_HAUPPAUGE_HVR4000, + }, { + .subvendor = 0x0070, + .subdevice = 0x6902, + .card = CX88_BOARD_HAUPPAUGE_HVR4000, + }, { + .subvendor = 0x0070, + .subdevice = 0x6905, + .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, + }, { + .subvendor = 0x0070, + .subdevice = 0x6906, + .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, }, }; @@ -2065,6 +2130,13 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ case 34519: /* WinTV-PCI-FM */ + case 69009: + /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */ + case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */ + case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */ + case 69559: + /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */ + case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */ case 90002: /* Nova-T-PCI (9002) */ case 92001: /* Nova-S-Plus (Video and IR) */ case 92002: /* Nova-S-Plus (Video and IR) */ @@ -2415,6 +2487,11 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) /* Enable the xc5000 tuner */ cx_set(MO_GP0_IO, 0x00001010); break; + case CX88_BOARD_HAUPPAUGE_HVR4000: + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + /* Init GPIO to allow tuner to attach */ + cx_write(MO_GP0_IO, 0x0000c4bf); + udelay(1000); } } @@ -2489,6 +2566,8 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR1300: + case CX88_BOARD_HAUPPAUGE_HVR4000: + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: if (0 == core->i2c_rc) hauppauge_eeprom(core, eeprom); break; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9f0e5b3c515..7a5a4a2c69c 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -48,6 +48,7 @@ #include "tuner-simple.h" #include "tda9887.h" #include "s5h1411.h" +#include "cx24116.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -518,6 +519,35 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) return 0; } +static int cx24116_set_ts_param(struct dvb_frontend *fe, + int is_punctured) +{ + struct cx8802_dev *dev = fe->dvb->priv; + dev->ts_gen_cntrl = 0x2; + + return 0; +} + +static int cx24116_reset_device(struct dvb_frontend *fe) +{ + struct cx8802_dev *dev = fe->dvb->priv; + struct cx88_core *core = dev->core; + + /* Reset the part */ + cx_write(MO_SRST_IO, 0); + msleep(10); + cx_write(MO_SRST_IO, 1); + msleep(10); + + return 0; +} + +static struct cx24116_config hauppauge_hvr4000_config = { + .demod_address = 0x05, + .set_ts_params = cx24116_set_ts_param, + .reset_device = cx24116_reset_device, +}; + static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -876,6 +906,18 @@ static int dvb_register(struct cx8802_dev *dev) goto frontend_detach; } break; + case CX88_BOARD_HAUPPAUGE_HVR4000: + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + /* Support for DVB-S only, not DVB-T support */ + dev->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend) { + dvb_attach(isl6421_attach, dev->dvb.frontend, + &dev->core->i2c_adap, + 0x08, 0x00, 0x00); + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 53526d997a4..097081eb505 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -224,6 +224,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -462,6 +464,8 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_PINNACLE_PCTV_HD_800i: + case CX88_BOARD_HAUPPAUGE_HVR4000: + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); if ((ircode & 0xfffff000) != 0x3000) diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 54fe6509471..edcdabaf7bc 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -221,6 +221,8 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 #define CX88_BOARD_PROLINK_PV_8000GT 66 #define CX88_BOARD_KWORLD_ATSC_120 67 +#define CX88_BOARD_HAUPPAUGE_HVR4000 68 +#define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From 13c97bf56724b4f2d3dac139fb4cb081a3c401dc Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 4 Sep 2008 21:19:43 -0300 Subject: [PATCH 4101/5416] V4L/DVB (8988): S2API: Allow the properties to call legacy ioctls SET_TONE and SET_VOLTAGE were not previously implemented. Two options existed. Either cut/paste from the previous ioctl handler into the process_properties function, which is code duplication. Or, split the current ioctl handler into it's two major pieces. Piece 1, responsible for input validation and semaphore acquiring Piece 2 the processing of the previous ioctls and finally, a new third pieces where the array of properties is processed, and can freely call the legacy ioctl handler without having to re-acquire the fepriv->sem semaphore. This is a clean approach and ensures the existing legacy ioctls are processed as they were previously (but with an extra function call) and allows the new API to share code without duplication. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 67 ++++++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index e68974b2fee..86af06cf578 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1156,9 +1156,16 @@ int tv_property_cache_submit(struct dvb_frontend *fe) return r; } -int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp) +static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, + unsigned int cmd, void *parg); +static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, + unsigned int cmd, void *parg); + +int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp, + struct inode *inode, struct file *file) { int r = 0; + struct dvb_frontend_private *fepriv = fe->frontend_priv; printk("%s()\n", __FUNCTION__); tv_property_dump(tvp); @@ -1181,7 +1188,9 @@ int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp) */ fe->tv_property_cache.state = TV_SEQ_COMPLETE; printk("%s() Finalised property cache\n", __FUNCTION__); - r = tv_property_cache_submit(fe); + r |= tv_property_cache_submit(fe); + r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, + &fepriv->parameters); break; case TV_SET_FREQUENCY: fe->tv_property_cache.frequency = tvp->u.data; @@ -1278,10 +1287,25 @@ int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp) case TV_GET_ISDB_LAYERC_SEGMENT_WIDTH: tvp->u.data = fe->tv_property_cache.isdb_layerc_segment_width; break; - + case TV_SET_VOLTAGE: + fe->tv_property_cache.voltage = tvp->u.data; + r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, + &fe->tv_property_cache.voltage); + break; + case TV_GET_VOLTAGE: + tvp->u.data = fe->tv_property_cache.voltage; + break; + case TV_SET_TONE: + fe->tv_property_cache.sectone = tvp->u.data; + r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE, + (void *)fe->tv_property_cache.sectone); + break; + case TV_GET_TONE: + tvp->u.data = fe->tv_property_cache.sectone; + break; } - return 0; + return r; } static int dvb_frontend_ioctl(struct inode *inode, struct file *file, @@ -1291,7 +1315,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = -EOPNOTSUPP; - tv_property_t* tvp; dprintk ("%s\n", __func__); @@ -1306,6 +1329,25 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, if (down_interruptible (&fepriv->sem)) return -ERESTARTSYS; + if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) + err = dvb_frontend_ioctl_properties(inode, file, cmd, parg); + else + err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg); + + up(&fepriv->sem); + return err; +} + +static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_frontend *fe = dvbdev->priv; + int err = -EOPNOTSUPP; + tv_property_t *tvp; + + dprintk("%s\n", __func__); + if(cmd == FE_SET_PROPERTY) { printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); @@ -1314,7 +1356,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, /* TODO: ioctl userdata out of range check here */ tvp = parg; while(tvp->cmd != TV_SEQ_UNDEFINED) { - tv_property_process(fe, tvp); + tv_property_process(fe, tvp, inode, file); if( (tvp->cmd == TV_SEQ_TERMINATE) || (tvp->cmd == TV_SEQ_COMPLETE) ) break; tvp++; @@ -1322,11 +1364,21 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, if(fe->tv_property_cache.state == TV_SEQ_COMPLETE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); - cmd = FE_SET_FRONTEND; } err = 0; } + return err; +} + +static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_frontend *fe = dvbdev->priv; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + int err = -EOPNOTSUPP; + switch (cmd) { case FE_GET_INFO: { struct dvb_frontend_info* info = parg; @@ -1585,7 +1637,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, break; }; - up (&fepriv->sem); return err; } -- GitLab From af832623c2a44525df6e4ae0142fb0385479546c Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Thu, 4 Sep 2008 17:24:14 -0300 Subject: [PATCH 4102/5416] V4L/DVB (8989): Added support for TeVii S460 DVB-S/S2 card Added support for TeVii S460 DVB-S/S2 card. The card based on cx24116 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 23 +++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 40 +++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 64 insertions(+) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 538967e3228..23948daae85 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1709,6 +1709,18 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TEVII_S460] = { + .name = "TeVii S460 DVB-S/S2", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2078,6 +2090,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x0070, .subdevice = 0x6906, .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, + }, { + .subvendor = 0xD460, + .subdevice = 0x9022, + .card = CX88_BOARD_TEVII_S460, }, }; @@ -2649,7 +2665,14 @@ static void cx88_card_setup(struct cx88_core *core) tea5767_cfg.priv = &ctl; cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); + break; } + case CX88_BOARD_TEVII_S460: + cx_write(MO_SRST_IO, 0); + msleep(100); + cx_write(MO_SRST_IO, 1); + msleep(100); + break; } /*end switch() */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 7a5a4a2c69c..5ff6e9d2871 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -376,6 +376,31 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } +static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + switch (voltage) { + case SEC_VOLTAGE_13: + printk("LNB Voltage SEC_VOLTAGE_13\n"); + cx_write(MO_GP0_IO, 0x00006040); + break; + case SEC_VOLTAGE_18: + printk("LNB Voltage SEC_VOLTAGE_18\n"); + cx_write(MO_GP0_IO, 0x00006060); + break; + case SEC_VOLTAGE_OFF: + printk("LNB Voltage SEC_VOLTAGE_off\n"); + break; + } + + if (core->prev_set_voltage) + return core->prev_set_voltage(fe, voltage); + return 0; +} + static int cx88_pci_nano_callback(void *ptr, int command, int arg) { struct cx88_core *core = ptr; @@ -548,6 +573,12 @@ static struct cx24116_config hauppauge_hvr4000_config = { .reset_device = cx24116_reset_device, }; +static struct cx24116_config tevii_s460_config = { + .demod_address = 0x55, + .set_ts_params = cx24116_set_ts_param, + .reset_device = cx24116_reset_device, +}; + static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -918,6 +949,15 @@ static int dvb_register(struct cx8802_dev *dev) 0x08, 0x00, 0x00); } break; + case CX88_BOARD_TEVII_S460: + dev->dvb.frontend = dvb_attach(cx24116_attach, + &tevii_s460_config, + &core->i2c_adap); + if (dev->dvb.frontend != NULL) { + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index edcdabaf7bc..2b82c6aac89 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -223,6 +223,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_KWORLD_ATSC_120 67 #define CX88_BOARD_HAUPPAUGE_HVR4000 68 #define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 +#define CX88_BOARD_TEVII_S460 70 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From 2cf801e3e38f649d25fe3b4e236976f45e26289f Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 8 Sep 2008 12:07:06 -0300 Subject: [PATCH 4103/5416] V4L/DVB (8990): S2API: DVB-S/S2 voltage selection bug fix Thanks to Hans Werner for finding the problem. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index c95a2fb70c3..b51485c1631 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -68,3 +68,4 @@ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid [0070:6900,0070:6904,0070:6902] 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2 [0070:6905,0070:6906] + 70 -> TeVii S460 DVB-S/S2 [D460:9022] diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 86af06cf578..620c6208402 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1290,7 +1290,7 @@ int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp, case TV_SET_VOLTAGE: fe->tv_property_cache.voltage = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, - &fe->tv_property_cache.voltage); + (void *)fe->tv_property_cache.voltage); break; case TV_GET_VOLTAGE: tvp->u.data = fe->tv_property_cache.voltage; -- GitLab From fe03d5ee6758a2533dbc5e69a693d264d270d04b Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 8 Sep 2008 17:16:40 -0300 Subject: [PATCH 4104/5416] V4L/DVB (8991): Added support for DVBWorld 2104 and TeVii S650 USB DVB-S2 cards Added support for DVBWorld 2104 and TeVii S650 USB DVB-S2 cards This cards based on cx24116 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 305 +++++++++++++++++++++++------ drivers/media/dvb/dvb-usb/dw2102.h | 1 - 2 files changed, 248 insertions(+), 58 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index a4d898b44e5..0f3f962b35b 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -1,4 +1,5 @@ -/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card +/* DVB USB framework compliant Linux driver for the +* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card * * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) * @@ -12,18 +13,23 @@ #include "dw2102.h" #include "stv0299.h" #include "z0194a.h" +#include "cx24116.h" #ifndef USB_PID_DW2102 #define USB_PID_DW2102 0x2102 #endif +#ifndef USB_PID_DW2104 +#define USB_PID_DW2104 0x2104 +#endif + #define DW2102_READ_MSG 0 #define DW2102_WRITE_MSG 1 #define REG_1F_SYMBOLRATE_BYTE0 0x1f #define REG_20_SYMBOLRATE_BYTE1 0x20 #define REG_21_SYMBOLRATE_BYTE2 0x21 - +/* on my own*/ #define DW2102_VOLTAGE_CTRL (0x1800) #define DW2102_RC_QUERY (0x1a00) @@ -35,22 +41,27 @@ struct dw2102_rc_keys { u32 event; }; +/* debug */ +static int dvb_usb_dw2102_debug; +module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value, - u8 *data, u16 len, int flags) + u16 index, u8 * data, u16 len, int flags) { int ret; u8 u8buf[len]; unsigned int pipe = (flags == DW2102_READ_MSG) ? - usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); + usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; if (flags == DW2102_WRITE_MSG) memcpy(u8buf, data, len); - ret = usb_control_msg(dev, pipe, request, - request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000); + ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, + value, index , u8buf, len, 2000); if (flags == DW2102_READ_MSG) memcpy(data, u8buf, len); @@ -65,7 +76,6 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], struct dvb_usb_device *d = i2c_get_adapdata(adap); int i = 0, ret = 0; u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; - u8 request; u16 value; if (!d) @@ -76,12 +86,11 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); switch (num) { case 2: /* read stv0299 register */ - request = 0xb5; value = msg[0].buf[0];/* register */ for (i = 0; i < msg[1].len; i++) { value = value + i; - ret = dw2102_op_rw(d->udev, 0xb5, - value, buf6, 2, DW2102_READ_MSG); + ret = dw2102_op_rw(d->udev, 0xb5, value, 0, + buf6, 2, DW2102_READ_MSG); msg[1].buf[i] = buf6[0]; } @@ -93,8 +102,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); buf6[0] = 0x2a; buf6[1] = msg[0].buf[0]; buf6[2] = msg[0].buf[1]; - ret = dw2102_op_rw(d->udev, 0xb2, - 0, buf6, 3, DW2102_WRITE_MSG); + ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, + buf6, 3, DW2102_WRITE_MSG); break; case 0x60: if (msg[0].flags == 0) { @@ -106,26 +115,26 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); buf6[4] = msg[0].buf[1]; buf6[5] = msg[0].buf[2]; buf6[6] = msg[0].buf[3]; - ret = dw2102_op_rw(d->udev, 0xb2, - 0, buf6, 7, DW2102_WRITE_MSG); + ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, + buf6, 7, DW2102_WRITE_MSG); } else { - /* write to tuner pll */ - ret = dw2102_op_rw(d->udev, 0xb5, - 0, buf6, 1, DW2102_READ_MSG); + /* read from tuner */ + ret = dw2102_op_rw(d->udev, 0xb5, 0,0, + buf6, 1, DW2102_READ_MSG); msg[0].buf[0] = buf6[0]; } break; case (DW2102_RC_QUERY): - ret = dw2102_op_rw(d->udev, 0xb8, - 0, buf6, 2, DW2102_READ_MSG); + ret = dw2102_op_rw(d->udev, 0xb8, 0, 0, + buf6, 2, DW2102_READ_MSG); msg[0].buf[0] = buf6[0]; msg[0].buf[1] = buf6[1]; break; case (DW2102_VOLTAGE_CTRL): buf6[0] = 0x30; buf6[1] = msg[0].buf[0]; - ret = dw2102_op_rw(d->udev, 0xb2, - 0, buf6, 2, DW2102_WRITE_MSG); + ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, + buf6, 2, DW2102_WRITE_MSG); break; } @@ -136,6 +145,88 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); return num; } +static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0; + int len, i; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + switch (num) { + case 2: { + /* read */ + /* first write first register number */ + u8 ibuf [msg[1].len + 2], obuf[3]; + obuf[0] = 0xaa; + obuf[1] = msg[0].len; + obuf[2] = msg[0].buf[0]; + ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW2102_WRITE_MSG); + /* second read registers */ + ret = dw2102_op_rw(d->udev, 0xc3, 0xab , 0, + ibuf, msg[1].len + 2, DW2102_READ_MSG); + memcpy(msg[1].buf, ibuf + 2, msg[1].len); + + break; + } + case 1: + switch (msg[0].addr) { + case 0x55: { + if (msg[0].buf[0] == 0xf7) { + /* firmware */ + /* Write in small blocks */ + u8 obuf[19]; + obuf[0] = 0xaa; + obuf[1] = 0x11; + obuf[2] = 0xf7; + len = msg[0].len - 1; + i = 1; + do { + memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); + ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, + obuf, (len > 16 ? 16 : len) + 3, DW2102_WRITE_MSG); + i += 16; + len -= 16; + } while (len > 0); + } else { + /* write to register */ + u8 obuf[msg[0].len + 2]; + obuf[0] = 0xaa; + obuf[1] = msg[0].len; + memcpy(obuf + 2, msg[0].buf, msg[0].len); + ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW2102_WRITE_MSG); + } + break; + } + case(DW2102_RC_QUERY): { + u8 ibuf[2]; + ret = dw2102_op_rw(d->udev, 0xb8, 0, 0, + ibuf, 2, DW2102_READ_MSG); + memcpy(msg[0].buf, ibuf , 2); + break; + } + case(DW2102_VOLTAGE_CTRL): { + u8 obuf[2]; + obuf[0] = 0x30; + obuf[1] = msg[0].buf[0]; + ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, + obuf, 2, DW2102_WRITE_MSG); + break; + } + } + + break; + } + + mutex_unlock(&d->i2c_mutex); + return num; +} + static u32 dw2102_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -146,6 +237,34 @@ static struct i2c_algorithm dw2102_i2c_algo = { .functionality = dw2102_i2c_func, }; +static struct i2c_algorithm dw2104_i2c_algo = { + .master_xfer = dw2104_i2c_transfer, + .functionality = dw2102_i2c_func, +}; + +static int dw2102_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +{ + int i; + u8 ibuf[] = {0, 0}; + u8 eeprom[256], eepromline[16]; + + for (i = 0; i < 256; i++) { + if (dw2102_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW2102_READ_MSG) < 0) { + err("read eeprom failed."); + return -1; + } else { + eepromline[i%16] = ibuf[0]; + eeprom[i] = ibuf[0]; + } + if ((i % 16) == 15) { + deb_xfer("%02x: ", i - 15); + debug_dump(eepromline, 16, deb_xfer); + } + } + memcpy(mac, eeprom + 8, 6); + return 0; +}; + static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { static u8 command_13v[1] = {0x00}; @@ -163,6 +282,22 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) return 0; } +static struct cx24116_config dw2104_config = { + .demod_address = 0x55, + /*.mpg_clk_pos_pol = 0x01,*/ +}; + +static int dw2104_frontend_attach(struct dvb_usb_adapter *d) +{ + if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, + &d->dev->i2c_adap)) != NULL) { + d->fe->ops.set_voltage = dw2102_set_voltage; + info("Attached cx24116!\n"); + return 0; + } + return -EIO; +} + static int dw2102_frontend_attach(struct dvb_usb_adapter *d) { d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, @@ -249,6 +384,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static struct usb_device_id dw2102_table[] = { {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, + {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, + {USB_DEVICE(0x9022, 0xd650)}, { } }; @@ -273,25 +410,23 @@ static int dw2102_load_firmware(struct usb_device *dev, return ret; } break; - case USB_PID_DW2102: + default: fw = frmwr; break; } - info("start downloading DW2102 firmware"); + info("start downloading DW210X firmware"); p = kmalloc(fw->size, GFP_KERNEL); reset = 1; /*stop the CPU*/ - dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG); - dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG); + dw2102_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW2102_WRITE_MSG); + dw2102_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW2102_WRITE_MSG); if (p != NULL) { memcpy(p, fw->data, fw->size); for (i = 0; i < fw->size; i += 0x40) { b = (u8 *) p + i; - if (dw2102_op_rw - (dev, 0xa0, i, b , 0x40, - DW2102_WRITE_MSG) != 0x40 - ) { + if (dw2102_op_rw(dev, 0xa0, i, 0, b , 0x40, + DW2102_WRITE_MSG) != 0x40) { err("error while transferring firmware"); ret = -EINVAL; break; @@ -299,43 +434,45 @@ static int dw2102_load_firmware(struct usb_device *dev, } /* restart the CPU */ reset = 0; - if (ret || dw2102_op_rw - (dev, 0xa0, 0x7f92, &reset, 1, - DW2102_WRITE_MSG) != 1) { + if (ret || dw2102_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, + DW2102_WRITE_MSG) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } - if (ret || dw2102_op_rw - (dev, 0xa0, 0xe600, &reset, 1, - DW2102_WRITE_MSG) != 1) { + if (ret || dw2102_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, + DW2102_WRITE_MSG) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } /* init registers */ switch (dev->descriptor.idProduct) { + case USB_PID_DW2104: + case 0xd650: + reset = 1; + dw2102_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, + DW2102_WRITE_MSG); + reset = 0; + dw2102_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, + DW2102_WRITE_MSG); + break; case USB_PID_DW2102: - dw2102_op_rw - (dev, 0xbf, 0x0040, &reset, 0, - DW2102_WRITE_MSG); - dw2102_op_rw - (dev, 0xb9, 0x0000, &reset16[0], 2, - DW2102_READ_MSG); + dw2102_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, + DW2102_WRITE_MSG); + dw2102_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, + DW2102_READ_MSG); break; case 0x2101: - dw2102_op_rw - (dev, 0xbc, 0x0030, &reset16[0], 2, - DW2102_READ_MSG); - dw2102_op_rw - (dev, 0xba, 0x0000, &reset16[0], 7, - DW2102_READ_MSG); - dw2102_op_rw - (dev, 0xba, 0x0000, &reset16[0], 7, - DW2102_READ_MSG); - dw2102_op_rw - (dev, 0xb9, 0x0000, &reset16[0], 2, - DW2102_READ_MSG); + dw2102_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, + DW2102_READ_MSG); + dw2102_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, + DW2102_READ_MSG); + dw2102_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, + DW2102_READ_MSG); + dw2102_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, + DW2102_READ_MSG); break; } + msleep(100); kfree(p); } return ret; @@ -358,7 +495,8 @@ static struct dvb_usb_device_properties dw2102_properties = { /* parameter for the MPEG2-data transfer */ .num_adapters = 1, .download_firmware = dw2102_load_firmware, - .adapter = { + .read_mac_address = dw2102_read_mac_address, + .adapter = { { .frontend_attach = dw2102_frontend_attach, .streaming_ctrl = NULL, @@ -388,11 +526,64 @@ static struct dvb_usb_device_properties dw2102_properties = { } }; +static struct dvb_usb_device_properties dw2104_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-dw2104.fw", + .size_of_priv = sizeof(struct dw2102_state), + .no_reconnect = 1, + + .i2c_algo = &dw2104_i2c_algo, + .rc_key_map = dw2102_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys), + .rc_interval = 150, + .rc_query = dw2102_rc_query, + + .generic_bulk_ctrl_endpoint = 0x81, + /* parameter for the MPEG2-data transfer */ + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = dw2102_read_mac_address, + .adapter = { + { + .frontend_attach = dw2104_frontend_attach, + .streaming_ctrl = NULL, + /*.tuner_attach = dw2104_tuner_attach,*/ + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + .num_device_descs = 2, + .devices = { + { "DVBWorld DW2104 USB2.0", + {&dw2102_table[2], NULL}, + {NULL}, + }, + { "TeVii S650 USB2.0", + {&dw2102_table[3], NULL}, + {NULL}, + }, + } +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf, &dw2102_properties, - THIS_MODULE, NULL, adapter_nr); + if (0 == dvb_usb_device_init(intf, &dw2102_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dw2104_properties, + THIS_MODULE, NULL, adapter_nr)) { + return 0; + } + return -ENODEV; } static struct usb_driver dw2102_driver = { @@ -420,6 +611,6 @@ module_init(dw2102_module_init); module_exit(dw2102_module_exit); MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); -MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device"); +MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h index 7a310f90683..e3370734e95 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.h +++ b/drivers/media/dvb/dvb-usb/dw2102.h @@ -4,6 +4,5 @@ #define DVB_USB_LOG_PREFIX "dw2102" #include "dvb-usb.h" -extern int dvb_usb_dw2102_debug; #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) #endif -- GitLab From 4e54676895a867621f8451b8d97549172730997d Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 9 Sep 2008 11:29:43 -0300 Subject: [PATCH 4105/5416] V4L/DVB (8992): Kconfig corrections for DVBWorld 2104 and TeVii S650 USB DVB-S2 cards Change menu item in Kconfig for DVBWorld 2104 and TeVii S650 USB DVB-S2 cards Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index b35d7f0db9a..aee3b5dd651 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -247,12 +247,14 @@ config DVB_USB_AF9005_REMOTE Afatech AF9005 based receiver. config DVB_USB_DW2102 - tristate "DvbWorld 2102 DVB-S USB2.0 receiver" + tristate "DvbWorld DVB-S/S2 USB2.0 support" depends on DVB_USB - select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_CX24116 if !DVB_FE_CUSTOMISE help - Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver. + Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers + and the TeVii S650. config DVB_USB_ANYSEE tristate "Anysee DVB-T/C USB2.0 support" -- GitLab From 3f8e51add2b7d37f16343e6bdcc63862d87ccd04 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 9 Sep 2008 13:22:29 -0300 Subject: [PATCH 4106/5416] V4L/DVB (8993): cx24116: Fix lock for high (above 30000 kSyms) symbol rates cx24116: Fix lock for high (above 30000 kSyms) symbol rates Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24116.c | 37 ++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 1402086a5c4..2ff9e20c595 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -30,6 +30,11 @@ * Sync with legacy version. * Some clean ups. */ +/* Updates by Igor Liplianin + * + * September, 9th 2008 + * Fixed locking on high symbol rates (>30000). + */ #include #include @@ -809,7 +814,7 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par struct tv_frontend_properties *c = &fe->tv_property_cache; struct cx24116_cmd cmd; fe_status_t tunerstat; - int ret; + int ret, above30msps; u8 retune=4; dprintk("%s()\n",__func__); @@ -839,6 +844,16 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); + above30msps = (state->dcur.symbol_rate > 30000000); + + if (above30msps){ + cx24116_writereg(state, 0xF9, 0x01); + cx24116_writereg(state, 0xF3, 0x44); + } else { + cx24116_writereg(state, 0xF9, 0x00); + cx24116_writereg(state, 0xF3, 0x46); + } + /* Prepare a tune request */ cmd.args[0x00] = CMD_TUNEREQUEST; @@ -866,11 +881,21 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par cmd.args[0x0b] = 0x00; cmd.args[0x0c] = 0x02; cmd.args[0x0d] = state->dcur.fec_mask; - cmd.args[0x0e] = 0x06; - cmd.args[0x0f] = 0x00; - cmd.args[0x10] = 0x00; - cmd.args[0x11] = 0xFA; - cmd.args[0x12] = 0x24; + + if (above30msps){ + cmd.args[0x0e] = 0x04; + cmd.args[0x0f] = 0x00; + cmd.args[0x10] = 0x01; + cmd.args[0x11] = 0x77; + cmd.args[0x12] = 0x36; + } else { + cmd.args[0x0e] = 0x06; + cmd.args[0x0f] = 0x00; + cmd.args[0x10] = 0x00; + cmd.args[0x11] = 0xFA; + cmd.args[0x12] = 0x24; + } + cmd.len= 0x13; /* We need to support pilot and non-pilot tuning in the -- GitLab From cc8c4f3a9c8dacff198438debd159ae4753744fc Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 9 Sep 2008 13:57:47 -0300 Subject: [PATCH 4107/5416] V4L/DVB (8994): Adjust MPEG initialization in cx24116 Adjust MPEG initialization in cx24116 in order to accomodate different MPEG CLK position and polarity in different cards. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 2 +- drivers/media/dvb/frontends/cx24116.c | 5 ++++- drivers/media/dvb/frontends/cx24116.h | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 0f3f962b35b..ad3d6fca9ab 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -284,7 +284,7 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static struct cx24116_config dw2104_config = { .demod_address = 0x55, - /*.mpg_clk_pos_pol = 0x01,*/ + .mpg_clk_pos_pol = 0x01, }; static int dw2104_frontend_attach(struct dvb_usb_adapter *d) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 2ff9e20c595..666a0d89e83 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -478,7 +478,10 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware cmd.args[0x01] = 0x01; cmd.args[0x02] = 0x75; cmd.args[0x03] = 0x00; - cmd.args[0x04] = 0x02; + if (state->config->mpg_clk_pos_pol) + cmd.args[0x04] = state->config->mpg_clk_pos_pol; + else + cmd.args[0x04] = 0x02; cmd.args[0x05] = 0x00; cmd.len= 0x06; ret = cx24116_cmd_execute(fe, &cmd); diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h index 27896725204..8dbcec26839 100644 --- a/drivers/media/dvb/frontends/cx24116.h +++ b/drivers/media/dvb/frontends/cx24116.h @@ -33,6 +33,9 @@ struct cx24116_config /* Need to reset device during firmware loading */ int (*reset_device)(struct dvb_frontend* fe); + + /* Need to set MPEG parameters */ + u8 mpg_clk_pos_pol:0x02; }; #if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) -- GitLab From 56f0680a28397f4b412fc14f60ac380b910ee328 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 11 Sep 2008 10:19:27 -0300 Subject: [PATCH 4108/5416] V4L/DVB (8995): S2API: tv_ / TV_ to dtv_ / DTV_ namespace changes The group preferred dtv_ over tv_, this implements it. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 442 +++++++++++----------- drivers/media/dvb/dvb-core/dvb_frontend.h | 8 +- drivers/media/dvb/frontends/cx24116.c | 6 +- include/linux/dvb/frontend.h | 108 +++--- 4 files changed, 282 insertions(+), 282 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 620c6208402..9c4761506d2 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -755,235 +755,235 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, return 0; } -struct tv_cmds_h tv_cmds[] = { - [TV_SEQ_UNDEFINED] = { - .name = "TV_SEQ_UNDEFINED", - .cmd = TV_SEQ_UNDEFINED, +struct dtv_cmds_h dtv_cmds[] = { + [DTV_SEQ_UNDEFINED] = { + .name = "DTV_SEQ_UNDEFINED", + .cmd = DTV_SEQ_UNDEFINED, .set = 1, }, - [TV_SEQ_START] = { - .name = "TV_SEQ_START", - .cmd = TV_SEQ_START, + [DTV_SEQ_START] = { + .name = "DTV_SEQ_START", + .cmd = DTV_SEQ_START, .set = 1, }, - [TV_SEQ_CONTINUE] = { - .name = "TV_SEQ_CONTINUE", - .cmd = TV_SEQ_CONTINUE, + [DTV_SEQ_CONTINUE] = { + .name = "DTV_SEQ_CONTINUE", + .cmd = DTV_SEQ_CONTINUE, .set = 1, }, - [TV_SEQ_COMPLETE] = { - .name = "TV_SEQ_COMPLETE", - .cmd = TV_SEQ_COMPLETE, + [DTV_SEQ_COMPLETE] = { + .name = "DTV_SEQ_COMPLETE", + .cmd = DTV_SEQ_COMPLETE, .set = 1, }, - [TV_SEQ_TERMINATE] = { - .name = "TV_SEQ_TERMINATE", - .cmd = TV_SEQ_TERMINATE, + [DTV_SEQ_TERMINATE] = { + .name = "DTV_SEQ_TERMINATE", + .cmd = DTV_SEQ_TERMINATE, .set = 1, }, /* Set */ - [TV_SET_FREQUENCY] = { - .name = "TV_SET_FREQUENCY", - .cmd = TV_SET_FREQUENCY, + [DTV_SET_FREQUENCY] = { + .name = "DTV_SET_FREQUENCY", + .cmd = DTV_SET_FREQUENCY, .set = 1, }, - [TV_SET_BANDWIDTH] = { - .name = "TV_SET_BANDWIDTH", - .cmd = TV_SET_BANDWIDTH, + [DTV_SET_BANDWIDTH] = { + .name = "DTV_SET_BANDWIDTH", + .cmd = DTV_SET_BANDWIDTH, .set = 1, }, - [TV_SET_MODULATION] = { - .name = "TV_SET_MODULATION", - .cmd = TV_SET_MODULATION, + [DTV_SET_MODULATION] = { + .name = "DTV_SET_MODULATION", + .cmd = DTV_SET_MODULATION, .set = 1, }, - [TV_SET_INVERSION] = { - .name = "TV_SET_INVERSION", - .cmd = TV_SET_INVERSION, + [DTV_SET_INVERSION] = { + .name = "DTV_SET_INVERSION", + .cmd = DTV_SET_INVERSION, .set = 1, }, - [TV_SET_DISEQC_MASTER] = { - .name = "TV_SET_DISEQC_MASTER", - .cmd = TV_SET_DISEQC_MASTER, + [DTV_SET_DISEQC_MASTER] = { + .name = "DTV_SET_DISEQC_MASTER", + .cmd = DTV_SET_DISEQC_MASTER, .set = 1, .buffer = 1, }, - [TV_SET_SYMBOLRATE] = { - .name = "TV_SET_SYMBOLRATE", - .cmd = TV_SET_SYMBOLRATE, + [DTV_SET_SYMBOLRATE] = { + .name = "DTV_SET_SYMBOLRATE", + .cmd = DTV_SET_SYMBOLRATE, .set = 1, }, - [TV_SET_INNERFEC] = { - .name = "TV_SET_INNERFEC", - .cmd = TV_SET_INNERFEC, + [DTV_SET_INNERFEC] = { + .name = "DTV_SET_INNERFEC", + .cmd = DTV_SET_INNERFEC, .set = 1, }, - [TV_SET_VOLTAGE] = { - .name = "TV_SET_VOLTAGE", - .cmd = TV_SET_VOLTAGE, + [DTV_SET_VOLTAGE] = { + .name = "DTV_SET_VOLTAGE", + .cmd = DTV_SET_VOLTAGE, .set = 1, }, - [TV_SET_TONE] = { - .name = "TV_SET_TONE", - .cmd = TV_SET_TONE, + [DTV_SET_TONE] = { + .name = "DTV_SET_TONE", + .cmd = DTV_SET_TONE, .set = 1, }, - [TV_SET_PILOT] = { - .name = "TV_SET_PILOT", - .cmd = TV_SET_PILOT, + [DTV_SET_PILOT] = { + .name = "DTV_SET_PILOT", + .cmd = DTV_SET_PILOT, .set = 1, }, - [TV_SET_ROLLOFF] = { - .name = "TV_SET_ROLLOFF", - .cmd = TV_SET_ROLLOFF, + [DTV_SET_ROLLOFF] = { + .name = "DTV_SET_ROLLOFF", + .cmd = DTV_SET_ROLLOFF, .set = 1, }, - [TV_SET_DELIVERY_SYSTEM] = { - .name = "TV_SET_DELIVERY_SYSTEM", - .cmd = TV_SET_DELIVERY_SYSTEM, + [DTV_SET_DELIVERY_SYSTEM] = { + .name = "DTV_SET_DELIVERY_SYSTEM", + .cmd = DTV_SET_DELIVERY_SYSTEM, .set = 1, }, - [TV_SET_ISDB_SEGMENT_NUM] = { - .name = "TV_SET_ISDB_SEGMENT_NUM", - .cmd = TV_SET_ISDB_SEGMENT_NUM, + [DTV_SET_ISDB_SEGMENT_NUM] = { + .name = "DTV_SET_ISDB_SEGMENT_NUM", + .cmd = DTV_SET_ISDB_SEGMENT_NUM, .set = 1, }, - [TV_SET_ISDB_SEGMENT_WIDTH] = { - .name = "TV_SET_ISDB_SEGMENT_WIDTH", - .cmd = TV_SET_ISDB_SEGMENT_WIDTH, + [DTV_SET_ISDB_SEGMENT_WIDTH] = { + .name = "DTV_SET_ISDB_SEGMENT_WIDTH", + .cmd = DTV_SET_ISDB_SEGMENT_WIDTH, .set = 1, }, /* Get */ - [TV_GET_FREQUENCY] = { - .name = "TV_GET_FREQUENCY", - .cmd = TV_GET_FREQUENCY, + [DTV_GET_FREQUENCY] = { + .name = "DTV_GET_FREQUENCY", + .cmd = DTV_GET_FREQUENCY, .set = 0, }, - [TV_GET_BANDWIDTH] = { - .name = "TV_GET_BANDWIDTH", - .cmd = TV_GET_BANDWIDTH, + [DTV_GET_BANDWIDTH] = { + .name = "DTV_GET_BANDWIDTH", + .cmd = DTV_GET_BANDWIDTH, .set = 0, }, - [TV_GET_MODULATION] = { - .name = "TV_GET_MODULATION", - .cmd = TV_GET_MODULATION, + [DTV_GET_MODULATION] = { + .name = "DTV_GET_MODULATION", + .cmd = DTV_GET_MODULATION, .set = 0, }, - [TV_GET_INVERSION] = { - .name = "TV_GET_INVERSION", - .cmd = TV_GET_INVERSION, + [DTV_GET_INVERSION] = { + .name = "DTV_GET_INVERSION", + .cmd = DTV_GET_INVERSION, .set = 0, }, - [TV_GET_DISEQC_SLAVE_REPLY] = { - .name = "TV_GET_DISEQC_SLAVE_REPLY", - .cmd = TV_GET_DISEQC_SLAVE_REPLY, + [DTV_GET_DISEQC_SLAVE_REPLY] = { + .name = "DTV_GET_DISEQC_SLAVE_REPLY", + .cmd = DTV_GET_DISEQC_SLAVE_REPLY, .set = 0, .buffer = 1, }, - [TV_GET_SYMBOLRATE] = { - .name = "TV_GET_SYMBOLRATE", - .cmd = TV_GET_SYMBOLRATE, + [DTV_GET_SYMBOLRATE] = { + .name = "DTV_GET_SYMBOLRATE", + .cmd = DTV_GET_SYMBOLRATE, .set = 0, }, - [TV_GET_INNERFEC] = { - .name = "TV_GET_INNERFEC", - .cmd = TV_GET_INNERFEC, + [DTV_GET_INNERFEC] = { + .name = "DTV_GET_INNERFEC", + .cmd = DTV_GET_INNERFEC, .set = 0, }, - [TV_GET_VOLTAGE] = { - .name = "TV_GET_VOLTAGE", - .cmd = TV_GET_VOLTAGE, + [DTV_GET_VOLTAGE] = { + .name = "DTV_GET_VOLTAGE", + .cmd = DTV_GET_VOLTAGE, .set = 0, }, - [TV_GET_TONE] = { - .name = "TV_GET_TONE", - .cmd = TV_GET_TONE, + [DTV_GET_TONE] = { + .name = "DTV_GET_TONE", + .cmd = DTV_GET_TONE, .set = 0, }, - [TV_GET_PILOT] = { - .name = "TV_GET_PILOT", - .cmd = TV_GET_PILOT, + [DTV_GET_PILOT] = { + .name = "DTV_GET_PILOT", + .cmd = DTV_GET_PILOT, .set = 0, }, - [TV_GET_ROLLOFF] = { - .name = "TV_GET_ROLLOFF", - .cmd = TV_GET_ROLLOFF, + [DTV_GET_ROLLOFF] = { + .name = "DTV_GET_ROLLOFF", + .cmd = DTV_GET_ROLLOFF, .set = 0, }, - [TV_GET_DELIVERY_SYSTEM] = { - .name = "TV_GET_DELIVERY_SYSTEM", - .cmd = TV_GET_DELIVERY_SYSTEM, + [DTV_GET_DELIVERY_SYSTEM] = { + .name = "DTV_GET_DELIVERY_SYSTEM", + .cmd = DTV_GET_DELIVERY_SYSTEM, .set = 0, }, - [TV_GET_ISDB_SEGMENT_NUM] = { - .name = "TV_GET_ISDB_SEGMENT_NUM", - .cmd = TV_GET_ISDB_SEGMENT_NUM, + [DTV_GET_ISDB_SEGMENT_NUM] = { + .name = "DTV_GET_ISDB_SEGMENT_NUM", + .cmd = DTV_GET_ISDB_SEGMENT_NUM, .set = 0, }, - [TV_GET_ISDB_SEGMENT_WIDTH] = { - .name = "TV_GET_ISDB_SEGMENT_WIDTH", - .cmd = TV_GET_ISDB_SEGMENT_WIDTH, + [DTV_GET_ISDB_SEGMENT_WIDTH] = { + .name = "DTV_GET_ISDB_SEGMENT_WIDTH", + .cmd = DTV_GET_ISDB_SEGMENT_WIDTH, .set = 0, }, - [TV_GET_ISDB_LAYERA_FEC] = { - .name = "TV_GET_ISDB_LAYERA_FEC", - .cmd = TV_GET_ISDB_LAYERA_FEC, + [DTV_GET_ISDB_LAYERA_FEC] = { + .name = "DTV_GET_ISDB_LAYERA_FEC", + .cmd = DTV_GET_ISDB_LAYERA_FEC, .set = 0, }, - [TV_GET_ISDB_LAYERA_MODULATION] = { - .name = "TV_GET_ISDB_LAYERA_MODULATION", - .cmd = TV_GET_ISDB_LAYERA_MODULATION, + [DTV_GET_ISDB_LAYERA_MODULATION] = { + .name = "DTV_GET_ISDB_LAYERA_MODULATION", + .cmd = DTV_GET_ISDB_LAYERA_MODULATION, .set = 0, }, - [TV_GET_ISDB_LAYERA_SEGMENT_WIDTH] = { - .name = "TV_GET_ISDB_LAYERA_SEGMENT_WIDTH", - .cmd = TV_GET_ISDB_LAYERA_SEGMENT_WIDTH, + [DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH] = { + .name = "DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH", + .cmd = DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH, .set = 0, }, - [TV_GET_ISDB_LAYERB_FEC] = { - .name = "TV_GET_ISDB_LAYERB_FEC", - .cmd = TV_GET_ISDB_LAYERB_FEC, + [DTV_GET_ISDB_LAYERB_FEC] = { + .name = "DTV_GET_ISDB_LAYERB_FEC", + .cmd = DTV_GET_ISDB_LAYERB_FEC, .set = 0, }, - [TV_GET_ISDB_LAYERB_MODULATION] = { - .name = "TV_GET_ISDB_LAYERB_MODULATION", - .cmd = TV_GET_ISDB_LAYERB_MODULATION, + [DTV_GET_ISDB_LAYERB_MODULATION] = { + .name = "DTV_GET_ISDB_LAYERB_MODULATION", + .cmd = DTV_GET_ISDB_LAYERB_MODULATION, .set = 0, }, - [TV_GET_ISDB_LAYERB_SEGMENT_WIDTH] = { - .name = "TV_GET_ISDB_LAYERB_SEGMENT_WIDTH", - .cmd = TV_GET_ISDB_LAYERB_SEGMENT_WIDTH, + [DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH] = { + .name = "DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH", + .cmd = DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH, .set = 0, }, - [TV_GET_ISDB_LAYERC_FEC] = { - .name = "TV_GET_ISDB_LAYERC_FEC", - .cmd = TV_GET_ISDB_LAYERC_FEC, + [DTV_GET_ISDB_LAYERC_FEC] = { + .name = "DTV_GET_ISDB_LAYERC_FEC", + .cmd = DTV_GET_ISDB_LAYERC_FEC, .set = 0, }, - [TV_GET_ISDB_LAYERC_MODULATION] = { - .name = "TV_GET_ISDB_LAYERC_MODULATION", - .cmd = TV_GET_ISDB_LAYERC_MODULATION, + [DTV_GET_ISDB_LAYERC_MODULATION] = { + .name = "DTV_GET_ISDB_LAYERC_MODULATION", + .cmd = DTV_GET_ISDB_LAYERC_MODULATION, .set = 0, }, - [TV_GET_ISDB_LAYERC_SEGMENT_WIDTH] = { - .name = "TV_GET_ISDB_LAYERC_SEGMENT_WIDTH", - .cmd = TV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + [DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH] = { + .name = "DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH", + .cmd = DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH, .set = 0, }, }; -void tv_property_dump(tv_property_t *tvp) +void dtv_property_dump(dtv_property_t *tvp) { int i; printk("%s() tvp.cmd = 0x%08x (%s)\n" ,__FUNCTION__ ,tvp->cmd - ,tv_cmds[ tvp->cmd ].name); + ,dtv_cmds[ tvp->cmd ].name); - if(tv_cmds[ tvp->cmd ].buffer) { + if(dtv_cmds[ tvp->cmd ].buffer) { printk("%s() tvp.u.buffer.len = 0x%02x\n" ,__FUNCTION__ @@ -1008,7 +1008,7 @@ int is_legacy_delivery_system(fe_delivery_system_t s) return 0; } -int tv_property_cache_submit(struct dvb_frontend *fe) +int dtv_property_cache_submit(struct dvb_frontend *fe) { /* We have to do one of two things: @@ -1036,7 +1036,7 @@ int tv_property_cache_submit(struct dvb_frontend *fe) int r; - struct tv_frontend_properties *c = &fe->tv_property_cache; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_parameters p; @@ -1115,7 +1115,7 @@ int tv_property_cache_submit(struct dvb_frontend *fe) case _16APSK: case NBC_QPSK: /* Just post a notification to the demod driver and let it pull - * the specific values it wants from its tv_property_cache. + * the specific values it wants from its dtv_property_cache. * It can decide how best to use those parameters. * IOCTL will call set_frontend (by default) due to zigzag * support etc. @@ -1161,147 +1161,147 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, unsigned int cmd, void *parg); -int tv_property_process(struct dvb_frontend *fe, tv_property_t *tvp, +int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, struct inode *inode, struct file *file) { int r = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; printk("%s()\n", __FUNCTION__); - tv_property_dump(tvp); + dtv_property_dump(tvp); switch(tvp->cmd) { - case TV_SEQ_START: - case TV_SEQ_TERMINATE: + case DTV_SEQ_START: + case DTV_SEQ_TERMINATE: /* Reset a cache of data specific to the frontend here. This does * not effect hardware. */ printk("%s() Flushing property cache\n", __FUNCTION__); - memset(&fe->tv_property_cache, 0, sizeof(struct tv_frontend_properties)); - fe->tv_property_cache.state = TV_SEQ_START; - fe->tv_property_cache.delivery_system = SYS_UNDEFINED; + memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); + fe->dtv_property_cache.state = DTV_SEQ_START; + fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; break; - case TV_SEQ_COMPLETE: + case DTV_SEQ_COMPLETE: /* interpret the cache of data, build either a traditional frontend * tunerequest and submit it to a subset of the ioctl handler, * or, call a new undefined method on the frontend to deal with * all new tune requests. */ - fe->tv_property_cache.state = TV_SEQ_COMPLETE; + fe->dtv_property_cache.state = DTV_SEQ_COMPLETE; printk("%s() Finalised property cache\n", __FUNCTION__); - r |= tv_property_cache_submit(fe); + r |= dtv_property_cache_submit(fe); r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; - case TV_SET_FREQUENCY: - fe->tv_property_cache.frequency = tvp->u.data; + case DTV_SET_FREQUENCY: + fe->dtv_property_cache.frequency = tvp->u.data; break; - case TV_GET_FREQUENCY: - tvp->u.data = fe->tv_property_cache.frequency; + case DTV_GET_FREQUENCY: + tvp->u.data = fe->dtv_property_cache.frequency; break; - case TV_SET_MODULATION: - fe->tv_property_cache.modulation = tvp->u.data; + case DTV_SET_MODULATION: + fe->dtv_property_cache.modulation = tvp->u.data; break; - case TV_GET_MODULATION: - tvp->u.data = fe->tv_property_cache.modulation; + case DTV_GET_MODULATION: + tvp->u.data = fe->dtv_property_cache.modulation; break; - case TV_SET_BANDWIDTH: - fe->tv_property_cache.bandwidth = tvp->u.data; + case DTV_SET_BANDWIDTH: + fe->dtv_property_cache.bandwidth = tvp->u.data; break; - case TV_GET_BANDWIDTH: - tvp->u.data = fe->tv_property_cache.bandwidth; + case DTV_GET_BANDWIDTH: + tvp->u.data = fe->dtv_property_cache.bandwidth; break; - case TV_SET_INVERSION: - fe->tv_property_cache.inversion = tvp->u.data; + case DTV_SET_INVERSION: + fe->dtv_property_cache.inversion = tvp->u.data; break; - case TV_GET_INVERSION: - tvp->u.data = fe->tv_property_cache.inversion; + case DTV_GET_INVERSION: + tvp->u.data = fe->dtv_property_cache.inversion; break; - case TV_SET_SYMBOLRATE: - fe->tv_property_cache.symbol_rate = tvp->u.data; + case DTV_SET_SYMBOLRATE: + fe->dtv_property_cache.symbol_rate = tvp->u.data; break; - case TV_GET_SYMBOLRATE: - tvp->u.data = fe->tv_property_cache.symbol_rate; + case DTV_GET_SYMBOLRATE: + tvp->u.data = fe->dtv_property_cache.symbol_rate; break; - case TV_SET_INNERFEC: - fe->tv_property_cache.fec_inner = tvp->u.data; + case DTV_SET_INNERFEC: + fe->dtv_property_cache.fec_inner = tvp->u.data; break; - case TV_GET_INNERFEC: - tvp->u.data = fe->tv_property_cache.fec_inner; + case DTV_GET_INNERFEC: + tvp->u.data = fe->dtv_property_cache.fec_inner; break; - case TV_SET_PILOT: - fe->tv_property_cache.pilot = tvp->u.data; + case DTV_SET_PILOT: + fe->dtv_property_cache.pilot = tvp->u.data; break; - case TV_GET_PILOT: - tvp->u.data = fe->tv_property_cache.pilot; + case DTV_GET_PILOT: + tvp->u.data = fe->dtv_property_cache.pilot; break; - case TV_SET_ROLLOFF: - fe->tv_property_cache.rolloff = tvp->u.data; + case DTV_SET_ROLLOFF: + fe->dtv_property_cache.rolloff = tvp->u.data; break; - case TV_GET_ROLLOFF: - tvp->u.data = fe->tv_property_cache.rolloff; + case DTV_GET_ROLLOFF: + tvp->u.data = fe->dtv_property_cache.rolloff; break; - case TV_SET_DELIVERY_SYSTEM: - fe->tv_property_cache.delivery_system = tvp->u.data; + case DTV_SET_DELIVERY_SYSTEM: + fe->dtv_property_cache.delivery_system = tvp->u.data; break; - case TV_GET_DELIVERY_SYSTEM: - tvp->u.data = fe->tv_property_cache.delivery_system; + case DTV_GET_DELIVERY_SYSTEM: + tvp->u.data = fe->dtv_property_cache.delivery_system; break; /* ISDB-T Support here */ - case TV_SET_ISDB_SEGMENT_NUM: - fe->tv_property_cache.isdb_segment_num = tvp->u.data; + case DTV_SET_ISDB_SEGMENT_NUM: + fe->dtv_property_cache.isdb_segment_num = tvp->u.data; break; - case TV_GET_ISDB_SEGMENT_NUM: - tvp->u.data = fe->tv_property_cache.isdb_segment_num; + case DTV_GET_ISDB_SEGMENT_NUM: + tvp->u.data = fe->dtv_property_cache.isdb_segment_num; break; - case TV_SET_ISDB_SEGMENT_WIDTH: - fe->tv_property_cache.isdb_segment_width = tvp->u.data; + case DTV_SET_ISDB_SEGMENT_WIDTH: + fe->dtv_property_cache.isdb_segment_width = tvp->u.data; break; - case TV_GET_ISDB_SEGMENT_WIDTH: - tvp->u.data = fe->tv_property_cache.isdb_segment_width; + case DTV_GET_ISDB_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_segment_width; break; - case TV_GET_ISDB_LAYERA_FEC: - tvp->u.data = fe->tv_property_cache.isdb_layera_fec; + case DTV_GET_ISDB_LAYERA_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layera_fec; break; - case TV_GET_ISDB_LAYERA_MODULATION: - tvp->u.data = fe->tv_property_cache.isdb_layera_modulation; + case DTV_GET_ISDB_LAYERA_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layera_modulation; break; - case TV_GET_ISDB_LAYERA_SEGMENT_WIDTH: - tvp->u.data = fe->tv_property_cache.isdb_layera_segment_width; + case DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layera_segment_width; break; - case TV_GET_ISDB_LAYERB_FEC: - tvp->u.data = fe->tv_property_cache.isdb_layerb_fec; + case DTV_GET_ISDB_LAYERB_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_fec; break; - case TV_GET_ISDB_LAYERB_MODULATION: - tvp->u.data = fe->tv_property_cache.isdb_layerb_modulation; + case DTV_GET_ISDB_LAYERB_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_modulation; break; - case TV_GET_ISDB_LAYERB_SEGMENT_WIDTH: - tvp->u.data = fe->tv_property_cache.isdb_layerb_segment_width; + case DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_segment_width; break; - case TV_GET_ISDB_LAYERC_FEC: - tvp->u.data = fe->tv_property_cache.isdb_layerc_fec; + case DTV_GET_ISDB_LAYERC_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_fec; break; - case TV_GET_ISDB_LAYERC_MODULATION: - tvp->u.data = fe->tv_property_cache.isdb_layerc_modulation; + case DTV_GET_ISDB_LAYERC_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_modulation; break; - case TV_GET_ISDB_LAYERC_SEGMENT_WIDTH: - tvp->u.data = fe->tv_property_cache.isdb_layerc_segment_width; + case DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_segment_width; break; - case TV_SET_VOLTAGE: - fe->tv_property_cache.voltage = tvp->u.data; + case DTV_SET_VOLTAGE: + fe->dtv_property_cache.voltage = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, - (void *)fe->tv_property_cache.voltage); + (void *)fe->dtv_property_cache.voltage); break; - case TV_GET_VOLTAGE: - tvp->u.data = fe->tv_property_cache.voltage; + case DTV_GET_VOLTAGE: + tvp->u.data = fe->dtv_property_cache.voltage; break; - case TV_SET_TONE: - fe->tv_property_cache.sectone = tvp->u.data; + case DTV_SET_TONE: + fe->dtv_property_cache.sectone = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE, - (void *)fe->tv_property_cache.sectone); + (void *)fe->dtv_property_cache.sectone); break; - case TV_GET_TONE: - tvp->u.data = fe->tv_property_cache.sectone; + case DTV_GET_TONE: + tvp->u.data = fe->dtv_property_cache.sectone; break; } @@ -1344,7 +1344,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; int err = -EOPNOTSUPP; - tv_property_t *tvp; + dtv_property_t *tvp; dprintk("%s\n", __func__); @@ -1355,14 +1355,14 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, /* TODO: ioctl userdata out of range check here */ tvp = parg; - while(tvp->cmd != TV_SEQ_UNDEFINED) { - tv_property_process(fe, tvp, inode, file); - if( (tvp->cmd == TV_SEQ_TERMINATE) || (tvp->cmd == TV_SEQ_COMPLETE) ) + while(tvp->cmd != DTV_SEQ_UNDEFINED) { + dtv_property_process(fe, tvp, inode, file); + if( (tvp->cmd == DTV_SEQ_TERMINATE) || (tvp->cmd == DTV_SEQ_COMPLETE) ) break; tvp++; } - if(fe->tv_property_cache.state == TV_SEQ_COMPLETE) { + if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); } err = 0; @@ -1545,7 +1545,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, case FE_SET_FRONTEND: { struct dvb_frontend_tune_settings fetunesettings; - if(fe->tv_property_cache.state == TV_SEQ_COMPLETE) { + if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { err = -EINVAL; break; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 61d53ee70f2..f376f281cde 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -170,8 +170,8 @@ struct dvb_frontend_ops { struct dvb_tuner_ops tuner_ops; struct analog_demod_ops analog_ops; - int (*set_property)(struct dvb_frontend* fe, tv_property_t* tvp); - int (*get_property)(struct dvb_frontend* fe, tv_property_t* tvp); + int (*set_property)(struct dvb_frontend* fe, dtv_property_t* tvp); + int (*get_property)(struct dvb_frontend* fe, dtv_property_t* tvp); int (*set_params)(struct dvb_frontend* fe); }; @@ -186,7 +186,7 @@ struct dvb_fe_events { struct mutex mtx; }; -struct tv_frontend_properties { +struct dtv_frontend_properties { /* Cache State */ u32 state; @@ -233,7 +233,7 @@ struct dvb_frontend { void *frontend_priv; void *sec_priv; void *analog_demod_priv; - struct tv_frontend_properties tv_property_cache; + struct dtv_frontend_properties dtv_property_cache; }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 666a0d89e83..f150fa24ff9 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -776,7 +776,7 @@ error: static int cx24116_get_params(struct dvb_frontend* fe) { struct cx24116_state *state = fe->demodulator_priv; - struct tv_frontend_properties *cache = &fe->tv_property_cache; + struct dtv_frontend_properties *cache = &fe->dtv_property_cache; dprintk("%s()\n",__func__); @@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe) return cx24116_diseqc_init(fe); } -static int cx24116_set_property(struct dvb_frontend *fe, tv_property_t* tvp) +static int cx24116_set_property(struct dvb_frontend *fe, dtv_property_t* tvp) { dprintk("%s(..)\n", __func__); return 0; @@ -814,7 +814,7 @@ static int cx24116_set_params(struct dvb_frontend *fe) static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct cx24116_state *state = fe->demodulator_priv; - struct tv_frontend_properties *c = &fe->tv_property_cache; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24116_cmd cmd; fe_status_t tunerstat; int ret, above30msps; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 4d377002173..aeace74b536 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -250,61 +250,61 @@ struct dvb_frontend_event { * don't insert random new commands and break backwards * binary compatability. */ -typedef enum tv_cmd_types { - TV_SEQ_UNDEFINED, - TV_SEQ_START, - TV_SEQ_CONTINUE, - TV_SEQ_COMPLETE, - TV_SEQ_TERMINATE, - - TV_SET_FREQUENCY, - TV_SET_MODULATION, - TV_SET_BANDWIDTH, - TV_SET_INVERSION, - TV_SET_DISEQC_MASTER, - TV_SET_SYMBOLRATE, - TV_SET_INNERFEC, - TV_SET_VOLTAGE, - TV_SET_TONE, - TV_SET_PILOT, - TV_SET_ROLLOFF, - - TV_GET_FREQUENCY, - TV_GET_MODULATION, - TV_GET_BANDWIDTH, - TV_GET_INVERSION, - TV_GET_DISEQC_SLAVE_REPLY, - TV_GET_SYMBOLRATE, - TV_GET_INNERFEC, - TV_GET_VOLTAGE, - TV_GET_TONE, - TV_GET_PILOT, - TV_GET_ROLLOFF, +typedef enum dtv_cmd_types { + DTV_SEQ_UNDEFINED, + DTV_SEQ_START, + DTV_SEQ_CONTINUE, + DTV_SEQ_COMPLETE, + DTV_SEQ_TERMINATE, + + DTV_SET_FREQUENCY, + DTV_SET_MODULATION, + DTV_SET_BANDWIDTH, + DTV_SET_INVERSION, + DTV_SET_DISEQC_MASTER, + DTV_SET_SYMBOLRATE, + DTV_SET_INNERFEC, + DTV_SET_VOLTAGE, + DTV_SET_TONE, + DTV_SET_PILOT, + DTV_SET_ROLLOFF, + + DTV_GET_FREQUENCY, + DTV_GET_MODULATION, + DTV_GET_BANDWIDTH, + DTV_GET_INVERSION, + DTV_GET_DISEQC_SLAVE_REPLY, + DTV_GET_SYMBOLRATE, + DTV_GET_INNERFEC, + DTV_GET_VOLTAGE, + DTV_GET_TONE, + DTV_GET_PILOT, + DTV_GET_ROLLOFF, /* Basic enumeration set for querying unlimited capabilities */ - TV_GET_FE_CAPABILITY_COUNT, - TV_GET_FE_CAPABILITY, + DTV_GET_FE_CAPABILITY_COUNT, + DTV_GET_FE_CAPABILITY, /* New commands are always appended */ - TV_SET_DELIVERY_SYSTEM, - TV_GET_DELIVERY_SYSTEM, + DTV_SET_DELIVERY_SYSTEM, + DTV_GET_DELIVERY_SYSTEM, /* ISDB-T */ - TV_SET_ISDB_SEGMENT_NUM, - TV_GET_ISDB_SEGMENT_NUM, - TV_SET_ISDB_SEGMENT_WIDTH, - TV_GET_ISDB_SEGMENT_WIDTH, - TV_GET_ISDB_LAYERA_FEC, - TV_GET_ISDB_LAYERA_MODULATION, - TV_GET_ISDB_LAYERA_SEGMENT_WIDTH, - TV_GET_ISDB_LAYERB_FEC, - TV_GET_ISDB_LAYERB_MODULATION, - TV_GET_ISDB_LAYERB_SEGMENT_WIDTH, - TV_GET_ISDB_LAYERC_FEC, - TV_GET_ISDB_LAYERC_MODULATION, - TV_GET_ISDB_LAYERC_SEGMENT_WIDTH, - -} tv_cmd_types_t; + DTV_SET_ISDB_SEGMENT_NUM, + DTV_GET_ISDB_SEGMENT_NUM, + DTV_SET_ISDB_SEGMENT_WIDTH, + DTV_GET_ISDB_SEGMENT_WIDTH, + DTV_GET_ISDB_LAYERA_FEC, + DTV_GET_ISDB_LAYERA_MODULATION, + DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH, + DTV_GET_ISDB_LAYERB_FEC, + DTV_GET_ISDB_LAYERB_MODULATION, + DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH, + DTV_GET_ISDB_LAYERC_FEC, + DTV_GET_ISDB_LAYERC_MODULATION, + DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + +} dtv_cmd_types_t; typedef enum fe_pilot { PILOT_ON, @@ -337,7 +337,7 @@ typedef enum fe_delivery_system { SYS_DAB, } fe_delivery_system_t; -struct tv_cmds_h { +struct dtv_cmds_h { char *name; /* A display name for debugging purposes */ __u32 cmd; /* A unique ID */ @@ -357,13 +357,13 @@ typedef struct { __u32 len; } buffer; } u; -} tv_property_t; +} dtv_property_t; /* No more than 16 properties during any given ioctl */ -typedef tv_property_t tv_properties_t[16]; +typedef dtv_property_t dtv_properties_t[16]; -#define FE_SET_PROPERTY _IOW('o', 82, tv_properties_t) -#define FE_GET_PROPERTY _IOR('o', 83, tv_properties_t) +#define FE_SET_PROPERTY _IOW('o', 82, dtv_properties_t) +#define FE_GET_PROPERTY _IOR('o', 83, dtv_properties_t) /** -- GitLab From e7fee0f3aa111d42cdcfc1470cfdc21dde0cdbe2 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 11 Sep 2008 10:23:01 -0300 Subject: [PATCH 4109/5416] V4L/DVB (8996): S2API: typedefs replaced, _SEQ_'s removed, fixed 16 command arrays replaced After discussion the following changes were made: 1. Removed the typedefs in frontend.h, use structures. 2. In the frontend.h, remove the 16 command limit on the API and switch to a flexible variable length API. For practical reasons a #define limits this to 64, this should be discussed. 3. Changed dvb-core ioctl handing to deal with variable sequences of commands. tune-v0.0.3.c is required to use this API, it contains the interface changes. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 83 ++++++++++++----------- drivers/media/dvb/dvb-core/dvb_frontend.h | 4 +- drivers/media/dvb/frontends/cx24116.c | 2 +- include/linux/dvb/frontend.h | 27 +++++--- 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 9c4761506d2..763da968236 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -756,29 +756,14 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, } struct dtv_cmds_h dtv_cmds[] = { - [DTV_SEQ_UNDEFINED] = { - .name = "DTV_SEQ_UNDEFINED", - .cmd = DTV_SEQ_UNDEFINED, + [DTV_TUNE] = { + .name = "DTV_TUNE", + .cmd = DTV_TUNE, .set = 1, }, - [DTV_SEQ_START] = { - .name = "DTV_SEQ_START", - .cmd = DTV_SEQ_START, - .set = 1, - }, - [DTV_SEQ_CONTINUE] = { - .name = "DTV_SEQ_CONTINUE", - .cmd = DTV_SEQ_CONTINUE, - .set = 1, - }, - [DTV_SEQ_COMPLETE] = { - .name = "DTV_SEQ_COMPLETE", - .cmd = DTV_SEQ_COMPLETE, - .set = 1, - }, - [DTV_SEQ_TERMINATE] = { - .name = "DTV_SEQ_TERMINATE", - .cmd = DTV_SEQ_TERMINATE, + [DTV_CLEAR] = { + .name = "DTV_CLEAR", + .cmd = DTV_CLEAR, .set = 1, }, @@ -974,7 +959,7 @@ struct dtv_cmds_h dtv_cmds[] = { }, }; -void dtv_property_dump(dtv_property_t *tvp) +void dtv_property_dump(struct dtv_property *tvp) { int i; @@ -1044,6 +1029,7 @@ int dtv_property_cache_submit(struct dvb_frontend *fe) /* For legacy delivery systems we don't need the delivery_system to be specified */ if(is_legacy_delivery_system(c->delivery_system)) { + printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation); switch(c->modulation) { case QPSK: printk("%s() Preparing QPSK req\n", __FUNCTION__); @@ -1161,7 +1147,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, unsigned int cmd, void *parg); -int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, +int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, struct inode *inode, struct file *file) { int r = 0; @@ -1170,23 +1156,22 @@ int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, dtv_property_dump(tvp); switch(tvp->cmd) { - case DTV_SEQ_START: - case DTV_SEQ_TERMINATE: + case DTV_CLEAR: /* Reset a cache of data specific to the frontend here. This does * not effect hardware. */ printk("%s() Flushing property cache\n", __FUNCTION__); memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); - fe->dtv_property_cache.state = DTV_SEQ_START; + fe->dtv_property_cache.state = tvp->cmd; fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; break; - case DTV_SEQ_COMPLETE: + case DTV_TUNE: /* interpret the cache of data, build either a traditional frontend * tunerequest and submit it to a subset of the ioctl handler, * or, call a new undefined method on the frontend to deal with * all new tune requests. */ - fe->dtv_property_cache.state = DTV_SEQ_COMPLETE; + fe->dtv_property_cache.state = tvp->cmd; printk("%s() Finalised property cache\n", __FUNCTION__); r |= dtv_property_cache_submit(fe); r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, @@ -1344,30 +1329,48 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; int err = -EOPNOTSUPP; - dtv_property_t *tvp; + + struct dtv_properties *tvps = NULL; + struct dtv_property *tvp = NULL; + int i; dprintk("%s\n", __func__); if(cmd == FE_SET_PROPERTY) { printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); - /* TODO: basic property validation here */ + tvps = (struct dtv_properties __user *)parg; - /* TODO: ioctl userdata out of range check here */ - tvp = parg; - while(tvp->cmd != DTV_SEQ_UNDEFINED) { - dtv_property_process(fe, tvp, inode, file); - if( (tvp->cmd == DTV_SEQ_TERMINATE) || (tvp->cmd == DTV_SEQ_COMPLETE) ) - break; - tvp++; + printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num); + printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props); + + /* Put an arbitrary limit on the number of messages that can + * be sent at once */ + if (tvps->num > DTV_IOCTL_MAX_MSGS) + return -EINVAL; + + tvp = (struct dtv_property *) kmalloc(tvps->num * + sizeof(struct dtv_property), GFP_KERNEL); + if (!tvp) { + err = -ENOMEM; + goto out; } - if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { + if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { + err = -EFAULT; + goto out; + } + + for (i = 0; i < tvps->num; i++) + dtv_property_process(fe, tvp + i, inode, file); + + if(fe->dtv_property_cache.state == DTV_TUNE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); } err = 0; } - +out: + kfree(tvp); return err; } @@ -1545,7 +1548,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, case FE_SET_FRONTEND: { struct dvb_frontend_tune_settings fetunesettings; - if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { + if(fe->dtv_property_cache.state == DTV_TUNE) { if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { err = -EINVAL; break; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index f376f281cde..85d30201a69 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -170,8 +170,8 @@ struct dvb_frontend_ops { struct dvb_tuner_ops tuner_ops; struct analog_demod_ops analog_ops; - int (*set_property)(struct dvb_frontend* fe, dtv_property_t* tvp); - int (*get_property)(struct dvb_frontend* fe, dtv_property_t* tvp); + int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); + int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); int (*set_params)(struct dvb_frontend* fe); }; diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index f150fa24ff9..9f93930a259 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe) return cx24116_diseqc_init(fe); } -static int cx24116_set_property(struct dvb_frontend *fe, dtv_property_t* tvp) +static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) { dprintk("%s(..)\n", __func__); return 0; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index aeace74b536..f667bf377a7 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -251,11 +251,8 @@ struct dvb_frontend_event { * binary compatability. */ typedef enum dtv_cmd_types { - DTV_SEQ_UNDEFINED, - DTV_SEQ_START, - DTV_SEQ_CONTINUE, - DTV_SEQ_COMPLETE, - DTV_SEQ_TERMINATE, + DTV_TUNE, + DTV_CLEAR, DTV_SET_FREQUENCY, DTV_SET_MODULATION, @@ -348,22 +345,32 @@ struct dtv_cmds_h { __u32 reserved:30; /* Align */ }; -typedef struct { +struct dtv_property { __u32 cmd; + __u32 reserved[3]; union { + __s32 valuemin; + __s32 valuemax; __u32 data; struct { __u8 data[32]; __u32 len; + __u32 reserved1[3]; + void *reserved2; } buffer; } u; -} dtv_property_t; +} __attribute__ ((packed)); /* No more than 16 properties during any given ioctl */ -typedef dtv_property_t dtv_properties_t[16]; +struct dtv_properties { + __u32 num; + struct dtv_property *props; +}; + +#define DTV_IOCTL_MAX_MSGS 64 -#define FE_SET_PROPERTY _IOW('o', 82, dtv_properties_t) -#define FE_GET_PROPERTY _IOR('o', 83, dtv_properties_t) +#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties) +#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties) /** -- GitLab From 177b868d93861077619261dcecd0147d1c033026 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 11 Sep 2008 10:34:19 -0300 Subject: [PATCH 4110/5416] V4L/DVB (8997): S2API: Cleanup SYMBOLRATE, INNERFEC -> SYMBOL_RATE, INNER_FEC This is now consistent with the existing API. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 32 +++++++++++------------ include/linux/dvb/frontend.h | 8 +++--- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 763da968236..ce1de403e99 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -794,14 +794,14 @@ struct dtv_cmds_h dtv_cmds[] = { .set = 1, .buffer = 1, }, - [DTV_SET_SYMBOLRATE] = { - .name = "DTV_SET_SYMBOLRATE", - .cmd = DTV_SET_SYMBOLRATE, + [DTV_SET_SYMBOL_RATE] = { + .name = "DTV_SET_SYMBOL_RATE", + .cmd = DTV_SET_SYMBOL_RATE, .set = 1, }, - [DTV_SET_INNERFEC] = { - .name = "DTV_SET_INNERFEC", - .cmd = DTV_SET_INNERFEC, + [DTV_SET_INNER_FEC] = { + .name = "DTV_SET_INNER_FEC", + .cmd = DTV_SET_INNER_FEC, .set = 1, }, [DTV_SET_VOLTAGE] = { @@ -867,14 +867,14 @@ struct dtv_cmds_h dtv_cmds[] = { .set = 0, .buffer = 1, }, - [DTV_GET_SYMBOLRATE] = { - .name = "DTV_GET_SYMBOLRATE", - .cmd = DTV_GET_SYMBOLRATE, + [DTV_GET_SYMBOL_RATE] = { + .name = "DTV_GET_SYMBOL_RATE", + .cmd = DTV_GET_SYMBOL_RATE, .set = 0, }, - [DTV_GET_INNERFEC] = { - .name = "DTV_GET_INNERFEC", - .cmd = DTV_GET_INNERFEC, + [DTV_GET_INNER_FEC] = { + .name = "DTV_GET_INNER_FEC", + .cmd = DTV_GET_INNER_FEC, .set = 0, }, [DTV_GET_VOLTAGE] = { @@ -1201,16 +1201,16 @@ int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_GET_INVERSION: tvp->u.data = fe->dtv_property_cache.inversion; break; - case DTV_SET_SYMBOLRATE: + case DTV_SET_SYMBOL_RATE: fe->dtv_property_cache.symbol_rate = tvp->u.data; break; - case DTV_GET_SYMBOLRATE: + case DTV_GET_SYMBOL_RATE: tvp->u.data = fe->dtv_property_cache.symbol_rate; break; - case DTV_SET_INNERFEC: + case DTV_SET_INNER_FEC: fe->dtv_property_cache.fec_inner = tvp->u.data; break; - case DTV_GET_INNERFEC: + case DTV_GET_INNER_FEC: tvp->u.data = fe->dtv_property_cache.fec_inner; break; case DTV_SET_PILOT: diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index f667bf377a7..bfd670fa16b 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -259,8 +259,8 @@ typedef enum dtv_cmd_types { DTV_SET_BANDWIDTH, DTV_SET_INVERSION, DTV_SET_DISEQC_MASTER, - DTV_SET_SYMBOLRATE, - DTV_SET_INNERFEC, + DTV_SET_SYMBOL_RATE, + DTV_SET_INNER_FEC, DTV_SET_VOLTAGE, DTV_SET_TONE, DTV_SET_PILOT, @@ -271,8 +271,8 @@ typedef enum dtv_cmd_types { DTV_GET_BANDWIDTH, DTV_GET_INVERSION, DTV_GET_DISEQC_SLAVE_REPLY, - DTV_GET_SYMBOLRATE, - DTV_GET_INNERFEC, + DTV_GET_SYMBOL_RATE, + DTV_GET_INNER_FEC, DTV_GET_VOLTAGE, DTV_GET_TONE, DTV_GET_PILOT, -- GitLab From 65af619d84ee2d3a1faacbbeded374d0b313d3a9 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 11 Sep 2008 21:08:59 -0300 Subject: [PATCH 4111/5416] V4L/DVB (8998): s2api: restore DTV_UNDEFINED Signed-off-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/frontend.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index bfd670fa16b..915edd319f3 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -251,6 +251,7 @@ struct dvb_frontend_event { * binary compatability. */ typedef enum dtv_cmd_types { + DTV_UNDEFINED, DTV_TUNE, DTV_CLEAR, -- GitLab From ee33c525c4d09756156cd4c18e6586da900eb310 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 11 Sep 2008 23:52:32 -0300 Subject: [PATCH 4112/5416] V4L/DVB (8999): S2API: Reduce demod driver complexity by using a cache sync For demod drivers, we want a single tuning function (set_frontend) to have access to the properly constructed dvb_frontend_parameters structure, or the cache values - regardless of whether the legacy or new API is being used. This cuts down on redundant code in the demod drivers and ensures the tuning parameters are consistent regardless of the API entry type. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index ce1de403e99..7e9cd792131 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -993,6 +993,42 @@ int is_legacy_delivery_system(fe_delivery_system_t s) return 0; } +/* Synchronise the legacy tuning parameters into the cache, so that demodulator + * drivers can use a single set_frontend tuning function, regardless of whether + * it's being used for the legacy or new API, reducing code and complexity. + */ +void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + c->frequency = p->frequency; + c->inversion = p->inversion; + + switch (fe->ops.info.type) { + case FE_QPSK: + c->symbol_rate = p->u.qpsk.symbol_rate; + c->fec_inner = p->u.qpsk.fec_inner; + break; + case FE_QAM: + c->symbol_rate = p->u.qam.symbol_rate; + c->fec_inner = p->u.qam.fec_inner; + c->modulation = p->u.qam.modulation; + break; + case FE_OFDM: + c->bandwidth = p->u.ofdm.bandwidth; + c->code_rate_HP = p->u.ofdm.code_rate_HP; + c->code_rate_LP = p->u.ofdm.code_rate_LP; + c->modulation = p->u.ofdm.constellation; + c->transmission_mode = p->u.ofdm.transmission_mode; + c->guard_interval = p->u.ofdm.guard_interval; + c->hierarchy = p->u.ofdm.hierarchy_information; + break; + case FE_ATSC: + c->modulation = p->u.vsb.modulation; + break; + } +} + int dtv_property_cache_submit(struct dvb_frontend *fe) { @@ -1548,6 +1584,8 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, case FE_SET_FRONTEND: { struct dvb_frontend_tune_settings fetunesettings; + dtv_property_cache_sync(fe, &fepriv->parameters); + if(fe->dtv_property_cache.state == DTV_TUNE) { if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { err = -EINVAL; -- GitLab From d5748f1079c01c8861b05e0de7c4cda271532cb9 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Sep 2008 00:27:13 -0300 Subject: [PATCH 4113/5416] V4L/DVB (9000): S2API: Cleanup code that prepares tuning structures. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 219 +++++++++------------- 1 file changed, 91 insertions(+), 128 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 7e9cd792131..2aaaca62003 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1001,6 +1001,8 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame { struct dtv_frontend_properties *c = &fe->dtv_property_cache; + printk("%s()\n", __FUNCTION__); + c->frequency = p->frequency; c->inversion = p->inversion; @@ -1029,153 +1031,114 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame } } -int dtv_property_cache_submit(struct dvb_frontend *fe) +/* Ensure the cached values are set correctly in the frontend + * legacy tuning structures, for the advanced tuning API. + */ +void dtv_property_legacy_params_sync(struct dvb_frontend *fe) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dvb_frontend_parameters *p = &fepriv->parameters; - /* We have to do one of two things: - * To support legacy devices using the new API we take values from - * the tv_cache and generate a legacy truning structure. - * - * Or, - * - * To support advanced tuning devices with the new API we - * notify the new advance driver type that a tuning operation is required - * and let it pull values from the cache as is, we don't need to - * pass structures. - * - * We'll use the modulation type to assess how this is handled. as the API - * progresses we'll probably want to have a flag in dvb_frontend_ops - * to allow the frontend driver to dictate how it likes to be tuned. - * - * Because of how this is attached to the ioctl handler for legacy support, - * it's important to return an appropriate result code with atleast the following - * three meanings: - * < 0 = processing error - * 0 = lecagy ioctl handler to submit a traditional set_frontend() call. - * 1 = lecagy ioctl handler should NOT submit a traditional set_frontend() call. - */ + printk("%s()\n", __FUNCTION__); - int r; + p->frequency = c->frequency; + p->inversion = c->inversion; + switch (fe->ops.info.type) { + case FE_QPSK: + printk("%s() Preparing QPSK req\n", __FUNCTION__); + p->u.qpsk.symbol_rate = c->symbol_rate; + p->u.qpsk.fec_inner = c->fec_inner; + break; + case FE_QAM: + printk("%s() Preparing QAM req\n", __FUNCTION__); + p->u.qam.symbol_rate = c->symbol_rate; + p->u.qam.fec_inner = c->fec_inner; + p->u.qam.modulation = c->modulation; + break; + case FE_OFDM: + printk("%s() Preparing OFDM req\n", __FUNCTION__); + p->u.ofdm.bandwidth = c->bandwidth; + p->u.ofdm.code_rate_HP = c->code_rate_HP; + p->u.ofdm.code_rate_LP = c->code_rate_LP; + p->u.ofdm.constellation = c->modulation; + p->u.ofdm.transmission_mode = c->transmission_mode; + p->u.ofdm.guard_interval = c->guard_interval; + p->u.ofdm.hierarchy_information = c->hierarchy; + break; + case FE_ATSC: + printk("%s() Preparing VSB req\n", __FUNCTION__); + p->u.vsb.modulation = c->modulation; + break; + } +} + +/* Ensure the cached values are set correctly in the frontend + * legacy tuning structures, for the legacy tuning API. + */ +void dtv_property_adv_params_sync(struct dvb_frontend *fe) +{ struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; - struct dvb_frontend_parameters p; + struct dvb_frontend_parameters *p = &fepriv->parameters; printk("%s()\n", __FUNCTION__); - /* For legacy delivery systems we don't need the delivery_system to be specified */ - if(is_legacy_delivery_system(c->delivery_system)) { - printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation); - switch(c->modulation) { - case QPSK: - printk("%s() Preparing QPSK req\n", __FUNCTION__); - p.frequency = c->frequency; - p.inversion = c->inversion; - p.u.qpsk.symbol_rate = c->symbol_rate; - p.u.qpsk.fec_inner = c->fec_inner; - memcpy(&fepriv->parameters, &p, - sizeof (struct dvb_frontend_parameters)); + p->frequency = c->frequency; + p->inversion = c->inversion; - /* Call the traditional tuning mechanisms. */ + switch(c->modulation) { + case _8PSK: + case _16APSK: + case NBC_QPSK: + p->u.qpsk.symbol_rate = c->symbol_rate; + p->u.qpsk.fec_inner = c->fec_inner; + break; + default: + break; + } - r = 0; - break; - case QAM_16: - case QAM_32: - case QAM_64: - case QAM_128: - case QAM_256: - case QAM_AUTO: - printk("%s() Preparing QAM req\n", __FUNCTION__); - p.frequency = c->frequency; - p.inversion = c->inversion; - p.u.qam.symbol_rate = c->symbol_rate; - p.u.vsb.modulation = c->modulation; - printk("%s() frequency = %d\n", __FUNCTION__, p.frequency); - printk("%s() QAM = %d\n", __FUNCTION__, p.u.vsb.modulation); - memcpy(&fepriv->parameters, &p, - sizeof (struct dvb_frontend_parameters)); + if(c->delivery_system == SYS_ISDBT) { + /* Fake out a generic DVB-T request so we pass validation in the ioctl */ + p->frequency = c->frequency; + p->inversion = INVERSION_AUTO; + p->u.ofdm.constellation = QAM_AUTO; + p->u.ofdm.code_rate_HP = FEC_AUTO; + p->u.ofdm.code_rate_LP = FEC_AUTO; + p->u.ofdm.bandwidth = BANDWIDTH_AUTO; + p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; + } +} - /* At this point we're fully formed for backwards - * compatability and we need to return this - * via the ioctl handler as SET_FRONTEND (arg). - * We've already patched the new values into the - * frontends tuning structures so the ioctl code just - * continues as if a legacy tune structure was passed - * from userspace. - */ +void dtv_property_cache_submit(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - r = 0; - break; - case VSB_8: - case VSB_16: - printk("%s() Preparing VSB req\n", __FUNCTION__); - p.frequency = c->frequency; - p.u.vsb.modulation = c->modulation; - memcpy(&fepriv->parameters, &p, - sizeof (struct dvb_frontend_parameters)); + printk("%s()\n", __FUNCTION__); - /* Call the traditional tuning mechanisms. */ + /* For legacy delivery systems we don't need the delivery_system to + * be specified, but we populate the older structures from the cache + * so we can call set_frontend on older drivers. + */ + if(is_legacy_delivery_system(c->delivery_system)) { + + printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation); + dtv_property_legacy_params_sync(fe); - r = 0; - break; - /* TODO: Add any missing modulation types */ - default: - r = -1; - } } else { + printk("%s() adv, modulation = %d\n", __FUNCTION__, c->modulation); + /* For advanced delivery systems / modulation types ... * we seed the lecacy dvb_frontend_parameters structure * so that the sanity checking code later in the IOCTL processing * can validate our basic frequency ranges, symbolrates, modulation * etc. */ - r = -1; - - switch(c->modulation) { - case _8PSK: - case _16APSK: - case NBC_QPSK: - /* Just post a notification to the demod driver and let it pull - * the specific values it wants from its dtv_property_cache. - * It can decide how best to use those parameters. - * IOCTL will call set_frontend (by default) due to zigzag - * support etc. - */ - if (fe->ops.set_params) - r = fe->ops.set_params(fe); - - p.frequency = c->frequency; - p.inversion = c->inversion; - p.u.qpsk.symbol_rate = c->symbol_rate; - p.u.qpsk.fec_inner = c->fec_inner; - memcpy(&fepriv->parameters, &p, - sizeof (struct dvb_frontend_parameters)); - - r = 0; - break; - default: - r = -1; - } - - if(c->delivery_system == SYS_ISDBT) { - /* Fake out a generic DVB-T request so we pass validation in the ioctl */ - p.frequency = c->frequency; - p.inversion = INVERSION_AUTO; - p.u.ofdm.constellation = QAM_AUTO; - p.u.ofdm.code_rate_HP = FEC_AUTO; - p.u.ofdm.code_rate_LP = FEC_AUTO; - p.u.ofdm.bandwidth = BANDWIDTH_AUTO; - p.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; - p.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; - p.u.ofdm.hierarchy_information = HIERARCHY_AUTO; - memcpy(&fepriv->parameters, &p, - sizeof (struct dvb_frontend_parameters)); - - r = 0; - } + dtv_property_adv_params_sync(fe); } - return r; } static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, @@ -1203,13 +1166,13 @@ int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, break; case DTV_TUNE: /* interpret the cache of data, build either a traditional frontend - * tunerequest and submit it to a subset of the ioctl handler, - * or, call a new undefined method on the frontend to deal with - * all new tune requests. + * tunerequest so we can pass validation in the FE_SET_FRONTEND + * ioctl. */ fe->dtv_property_cache.state = tvp->cmd; printk("%s() Finalised property cache\n", __FUNCTION__); - r |= dtv_property_cache_submit(fe); + dtv_property_cache_submit(fe); + r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; -- GitLab From d7c1500183bc138b634377ed90c046e722b887d8 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Sep 2008 00:33:04 -0300 Subject: [PATCH 4114/5416] V4L/DVB (9001): S2API: ISDBT_SEGMENT_NUM -> ISDBT_SEGMENT_IDX Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 20 ++++++++++---------- drivers/media/dvb/dvb-core/dvb_frontend.h | 2 +- include/linux/dvb/frontend.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 2aaaca62003..dc76f9935c8 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -829,9 +829,9 @@ struct dtv_cmds_h dtv_cmds[] = { .cmd = DTV_SET_DELIVERY_SYSTEM, .set = 1, }, - [DTV_SET_ISDB_SEGMENT_NUM] = { - .name = "DTV_SET_ISDB_SEGMENT_NUM", - .cmd = DTV_SET_ISDB_SEGMENT_NUM, + [DTV_SET_ISDB_SEGMENT_IDX] = { + .name = "DTV_SET_ISDB_SEGMENT_IDX", + .cmd = DTV_SET_ISDB_SEGMENT_IDX, .set = 1, }, [DTV_SET_ISDB_SEGMENT_WIDTH] = { @@ -902,9 +902,9 @@ struct dtv_cmds_h dtv_cmds[] = { .cmd = DTV_GET_DELIVERY_SYSTEM, .set = 0, }, - [DTV_GET_ISDB_SEGMENT_NUM] = { - .name = "DTV_GET_ISDB_SEGMENT_NUM", - .cmd = DTV_GET_ISDB_SEGMENT_NUM, + [DTV_GET_ISDB_SEGMENT_IDX] = { + .name = "DTV_GET_ISDB_SEGMENT_IDX", + .cmd = DTV_GET_ISDB_SEGMENT_IDX, .set = 0, }, [DTV_GET_ISDB_SEGMENT_WIDTH] = { @@ -1232,11 +1232,11 @@ int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, break; /* ISDB-T Support here */ - case DTV_SET_ISDB_SEGMENT_NUM: - fe->dtv_property_cache.isdb_segment_num = tvp->u.data; + case DTV_SET_ISDB_SEGMENT_IDX: + fe->dtv_property_cache.isdb_segment_idx = tvp->u.data; break; - case DTV_GET_ISDB_SEGMENT_NUM: - tvp->u.data = fe->dtv_property_cache.isdb_segment_num; + case DTV_GET_ISDB_SEGMENT_IDX: + tvp->u.data = fe->dtv_property_cache.isdb_segment_idx; break; case DTV_SET_ISDB_SEGMENT_WIDTH: fe->dtv_property_cache.isdb_segment_width = tvp->u.data; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 85d30201a69..1c2090966ba 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -212,7 +212,7 @@ struct dtv_frontend_properties { fe_delivery_system_t delivery_system; /* ISDB-T specifics */ - u32 isdb_segment_num; + u32 isdb_segment_idx; u32 isdb_segment_width; fe_code_rate_t isdb_layera_fec; fe_modulation_t isdb_layera_modulation; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 915edd319f3..e4f211735ef 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -288,8 +288,8 @@ typedef enum dtv_cmd_types { DTV_GET_DELIVERY_SYSTEM, /* ISDB-T */ - DTV_SET_ISDB_SEGMENT_NUM, - DTV_GET_ISDB_SEGMENT_NUM, + DTV_SET_ISDB_SEGMENT_IDX, + DTV_GET_ISDB_SEGMENT_IDX, DTV_SET_ISDB_SEGMENT_WIDTH, DTV_GET_ISDB_SEGMENT_WIDTH, DTV_GET_ISDB_LAYERA_FEC, -- GitLab From 80a773c9bcc6f67944e186de3d2ab8b582889bc8 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Sep 2008 00:53:50 -0300 Subject: [PATCH 4115/5416] V4L/DVB (9002): S2API: Ensure cache->delivery_system is set at all times. This helps complex demods which support different modulation types be better informed. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index dc76f9935c8..205f60262c3 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1010,11 +1010,13 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame case FE_QPSK: c->symbol_rate = p->u.qpsk.symbol_rate; c->fec_inner = p->u.qpsk.fec_inner; + c->delivery_system = SYS_DVBS; break; case FE_QAM: c->symbol_rate = p->u.qam.symbol_rate; c->fec_inner = p->u.qam.fec_inner; c->modulation = p->u.qam.modulation; + c->delivery_system = SYS_DVBC_ANNEX_AC; break; case FE_OFDM: c->bandwidth = p->u.ofdm.bandwidth; @@ -1024,9 +1026,14 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame c->transmission_mode = p->u.ofdm.transmission_mode; c->guard_interval = p->u.ofdm.guard_interval; c->hierarchy = p->u.ofdm.hierarchy_information; + c->delivery_system = SYS_DVBT; break; case FE_ATSC: c->modulation = p->u.vsb.modulation; + if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) + c->delivery_system = SYS_ATSC; + else + c->delivery_system = SYS_DVBC_ANNEX_B; break; } } @@ -1050,12 +1057,14 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe) printk("%s() Preparing QPSK req\n", __FUNCTION__); p->u.qpsk.symbol_rate = c->symbol_rate; p->u.qpsk.fec_inner = c->fec_inner; + c->delivery_system = SYS_DVBS; break; case FE_QAM: printk("%s() Preparing QAM req\n", __FUNCTION__); p->u.qam.symbol_rate = c->symbol_rate; p->u.qam.fec_inner = c->fec_inner; p->u.qam.modulation = c->modulation; + c->delivery_system = SYS_DVBC_ANNEX_AC; break; case FE_OFDM: printk("%s() Preparing OFDM req\n", __FUNCTION__); @@ -1066,10 +1075,15 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe) p->u.ofdm.transmission_mode = c->transmission_mode; p->u.ofdm.guard_interval = c->guard_interval; p->u.ofdm.hierarchy_information = c->hierarchy; + c->delivery_system = SYS_DVBT; break; case FE_ATSC: printk("%s() Preparing VSB req\n", __FUNCTION__); p->u.vsb.modulation = c->modulation; + if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) + c->delivery_system = SYS_ATSC; + else + c->delivery_system = SYS_DVBC_ANNEX_B; break; } } -- GitLab From 363429a089590f3f4071ebc492b3712fdcba770b Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Sep 2008 01:34:28 -0300 Subject: [PATCH 4116/5416] V4L/DVB (9003): S2API: Remove the DTV_SET_ and DTV_GET_ prefixes The API now assumes that ioctl calls for FE_SET_PROPERTY and all set commands, and FE_GET_PROPERTY are get commands. Simplification. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 431 +++++++++++----------- include/linux/dvb/frontend.h | 67 ++-- 2 files changed, 239 insertions(+), 259 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 205f60262c3..2ed748486e5 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -768,193 +768,128 @@ struct dtv_cmds_h dtv_cmds[] = { }, /* Set */ - [DTV_SET_FREQUENCY] = { - .name = "DTV_SET_FREQUENCY", - .cmd = DTV_SET_FREQUENCY, + [DTV_FREQUENCY] = { + .name = "DTV_FREQUENCY", + .cmd = DTV_FREQUENCY, .set = 1, }, - [DTV_SET_BANDWIDTH] = { - .name = "DTV_SET_BANDWIDTH", - .cmd = DTV_SET_BANDWIDTH, + [DTV_BANDWIDTH] = { + .name = "DTV_BANDWIDTH", + .cmd = DTV_BANDWIDTH, .set = 1, }, - [DTV_SET_MODULATION] = { - .name = "DTV_SET_MODULATION", - .cmd = DTV_SET_MODULATION, + [DTV_MODULATION] = { + .name = "DTV_MODULATION", + .cmd = DTV_MODULATION, .set = 1, }, - [DTV_SET_INVERSION] = { - .name = "DTV_SET_INVERSION", - .cmd = DTV_SET_INVERSION, + [DTV_INVERSION] = { + .name = "DTV_INVERSION", + .cmd = DTV_INVERSION, .set = 1, }, - [DTV_SET_DISEQC_MASTER] = { - .name = "DTV_SET_DISEQC_MASTER", - .cmd = DTV_SET_DISEQC_MASTER, + [DTV_DISEQC_MASTER] = { + .name = "DTV_DISEQC_MASTER", + .cmd = DTV_DISEQC_MASTER, .set = 1, .buffer = 1, }, - [DTV_SET_SYMBOL_RATE] = { - .name = "DTV_SET_SYMBOL_RATE", - .cmd = DTV_SET_SYMBOL_RATE, + [DTV_SYMBOL_RATE] = { + .name = "DTV_SYMBOL_RATE", + .cmd = DTV_SYMBOL_RATE, .set = 1, }, - [DTV_SET_INNER_FEC] = { - .name = "DTV_SET_INNER_FEC", - .cmd = DTV_SET_INNER_FEC, + [DTV_INNER_FEC] = { + .name = "DTV_INNER_FEC", + .cmd = DTV_INNER_FEC, .set = 1, }, - [DTV_SET_VOLTAGE] = { - .name = "DTV_SET_VOLTAGE", - .cmd = DTV_SET_VOLTAGE, + [DTV_VOLTAGE] = { + .name = "DTV_VOLTAGE", + .cmd = DTV_VOLTAGE, .set = 1, }, - [DTV_SET_TONE] = { - .name = "DTV_SET_TONE", - .cmd = DTV_SET_TONE, + [DTV_TONE] = { + .name = "DTV_TONE", + .cmd = DTV_TONE, .set = 1, }, - [DTV_SET_PILOT] = { - .name = "DTV_SET_PILOT", - .cmd = DTV_SET_PILOT, + [DTV_PILOT] = { + .name = "DTV_PILOT", + .cmd = DTV_PILOT, .set = 1, }, - [DTV_SET_ROLLOFF] = { - .name = "DTV_SET_ROLLOFF", - .cmd = DTV_SET_ROLLOFF, + [DTV_ROLLOFF] = { + .name = "DTV_ROLLOFF", + .cmd = DTV_ROLLOFF, .set = 1, }, - [DTV_SET_DELIVERY_SYSTEM] = { - .name = "DTV_SET_DELIVERY_SYSTEM", - .cmd = DTV_SET_DELIVERY_SYSTEM, + [DTV_DELIVERY_SYSTEM] = { + .name = "DTV_DELIVERY_SYSTEM", + .cmd = DTV_DELIVERY_SYSTEM, .set = 1, }, - [DTV_SET_ISDB_SEGMENT_IDX] = { - .name = "DTV_SET_ISDB_SEGMENT_IDX", - .cmd = DTV_SET_ISDB_SEGMENT_IDX, + [DTV_ISDB_SEGMENT_IDX] = { + .name = "DTV_ISDB_SEGMENT_IDX", + .cmd = DTV_ISDB_SEGMENT_IDX, .set = 1, }, - [DTV_SET_ISDB_SEGMENT_WIDTH] = { - .name = "DTV_SET_ISDB_SEGMENT_WIDTH", - .cmd = DTV_SET_ISDB_SEGMENT_WIDTH, + [DTV_ISDB_SEGMENT_WIDTH] = { + .name = "DTV_ISDB_SEGMENT_WIDTH", + .cmd = DTV_ISDB_SEGMENT_WIDTH, .set = 1, }, /* Get */ - [DTV_GET_FREQUENCY] = { - .name = "DTV_GET_FREQUENCY", - .cmd = DTV_GET_FREQUENCY, - .set = 0, - }, - [DTV_GET_BANDWIDTH] = { - .name = "DTV_GET_BANDWIDTH", - .cmd = DTV_GET_BANDWIDTH, - .set = 0, - }, - [DTV_GET_MODULATION] = { - .name = "DTV_GET_MODULATION", - .cmd = DTV_GET_MODULATION, - .set = 0, - }, - [DTV_GET_INVERSION] = { - .name = "DTV_GET_INVERSION", - .cmd = DTV_GET_INVERSION, - .set = 0, - }, - [DTV_GET_DISEQC_SLAVE_REPLY] = { - .name = "DTV_GET_DISEQC_SLAVE_REPLY", - .cmd = DTV_GET_DISEQC_SLAVE_REPLY, + [DTV_DISEQC_SLAVE_REPLY] = { + .name = "DTV_DISEQC_SLAVE_REPLY", + .cmd = DTV_DISEQC_SLAVE_REPLY, .set = 0, .buffer = 1, }, - [DTV_GET_SYMBOL_RATE] = { - .name = "DTV_GET_SYMBOL_RATE", - .cmd = DTV_GET_SYMBOL_RATE, - .set = 0, - }, - [DTV_GET_INNER_FEC] = { - .name = "DTV_GET_INNER_FEC", - .cmd = DTV_GET_INNER_FEC, - .set = 0, - }, - [DTV_GET_VOLTAGE] = { - .name = "DTV_GET_VOLTAGE", - .cmd = DTV_GET_VOLTAGE, - .set = 0, - }, - [DTV_GET_TONE] = { - .name = "DTV_GET_TONE", - .cmd = DTV_GET_TONE, - .set = 0, - }, - [DTV_GET_PILOT] = { - .name = "DTV_GET_PILOT", - .cmd = DTV_GET_PILOT, - .set = 0, - }, - [DTV_GET_ROLLOFF] = { - .name = "DTV_GET_ROLLOFF", - .cmd = DTV_GET_ROLLOFF, - .set = 0, - }, - [DTV_GET_DELIVERY_SYSTEM] = { - .name = "DTV_GET_DELIVERY_SYSTEM", - .cmd = DTV_GET_DELIVERY_SYSTEM, - .set = 0, - }, - [DTV_GET_ISDB_SEGMENT_IDX] = { - .name = "DTV_GET_ISDB_SEGMENT_IDX", - .cmd = DTV_GET_ISDB_SEGMENT_IDX, - .set = 0, - }, - [DTV_GET_ISDB_SEGMENT_WIDTH] = { - .name = "DTV_GET_ISDB_SEGMENT_WIDTH", - .cmd = DTV_GET_ISDB_SEGMENT_WIDTH, + [DTV_ISDB_LAYERA_FEC] = { + .name = "DTV_ISDB_LAYERA_FEC", + .cmd = DTV_ISDB_LAYERA_FEC, .set = 0, }, - [DTV_GET_ISDB_LAYERA_FEC] = { - .name = "DTV_GET_ISDB_LAYERA_FEC", - .cmd = DTV_GET_ISDB_LAYERA_FEC, + [DTV_ISDB_LAYERA_MODULATION] = { + .name = "DTV_ISDB_LAYERA_MODULATION", + .cmd = DTV_ISDB_LAYERA_MODULATION, .set = 0, }, - [DTV_GET_ISDB_LAYERA_MODULATION] = { - .name = "DTV_GET_ISDB_LAYERA_MODULATION", - .cmd = DTV_GET_ISDB_LAYERA_MODULATION, + [DTV_ISDB_LAYERA_SEGMENT_WIDTH] = { + .name = "DTV_ISDB_LAYERA_SEGMENT_WIDTH", + .cmd = DTV_ISDB_LAYERA_SEGMENT_WIDTH, .set = 0, }, - [DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH] = { - .name = "DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH", - .cmd = DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH, + [DTV_ISDB_LAYERB_FEC] = { + .name = "DTV_ISDB_LAYERB_FEC", + .cmd = DTV_ISDB_LAYERB_FEC, .set = 0, }, - [DTV_GET_ISDB_LAYERB_FEC] = { - .name = "DTV_GET_ISDB_LAYERB_FEC", - .cmd = DTV_GET_ISDB_LAYERB_FEC, + [DTV_ISDB_LAYERB_MODULATION] = { + .name = "DTV_ISDB_LAYERB_MODULATION", + .cmd = DTV_ISDB_LAYERB_MODULATION, .set = 0, }, - [DTV_GET_ISDB_LAYERB_MODULATION] = { - .name = "DTV_GET_ISDB_LAYERB_MODULATION", - .cmd = DTV_GET_ISDB_LAYERB_MODULATION, + [DTV_ISDB_LAYERB_SEGMENT_WIDTH] = { + .name = "DTV_ISDB_LAYERB_SEGMENT_WIDTH", + .cmd = DTV_ISDB_LAYERB_SEGMENT_WIDTH, .set = 0, }, - [DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH] = { - .name = "DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH", - .cmd = DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH, + [DTV_ISDB_LAYERC_FEC] = { + .name = "DTV_ISDB_LAYERC_FEC", + .cmd = DTV_ISDB_LAYERC_FEC, .set = 0, }, - [DTV_GET_ISDB_LAYERC_FEC] = { - .name = "DTV_GET_ISDB_LAYERC_FEC", - .cmd = DTV_GET_ISDB_LAYERC_FEC, + [DTV_ISDB_LAYERC_MODULATION] = { + .name = "DTV_ISDB_LAYERC_MODULATION", + .cmd = DTV_ISDB_LAYERC_MODULATION, .set = 0, }, - [DTV_GET_ISDB_LAYERC_MODULATION] = { - .name = "DTV_GET_ISDB_LAYERC_MODULATION", - .cmd = DTV_GET_ISDB_LAYERC_MODULATION, - .set = 0, - }, - [DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH] = { - .name = "DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH", - .cmd = DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + [DTV_ISDB_LAYERC_SEGMENT_WIDTH] = { + .name = "DTV_ISDB_LAYERC_SEGMENT_WIDTH", + .cmd = DTV_ISDB_LAYERC_SEGMENT_WIDTH, .set = 0, }, }; @@ -1160,7 +1095,92 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, unsigned int cmd, void *parg); -int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, +int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, + struct inode *inode, struct file *file) +{ + int r = 0; + + printk("%s()\n", __FUNCTION__); + + dtv_property_dump(tvp); + + switch(tvp->cmd) { + case DTV_FREQUENCY: + tvp->u.data = fe->dtv_property_cache.frequency; + break; + case DTV_MODULATION: + tvp->u.data = fe->dtv_property_cache.modulation; + break; + case DTV_BANDWIDTH: + tvp->u.data = fe->dtv_property_cache.bandwidth; + break; + case DTV_INVERSION: + tvp->u.data = fe->dtv_property_cache.inversion; + break; + case DTV_SYMBOL_RATE: + tvp->u.data = fe->dtv_property_cache.symbol_rate; + break; + case DTV_INNER_FEC: + tvp->u.data = fe->dtv_property_cache.fec_inner; + break; + case DTV_PILOT: + tvp->u.data = fe->dtv_property_cache.pilot; + break; + case DTV_ROLLOFF: + tvp->u.data = fe->dtv_property_cache.rolloff; + break; + case DTV_DELIVERY_SYSTEM: + tvp->u.data = fe->dtv_property_cache.delivery_system; + break; + + /* ISDB-T Support here */ + case DTV_ISDB_SEGMENT_IDX: + tvp->u.data = fe->dtv_property_cache.isdb_segment_idx; + break; + case DTV_ISDB_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_segment_width; + break; + case DTV_ISDB_LAYERA_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layera_fec; + break; + case DTV_ISDB_LAYERA_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layera_modulation; + break; + case DTV_ISDB_LAYERA_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layera_segment_width; + break; + case DTV_ISDB_LAYERB_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_fec; + break; + case DTV_ISDB_LAYERB_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_modulation; + break; + case DTV_ISDB_LAYERB_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layerb_segment_width; + break; + case DTV_ISDB_LAYERC_FEC: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_fec; + break; + case DTV_ISDB_LAYERC_MODULATION: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_modulation; + break; + case DTV_ISDB_LAYERC_SEGMENT_WIDTH: + tvp->u.data = fe->dtv_property_cache.isdb_layerc_segment_width; + break; + case DTV_VOLTAGE: + tvp->u.data = fe->dtv_property_cache.voltage; + break; + case DTV_TONE: + tvp->u.data = fe->dtv_property_cache.sectone; + break; + default: + r = -1; + } + + return r; +} + +int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp, struct inode *inode, struct file *file) { int r = 0; @@ -1190,117 +1210,53 @@ int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; - case DTV_SET_FREQUENCY: + case DTV_FREQUENCY: fe->dtv_property_cache.frequency = tvp->u.data; break; - case DTV_GET_FREQUENCY: - tvp->u.data = fe->dtv_property_cache.frequency; - break; - case DTV_SET_MODULATION: + case DTV_MODULATION: fe->dtv_property_cache.modulation = tvp->u.data; break; - case DTV_GET_MODULATION: - tvp->u.data = fe->dtv_property_cache.modulation; - break; - case DTV_SET_BANDWIDTH: + case DTV_BANDWIDTH: fe->dtv_property_cache.bandwidth = tvp->u.data; break; - case DTV_GET_BANDWIDTH: - tvp->u.data = fe->dtv_property_cache.bandwidth; - break; - case DTV_SET_INVERSION: + case DTV_INVERSION: fe->dtv_property_cache.inversion = tvp->u.data; break; - case DTV_GET_INVERSION: - tvp->u.data = fe->dtv_property_cache.inversion; - break; - case DTV_SET_SYMBOL_RATE: + case DTV_SYMBOL_RATE: fe->dtv_property_cache.symbol_rate = tvp->u.data; break; - case DTV_GET_SYMBOL_RATE: - tvp->u.data = fe->dtv_property_cache.symbol_rate; - break; - case DTV_SET_INNER_FEC: + case DTV_INNER_FEC: fe->dtv_property_cache.fec_inner = tvp->u.data; break; - case DTV_GET_INNER_FEC: - tvp->u.data = fe->dtv_property_cache.fec_inner; - break; - case DTV_SET_PILOT: + case DTV_PILOT: fe->dtv_property_cache.pilot = tvp->u.data; break; - case DTV_GET_PILOT: - tvp->u.data = fe->dtv_property_cache.pilot; - break; - case DTV_SET_ROLLOFF: + case DTV_ROLLOFF: fe->dtv_property_cache.rolloff = tvp->u.data; break; - case DTV_GET_ROLLOFF: - tvp->u.data = fe->dtv_property_cache.rolloff; - break; - case DTV_SET_DELIVERY_SYSTEM: + case DTV_DELIVERY_SYSTEM: fe->dtv_property_cache.delivery_system = tvp->u.data; break; - case DTV_GET_DELIVERY_SYSTEM: - tvp->u.data = fe->dtv_property_cache.delivery_system; - break; /* ISDB-T Support here */ - case DTV_SET_ISDB_SEGMENT_IDX: + case DTV_ISDB_SEGMENT_IDX: fe->dtv_property_cache.isdb_segment_idx = tvp->u.data; break; - case DTV_GET_ISDB_SEGMENT_IDX: - tvp->u.data = fe->dtv_property_cache.isdb_segment_idx; - break; - case DTV_SET_ISDB_SEGMENT_WIDTH: + case DTV_ISDB_SEGMENT_WIDTH: fe->dtv_property_cache.isdb_segment_width = tvp->u.data; break; - case DTV_GET_ISDB_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_segment_width; - break; - case DTV_GET_ISDB_LAYERA_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layera_fec; - break; - case DTV_GET_ISDB_LAYERA_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layera_modulation; - break; - case DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layera_segment_width; - break; - case DTV_GET_ISDB_LAYERB_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_fec; - break; - case DTV_GET_ISDB_LAYERB_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_modulation; - break; - case DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_segment_width; - break; - case DTV_GET_ISDB_LAYERC_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_fec; - break; - case DTV_GET_ISDB_LAYERC_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_modulation; - break; - case DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_segment_width; - break; - case DTV_SET_VOLTAGE: + case DTV_VOLTAGE: fe->dtv_property_cache.voltage = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, (void *)fe->dtv_property_cache.voltage); break; - case DTV_GET_VOLTAGE: - tvp->u.data = fe->dtv_property_cache.voltage; - break; - case DTV_SET_TONE: + case DTV_TONE: fe->dtv_property_cache.sectone = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE, (void *)fe->dtv_property_cache.sectone); break; - case DTV_GET_TONE: - tvp->u.data = fe->dtv_property_cache.sectone; - break; + default: + r = -1; } return r; @@ -1375,13 +1331,50 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, } for (i = 0; i < tvps->num; i++) - dtv_property_process(fe, tvp + i, inode, file); + dtv_property_process_set(fe, tvp + i, inode, file); if(fe->dtv_property_cache.state == DTV_TUNE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); } err = 0; - } + } else + if(cmd == FE_GET_PROPERTY) { + printk("%s() FE_GET_PROPERTY\n", __FUNCTION__); + + tvps = (struct dtv_properties __user *)parg; + + printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num); + printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props); + + /* Put an arbitrary limit on the number of messages that can + * be sent at once */ + if (tvps->num > DTV_IOCTL_MAX_MSGS) + return -EINVAL; + + tvp = (struct dtv_property *) kmalloc(tvps->num * + sizeof(struct dtv_property), GFP_KERNEL); + if (!tvp) { + err = -ENOMEM; + goto out; + } + + if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { + err = -EFAULT; + goto out; + } + + for (i = 0; i < tvps->num; i++) + dtv_property_process_get(fe, tvp + i, inode, file); + + if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { + err = -EFAULT; + goto out; + } + + err = 0; + } else + err = -EOPNOTSUPP; + out: kfree(tvp); return err; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index e4f211735ef..05bdec9bc5a 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -255,52 +255,39 @@ typedef enum dtv_cmd_types { DTV_TUNE, DTV_CLEAR, - DTV_SET_FREQUENCY, - DTV_SET_MODULATION, - DTV_SET_BANDWIDTH, - DTV_SET_INVERSION, - DTV_SET_DISEQC_MASTER, - DTV_SET_SYMBOL_RATE, - DTV_SET_INNER_FEC, - DTV_SET_VOLTAGE, - DTV_SET_TONE, - DTV_SET_PILOT, - DTV_SET_ROLLOFF, - - DTV_GET_FREQUENCY, - DTV_GET_MODULATION, - DTV_GET_BANDWIDTH, - DTV_GET_INVERSION, - DTV_GET_DISEQC_SLAVE_REPLY, - DTV_GET_SYMBOL_RATE, - DTV_GET_INNER_FEC, - DTV_GET_VOLTAGE, - DTV_GET_TONE, - DTV_GET_PILOT, - DTV_GET_ROLLOFF, + DTV_FREQUENCY, + DTV_MODULATION, + DTV_BANDWIDTH, + DTV_INVERSION, + DTV_DISEQC_MASTER, + DTV_SYMBOL_RATE, + DTV_INNER_FEC, + DTV_VOLTAGE, + DTV_TONE, + DTV_PILOT, + DTV_ROLLOFF, + + DTV_DISEQC_SLAVE_REPLY, /* Basic enumeration set for querying unlimited capabilities */ - DTV_GET_FE_CAPABILITY_COUNT, - DTV_GET_FE_CAPABILITY, + DTV_FE_CAPABILITY_COUNT, + DTV_FE_CAPABILITY, /* New commands are always appended */ - DTV_SET_DELIVERY_SYSTEM, - DTV_GET_DELIVERY_SYSTEM, + DTV_DELIVERY_SYSTEM, /* ISDB-T */ - DTV_SET_ISDB_SEGMENT_IDX, - DTV_GET_ISDB_SEGMENT_IDX, - DTV_SET_ISDB_SEGMENT_WIDTH, - DTV_GET_ISDB_SEGMENT_WIDTH, - DTV_GET_ISDB_LAYERA_FEC, - DTV_GET_ISDB_LAYERA_MODULATION, - DTV_GET_ISDB_LAYERA_SEGMENT_WIDTH, - DTV_GET_ISDB_LAYERB_FEC, - DTV_GET_ISDB_LAYERB_MODULATION, - DTV_GET_ISDB_LAYERB_SEGMENT_WIDTH, - DTV_GET_ISDB_LAYERC_FEC, - DTV_GET_ISDB_LAYERC_MODULATION, - DTV_GET_ISDB_LAYERC_SEGMENT_WIDTH, + DTV_ISDB_SEGMENT_IDX, + DTV_ISDB_SEGMENT_WIDTH, + DTV_ISDB_LAYERA_FEC, + DTV_ISDB_LAYERA_MODULATION, + DTV_ISDB_LAYERA_SEGMENT_WIDTH, + DTV_ISDB_LAYERB_FEC, + DTV_ISDB_LAYERB_MODULATION, + DTV_ISDB_LAYERB_SEGMENT_WIDTH, + DTV_ISDB_LAYERC_FEC, + DTV_ISDB_LAYERC_MODULATION, + DTV_ISDB_LAYERC_SEGMENT_WIDTH, } dtv_cmd_types_t; -- GitLab From bfbf2dae30ed75bceccc6a88d2d9368694d6bf40 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Sep 2008 01:37:37 -0300 Subject: [PATCH 4117/5416] V4L/DVB (9004): S2API: Implement GET/SET handing to the demods The frontends will be notified (if they chose) of all _get and _set commands so they can help determine result or action. Results are now returned to userspace correctly. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 21 +++++++++++++++++---- drivers/media/dvb/dvb-core/dvb_frontend.h | 1 - drivers/media/dvb/frontends/cx24116.c | 6 +++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 2ed748486e5..8bc3c0842b3 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1104,6 +1104,13 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, dtv_property_dump(tvp); + /* Allow the frontend to validate incoming properties */ + if (fe->ops.get_property) + r = fe->ops.get_property(fe, tvp); + + if (r < 0) + return r; + switch(tvp->cmd) { case DTV_FREQUENCY: tvp->u.data = fe->dtv_property_cache.frequency; @@ -1188,6 +1195,13 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp, printk("%s()\n", __FUNCTION__); dtv_property_dump(tvp); + /* Allow the frontend to validate incoming properties */ + if (fe->ops.set_property) + r = fe->ops.set_property(fe, tvp); + + if (r < 0) + return r; + switch(tvp->cmd) { case DTV_CLEAR: /* Reset a cache of data specific to the frontend here. This does @@ -1331,12 +1345,12 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, } for (i = 0; i < tvps->num; i++) - dtv_property_process_set(fe, tvp + i, inode, file); + err |= dtv_property_process_set(fe, tvp + i, inode, file); if(fe->dtv_property_cache.state == DTV_TUNE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); } - err = 0; + } else if(cmd == FE_GET_PROPERTY) { printk("%s() FE_GET_PROPERTY\n", __FUNCTION__); @@ -1364,14 +1378,13 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, } for (i = 0; i < tvps->num; i++) - dtv_property_process_get(fe, tvp + i, inode, file); + err |= dtv_property_process_get(fe, tvp + i, inode, file); if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { err = -EFAULT; goto out; } - err = 0; } else err = -EOPNOTSUPP; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 1c2090966ba..784e8fe1d3b 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -172,7 +172,6 @@ struct dvb_frontend_ops { int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); - int (*set_params)(struct dvb_frontend* fe); }; #define MAX_EVENT 8 diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 9f93930a259..0ac2c549308 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -802,9 +802,9 @@ static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tv return 0; } -static int cx24116_set_params(struct dvb_frontend *fe) +static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp) { - dprintk("%s(..) We were notified that a tune request may occur\n", __func__); + dprintk("%s(..)\n", __func__); return 0; } @@ -964,7 +964,7 @@ static struct dvb_frontend_ops cx24116_ops = { .diseqc_send_burst = cx24116_diseqc_send_burst, .set_property = cx24116_set_property, - .set_params = cx24116_set_params, + .get_property = cx24116_get_property, .set_frontend = cx24116_set_frontend, }; -- GitLab From e6f9ec86575358309cf9d4b2643df2f3b1f6f9fa Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 12 Sep 2008 14:49:06 -0300 Subject: [PATCH 4118/5416] V4L/DVB (9005): Bug fix: ioctl FE_SET_PROPERTY/FE_GET_PROPERTY always return error Bug fix: ioctl FE_SET_PROPERTY/FE_GET_PROPERTY always return error Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 8bc3c0842b3..161ebcf9258 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1311,7 +1311,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; - int err = -EOPNOTSUPP; + int err = 0; struct dtv_properties *tvps = NULL; struct dtv_property *tvp = NULL; -- GitLab From 4dd88bec368a6e4caa86a511f7adbc4c08992c5c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 13 Sep 2008 15:09:07 -0300 Subject: [PATCH 4119/5416] V4L/DVB (9006): S2API: Allow reliable use of old and new api on the same frontend, regardless. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 161ebcf9258..6b914f9a03c 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1299,8 +1299,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) err = dvb_frontend_ioctl_properties(inode, file, cmd, parg); - else + else { + fe->dtv_property_cache.state = DTV_UNDEFINED; err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg); + } up(&fepriv->sem); return err; @@ -1567,8 +1569,6 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, case FE_SET_FRONTEND: { struct dvb_frontend_tune_settings fetunesettings; - dtv_property_cache_sync(fe, &fepriv->parameters); - if(fe->dtv_property_cache.state == DTV_TUNE) { if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { err = -EINVAL; @@ -1580,6 +1580,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, break; } + dtv_property_cache_sync(fe, &fepriv->parameters); memcpy (&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters)); } -- GitLab From 75b7f9437b1cf63750bb58efaaeb6d72d04b3c7f Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 13 Sep 2008 16:56:34 -0300 Subject: [PATCH 4120/5416] V4L/DVB (9007): S2API: Changed bandwidth to be expressed in HZ Also added some compat code for the older API. Added more ISDB message/command suggestions, current not connected in dvb-core. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 33 ++++++++++++++++------- drivers/media/dvb/dvb-core/dvb_frontend.h | 2 +- include/linux/dvb/frontend.h | 27 ++++++++++++++++--- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 6b914f9a03c..7dffb48e55e 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -773,9 +773,9 @@ struct dtv_cmds_h dtv_cmds[] = { .cmd = DTV_FREQUENCY, .set = 1, }, - [DTV_BANDWIDTH] = { - .name = "DTV_BANDWIDTH", - .cmd = DTV_BANDWIDTH, + [DTV_BANDWIDTH_HZ] = { + .name = "DTV_BANDWIDTH_HZ", + .cmd = DTV_BANDWIDTH_HZ, .set = 1, }, [DTV_MODULATION] = { @@ -954,7 +954,15 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame c->delivery_system = SYS_DVBC_ANNEX_AC; break; case FE_OFDM: - c->bandwidth = p->u.ofdm.bandwidth; + if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) + c->bandwidth_hz = 6000000; + else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) + c->bandwidth_hz = 7000000; + else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) + c->bandwidth_hz = 8000000; + else + /* Including BANDWIDTH_AUTO */ + c->bandwidth_hz = 0; c->code_rate_HP = p->u.ofdm.code_rate_HP; c->code_rate_LP = p->u.ofdm.code_rate_LP; c->modulation = p->u.ofdm.constellation; @@ -1003,7 +1011,14 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe) break; case FE_OFDM: printk("%s() Preparing OFDM req\n", __FUNCTION__); - p->u.ofdm.bandwidth = c->bandwidth; + if (c->bandwidth_hz == 6000000) + p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + else if (c->bandwidth_hz == 7000000) + p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + else if (c->bandwidth_hz == 8000000) + p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + else + p->u.ofdm.bandwidth = BANDWIDTH_AUTO; p->u.ofdm.code_rate_HP = c->code_rate_HP; p->u.ofdm.code_rate_LP = c->code_rate_LP; p->u.ofdm.constellation = c->modulation; @@ -1118,8 +1133,8 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_MODULATION: tvp->u.data = fe->dtv_property_cache.modulation; break; - case DTV_BANDWIDTH: - tvp->u.data = fe->dtv_property_cache.bandwidth; + case DTV_BANDWIDTH_HZ: + tvp->u.data = fe->dtv_property_cache.bandwidth_hz; break; case DTV_INVERSION: tvp->u.data = fe->dtv_property_cache.inversion; @@ -1230,8 +1245,8 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_MODULATION: fe->dtv_property_cache.modulation = tvp->u.data; break; - case DTV_BANDWIDTH: - fe->dtv_property_cache.bandwidth = tvp->u.data; + case DTV_BANDWIDTH_HZ: + fe->dtv_property_cache.bandwidth_hz = tvp->u.data; break; case DTV_INVERSION: fe->dtv_property_cache.inversion = tvp->u.data; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 784e8fe1d3b..2fa37f5a0d9 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -198,7 +198,7 @@ struct dtv_frontend_properties { fe_spectral_inversion_t inversion; fe_code_rate_t fec_inner; fe_transmit_mode_t transmission_mode; - fe_bandwidth_t bandwidth; + u32 bandwidth_hz; /* 0 = AUTO */ fe_guard_interval_t guard_interval; fe_hierarchy_t hierarchy; u32 symbol_rate; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 05bdec9bc5a..4f3fd641ccb 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -257,7 +257,12 @@ typedef enum dtv_cmd_types { DTV_FREQUENCY, DTV_MODULATION, - DTV_BANDWIDTH, + + /* XXX PB: I would like to have field which describes the + * bandwidth of a channel in Hz or kHz - maybe we can remove the + * DTV_BANDWIDTH now and put a compat layer */ + DTV_BANDWIDTH_HZ, + DTV_INVERSION, DTV_DISEQC_MASTER, DTV_SYMBOL_RATE, @@ -276,18 +281,34 @@ typedef enum dtv_cmd_types { /* New commands are always appended */ DTV_DELIVERY_SYSTEM, - /* ISDB-T */ + /* ISDB */ + /* maybe a dup of DTV_ISDB_SOUND_BROADCASTING_SUBCHANNEL_ID ??? */ DTV_ISDB_SEGMENT_IDX, - DTV_ISDB_SEGMENT_WIDTH, + DTV_ISDB_SEGMENT_WIDTH, /* 1, 3 or 13 ??? */ + + /* the central segment can be received independently or 1/3 seg in SB-mode */ + DTV_ISDB_PARTIAL_RECEPTION, + /* sound broadcasting is used 0 = 13segment, 1 = 1 or 3 see DTV_ISDB_PARTIAL_RECEPTION */ + DTV_ISDB_SOUND_BROADCASTING, + + /* only used in SB */ + /* determines the initial PRBS of the segment (to match with 13seg channel) */ + DTV_ISDB_SOUND_BROADCASTING_SUBCHANNEL_ID, + DTV_ISDB_LAYERA_FEC, DTV_ISDB_LAYERA_MODULATION, DTV_ISDB_LAYERA_SEGMENT_WIDTH, + DTV_ISDB_LAYERA_TIME_INTERLEAVER, + DTV_ISDB_LAYERB_FEC, DTV_ISDB_LAYERB_MODULATION, DTV_ISDB_LAYERB_SEGMENT_WIDTH, + DTV_ISDB_LAYERB_TIME_INTERLEAVING, + DTV_ISDB_LAYERC_FEC, DTV_ISDB_LAYERC_MODULATION, DTV_ISDB_LAYERC_SEGMENT_WIDTH, + DTV_ISDB_LAYERC_TIME_INTERLEAVING, } dtv_cmd_types_t; -- GitLab From 1d78cac4779be3ae6bef4791b3b12928e2499fef Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 13 Sep 2008 18:15:17 -0300 Subject: [PATCH 4121/5416] V4L/DVB (9008): S2API: Bugfix related to syncing the cache when used with the old API. Many thanks to Darron Broad for pointing out the obvious. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 7dffb48e55e..05d0b73cf9a 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1595,9 +1595,9 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, break; } - dtv_property_cache_sync(fe, &fepriv->parameters); memcpy (&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters)); + dtv_property_cache_sync(fe, &fepriv->parameters); } memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); -- GitLab From 83fe92e71ef736a26a6eedd0822b34ed5af077f0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 13 Sep 2008 19:22:15 -0300 Subject: [PATCH 4122/5416] V4L/DVB (9009): Nova-se2 / Nova-s-plus Intersil6421 power fix to support switches. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 5ff6e9d2871..891acb50bd9 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -847,7 +847,7 @@ static int dvb_register(struct cx8802_dev *dev) &core->i2c_adap); if (dev->dvb.frontend) { if (!dvb_attach(isl6421_attach, dev->dvb.frontend, - &core->i2c_adap, 0x08, 0x00, 0x00)) + &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } break; @@ -950,7 +950,7 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_TEVII_S460: - dev->dvb.frontend = dvb_attach(cx24116_attach, + dev->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, &core->i2c_adap); if (dev->dvb.frontend != NULL) { -- GitLab From a611d0ca006fe76d88b8dd5ac44f4468293b6760 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 13 Sep 2008 10:10:53 -0300 Subject: [PATCH 4123/5416] V4L/DVB (9010): Add support for SDMC DM1105 PCI chip Add support for SDMC DM1105 PCI chip. There is a lot of cards based on it, like DvbWorld 2002 DVB-S , 2004 DVB-S2 Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 4 + drivers/media/dvb/Makefile | 2 +- drivers/media/dvb/dm1105/Kconfig | 14 + drivers/media/dvb/dm1105/Makefile | 3 + drivers/media/dvb/dm1105/dm1105.c | 917 ++++++++++++++++++++++++++++++ 5 files changed, 939 insertions(+), 1 deletion(-) create mode 100644 drivers/media/dvb/dm1105/Kconfig create mode 100644 drivers/media/dvb/dm1105/Makefile create mode 100644 drivers/media/dvb/dm1105/dm1105.c diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 8bc1445bd33..5858744e70d 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -35,6 +35,10 @@ comment "Supported Pluto2 Adapters" depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/pluto2/Kconfig" +comment "Supported SDMC DM1105 Adapters" + depends on DVB_CORE && PCI && I2C +source "drivers/media/dvb/dm1105/Kconfig" + comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index d6ba4d19520..ea953a03e24 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ +obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ dm1105/ diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig new file mode 100644 index 00000000000..fc2ca7dca6b --- /dev/null +++ b/drivers/media/dvb/dm1105/Kconfig @@ -0,0 +1,14 @@ +config DVB_DM1105 + tristate "SDMC DM1105 based PCI cards" + depends on DVB_CORE && PCI && I2C + select DVB_PLL if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + help + Support for cards based on the SDMC DM1105 PCI chip like + DvbWorld 2002 + + Since these cards have no MPEG decoder onboard, they transmit + only compressed MPEG data over the PCI bus, so you need + an external software decoder to watch TV on your computer. + + Say Y or M if you own such a device and want to use it. diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile new file mode 100644 index 00000000000..8ac28b0546a --- /dev/null +++ b/drivers/media/dvb/dm1105/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_DM1105) += dm1105.o + +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c new file mode 100644 index 00000000000..fe8d0e58c0e --- /dev/null +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -0,0 +1,917 @@ +/* + * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip + * + * Copyright (C) 2008 Igor M. Liplianin + * + * 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 "demux.h" +#include "dmxdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" +#include "dvbdev.h" +#include "dvb-pll.h" + +#include "stv0299.h" +/*#include "stv0288.h" + *#include "si21xx.h" + *#include "stb6000.h" + *#include "cx24116.h"*/ +#include "z0194a.h" + +/* ----------------------------------------------- */ +/* + * PCI ID's + */ +#ifndef PCI_VENDOR_ID_TRIGEM +#define PCI_VENDOR_ID_TRIGEM 0x109f +#endif +#ifndef PCI_DEVICE_ID_DM1105 +#define PCI_DEVICE_ID_DM1105 0x036f +#endif +#ifndef PCI_DEVICE_ID_DW2002 +#define PCI_DEVICE_ID_DW2002 0x2002 +#endif +#ifndef PCI_DEVICE_ID_DW2004 +#define PCI_DEVICE_ID_DW2004 0x2004 +#endif +/* ----------------------------------------------- */ +/* sdmc dm1105 registers */ + +/* TS Control */ +#define DM1105_TSCTR 0x00 +#define DM1105_DTALENTH 0x04 + +/* GPIO Interface */ +#define DM1105_GPIOVAL 0x08 +#define DM1105_GPIOCTR 0x0c + +/* PID serial number */ +#define DM1105_PIDN 0x10 + +/* Odd-even secret key select */ +#define DM1105_CWSEL 0x14 + +/* Host Command Interface */ +#define DM1105_HOST_CTR 0x18 +#define DM1105_HOST_AD 0x1c + +/* PCI Interface */ +#define DM1105_CR 0x30 +#define DM1105_RST 0x34 +#define DM1105_STADR 0x38 +#define DM1105_RLEN 0x3c +#define DM1105_WRP 0x40 +#define DM1105_INTCNT 0x44 +#define DM1105_INTMAK 0x48 +#define DM1105_INTSTS 0x4c + +/* CW Value */ +#define DM1105_ODD 0x50 +#define DM1105_EVEN 0x58 + +/* PID Value */ +#define DM1105_PID 0x60 + +/* IR Control */ +#define DM1105_IRCTR 0x64 +#define DM1105_IRMODE 0x68 +#define DM1105_SYSTEMCODE 0x6c +#define DM1105_IRCODE 0x70 + +/* Unknown Values */ +#define DM1105_ENCRYPT 0x74 +#define DM1105_VER 0x7c + +/* I2C Interface */ +#define DM1105_I2CCTR 0x80 +#define DM1105_I2CSTS 0x81 +#define DM1105_I2CDAT 0x82 +#define DM1105_I2C_RA 0x83 +/* ----------------------------------------------- */ +/* Interrupt Mask Bits */ + +#define INTMAK_TSIRQM 0x01 +#define INTMAK_HIRQM 0x04 +#define INTMAK_IRM 0x08 +#define INTMAK_ALLMASK (INTMAK_TSIRQM | \ + INTMAK_HIRQM | \ + INTMAK_IRM) +#define INTMAK_NONEMASK 0x00 + +/* Interrupt Status Bits */ +#define INTSTS_TSIRQ 0x01 +#define INTSTS_HIRQ 0x04 +#define INTSTS_IR 0x08 + +/* IR Control Bits */ +#define DM1105_IR_EN 0x01 +#define DM1105_SYS_CHK 0x02 +#define DM1105_REP_FLG 0x08 + +/* EEPROM addr */ +#define IIC_24C01_addr 0xa0 +/* Max board count */ +#define DM1105_MAX 0x04 + +#define DRIVER_NAME "dm1105" + +#define DM1105_DMA_PACKETS 47 +#define DM1105_DMA_PACKET_LENGTH (128*4) +#define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) + +/* GPIO's for LNB power control */ +#define DM1105_LNB_MASK 0x00000000 +#define DM1105_LNB_13V 0x00010100 +#define DM1105_LNB_18V 0x00000100 + +static int ir_debug; +module_param(ir_debug, int, 0644); +MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static u16 ir_codes_dm1105_nec[128] = { + [0x0a] = KEY_Q, /*power*/ + [0x0c] = KEY_M, /*mute*/ + [0x11] = KEY_1, + [0x12] = KEY_2, + [0x13] = KEY_3, + [0x14] = KEY_4, + [0x15] = KEY_5, + [0x16] = KEY_6, + [0x17] = KEY_7, + [0x18] = KEY_8, + [0x19] = KEY_9, + [0x10] = KEY_0, + [0x1c] = KEY_PAGEUP, /*ch+*/ + [0x0f] = KEY_PAGEDOWN, /*ch-*/ + [0x1a] = KEY_O, /*vol+*/ + [0x0e] = KEY_Z, /*vol-*/ + [0x04] = KEY_R, /*rec*/ + [0x09] = KEY_D, /*fav*/ + [0x08] = KEY_BACKSPACE, /*rewind*/ + [0x07] = KEY_A, /*fast*/ + [0x0b] = KEY_P, /*pause*/ + [0x02] = KEY_ESC, /*cancel*/ + [0x03] = KEY_G, /*tab*/ + [0x00] = KEY_UP, /*up*/ + [0x1f] = KEY_ENTER, /*ok*/ + [0x01] = KEY_DOWN, /*down*/ + [0x05] = KEY_C, /*cap*/ + [0x06] = KEY_S, /*stop*/ + [0x40] = KEY_F, /*full*/ + [0x1e] = KEY_W, /*tvmode*/ + [0x1b] = KEY_B, /*recall*/ +}; + +/* infrared remote control */ +struct infrared { + u16 key_map[128]; + struct input_dev *input_dev; + char input_phys[32]; + struct tasklet_struct ir_tasklet; + u32 ir_command; +}; + +struct dm1105dvb { + /* pci */ + struct pci_dev *pdev; + u8 __iomem *io_mem; + + /* ir */ + struct infrared ir; + + /* dvb */ + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; + struct dmxdev dmxdev; + struct dvb_adapter dvb_adapter; + struct dvb_demux demux; + struct dvb_frontend *fe; + struct dvb_net dvbnet; + unsigned int full_ts_users; + + /* i2c */ + struct i2c_adapter i2c_adap; + + /* dma */ + dma_addr_t dma_addr; + unsigned char *ts_buf; + u32 wrp; + u32 buffer_size; + unsigned int PacketErrorCount; + unsigned int dmarst; + spinlock_t lock; + +}; + +#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) + +static struct dm1105dvb *dm1105dvb_local; + +static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct dm1105dvb *dm1105dvb ; + + int addr, rc, i, j, k, len, byte, data; + u8 status; + + dm1105dvb = i2c_adap->algo_data; + for (i = 0; i < num; i++) { + outb(0x00, dm_io_mem(DM1105_I2CCTR)); + if (msgs[i].flags & I2C_M_RD) { + /* read bytes */ + addr = msgs[i].addr << 1; + addr |= 1; + outb(addr, dm_io_mem(DM1105_I2CDAT)); + for (byte = 0; byte < msgs[i].len; byte++) + outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1)); + + outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + for (j = 0; j < 55; j++) { + mdelay(10); + status = inb(dm_io_mem(DM1105_I2CSTS)); + if ((status & 0xc0) == 0x40) + break; + } + if (j >= 55) + return -1; + + for (byte = 0; byte < msgs[i].len; byte++) { + rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1)); + if (rc < 0) + goto err; + msgs[i].buf[byte] = rc; + } + } else { + if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { + /* prepaired for cx24116 firmware */ + /* Write in small blocks */ + len = msgs[i].len - 1; + k = 1; + do { + outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); + outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); + for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { + data = msgs[i].buf[k+byte]; + outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); + } + outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); + for (j = 0; j < 25; j++) { + mdelay(10); + status = inb(dm_io_mem(DM1105_I2CSTS)); + if ((status & 0xc0) == 0x40) + break; + } + + if (j >= 25) + return -1; + + k += 48; + len -= 48; + } while (len > 0); + } else { + /* write bytes */ + outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); + for (byte = 0; byte < msgs[i].len; byte++) { + data = msgs[i].buf[byte]; + outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); + } + outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + for (j = 0; j < 25; j++) { + mdelay(10); + status = inb(dm_io_mem(DM1105_I2CSTS)); + if ((status & 0xc0) == 0x40) + break; + } + + if (j >= 25) + return -1; + } + } + } + return num; + err: + return rc; +} + +static u32 functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm dm1105_algo = { + .master_xfer = dm1105_i2c_xfer, + .functionality = functionality, +}; + +static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed) +{ + return container_of(feed->demux, struct dm1105dvb, demux); +} + +static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) +{ + return container_of(fe->dvb, struct dm1105dvb, dvb_adapter); +} + +static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); + + if (voltage == SEC_VOLTAGE_18) { + outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); + outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL)); + } else { + /*LNB ON-13V by default!*/ + outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); + outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL)); + } + + return 0; +} + +static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb) +{ + outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR)); +} + +static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb) +{ + dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr); + + return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr); +} + +static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) +{ + pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); +} + +static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) +{ + outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); + outb(1, dm_io_mem(DM1105_CR)); +} + +static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb) +{ + outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK)); + outb(0, dm_io_mem(DM1105_CR)); +} + +static int dm1105dvb_start_feed(struct dvb_demux_feed *f) +{ + struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); + + if (dm1105dvb->full_ts_users++ == 0) + dm1105dvb_enable_irqs(dm1105dvb); + + return 0; +} + +static int dm1105dvb_stop_feed(struct dvb_demux_feed *f) +{ + struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); + + if (--dm1105dvb->full_ts_users == 0) + dm1105dvb_disable_irqs(dm1105dvb); + + return 0; +} + +/* ir tasklet */ +static void dm1105_emit_key(unsigned long parm) +{ + struct infrared *ir = (struct infrared *) parm; + u32 ircom = ir->ir_command; + u8 data; + u16 keycode; + + data = (ircom >> 8) & 0x7f; + + input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data); + input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); + keycode = ir->key_map[data]; + + if (!keycode) + return; + + input_event(ir->input_dev, EV_KEY, keycode, 1); + input_sync(ir->input_dev); + input_event(ir->input_dev, EV_KEY, keycode, 0); + input_sync(ir->input_dev); + +} + +static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) +{ + struct dm1105dvb *dm1105dvb = dev_id; + unsigned int piece; + unsigned int nbpackets; + u32 command; + u32 nextwrp; + u32 oldwrp; + + /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ + unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); + outb(intsts, dm_io_mem(DM1105_INTSTS)); + + switch (intsts) { + case INTSTS_TSIRQ: + case (INTSTS_TSIRQ | INTSTS_IR): + nextwrp = inl(dm_io_mem(DM1105_WRP)) - + inl(dm_io_mem(DM1105_STADR)) ; + oldwrp = dm1105dvb->wrp; + spin_lock(&dm1105dvb->lock); + if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && + (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && + (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { + dm1105dvb->PacketErrorCount++; + /* bad packet found */ + if ((dm1105dvb->PacketErrorCount >= 2) && + (dm1105dvb->dmarst == 0)) { + outb(1, dm_io_mem(DM1105_RST)); + dm1105dvb->wrp = 0; + dm1105dvb->PacketErrorCount = 0; + dm1105dvb->dmarst = 0; + spin_unlock(&dm1105dvb->lock); + return IRQ_HANDLED; + } + } + if (nextwrp < oldwrp) { + piece = dm1105dvb->buffer_size - oldwrp; + memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp); + nbpackets = (piece + nextwrp)/188; + } else { + nbpackets = (nextwrp - oldwrp)/188; + } + dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets); + dm1105dvb->wrp = nextwrp; + spin_unlock(&dm1105dvb->lock); + break; + case INTSTS_IR: + command = inl(dm_io_mem(DM1105_IRCODE)); + if (ir_debug) + printk("dm1105: received byte 0x%04x\n", command); + + dm1105dvb->ir.ir_command = command; + tasklet_schedule(&dm1105dvb->ir.ir_tasklet); + break; + } + return IRQ_HANDLED; + + +} + +/* register with input layer */ +static void input_register_keys(struct infrared *ir) +{ + int i; + + memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); + + for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) + set_bit(ir->key_map[i], ir->input_dev->keybit); + + ir->input_dev->keycode = ir->key_map; + ir->input_dev->keycodesize = sizeof(ir->key_map[0]); + ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); +} + +int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) +{ + struct input_dev *input_dev; + int err; + + dm1105dvb_local = dm1105; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + dm1105->ir.input_dev = input_dev; + snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), + "pci-%s/ir0", pci_name(dm1105->pdev)); + + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->name = "DVB on-card IR receiver"; + + input_dev->phys = dm1105->ir.input_phys; + input_dev->id.bustype = BUS_PCI; + input_dev->id.version = 2; + if (dm1105->pdev->subsystem_vendor) { + input_dev->id.vendor = dm1105->pdev->subsystem_vendor; + input_dev->id.product = dm1105->pdev->subsystem_device; + } else { + input_dev->id.vendor = dm1105->pdev->vendor; + input_dev->id.product = dm1105->pdev->device; + } + input_dev->dev.parent = &dm1105->pdev->dev; + /* initial keymap */ + memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map); + input_register_keys(&dm1105->ir); + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } + + tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir); + + return 0; +} + + +void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) +{ + tasklet_kill(&dm1105->ir.ir_tasklet); + input_unregister_device(dm1105->ir.input_dev); + +} + +static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) +{ + dm1105dvb_disable_irqs(dm1105dvb); + + outb(0, dm_io_mem(DM1105_HOST_CTR)); + + /*DATALEN 188,*/ + outb(188, dm_io_mem(DM1105_DTALENTH)); + /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ + outw(0xc10a, dm_io_mem(DM1105_TSCTR)); + + /* map DMA and set address */ + dm1105dvb_dma_map(dm1105dvb); + dm1105dvb_set_dma_addr(dm1105dvb); + /* big buffer */ + outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); + outb(47, dm_io_mem(DM1105_INTCNT)); + + /* IR NEC mode enable */ + outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR)); + outb(0, dm_io_mem(DM1105_IRMODE)); + outw(0, dm_io_mem(DM1105_SYSTEMCODE)); + + return 0; +} + +static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb) +{ + dm1105dvb_disable_irqs(dm1105dvb); + + /* IR disable */ + outb(0, dm_io_mem(DM1105_IRCTR)); + outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); + + dm1105dvb_dma_unmap(dm1105dvb); +} +#if 0 +static struct stv0288_config earda_config = { + .demod_address = 0x68, + .min_delay_ms = 100, +}; + +static struct si21xx_config serit_config = { + .demod_address = 0x68, + .min_delay_ms = 100, + +}; + +static struct cx24116_config serit_sp2633_config = { + .demod_address = 0x55, +}; +#endif /* keep */ + +static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) +{ + int ret; + + switch (dm1105dvb->pdev->subsystem_device) { + case PCI_DEVICE_ID_DW2002: + dm1105dvb->fe = dvb_attach( + stv0299_attach, &sharp_z0194a_config, + &dm1105dvb->i2c_adap); + + if (dm1105dvb->fe) { + dm1105dvb->fe->ops.set_voltage = + dm1105dvb_set_voltage; + dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, + &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); + } +#if 0 + if (!dm1105dvb->fe) { + dm1105dvb->fe = dvb_attach( + stv0288_attach, &earda_config, + &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) { + dm1105dvb->fe->ops.set_voltage = + dm1105dvb_set_voltage; + dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, + &dm1105dvb->i2c_adap); + } + } + + if (!dm1105dvb->fe) { + dm1105dvb->fe = dvb_attach( + si21xx_attach, &serit_config, + &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) + dm1105dvb->fe->ops.set_voltage = + dm1105dvb_set_voltage; + } +#endif /* keep */ + break; + case PCI_DEVICE_ID_DW2004: +#if 0 + dm1105dvb->fe = dvb_attach( + cx24116_attach, &serit_sp2633_config, + &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) + dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; +#else /* keep */ + dev_err(&dm1105dvb->pdev->dev, "needs cx24116 module\n"); +#endif /* keep */ + break; + } + + if (!dm1105dvb->fe) { + dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n"); + return -ENODEV; + } + + ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe); + if (ret < 0) { + if (dm1105dvb->fe->ops.release) + dm1105dvb->fe->ops.release(dm1105dvb->fe); + dm1105dvb->fe = NULL; + return ret; + } + + return 0; +} + +static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) +{ + static u8 command[1] = { 0x28 }; + + struct i2c_msg msg[] = { + { .addr = IIC_24C01_addr >> 1, .flags = 0, + .buf = command, .len = 1 }, + { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, + .buf = mac, .len = 6 }, + }; + + dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); + dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +static int __devinit dm1105_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct dm1105dvb *dm1105dvb; + struct dvb_adapter *dvb_adapter; + struct dvb_demux *dvbdemux; + struct dmx_demux *dmx; + int ret = -ENOMEM; + + dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); + if (!dm1105dvb) + goto out; + + dm1105dvb->pdev = pdev; + dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; + dm1105dvb->PacketErrorCount = 0; + dm1105dvb->dmarst = 0; + + ret = pci_enable_device(pdev); + if (ret < 0) + goto err_kfree; + + ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (ret < 0) + goto err_pci_disable_device; + + pci_set_master(pdev); + + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret < 0) + goto err_pci_disable_device; + + dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); + if (!dm1105dvb->io_mem) { + ret = -EIO; + goto err_pci_release_regions; + } + + spin_lock_init(&dm1105dvb->lock); + pci_set_drvdata(pdev, dm1105dvb); + + ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb); + if (ret < 0) + goto err_pci_iounmap; + + ret = dm1105dvb_hw_init(dm1105dvb); + if (ret < 0) + goto err_free_irq; + + /* i2c */ + i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); + strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME); + dm1105dvb->i2c_adap.owner = THIS_MODULE; + dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; + dm1105dvb->i2c_adap.dev.parent = &pdev->dev; + dm1105dvb->i2c_adap.algo = &dm1105_algo; + dm1105dvb->i2c_adap.algo_data = dm1105dvb; + ret = i2c_add_adapter(&dm1105dvb->i2c_adap); + + if (ret < 0) + goto err_dm1105dvb_hw_exit; + + /* dvb */ + ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME, + THIS_MODULE, &pdev->dev, adapter_nr); + if (ret < 0) + goto err_i2c_del_adapter; + + dvb_adapter = &dm1105dvb->dvb_adapter; + + dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac); + + dvbdemux = &dm1105dvb->demux; + dvbdemux->filternum = 256; + dvbdemux->feednum = 256; + dvbdemux->start_feed = dm1105dvb_start_feed; + dvbdemux->stop_feed = dm1105dvb_stop_feed; + dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | + DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); + ret = dvb_dmx_init(dvbdemux); + if (ret < 0) + goto err_dvb_unregister_adapter; + + dmx = &dvbdemux->dmx; + dm1105dvb->dmxdev.filternum = 256; + dm1105dvb->dmxdev.demux = dmx; + dm1105dvb->dmxdev.capabilities = 0; + + ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter); + if (ret < 0) + goto err_dvb_dmx_release; + + dm1105dvb->hw_frontend.source = DMX_FRONTEND_0; + + ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend); + if (ret < 0) + goto err_dvb_dmxdev_release; + + dm1105dvb->mem_frontend.source = DMX_MEMORY_FE; + + ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend); + if (ret < 0) + goto err_remove_hw_frontend; + + ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend); + if (ret < 0) + goto err_remove_mem_frontend; + + ret = frontend_init(dm1105dvb); + if (ret < 0) + goto err_disconnect_frontend; + + dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); + dm1105_ir_init(dm1105dvb); +out: + return ret; + +err_disconnect_frontend: + dmx->disconnect_frontend(dmx); +err_remove_mem_frontend: + dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); +err_remove_hw_frontend: + dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); +err_dvb_dmxdev_release: + dvb_dmxdev_release(&dm1105dvb->dmxdev); +err_dvb_dmx_release: + dvb_dmx_release(dvbdemux); +err_dvb_unregister_adapter: + dvb_unregister_adapter(dvb_adapter); +err_i2c_del_adapter: + i2c_del_adapter(&dm1105dvb->i2c_adap); +err_dm1105dvb_hw_exit: + dm1105dvb_hw_exit(dm1105dvb); +err_free_irq: + free_irq(pdev->irq, dm1105dvb); +err_pci_iounmap: + pci_iounmap(pdev, dm1105dvb->io_mem); +err_pci_release_regions: + pci_release_regions(pdev); +err_pci_disable_device: + pci_disable_device(pdev); +err_kfree: + pci_set_drvdata(pdev, NULL); + kfree(dm1105dvb); + goto out; +} + +static void __devexit dm1105_remove(struct pci_dev *pdev) +{ + struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev); + struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter; + struct dvb_demux *dvbdemux = &dm1105dvb->demux; + struct dmx_demux *dmx = &dvbdemux->dmx; + + dm1105_ir_exit(dm1105dvb); + dmx->close(dmx); + dvb_net_release(&dm1105dvb->dvbnet); + if (dm1105dvb->fe) + dvb_unregister_frontend(dm1105dvb->fe); + + dmx->disconnect_frontend(dmx); + dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); + dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); + dvb_dmxdev_release(&dm1105dvb->dmxdev); + dvb_dmx_release(dvbdemux); + dvb_unregister_adapter(dvb_adapter); + if (&dm1105dvb->i2c_adap) + i2c_del_adapter(&dm1105dvb->i2c_adap); + + dm1105dvb_hw_exit(dm1105dvb); + synchronize_irq(pdev->irq); + free_irq(pdev->irq, dm1105dvb); + pci_iounmap(pdev, dm1105dvb->io_mem); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + kfree(dm1105dvb); +} + +static struct pci_device_id dm1105_id_table[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_TRIGEM, + .device = PCI_DEVICE_ID_DM1105, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_DEVICE_ID_DW2002, + }, { + .vendor = PCI_VENDOR_ID_TRIGEM, + .device = PCI_DEVICE_ID_DM1105, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_DEVICE_ID_DW2004, + }, { + /* empty */ + }, +}; + +MODULE_DEVICE_TABLE(pci, dm1105_id_table); + +static struct pci_driver dm1105_driver = { + .name = DRIVER_NAME, + .id_table = dm1105_id_table, + .probe = dm1105_probe, + .remove = __devexit_p(dm1105_remove), +}; + +static int __init dm1105_init(void) +{ + return pci_register_driver(&dm1105_driver); +} + +static void __exit dm1105_exit(void) +{ + pci_unregister_driver(&dm1105_driver); +} + +module_init(dm1105_init); +module_exit(dm1105_exit); + +MODULE_AUTHOR("Igor M. Liplianin "); +MODULE_DESCRIPTION("SDMC DM1105 DVB driver"); +MODULE_LICENSE("GPL"); -- GitLab From 490c868408bc57a756550148313ac8582fe501ef Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Sat, 13 Sep 2008 19:42:16 -0300 Subject: [PATCH 4124/5416] V4L/DVB (9011): S2API: A number of cleanusp from the last 24 months. I was given these changes by Darron Broad and Igor Liplianin and represent a series of patches they've been making to the cx24116 driver over the last two years. Changes for handling symbolrates >30Ksps Tone handling changes. Diseqc support. Sleep support, shutting down the clocks correctly. Cleanup on ROLL_OFF and PILOT support. *** ST - We need to cleanup the sysclt control, this is abnormal in a demod driver. We should work towards understanding the missing API's and ensure we have them in S2API. *** Signed-off-by: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24116.c | 808 ++++++++++++++++++++------ 1 file changed, 617 insertions(+), 191 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 0ac2c549308..cfb265de522 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -2,6 +2,18 @@ Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver Copyright (C) 2006-2008 Steven Toth + Copyright (C) 2006-2007 Georg Acher + Copyright (C) 2007-2008 Darron Broad + March 2007 + Fixed some bugs. + Added diseqc support. + Added corrected signal strength support. + August 2007 + Sync with legacy version. + Some clean ups. + Copyright (C) 2008 Igor Liplianin + September, 9th 2008 + Fixed locking on high symbol rates (>30000). 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 @@ -18,51 +30,69 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * Updates by Darron Broad 2007. - * - * March - * Fixed some bugs. - * Added diseqc support. - * Added corrected signal strength support. - * - * August - * Sync with legacy version. - * Some clean ups. - */ -/* Updates by Igor Liplianin - * - * September, 9th 2008 - * Fixed locking on high symbol rates (>30000). - */ - #include #include #include #include #include #include +#include #include "dvb_frontend.h" #include "cx24116.h" -/* - * Fetch firmware in the following manner. - * - * #!/bin/sh - * wget ftp://167.206.143.11/outgoing/Oxford/88x_2_117_24275_1_INF.zip - * unzip 88x_2_117_24275_1_INF.zip - * dd if=Driver88/hcw88bda.sys of=dvb-fe-cx24116.fw skip=81768 bs=1 count=32522 - */ +static int debug = 0; +#define dprintk(args...) \ + do { \ + if (debug) printk ("cx24116: " args); \ + } while (0) + #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" #define CX24116_SEARCH_RANGE_KHZ 5000 -/* registers (TO BE COMPLETED) */ -#define CX24116_REG_SIGNAL (0xd5) +/* known registers */ +#define CX24116_REG_COMMAND (0x00) /* command args 0x00..0x1e */ +#define CX24116_REG_EXECUTE (0x1f) /* execute command */ +#define CX24116_REG_MAILBOX (0x96) /* FW or multipurpose mailbox? */ +#define CX24116_REG_RESET (0x20) /* reset status > 0 */ +#define CX24116_REG_SIGNAL (0x9e) /* signal low */ +#define CX24116_REG_SSTATUS (0x9d) /* signal high / status */ +#define CX24116_REG_QSTATUS (0xbc) +#define CX24116_REG_QUALITY (0xd5) +#define CX24116_REG_BER0 (0xc9) +#define CX24116_REG_BER8 (0xc8) +#define CX24116_REG_BER16 (0xc7) +#define CX24116_REG_BER24 (0xc6) +#define CX24116_REG_UCB0 (0xcb) +#define CX24116_REG_UCB8 (0xca) +#define CX24116_REG_CLKDIV (0xf3) +#define CX24116_REG_RATEDIV (0xf9) /* arg buffer size */ #define CX24116_ARGLEN (0x1e) +/* rolloff */ +#define CX24116_ROLLOFF_020 (0x00) +#define CX24116_ROLLOFF_025 (0x01) +#define CX24116_ROLLOFF_035 (0x02) + +/* pilot bit */ +#define CX24116_PILOT (0x40) + +/* signal status */ +#define CX24116_HAS_SIGNAL (0x01) +#define CX24116_HAS_CARRIER (0x02) +#define CX24116_HAS_VITERBI (0x04) +#define CX24116_HAS_SYNCLOCK (0x08) +#define CX24116_HAS_UNKNOWN1 (0x10) +#define CX24116_HAS_UNKNOWN2 (0x20) +#define CX24116_STATUS_MASK (0x3f) +#define CX24116_SIGNAL_MASK (0xc0) + +#define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */ +#define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */ +#define CX24116_DISEQC_MESGCACHE (2) /* message cached */ + /* arg offset for DiSEqC */ #define CX24116_DISEQC_BURST (1) #define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */ @@ -75,21 +105,88 @@ #define CX24116_DISEQC_MINI_A (0) #define CX24116_DISEQC_MINI_B (1) -static int debug = 0; -#define dprintk(args...) \ - do { \ - if (debug) printk ("cx24116: " args); \ - } while (0) +/* DiSEqC tone burst */ +static int toneburst = 1; + +/* debug & toneburst sysctl */ +static struct ctl_table_header *kernel_table_header; +static ctl_table toneburst_table[] = { +{ + .ctl_name = 0, + .procname = "toneburst", + .data = &toneburst, + .maxlen = sizeof(int), + .mode = 0666, + .child = NULL, + .parent = NULL, + .proc_handler = &proc_dointvec, + .strategy = NULL, + .extra1 = NULL, + .extra2 = NULL, +}, +{ + .ctl_name = 0, + .procname = "debug", + .data = &debug, + .maxlen = sizeof(int), + .mode = 0666, + .child = NULL, + .parent = NULL, + .proc_handler = &proc_dointvec, + .strategy = NULL, + .extra1 = NULL, + .extra2 = NULL, + }, + {0}, +}; +static ctl_table cx24116_table[] = { +{ + .ctl_name = 0, + .procname = "cx24116", + .data = NULL, + .maxlen = 0, + .mode = 0555, + .child = toneburst_table, + .parent = NULL, + .proc_handler = NULL, + .strategy = NULL, + .extra1 = NULL, + .extra2 = NULL, + }, + {0}, +}; +static ctl_table kernel_table[] = { +{ + .ctl_name = CTL_DEV, + .procname = "dev", + .data = NULL, + .maxlen = 0, + .mode = 0555, + .child = cx24116_table, + .parent = NULL, + .proc_handler = NULL, + .strategy = NULL, + .extra1 = NULL, + .extra2 = NULL, + }, + {0}, +}; enum cmds { - CMD_INIT_CMD10 = 0x10, + CMD_SET_VCO = 0x10, CMD_TUNEREQUEST = 0x11, - CMD_INIT_CMD13 = 0x13, - CMD_INIT_CMD14 = 0x14, - CMD_SEND_DISEQC = 0x21, + CMD_MPEGCONFIG = 0x13, + CMD_TUNERINIT = 0x14, + CMD_BANDWIDTH = 0x15, + CMD_GETAGC = 0x19, + CMD_LNBCONFIG = 0x20, + CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */ CMD_SET_TONEPRE = 0x22, CMD_SET_TONE = 0x23, + CMD_UPDFWVERS = 0x35, + CMD_TUNERSLEEP = 0x36, + CMD_AGCCONTROL = 0x3b, /* Unknown */ }; /* The Demod/Tuner can't easily provide these, we cache them */ @@ -101,11 +198,14 @@ struct cx24116_tuning fe_code_rate_t fec; fe_modulation_t modulation; + fe_pilot_t pilot; + fe_rolloff_t rolloff; /* Demod values */ u8 fec_val; u8 fec_mask; u8 inversion_val; + u8 rolloff_val; }; /* Basic commands that are sent to the firmware */ @@ -127,6 +227,7 @@ struct cx24116_state u8 skip_fw_load; u8 burst; + struct cx24116_cmd dsec_cmd; }; static int cx24116_writereg(struct cx24116_state* state, int reg, int data) @@ -233,6 +334,66 @@ static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_invers return 0; } +/* + * modfec (modulation and FEC) + * =========================== + * + * MOD FEC mask/val standard + * ---- -------- ----------- -------- + * QPSK FEC_1_2 0x02 0x02+X DVB-S + * QPSK FEC_2_3 0x04 0x02+X DVB-S + * QPSK FEC_3_4 0x08 0x02+X DVB-S + * QPSK FEC_4_5 0x10 0x02+X DVB-S (?) + * QPSK FEC_5_6 0x20 0x02+X DVB-S + * QPSK FEC_6_7 0x40 0x02+X DVB-S + * QPSK FEC_7_8 0x80 0x02+X DVB-S + * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?) + * QPSK AUTO 0xff 0x02+X DVB-S + * + * For DVB-S high byte probably represents FEC + * and low byte selects the modulator. The high + * byte is search range mask. Bit 5 may turn + * on DVB-S and remaining bits represent some + * kind of calibration (how/what i do not know). + * + * Eg.(2/3) szap "Zone Horror" + * + * mask/val = 0x04, 0x20 + * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK + * + * mask/val = 0x04, 0x30 + * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK + * + * After tuning FECSTATUS contains actual FEC + * in use numbered 1 through to 8 for 1/2 .. 2/3 etc + * + * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only) + * + * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2 + * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2 + * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2 + * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2 + * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2 + * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2 + * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2 + * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2 + * + * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2 + * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2 + * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2 + * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2 + * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2 + * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2 + * + * For DVB-S2 low bytes selects both modulator + * and FEC. High byte is meaningless here. To + * set pilot, bit 6 (0x40) is set. When inspecting + * FECSTATUS bit 7 (0x80) represents the pilot + * selection whilst not tuned. When tuned, actual FEC + * in use is found in FECSTATUS as per above. Pilot + * value is reset. + */ + /* A table of modulation, fec and configuration bytes for the demod. * Not all S2 mmodulation schemes are support and not all rates with * a scheme are support. Especially, no auto detect when in S2 mode. @@ -244,15 +405,17 @@ struct cx24116_modfec { u8 val; /* Passed to the firmware to indicate mode selection */ } CX24116_MODFEC_MODES[] = { /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */ + + /*mod fec mask val */ { QPSK, FEC_NONE, 0xfe, 0x30 }, - { QPSK, FEC_1_2, 0x02, 0x2e }, - { QPSK, FEC_2_3, 0x04, 0x2f }, - { QPSK, FEC_3_4, 0x08, 0x30 }, - { QPSK, FEC_4_5, 0xfe, 0x30 }, - { QPSK, FEC_5_6, 0x20, 0x31 }, - { QPSK, FEC_6_7, 0xfe, 0x30 }, - { QPSK, FEC_7_8, 0x80, 0x32 }, - { QPSK, FEC_8_9, 0xfe, 0x30 }, + { QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */ + { QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */ + { QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */ + { QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */ + { QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */ + { QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */ + { QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */ + { QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */ { QPSK, FEC_AUTO, 0xfe, 0x30 }, /* NBC-QPSK */ { NBC_QPSK, FEC_1_2, 0x00, 0x04 }, @@ -268,7 +431,12 @@ struct cx24116_modfec { { _8PSK, FEC_2_3, 0x00, 0x0d }, { _8PSK, FEC_3_4, 0x00, 0x0e }, { _8PSK, FEC_5_6, 0x00, 0x0f }, + { _8PSK, FEC_8_9, 0x00, 0x10 }, { _8PSK, FEC_9_10, 0x00, 0x11 }, + /* + * `val' can be found in the FECSTATUS register when tuning. + * FECSTATUS will give the actual FEC in use if tuning was successful. + */ }; static int cx24116_lookup_fecmod(struct cx24116_state* state, @@ -276,6 +444,8 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state, { int i, ret = -EOPNOTSUPP; + dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f); + for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) { if( (m == CX24116_MODFEC_MODES[i].modulation) && @@ -292,37 +462,38 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state, static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec) { int ret = 0; - dprintk("%s()\n", __func__); + + dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec); ret = cx24116_lookup_fecmod(state, mod, fec); if(ret < 0) return ret; + state->dnxt.fec = fec; state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val; state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask; - dprintk("%s() fec_val/mask = 0x%02x/0x%02x\n", __func__, - state->dnxt.fec_val, state->dnxt.fec_mask); + dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__, + state->dnxt.fec_mask, state->dnxt.fec_val); return 0; } static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) { - int ret = 0; + dprintk("%s(%d)\n", __func__, rate); - dprintk("%s()\n", __func__); + /* check if symbol rate is within limits */ + if ((rate > state->frontend.ops.info.symbol_rate_max) || + (rate < state->frontend.ops.info.symbol_rate_min)) { + dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate); + return -EOPNOTSUPP; + } state->dnxt.symbol_rate = rate; + dprintk("%s() symbol_rate = %d\n", __func__, rate); - dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate); - - /* check if symbol rate is within limits */ - if ((state->dnxt.symbol_rate > state->frontend.ops.info.symbol_rate_max) || - (state->dnxt.symbol_rate < state->frontend.ops.info.symbol_rate_min)) - ret = -EOPNOTSUPP; - - return ret; + return 0; } static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); @@ -392,8 +563,8 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) } /* Start execution and wait for cmd to terminate */ - cx24116_writereg(state, 0x1f, 0x01); - while( cx24116_readreg(state, 0x1f) ) + cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01); + while( cx24116_readreg(state, CX24116_REG_EXECUTE) ) { msleep(10); if(i++ > 64) @@ -410,7 +581,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware { struct cx24116_state* state = fe->demodulator_priv; struct cx24116_cmd cmd; - int ret; + int i, ret; + unsigned char vers[4]; dprintk("%s\n", __func__); dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" @@ -427,11 +599,21 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware /* Begin the firmware load process */ /* Prepare the demod, load the firmware, cleanup after load */ + + /* Init PLL */ + cx24116_writereg(state, 0xE5, 0x00); cx24116_writereg(state, 0xF1, 0x08); - cx24116_writereg(state, 0xF2, cx24116_readreg(state, 0xF2) | 0x03); - cx24116_writereg(state, 0xF3, 0x46); - cx24116_writereg(state, 0xF9, 0x00); + cx24116_writereg(state, 0xF2, 0x13); + + /* Start PLL */ + cx24116_writereg(state, 0xe0, 0x03); + cx24116_writereg(state, 0xe0, 0x00); + + /* Unknown */ + cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46); + cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00); + /* Unknown */ cx24116_writereg(state, 0xF0, 0x03); cx24116_writereg(state, 0xF4, 0x81); cx24116_writereg(state, 0xF5, 0x00); @@ -444,8 +626,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware cx24116_writereg(state, 0xF0, 0x00); cx24116_writereg(state, 0xF8, 0x06); - /* Firmware CMD 10: Chip config? */ - cmd.args[0x00] = CMD_INIT_CMD10; + /* Firmware CMD 10: VCO config */ + cmd.args[0x00] = CMD_SET_VCO; cmd.args[0x01] = 0x05; cmd.args[0x02] = 0xdc; cmd.args[0x03] = 0xda; @@ -460,10 +642,10 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware if (ret != 0) return ret; - cx24116_writereg(state, 0x9d, 0x00); + cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00); - /* Firmware CMD 14: Unknown */ - cmd.args[0x00] = CMD_INIT_CMD14; + /* Firmware CMD 14: Tuner config */ + cmd.args[0x00] = CMD_TUNERINIT; cmd.args[0x01] = 0x00; cmd.args[0x02] = 0x00; cmd.len= 0x03; @@ -473,8 +655,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware cx24116_writereg(state, 0xe5, 0x00); - /* Firmware CMD 13: Unknown - Firmware config? */ - cmd.args[0x00] = CMD_INIT_CMD13; + /* Firmware CMD 13: MPEG config */ + cmd.args[0x00] = CMD_MPEGCONFIG; cmd.args[0x01] = 0x01; cmd.args[0x02] = 0x75; cmd.args[0x03] = 0x00; @@ -488,6 +670,19 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware if (ret != 0) return ret; + /* Firmware CMD 35: Get firmware version */ + cmd.args[0x00] = CMD_UPDFWVERS; + cmd.len= 0x02; + for(i=0; i<4; i++) { + cmd.args[0x01] = i; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX); + } + printk("%s: FW version %i.%i.%i.%i\n", __func__, + vers[0], vers[1], vers[2], vers[3]); + return 0; } @@ -503,75 +698,98 @@ static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct cx24116_state *state = fe->demodulator_priv; - int lock = cx24116_readreg(state, 0x9d); + int lock = cx24116_readreg(state, CX24116_REG_SSTATUS); dprintk("%s: status = 0x%02x\n", __func__, lock); *status = 0; - if (lock & 0x01) + if (lock & CX24116_HAS_SIGNAL) *status |= FE_HAS_SIGNAL; - if (lock & 0x02) + if (lock & CX24116_HAS_CARRIER) *status |= FE_HAS_CARRIER; - if (lock & 0x04) + if (lock & CX24116_HAS_VITERBI) *status |= FE_HAS_VITERBI; - if (lock & 0x08) + if (lock & CX24116_HAS_SYNCLOCK) *status |= FE_HAS_SYNC | FE_HAS_LOCK; return 0; } -/* TODO: Not clear how we do this */ static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) { - //struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); - *ber = 0; + + *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) | + ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) | + ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) | + cx24116_readreg(state, CX24116_REG_BER0 ); return 0; } -/* Signal strength (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */ +/* TODO Determine function and scale appropriately */ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) { struct cx24116_state *state = fe->demodulator_priv; - u8 strength_reg; - static const u32 strength_tab[] = { /* 10 x Table (rounded up) */ - 0x00000,0x0199A,0x03333,0x04ccD,0x06667,0x08000,0x0999A,0x0b333,0x0cccD,0x0e667, - 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; + struct cx24116_cmd cmd; + int ret; + u16 sig_reading; dprintk("%s()\n", __func__); - strength_reg = cx24116_readreg(state, CX24116_REG_SIGNAL); + /* Firmware CMD 19: Get AGC */ + cmd.args[0x00] = CMD_GETAGC; + cmd.len= 0x01; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; - if(strength_reg < 0xa0) - *signal_strength = strength_tab [ ( strength_reg & 0xf0 ) >> 4 ] + - ( strength_tab [ ( strength_reg & 0x0f ) ] >> 4 ); - else - *signal_strength = 0xffff; + sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) | + ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 ); + *signal_strength= 0 - sig_reading; - dprintk("%s: Signal strength (raw / cooked) = (0x%02x / 0x%04x)\n", - __func__,strength_reg,*signal_strength); + dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); return 0; } -/* TODO: Not clear how we do this */ +/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */ static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr) { - //struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_state *state = fe->demodulator_priv; + u8 snr_reading; + static const u32 snr_tab[] = { /* 10 x Table (rounded up) */ + 0x00000,0x0199A,0x03333,0x04ccD,0x06667, + 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667, + 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; + dprintk("%s()\n", __func__); - *snr = 0; + + snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY); + + if(snr_reading >= 0xa0 /* 100% */) + *snr = 0xffff; + else + *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] + + ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 ); + + dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, + snr_reading, *snr); return 0; } -/* TODO: Not clear how we do this */ static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - //struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); - *ucblocks = 0; + + *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) | + cx24116_readreg(state, CX24116_REG_UCB0); return 0; } @@ -583,6 +801,27 @@ static void cx24116_clone_params(struct dvb_frontend* fe) memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); } +/* Wait for LNB */ +static int cx24116_wait_for_lnb(struct dvb_frontend* fe) +{ + struct cx24116_state *state = fe->demodulator_priv; + int i; + + dprintk("%s() qstatus = 0x%02x\n", __func__, + cx24116_readreg(state, CX24116_REG_QSTATUS)); + + /* Wait for up to 300 ms */ + for(i = 0; i < 30 ; i++) { + if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20) + return 0; + msleep(10); + } + + dprintk("%s(): LNB not ready\n", __func__); + + return -ETIMEDOUT; /* -EBUSY ? */ +} + static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { struct cx24116_cmd cmd; @@ -594,6 +833,14 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) return -EINVAL; } + /* Wait for LNB ready */ + ret = cx24116_wait_for_lnb(fe); + if(ret != 0) + return ret; + + /* Min delay time after DiSEqC send */ + msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ + /* This is always done before the tone is set */ cmd.args[0x00] = CMD_SET_TONEPRE; cmd.args[0x01] = 0x00; @@ -619,6 +866,9 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) } cmd.len= 0x04; + /* Min delay time before DiSEqC send */ + msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ + return cx24116_cmd_execute(fe, &cmd); } @@ -626,9 +876,39 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) static int cx24116_diseqc_init(struct dvb_frontend* fe) { struct cx24116_state *state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int ret; + + /* Firmware CMD 20: LNB/DiSEqC config */ + cmd.args[0x00] = CMD_LNBCONFIG; + cmd.args[0x01] = 0x00; + cmd.args[0x02] = 0x10; + cmd.args[0x03] = 0x00; + cmd.args[0x04] = 0x8f; + cmd.args[0x05] = 0x28; + cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01; + cmd.args[0x07] = 0x01; + cmd.len= 0x08; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + + /* Prepare a DiSEqC command */ + state->dsec_cmd.args[0x00] = CMD_LNBSEND; + + /* DiSEqC burst */ + state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; + + /* Unknown */ + state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; + state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; + state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */ - /* Default DiSEqC burst state */ - state->burst = CX24116_DISEQC_MINI_A; + /* DiSEqC message length */ + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; + + /* Command length */ + state->dsec_cmd.len= CX24116_DISEQC_MSGOFS; return 0; } @@ -637,7 +917,6 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe) static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) { struct cx24116_state *state = fe->demodulator_priv; - struct cx24116_cmd cmd; int i, ret; /* Dump DiSEqC message */ @@ -647,82 +926,134 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma printk("0x%02x", d->msg[i]); if(++i < d->msg_len) printk(", "); - } - printk(")\n"); + } + printk(") toneburst=%d\n", toneburst); } + /* Validate length */ if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) return -EINVAL; - cmd.args[0x00] = CMD_SEND_DISEQC; - cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; - cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; - cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; - /* DiSEqC message */ for (i = 0; i < d->msg_len; i++) - cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; + state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; + + /* DiSEqC message length */ + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; + + /* Command length */ + state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; + + /* DiSEqC toneburst */ + if(toneburst == CX24116_DISEQC_MESGCACHE) + /* Message is cached */ + return 0; + + else if(toneburst == CX24116_DISEQC_TONEOFF) + /* Message is sent without burst */ + state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0; + + else if(toneburst == CX24116_DISEQC_TONECACHE) { + /* + * Message is sent with derived else cached burst + * + * WRITE PORT GROUP COMMAND 38 + * + * 0/A/A: E0 10 38 F0..F3 + * 1/B/B: E0 10 38 F4..F7 + * 2/C/A: E0 10 38 F8..FB + * 3/D/B: E0 10 38 FC..FF + * + * datebyte[3]= 8421:8421 + * ABCD:WXYZ + * CLR :SET + * + * WX= PORT SELECT 0..3 (X=TONEBURST) + * Y = VOLTAGE (0=13V, 1=18V) + * Z = BAND (0=LOW, 1=HIGH(22K)) + */ + if(d->msg_len >= 4 && d->msg[2] == 0x38) + state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); + if(debug) + dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); + } - /* Hack: Derive burst from command else use previous burst */ - if(d->msg_len >= 4 && d->msg[2] == 0x38) - cmd.args[CX24116_DISEQC_BURST] = (d->msg[3] >> 2) & 1; - else - cmd.args[CX24116_DISEQC_BURST] = state->burst; + /* Wait for LNB ready */ + ret = cx24116_wait_for_lnb(fe); + if(ret != 0) + return ret; - cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; - cmd.len = CX24116_DISEQC_MSGOFS + d->msg_len; + /* Wait for voltage/min repeat delay */ + msleep(100); - ret = cx24116_cmd_execute(fe, &cmd); - - /* Firmware command duration is unknown, so guess... + /* Command */ + ret = cx24116_cmd_execute(fe, &state->dsec_cmd); + if(ret != 0) + return ret; + /* + * Wait for send * * Eutelsat spec: - * >15ms delay + - * 13.5ms per byte + - * >15ms delay + - * 12.5ms burst + - * >15ms delay + * >15ms delay + (XXX determine if FW does this, see set_tone) + * 13.5ms per byte + + * >15ms delay + + * 12.5ms burst + + * >15ms delay (XXX determine if FW does this, see set_tone) */ - if(ret == 0) - msleep( (cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 ); + msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) ); - return ret; + return 0; } /* Send DiSEqC burst */ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) { struct cx24116_state *state = fe->demodulator_priv; - struct cx24116_cmd cmd; int ret; - dprintk("%s(%d)\n",__func__,(int)burst); - - cmd.args[0x00] = CMD_SEND_DISEQC; - cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; - cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; - cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; + dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst); + /* DiSEqC burst */ if (burst == SEC_MINI_A) - cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; + state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; else if(burst == SEC_MINI_B) - cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; + state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; else return -EINVAL; - /* Cache as previous burst state */ - state->burst= cmd.args[CX24116_DISEQC_BURST]; + /* DiSEqC toneburst */ + if(toneburst != CX24116_DISEQC_MESGCACHE) + /* Burst is cached */ + return 0; - cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; - cmd.len= CX24116_DISEQC_MSGOFS; + /* Burst is to be sent with cached message */ - ret= cx24116_cmd_execute(fe, &cmd); + /* Wait for LNB ready */ + ret = cx24116_wait_for_lnb(fe); + if(ret != 0) + return ret; - /* Firmware command duration is unknown, so guess... */ - if(ret == 0) - msleep(60); + /* Wait for voltage/min repeat delay */ + msleep(100); - return ret; + /* Command */ + ret = cx24116_cmd_execute(fe, &state->dsec_cmd); + if(ret != 0) + return ret; + + /* + * Wait for send + * + * Eutelsat spec: + * >15ms delay + (XXX determine if FW does this, see set_tone) + * 13.5ms per byte + + * >15ms delay + + * 12.5ms burst + + * >15ms delay (XXX determine if FW does this, see set_tone) + */ + msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 ); + + return 0; } static void cx24116_release(struct dvb_frontend* fe) @@ -730,6 +1061,7 @@ static void cx24116_release(struct dvb_frontend* fe) struct cx24116_state* state = fe->demodulator_priv; dprintk("%s\n",__func__); kfree(state); + unregister_sysctl_table(kernel_table_header); } static struct dvb_frontend_ops cx24116_ops; @@ -742,11 +1074,15 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, dprintk("%s\n",__func__); + kernel_table_header = register_sysctl_table(kernel_table); + if(!kernel_table_header) + goto error1; + /* allocate memory for the internal state */ state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); if (state == NULL) { printk("Unable to kmalloc\n"); - goto error; + goto error2; } /* setup the state */ @@ -759,7 +1095,7 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); if (ret != 0x0501) { printk("Invalid probe, probably not a CX24116 device\n"); - goto error; + goto error3; } /* create dvb_frontend */ @@ -767,33 +1103,64 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, state->frontend.demodulator_priv = state; return &state->frontend; -error: - kfree(state); - - return NULL; +error3: kfree(state); +error2: unregister_sysctl_table(kernel_table_header); +error1: return NULL; } - -static int cx24116_get_params(struct dvb_frontend* fe) +/* + * Initialise or wake up device + * + * Power config will reset and load initial firmware if required + */ +static int cx24116_initfe(struct dvb_frontend* fe) { - struct cx24116_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *cache = &fe->dtv_property_cache; + struct cx24116_state* state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int ret; dprintk("%s()\n",__func__); - cache->frequency = state->dcur.frequency; - cache->inversion = state->dcur.inversion; - cache->modulation = state->dcur.modulation; - cache->fec_inner = state->dcur.fec; - cache->symbol_rate = state->dcur.symbol_rate; + /* Power on */ + cx24116_writereg(state, 0xe0, 0); + cx24116_writereg(state, 0xe1, 0); + cx24116_writereg(state, 0xea, 0); - return 0; + /* Firmware CMD 36: Power config */ + cmd.args[0x00] = CMD_TUNERSLEEP; + cmd.args[0x01] = 0; + cmd.len= 0x02; + ret = cx24116_cmd_execute(fe, &cmd); + if(ret != 0) + return ret; + + return cx24116_diseqc_init(fe); } -static int cx24116_initfe(struct dvb_frontend* fe) +/* + * Put device to sleep + */ +static int cx24116_sleep(struct dvb_frontend* fe) { + struct cx24116_state* state = fe->demodulator_priv; + struct cx24116_cmd cmd; + int ret; + dprintk("%s()\n",__func__); - return cx24116_diseqc_init(fe); + /* Firmware CMD 36: Power config */ + cmd.args[0x00] = CMD_TUNERSLEEP; + cmd.args[0x01] = 1; + cmd.len= 0x02; + ret = cx24116_cmd_execute(fe, &cmd); + if(ret != 0) + return ret; + + /* Power off (Shutdown clocks) */ + cx24116_writereg(state, 0xea, 0xff); + cx24116_writereg(state, 0xe1, 1); + cx24116_writereg(state, 0xe0, 1); + + return 0; } static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) @@ -817,14 +1184,45 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24116_cmd cmd; fe_status_t tunerstat; - int ret, above30msps; - u8 retune=4; + int i, status, ret, retune = 1; dprintk("%s()\n",__func__); state->dnxt.modulation = c->modulation; state->dnxt.frequency = c->frequency; + switch(c->delivery_system) { + case SYS_DVBS: + dprintk("%s: DVB-S delivery system selected\n",__func__); + state->dnxt.pilot = PILOT_OFF; + state->dnxt.rolloff = CX24116_ROLLOFF_035; + break; + case SYS_DVBS2: + dprintk("%s: DVB-S2 delivery system selected\n",__func__); + if(c->pilot == PILOT_AUTO) + retune++; + state->dnxt.pilot = c->pilot; + switch(c->rolloff) { + case ROLLOFF_20: + state->dnxt.rolloff_val= CX24116_ROLLOFF_020; + break; + case ROLLOFF_25: + state->dnxt.rolloff_val= CX24116_ROLLOFF_025; + break; + case ROLLOFF_35: + state->dnxt.rolloff_val= CX24116_ROLLOFF_035; + break; + case ROLLOFF_AUTO: + return -EOPNOTSUPP; + } + state->dnxt.rolloff = c->rolloff; + break; + default: + dprintk("%s: unsupported delivery system selected (%d)\n", + __func__, c->delivery_system); + return -EOPNOTSUPP; + } + if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) return ret; @@ -837,6 +1235,9 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par /* discard the 'current' tuning parameters and prepare to tune */ cx24116_clone_params(fe); + dprintk("%s: retune = %d\n", __func__, retune); + dprintk("%s: rolloff = %d\n", __func__, state->dcur.rolloff); + dprintk("%s: pilot = %d\n", __func__, state->dcur.pilot); dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__, @@ -844,18 +1245,17 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__, state->dcur.inversion, state->dcur.inversion_val); + /* This is also done in advise/acquire on HVR4000 but not on LITE */ if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); - above30msps = (state->dcur.symbol_rate > 30000000); - - if (above30msps){ - cx24116_writereg(state, 0xF9, 0x01); - cx24116_writereg(state, 0xF3, 0x44); - } else { - cx24116_writereg(state, 0xF9, 0x00); - cx24116_writereg(state, 0xF3, 0x46); - } + /* Set/Reset B/W */ + cmd.args[0x00] = CMD_BANDWIDTH; + cmd.args[0x01] = 0x01; + cmd.len= 0x02; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; /* Prepare a tune request */ cmd.args[0x00] = CMD_TUNEREQUEST; @@ -875,28 +1275,32 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par /* Modulation / FEC & Pilot Off */ cmd.args[0x07] = state->dcur.fec_val; - if (c->pilot == PILOT_ON) - cmd.args[0x07] |= 0x40; + if (state->dcur.pilot == PILOT_ON) + cmd.args[0x07] |= CX24116_PILOT; cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8; cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff; cmd.args[0x0a] = 0x00; cmd.args[0x0b] = 0x00; - cmd.args[0x0c] = 0x02; + cmd.args[0x0c] = state->dcur.rolloff_val; cmd.args[0x0d] = state->dcur.fec_mask; - if (above30msps){ + if (state->dcur.symbol_rate > 30000000) { cmd.args[0x0e] = 0x04; cmd.args[0x0f] = 0x00; cmd.args[0x10] = 0x01; cmd.args[0x11] = 0x77; cmd.args[0x12] = 0x36; + cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44); + cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01); } else { cmd.args[0x0e] = 0x06; cmd.args[0x0f] = 0x00; cmd.args[0x10] = 0x00; cmd.args[0x11] = 0xFA; cmd.args[0x12] = 0x24; + cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46); + cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00); } cmd.len= 0x13; @@ -906,29 +1310,47 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par * the demod does not support autodetect. */ do { - /* Reset status register? */ - cx24116_writereg(state, 0x9d, 0xc1); + /* Reset status register */ + status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; + cx24116_writereg(state, CX24116_REG_SSTATUS, status); /* Tune */ ret = cx24116_cmd_execute(fe, &cmd); if( ret != 0 ) break; - /* The hardware can take time to lock, wait a while */ - msleep(500); - - cx24116_read_status(fe, &tunerstat); - if(tunerstat & FE_HAS_SIGNAL) { - if(tunerstat & FE_HAS_SYNC) - /* Tuned */ - break; - else if(c->pilot == PILOT_AUTO) - /* Toggle pilot bit */ - cmd.args[0x07] ^= 0x40; + /* + * Wait for up to 500 ms before retrying + * + * If we are able to tune then generally it occurs within 100ms. + * If it takes longer, try a different toneburst setting. + */ + for(i = 0; i < 50 ; i++) { + cx24116_read_status(fe, &tunerstat); + status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC); + if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) { + dprintk("%s: Tuned\n",__func__); + goto tuned; + } + msleep(10); } + + dprintk("%s: Not tuned\n",__func__); + + /* Toggle pilot bit when in auto-pilot */ + if(state->dcur.pilot == PILOT_AUTO) + cmd.args[0x07] ^= CX24116_PILOT; } while(--retune); +tuned: /* Set/Reset B/W */ + cmd.args[0x00] = CMD_BANDWIDTH; + cmd.args[0x01] = 0x00; + cmd.len= 0x02; + ret = cx24116_cmd_execute(fe, &cmd); + if (ret != 0) + return ret; + return ret; } @@ -953,6 +1375,7 @@ static struct dvb_frontend_ops cx24116_ops = { .release = cx24116_release, .init = cx24116_initfe, + .sleep = cx24116_sleep, .read_status = cx24116_read_status, .read_ber = cx24116_read_ber, .read_signal_strength = cx24116_read_signal_strength, @@ -971,6 +1394,9 @@ static struct dvb_frontend_ops cx24116_ops = { module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); +module_param(toneburst, int, 0644); +MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); + MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); -- GitLab From 35d9c42779ef5e8cb46902bb6987443e136c0517 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 13 Sep 2008 20:56:59 -0300 Subject: [PATCH 4125/5416] V4L/DVB (9012): Add support for DvbWorld 2004 DVB-S2 PCI adapter Add support for DvbWorld 2004 DVB-S2 PCI adapter. The card contains dm1105 PCI chip and cx24116 demodulator Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 2 +- drivers/media/dvb/dm1105/Kconfig | 19 ++++++++++--------- drivers/media/dvb/dm1105/dm1105.c | 10 +++------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 5858744e70d..14488f64479 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -36,7 +36,7 @@ comment "Supported Pluto2 Adapters" source "drivers/media/dvb/pluto2/Kconfig" comment "Supported SDMC DM1105 Adapters" - depends on DVB_CORE && PCI && I2C + depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/dm1105/Kconfig" comment "Supported DVB Frontends" diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index fc2ca7dca6b..4b96bbba9f4 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -1,14 +1,15 @@ config DVB_DM1105 - tristate "SDMC DM1105 based PCI cards" - depends on DVB_CORE && PCI && I2C + tristate "SDMC DM1105 based PCI cards" + depends on DVB_CORE && PCI && I2C select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE - help - Support for cards based on the SDMC DM1105 PCI chip like - DvbWorld 2002 + select DVB_CX24116 if !DVB_FE_CUSTOMISE + help + Support for cards based on the SDMC DM1105 PCI chip like + DvbWorld 2002 - Since these cards have no MPEG decoder onboard, they transmit - only compressed MPEG data over the PCI bus, so you need - an external software decoder to watch TV on your computer. + Since these cards have no MPEG decoder onboard, they transmit + only compressed MPEG data over the PCI bus, so you need + an external software decoder to watch TV on your computer. - Say Y or M if you own such a device and want to use it. + Say Y or M if you own such a device and want to use it. diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index fe8d0e58c0e..204763d2de4 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -41,8 +41,8 @@ #include "stv0299.h" /*#include "stv0288.h" *#include "si21xx.h" - *#include "stb6000.h" - *#include "cx24116.h"*/ + *#include "stb6000.h"*/ +#include "cx24116.h" #include "z0194a.h" /* ----------------------------------------------- */ @@ -605,11 +605,11 @@ static struct si21xx_config serit_config = { .min_delay_ms = 100, }; +#endif /* keep */ static struct cx24116_config serit_sp2633_config = { .demod_address = 0x55, }; -#endif /* keep */ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) { @@ -651,15 +651,11 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) #endif /* keep */ break; case PCI_DEVICE_ID_DW2004: -#if 0 dm1105dvb->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; -#else /* keep */ - dev_err(&dm1105dvb->pdev->dev, "needs cx24116 module\n"); -#endif /* keep */ break; } -- GitLab From 7396d3ea94b871de66940ea27d4bf81513404990 Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Sun, 14 Sep 2008 10:45:58 -0300 Subject: [PATCH 4126/5416] V4L/DVB (9013): S2API: cx24116 Rolloff changes, sysctls cleanup, isl power changes. Remove the debugging sysctls. Rolloff was broken, not it works as expected and has been tested in kaffeine. Power related changes for the isl6421 are not implemented on the HVR4000/4000LITE. Signed-off-by: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24116.c | 82 ++------------------------- drivers/media/video/cx88/cx88-dvb.c | 2 +- 2 files changed, 7 insertions(+), 77 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index cfb265de522..fdc741e7e76 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "dvb_frontend.h" #include "cx24116.h" @@ -108,70 +107,6 @@ static int debug = 0; /* DiSEqC tone burst */ static int toneburst = 1; -/* debug & toneburst sysctl */ -static struct ctl_table_header *kernel_table_header; -static ctl_table toneburst_table[] = { -{ - .ctl_name = 0, - .procname = "toneburst", - .data = &toneburst, - .maxlen = sizeof(int), - .mode = 0666, - .child = NULL, - .parent = NULL, - .proc_handler = &proc_dointvec, - .strategy = NULL, - .extra1 = NULL, - .extra2 = NULL, -}, -{ - .ctl_name = 0, - .procname = "debug", - .data = &debug, - .maxlen = sizeof(int), - .mode = 0666, - .child = NULL, - .parent = NULL, - .proc_handler = &proc_dointvec, - .strategy = NULL, - .extra1 = NULL, - .extra2 = NULL, - }, - {0}, -}; -static ctl_table cx24116_table[] = { -{ - .ctl_name = 0, - .procname = "cx24116", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = toneburst_table, - .parent = NULL, - .proc_handler = NULL, - .strategy = NULL, - .extra1 = NULL, - .extra2 = NULL, - }, - {0}, -}; -static ctl_table kernel_table[] = { -{ - .ctl_name = CTL_DEV, - .procname = "dev", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = cx24116_table, - .parent = NULL, - .proc_handler = NULL, - .strategy = NULL, - .extra1 = NULL, - .extra2 = NULL, - }, - {0}, -}; - enum cmds { CMD_SET_VCO = 0x10, @@ -964,7 +899,7 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma * 2/C/A: E0 10 38 F8..FB * 3/D/B: E0 10 38 FC..FF * - * datebyte[3]= 8421:8421 + * databyte[3]= 8421:8421 * ABCD:WXYZ * CLR :SET * @@ -1061,7 +996,6 @@ static void cx24116_release(struct dvb_frontend* fe) struct cx24116_state* state = fe->demodulator_priv; dprintk("%s\n",__func__); kfree(state); - unregister_sysctl_table(kernel_table_header); } static struct dvb_frontend_ops cx24116_ops; @@ -1074,15 +1008,11 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, dprintk("%s\n",__func__); - kernel_table_header = register_sysctl_table(kernel_table); - if(!kernel_table_header) - goto error1; - /* allocate memory for the internal state */ state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); if (state == NULL) { printk("Unable to kmalloc\n"); - goto error2; + goto error1; } /* setup the state */ @@ -1095,7 +1025,7 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); if (ret != 0x0501) { printk("Invalid probe, probably not a CX24116 device\n"); - goto error3; + goto error2; } /* create dvb_frontend */ @@ -1103,8 +1033,7 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, state->frontend.demodulator_priv = state; return &state->frontend; -error3: kfree(state); -error2: unregister_sysctl_table(kernel_table_header); +error2: kfree(state); error1: return NULL; } /* @@ -1195,7 +1124,8 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par case SYS_DVBS: dprintk("%s: DVB-S delivery system selected\n",__func__); state->dnxt.pilot = PILOT_OFF; - state->dnxt.rolloff = CX24116_ROLLOFF_035; + state->dnxt.rolloff_val = CX24116_ROLLOFF_035; + state->dnxt.rolloff = c->rolloff; break; case SYS_DVBS2: dprintk("%s: DVB-S2 delivery system selected\n",__func__); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 891acb50bd9..ce1752dc8e2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -946,7 +946,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend) { dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->core->i2c_adap, - 0x08, 0x00, 0x00); + 0x08, ISL6421_DCL, 0x00); } break; case CX88_BOARD_TEVII_S460: -- GitLab From c063a48923525dcf20924eb8f1af3b22248f1e13 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 14 Sep 2008 07:43:53 -0300 Subject: [PATCH 4127/5416] V4L/DVB (9014): History update: MPEG initialization in cx24116. Adjust MPEG initialization in cx24116 in order to accomodate different MPEG CLK position and polarity in different cards. For example, HVR4000 uses 0x02 value, but DvbWorld & TeVii USB cards uses 0x01. Without it MPEG stream was broken on that cards for symbol rates > 30000 kSyms/s. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24116.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index fdc741e7e76..4ad86d84875 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -13,7 +13,8 @@ Some clean ups. Copyright (C) 2008 Igor Liplianin September, 9th 2008 - Fixed locking on high symbol rates (>30000). + Fixed locking on high symbol rates (>30000). + Implement MPEG initialization parameter. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- GitLab From 681faa0b7a1d67576df07e0ad55ca42b2eab174a Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Mon, 22 Sep 2008 00:47:20 -0300 Subject: [PATCH 4128/5416] V4L/DVB (9015): S2API: cx24116 register description fixes. From the author: Here is a simple patch detailing some reverse engineered register detail lost in my latest merge. The comments in the code refer to this register but it is never defined. This corrects this. Signed-off-by: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24116.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index 4ad86d84875..02ed4ef79c6 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c @@ -67,6 +67,13 @@ static int debug = 0; #define CX24116_REG_UCB8 (0xca) #define CX24116_REG_CLKDIV (0xf3) #define CX24116_REG_RATEDIV (0xf9) +#define CX24116_REG_FECSTATUS (0x9c) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */ + +/* FECSTATUS bits */ +#define CX24116_FEC_FECMASK (0x1f) /* mask to determine configured fec (not tuned) or actual fec (tuned) */ +#define CX24116_FEC_DVBS (0x20) /* Select DVB-S demodulator, else DVB-S2 */ +#define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */ +#define CX24116_FEC_PILOT (0x80) /* Pilot mode requested when tuning else always reset when tuned */ /* arg buffer size */ #define CX24116_ARGLEN (0x1e) -- GitLab From 34c080295af9b3ed9f704a881e07eb5ac128e1ed Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Mon, 22 Sep 2008 00:54:59 -0300 Subject: [PATCH 4129/5416] V4L/DVB (9016): HVR3000/4000 Hauppauge related IR cleanups From the author: This patch-set fixes remote control issues I have experienced with hauppauge drivers in Linux since the PVR-350 and now with both a NOVA-S+ and HVR-4000. It has also been confirmed to work with an HVR-1300 user who had exactly the same issue. Hauppage remote controls use RC5. RC5 has a bit-field which represents the target device. The hauppauge windows drivers have a registry key which can enable filtering, but the linux drivers will accept any target device in this bit field for internal processing. This causes problems with setups such as mythtv where remote control key presses destined for the TV (target = 0) are interpreted by the kernel and subsequenctly LIRC then mythtv. Of the remote controls I have to hand (wintv black, pvr/hvr silver) the hauppauge remotes send one of two device targets ids, these are interpreted by the patch which then filters out any non hauppauge addresses. Signed-off-by: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 30 +++++++++++++++++++++++++-- drivers/media/video/ir-kbd-i2c.c | 22 ++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 097081eb505..13bc5d16076 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -394,7 +394,7 @@ void cx88_ir_irq(struct cx88_core *core) { struct cx88_IR *ir = core->ir; u32 samples, ircode; - int i; + int i, start, range, toggle, dev, code; if (NULL == ir) return; @@ -463,9 +463,35 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_PINNACLE_PCTV_HD_800i: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); + ir_dprintk("biphase decoded: %x\n", ircode); + /* + * RC5 has an extension bit which adds a new range + * of available codes, this is detected here. Also + * hauppauge remotes (black/silver) always use + * specific device ids. If we do not filter the + * device ids then messages destined for devices + * such as TVs (id=0) will get through to the + * device causing mis-fired events. + */ + /* split rc5 data block ... */ + start = (ircode & 0x2000) >> 13; + range = (ircode & 0x1000) >> 12; + toggle= (ircode & 0x0800) >> 11; + dev = (ircode & 0x07c0) >> 6; + code = (ircode & 0x003f) | ((range << 6) ^ 0x0040); + if( start != 1) + /* no key pressed */ + break; + if ( dev != 0x1e && dev != 0x1f ) + /* not a hauppauge remote */ + break; + ir_input_keydown(ir->input, &ir->ir, code, ircode); + ir->release = jiffies + msecs_to_jiffies(120); + break; + case CX88_BOARD_PINNACLE_PCTV_HD_800i: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); if ((ircode & 0xfffff000) != 0x3000) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a30254bed31..703195a5ad4 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -65,7 +65,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, int size, int offset) { unsigned char buf[6]; - int start, range, toggle, dev, code; + int start, range, toggle, dev, code, ircode; /* poll IR chip */ if (size != i2c_master_recv(&ir->c,buf,size)) @@ -85,6 +85,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, if (!start) /* no key pressed */ return 0; + /* + * Hauppauge remotes (black/silver) always use + * specific device ids. If we do not filter the + * device ids then messages destined for devices + * such as TVs (id=0) will get through causing + * mis-fired events. + * + * We also filter out invalid key presses which + * produce annoying debug log entries. + */ + ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; + if ((ircode & 0x1fff)==0x1fff) + /* invalid key press */ + return 0; + + if (dev!=0x1e && dev!=0x1f) + /* not a hauppauge remote */ + return 0; if (!range) code += 64; @@ -94,7 +112,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, /* return key */ *ir_key = code; - *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code; + *ir_raw = ircode; return 1; } -- GitLab From 04ad28c9916da709f38b1d43817892142c2c3508 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 16 Sep 2008 18:21:11 -0300 Subject: [PATCH 4130/5416] V4L/DVB (9017): Add support for Silicon Laboratories SI2109/2110 demodulators. Add support for Silicon Laboratories SI2109/2110 demodulator and cards with it, such as DvbWorld PCI2002. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/Kconfig | 1 + drivers/media/dvb/dm1105/dm1105.c | 7 +- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/si21xx.c | 974 +++++++++++++++++++++++++++ drivers/media/dvb/frontends/si21xx.h | 37 + 6 files changed, 1023 insertions(+), 4 deletions(-) create mode 100644 drivers/media/dvb/frontends/si21xx.c create mode 100644 drivers/media/dvb/frontends/si21xx.h diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index 4b96bbba9f4..2af5fffe138 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -4,6 +4,7 @@ config DVB_DM1105 select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE + select DVB_SI21XX if !DVB_FE_CUSTOMISE help Support for cards based on the SDMC DM1105 PCI chip like DvbWorld 2002 diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 204763d2de4..0c1790fe2b5 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -40,8 +40,8 @@ #include "stv0299.h" /*#include "stv0288.h" - *#include "si21xx.h" *#include "stb6000.h"*/ +#include "si21xx.h" #include "cx24116.h" #include "z0194a.h" @@ -600,12 +600,12 @@ static struct stv0288_config earda_config = { .min_delay_ms = 100, }; +#endif /* keep */ static struct si21xx_config serit_config = { .demod_address = 0x68, .min_delay_ms = 100, }; -#endif /* keep */ static struct cx24116_config serit_sp2633_config = { .demod_address = 0x55, @@ -639,7 +639,7 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) &dm1105dvb->i2c_adap); } } - +#endif /* keep */ if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach( si21xx_attach, &serit_config, @@ -648,7 +648,6 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; } -#endif /* keep */ break; case PCI_DEVICE_ID_DW2004: dm1105dvb->fe = dvb_attach( diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index d2f31da26cb..7697391ca86 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -99,6 +99,13 @@ config DVB_CX24116 help A DVB-S/S2 tuner module. Say Y when you want to support this frontend. +config DVB_SI21XX + tristate "Silicon Labs SI21XX based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 5deb8a542ab..c719b7fdce4 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o +obj-$(CONFIG_DVB_SI21XX) += si21xx.o diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c new file mode 100644 index 00000000000..3ddbe69c45c --- /dev/null +++ b/drivers/media/dvb/frontends/si21xx.c @@ -0,0 +1,974 @@ +/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator +* +* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "si21xx.h" + +#define REVISION_REG 0x00 +#define SYSTEM_MODE_REG 0x01 +#define TS_CTRL_REG_1 0x02 +#define TS_CTRL_REG_2 0x03 +#define PIN_CTRL_REG_1 0x04 +#define PIN_CTRL_REG_2 0x05 +#define LOCK_STATUS_REG_1 0x0f +#define LOCK_STATUS_REG_2 0x10 +#define ACQ_STATUS_REG 0x11 +#define ACQ_CTRL_REG_1 0x13 +#define ACQ_CTRL_REG_2 0x14 +#define PLL_DIVISOR_REG 0x15 +#define COARSE_TUNE_REG 0x16 +#define FINE_TUNE_REG_L 0x17 +#define FINE_TUNE_REG_H 0x18 + +#define ANALOG_AGC_POWER_LEVEL_REG 0x28 +#define CFO_ESTIMATOR_CTRL_REG_1 0x29 +#define CFO_ESTIMATOR_CTRL_REG_2 0x2a +#define CFO_ESTIMATOR_CTRL_REG_3 0x2b + +#define SYM_RATE_ESTIMATE_REG_L 0x31 +#define SYM_RATE_ESTIMATE_REG_M 0x32 +#define SYM_RATE_ESTIMATE_REG_H 0x33 + +#define CFO_ESTIMATOR_OFFSET_REG_L 0x36 +#define CFO_ESTIMATOR_OFFSET_REG_H 0x37 +#define CFO_ERROR_REG_L 0x38 +#define CFO_ERROR_REG_H 0x39 +#define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a + +#define SYM_RATE_REG_L 0x3f +#define SYM_RATE_REG_M 0x40 +#define SYM_RATE_REG_H 0x41 +#define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42 +#define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43 + +#define C_N_ESTIMATOR_CTRL_REG 0x7c +#define C_N_ESTIMATOR_THRSHLD_REG 0x7d +#define C_N_ESTIMATOR_LEVEL_REG_L 0x7e +#define C_N_ESTIMATOR_LEVEL_REG_H 0x7f + +#define BLIND_SCAN_CTRL_REG 0x80 + +#define LSA_CTRL_REG_1 0x8D +#define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f +#define ONE_DB_BNDWDTH_THRSHLD_REG 0x90 +#define TWO_DB_BNDWDTH_THRSHLD_REG 0x91 +#define THREE_DB_BNDWDTH_THRSHLD_REG 0x92 +#define INBAND_POWER_THRSHLD_REG 0x93 +#define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94 + +#define VIT_SRCH_CTRL_REG_1 0xa0 +#define VIT_SRCH_CTRL_REG_2 0xa1 +#define VIT_SRCH_CTRL_REG_3 0xa2 +#define VIT_SRCH_STATUS_REG 0xa3 +#define VITERBI_BER_COUNT_REG_L 0xab +#define REED_SOLOMON_CTRL_REG 0xb0 +#define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1 +#define PRBS_CTRL_REG 0xb5 + +#define LNB_CTRL_REG_1 0xc0 +#define LNB_CTRL_REG_2 0xc1 +#define LNB_CTRL_REG_3 0xc2 +#define LNB_CTRL_REG_4 0xc3 +#define LNB_CTRL_STATUS_REG 0xc4 +#define LNB_FIFO_REGS_0 0xc5 +#define LNB_FIFO_REGS_1 0xc6 +#define LNB_FIFO_REGS_2 0xc7 +#define LNB_FIFO_REGS_3 0xc8 +#define LNB_FIFO_REGS_4 0xc9 +#define LNB_FIFO_REGS_5 0xca +#define LNB_SUPPLY_CTRL_REG_1 0xcb +#define LNB_SUPPLY_CTRL_REG_2 0xcc +#define LNB_SUPPLY_CTRL_REG_3 0xcd +#define LNB_SUPPLY_CTRL_REG_4 0xce +#define LNB_SUPPLY_STATUS_REG 0xcf + +#define FALSE 0 +#define TRUE 1 +#define FAIL -1 +#define PASS 0 + +#define ALLOWABLE_FS_COUNT 10 +#define STATUS_BER 0 +#define STATUS_UCBLOCKS 1 + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "si21xx: " args); \ + } while (0) + +enum { + ACTIVE_HIGH, + ACTIVE_LOW +}; +enum { + BYTE_WIDE, + BIT_WIDE +}; +enum { + CLK_GAPPED_MODE, + CLK_CONTINUOUS_MODE +}; +enum { + RISING_EDGE, + FALLING_EDGE +}; +enum { + MSB_FIRST, + LSB_FIRST +}; +enum { + SERIAL, + PARALLEL +}; + +struct si21xx_state { + struct i2c_adapter *i2c; + const struct si21xx_config *config; + struct dvb_frontend frontend; + u8 initialised:1; + int errmode; + int fs; /*Sampling rate of the ADC in MHz*/ +}; + +/* register default initialization */ +static u8 serit_sp1511lhb_inittab[] = { + 0x01, 0x28, /* set i2c_inc_disable */ + 0x20, 0x03, + 0x27, 0x20, + 0xe0, 0x45, + 0xe1, 0x08, + 0xfe, 0x01, + 0x01, 0x28, + 0x89, 0x09, + 0x04, 0x80, + 0x05, 0x01, + 0x06, 0x00, + 0x20, 0x03, + 0x24, 0x88, + 0x29, 0x09, + 0x2a, 0x0f, + 0x2c, 0x10, + 0x2d, 0x19, + 0x2e, 0x08, + 0x2f, 0x10, + 0x30, 0x19, + 0x34, 0x20, + 0x35, 0x03, + 0x45, 0x02, + 0x46, 0x45, + 0x47, 0xd0, + 0x48, 0x00, + 0x49, 0x40, + 0x4a, 0x03, + 0x4c, 0xfd, + 0x4f, 0x2e, + 0x50, 0x2e, + 0x51, 0x10, + 0x52, 0x10, + 0x56, 0x92, + 0x59, 0x00, + 0x5a, 0x2d, + 0x5b, 0x33, + 0x5c, 0x1f, + 0x5f, 0x76, + 0x62, 0xc0, + 0x63, 0xc0, + 0x64, 0xf3, + 0x65, 0xf3, + 0x79, 0x40, + 0x6a, 0x40, + 0x6b, 0x0a, + 0x6c, 0x80, + 0x6d, 0x27, + 0x71, 0x06, + 0x75, 0x60, + 0x78, 0x00, + 0x79, 0xb5, + 0x7c, 0x05, + 0x7d, 0x1a, + 0x87, 0x55, + 0x88, 0x72, + 0x8f, 0x08, + 0x90, 0xe0, + 0x94, 0x40, + 0xa0, 0x3f, + 0xa1, 0xc0, + 0xa4, 0xcc, + 0xa5, 0x66, + 0xa6, 0x66, + 0xa7, 0x7b, + 0xa8, 0x7b, + 0xa9, 0x7b, + 0xaa, 0x9a, + 0xed, 0x04, + 0xad, 0x00, + 0xae, 0x03, + 0xcc, 0xab, + 0x01, 0x08, + 0xff, 0xff +}; + +/* low level read/writes */ +static int si21_writeregs(struct si21xx_state *state, u8 reg1, + u8 *data, int len) +{ + int ret; + u8 buf[60];/* = { reg1, data };*/ + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = len + 1 + }; + + msg.buf[0] = reg1; + memcpy(msg.buf + 1, data, len); + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, " + "ret == %i)\n", __func__, reg1, data[0], ret); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, " + "ret == %i)\n", __func__, reg, data, ret); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int si21_write(struct dvb_frontend *fe, u8 *buf, int len) +{ + struct si21xx_state *state = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return si21_writereg(state, buf[0], buf[1]); +} + +static u8 si21_readreg(struct si21xx_state *state, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + }, { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", + __func__, reg, ret); + + return b1[0]; +} + +static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len) +{ + int ret; + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = ®1, + .len = 1 + }, { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b, + .len = len + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __func__, ret); + + return ret == 2 ? 0 : -1; +} + +static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout) +{ + unsigned long start = jiffies; + + dprintk("%s\n", __func__); + + while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) { + if (jiffies - start > timeout) { + dprintk("%s: timeout!!\n", __func__); + return -ETIMEDOUT; + } + msleep(10); + }; + + return 0; +} + +static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate) +{ + struct si21xx_state *state = fe->demodulator_priv; + u32 sym_rate, data_rate; + int i; + u8 sym_rate_bytes[3]; + + dprintk("%s : srate = %i\n", __func__ , srate); + + if ((srate < 1000000) || (srate > 45000000)) + return -EINVAL; + + data_rate = srate; + sym_rate = 0; + + for (i = 0; i < 4; ++i) { + sym_rate /= 100; + sym_rate = sym_rate + ((data_rate % 100) * 0x800000) / + state->fs; + data_rate /= 100; + } + for (i = 0; i < 3; ++i) + sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff); + + si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03); + + return 0; +} + +static int si21xx_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *m) +{ + struct si21xx_state *state = fe->demodulator_priv; + u8 lnb_status; + u8 LNB_CTRL_1; + int status; + + dprintk("%s\n", __func__); + + status = PASS; + LNB_CTRL_1 = 0; + + status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01); + status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01); + + /*fill the FIFO*/ + status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len); + + LNB_CTRL_1 = (lnb_status & 0x70); + LNB_CTRL_1 |= m->msg_len; + + LNB_CTRL_1 |= 0x80; /* begin LNB signaling */ + + status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01); + + return status; +} + +static int si21xx_send_diseqc_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t burst) +{ + struct si21xx_state *state = fe->demodulator_priv; + u8 val; + + dprintk("%s\n", __func__); + + if (si21xx_wait_diseqc_idle(state, 100) < 0) + return -ETIMEDOUT; + + val = (0x80 | si21_readreg(state, 0xc1)); + if (si21_writereg(state, LNB_CTRL_REG_1, + burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10))) + return -EREMOTEIO; + + if (si21xx_wait_diseqc_idle(state, 100) < 0) + return -ETIMEDOUT; + + if (si21_writereg(state, LNB_CTRL_REG_1, val)) + return -EREMOTEIO; + + return 0; +} +/* 30.06.2008 */ +static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct si21xx_state *state = fe->demodulator_priv; + u8 val; + + dprintk("%s\n", __func__); + val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); + + switch (tone) { + case SEC_TONE_ON: + return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20); + + case SEC_TONE_OFF: + return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20)); + + default: + return -EINVAL; + } +} + +static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) +{ + struct si21xx_state *state = fe->demodulator_priv; + + u8 val; + dprintk("%s: %s\n", __func__, + volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : + volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); + + + val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); + + switch (volt) { + case SEC_VOLTAGE_18: + return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40); + break; + case SEC_VOLTAGE_13: + return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40)); + break; + default: + return -EINVAL; + }; +} + +static int si21xx_init(struct dvb_frontend *fe) +{ + struct si21xx_state *state = fe->demodulator_priv; + int i; + int status = 0; + u8 reg1; + u8 val; + u8 reg2[2]; + + dprintk("%s\n", __func__); + + for (i = 0; ; i += 2) { + reg1 = serit_sp1511lhb_inittab[i]; + val = serit_sp1511lhb_inittab[i+1]; + if (reg1 == 0xff && val == 0xff) + break; + si21_writeregs(state, reg1, &val, 1); + } + + /*DVB QPSK SYSTEM MODE REG*/ + reg1 = 0x08; + si21_writeregs(state, SYSTEM_MODE_REG, ®1, 0x01); + + /*transport stream config*/ + /* + mode = PARALLEL; + sdata_form = LSB_FIRST; + clk_edge = FALLING_EDGE; + clk_mode = CLK_GAPPED_MODE; + strt_len = BYTE_WIDE; + sync_pol = ACTIVE_HIGH; + val_pol = ACTIVE_HIGH; + err_pol = ACTIVE_HIGH; + sclk_rate = 0x00; + parity = 0x00 ; + data_delay = 0x00; + clk_delay = 0x00; + pclk_smooth = 0x00; + */ + reg2[0] = + PARALLEL + (LSB_FIRST << 1) + + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3) + + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5) + + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7); + + reg2[1] = 0; + /* sclk_rate + (parity << 2) + + (data_delay << 3) + (clk_delay << 4) + + (pclk_smooth << 5); + */ + status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02); + if (status != 0) + dprintk(" %s : TS Set Error\n", __func__); + + return 0; + +} + +static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct si21xx_state *state = fe->demodulator_priv; + u8 regs_read[2]; + u8 reg_read; + u8 i; + u8 lock; + u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG); + + si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02); + reg_read = 0; + + for (i = 0; i < 7; ++i) + reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i); + + lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80)); + + dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock); + *status = 0; + + if (signal > 10) + *status |= FE_HAS_SIGNAL; + + if (lock & 0x2) + *status |= FE_HAS_CARRIER; + + if (lock & 0x20) + *status |= FE_HAS_VITERBI; + + if (lock & 0x40) + *status |= FE_HAS_SYNC; + + if ((lock & 0x7b) == 0x7b) + *status |= FE_HAS_LOCK; + + return 0; +} + +static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct si21xx_state *state = fe->demodulator_priv; + + /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG, + (u8*)agclevel, 0x01);*/ + + u16 signal = (3 * si21_readreg(state, 0x27) * + si21_readreg(state, 0x28)); + + dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__, + si21_readreg(state, 0x27), + si21_readreg(state, 0x28), (int) signal); + + signal <<= 4; + *strength = signal; + + return 0; +} + +static int si21_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct si21xx_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + if (state->errmode != STATUS_BER) + return 0; + + *ber = (si21_readreg(state, 0x1d) << 8) | + si21_readreg(state, 0x1e); + + return 0; +} + +static int si21_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct si21xx_state *state = fe->demodulator_priv; + + s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) | + si21_readreg(state, 0x25)); + xsnr = 3 * (xsnr - 0xa100); + *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; + + dprintk("%s\n", __func__); + + return 0; +} + +static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct si21xx_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + if (state->errmode != STATUS_UCBLOCKS) + *ucblocks = 0; + else + *ucblocks = (si21_readreg(state, 0x1d) << 8) | + si21_readreg(state, 0x1e); + + return 0; +} + +/* initiates a channel acquisition sequence + using the specified symbol rate and code rate */ +static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate, + fe_code_rate_t crate) +{ + + struct si21xx_state *state = fe->demodulator_priv; + u8 coderates[] = { + 0x0, 0x01, 0x02, 0x04, 0x00, + 0x8, 0x10, 0x20, 0x00, 0x3f + }; + + u8 coderate_ptr; + int status; + u8 start_acq = 0x80; + u8 reg, regs[3]; + + dprintk("%s\n", __func__); + + status = PASS; + coderate_ptr = coderates[crate]; + + si21xx_set_symbolrate(fe, symbrate); + + /* write code rates to use in the Viterbi search */ + status |= si21_writeregs(state, + VIT_SRCH_CTRL_REG_1, + &coderate_ptr, 0x01); + + /* clear acq_start bit */ + status |= si21_readregs(state, ACQ_CTRL_REG_2, ®, 0x01); + reg &= ~start_acq; + status |= si21_writeregs(state, ACQ_CTRL_REG_2, ®, 0x01); + + /* use new Carrier Frequency Offset Estimator (QuickLock) */ + regs[0] = 0xCB; + regs[1] = 0x40; + regs[2] = 0xCB; + + status |= si21_writeregs(state, + TWO_DB_BNDWDTH_THRSHLD_REG, + ®s[0], 0x03); + reg = 0x56; + status |= si21_writeregs(state, + LSA_CTRL_REG_1, ®, 1); + reg = 0x05; + status |= si21_writeregs(state, + BLIND_SCAN_CTRL_REG, ®, 1); + /* start automatic acq */ + status |= si21_writeregs(state, + ACQ_CTRL_REG_2, &start_acq, 0x01); + + return status; +} + +static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int si21xx_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *dfp) +{ + struct si21xx_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz) + datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/ + + /* in MHz */ + unsigned char coarse_tune_freq; + int fine_tune_freq; + unsigned char sample_rate = 0; + /* boolean */ + unsigned int inband_interferer_ind; + + /* INTERMEDIATE VALUES */ + int icoarse_tune_freq; /* MHz */ + int ifine_tune_freq; /* MHz */ + unsigned int band_high; + unsigned int band_low; + unsigned int x1; + unsigned int x2; + int i; + unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = { + FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE + }; + unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = { + FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE + }; + + int status; + + /* allowable sample rates for ADC in MHz */ + int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195, + 196, 204, 205, 206, 207 + }; + /* in MHz */ + int if_limit_high; + int if_limit_low; + int lnb_lo; + int lnb_uncertanity; + + int rf_freq; + int data_rate; + unsigned char regs[4]; + + dprintk("%s : FE_SET_FRONTEND\n", __func__); + + if (c->delivery_system != SYS_DVBS) { + dprintk("%s: unsupported delivery system selected (%d)\n", + __func__, c->delivery_system); + return -EOPNOTSUPP; + } + + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) + inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE; + + if_limit_high = -700000; + if_limit_low = -100000; + /* in MHz */ + lnb_lo = 0; + lnb_uncertanity = 0; + + rf_freq = 10 * c->frequency ; + data_rate = c->symbol_rate / 100; + + status = PASS; + + band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200) + + (data_rate * 135)) / 200; + + band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200) + + (data_rate * 135)) / 200; + + + icoarse_tune_freq = 100000 * + (((rf_freq - lnb_lo) - + (if_limit_low + if_limit_high) / 2) + / 100000); + + ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ; + + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { + x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * + (afs[i] * 2500) + afs[i] * 2500; + + x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * + (afs[i] * 2500); + + if (((band_low < x1) && (x1 < band_high)) || + ((band_low < x2) && (x2 < band_high))) + inband_interferer_div4[i] = TRUE; + + } + + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { + x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * + (afs[i] * 5000) + afs[i] * 5000; + + x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * + (afs[i] * 5000); + + if (((band_low < x1) && (x1 < band_high)) || + ((band_low < x2) && (x2 < band_high))) + inband_interferer_div2[i] = TRUE; + } + + inband_interferer_ind = TRUE; + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) + inband_interferer_ind &= inband_interferer_div2[i] | + inband_interferer_div4[i]; + + if (inband_interferer_ind) { + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { + if (inband_interferer_div2[i] == FALSE) { + sample_rate = (u8) afs[i]; + break; + } + } + } else { + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { + if ((inband_interferer_div2[i] | + inband_interferer_div4[i]) == FALSE) { + sample_rate = (u8) afs[i]; + break; + } + } + + } + + if (sample_rate > 207 || sample_rate < 192) + sample_rate = 200; + + fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) / + ((sample_rate) * 1000)); + + coarse_tune_freq = (u8)(icoarse_tune_freq / 100000); + + regs[0] = sample_rate; + regs[1] = coarse_tune_freq; + regs[2] = fine_tune_freq & 0xFF; + regs[3] = fine_tune_freq >> 8 & 0xFF; + + status |= si21_writeregs(state, PLL_DIVISOR_REG, ®s[0], 0x04); + + state->fs = sample_rate;/*ADC MHz*/ + si21xx_setacquire(fe, c->symbol_rate, c->fec_inner); + + return 0; +} + +static int si21xx_sleep(struct dvb_frontend *fe) +{ + struct si21xx_state *state = fe->demodulator_priv; + u8 regdata; + + dprintk("%s\n", __func__); + + si21_readregs(state, SYSTEM_MODE_REG, ®data, 0x01); + regdata |= 1 << 6; + si21_writeregs(state, SYSTEM_MODE_REG, ®data, 0x01); + state->initialised = 0; + + return 0; +} + +static void si21xx_release(struct dvb_frontend *fe) +{ + struct si21xx_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + kfree(state); +} + +static struct dvb_frontend_ops si21xx_ops = { + + .info = { + .name = "SL SI21XX DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + + .release = si21xx_release, + .init = si21xx_init, + .sleep = si21xx_sleep, + .write = si21_write, + .read_status = si21_read_status, + .read_ber = si21_read_ber, + .read_signal_strength = si21_read_signal_strength, + .read_snr = si21_read_snr, + .read_ucblocks = si21_read_ucblocks, + .diseqc_send_master_cmd = si21xx_send_diseqc_msg, + .diseqc_send_burst = si21xx_send_diseqc_burst, + .set_tone = si21xx_set_tone, + .set_voltage = si21xx_set_voltage, + + .set_property = si21xx_set_property, + .get_property = si21xx_get_property, + .set_frontend = si21xx_set_frontend, +}; + +struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, + struct i2c_adapter *i2c) +{ + struct si21xx_state *state = NULL; + int id; + + dprintk("%s\n", __func__); + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + state->initialised = 0; + state->errmode = STATUS_BER; + + /* check if the demod is there */ + id = si21_readreg(state, SYSTEM_MODE_REG); + si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */ + msleep(200); + id = si21_readreg(state, 0x00); + + /* register 0x00 contains: + 0x34 for SI2107 + 0x24 for SI2108 + 0x14 for SI2109 + 0x04 for SI2110 + */ + if (id != 0x04 && id != 0x14) + goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &si21xx_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(si21xx_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver"); +MODULE_AUTHOR("Igor M. Liplianin"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb/frontends/si21xx.h new file mode 100644 index 00000000000..141b5b8a5f6 --- /dev/null +++ b/drivers/media/dvb/frontends/si21xx.h @@ -0,0 +1,37 @@ +#ifndef SI21XX_H +#define SI21XX_H + +#include +#include "dvb_frontend.h" + +struct si21xx_config { + /* the demodulator's i2c address */ + u8 demod_address; + + /* minimum delay before retuning */ + int min_delay_ms; +}; + +#if defined(CONFIG_DVB_SI21XX) || \ + (defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE)) +extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *si21xx_attach( + const struct si21xx_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val) +{ + int r = 0; + u8 buf[] = {reg, val}; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 2); + return r; +} + +#endif -- GitLab From 21b007b94c714cda3ebf0fa5b4e40342d2444f79 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 17 Sep 2008 19:19:19 -0300 Subject: [PATCH 4131/5416] V4L/DVB (9018): Add support for USB card modification with SI2109/2110 demodulator. Add support for USB card modification with SI2109/2110 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 260 +++++++++++++++++++---------- 1 file changed, 173 insertions(+), 87 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index ad3d6fca9ab..20ba3f12900 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -11,6 +11,7 @@ */ #include #include "dw2102.h" +#include "si21xx.h" #include "stv0299.h" #include "z0194a.h" #include "cx24116.h" @@ -23,8 +24,8 @@ #define USB_PID_DW2104 0x2104 #endif -#define DW2102_READ_MSG 0 -#define DW2102_WRITE_MSG 1 +#define DW210X_READ_MSG 0 +#define DW210X_WRITE_MSG 1 #define REG_1F_SYMBOLRATE_BYTE0 0x1f #define REG_20_SYMBOLRATE_BYTE1 0x20 @@ -33,10 +34,10 @@ #define DW2102_VOLTAGE_CTRL (0x1800) #define DW2102_RC_QUERY (0x1a00) -struct dw2102_state { +struct dw210x_state { u32 last_key_pressed; }; -struct dw2102_rc_keys { +struct dw210x_rc_keys { u32 keycode; u32 event; }; @@ -48,28 +49,27 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value, +static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, u16 index, u8 * data, u16 len, int flags) { int ret; u8 u8buf[len]; - unsigned int pipe = (flags == DW2102_READ_MSG) ? + unsigned int pipe = (flags == DW210X_READ_MSG) ? usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); - u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; + u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; - if (flags == DW2102_WRITE_MSG) + if (flags == DW210X_WRITE_MSG) memcpy(u8buf, data, len); ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, value, index , u8buf, len, 2000); - if (flags == DW2102_READ_MSG) + if (flags == DW210X_READ_MSG) memcpy(data, u8buf, len); return ret; } /* I2C */ - static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { @@ -89,10 +89,9 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); value = msg[0].buf[0];/* register */ for (i = 0; i < msg[1].len; i++) { value = value + i; - ret = dw2102_op_rw(d->udev, 0xb5, value, 0, - buf6, 2, DW2102_READ_MSG); + ret = dw210x_op_rw(d->udev, 0xb5, value, 0, + buf6, 2, DW210X_READ_MSG); msg[1].buf[i] = buf6[0]; - } break; case 1: @@ -102,8 +101,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); buf6[0] = 0x2a; buf6[1] = msg[0].buf[0]; buf6[2] = msg[0].buf[1]; - ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, - buf6, 3, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, + buf6, 3, DW210X_WRITE_MSG); break; case 0x60: if (msg[0].flags == 0) { @@ -115,26 +114,26 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); buf6[4] = msg[0].buf[1]; buf6[5] = msg[0].buf[2]; buf6[6] = msg[0].buf[3]; - ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, - buf6, 7, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, + buf6, 7, DW210X_WRITE_MSG); } else { /* read from tuner */ - ret = dw2102_op_rw(d->udev, 0xb5, 0,0, - buf6, 1, DW2102_READ_MSG); + ret = dw210x_op_rw(d->udev, 0xb5, 0, 0, + buf6, 1, DW210X_READ_MSG); msg[0].buf[0] = buf6[0]; } break; case (DW2102_RC_QUERY): - ret = dw2102_op_rw(d->udev, 0xb8, 0, 0, - buf6, 2, DW2102_READ_MSG); + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + buf6, 2, DW210X_READ_MSG); msg[0].buf[0] = buf6[0]; msg[0].buf[1] = buf6[1]; break; case (DW2102_VOLTAGE_CTRL): buf6[0] = 0x30; buf6[1] = msg[0].buf[0]; - ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, - buf6, 2, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, + buf6, 2, DW210X_WRITE_MSG); break; } @@ -145,6 +144,62 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); return num; } +static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, + struct i2c_msg msg[], int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0; + u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + switch (num) { + case 2: + /* read si2109 register by number */ + buf6[0] = 0xd0; + buf6[1] = msg[0].len; + buf6[2] = msg[0].buf[0]; + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + buf6, msg[0].len + 2, DW210X_WRITE_MSG); + /* read si2109 register */ + ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, + buf6, msg[1].len + 2, DW210X_READ_MSG); + memcpy(msg[1].buf, buf6 + 2, msg[1].len); + + break; + case 1: + switch (msg[0].addr) { + case 0x68: + /* write to si2109 register */ + buf6[0] = 0xd0; + buf6[1] = msg[0].len; + memcpy(buf6 + 2, msg[0].buf, msg[0].len); + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, + msg[0].len + 2, DW210X_WRITE_MSG); + break; + case(DW2102_RC_QUERY): + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + buf6, 2, DW210X_READ_MSG); + msg[0].buf[0] = buf6[0]; + msg[0].buf[1] = buf6[1]; + break; + case(DW2102_VOLTAGE_CTRL): + buf6[0] = 0x30; + buf6[1] = msg[0].buf[0]; + ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, + buf6, 2, DW210X_WRITE_MSG); + break; + } + break; + } + + mutex_unlock(&d->i2c_mutex); + return num; +} + static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); @@ -164,11 +219,11 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i obuf[0] = 0xaa; obuf[1] = msg[0].len; obuf[2] = msg[0].buf[0]; - ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, - obuf, msg[0].len + 2, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); /* second read registers */ - ret = dw2102_op_rw(d->udev, 0xc3, 0xab , 0, - ibuf, msg[1].len + 2, DW2102_READ_MSG); + ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0, + ibuf, msg[1].len + 2, DW210X_READ_MSG); memcpy(msg[1].buf, ibuf + 2, msg[1].len); break; @@ -187,8 +242,8 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i i = 1; do { memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); - ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, - obuf, (len > 16 ? 16 : len) + 3, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG); i += 16; len -= 16; } while (len > 0); @@ -198,15 +253,15 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i obuf[0] = 0xaa; obuf[1] = msg[0].len; memcpy(obuf + 2, msg[0].buf, msg[0].len); - ret = dw2102_op_rw(d->udev, 0xc2, 0, 0, - obuf, msg[0].len + 2, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); } break; } case(DW2102_RC_QUERY): { u8 ibuf[2]; - ret = dw2102_op_rw(d->udev, 0xb8, 0, 0, - ibuf, 2, DW2102_READ_MSG); + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + ibuf, 2, DW210X_READ_MSG); memcpy(msg[0].buf, ibuf , 2); break; } @@ -214,8 +269,8 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i u8 obuf[2]; obuf[0] = 0x30; obuf[1] = msg[0].buf[0]; - ret = dw2102_op_rw(d->udev, 0xb2, 0, 0, - obuf, 2, DW2102_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, + obuf, 2, DW210X_WRITE_MSG); break; } } @@ -227,29 +282,34 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i return num; } -static u32 dw2102_i2c_func(struct i2c_adapter *adapter) +static u32 dw210x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } static struct i2c_algorithm dw2102_i2c_algo = { .master_xfer = dw2102_i2c_transfer, - .functionality = dw2102_i2c_func, + .functionality = dw210x_i2c_func, +}; + +static struct i2c_algorithm dw2102_serit_i2c_algo = { + .master_xfer = dw2102_serit_i2c_transfer, + .functionality = dw210x_i2c_func, }; static struct i2c_algorithm dw2104_i2c_algo = { .master_xfer = dw2104_i2c_transfer, - .functionality = dw2102_i2c_func, + .functionality = dw210x_i2c_func, }; -static int dw2102_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) { int i; u8 ibuf[] = {0, 0}; u8 eeprom[256], eepromline[16]; for (i = 0; i < 256; i++) { - if (dw2102_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW2102_READ_MSG) < 0) { + if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { err("read eeprom failed."); return -1; } else { @@ -265,7 +325,7 @@ static int dw2102_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) return 0; }; -static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { static u8 command_13v[1] = {0x00}; static u8 command_18v[1] = {0x01}; @@ -287,25 +347,46 @@ static struct cx24116_config dw2104_config = { .mpg_clk_pos_pol = 0x01, }; +static struct si21xx_config serit_sp1511lhb_config = { + .demod_address = 0x68, + .min_delay_ms = 100, + +}; + static int dw2104_frontend_attach(struct dvb_usb_adapter *d) { if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, &d->dev->i2c_adap)) != NULL) { - d->fe->ops.set_voltage = dw2102_set_voltage; + d->fe->ops.set_voltage = dw210x_set_voltage; info("Attached cx24116!\n"); return 0; } return -EIO; } +static struct dvb_usb_device_properties dw2102_properties; + static int dw2102_frontend_attach(struct dvb_usb_adapter *d) { - d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, - &d->dev->i2c_adap); - if (d->fe != NULL) { - d->fe->ops.set_voltage = dw2102_set_voltage; - info("Attached stv0299!\n"); - return 0; + if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { + /*dw2102_properties.adapter->tuner_attach = NULL;*/ + d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, + &d->dev->i2c_adap); + if (d->fe != NULL) { + d->fe->ops.set_voltage = dw210x_set_voltage; + info("Attached si21xx!\n"); + return 0; + } + } + if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { + /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ + d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, + &d->dev->i2c_adap); + if (d->fe != NULL) { + d->fe->ops.set_voltage = dw210x_set_voltage; + info("Attached stv0299!\n"); + return 0; + } } return -EIO; } @@ -317,7 +398,7 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static struct dvb_usb_rc_key dw2102_rc_keys[] = { +static struct dvb_usb_rc_key dw210x_rc_keys[] = { { 0xf8, 0x0a, KEY_Q }, /*power*/ { 0xf8, 0x0c, KEY_M }, /*mute*/ { 0xf8, 0x11, KEY_1 }, @@ -356,7 +437,7 @@ static struct dvb_usb_rc_key dw2102_rc_keys[] = { static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct dw2102_state *st = d->priv; + struct dw210x_state *st = d->priv; u8 key[2]; struct i2c_msg msg[] = { {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, @@ -366,12 +447,12 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { - for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) { - if (dw2102_rc_keys[i].data == msg[0].buf[0]) { + for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { + if (dw210x_rc_keys[i].data == msg[0].buf[0]) { *state = REMOTE_KEY_PRESSED; - *event = dw2102_rc_keys[i].event; + *event = dw210x_rc_keys[i].event; st->last_key_pressed = - dw2102_rc_keys[i].event; + dw210x_rc_keys[i].event; break; } st->last_key_pressed = 0; @@ -418,15 +499,15 @@ static int dw2102_load_firmware(struct usb_device *dev, p = kmalloc(fw->size, GFP_KERNEL); reset = 1; /*stop the CPU*/ - dw2102_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW2102_WRITE_MSG); - dw2102_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW2102_WRITE_MSG); + dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); + dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); if (p != NULL) { memcpy(p, fw->data, fw->size); for (i = 0; i < fw->size; i += 0x40) { b = (u8 *) p + i; - if (dw2102_op_rw(dev, 0xa0, i, 0, b , 0x40, - DW2102_WRITE_MSG) != 0x40) { + if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, + DW210X_WRITE_MSG) != 0x40) { err("error while transferring firmware"); ret = -EINVAL; break; @@ -434,13 +515,13 @@ static int dw2102_load_firmware(struct usb_device *dev, } /* restart the CPU */ reset = 0; - if (ret || dw2102_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, - DW2102_WRITE_MSG) != 1) { + if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, + DW210X_WRITE_MSG) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } - if (ret || dw2102_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, - DW2102_WRITE_MSG) != 1) { + if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, + DW210X_WRITE_MSG) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } @@ -449,27 +530,32 @@ static int dw2102_load_firmware(struct usb_device *dev, case USB_PID_DW2104: case 0xd650: reset = 1; - dw2102_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, - DW2102_WRITE_MSG); + dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, + DW210X_WRITE_MSG); reset = 0; - dw2102_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, - DW2102_WRITE_MSG); + dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, + DW210X_WRITE_MSG); break; case USB_PID_DW2102: - dw2102_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, - DW2102_WRITE_MSG); - dw2102_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, - DW2102_READ_MSG); + dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, + DW210X_WRITE_MSG); + dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, + DW210X_READ_MSG); + /* check STV0299 frontend */ + dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, + DW210X_READ_MSG); + if (reset16[0] == 0xa1) + dw2102_properties.i2c_algo = &dw2102_i2c_algo; break; case 0x2101: - dw2102_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, - DW2102_READ_MSG); - dw2102_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, - DW2102_READ_MSG); - dw2102_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, - DW2102_READ_MSG); - dw2102_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, - DW2102_READ_MSG); + dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, + DW210X_READ_MSG); + dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, + DW210X_READ_MSG); + dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, + DW210X_READ_MSG); + dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, + DW210X_READ_MSG); break; } msleep(100); @@ -482,12 +568,12 @@ static struct dvb_usb_device_properties dw2102_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-dw2102.fw", - .size_of_priv = sizeof(struct dw2102_state), + .size_of_priv = sizeof(struct dw210x_state), .no_reconnect = 1, - .i2c_algo = &dw2102_i2c_algo, - .rc_key_map = dw2102_rc_keys, - .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys), + .i2c_algo = &dw2102_serit_i2c_algo, + .rc_key_map = dw210x_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), .rc_interval = 150, .rc_query = dw2102_rc_query, @@ -495,7 +581,7 @@ static struct dvb_usb_device_properties dw2102_properties = { /* parameter for the MPEG2-data transfer */ .num_adapters = 1, .download_firmware = dw2102_load_firmware, - .read_mac_address = dw2102_read_mac_address, + .read_mac_address = dw210x_read_mac_address, .adapter = { { .frontend_attach = dw2102_frontend_attach, @@ -530,12 +616,12 @@ static struct dvb_usb_device_properties dw2104_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-dw2104.fw", - .size_of_priv = sizeof(struct dw2102_state), + .size_of_priv = sizeof(struct dw210x_state), .no_reconnect = 1, .i2c_algo = &dw2104_i2c_algo, - .rc_key_map = dw2102_rc_keys, - .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys), + .rc_key_map = dw210x_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), .rc_interval = 150, .rc_query = dw2102_rc_query, @@ -543,7 +629,7 @@ static struct dvb_usb_device_properties dw2104_properties = { /* parameter for the MPEG2-data transfer */ .num_adapters = 1, .download_firmware = dw2102_load_firmware, - .read_mac_address = dw2102_read_mac_address, + .read_mac_address = dw210x_read_mac_address, .adapter = { { .frontend_attach = dw2104_frontend_attach, -- GitLab From 4cd7fb876ce0beecd4907f81d1a16ea95f5d6d6e Mon Sep 17 00:00:00 2001 From: Oleg Roitburd Date: Wed, 17 Sep 2008 11:30:21 -0300 Subject: [PATCH 4132/5416] V4L/DVB (9019): Added support for Omicom SS4 DVB-S/S2 card Added support for Omicom SS4 DVB-S/S2 card. The card based on cx24116 demodulator. Signed-off-by: Oleg Roitburd Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 22 ++++++++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 9 +++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 32 insertions(+) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 23948daae85..afaafd519ea 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1721,6 +1721,18 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_OMICOM_SS4_PCI] = { + .name = "Omicom SS4 DVB-S/S2 PCI", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2094,6 +2106,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xD460, .subdevice = 0x9022, .card = CX88_BOARD_TEVII_S460, + }, { + .subvendor = 0xA044, + .subdevice = 0x2011, + .card = CX88_BOARD_OMICOM_SS4_PCI, }, }; @@ -2673,6 +2689,12 @@ static void cx88_card_setup(struct cx88_core *core) cx_write(MO_SRST_IO, 1); msleep(100); break; + case CX88_BOARD_OMICOM_SS4_PCI: + cx_write(MO_SRST_IO, 0); + msleep(100); + cx_write(MO_SRST_IO, 1); + msleep(100); + break; } /*end switch() */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ce1752dc8e2..c86802b913e 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -958,6 +958,15 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; + case CX88_BOARD_OMICOM_SS4_PCI: + dev->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &core->i2c_adap); + if (dev->dvb.frontend != NULL) { + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 2b82c6aac89..628371b49c5 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -224,6 +224,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_HVR4000 68 #define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 #define CX88_BOARD_TEVII_S460 70 +#define CX88_BOARD_OMICOM_SS4_PCI 71 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From ee73042c002b435cc8bc49414d466cc3f31af123 Mon Sep 17 00:00:00 2001 From: Oleg Roitburd Date: Wed, 17 Sep 2008 11:58:33 -0300 Subject: [PATCH 4133/5416] V4L/DVB (9020): Added support for TBS 8920 DVB-S/S2 card Added support for TBS 8920 DVB-S/S2 card. The card based on cx24116 demodulator. Signed-off-by: Oleg Roitburd Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 22 ++++++++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 9 +++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 32 insertions(+) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index afaafd519ea..a0e6156bc20 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1733,6 +1733,18 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TBS_8920] = { + .name = "TBS 8920 DVB-S/S2", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 1, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2110,6 +2122,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xA044, .subdevice = 0x2011, .card = CX88_BOARD_OMICOM_SS4_PCI, + }, { + .subvendor = 0x8920, + .subdevice = 0x8888, + .card = CX88_BOARD_TBS_8920, }, }; @@ -2695,6 +2711,12 @@ static void cx88_card_setup(struct cx88_core *core) cx_write(MO_SRST_IO, 1); msleep(100); break; + case CX88_BOARD_TBS_8920: + cx_write(MO_SRST_IO, 0); + msleep(100); + cx_write(MO_SRST_IO, 1); + msleep(100); + break; } /*end switch() */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index c86802b913e..a6c4f66bb16 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -967,6 +967,15 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; + case CX88_BOARD_TBS_8920: + dev->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &core->i2c_adap); + if (dev->dvb.frontend != NULL) { + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 628371b49c5..fa3a72525d6 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -225,6 +225,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 #define CX88_BOARD_TEVII_S460 70 #define CX88_BOARD_OMICOM_SS4_PCI 71 +#define CX88_BOARD_TBS_8920 72 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From 5bacea3b9db1b88eeae5427f41efe65138f056da Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 22 Sep 2008 01:45:01 -0300 Subject: [PATCH 4134/5416] V4L/DVB (9021): S2API: Add Kconf dependency Patch provided by Darron Broad Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 ++ drivers/media/video/cx88/Kconfig | 1 + 2 files changed, 3 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index b51485c1631..8fea2975410 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -69,3 +69,5 @@ 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid [0070:6900,0070:6904,0070:6902] 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2 [0070:6905,0070:6906] 70 -> TeVii S460 DVB-S/S2 [D460:9022] + 71 -> Omicom SS4 DVB-S/S2 PCI [A044:2011] + 72 -> TBS 8920 DVB-S/S2 [8920:8888] diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 9dd7bdf659b..4f65ce3088b 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -58,6 +58,7 @@ config VIDEO_CX88_DVB select DVB_ISL6421 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE + select DVB_CX24116 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. -- GitLab From 1cbd89dbde2a473f2f3d47ae31163d80fc8ca7e7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 22 Sep 2008 01:46:26 -0300 Subject: [PATCH 4135/5416] V4L/DVB (9022): cx88: Enable TDA9887 on HVR1300 / 3000 / 4000 Patch provided by Darron Broad. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-i2c.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index d7406a994f0..8e74d64fdcd 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -201,7 +201,23 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); if (0 == core->i2c_rc) { + static u8 tuner_data[] = + { 0x0b, 0xdc, 0x86, 0x52 }; + static struct i2c_msg tuner_msg = + { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 }; + dprintk(1, "i2c register ok\n"); + switch( core->boardnr ) { + case CX88_BOARD_HAUPPAUGE_HVR1300: + case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n", + core->name); + i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1); + break; + default: + break; + } if (i2c_scan) do_i2c_scan(core->name,&core->i2c_client); } else -- GitLab From 2491fbb7d5d83ea78c6127cb589c9e6c7649e0aa Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 22 Sep 2008 01:48:13 -0300 Subject: [PATCH 4136/5416] V4L/DVB (9023): cx88: HVR3000 / 4000 GPIO related changes Patch by Darron Broad. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 55 +++++++++++++++++++++------ 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index a0e6156bc20..0203c7579a3 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1349,27 +1349,30 @@ static const struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .audio_chip = V4L2_IDENT_WM8775, + /* + * gpio0 as reported by Mike Crash + */ .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0xe780, + .gpio0 = 0xef88, .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0xe780, + .gpio0 = 0xef88, .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0xe780, + .gpio0 = 0xef88, .audioroute = 2, }}, /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, .radio = { .type = CX88_RADIO, - .gpio0 = 0xe780, + .gpio0 = 0xef88, }, }, [CX88_BOARD_ADSTECH_PTV_390] = { @@ -1680,6 +1683,26 @@ static const struct cx88_board cx88_boards[] = { * S-Video 0xc4bf 0xc4bb * Composite1 0xc4ff 0xc4fb * S-Video1 0xc4ff 0xc4fb + * + * BIT VALUE FUNCTION GP{x}_IO + * 0 1 I:? + * 1 1 I:? + * 2 1 O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH + * 3 1 I:? + * 4 1 I:? + * 5 1 I:? + * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION + * 7 1 O:DVB-T DEMOD RESET LOW + * + * BIT VALUE FUNCTION GP{x}_OE + * 8 0 I + * 9 0 I + * a 1 O + * b 0 I + * c 0 I + * d 0 I + * e 1 O + * f 1 O */ .input = {{ .type = CX88_VMUX_TELEVISION, @@ -2512,13 +2535,18 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) { switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ - /* We leave here with the 702 on the bus */ - cx_write(MO_GP0_IO, 0x0000e780); + /* + * Bring the 702 demod up before i2c scanning/attach or devices are hidden + * We leave here with the 702 on the bus + * + * "reset the IR receiver on GPIO[3]" + * Reported by Mike Crash + */ + cx_write(MO_GP0_IO, 0x0000ef88); udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); + cx_clear(MO_GP0_IO, 0x00000088); udelay(50); - cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ + cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */ udelay(1000); break; @@ -2531,15 +2559,18 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) msleep(10); break; - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: /* Enable the xc5000 tuner */ cx_set(MO_GP0_IO, 0x00001010); break; + + case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - /* Init GPIO to allow tuner to attach */ - cx_write(MO_GP0_IO, 0x0000c4bf); + /* Init GPIO */ + cx_write(MO_GP0_IO, core->board.input[0].gpio0); udelay(1000); + break; } } -- GitLab From fc6e8c284bcb23ac7a576b7959803168398e390a Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 23 Sep 2008 22:14:33 -0300 Subject: [PATCH 4137/5416] V4L/DVB (9024): S2API: Cleanup dtv_property remove unwanted fields. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/frontend.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 4f3fd641ccb..71f25f5bf37 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -358,8 +358,6 @@ struct dtv_property { __u32 cmd; __u32 reserved[3]; union { - __s32 valuemin; - __s32 valuemax; __u32 data; struct { __u8 data[32]; -- GitLab From 8316568930074723bdc47d6777f822be0422a5b7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 23 Sep 2008 22:21:26 -0300 Subject: [PATCH 4138/5416] V4L/DVB (9025): S2API: Deactivate the ISDB-T definitions We don't want to push the ISDB-T definitions into the kernel until we have a high level of confidence in the ISDB-T API. More testing is required before this code is released. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 99 ----------------------- drivers/media/dvb/dvb-core/dvb_frontend.h | 13 --- include/linux/dvb/frontend.h | 30 ------- 3 files changed, 142 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 05d0b73cf9a..7da25372078 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -829,17 +829,6 @@ struct dtv_cmds_h dtv_cmds[] = { .cmd = DTV_DELIVERY_SYSTEM, .set = 1, }, - [DTV_ISDB_SEGMENT_IDX] = { - .name = "DTV_ISDB_SEGMENT_IDX", - .cmd = DTV_ISDB_SEGMENT_IDX, - .set = 1, - }, - [DTV_ISDB_SEGMENT_WIDTH] = { - .name = "DTV_ISDB_SEGMENT_WIDTH", - .cmd = DTV_ISDB_SEGMENT_WIDTH, - .set = 1, - }, - /* Get */ [DTV_DISEQC_SLAVE_REPLY] = { .name = "DTV_DISEQC_SLAVE_REPLY", @@ -847,51 +836,6 @@ struct dtv_cmds_h dtv_cmds[] = { .set = 0, .buffer = 1, }, - [DTV_ISDB_LAYERA_FEC] = { - .name = "DTV_ISDB_LAYERA_FEC", - .cmd = DTV_ISDB_LAYERA_FEC, - .set = 0, - }, - [DTV_ISDB_LAYERA_MODULATION] = { - .name = "DTV_ISDB_LAYERA_MODULATION", - .cmd = DTV_ISDB_LAYERA_MODULATION, - .set = 0, - }, - [DTV_ISDB_LAYERA_SEGMENT_WIDTH] = { - .name = "DTV_ISDB_LAYERA_SEGMENT_WIDTH", - .cmd = DTV_ISDB_LAYERA_SEGMENT_WIDTH, - .set = 0, - }, - [DTV_ISDB_LAYERB_FEC] = { - .name = "DTV_ISDB_LAYERB_FEC", - .cmd = DTV_ISDB_LAYERB_FEC, - .set = 0, - }, - [DTV_ISDB_LAYERB_MODULATION] = { - .name = "DTV_ISDB_LAYERB_MODULATION", - .cmd = DTV_ISDB_LAYERB_MODULATION, - .set = 0, - }, - [DTV_ISDB_LAYERB_SEGMENT_WIDTH] = { - .name = "DTV_ISDB_LAYERB_SEGMENT_WIDTH", - .cmd = DTV_ISDB_LAYERB_SEGMENT_WIDTH, - .set = 0, - }, - [DTV_ISDB_LAYERC_FEC] = { - .name = "DTV_ISDB_LAYERC_FEC", - .cmd = DTV_ISDB_LAYERC_FEC, - .set = 0, - }, - [DTV_ISDB_LAYERC_MODULATION] = { - .name = "DTV_ISDB_LAYERC_MODULATION", - .cmd = DTV_ISDB_LAYERC_MODULATION, - .set = 0, - }, - [DTV_ISDB_LAYERC_SEGMENT_WIDTH] = { - .name = "DTV_ISDB_LAYERC_SEGMENT_WIDTH", - .cmd = DTV_ISDB_LAYERC_SEGMENT_WIDTH, - .set = 0, - }, }; void dtv_property_dump(struct dtv_property *tvp) @@ -1154,41 +1098,6 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_DELIVERY_SYSTEM: tvp->u.data = fe->dtv_property_cache.delivery_system; break; - - /* ISDB-T Support here */ - case DTV_ISDB_SEGMENT_IDX: - tvp->u.data = fe->dtv_property_cache.isdb_segment_idx; - break; - case DTV_ISDB_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_segment_width; - break; - case DTV_ISDB_LAYERA_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layera_fec; - break; - case DTV_ISDB_LAYERA_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layera_modulation; - break; - case DTV_ISDB_LAYERA_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layera_segment_width; - break; - case DTV_ISDB_LAYERB_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_fec; - break; - case DTV_ISDB_LAYERB_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_modulation; - break; - case DTV_ISDB_LAYERB_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layerb_segment_width; - break; - case DTV_ISDB_LAYERC_FEC: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_fec; - break; - case DTV_ISDB_LAYERC_MODULATION: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_modulation; - break; - case DTV_ISDB_LAYERC_SEGMENT_WIDTH: - tvp->u.data = fe->dtv_property_cache.isdb_layerc_segment_width; - break; case DTV_VOLTAGE: tvp->u.data = fe->dtv_property_cache.voltage; break; @@ -1266,14 +1175,6 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_DELIVERY_SYSTEM: fe->dtv_property_cache.delivery_system = tvp->u.data; break; - - /* ISDB-T Support here */ - case DTV_ISDB_SEGMENT_IDX: - fe->dtv_property_cache.isdb_segment_idx = tvp->u.data; - break; - case DTV_ISDB_SEGMENT_WIDTH: - fe->dtv_property_cache.isdb_segment_width = tvp->u.data; - break; case DTV_VOLTAGE: fe->dtv_property_cache.voltage = tvp->u.data; r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 2fa37f5a0d9..1c575402814 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -209,19 +209,6 @@ struct dtv_frontend_properties { fe_rolloff_t rolloff; fe_delivery_system_t delivery_system; - - /* ISDB-T specifics */ - u32 isdb_segment_idx; - u32 isdb_segment_width; - fe_code_rate_t isdb_layera_fec; - fe_modulation_t isdb_layera_modulation; - u32 isdb_layera_segment_width; - fe_code_rate_t isdb_layerb_fec; - fe_modulation_t isdb_layerb_modulation; - u32 isdb_layerb_segment_width; - fe_code_rate_t isdb_layerc_fec; - fe_modulation_t isdb_layerc_modulation; - u32 isdb_layerc_segment_width; }; struct dvb_frontend { diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 71f25f5bf37..c822bc156c4 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -280,36 +280,6 @@ typedef enum dtv_cmd_types { /* New commands are always appended */ DTV_DELIVERY_SYSTEM, - - /* ISDB */ - /* maybe a dup of DTV_ISDB_SOUND_BROADCASTING_SUBCHANNEL_ID ??? */ - DTV_ISDB_SEGMENT_IDX, - DTV_ISDB_SEGMENT_WIDTH, /* 1, 3 or 13 ??? */ - - /* the central segment can be received independently or 1/3 seg in SB-mode */ - DTV_ISDB_PARTIAL_RECEPTION, - /* sound broadcasting is used 0 = 13segment, 1 = 1 or 3 see DTV_ISDB_PARTIAL_RECEPTION */ - DTV_ISDB_SOUND_BROADCASTING, - - /* only used in SB */ - /* determines the initial PRBS of the segment (to match with 13seg channel) */ - DTV_ISDB_SOUND_BROADCASTING_SUBCHANNEL_ID, - - DTV_ISDB_LAYERA_FEC, - DTV_ISDB_LAYERA_MODULATION, - DTV_ISDB_LAYERA_SEGMENT_WIDTH, - DTV_ISDB_LAYERA_TIME_INTERLEAVER, - - DTV_ISDB_LAYERB_FEC, - DTV_ISDB_LAYERB_MODULATION, - DTV_ISDB_LAYERB_SEGMENT_WIDTH, - DTV_ISDB_LAYERB_TIME_INTERLEAVING, - - DTV_ISDB_LAYERC_FEC, - DTV_ISDB_LAYERC_MODULATION, - DTV_ISDB_LAYERC_SEGMENT_WIDTH, - DTV_ISDB_LAYERC_TIME_INTERLEAVING, - } dtv_cmd_types_t; typedef enum fe_pilot { -- GitLab From e4aab64cb78a42e45e1d387f272712e06cf89a66 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 23 Sep 2008 15:43:57 -0300 Subject: [PATCH 4139/5416] V4L/DVB (9026): Add support for ST STV0288 demodulator and cards with it. Add support for ST STV0288 demodulator and cards with it, such as TeVii S420. Patch is co-authored with Georg Acher Signed-off-by: Georg Acher Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 11 +- drivers/media/dvb/frontends/Kconfig | 14 + drivers/media/dvb/frontends/Makefile | 2 + drivers/media/dvb/frontends/stb6000.c | 254 +++++++++++ drivers/media/dvb/frontends/stb6000.h | 51 +++ drivers/media/dvb/frontends/stv0288.c | 606 ++++++++++++++++++++++++++ drivers/media/dvb/frontends/stv0288.h | 65 +++ drivers/media/dvb/frontends/stv0299.c | 2 + drivers/media/dvb/frontends/stv0299.h | 13 +- drivers/media/video/cx88/Kconfig | 3 + drivers/media/video/cx88/cx88-cards.c | 19 +- drivers/media/video/cx88/cx88-dvb.c | 48 ++ drivers/media/video/cx88/cx88.h | 1 + 13 files changed, 1077 insertions(+), 12 deletions(-) create mode 100644 drivers/media/dvb/frontends/stb6000.c create mode 100644 drivers/media/dvb/frontends/stb6000.h create mode 100644 drivers/media/dvb/frontends/stv0288.c create mode 100644 drivers/media/dvb/frontends/stv0288.h diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 0c1790fe2b5..f7321448b4b 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -39,8 +39,8 @@ #include "dvb-pll.h" #include "stv0299.h" -/*#include "stv0288.h" - *#include "stb6000.h"*/ +#include "stv0288.h" +#include "stb6000.h" #include "si21xx.h" #include "cx24116.h" #include "z0194a.h" @@ -594,13 +594,12 @@ static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb) dm1105dvb_dma_unmap(dm1105dvb); } -#if 0 + static struct stv0288_config earda_config = { .demod_address = 0x68, .min_delay_ms = 100, }; -#endif /* keep */ static struct si21xx_config serit_config = { .demod_address = 0x68, .min_delay_ms = 100, @@ -627,7 +626,7 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); } -#if 0 + if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach( stv0288_attach, &earda_config, @@ -639,7 +638,7 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) &dm1105dvb->i2c_adap); } } -#endif /* keep */ + if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach( si21xx_attach, &serit_config, diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7697391ca86..96b93e21a84 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -43,6 +43,20 @@ config DVB_S5H1420 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_STV0288 + tristate "ST STV0288 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + +config DVB_STB6000 + tristate "ST STB6000 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S silicon tuner module. Say Y when you want to support this tuner. + config DVB_STV0299 tristate "ST STV0299 based" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index c719b7fdce4..491eb5c5585 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -53,3 +53,5 @@ obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o obj-$(CONFIG_DVB_SI21XX) += si21xx.o +obj-$(CONFIG_DVB_STV0299) += stv0288.o +obj-$(CONFIG_DVB_STB6000) += stb6000.o diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c new file mode 100644 index 00000000000..7d65123b4ec --- /dev/null +++ b/drivers/media/dvb/frontends/stb6000.c @@ -0,0 +1,254 @@ + /* + Driver for ST STB6000 DVBS Silicon tuner + + Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) + + 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 "stb6000.h" + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "stb6000: " args); \ + } while (0) + +struct stb6000_priv { + /* i2c details */ + int i2c_address; + struct i2c_adapter *i2c; + u32 frequency; +}; + +static int stb6000_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int stb6000_sleep(struct dvb_frontend *fe) +{ + struct stb6000_priv *priv = fe->tuner_priv; + int ret; + u8 buf[] = { 10, 0 }; + struct i2c_msg msg = { + .addr = priv->i2c_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + dprintk("%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer(priv->i2c, &msg, 1); + if (ret != 1) + dprintk("%s: i2c error\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return (ret == 1) ? 0 : ret; +} + +static int stb6000_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct stb6000_priv *priv = fe->tuner_priv; + unsigned int n, m; + int ret; + u32 freq_mhz; + int bandwidth; + u8 buf[12]; + struct i2c_msg msg = { + .addr = priv->i2c_address, + .flags = 0, + .buf = buf, + .len = 12 + }; + + dprintk("%s:\n", __func__); + + freq_mhz = params->frequency / 1000; + bandwidth = params->u.qpsk.symbol_rate / 1000000; + + if (bandwidth > 31) + bandwidth = 31; + + if ((freq_mhz > 949) && (freq_mhz < 2151)) { + buf[0] = 0x01; + buf[1] = 0xac; + if (freq_mhz < 1950) + buf[1] = 0xaa; + if (freq_mhz < 1800) + buf[1] = 0xa8; + if (freq_mhz < 1650) + buf[1] = 0xa6; + if (freq_mhz < 1530) + buf[1] = 0xa5; + if (freq_mhz < 1470) + buf[1] = 0xa4; + if (freq_mhz < 1370) + buf[1] = 0xa2; + if (freq_mhz < 1300) + buf[1] = 0xa1; + if (freq_mhz < 1200) + buf[1] = 0xa0; + if (freq_mhz < 1075) + buf[1] = 0xbc; + if (freq_mhz < 1000) + buf[1] = 0xba; + if (freq_mhz < 1075) { + n = freq_mhz / 8; /* vco=lo*4 */ + m = 2; + } else { + n = freq_mhz / 16; /* vco=lo*2 */ + m = 1; + } + buf[2] = n >> 1; + buf[3] = (unsigned char)(((n & 1) << 7) | + (m * freq_mhz - n * 16) | 0x60); + buf[4] = 0x04; + buf[5] = 0x0e; + + buf[6] = (unsigned char)(bandwidth); + + buf[7] = 0xd8; + buf[8] = 0xd0; + buf[9] = 0x50; + buf[10] = 0xeb; + buf[11] = 0x4f; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer(priv->i2c, &msg, 1); + if (ret != 1) + dprintk("%s: i2c error\n", __func__); + + udelay(10); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + buf[0] = 0x07; + buf[1] = 0xdf; + buf[2] = 0xd0; + buf[3] = 0x50; + buf[4] = 0xfb; + msg.len = 5; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer(priv->i2c, &msg, 1); + if (ret != 1) + dprintk("%s: i2c error\n", __func__); + + udelay(10); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + priv->frequency = freq_mhz * 1000; + + return (ret == 1) ? 0 : ret; + } + return -1; +} + +static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct stb6000_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static struct dvb_tuner_ops stb6000_tuner_ops = { + .info = { + .name = "ST STB6000", + .frequency_min = 950000, + .frequency_max = 2150000 + }, + .release = stb6000_release, + .sleep = stb6000_sleep, + .set_params = stb6000_set_params, + .get_frequency = stb6000_get_frequency, +}; + +struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, + struct i2c_adapter *i2c) +{ + struct stb6000_priv *priv = NULL; + u8 b1[] = { 0, 0 }; + struct i2c_msg msg[2] = { + { + .addr = addr, + .flags = 0, + .buf = NULL, + .len = 0 + }, { + .addr = addr, + .flags = I2C_M_RD, + .buf = b1, + .len = 2 + } + }; + int ret; + + dprintk("%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* is some i2c device here ? */ + ret = i2c_transfer(i2c, msg, 2); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 2) + return NULL; + + priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c_address = addr; + priv->i2c = i2c; + + memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + + return fe; +} +EXPORT_SYMBOL(stb6000_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("DVB STB6000 driver"); +MODULE_AUTHOR("Igor M. Liplianin "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h new file mode 100644 index 00000000000..7be479c22d5 --- /dev/null +++ b/drivers/media/dvb/frontends/stb6000.h @@ -0,0 +1,51 @@ + /* + Driver for ST stb6000 DVBS Silicon tuner + + Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#ifndef __DVB_STB6000_H__ +#define __DVB_STB6000_H__ + +#include +#include "dvb_frontend.h" + +/** + * Attach a stb6000 tuner to the supplied frontend structure. + * + * @param fe Frontend to attach to. + * @param addr i2c address of the tuner. + * @param i2c i2c adapter to use. + * @return FE pointer on success, NULL on failure. + */ +#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, + int addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_STB6000 */ + +#endif /* __DVB_STB6000_H__ */ diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c new file mode 100644 index 00000000000..90e72e771a0 --- /dev/null +++ b/drivers/media/dvb/frontends/stv0288.c @@ -0,0 +1,606 @@ +/* + Driver for ST STV0288 demodulator + Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de + for Reel Multimedia + Copyright (C) 2008 TurboSight.com, Bob Liu + Copyright (C) 2008 Igor M. Liplianin + Removed stb6000 specific tuner code and revised some + procedures. + + 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 "dvb_frontend.h" +#include "stv0288.h" + +struct stv0288_state { + struct i2c_adapter *i2c; + const struct stv0288_config *config; + struct dvb_frontend frontend; + + u8 initialised:1; + u32 tuner_frequency; + u32 symbol_rate; + fe_code_rate_t fec_inner; + int errmode; +}; + +#define STATUS_BER 0 +#define STATUS_UCBLOCKS 1 + +static int debug; +static int debug_legacy_dish_switch; +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "stv0288: " args); \ + } while (0) + + +static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " + "ret == %i)\n", __func__, reg, data, ret); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int stv0288_write(struct dvb_frontend *fe, u8 *buf, int len) +{ + struct stv0288_state *state = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return stv0288_writeregI(state, buf[0], buf[1]); +} + +static u8 stv0288_readreg(struct stv0288_state *state, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + }, { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", + __func__, reg, ret); + + return b1[0]; +} + +static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate) +{ + struct stv0288_state *state = fe->demodulator_priv; + unsigned int temp; + unsigned char b[3]; + + if ((srate < 1000000) || (srate > 45000000)) + return -EINVAL; + + temp = (unsigned int)srate / 1000; + + temp = temp * 32768; + temp = temp / 25; + temp = temp / 125; + b[0] = (unsigned char)((temp >> 12) & 0xff); + b[1] = (unsigned char)((temp >> 4) & 0xff); + b[2] = (unsigned char)((temp << 4) & 0xf0); + stv0288_writeregI(state, 0x28, 0x80); /* SFRH */ + stv0288_writeregI(state, 0x29, 0); /* SFRM */ + stv0288_writeregI(state, 0x2a, 0); /* SFRL */ + + stv0288_writeregI(state, 0x28, b[0]); + stv0288_writeregI(state, 0x29, b[1]); + stv0288_writeregI(state, 0x2a, b[2]); + dprintk("stv0288: stv0288_set_symbolrate\n"); + + return 0; +} + +static int stv0288_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *m) +{ + struct stv0288_state *state = fe->demodulator_priv; + + int i; + + dprintk("%s\n", __func__); + + stv0288_writeregI(state, 0x09, 0); + msleep(30); + stv0288_writeregI(state, 0x05, 0x16); + + for (i = 0; i < m->msg_len; i++) { + if (stv0288_writeregI(state, 0x06, m->msg[i])) + return -EREMOTEIO; + msleep(12); + } + + return 0; +} + +static int stv0288_send_diseqc_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t burst) +{ + struct stv0288_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + if (stv0288_writeregI(state, 0x05, 0x16))/* burst mode */ + return -EREMOTEIO; + + if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff)) + return -EREMOTEIO; + + if (stv0288_writeregI(state, 0x06, 0x12)) + return -EREMOTEIO; + + return 0; +} + +static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct stv0288_state *state = fe->demodulator_priv; + + switch (tone) { + case SEC_TONE_ON: + if (stv0288_writeregI(state, 0x05, 0x10))/* burst mode */ + return -EREMOTEIO; + return stv0288_writeregI(state, 0x06, 0xff); + + case SEC_TONE_OFF: + if (stv0288_writeregI(state, 0x05, 0x13))/* burst mode */ + return -EREMOTEIO; + return stv0288_writeregI(state, 0x06, 0x00); + + default: + return -EINVAL; + } +} + +static u8 stv0288_inittab[] = { + 0x01, 0x15, + 0x02, 0x20, + 0x09, 0x0, + 0x0a, 0x4, + 0x0b, 0x0, + 0x0c, 0x0, + 0x0d, 0x0, + 0x0e, 0xd4, + 0x0f, 0x30, + 0x11, 0x80, + 0x12, 0x03, + 0x13, 0x48, + 0x14, 0x84, + 0x15, 0x45, + 0x16, 0xb7, + 0x17, 0x9c, + 0x18, 0x0, + 0x19, 0xa6, + 0x1a, 0x88, + 0x1b, 0x8f, + 0x1c, 0xf0, + 0x20, 0x0b, + 0x21, 0x54, + 0x22, 0x0, + 0x23, 0x0, + 0x2b, 0xff, + 0x2c, 0xf7, + 0x30, 0x0, + 0x31, 0x1e, + 0x32, 0x14, + 0x33, 0x0f, + 0x34, 0x09, + 0x35, 0x0c, + 0x36, 0x05, + 0x37, 0x2f, + 0x38, 0x16, + 0x39, 0xbe, + 0x3a, 0x0, + 0x3b, 0x13, + 0x3c, 0x11, + 0x3d, 0x30, + 0x40, 0x63, + 0x41, 0x04, + 0x42, 0x60, + 0x43, 0x00, + 0x44, 0x00, + 0x45, 0x00, + 0x46, 0x00, + 0x47, 0x00, + 0x4a, 0x00, + 0x50, 0x10, + 0x51, 0x38, + 0x52, 0x21, + 0x58, 0x54, + 0x59, 0x86, + 0x5a, 0x0, + 0x5b, 0x9b, + 0x5c, 0x08, + 0x5d, 0x7f, + 0x5e, 0x0, + 0x5f, 0xff, + 0x70, 0x0, + 0x71, 0x0, + 0x72, 0x0, + 0x74, 0x0, + 0x75, 0x0, + 0x76, 0x0, + 0x81, 0x0, + 0x82, 0x3f, + 0x83, 0x3f, + 0x84, 0x0, + 0x85, 0x0, + 0x88, 0x0, + 0x89, 0x0, + 0x8a, 0x0, + 0x8b, 0x0, + 0x8c, 0x0, + 0x90, 0x0, + 0x91, 0x0, + 0x92, 0x0, + 0x93, 0x0, + 0x94, 0x1c, + 0x97, 0x0, + 0xa0, 0x48, + 0xa1, 0x0, + 0xb0, 0xb8, + 0xb1, 0x3a, + 0xb2, 0x10, + 0xb3, 0x82, + 0xb4, 0x80, + 0xb5, 0x82, + 0xb6, 0x82, + 0xb7, 0x82, + 0xb8, 0x20, + 0xb9, 0x0, + 0xf0, 0x0, + 0xf1, 0x0, + 0xf2, 0xc0, + 0x51, 0x36, + 0x52, 0x09, + 0x53, 0x94, + 0x54, 0x62, + 0x55, 0x29, + 0x56, 0x64, + 0x57, 0x2b, + 0xff, 0xff, +}; + +static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) +{ + dprintk("%s: %s\n", __func__, + volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : + volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); + + return 0; +} + +static int stv0288_init(struct dvb_frontend *fe) +{ + struct stv0288_state *state = fe->demodulator_priv; + int i; + + dprintk("stv0288: init chip\n"); + stv0288_writeregI(state, 0x41, 0x04); + msleep(50); + + for (i = 0; !(stv0288_inittab[i] == 0xff && + stv0288_inittab[i + 1] == 0xff); i += 2) + stv0288_writeregI(state, stv0288_inittab[i], + stv0288_inittab[i + 1]); + + return 0; +} + +static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct stv0288_state *state = fe->demodulator_priv; + + u8 sync = stv0288_readreg(state, 0x24); + if (sync == 255) + sync = 0; + + dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync); + + *status = 0; + + if ((sync & 0x08) == 0x08) { + *status |= FE_HAS_LOCK; + dprintk("stv0288 has locked\n"); + } + + return 0; +} + +static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct stv0288_state *state = fe->demodulator_priv; + + if (state->errmode != STATUS_BER) + return 0; + *ber = (stv0288_readreg(state, 0x26) << 8) | + stv0288_readreg(state, 0x27); + dprintk("stv0288_read_ber %d\n", *ber); + + return 0; +} + + +static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct stv0288_state *state = fe->demodulator_priv; + + s32 signal = 0xffff - ((stv0288_readreg(state, 0x10) << 8)); + + + signal = signal * 5 / 4; + *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal; + dprintk("stv0288_read_signal_strength %d\n", *strength); + + return 0; +} +static int stv0288_sleep(struct dvb_frontend *fe) +{ + struct stv0288_state *state = fe->demodulator_priv; + + stv0288_writeregI(state, 0x41, 0x84); + state->initialised = 0; + + return 0; +} +static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct stv0288_state *state = fe->demodulator_priv; + + s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8) + | stv0288_readreg(state, 0x2e)); + xsnr = 3 * (xsnr - 0xa100); + *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; + dprintk("stv0288_read_snr %d\n", *snr); + + return 0; +} + +static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct stv0288_state *state = fe->demodulator_priv; + + if (state->errmode != STATUS_BER) + return 0; + *ucblocks = (stv0288_readreg(state, 0x26) << 8) | + stv0288_readreg(state, 0x27); + dprintk("stv0288_read_ber %d\n", *ucblocks); + + return 0; +} + +static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int stv0288_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *dfp) +{ + struct stv0288_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + char tm; + unsigned char tda[3]; + + dprintk("%s : FE_SET_FRONTEND\n", __func__); + + if (c->delivery_system != SYS_DVBS) { + dprintk("%s: unsupported delivery " + "system selected (%d)\n", + __func__, c->delivery_system); + return -EOPNOTSUPP; + } + + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + + /* only frequency & symbol_rate are used for tuner*/ + dfp->frequency = c->frequency; + dfp->u.qpsk.symbol_rate = c->symbol_rate; + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, dfp); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + udelay(10); + stv0288_set_symbolrate(fe, c->symbol_rate); + /* Carrier lock control register */ + stv0288_writeregI(state, 0x15, 0xc5); + + tda[0] = 0x2b; /* CFRM */ + tda[2] = 0x0; /* CFRL */ + for (tm = -6; tm < 7;) { + /* Viterbi status */ + if (stv0288_readreg(state, 0x24) & 0x80) + break; + + tda[2] += 40; + if (tda[2] < 40) + tm++; + tda[1] = (unsigned char)tm; + stv0288_writeregI(state, 0x2b, tda[1]); + stv0288_writeregI(state, 0x2c, tda[2]); + udelay(30); + } + + state->tuner_frequency = c->frequency; + state->fec_inner = FEC_AUTO; + state->symbol_rate = c->symbol_rate; + + return 0; +} + +static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct stv0288_state *state = fe->demodulator_priv; + + if (enable) + stv0288_writeregI(state, 0x01, 0xb5); + else + stv0288_writeregI(state, 0x01, 0x35); + + udelay(1); + + return 0; +} + +static void stv0288_release(struct dvb_frontend *fe) +{ + struct stv0288_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops stv0288_ops = { + + .info = { + .name = "ST STV0288 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1000, /* kHz for QPSK frontends */ + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + + .release = stv0288_release, + .init = stv0288_init, + .sleep = stv0288_sleep, + .write = stv0288_write, + .i2c_gate_ctrl = stv0288_i2c_gate_ctrl, + .read_status = stv0288_read_status, + .read_ber = stv0288_read_ber, + .read_signal_strength = stv0288_read_signal_strength, + .read_snr = stv0288_read_snr, + .read_ucblocks = stv0288_read_ucblocks, + .diseqc_send_master_cmd = stv0288_send_diseqc_msg, + .diseqc_send_burst = stv0288_send_diseqc_burst, + .set_tone = stv0288_set_tone, + .set_voltage = stv0288_set_voltage, + + .set_property = stv0288_set_property, + .get_property = stv0288_get_property, + .set_frontend = stv0288_set_frontend, +}; + +struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, + struct i2c_adapter *i2c) +{ + struct stv0288_state *state = NULL; + int id; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + state->initialised = 0; + state->tuner_frequency = 0; + state->symbol_rate = 0; + state->fec_inner = 0; + state->errmode = STATUS_BER; + + stv0288_writeregI(state, 0x41, 0x04); + msleep(200); + id = stv0288_readreg(state, 0x00); + dprintk("stv0288 id %x\n", id); + + /* register 0x00 contains 0x11 for STV0288 */ + if (id != 0x11) + goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &stv0288_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(stv0288_attach); + +module_param(debug_legacy_dish_switch, int, 0444); +MODULE_PARM_DESC(debug_legacy_dish_switch, + "Enable timing analysis for Dish Network legacy switches"); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver"); +MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h new file mode 100644 index 00000000000..aa0cdd27304 --- /dev/null +++ b/drivers/media/dvb/frontends/stv0288.h @@ -0,0 +1,65 @@ +/* + Driver for ST STV0288 demodulator + + Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de + for Reel Multimedia + Copyright (C) 2008 TurboSight.com, + Copyright (C) 2008 Igor M. Liplianin + Removed stb6000 specific tuner code and revised some + procedures. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef STV0288_H +#define STV0288_H + +#include +#include "dvb_frontend.h" + +struct stv0288_config { + /* the demodulator's i2c address */ + u8 demod_address; + + /* minimum delay before retuning */ + int min_delay_ms; + + int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); +}; + +#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \ + defined(MODULE)) +extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_STV0288 */ + +static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val) +{ + int r = 0; + u8 buf[] = { reg, val }; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 2); + return r; +} + +#endif /* STV0288_H */ diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 35435bef8e7..6c1cb1973c6 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -559,6 +559,8 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par int invval = 0; dprintk ("%s : FE_SET_FRONTEND\n", __func__); + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); // set the inversion if (p->inversion == INVERSION_OFF) invval = 0; diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 3282f43022f..0fd96e22b65 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -89,15 +89,18 @@ struct stv0299_config int min_delay_ms; /* Set the symbol rate */ - int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); + int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio); + + /* Set device param to start dma */ + int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); }; #if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) -extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, - struct i2c_adapter* i2c); +extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config, + struct i2c_adapter *i2c); #else -static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, - struct i2c_adapter* i2c) +static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config, + struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 4f65ce3088b..0b9e5fac623 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -59,6 +59,9 @@ config VIDEO_CX88_DVB select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_STV0288 if !DVB_FE_CUSTOMISE + select DVB_STB6000 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 0203c7579a3..16bb9c35fc7 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1732,6 +1732,18 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TEVII_S420] = { + .name = "TeVii S420 DVB-S", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_TEVII_S460] = { .name = "TeVii S460 DVB-S/S2", .tuner_type = UNSET, @@ -2138,7 +2150,11 @@ static const struct cx88_subid cx88_subids[] = { .subdevice = 0x6906, .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, }, { - .subvendor = 0xD460, + .subvendor = 0xd420, + .subdevice = 0x9022, + .card = CX88_BOARD_TEVII_S420, + }, { + .subvendor = 0xd460, .subdevice = 0x9022, .card = CX88_BOARD_TEVII_S460, }, { @@ -2730,6 +2746,7 @@ static void cx88_card_setup(struct cx88_core *core) cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); break; } + case CX88_BOARD_TEVII_S420: case CX88_BOARD_TEVII_S460: cx_write(MO_SRST_IO, 0); msleep(100); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index a6c4f66bb16..cd368b512d1 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -48,6 +48,10 @@ #include "tuner-simple.h" #include "tda9887.h" #include "s5h1411.h" +#include "stv0299.h" +#include "z0194a.h" +#include "stv0288.h" +#include "stb6000.h" #include "cx24116.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); @@ -579,6 +583,25 @@ static struct cx24116_config tevii_s460_config = { .reset_device = cx24116_reset_device, }; +static struct stv0299_config tevii_tuner_sharp_config = { + .demod_address = 0x68, + .inittab = sharp_z0194a__inittab, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .lock_output = 1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = sharp_z0194a__set_symbol_rate, + .set_ts_params = cx24116_set_ts_param, +}; + +static struct stv0288_config tevii_tuner_earda_config = { + .demod_address = 0x68, + .min_delay_ms = 100, + .set_ts_params = cx24116_set_ts_param, +}; + static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -949,6 +972,31 @@ static int dvb_register(struct cx8802_dev *dev) 0x08, ISL6421_DCL, 0x00); } break; + case CX88_BOARD_TEVII_S420: + dev->dvb.frontend = dvb_attach(stv0299_attach, + &tevii_tuner_sharp_config, + &core->i2c_adap); + if (dev->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + &core->i2c_adap, DVB_PLL_OPERA1)) + goto frontend_detach; + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + + } else { + dev->dvb.frontend = dvb_attach(stv0288_attach, + &tevii_tuner_earda_config, + &core->i2c_adap); + if (dev->dvb.frontend != NULL) { + if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61, + &core->i2c_adap)) + goto frontend_detach; + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + + } + } + break; case CX88_BOARD_TEVII_S460: dev->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index fa3a72525d6..e17bd513b58 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -226,6 +226,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TEVII_S460 70 #define CX88_BOARD_OMICOM_SS4_PCI 71 #define CX88_BOARD_TBS_8920 72 +#define CX88_BOARD_TEVII_S420 73 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From 301e9d64e0bb00c557d9385474cc9d79db0485d9 Mon Sep 17 00:00:00 2001 From: hermann pitton Date: Sun, 14 Sep 2008 17:49:14 -0300 Subject: [PATCH 4140/5416] V4L/DVB (9028): saa7134: add support for the triple Asus Tiger 3in1 after looking it up, all rants about the 80 columns restriction seem to be in vain. After changing the card's name it are now "only" seven new lines in the tiny DVB-T/DVB-S switch function. saa7130/34: v4l2 driver version 0.2.14 loaded saa7133[0]: found at 0000:02:08.0, rev: 209, irq: 18, latency: 32, mmio: 0xfdef7000 saa7133[0]: subsystem: 1043:4878, board: Asus Tiger 3in1 [card=147,autodetected] saa7133[0]: board init: gpio is 200000 tuner' 2-004b: chip found @ 0x96 (saa7133[0]) saa7133[0]: i2c eeprom 00: 43 10 78 48 54 20 1c 00 43 43 a9 1c 55 d2 b2 92 saa7133[0]: i2c eeprom 10: ff ff ff 0f ff 20 ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 20: 01 40 01 02 03 01 01 03 08 ff 00 d7 ff ff ff ff saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 40: ff 28 00 c2 96 16 03 02 c0 1c ff ff ff ff ff ff saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c eeprom f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff saa7133[0]: i2c scan: found device @ 0x10 [???] saa7133[0]: i2c scan: found device @ 0x16 [???] saa7133[0]: i2c scan: found device @ 0x1c [???] saa7133[0]: i2c scan: found device @ 0x96 [???] saa7133[0]: i2c scan: found device @ 0xa0 [eeprom] tda829x 2-004b: setting tuner address to 61 tda829x 2-004b: type set to tda8290+75a saa7133[0]: registered device video0 [v4l2] saa7133[0]: registered device vbi0 saa7133[0]: registered device radio0 DVB: registering new adapter (saa7133[0]) DVB: registering frontend 0 (Philips TDA10086 DVB-S)... The board init gpio is 0x0, 0x200000 is from previously unloading with antenna_switch = 1. It needs firmware for the tda10046 and analog sound needs saa7134-alsa. I have support for one more board and need to fix the first revision of the Asus Tiger DVB-T hybrid. DVB-T currently hangs on the male radio antenna input, also some small other stuff. Please report any issues with this patch, the next are depending on this one. saa7134: add support for the triple Asus Tiger 3in1 Signed-off-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 3 +- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 44 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 39 ++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 8fea2975410..075650c95fe 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -68,6 +68,7 @@ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid [0070:6900,0070:6904,0070:6902] 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2 [0070:6905,0070:6906] - 70 -> TeVii S460 DVB-S/S2 [D460:9022] + 70 -> TeVii S460 DVB-S/S2 [d460:9022] 71 -> Omicom SS4 DVB-S/S2 PCI [A044:2011] 72 -> TBS 8920 DVB-S/S2 [8920:8888] + 73 -> TeVii S420 DVB-S [d420:9022] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 39868af9cf9..c121f44aefc 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -145,3 +145,4 @@ 144 -> Beholder BeholdTV M6 Extra [5ace:6193] 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] 146 -> ASUSTeK P7131 Analog +147 -> Asus Tiger 3in1 [1043:4878] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 98364d171de..3c2f09fb044 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4409,6 +4409,36 @@ struct saa7134_board saa7134_boards[] = { /* no DVB support for now */ /* .mpeg = SAA7134_MPEG_DVB, */ }, + [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = { + .name = "Asus Tiger 3in1", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .gpiomask = 1 << 21, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5431,6 +5461,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1461, /* Avermedia Technologies Inc */ .subdevice = 0xf636, .driver_data = SAA7134_BOARD_AVERMEDIA_M103, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1043, + .subdevice = 0x4878, /* REV:1.02G */ + .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -6002,6 +6038,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); break; } + case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: + { + u8 data[] = { 0x3c, 0x33, 0x60}; + struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data, + .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + break; + } case SAA7134_BOARD_FLYDVB_TRIO: { u8 data[] = { 0x3c, 0x33, 0x62}; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index be48b9b66a6..7fa6ce76642 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -799,6 +799,20 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = { .request_firmware = philips_tda1004x_request_firmware }; +static struct tda1004x_config asus_tiger_3in1_config = { + .demod_address = 0x0b, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, + .if_freq = TDA10046_FREQ_045, + .i2c_gate = 0x4b, + .tuner_address = 0x61, + .antenna_switch = 1, + .request_firmware = philips_tda1004x_request_firmware +}; + /* ------------------------------------------------------------------ * special case: this card uses saa713x GPIO22 for the mode switch */ @@ -1300,6 +1314,31 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); attach_xc3028 = 1; break; + case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: + if (!use_frontend) { /* terrestrial */ + if (configure_tda827x_fe(dev, &asus_tiger_3in1_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; + } else { /* satellite */ + dev->dvb.frontend = dvb_attach(tda10086_attach, + &flydvbs, &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, + dev->dvb.frontend, 0x60, + &dev->i2c_adap, 0) == NULL) { + wprintk("%s: Asus Tiger 3in1, no " + "tda826x found!\n", __func__); + goto dettach_frontend; + } + if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + &dev->i2c_adap, 0, 0) == NULL) { + wprintk("%s: Asus Tiger 3in1, no lnbp21" + " found!\n", __func__); + goto dettach_frontend; + } + } + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 5e7fc731fab..cbfdac27b69 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -269,6 +269,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_M6_EXTRA 144 #define SAA7134_BOARD_AVERMEDIA_M103 145 #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 +#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- GitLab From 80845e1078463913f8b456e45f1fae886687c363 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 15 Sep 2008 22:19:46 -0300 Subject: [PATCH 4141/5416] V4L/DVB (9030): uvcvideo : Add support for Advent 4211 integrated webcam Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 4ab4d1ebb22..fee85a2465c 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1939,6 +1939,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* Advent 4211 - Bison Electronics */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x5986, + .idProduct = 0x0203, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bison Electronics */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- GitLab From d63beb9ef004ff9587b3c466361276254d57d7a7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 15 Sep 2008 22:24:29 -0300 Subject: [PATCH 4142/5416] V4L/DVB (9031): uvcvideo: Fix incomplete frame drop when switching to a variable size format. When streaming in a fixed size format the driver sets a flag in the uvc_queue structure to drop incomplete incoming frames. The flag wasn't cleared when switching to a variable size format, which resulted in a broken 'MJPEG after YUV'. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 4 ---- drivers/media/video/uvc/uvc_video.c | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index d4758c8e13a..78e4c4e09d8 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -842,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, if (ret < 0) return ret; - if (!(video->streaming->cur_format->flags & - UVC_FMT_FLAG_COMPRESSED)) - video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; - rb->count = ret; ret = 0; break; diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 593aebffe57..b7bb23820d8 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -971,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) return 0; } + if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) + video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + else + video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; + if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) return ret; -- GitLab From a31a4055473bf0a7b2b06cb2262347200d0711e1 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 16 Sep 2008 03:32:20 -0300 Subject: [PATCH 4143/5416] V4L/DVB:usbvideo:don't use part of buffer for USB transfer #4 The status[] is part of uvc_device structure. We can't make sure the address of status is at a cache-line boundary in all archs,so status[] might share a cache-line with some fields in uvc_structure. This can lead to some cache coherence issues(http://lwn.net/Articles/2265/). Use dynamically allocated buffer instead. Signed-off-by: Ming Lei Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_status.c | 11 +++++++++-- drivers/media/video/uvc/uvcvideo.h | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index 75e678ac54e..5d60b264d59 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c @@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev) uvc_input_init(dev); + dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); + if (dev->status == NULL) + return -ENOMEM; + dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dev->int_urb == NULL) + if (dev->int_urb == NULL) { + kfree(dev->status); return -ENOMEM; + } pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); @@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev) interval = fls(interval) - 1; usb_fill_int_urb(dev->int_urb, dev->udev, pipe, - dev->status, sizeof dev->status, uvc_status_complete, + dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, dev, interval); return usb_submit_urb(dev->int_urb, GFP_KERNEL); @@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); usb_free_urb(dev->int_urb); + kfree(dev->status); uvc_input_cleanup(dev); } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bafe3406e30..9a6bc1aafb1 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -303,6 +303,8 @@ struct uvc_xu_control { #define UVC_MAX_FRAME_SIZE (16*1024*1024) /* Maximum number of video buffers. */ #define UVC_MAX_VIDEO_BUFFERS 32 +/* Maximum status buffer size in bytes of interrupt URB. */ +#define UVC_MAX_STATUS_SIZE 16 #define UVC_CTRL_CONTROL_TIMEOUT 300 #define UVC_CTRL_STREAMING_TIMEOUT 1000 @@ -634,7 +636,7 @@ struct uvc_device { /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; struct urb *int_urb; - __u8 status[16]; + __u8 *status; struct input_dev *input; /* Video Streaming interfaces */ -- GitLab From 714b9a1e0ae3224728d1d96d77150ceea7487a61 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 18 Sep 2008 23:26:35 -0300 Subject: [PATCH 4144/5416] V4L/DVB (9033): drivers/media/video/tda9840.c: unbreak drivers/media/video/tda9840.c: In function 'tda9840_command': drivers/media/video/tda9840.c:152: warning: 'result' is used uninitialized in this function [mchehab@redhat.com: Fix conflict with another patch that were meant to solve the warning] Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda9840.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 77bfd24ecfa..1c391f0328f 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -71,7 +71,6 @@ static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) { - int result = 0; int byte = *(int *)arg; switch (cmd) { @@ -176,9 +175,6 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) return -ENOIOCTLCMD; } - if (result) - return -EIO; - return 0; } -- GitLab From 4aaec3ea41addf6fe4fe029aa535f3c019ee0e6d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Sun, 21 Sep 2008 04:12:03 -0300 Subject: [PATCH 4145/5416] V4L/DVB (9034): With the recent patch to v4l2 titled "v4l2: use register_chrdev_region instead of register_chrdev", the internal reference count is no longer necessary in order to free the internal stk_webcam struct. This patch removes the reference counter from the stk_webcam struct and frees the struct via the video_device release callback. It also fixes an associated bug in stk_camera_probe which could result from video_unregister_device being called before video_register_device. Lastly, it simplifies access to the stk_webcam struct in several places. This patch should apply cleanly against the "working" branch of the v4l-dvb git repository. This patch is identical to the patch I sent a couple of months back titled "stk-webcam: Fix video_device handling" except that it has been rebased against current modifications to stk-webcam and it no longer depends on any other outstanding patches. Acked-by: Jaime Velasco Juan Signed-off-by: David Ellingsworth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 84 +++++++++----------------------- drivers/media/video/stk-webcam.h | 2 - 2 files changed, 23 insertions(+), 63 deletions(-) diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 8dda5680094..db69bc5556d 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = { }; MODULE_DEVICE_TABLE(usb, stkwebcam_table); -static void stk_camera_cleanup(struct kref *kref) -{ - struct stk_camera *dev = to_stk_camera(kref); - - STK_INFO("Syntek USB2.0 Camera release resources" - " video device /dev/video%d\n", dev->vdev.minor); - video_unregister_device(&dev->vdev); - video_set_drvdata(&dev->vdev, NULL); - - if (dev->sio_bufs != NULL || dev->isobufs != NULL) - STK_ERROR("We are leaking memory\n"); - usb_put_intf(dev->interface); - kfree(dev); -} - - /* * Basic stuff */ @@ -694,8 +678,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) unlock_kernel(); return -ENXIO; } - fp->private_data = vdev; - kref_get(&dev->kref); + fp->private_data = dev; usb_autopm_get_interface(dev->interface); unlock_kernel(); @@ -704,23 +687,10 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) static int v4l_stk_release(struct inode *inode, struct file *fp) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - if (vdev == NULL) { - STK_ERROR("v4l_release called w/o video devdata\n"); - return -EFAULT; - } - dev = vdev_to_camera(vdev); - if (dev == NULL) { - STK_ERROR("v4l_release called on removed device\n"); - return -ENODEV; - } + struct stk_camera *dev = fp->private_data; if (dev->owner != fp) { usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -731,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) dev->owner = NULL; usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -742,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, int i; int ret; unsigned long flags; - struct stk_camera *dev; - struct video_device *vdev; struct stk_sio_buffer *sbuf; - - vdev = video_devdata(fp); - if (vdev == NULL) - return -EFAULT; - dev = vdev_to_camera(vdev); + struct stk_camera *dev = fp->private_data; if (dev == NULL) return -EIO; @@ -808,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - - if (vdev == NULL) - return -EFAULT; + struct stk_camera *dev = fp->private_data; - dev = vdev_to_camera(vdev); if (dev == NULL) return -ENODEV; @@ -854,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) unsigned int i; int ret; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - struct stk_camera *dev; - struct video_device *vdev; + struct stk_camera *dev = fp->private_data; struct stk_sio_buffer *sbuf = NULL; if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) return -EINVAL; - vdev = video_devdata(fp); - dev = vdev_to_camera(vdev); - for (i = 0; i < dev->n_sbufs; i++) { if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { sbuf = dev->sio_bufs + i; @@ -1359,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { static void stk_v4l_dev_release(struct video_device *vd) { + struct stk_camera *dev = vdev_to_camera(vd); + + if (dev->sio_bufs != NULL || dev->isobufs != NULL) + STK_ERROR("We are leaking memory\n"); + usb_put_intf(dev->interface); + kfree(dev); } static struct video_device stk_v4l_data = { @@ -1379,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) dev->vdev = stk_v4l_data; dev->vdev.debug = debug; dev->vdev.parent = &dev->interface->dev; - video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (err) STK_ERROR("v4l registration failed\n"); @@ -1396,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, const struct usb_device_id *id) { int i; - int err; + int err = 0; struct stk_camera *dev = NULL; struct usb_device *udev = interface_to_usbdev(interface); @@ -1409,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, return -ENOMEM; } - kref_init(&dev->kref); spin_lock_init(&dev->spinlock); init_waitqueue_head(&dev->wait_frame); @@ -1442,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, } if (!dev->isoc_ep) { STK_ERROR("Could not find isoc-in endpoint"); - kref_put(&dev->kref, stk_camera_cleanup); - return -ENODEV; + err = -ENODEV; + goto error; } dev->vsettings.brightness = 0x7fff; dev->vsettings.palette = V4L2_PIX_FMT_RGB565; @@ -1457,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, err = stk_register_video_device(dev); if (err) { - kref_put(&dev->kref, stk_camera_cleanup); - return err; + goto error; } stk_create_sysfs_files(&dev->vdev); usb_autopm_enable(dev->interface); return 0; + +error: + kfree(dev); + return err; } static void stk_camera_disconnect(struct usb_interface *interface) @@ -1477,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); stk_remove_sysfs_files(&dev->vdev); - kref_put(&dev->kref, stk_camera_cleanup); + STK_INFO("Syntek USB2.0 Camera release resources" + "video device /dev/video%d\n", dev->vdev.minor); + + video_unregister_device(&dev->vdev); } #ifdef CONFIG_PM diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index df4dfefc532..084a85bdd16 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h @@ -99,7 +99,6 @@ struct stk_camera { u8 isoc_ep; - struct kref kref; /* Not sure if this is right */ atomic_t urbs_used; @@ -121,7 +120,6 @@ struct stk_camera { unsigned sequence; }; -#define to_stk_camera(d) container_of(d, struct stk_camera, kref) #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) void stk_camera_delete(struct kref *); -- GitLab From 5e26d50f4e6b9c42bbfbaa452722797ece929cda Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 22 Sep 2008 13:14:59 -0300 Subject: [PATCH 4146/5416] V4L/DVB (9035): uvcvideo: Declare missing camera and processing unit controls. This declares all missing UVC camera and processing unit controls. V4L2 mappings are not supported yet for those controls. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 164 +++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index feab12aa2c7..088437a5f60 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -81,6 +81,22 @@ static struct uvc_control_info uvc_ctrls[] = { .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | UVC_CONTROL_RESTORE, }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .index = 7, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, { .entity = UVC_GUID_UVC_PROCESSING, .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, @@ -113,6 +129,60 @@ static struct uvc_control_info uvc_ctrls[] = { .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, + .index = 12, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .index = 13, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, + .index = 15, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, + .index = 16, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_LOCK_STATUS_CONTROL, + .index = 17, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_SCANNING_MODE_CONTROL, + .index = 0, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, { .entity = UVC_GUID_UVC_CAMERA, .selector = CT_AE_MODE_CONTROL, @@ -138,6 +208,14 @@ static struct uvc_control_info uvc_ctrls[] = { .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | UVC_CONTROL_RESTORE, }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, + .index = 4, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, { .entity = UVC_GUID_UVC_CAMERA, .selector = CT_FOCUS_ABSOLUTE_CONTROL, @@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_AUTO_CONTROL, - .index = 17, - .size = 1, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + .selector = CT_FOCUS_RELATIVE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .index = 12, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_ABSOLUTE_CONTROL, + .index = 7, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_RELATIVE_CONTROL, + .index = 8, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .index = 6, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_RELATIVE_CONTROL, + .index = 10, + .size = 3, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_ABSOLUTE_CONTROL, + .index = 11, + .size = 8, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_RELATIVE_CONTROL, + .index = 12, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_ABSOLUTE_CONTROL, .index = 13, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_RELATIVE_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_FOCUS_AUTO_CONTROL, + .index = 17, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, - .index = 7, - .size = 4, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PRIVACY_CONTROL, + .index = 18, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, }; -- GitLab From b1accfa15533fdd40280aae3102e9599e63a7c10 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 27 Sep 2008 20:54:02 -0300 Subject: [PATCH 4147/5416] V4L/DVB (9036): uvcvideo: Fix control cache access when setting composite auto-update controls Auto-update controls are never marked is loaded to prevent uvc_get_ctrl from loading the control value from the cache. When setting a composite (mapped to several V4L2 controls) auto-update UVC control, the driver updates the control cache value before processing each V4L2 control, overwriting the previously set V4L2 control. This fixes the problem by marking all controls as loaded in uvc_set_ctrl regardless of their type and resetting the loaded flag in uvc_commit_ctrl for auto-update controls. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 088437a5f60..f16aafe9cf1 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -837,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, for (i = 0; i < entity->ncontrols; ++i) { ctrl = &entity->controls[i]; - if (ctrl->info == NULL || !ctrl->dirty) + if (ctrl->info == NULL) + continue; + + /* Reset the loaded flag for auto-update controls that were + * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent + * uvc_ctrl_get from using the cached value. + */ + if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) + ctrl->loaded = 0; + + if (!ctrl->dirty) continue; if (!rollback) @@ -853,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), ctrl->info->size); - if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) - ctrl->loaded = 0; - ctrl->dirty = 0; if (ret < 0) @@ -913,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, if (ret < 0) return ret; - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } xctrl->value = uvc_get_le_value( @@ -965,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, return ret; } - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } if (!ctrl->dirty) { -- GitLab From 17a370bcca661a849c9af07feae86f42d0c6dfd1 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 6 Sep 2008 13:42:47 -0300 Subject: [PATCH 4148/5416] V4L/DVB (9038): Add support for the Gigabyte R8000-HT USB DVB-T adapter. Thanks to Ilia Penev for the tip-off that this device is much the same as (identical to?) a Terratec Cinergy HT USB XE, and for the firmware hints: http://linuxtv.org/pipermail/linux-dvb/2008-August/028108.html DVB functionality tested OK with xine using the usual dib0700 firmware. This diff is based on the latest latest linuxtv.org v4l-dvb mercurial repo. Signed-off-by: Finn Thain Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 6c0e5c5f436..110d9344bc9 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1119,6 +1119,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, + { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1408,7 +1409,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1422,6 +1423,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[32], NULL }, { NULL }, }, + { "Gigabyte U8000-RH", + { &dib0700_usb_id_table[37], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 7ae262e08f8..e60e8731554 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -221,6 +221,7 @@ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 #define USB_PID_GIGABYTE_U7000 0x7001 +#define USB_PID_GIGABYTE_U8000 0x7002 #define USB_PID_ASUS_U3000 0x171f #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc -- GitLab From bdc203e156ce938e12d957912bd29ca53d160540 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 6 Sep 2008 13:45:27 -0300 Subject: [PATCH 4149/5416] V4L/DVB (9039): Add support for new i2c API provided in firmware version 1.20 The Pinnacle PCTV HD Pro has an xc5000, which exposed a bug in the dib0700's i2c implementation where it did not properly support a single i2c read request (sending it as an i2c write request instead). Version 1.20 of the firmware added support for a new i2c API which supported such requests. This change defaults to fw 1.20 for all devices, but does not default to using the new i2c API (since initial testing suggests problems interacting with the mt2060). Maintainers can enable the use of the new i2c API by putting the following into their frontend initialization: struct dib0700_state *st = adap->dev->priv; st->fw_use_new_i2c_api = 1; Also note that the code expects i2c repeated start to be supported. If the i2c slave does not support repeated start, i2c messsages should have the I2C_M_NOSTART flag set. Thanks to Patrick Boettcher for providing new firmware fixing the issue as well as example i2c code utilizing the interface. Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700.h | 3 + drivers/media/dvb/dvb-usb/dib0700_core.c | 108 +++++++++++++++++++- drivers/media/dvb/dvb-usb/dib0700_devices.c | 2 +- 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 66d4dc6ba46..cc0c51d82f2 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug; // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) #define REQUEST_SET_RC 0x11 +#define REQUEST_NEW_I2C_READ 0x12 +#define REQUEST_NEW_I2C_WRITE 0x13 #define REQUEST_GET_VERSION 0x15 struct dib0700_state { @@ -39,6 +41,7 @@ struct dib0700_state { u8 rc_toggle; u8 rc_counter; u8 is_dib7000pc; + u8 fw_use_new_i2c_api; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 595a04696c8..4daac864200 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ } /* - * I2C master xfer function + * I2C master xfer function (supported in 1.20 firmware) */ -static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num) +static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + int num) +{ + /* The new i2c firmware messages are more reliable and in particular + properly support i2c read calls not preceded by a write */ + + struct dvb_usb_device *d = i2c_get_adapdata(adap); + uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ + uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ + uint8_t en_start = 0; + uint8_t en_stop = 0; + uint8_t buf[255]; /* TBV: malloc ? */ + int result, i; + + /* Ensure nobody else hits the i2c bus while we're sending our + sequence of messages, (such as the remote control thread) */ + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + for (i = 0; i < num; i++) { + if (i == 0) { + /* First message in the transaction */ + en_start = 1; + } else if (!(msg[i].flags & I2C_M_NOSTART)) { + /* Device supports repeated-start */ + en_start = 1; + } else { + /* Not the first packet and device doesn't support + repeated start */ + en_start = 0; + } + if (i == (num - 1)) { + /* Last message in the transaction */ + en_stop = 1; + } + + if (msg[i].flags & I2C_M_RD) { + /* Read request */ + u16 index, value; + uint8_t i2c_dest; + + i2c_dest = (msg[i].addr << 1); + value = ((en_start << 7) | (en_stop << 6) | + (msg[i].len & 0x3F)) << 8 | i2c_dest; + /* I2C ctrl + FE bus; */ + index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); + + result = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev, 0), + REQUEST_NEW_I2C_READ, + USB_TYPE_VENDOR | USB_DIR_IN, + value, index, msg[i].buf, + msg[i].len, + USB_CTRL_GET_TIMEOUT); + if (result < 0) { + err("i2c read error (status = %d)\n", result); + break; + } + } else { + /* Write request */ + buf[0] = REQUEST_NEW_I2C_WRITE; + buf[1] = (msg[i].addr << 1); + buf[2] = (en_start << 7) | (en_stop << 6) | + (msg[i].len & 0x3F); + /* I2C ctrl + FE bus; */ + buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); + /* The Actual i2c payload */ + memcpy(&buf[4], msg[i].buf, msg[i].len); + + result = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev, 0), + REQUEST_NEW_I2C_WRITE, + USB_TYPE_VENDOR | USB_DIR_OUT, + 0, 0, buf, msg[i].len + 4, + USB_CTRL_GET_TIMEOUT); + if (result < 0) { + err("i2c write error (status = %d)\n", result); + break; + } + } + } + mutex_unlock(&d->i2c_mutex); + return i; +} + +/* + * I2C master xfer function (pre-1.20 firmware) + */ +static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + struct i2c_msg *msg, int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i,len; @@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num return i; } +static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct dib0700_state *st = d->priv; + + if (st->fw_use_new_i2c_api == 1) { + /* User running at least fw 1.20 */ + return dib0700_i2c_xfer_new(adap, msg, num); + } else { + /* Use legacy calls */ + return dib0700_i2c_xfer_legacy(adap, msg, num); + } +} + static u32 dib0700_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 110d9344bc9..2555e53b31d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1127,7 +1127,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ .usb_ctrl = DEVICE_SPECIFIC, \ - .firmware = "dvb-usb-dib0700-1.10.fw", \ + .firmware = "dvb-usb-dib0700-1.20.fw", \ .download_firmware = dib0700_download_firmware, \ .no_reconnect = 1, \ .size_of_priv = sizeof(struct dib0700_state), \ -- GitLab From 4d2858c65bbd9a98d109b3548b4742d7fd74dcb0 Mon Sep 17 00:00:00 2001 From: Peter Beutner Date: Sat, 6 Sep 2008 13:54:06 -0300 Subject: [PATCH 4150/5416] V4L/DVB (9040): TTUSB-DEC DVB-S: claim to have lock As reported by BOUWSMA Barry the readout of the signal status doesn't work on dec3000-s models. Since we don't know how to do it better, revert back to the old behaviour and always report a signal lock. Reported by Barry Bouwsma Signed-off-by: Peter Beutner Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-dec/ttusbdecfe.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index 443af24097f..21260aad1e5 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -38,7 +38,17 @@ struct ttusbdecfe_state { }; -static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe, + fe_status_t *status) +{ + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + return 0; +} + + +static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe, + fe_status_t *status) { struct ttusbdecfe_state* state = fe->demodulator_priv; u8 b[] = { 0x00, 0x00, 0x00, 0x00, @@ -251,7 +261,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = { .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings, - .read_status = ttusbdecfe_read_status, + .read_status = ttusbdecfe_dvbt_read_status, }; static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { @@ -273,7 +283,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { .set_frontend = ttusbdecfe_dvbs_set_frontend, - .read_status = ttusbdecfe_read_status, + .read_status = ttusbdecfe_dvbs_read_status, .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd, .set_voltage = ttusbdecfe_dvbs_set_voltage, -- GitLab From 8751aaa6c8be191171cd8c7db01a9b4e01892b08 Mon Sep 17 00:00:00 2001 From: Daniel Oliveira Nascimento Date: Sun, 7 Sep 2008 12:39:44 -0300 Subject: [PATCH 4151/5416] V4L/DVB (9041): Add support YUAN High-Tech STK7700D (1164:1f08) This patch extends the dib0700 driver to support the DVB-part of the Asus notebook M51Sn tv-tunner (USB-ID 1164:1f08). Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 2555e53b31d..a5e970ecab2 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1120,6 +1120,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1409,7 +1410,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 4, + .num_device_descs = 5, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1427,6 +1428,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[37], NULL }, { NULL }, }, + { "YUAN High-Tech STK7700PH", + { &dib0700_usb_id_table[38], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index e60e8731554..7bf5a1cdb49 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -225,6 +225,7 @@ #define USB_PID_ASUS_U3000 0x171f #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc +#define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 -- GitLab From 5769743ad345881911cee4e73ddf6120b00ed3eb Mon Sep 17 00:00:00 2001 From: Albert Comerma Date: Sun, 7 Sep 2008 12:43:33 -0300 Subject: [PATCH 4152/5416] V4L/DVB (9042): Add support for Asus My Cinema U3000 Hybrid This patch introduces support for dvb-t for the following dibcom based cards: Asus My Cinema U3000 Hybrid (USB-ID: 0b05:1736) Signed-off-by: Albert Comerma Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 5 +++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index a5e970ecab2..d08cd456209 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1121,6 +1121,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, + { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1432,6 +1433,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[38], NULL }, { NULL }, }, + { "Asus My Cinema-U3000Hybrid", + { &dib0700_usb_id_table[39], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 7bf5a1cdb49..8926db2fc48 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -223,6 +223,7 @@ #define USB_PID_GIGABYTE_U7000 0x7001 #define USB_PID_GIGABYTE_U8000 0x7002 #define USB_PID_ASUS_U3000 0x171f +#define USB_PID_ASUS_U3000H 0x1736 #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_YUAN_STK7700PH 0x1f08 -- GitLab From cb22cb5213192d2c0baaeec0ae4961e268916419 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 8 Sep 2008 05:42:42 -0300 Subject: [PATCH 4153/5416] V4L/DVB (9044): Add support for Pinnacle PCTV HD Pro 801e (ATSC only) Add digital support for the Pinnacle PCTV HD Pro 801e (usb id 2304:023a) Thanks to Patrick Boettcher for providing new firmware fixing the issue with the i2c that prevented the xc5000 from working. Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700.h | 1 + drivers/media/dvb/dvb-usb/dib0700_core.c | 7 +- drivers/media/dvb/dvb-usb/dib0700_devices.c | 111 ++++++++++++++++++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 4 files changed, 119 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index cc0c51d82f2..739193943c1 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -42,6 +42,7 @@ struct dib0700_state { u8 rc_counter; u8 is_dib7000pc; u8 fw_use_new_i2c_api; + u8 disable_streaming_master_mode; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 4daac864200..dd53cee3896 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -350,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) b[0] = REQUEST_ENABLE_VIDEO; b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ - b[2] = (0x01 << 4); /* Master mode */ + + if (st->disable_streaming_master_mode == 1) + b[2] = 0x00; + else + b[2] = (0x01 << 4); /* Master mode */ + b[3] = 0x00; deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index d08cd456209..7d9efd70212 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -14,6 +14,8 @@ #include "mt2060.h" #include "mt2266.h" #include "tuner-xc2028.h" +#include "xc5000.h" +#include "s5h1411.h" #include "dib0070.h" static int force_lna_activation; @@ -1078,6 +1080,89 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* S5H1411 */ +static struct s5h1411_config pinnacle_801e_config = { + .output_mode = S5H1411_PARALLEL_OUTPUT, + .gpio = S5H1411_GPIO_OFF, + .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, + .qam_if = S5H1411_IF_44000, + .vsb_if = S5H1411_IF_44000, + .inversion = S5H1411_INVERSION_OFF, + .status_mode = S5H1411_DEMODLOCKING +}; + +/* Pinnacle PCTV HD Pro 801e GPIOs map: + GPIO0 - currently unknown + GPIO1 - xc5000 tuner reset + GPIO2 - CX25843 sleep + GPIO3 - currently unknown + GPIO4 - currently unknown + GPIO6 - currently unknown + GPIO7 - currently unknown + GPIO9 - currently unknown + GPIO10 - CX25843 reset + */ +static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_state *st = adap->dev->priv; + + /* Make use of the new i2c functions from FW 1.20 */ + st->fw_use_new_i2c_api = 1; + + /* The s5h1411 requires the dib0700 to not be in master mode */ + st->disable_streaming_master_mode = 1; + + /* All msleep values taken from Windows USB trace */ + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(400); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(60); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0); + msleep(30); + + /* Put the CX25843 to sleep for now since we're in digital mode */ + dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); + + /* GPIOs are initialized, do the attach */ + adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config, + &adap->dev->i2c_adap); + return adap->fe == NULL ? -ENODEV : 0; +} + +int dib0700_xc5000_tuner_callback(void *priv, int command, int arg) +{ + struct dvb_usb_adapter *adap = priv; + + /* Reset the tuner */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); + msleep(330); /* from Windows USB trace */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); + msleep(330); /* from Windows USB trace */ + + return 0; +} + +static struct xc5000_config s5h1411_xc5000_tunerconfig = { + .i2c_address = 0x64, + .if_khz = 5380, + .tuner_callback = dib0700_xc5000_tuner_callback +}; + +static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) +{ + return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, + &s5h1411_xc5000_tunerconfig, adap) + == NULL ? -ENODEV : 0; +} + /* DVB-USB and USB stuff follows */ struct usb_device_id dib0700_usb_id_table[] = { /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, @@ -1122,6 +1207,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, +/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1442,6 +1528,31 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_key_map = dib0700_rc_keys, .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), .rc_query = dib0700_rc_query + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .frontend_attach = s5h1411_frontend_attach, + .tuner_attach = xc5000_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + .size_of_priv = sizeof(struct + dib0700_adapter_state), + }, + }, + + .num_device_descs = 1, + .devices = { + { "Pinnacle PCTV HD Pro USB Stick", + { &dib0700_usb_id_table[40], NULL }, + { NULL }, + }, + }, + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 8926db2fc48..38a23be68db 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -171,6 +171,7 @@ #define USB_PID_PINNACLE_PCTV71E 0x022b #define USB_PID_PINNACLE_PCTV72E 0x0236 #define USB_PID_PINNACLE_PCTV73E 0x0237 +#define USB_PID_PINNACLE_PCTV801E 0x023a #define USB_PID_PCTV_200E 0x020e #define USB_PID_PCTV_400E 0x020f #define USB_PID_PCTV_450E 0x0222 -- GitLab From a58843743ca0a774fbfc551adb2e5ecd04d96079 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 25 Sep 2008 06:21:11 -0300 Subject: [PATCH 4154/5416] V4L/DVB (9045): Add Pinnacle 801e dependencies to KConfig Support for the Pinnacle PCTV HD Pro 801e creates a dib0700 dependency on the xc5000 tuner and s5h1411 demodulator drivers. Update KConfig accordingly. Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index aee3b5dd651..5880f2d4513 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -72,9 +72,11 @@ config DVB_USB_DIB0700 select DVB_DIB7000P select DVB_DIB7000M select DVB_DIB3000MC + select DVB_S5H1411 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select DVB_TUNER_DIB0070 help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The -- GitLab From d2fc3bfcc3abd14ffd1191b37d2809e780919ef4 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 25 Sep 2008 06:22:23 -0300 Subject: [PATCH 4155/5416] V4L/DVB (9046): Add support for Non-Pro version of Pinnacle PCTV HD USB Stick Add USB ID for Pinnacle PCTV HD USB Stick. According to the USB trace and photos, the only difference is the removal of the port for the analog S-video/audio input. Thanks to Mike Pringle for providing the USB trace of the device starting up, and testing the support. Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 7d9efd70212..7e692b3b078 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1208,6 +1208,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1542,12 +1543,16 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { "Pinnacle PCTV HD Pro USB Stick", { &dib0700_usb_id_table[40], NULL }, { NULL }, }, + { "Pinnacle PCTV HD USB Stick", + { &dib0700_usb_id_table[41], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 38a23be68db..dfaf1d2574d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -172,6 +172,7 @@ #define USB_PID_PINNACLE_PCTV72E 0x0236 #define USB_PID_PINNACLE_PCTV73E 0x0237 #define USB_PID_PINNACLE_PCTV801E 0x023a +#define USB_PID_PINNACLE_PCTV801E_SE 0x023b #define USB_PID_PCTV_200E 0x020e #define USB_PID_PCTV_400E 0x020f #define USB_PID_PCTV_450E 0x0222 -- GitLab From 48aa739164ca6430b8b1da12ea367b44bb14ce82 Mon Sep 17 00:00:00 2001 From: Chris Rankin Date: Thu, 25 Sep 2008 06:52:24 -0300 Subject: [PATCH 4156/5416] V4L/DVB (9047): [PATCH] Add remote control support to Nova-TD (52009) This patch adds remote control support for the Hauppauge WinTV Nova-TD (Diversity) model. (That's the 52009 version.) It also adds the key-codes for the credit-card style remote control that comes with this particular adapter. Signed-off-by: Chris Rankin Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 44 ++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 7e692b3b078..565563e6810 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -679,6 +679,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { { 0x01, 0x7d, KEY_VOLUMEDOWN }, { 0x02, 0x42, KEY_CHANNELUP }, { 0x00, 0x7d, KEY_CHANNELDOWN }, + + /* Key codes for Nova-TD "credit card" remote control. */ + { 0x1d, 0x00, KEY_0 }, + { 0x1d, 0x01, KEY_1 }, + { 0x1d, 0x02, KEY_2 }, + { 0x1d, 0x03, KEY_3 }, + { 0x1d, 0x04, KEY_4 }, + { 0x1d, 0x05, KEY_5 }, + { 0x1d, 0x06, KEY_6 }, + { 0x1d, 0x07, KEY_7 }, + { 0x1d, 0x08, KEY_8 }, + { 0x1d, 0x09, KEY_9 }, + { 0x1d, 0x0a, KEY_TEXT }, + { 0x1d, 0x0d, KEY_MENU }, + { 0x1d, 0x0f, KEY_MUTE }, + { 0x1d, 0x10, KEY_VOLUMEUP }, + { 0x1d, 0x11, KEY_VOLUMEDOWN }, + { 0x1d, 0x12, KEY_CHANNEL }, + { 0x1d, 0x14, KEY_UP }, + { 0x1d, 0x15, KEY_DOWN }, + { 0x1d, 0x16, KEY_LEFT }, + { 0x1d, 0x17, KEY_RIGHT }, + { 0x1d, 0x1c, KEY_TV }, + { 0x1d, 0x1e, KEY_NEXT }, + { 0x1d, 0x1f, KEY_BACK }, + { 0x1d, 0x20, KEY_CHANNELUP }, + { 0x1d, 0x21, KEY_CHANNELDOWN }, + { 0x1d, 0x24, KEY_LAST }, + { 0x1d, 0x25, KEY_OK }, + { 0x1d, 0x30, KEY_PAUSE }, + { 0x1d, 0x32, KEY_REWIND }, + { 0x1d, 0x34, KEY_FASTFORWARD }, + { 0x1d, 0x35, KEY_PLAY }, + { 0x1d, 0x36, KEY_STOP }, + { 0x1d, 0x37, KEY_RECORD }, + { 0x1d, 0x3b, KEY_GOTO }, + { 0x1d, 0x3d, KEY_POWER }, }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ @@ -1383,7 +1420,12 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[31], NULL }, { NULL }, } - } + }, + + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, -- GitLab From ebb8d68a5c8c236acd8e8cf8f0d6046e027a8e21 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 10 Sep 2008 01:39:20 -0300 Subject: [PATCH 4157/5416] V4L/DVB (9048): add a general-purpose callback pointer to struct dvb_frontend Remove tuner_callback pointers from tuner driver configuration and private state structures, replaced with a general-purpose callback pointer within struct dvb_frontend. A new parameter is added to the callback function, called component. This allows us to use this callback pointer by frontend components other than the tuner, if need be. So far, this is only used by tuner drivers. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 1c575402814..3055301ff3c 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -220,6 +220,8 @@ struct dvb_frontend { void *sec_priv; void *analog_demod_priv; struct dtv_frontend_properties dtv_property_cache; +#define DVB_FRONTEND_COMPONENT_TUNER 0 + int (*callback)(void *adapter_priv, int component, int cmd, int arg); }; extern int dvb_register_frontend(struct dvb_adapter *dvb, -- GitLab From d7cba043d7ec840d67bd5143779d1febe7d83407 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 12 Sep 2008 13:31:45 -0300 Subject: [PATCH 4158/5416] V4L/DVB (9049): convert tuner drivers to use dvb_frontend->callback Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda827x.c | 12 +++--- drivers/media/common/tuners/tda827x.h | 1 - drivers/media/common/tuners/tda8290.c | 4 +- drivers/media/common/tuners/tda8290.h | 1 - drivers/media/common/tuners/tuner-xc2028.c | 41 +++++++++++---------- drivers/media/common/tuners/tuner-xc2028.h | 2 - drivers/media/common/tuners/xc5000.c | 8 ++-- drivers/media/common/tuners/xc5000.h | 2 - drivers/media/dvb/dvb-usb/cxusb.c | 7 +++- drivers/media/dvb/dvb-usb/dib0700_devices.c | 8 ++-- drivers/media/video/au0828/au0828-cards.c | 2 +- drivers/media/video/au0828/au0828-dvb.c | 3 +- drivers/media/video/au0828/au0828.h | 3 +- drivers/media/video/cx18/cx18-gpio.c | 2 +- drivers/media/video/cx18/cx18-gpio.h | 2 +- drivers/media/video/cx23885/cx23885-cards.c | 2 +- drivers/media/video/cx23885/cx23885-dvb.c | 12 +----- drivers/media/video/cx23885/cx23885.h | 2 +- drivers/media/video/cx88/cx88-cards.c | 24 ++++++++++-- drivers/media/video/cx88/cx88-dvb.c | 40 +------------------- drivers/media/video/cx88/cx88.h | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-dvb.c | 3 +- drivers/media/video/em28xx/em28xx.h | 2 +- drivers/media/video/ivtv/ivtv-gpio.c | 2 +- drivers/media/video/ivtv/ivtv-gpio.h | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 7 +--- drivers/media/video/saa7134/saa7134.h | 2 +- drivers/media/video/tuner-core.c | 10 ++--- include/media/tuner.h | 2 +- 31 files changed, 90 insertions(+), 124 deletions(-) diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c index 8555d9cf905..4a74f65e759 100644 --- a/drivers/media/common/tuners/tda827x.c +++ b/drivers/media/common/tuners/tda827x.c @@ -447,17 +447,19 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, else arg = 0; } - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - gp_func, arg); + if (fe->callback) + fe->callback(priv->i2c_adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, + gp_func, arg); buf[1] = high ? 0 : 1; if (priv->cfg->config == 2) buf[1] = high ? 1 : 0; i2c_transfer(priv->i2c_adap, &msg, 1); break; case 3: /* switch with GPIO of saa713x */ - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high); + if (fe->callback) + fe->callback(priv->i2c_adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, 0, high); break; } } diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h index 7850a9a1dc8..7d72ce0a0c2 100644 --- a/drivers/media/common/tuners/tda827x.h +++ b/drivers/media/common/tuners/tda827x.h @@ -36,7 +36,6 @@ struct tda827x_config /* interface to tda829x driver */ unsigned int config; int switch_addr; - int (*tuner_callback) (void *dev, int command, int arg); void (*agcf)(struct dvb_frontend *fe); }; diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 91204d3f282..c112bdd4e0f 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -672,10 +672,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; priv->i2c_props.name = "tda829x"; - if (cfg) { + if (cfg) priv->cfg.config = cfg->lna_cfg; - priv->cfg.tuner_callback = cfg->tuner_callback; - } if (tda8290_probe(&priv->i2c_props) == 0) { priv->ver = TDA8290; diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h index aa074f3f0c0..7e288b26fcc 100644 --- a/drivers/media/common/tuners/tda8290.h +++ b/drivers/media/common/tuners/tda8290.h @@ -22,7 +22,6 @@ struct tda829x_config { unsigned int lna_cfg; - int (*tuner_callback) (void *dev, int command, int arg); unsigned int probe_tuner:1; #define TDA829X_PROBE_TUNER 0 diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 4dd1d2421cc..fc82d154c8c 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -71,9 +71,6 @@ struct firmware_properties { struct xc2028_data { struct list_head hybrid_tuner_instance_list; struct tuner_i2c_props i2c_props; - int (*tuner_callback) (void *dev, - int command, int arg); - void *video_dev; __u32 frequency; struct firmware_description *firm; @@ -492,6 +489,23 @@ ret: return i; } +static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg) +{ + struct xc2028_data *priv = fe->tuner_priv; + + /* analog side (tuner-core) uses i2c_adap->algo_data. + * digital side is not guaranteed to have algo_data defined. + * + * digital side will always have fe->dvb defined. + * analog side (tuner-core) doesn't (yet) define fe->dvb. + */ + + return (!fe->callback) ? -EINVAL : + fe->callback(((fe->dvb) && (fe->dvb->priv)) ? + fe->dvb->priv : priv->i2c_props.adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, cmd, arg); +} + static int load_firmware(struct dvb_frontend *fe, unsigned int type, v4l2_std_id *id) { @@ -530,8 +544,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, if (!size) { /* Special callback command received */ - rc = priv->tuner_callback(priv->video_dev, - XC2028_TUNER_RESET, 0); + rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); if (rc < 0) { tuner_err("Error at RESET code %d\n", (*p) & 0x7f); @@ -542,8 +555,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, if (size >= 0xff00) { switch (size) { case 0xff00: - rc = priv->tuner_callback(priv->video_dev, - XC2028_RESET_CLK, 0); + rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0); if (rc < 0) { tuner_err("Error at RESET code %d\n", (*p) & 0x7f); @@ -715,8 +727,7 @@ retry: memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); /* Reset is needed before loading firmware */ - rc = priv->tuner_callback(priv->video_dev, - XC2028_TUNER_RESET, 0); + rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); if (rc < 0) goto fail; @@ -933,7 +944,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, The reset CLK is needed only with tm6000. Driver should work fine even if this fails. */ - priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); + do_tuner_callback(fe, XC2028_RESET_CLK, 1); msleep(10); @@ -1177,20 +1188,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, break; case 1: /* new tuner instance */ - priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; mutex_init(&priv->lock); - /* analog side (tuner-core) uses i2c_adap->algo_data. - * digital side is not guaranteed to have algo_data defined. - * - * digital side will always have fe->dvb defined. - * analog side (tuner-core) doesn't (yet) define fe->dvb. - */ - priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ? - fe->dvb->priv : cfg->i2c_adap->algo_data; - fe->tuner_priv = priv; break; case 2: diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h index 2c5b6282b56..1af69f49f8e 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/common/tuners/tuner-xc2028.h @@ -39,9 +39,7 @@ struct xc2028_ctrl { struct xc2028_config { struct i2c_adapter *i2c_adap; u8 i2c_addr; - void *video_dev; struct xc2028_ctrl *ctrl; - int (*callback) (void *dev, int command, int arg); }; /* xc2028 commands for callback */ diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index ccc4dae4126..f9c2bb917f5 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -58,8 +58,6 @@ struct xc5000_priv { u32 bandwidth; u8 video_standard; u8 rf_mode; - - int (*tuner_callback) (void *priv, int command, int arg); }; /* Misc Defines */ @@ -232,10 +230,11 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); - if (priv->tuner_callback) { - ret = priv->tuner_callback(((fe->dvb) && (fe->dvb->priv)) ? + if (fe->callback) { + ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ? fe->dvb->priv : priv->i2c_props.adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, XC5000_TUNER_RESET, 0); if (ret) printk(KERN_ERR "xc5000: reset failed\n"); @@ -975,7 +974,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, /* new tuner instance */ priv->bandwidth = BANDWIDTH_6_MHZ; priv->if_khz = cfg->if_khz; - priv->tuner_callback = cfg->tuner_callback; fe->tuner_priv = priv; break; diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index fa0321cfd17..cf1a558e0e7 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -30,8 +30,6 @@ struct i2c_adapter; struct xc5000_config { u8 i2c_address; u32 if_khz; - - int (*tuner_callback) (void *priv, int command, int arg); }; /* xc5000 callback command */ diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 1a746127cbd..406d7fba369 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -742,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) +static int dvico_bluebird_xc2028_callback(void *ptr, int component, + int command, int arg) { struct dvb_usb_adapter *adap = ptr; struct dvb_usb_device *d = adap->dev; @@ -770,7 +771,6 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) struct xc2028_config cfg = { .i2c_adap = &adap->dev->i2c_adap, .i2c_addr = 0x61, - .callback = dvico_bluebird_xc2028_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -778,6 +778,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) .demod = XC3028_FE_ZARLINK456, }; + /* FIXME: generalize & move to common area */ + adap->fe->callback = dvico_bluebird_xc2028_callback; + fe = dvb_attach(xc2028_attach, adap->fe, &cfg); if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) return -EIO; diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 565563e6810..8b74e13a646 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -368,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, }; -static int stk7700ph_xc3028_callback(void *ptr, int command, int arg) +static int stk7700ph_xc3028_callback(void *ptr, int component, + int command, int arg) { struct dvb_usb_adapter *adap = ptr; @@ -396,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { static struct xc2028_config stk7700ph_xc3028_config = { .i2c_addr = 0x61, - .callback = stk7700ph_xc3028_callback, .ctrl = &stk7700ph_xc3028_ctrl, }; @@ -437,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) DIBX000_I2C_INTERFACE_TUNER, 1); stk7700ph_xc3028_config.i2c_adap = tun_i2c; - stk7700ph_xc3028_config.video_dev = adap; + + /* FIXME: generalize & move to common area */ + adap->fe->callback = stk7700ph_xc3028_callback; return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) == NULL ? -ENODEV : 0; diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index ed48908a903..5f07a8a072b 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { /* Tuner callback function for au0828 boards. Currently only needed * for HVR1500Q, which has an xc5000 tuner. */ -int au0828_tuner_callback(void *priv, int command, int arg) +int au0828_tuner_callback(void *priv, int component, int command, int arg) { struct au0828_dev *dev = priv; diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 96246959dce..a52abce16e1 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -53,7 +53,6 @@ static struct au8522_config hauppauge_woodbury_config = { static struct xc5000_config hauppauge_hvr950q_tunerconfig = { .i2c_address = 0x61, .if_khz = 6000, - .tuner_callback = au0828_tuner_callback }; static struct mxl5007t_config mxl5007t_hvr950q_config = { @@ -389,6 +388,8 @@ int au0828_dvb_register(struct au0828_dev *dev) __func__); return -1; } + /* define general-purpose callback pointer */ + dvb->frontend->callback = au0828_tuner_callback; /* register everything */ ret = dvb_register(dev); diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 4f10ff30013..9d6a1161dc9 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -103,7 +103,8 @@ extern int au0828_debug; extern struct au0828_board au0828_boards[]; extern struct usb_device_id au0828_usb_id_table[]; extern void au0828_gpio_setup(struct au0828_dev *dev); -extern int au0828_tuner_callback(void *priv, int command, int arg); +extern int au0828_tuner_callback(void *priv, int component, + int command, int arg); extern void au0828_card_setup(struct au0828_dev *dev); /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 3bdffbf7a96..0e560421989 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -152,7 +152,7 @@ void cx18_gpio_init(struct cx18 *cx) } /* Xceive tuner reset function */ -int cx18_reset_tuner_gpio(void *dev, int cmd, int value) +int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) { struct i2c_algo_bit_data *algo = dev; struct cx18_i2c_algo_callback_data *cb_data = algo->data; diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 22cd7ddf855..beb7424b994 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h @@ -23,5 +23,5 @@ void cx18_gpio_init(struct cx18 *cx); void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); void cx18_reset_ir_gpio(void *data); -int cx18_reset_tuner_gpio(void *dev, int cmd, int value); +int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index ccea8de7c7d..2cda15f829f 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -337,7 +337,7 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) dev->name, tv.model); } -int cx23885_tuner_callback(void *priv, int command, int arg) +int cx23885_tuner_callback(void *priv, int component, int command, int arg) { struct cx23885_tsport *port = priv; struct cx23885_dev *dev = port->dev; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 3b54f139180..6c5475d7d32 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -189,13 +189,11 @@ static struct s5h1411_config dvico_s5h1411_config = { static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback, }; static struct xc5000_config dvico_xc5000_tunerconfig = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback, }; static struct tda829x_config tda829x_no_probe = { @@ -403,8 +401,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -443,8 +439,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, @@ -485,8 +479,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -512,8 +504,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -536,6 +526,8 @@ static int dvb_register(struct cx23885_tsport *port) printk("%s: frontend initialization failed\n", dev->name); return -1; } + /* define general-purpose callback pointer */ + port->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 4e0fcb3f7fc..ba4e0aaed46 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -411,7 +411,7 @@ extern const unsigned int cx23885_bcount; extern struct cx23885_subid cx23885_subids[]; extern const unsigned int cx23885_idcount; -extern int cx23885_tuner_callback(void *priv, int command, int arg); +extern int cx23885_tuner_callback(void *priv, int component, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 16bb9c35fc7..b5a25094c9e 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2308,9 +2308,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core, { switch (command) { case XC2028_TUNER_RESET: - cx_write(MO_GP0_IO, 0x101000); - mdelay(5); - cx_set(MO_GP0_IO, 0x101010); + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + /* GPIO-4 xc3028 tuner */ + + cx_set(MO_GP0_IO, 0x00001000); + cx_clear(MO_GP0_IO, 0x00000010); + msleep(100); + cx_set(MO_GP0_IO, 0x00000010); + msleep(100); + break; + default: + cx_write(MO_GP0_IO, 0x101000); + mdelay(5); + cx_set(MO_GP0_IO, 0x101010); + } break; default: return -EINVAL; @@ -2419,6 +2431,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_PROLINK_PV_8000GT: return cx88_pv_8000gt_callback(core, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); } @@ -2486,7 +2499,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, return 0; /* Should never be here */ } -int cx88_tuner_callback(void *priv, int command, int arg) +int cx88_tuner_callback(void *priv, int component, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core; @@ -2503,6 +2516,9 @@ int cx88_tuner_callback(void *priv, int command, int arg) return -EINVAL; } + if (component != DVB_FRONTEND_COMPONENT_TUNER) + return -EINVAL; + switch (core->board.tuner_type) { case TUNER_XC2028: info_printk(core, "Calling XC2028/3028 callback\n"); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index cd368b512d1..6751f36e061 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -405,40 +405,6 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } -static int cx88_pci_nano_callback(void *ptr, int command, int arg) -{ - struct cx88_core *core = ptr; - - switch (command) { - case XC2028_TUNER_RESET: - /* Send the tuner in then out of reset */ - dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); - - switch (core->boardnr) { - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - /* GPIO-4 xc3028 tuner */ - - cx_set(MO_GP0_IO, 0x00001000); - cx_clear(MO_GP0_IO, 0x00000010); - msleep(100); - cx_set(MO_GP0_IO, 0x00000010); - msleep(100); - break; - } - - break; - case XC2028_RESET_CLK: - dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); - break; - default: - dprintk(1, "%s: unknown command %d, arg %d\n", __func__, - command, arg); - return -EINVAL; - } - - return 0; -} - static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, @@ -486,7 +452,6 @@ static struct s5h1409_config kworld_atsc_120_config = { static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx88_tuner_callback, }; static struct zl10353_config cx88_geniatech_x8000_mt = { @@ -507,7 +472,6 @@ static struct s5h1411_config dvico_fusionhdtv7_config = { static struct xc5000_config dvico_fusionhdtv7_tuner_config = { .i2c_address = 0xc2 >> 1, .if_khz = 5380, - .tuner_callback = cx88_tuner_callback, }; static int attach_xc3028(u8 addr, struct cx8802_dev *dev) @@ -518,7 +482,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, .ctrl = &ctl, - .callback = cx88_tuner_callback, }; if (!dev->dvb.frontend) { @@ -912,7 +875,6 @@ static int dvb_register(struct cx8802_dev *dev) struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, - .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -1035,6 +997,8 @@ static int dvb_register(struct cx8802_dev *dev) core->name); return -EINVAL; } + /* define general-purpose callback pointer */ + dev->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e17bd513b58..30b750ee856 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -607,7 +607,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, /* ----------------------------------------------------------- */ /* cx88-cards.c */ -extern int cx88_tuner_callback(void *dev, int command, int arg); +extern int cx88_tuner_callback(void *dev, int component, int command, int arg); extern int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci); extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 01804fac6aa..d65d0572403 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1271,7 +1271,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, }; -int em28xx_tuner_callback(void *ptr, int command, int arg) +int em28xx_tuner_callback(void *ptr, int component, int command, int arg) { int rc = 0; struct em28xx *dev = ptr; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index ea4f2a97bd2..855ad3940b2 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -249,7 +249,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; - cfg.callback = em28xx_tuner_callback; if (!dev->dvb->frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " @@ -474,6 +473,8 @@ static int dvb_init(struct em28xx *dev) result = -EINVAL; goto out_free; } + /* define general-purpose callback pointer */ + dvb->frontend->callback = em28xx_tuner_callback; /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index d992280613b..82781178e0a 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -528,7 +528,7 @@ extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); -int em28xx_tuner_callback(void *ptr, int command, int arg); +int em28xx_tuner_callback(void *ptr, int component, int command, int arg); /* Provided by em28xx-input.c */ /* TODO: Check if the standard get_key handlers on ir-common can be used */ diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index bc22905ea20..74a44844cca 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c @@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) } /* Xceive tuner reset function */ -int ivtv_reset_tuner_gpio(void *dev, int cmd, int value) +int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) { struct i2c_algo_bit_data *algo = dev; struct ivtv *itv = algo->data; diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h index 964a265d91a..48b6291613a 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ b/drivers/media/video/ivtv/ivtv-gpio.h @@ -24,7 +24,7 @@ /* GPIO stuff */ void ivtv_gpio_init(struct ivtv *itv); void ivtv_reset_ir_gpio(struct ivtv *itv); -int ivtv_reset_tuner_gpio(void *dev, int cmd, int value); +int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); #endif diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3c2f09fb044..622d3ba5a1e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5576,7 +5576,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, return 0; } -int saa7134_tuner_callback(void *priv, int command, int arg) +int saa7134_tuner_callback(void *priv, int component, int command, int arg) { struct saa7134_dev *dev = priv; if (dev != NULL) { diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 7fa6ce76642..0dd6b988820 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -553,7 +553,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, /* ------------------------------------------------------------------ */ static struct tda827x_config tda827x_cfg_0 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 0, @@ -561,7 +560,6 @@ static struct tda827x_config tda827x_cfg_0 = { }; static struct tda827x_config tda827x_cfg_1 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 1, @@ -569,7 +567,6 @@ static struct tda827x_config tda827x_cfg_1 = { }; static struct tda827x_config tda827x_cfg_2 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 2, @@ -577,7 +574,6 @@ static struct tda827x_config tda827x_cfg_2 = { }; static struct tda827x_config tda827x_cfg_2_sw42 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 2, @@ -836,7 +832,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) } static struct tda827x_config ads_duo_cfg = { - .tuner_callback = saa7134_tuner_callback, .init = ads_duo_tuner_init, .sleep = ads_duo_tuner_sleep, .config = 0 @@ -1366,6 +1361,8 @@ static int dvb_init(struct saa7134_dev *dev) printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; } + /* define general-purpose callback pointer */ + dev->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index cbfdac27b69..4005335c4f5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -653,7 +653,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; extern int saa7134_board_init1(struct saa7134_dev *dev); extern int saa7134_board_init2(struct saa7134_dev *dev); -int saa7134_tuner_callback(void *priv, int command, int arg); +int saa7134_tuner_callback(void *priv, int component, int command, int arg); /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 39c7b9b835a..4a7735c6c1a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -92,7 +92,6 @@ struct tuner { unsigned int type; /* chip type id */ unsigned int config; - int (*tuner_callback) (void *dev, int command, int arg); const char *name; }; @@ -346,7 +345,7 @@ static struct xc5000_config xc5000_cfg; static void set_type(struct i2c_client *c, unsigned int type, unsigned int new_mode_mask, unsigned int new_config, - int (*tuner_callback) (void *dev, int command,int arg)) + int (*tuner_callback) (void *dev, int component, int cmd, int arg)) { struct tuner *t = i2c_get_clientdata(c); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; @@ -362,7 +361,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->config = new_config; if (tuner_callback != NULL) { tuner_dbg("defining GPIO callback\n"); - t->tuner_callback = tuner_callback; + t->fe.callback = tuner_callback; } if (t->mode == T_UNINITIALIZED) { @@ -385,7 +384,6 @@ static void set_type(struct i2c_client *c, unsigned int type, { struct tda829x_config cfg = { .lna_cfg = t->config, - .tuner_callback = t->tuner_callback, }; if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, t->i2c->addr, &cfg)) @@ -433,7 +431,6 @@ static void set_type(struct i2c_client *c, unsigned int type, struct xc2028_config cfg = { .i2c_adap = t->i2c->adapter, .i2c_addr = t->i2c->addr, - .callback = t->tuner_callback, }; if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) goto attach_failed; @@ -450,7 +447,6 @@ static void set_type(struct i2c_client *c, unsigned int type, xc5000_cfg.i2c_address = t->i2c->addr; xc5000_cfg.if_khz = 5380; - xc5000_cfg.tuner_callback = t->tuner_callback; if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; @@ -1224,7 +1220,7 @@ register_client: } else { t->mode = V4L2_TUNER_DIGITAL_TV; } - set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); + set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); list_add_tail(&t->list, &tuner_list); return 0; } diff --git a/include/media/tuner.h b/include/media/tuner.h index ba818985cc8..67c1f514d0e 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -179,7 +179,7 @@ struct tuner_setup { unsigned int type; /* Tuner type */ unsigned int mode_mask; /* Allowed tuner modes */ unsigned int config; /* configuraion for more complex tuners */ - int (*tuner_callback) (void *dev, int command,int arg); + int (*tuner_callback) (void *dev, int component, int cmd, int arg); }; #endif /* __KERNEL__ */ -- GitLab From 767f3b3bf23244d52be0492df20b0eaf14f501c5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 25 Sep 2008 09:47:07 -0300 Subject: [PATCH 4159/5416] V4L/DVB (9051): dib0700: use dvb_frontend->callback for xc5000 gpio reset The tuner_callback function pointer from struct xc5000_config has been removed. Use dvb_frontend->callback instead. Also, mark function dib0700_xc5000_tuner_callback as static int. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 8b74e13a646..9891ca0924a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1176,7 +1176,8 @@ static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } -int dib0700_xc5000_tuner_callback(void *priv, int command, int arg) +static int dib0700_xc5000_tuner_callback(void *priv, int component, + int command, int arg) { struct dvb_usb_adapter *adap = priv; @@ -1192,14 +1193,16 @@ int dib0700_xc5000_tuner_callback(void *priv, int command, int arg) static struct xc5000_config s5h1411_xc5000_tunerconfig = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = dib0700_xc5000_tuner_callback }; static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) { return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, - &s5h1411_xc5000_tunerconfig, adap) + &s5h1411_xc5000_tunerconfig) == NULL ? -ENODEV : 0; + + /* FIXME: generalize & move to common area */ + adap->fe->callback = dib0700_xc5000_tuner_callback; } /* DVB-USB and USB stuff follows */ -- GitLab From 0975fc68719c75cbe14132c6f0dead57cd4d5210 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Sep 2008 02:24:44 -0300 Subject: [PATCH 4160/5416] V4L/DVB (9055): tuner-xc2028: Do a better job selecting firmware type Firmware selection is very tricky on this device. This patch do a better selection of the proper firmware type, by using a code to hint if the firmware to be loaded should be D2620 or D2633. It also allows overriding the hint at the control structure. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tuner-xc2028.c | 33 ++++++++++++++++------ drivers/media/common/tuners/tuner-xc2028.h | 8 +++++- drivers/media/video/cx23885/cx23885-dvb.c | 3 +- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index fc82d154c8c..b65e6803e6c 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -1013,11 +1013,6 @@ static int xc2028_set_params(struct dvb_frontend *fe, tuner_dbg("%s called\n", __func__); - if (priv->ctrl.d2633) - type |= D2633; - else - type |= D2620; - switch(fe->ops.info.type) { case FE_OFDM: bw = p->u.ofdm.bandwidth; @@ -1032,10 +1027,8 @@ static int xc2028_set_params(struct dvb_frontend *fe, break; case FE_ATSC: bw = BANDWIDTH_6_MHZ; - /* The only ATSC firmware (at least on v2.7) is D2633, - so overrides ctrl->d2633 */ - type |= ATSC| D2633; - type &= ~D2620; + /* The only ATSC firmware (at least on v2.7) is D2633 */ + type |= ATSC | D2633; break; /* DVB-S is not supported */ default: @@ -1068,6 +1061,28 @@ static int xc2028_set_params(struct dvb_frontend *fe, tuner_err("error: bandwidth not supported.\n"); }; + /* + Selects between D2633 or D2620 firmware. + It doesn't make sense for ATSC, since it should be D2633 on all cases + */ + if (fe->ops.info.type != FE_ATSC) { + switch (priv->ctrl.type) { + case XC2028_D2633: + type |= D2633; + break; + case XC2028_D2620: + type |= D2620; + break; + case XC2028_AUTO: + default: + /* Zarlink seems to need D2633 */ + if (priv->ctrl.demod == XC3028_FE_ZARLINK456) + type |= D2633; + else + type |= D2620; + } + } + /* All S-code tables need a 200kHz shift */ if (priv->ctrl.demod) demod = priv->ctrl.demod + 200; diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h index 1af69f49f8e..19de7928a74 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/common/tuners/tuner-xc2028.h @@ -24,16 +24,22 @@ #define XC3028_FE_ZARLINK456 4560 #define XC3028_FE_CHINA 5200 +enum firmware_type { + XC2028_AUTO = 0, /* By default, auto-detects */ + XC2028_D2633, + XC2028_D2620, +}; + struct xc2028_ctrl { char *fname; int max_len; unsigned int scode_table; unsigned int mts :1; - unsigned int d2633 :1; unsigned int input1:1; unsigned int vhfbw7:1; unsigned int uhfbw8:1; unsigned int demod; + enum firmware_type type:2; }; struct xc2028_config { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 6c5475d7d32..24bd18327aa 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -444,7 +444,8 @@ static int dvb_register(struct cx23885_tsport *port) .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = 5000, - .d2633 = 1 + /* This is true for all demods with v36 firmware? */ + .type = XC2028_D2633, }; fe = dvb_attach(xc2028_attach, -- GitLab From 8acdbcfd90a1954dcea36c2da4429c305813d470 Mon Sep 17 00:00:00 2001 From: David Bentham Date: Sun, 28 Sep 2008 16:29:51 -0300 Subject: [PATCH 4161/5416] V4L/DVB (9057): saa7134: Hauppauge HVR-1110, support for radio and analog audio in The audio switch is at 0x100 and radio on gpio 21. Tested-by: Thomas Genty Signed-off-by: David Bentham Reviewed-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 622d3ba5a1e..4f32486a10d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3260,6 +3260,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { /* Thomas Genty */ + /* David Bentham */ .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, @@ -3268,23 +3269,26 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tuner_config = 1, .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200100, .inputs = {{ .name = name_tv, .vmux = 1, .amux = TV, .tv = 1, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - }}, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, .radio = { .name = name_radio, - .amux = TV, + .amux = TV, + .gpio = 0x0200100, }, }, [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { -- GitLab From 27cf8fd14e44d17b22f3591ef65d6920fb9e0409 Mon Sep 17 00:00:00 2001 From: Shane Date: Thu, 11 Sep 2008 16:14:09 -0300 Subject: [PATCH 4162/5416] V4L/DVB (9058): spca561: while balance -> white balance typo Cc: Jean-Francois Moine Cc: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 95fcfcb9e31..e9b0d81f938 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1064,7 +1064,7 @@ static struct ctrl sd_ctrls_12a[] = { { .id = V4L2_CID_DO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "While Balance", + .name = "White Balance", .minimum = WHITE_MIN, .maximum = WHITE_MAX, .step = 1, -- GitLab From bf1ece6a4f30f05b227f2ec59fa0d45b5db186d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Jun 2008 17:03:00 -0300 Subject: [PATCH 4163/5416] V4L/DVB (9059): saa7134: Add support for Encore version 5.3 board Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/common/ir-keymaps.c | 43 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 43 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-input.c | 6 +++ drivers/media/video/saa7134/saa7134.h | 1 + include/media/ir-common.h | 1 + 6 files changed, 95 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index c121f44aefc..14383640393 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -146,3 +146,4 @@ 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] 146 -> ASUSTeK P7131 Analog 147 -> Asus Tiger 3in1 [1043:4878] +148 -> Encore ENLTV-FM v5.3 [1a7f:2008] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index aedfabd5738..891f3b30be0 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2288,3 +2288,46 @@ IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { [0x2a] = KEY_MENU, }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); + +/* Encore ENLTV-FM v5.3 + Mauro Carvalho Chehab + */ +IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { + [0x10] = KEY_POWER2, + [0x06] = KEY_MUTE, + + [0x09] = KEY_1, + [0x1d] = KEY_2, + [0x1f] = KEY_3, + [0x19] = KEY_4, + [0x1b] = KEY_5, + [0x11] = KEY_6, + [0x17] = KEY_7, + [0x12] = KEY_8, + [0x16] = KEY_9, + [0x48] = KEY_0, + + [0x04] = KEY_LIST, /* -/-- */ + [0x40] = KEY_LAST, /* recall */ + + [0x02] = KEY_MODE, /* TV/AV */ + [0x05] = KEY_SHUFFLE, /* SNAPSHOT */ + + [0x4c] = KEY_CHANNELUP, /* UP */ + [0x00] = KEY_CHANNELDOWN, /* DOWN */ + [0x0d] = KEY_VOLUMEUP, /* RIGHT */ + [0x15] = KEY_VOLUMEDOWN, /* LEFT */ + [0x49] = KEY_ENTER, /* OK */ + + [0x54] = KEY_RECORD, + [0x4d] = KEY_PLAY, /* pause */ + + [0x1e] = KEY_UP, /* video setting */ + [0x0e] = KEY_RIGHT, /* <- */ + [0x1a] = KEY_LEFT, /* -> */ + + [0x0a] = KEY_DOWN, /* video default */ + [0x0c] = KEY_ZOOM, /* hide pannel */ + [0x47] = KEY_SLEEP, /* shutdown */ +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 4f32486a10d..3ad5b941dfb 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3392,6 +3392,42 @@ struct saa7134_board saa7134_boards[] = { .amux = 0, }, }, + [SAA7134_BOARD_ENCORE_ENLTV_FM53] = { + .name = "Encore ENLTV-FM v5.3", + .audio_clock = 0x00200000, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x7000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = 1, + .tv = 1, + .gpio = 0x50000, + }, { + .name = name_comp1, + .vmux = 3, + .amux = 2, + .gpio = 0x2000, + }, { + .name = name_svideo, + .vmux = 8, + .amux = 2, + .gpio = 0x2000, + } }, + .radio = { + .name = name_radio, + .vmux = 1, + .amux = 1, + }, + .mute = { + .name = name_mute, + .gpio = 0xf000, + .amux = 0, + }, + }, [SAA7134_BOARD_CINERGY_HT_PCI] = { .name = "Terratec Cinergy HT PCI", .audio_clock = 0x00187de7, @@ -5190,6 +5226,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x230f, .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x1a7f, + .subdevice = 0x2008, + .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x153b, @@ -5684,6 +5726,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_A16AR: case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: + case SAA7134_BOARD_ENCORE_ENLTV_FM53: case SAA7134_BOARD_10MOONSTVMASTER3: case SAA7134_BOARD_BEHOLD_401: case SAA7134_BOARD_BEHOLD_403: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ac6beb2df83..f1767309b1e 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -509,6 +509,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x040000; polling = 50; // ms break; + case SAA7134_BOARD_ENCORE_ENLTV_FM53: + ir_codes = ir_codes_encore_enltv_fm53; + mask_keydown = 0x0040000; + mask_keycode = 0x00007f; + nec_gpio = 1; + break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = ir_codes_encore_enltv; mask_keycode = 0x5f80000; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4005335c4f5..982003d49dd 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -270,6 +270,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M103 145 #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 +#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 6f8ef35de4a..b029987d18c 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -153,6 +153,7 @@ extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE]; #endif -- GitLab From 36f6bb97caa772d7dc42250db74253e0867a444a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Jun 2008 17:03:00 -0300 Subject: [PATCH 4164/5416] V4L/DVB (9060): saa7134: Add support for Avermedia PCI pure analog (M135A) Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/common/ir-keymaps.c | 50 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 41 +++++++++++++++++ drivers/media/video/saa7134/saa7134-input.c | 6 +++ drivers/media/video/saa7134/saa7134.h | 1 + include/media/ir-common.h | 1 + 6 files changed, 100 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 14383640393..2023c4020ac 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -147,3 +147,4 @@ 146 -> ASUSTeK P7131 Analog 147 -> Asus Tiger 3in1 [1043:4878] 148 -> Encore ENLTV-FM v5.3 [1a7f:2008] +149 -> Avermedia PCI pure analog (M135A) [1461:f11d] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 891f3b30be0..f061dfbc927 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -103,6 +103,56 @@ IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); +/* Mauro Carvalho Chehab */ +IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { + [0x00] = KEY_POWER2, + [0x2e] = KEY_DOT, /* '.' */ + [0x01] = KEY_MODE, /* TV/FM */ + + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x11] = KEY_0, + + [0x13] = KEY_RIGHT, /* -> */ + [0x12] = KEY_LEFT, /* <- */ + + [0x17] = KEY_SLEEP, /* Capturar Imagem */ + [0x10] = KEY_SHUFFLE, /* Amostra */ + + /* FIXME: The keys bellow aren't ok */ + + [0x43] = KEY_CHANNELUP, + [0x42] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x0c] = KEY_ENTER, + + [0x14] = KEY_MUTE, + [0x08] = KEY_AUDIO, + + [0x03] = KEY_TEXT, + [0x04] = KEY_EPG, + [0x2b] = KEY_TV2, /* TV2 */ + + [0x1d] = KEY_RED, + [0x1c] = KEY_YELLOW, + [0x41] = KEY_GREEN, + [0x40] = KEY_BLUE, + + [0x1a] = KEY_PLAYPAUSE, + [0x19] = KEY_RECORD, + [0x18] = KEY_PLAY, + [0x1b] = KEY_STOP, +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); + /* Attila Kondoros */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3ad5b941dfb..a16ddb21288 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3671,6 +3671,40 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }}, }, + [SAA7134_BOARD_AVERMEDIA_M135A] = { + .name = "Avermedia PCI pure analog (M135A)", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .gpiomask = 0x020200000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x00200000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x01, + }, + }, [SAA7134_BOARD_BEHOLD_401] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov */ @@ -4846,6 +4880,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf11d, + .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = PCI_VENDOR_ID_PHILIPS, @@ -5702,6 +5742,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_777: + case SAA7134_BOARD_AVERMEDIA_M135A: /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f1767309b1e..0fded7511ea 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -401,6 +401,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; + case SAA7134_BOARD_AVERMEDIA_M135A: + ir_codes = ir_codes_avermedia_m135a; + mask_keydown = 0x0040000; + mask_keycode = 0x00013f; + nec_gpio = 1; + break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: ir_codes = ir_codes_avermedia; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 982003d49dd..caf055ce310 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -271,6 +271,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 #define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 +#define SAA7134_BOARD_AVERMEDIA_M135A 149 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/ir-common.h b/include/media/ir-common.h index b029987d18c..54a57d0c73e 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -110,6 +110,7 @@ void ir_rc5_timer_keyup(unsigned long data); extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; -- GitLab From 9b0001913983de65af17eee8baf02283160f5a69 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Jun 2008 17:03:00 -0300 Subject: [PATCH 4165/5416] V4L/DVB (9061): saa7134: Add support for Real Audio 220 Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/common/ir-keymaps.c | 40 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 36 +++++++++++++++++++ drivers/media/video/saa7134/saa7134-input.c | 6 ++++ drivers/media/video/saa7134/saa7134.h | 1 + include/media/ir-common.h | 2 +- 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 2023c4020ac..aa06151a2ef 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -146,5 +146,6 @@ 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] 146 -> ASUSTeK P7131 Analog 147 -> Asus Tiger 3in1 [1043:4878] +147 -> Zogis Real Angel 220 148 -> Encore ENLTV-FM v5.3 [1a7f:2008] 149 -> Avermedia PCI pure analog (M135A) [1461:f11d] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index f061dfbc927..b7ed88c59b5 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2381,3 +2381,43 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { [0x47] = KEY_SLEEP, /* shutdown */ }; EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); + +/* Zogis Real Audio 220 - 32 keys IR */ +IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { + [0x1c] = KEY_RADIO, + [0x12] = KEY_POWER2, + + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x00] = KEY_0, + + [0x0c] = KEY_VOLUMEUP, + [0x18] = KEY_VOLUMEDOWN, + [0x0b] = KEY_CHANNELUP, + [0x15] = KEY_CHANNELDOWN, + [0x16] = KEY_ENTER, + + [0x11] = KEY_LIST, /* Source */ + [0x0d] = KEY_AUDIO, /* stereo */ + + [0x0f] = KEY_PREVIOUS, /* Prev */ + [0x1b] = KEY_PAUSE, /* Timeshift */ + [0x1a] = KEY_NEXT, /* Next */ + + [0x0e] = KEY_STOP, + [0x1f] = KEY_PLAY, + [0x1e] = KEY_PLAYPAUSE, /* Pause */ + + [0x1d] = KEY_RECORD, + [0x13] = KEY_MUTE, + [0x19] = KEY_SHUFFLE, /* Snapshot */ + +}; +EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a16ddb21288..2a5e0dbc4d4 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4513,6 +4513,41 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_REAL_ANGEL_220] = { + .name = "Zogis Real Angel 220", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x801a8087, + .inputs = { { + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + .gpio = 0x624000, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + .gpio = 0x624000, + }, { + .name = name_svideo, + .vmux = 1, + .amux = LINE1, + .gpio = 0x624000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x624001, + }, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5780,6 +5815,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_GENIUS_TVGO_A11MCE: + case SAA7134_BOARD_REAL_ANGEL_220: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 0fded7511ea..72a1c67a8c3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -533,6 +533,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0xf00000; polling = 50; /* ms */ break; + case SAA7134_BOARD_REAL_ANGEL_220: + ir_codes = ir_codes_real_audio_220_32_keys; + mask_keycode = 0x3f00; + mask_keyup = 0x4000; + polling = 50; /* ms */ + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index caf055ce310..c17919a1695 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -272,6 +272,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 #define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 #define SAA7134_BOARD_AVERMEDIA_M135A 149 +#define SAA7134_BOARD_REAL_ANGEL_220 147 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 54a57d0c73e..436360ed0b1 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -155,7 +155,7 @@ extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE]; - +extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; #endif /* -- GitLab From a31d2bb773f23f55cc6713f2d1a9b60977bb8f89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Sep 2008 12:08:29 -0300 Subject: [PATCH 4166/5416] V4L/DVB (9062): Add support for Prolink Pixelview Global Extreme Thanks to Sidney Matias for getting GPIO values and testing on this device. Cc: Sidney Matias Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 39 ++++++++++++++++++++++++- drivers/media/video/cx88/cx88-input.c | 1 + drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 075650c95fe..50d0b1c559a 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -72,3 +72,4 @@ 71 -> Omicom SS4 DVB-S/S2 PCI [A044:2011] 72 -> TBS 8920 DVB-S/S2 [8920:8888] 73 -> TeVii S420 DVB-S [d420:9022] + 74 -> Prolink Pixelview Global Extreme [1554:4976] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index b5a25094c9e..9f721080152 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1628,6 +1628,36 @@ static const struct cx88_board cx88_boards[] = { .gpio2 = 0x0cfb, }, }, + [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = { + .name = "Prolink Pixelview Global Extreme", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cf7, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cfb, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x04ff, + .gpio1 = 0x04080, + .gpio2 = 0x0cf7, + }, + }, /* Both radio, analog and ATSC work with this board. However, for analog to work, s5h1409 gate should be open, otherwise, tuner-xc3028 won't be detected. @@ -2125,6 +2155,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x1554, .subdevice = 0x4935, .card = CX88_BOARD_PROLINK_PV_8000GT, + }, { + .subvendor = 0x1554, + .subdevice = 0x4976, + .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME, }, { .subvendor = 0x17de, .subdevice = 0x08c1, @@ -2429,6 +2463,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, return cx88_xc3028_geniatech_tuner_callback(core, command, arg); case CX88_BOARD_PROLINK_PV_8000GT: + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: return cx88_pv_8000gt_callback(core, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: @@ -2582,6 +2617,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) udelay(1000); break; + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: cx_write(MO_GP2_IO, 0xcf7); mdelay(50); @@ -2629,9 +2665,10 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: /* - * This board uses non-MTS firmware + * Those boards uses non-MTS firmware */ break; default: diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 13bc5d16076..8683d104de7 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -261,6 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->polling = 1; /* ms */ break; case CX88_BOARD_PROLINK_PV_8000GT: + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: ir_codes = ir_codes_pixelview_new; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 30b750ee856..6420fb7615b 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -227,6 +227,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_OMICOM_SS4_PCI 71 #define CX88_BOARD_TBS_8920 72 #define CX88_BOARD_TEVII_S420 73 +#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- GitLab From f689d9083a3a46ae3801c37d0dbcb170fc6a9608 Mon Sep 17 00:00:00 2001 From: Adam Glover Date: Tue, 6 May 2008 03:20:27 -0300 Subject: [PATCH 4167/5416] V4L/DVB (9063): Add ADS Tech Instant HDTV PCI support Add PCI ID and device specific tables for ADS Tech Instant HDTV. [mchehab@redhat.com: make checkpatch happy and fix merge conflicts] Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 3 +- drivers/media/video/saa7134/saa7134-cards.c | 31 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + drivers/media/video/saa7134/saa7134.h | 3 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index aa06151a2ef..727b5f21477 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -146,6 +146,7 @@ 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] 146 -> ASUSTeK P7131 Analog 147 -> Asus Tiger 3in1 [1043:4878] -147 -> Zogis Real Angel 220 148 -> Encore ENLTV-FM v5.3 [1a7f:2008] 149 -> Avermedia PCI pure analog (M135A) [1461:f11d] +150 -> Zogis Real Angel 220 +151 -> ADS Tech Instant HDTV [1421:0380] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 2a5e0dbc4d4..a2653b82e06 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4548,6 +4548,30 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, }, }, + [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = { + .name = "ADS Tech Instant HDTV", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TUV1236D, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp, + .vmux = 4, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5564,6 +5588,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x185b, .subdevice = 0xc900, .driver_data = SAA7134_BOARD_VIDEOMATE_T750, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ + .subvendor = 0x1421, + .subdevice = 0x0380, + .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6195,6 +6225,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); break; } + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: { /* enable tuner */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0dd6b988820..2c5185778af 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1156,6 +1156,7 @@ static int dvb_init(struct saa7134_dev *dev) dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_TDHU2); break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index c17919a1695..0907c70dc48 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -272,7 +272,8 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 #define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 #define SAA7134_BOARD_AVERMEDIA_M135A 149 -#define SAA7134_BOARD_REAL_ANGEL_220 147 +#define SAA7134_BOARD_REAL_ANGEL_220 150 +#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- GitLab From 3de2ed127013219efc439c0d052d1cc825da88c2 Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Mon, 29 Sep 2008 02:25:40 -0300 Subject: [PATCH 4168/5416] V4L/DVB (9065): saa7134: fix I2C remote controls on saa7134 This is patch for solve this regression. Load ir-kbd-i2c module when remote is i2c type. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 12872c042f3..b686bfabbde 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -699,6 +699,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; } + if (dev->has_remote == SAA7134_REMOTE_I2C) { + request_module("ir-kbd-i2c"); + } + saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, irq2_mask); -- GitLab From 3f6014fc77c3630d2511302e19f4f02af1605947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Voltz?= Date: Fri, 5 Sep 2008 14:33:54 -0300 Subject: [PATCH 4169/5416] V4L/DVB (9066): Pinnacle Hybrid PCTV Pro (pctv310c) DVB-T support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch against latest mercurial makes DVB-T working on Pinnacle Hybrid PCTV Pro (pctv310c). In cx88-dvb.c, a specific zl10353_config is created with the if2 inferred from the old comment in the currently used config. It is then used for attach, and i2c_gate_ctrl is set to NULL. The entry in cx88-cards.c is modified with GPIO gathered from windows with regspy, and DVB enabled. The frontend is set to XC3028_FE_ZARLINK456 to match the zl10353_config. It is working great with the freeview channels I can receive. Signed-off-by: Stéphane Voltz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 16 ++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 15 ++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 9f721080152..369ba69cd0b 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1449,15 +1449,26 @@ static const struct cx88_board cx88_boards[] = { .name = "Pinnacle Hybrid PCTV", .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x00001, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, } }, .radio = { .type = CX88_RADIO, @@ -1465,6 +1476,7 @@ static const struct cx88_board cx88_boards[] = { .gpio1 = 0x010ff, .gpio2 = 0x0ff, }, + .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { .name = "Winfast TV2000 XP Global", @@ -2671,6 +2683,10 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) * Those boards uses non-MTS firmware */ break; + case CX88_BOARD_PINNACLE_HYBRID_PCTV: + ctl->demod = XC3028_FE_ZARLINK456; + ctl->mts = 1; + break; default: ctl->demod = XC3028_FE_OREN538; ctl->mts = 1; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 6751f36e061..cccf38222a3 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -454,6 +454,12 @@ static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .if_khz = 5380, }; +static struct zl10353_config cx88_pinnacle_hybrid_pctv = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, +}; + static struct zl10353_config cx88_geniatech_x8000_mt = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -890,10 +896,13 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: dev->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_geniatech_x8000_mt, + &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + goto frontend_detach; + } break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; -- GitLab From 1dc7b76a89ea639a575c33710879c425d416dbdb Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 24 Sep 2008 22:48:53 -0300 Subject: [PATCH 4170/5416] V4L/DVB (9067): Kconfig correction for USB card modification with SI2109/2110 demodulator. Kconfig correction for USB card modification with SI2109/2110 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 5880f2d4513..241c9ab54b1 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -254,6 +254,7 @@ config DVB_USB_DW2102 select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE + select DVB_SI21XX if !DVB_FE_CUSTOMISE help Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers and the TeVii S650. -- GitLab From f907c0207924dd598db37092d331738e3fcb9fbd Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 24 Sep 2008 23:18:27 -0300 Subject: [PATCH 4171/5416] V4L/DVB (9068): Kconfig dependency fix for DW2002 card with ST STV0288 demodulator. Kconfig dependency fix for DW2002 card with ST STV0288 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index 2af5fffe138..1332301ef3a 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -3,6 +3,8 @@ config DVB_DM1105 depends on DVB_CORE && PCI && I2C select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_STV0288 if !DVB_FE_CUSTOMISE + select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE help -- GitLab From 3e01084519a678b410df247581a51eeb1bbf11d5 Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Thu, 25 Sep 2008 16:51:11 -0300 Subject: [PATCH 4172/5416] V4L/DVB (9069): cx88: Bugfix: all client disconnects put the frontend to sleep. From the author: "This fixes the problem where previously all client disconnects put the analogue frontend into standby. In the following example, the first command is succesfully watching TV but the second command which returns EBUSY detunes the receiver by entering it into the standby state. tvtime -d /dev/video0 & cat /dev/video0 " Signed-off-by: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 5 ++++- drivers/media/video/cx88/cx88.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 61e03d4703f..be45955dff6 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -839,6 +839,8 @@ static int video_open(struct inode *inode, struct file *file) } unlock_kernel(); + atomic_inc(&core->users); + return 0; } @@ -926,7 +928,8 @@ static int video_release(struct inode *inode, struct file *file) file->private_data = NULL; kfree(fh); - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + if(atomic_dec_and_test(&dev->core->users)) + cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); return 0; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 6420fb7615b..dce7d36edb4 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -349,6 +349,7 @@ struct cx88_core { struct mutex lock; /* various v4l controls */ u32 freq; + atomic_t users; /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev; -- GitLab From 459702bf98ae2bd20bad1e271c615aca4972c609 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 26 Sep 2008 00:04:52 -0300 Subject: [PATCH 4173/5416] V4L/DVB (9070): S2API: Removed the typedef for the commands, used defines instead. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/frontend.h | 57 ++++++++++++++---------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index c822bc156c4..7c17c71edb5 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -246,41 +246,28 @@ struct dvb_frontend_event { struct dvb_frontend_parameters parameters; }; -/* TODO: Turn this into a series of defines, so future maintainers - * don't insert random new commands and break backwards - * binary compatability. - */ -typedef enum dtv_cmd_types { - DTV_UNDEFINED, - DTV_TUNE, - DTV_CLEAR, - - DTV_FREQUENCY, - DTV_MODULATION, - - /* XXX PB: I would like to have field which describes the - * bandwidth of a channel in Hz or kHz - maybe we can remove the - * DTV_BANDWIDTH now and put a compat layer */ - DTV_BANDWIDTH_HZ, - - DTV_INVERSION, - DTV_DISEQC_MASTER, - DTV_SYMBOL_RATE, - DTV_INNER_FEC, - DTV_VOLTAGE, - DTV_TONE, - DTV_PILOT, - DTV_ROLLOFF, - - DTV_DISEQC_SLAVE_REPLY, - - /* Basic enumeration set for querying unlimited capabilities */ - DTV_FE_CAPABILITY_COUNT, - DTV_FE_CAPABILITY, - - /* New commands are always appended */ - DTV_DELIVERY_SYSTEM, -} dtv_cmd_types_t; +/* S2API Commands */ +#define DTV_UNDEFINED 0 +#define DTV_TUNE 1 +#define DTV_CLEAR 2 +#define DTV_FREQUENCY 3 +#define DTV_MODULATION 4 +#define DTV_BANDWIDTH_HZ 5 +#define DTV_INVERSION 6 +#define DTV_DISEQC_MASTER 7 +#define DTV_SYMBOL_RATE 8 +#define DTV_INNER_FEC 9 +#define DTV_VOLTAGE 10 +#define DTV_TONE 11 +#define DTV_PILOT 12 +#define DTV_ROLLOFF 13 +#define DTV_DISEQC_SLAVE_REPLY 14 + +/* Basic enumeration set for querying unlimited capabilities */ +#define DTV_FE_CAPABILITY_COUNT 15 +#define DTV_FE_CAPABILITY 16 +#define DTV_DELIVERY_SYSTEM 17 + typedef enum fe_pilot { PILOT_ON, -- GitLab From d48cb402a1ba48c4ad4a36c3c561386027318459 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 26 Sep 2008 00:16:25 -0300 Subject: [PATCH 4174/5416] V4L/DVB (9071): S2API: Implement result codes for individual commands This allows application developers to determine which particular command in a sequence is invalid, or failing with error. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 12 ++++++++---- include/linux/dvb/frontend.h | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 7da25372078..0ef9c2a2af8 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1262,8 +1262,10 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, goto out; } - for (i = 0; i < tvps->num; i++) - err |= dtv_property_process_set(fe, tvp + i, inode, file); + for (i = 0; i < tvps->num; i++) { + (tvp + i)->result = dtv_property_process_set(fe, tvp + i, inode, file); + err |= (tvp + i)->result; + } if(fe->dtv_property_cache.state == DTV_TUNE) { printk("%s() Property cache is full, tuning\n", __FUNCTION__); @@ -1295,8 +1297,10 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, goto out; } - for (i = 0; i < tvps->num; i++) - err |= dtv_property_process_get(fe, tvp + i, inode, file); + for (i = 0; i < tvps->num; i++) { + (tvp + i)->result = dtv_property_process_get(fe, tvp + i, inode, file); + err |= (tvp + i)->result; + } if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { err = -EFAULT; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 7c17c71edb5..b561626fc8a 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -323,6 +323,7 @@ struct dtv_property { void *reserved2; } buffer; } u; + int result; } __attribute__ ((packed)); /* No more than 16 properties during any given ioctl */ -- GitLab From eacf8d8d6bc6798f6870a2cf2c159bfcde3759ac Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 26 Sep 2008 00:29:49 -0300 Subject: [PATCH 4175/5416] V4L/DVB (9072): S2API: Add DTV_API_VERSION command This allows application developers to query the dvb-core API version dynamically, helping developers understand whether certain features will be available. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 9 +++++++++ include/linux/dvb/frontend.h | 1 + include/linux/dvb/version.h | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 0ef9c2a2af8..4c3f0d7e355 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -40,6 +40,7 @@ #include "dvb_frontend.h" #include "dvbdev.h" +#include static int dvb_frontend_debug; static int dvb_shutdown_timeout; @@ -836,6 +837,11 @@ struct dtv_cmds_h dtv_cmds[] = { .set = 0, .buffer = 1, }, + [DTV_API_VERSION] = { + .name = "DTV_API_VERSION", + .cmd = DTV_API_VERSION, + .set = 0, + }, }; void dtv_property_dump(struct dtv_property *tvp) @@ -1104,6 +1110,9 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, case DTV_TONE: tvp->u.data = fe->dtv_property_cache.sectone; break; + case DTV_API_VERSION: + tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; + break; default: r = -1; } diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index b561626fc8a..eb98f8c37ca 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -268,6 +268,7 @@ struct dvb_frontend_event { #define DTV_FE_CAPABILITY 16 #define DTV_DELIVERY_SYSTEM 17 +#define DTV_API_VERSION 35 typedef enum fe_pilot { PILOT_ON, diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h index 126e0c26cb0..25b823b8173 100644 --- a/include/linux/dvb/version.h +++ b/include/linux/dvb/version.h @@ -23,7 +23,7 @@ #ifndef _DVBVERSION_H_ #define _DVBVERSION_H_ -#define DVB_API_VERSION 3 -#define DVB_API_VERSION_MINOR 2 +#define DVB_API_VERSION 5 +#define DVB_API_VERSION_MINOR 0 #endif /*_DVBVERSION_H_*/ -- GitLab From 3c41cb77f4be3076fdbcf9a417052c3c6ce78094 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Sep 2008 02:57:09 -0300 Subject: [PATCH 4176/5416] V4L/DVB (9074): gspca: sonixj webcam 0c45:60fe added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 1d6f2ee1eec..2ca4d9f23fe 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1637,7 +1637,9 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, -/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */ +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE + {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, +#endif /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ -- GitLab From 117a45a85e8c250a45674f81aadd68d77281e57b Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 15 Sep 2008 04:18:51 -0300 Subject: [PATCH 4177/5416] V4L/DVB (9076): gspca: USB direction lacking in spca561. Signed-off-by: Shane Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index e9b0d81f938..4d8e2c0018b 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -152,7 +152,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, /* request */ - USB_TYPE_VENDOR | USB_RECIP_DEVICE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, 500); PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); if (ret < 0) -- GitLab From 9de436cfc4e966652f8804f0dda8d338ca7fe89c Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Mon, 15 Sep 2008 05:20:38 -0300 Subject: [PATCH 4178/5416] V4L/DVB (9077): gspca: Set the right V4L2_DEBUG values in the main driver. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 58761d9809f..e4c998965ab 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -843,9 +843,11 @@ static int dev_open(struct inode *inode, struct file *file) #ifdef GSPCA_DEBUG /* activate the v4l2 debug */ if (gspca_debug & D_V4L2) - gspca_dev->vdev.debug |= 3; + gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL + | V4L2_DEBUG_IOCTL_ARG; else - gspca_dev->vdev.debug &= ~3; + gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL + | V4L2_DEBUG_IOCTL_ARG); #endif ret = 0; out: -- GitLab From 1b60e1adc713e8d375dc117f5c3b5032d5b79abe Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 20 Sep 2008 05:44:21 -0300 Subject: [PATCH 4179/5416] V4L/DVB (9078): gspca: New exported function to retrieve the current frame buffer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 33 ++++++++++++++++++++----------- drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e4c998965ab..4694dc14a24 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -102,6 +102,22 @@ static struct vm_operations_struct gspca_vm_ops = { .close = gspca_vm_close, }; +/* get the current input frame buffer */ +struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) +{ + struct gspca_frame *frame; + int i; + + i = gspca_dev->fr_i; + i = gspca_dev->fr_queue[i]; + frame = &gspca_dev->frame[i]; + if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) + != V4L2_BUF_FLAG_QUEUED) + return NULL; + return frame; +} +EXPORT_SYMBOL(gspca_get_i_frame); + /* * fill a video frame from an URB and resubmit */ @@ -110,7 +126,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, { struct gspca_frame *frame; __u8 *data; /* address of data in the iso message */ - int i, j, len, st; + int i, len, st; cam_pkt_op pkt_scan; if (urb->status != 0) { @@ -124,11 +140,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, for (i = 0; i < urb->number_of_packets; i++) { /* check the availability of the frame buffer */ - j = gspca_dev->fr_i; - j = gspca_dev->fr_queue[j]; - frame = &gspca_dev->frame[j]; - if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) - != V4L2_BUF_FLAG_QUEUED) { + frame = gspca_get_i_frame(gspca_dev); + if (!frame) { gspca_dev->last_packet_type = DISCARD_PACKET; break; } @@ -185,7 +198,6 @@ static void bulk_irq(struct urb *urb { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; struct gspca_frame *frame; - int j; PDEBUG(D_PACK, "bulk irq"); if (!gspca_dev->streaming) @@ -199,11 +211,8 @@ static void bulk_irq(struct urb *urb } /* check the availability of the frame buffer */ - j = gspca_dev->fr_i; - j = gspca_dev->fr_queue[j]; - frame = &gspca_dev->frame[j]; - if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) - != V4L2_BUF_FLAG_QUEUED) { + frame = gspca_get_i_frame(gspca_dev); + if (!frame) { gspca_dev->last_packet_type = DISCARD_PACKET; } else { PDEBUG(D_PACK, "packet l:%d", urb->actual_length); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 78a35a88cf9..72a28857305 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -178,6 +178,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, struct gspca_frame *frame, const __u8 *data, int len); +struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); #ifdef CONFIG_PM int gspca_suspend(struct usb_interface *intf, pm_message_t message); int gspca_resume(struct usb_interface *intf); -- GitLab From 72ab97cecb7225a4c9f74cdd80268b50b74697bb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 20 Sep 2008 06:39:08 -0300 Subject: [PATCH 4180/5416] V4L/DVB (9079): gspca: Return error code from stream start functions. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 3 ++- drivers/media/video/gspca/etoms.c | 3 ++- drivers/media/video/gspca/gspca.c | 6 +++++- drivers/media/video/gspca/gspca.h | 2 +- drivers/media/video/gspca/mars.c | 20 +++++++++++--------- drivers/media/video/gspca/ov519.c | 5 +++-- drivers/media/video/gspca/pac207.c | 3 ++- drivers/media/video/gspca/pac7311.c | 3 ++- drivers/media/video/gspca/sonixb.c | 3 ++- drivers/media/video/gspca/sonixj.c | 3 ++- drivers/media/video/gspca/spca500.c | 3 ++- drivers/media/video/gspca/spca501.c | 3 ++- drivers/media/video/gspca/spca505.c | 3 ++- drivers/media/video/gspca/spca506.c | 3 ++- drivers/media/video/gspca/spca508.c | 3 ++- drivers/media/video/gspca/spca561.c | 6 ++++-- drivers/media/video/gspca/stk014.c | 5 +++-- drivers/media/video/gspca/sunplus.c | 3 ++- drivers/media/video/gspca/t613.c | 3 ++- drivers/media/video/gspca/tv8532.c | 3 ++- drivers/media/video/gspca/vc032x.c | 5 +++-- drivers/media/video/gspca/zc3xx.c | 3 ++- 22 files changed, 60 insertions(+), 34 deletions(-) diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 4d9f4cc255a..a9d51ba7c57 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -837,12 +837,13 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { cx11646_initsize(gspca_dev); cx11646_fw(gspca_dev); cx_sensor(gspca_dev); cx11646_jpeg(gspca_dev); + return 0; } static void sd_stop0(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 4ff0e386914..3be30b420a2 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -691,7 +691,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -704,6 +704,7 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); et_video(gspca_dev, 1); /* video on */ + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 4694dc14a24..a286b91965f 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -584,7 +584,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) goto out; /* start the cam */ - gspca_dev->sd_desc->start(gspca_dev); + ret = gspca_dev->sd_desc->start(gspca_dev); + if (ret < 0) { + destroy_urbs(gspca_dev); + goto out; + } gspca_dev->streaming = 1; atomic_set(&gspca_dev->nevent, 0); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 72a28857305..b0bdae194bb 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -93,7 +93,7 @@ struct sd_desc { /* mandatory operations */ cam_cf_op config; /* called on probe */ cam_op init; /* called on probe and resume */ - cam_v_op start; /* called on stream on */ + cam_op start; /* called on stream on */ cam_pkt_op pkt_scan; /* optional operations */ cam_v_op stopN; /* called on stream off - main alt */ diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 4d5db47ba8c..277ca34a881 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -134,7 +134,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { int err_code; __u8 *data; @@ -143,9 +143,10 @@ static void sd_start(struct gspca_dev *gspca_dev) int intpipe; PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); - if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) { + err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8); + if (err_code < 0) { PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); - return; + return err_code; } data = gspca_dev->usb_buf; @@ -154,7 +155,7 @@ static void sd_start(struct gspca_dev *gspca_dev) err_code = reg_w(gspca_dev, data[0], 2); if (err_code < 0) - return; + return err_code; /* Initialize the MR97113 chip register @@ -180,14 +181,14 @@ static void sd_start(struct gspca_dev *gspca_dev) err_code = reg_w(gspca_dev, data[0], 11); if (err_code < 0) - return; + return err_code; data[0] = 0x23; /* address */ data[1] = 0x09; /* reg 35, append frame header */ err_code = reg_w(gspca_dev, data[0], 2); if (err_code < 0) - return; + return err_code; data[0] = 0x3c; /* address */ /* if (gspca_dev->width == 1280) */ @@ -198,7 +199,7 @@ static void sd_start(struct gspca_dev *gspca_dev) * (unit: 4KB) 200KB */ err_code = reg_w(gspca_dev, data[0], 2); if (err_code < 0) - return; + return err_code; if (0) { /* fixed dark-gain */ data[1] = 0; /* reg 94, Y Gain (1.75) */ @@ -240,13 +241,13 @@ static void sd_start(struct gspca_dev *gspca_dev) err_code = reg_w(gspca_dev, data[0], 6); if (err_code < 0) - return; + return err_code; data[0] = 0x67; data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ err_code = reg_w(gspca_dev, data[0], 2); if (err_code < 0) - return; + return err_code; /* * initialize the value of MI sensor... @@ -326,6 +327,7 @@ static void sd_start(struct gspca_dev *gspca_dev) data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ reg_w(gspca_dev, data[0], 2); + return err_code; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4df4eec9f7e..ca671194679 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1854,7 +1854,7 @@ static int set_ov_sensor_window(struct sd *sd) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; @@ -1871,9 +1871,10 @@ static void sd_start(struct gspca_dev *gspca_dev) goto out; PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); ov51x_led_control(sd, 1); - return; + return 0; out: PDEBUG(D_ERR, "camera start error:%d", ret); + return ret; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 34e923d00b7..0b0c573d06d 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -281,7 +281,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 mode; @@ -323,6 +323,7 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->sof_read = 0; sd->autogain_ignore_frames = 0; atomic_set(&sd->avg_lum, -1); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index ba865b7f1ed..e5ff9a6199e 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -675,7 +675,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -724,6 +724,7 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x78, 0x01); else reg_w(gspca_dev, 0x78, 0x05); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 4328ad44c40..6c69bc7778f 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -892,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; @@ -976,6 +976,7 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->frames_to_drop = 0; sd->autogain_ignore_frames = 0; atomic_set(&sd->avg_lum, -1); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 2ca4d9f23fe..9c6a874be99 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1203,7 +1203,7 @@ static void setvflip(struct sd *sd) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; @@ -1357,6 +1357,7 @@ static void sd_start(struct gspca_dev *gspca_dev) } setautogain(gspca_dev); reg_w1(gspca_dev, 0x01, reg1); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 6e733901fcc..bca106c153f 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -660,7 +660,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int err; @@ -867,6 +867,7 @@ static void sd_start(struct gspca_dev *gspca_dev) write_vector(gspca_dev, Clicksmart510_defaults); break; } + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index e9eb59bae4f..b742f260c7c 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -1980,7 +1980,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int mode; @@ -2012,6 +2012,7 @@ static void sd_start(struct gspca_dev *gspca_dev) setbrightness(gspca_dev); setcontrast(gspca_dev); setcolors(gspca_dev); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index f601daf19eb..b345749213c 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -688,7 +688,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int ret; @@ -733,6 +733,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* reg_write(dev, 0x5, 0x0, 0x0); */ /* reg_write(dev, 0x5, 0x0, 0x1); */ /* reg_write(dev, 0x5, 0x11, 0x2); */ + return ret; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 195dce96ef0..645ee9d44d0 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -422,7 +422,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; __u16 norme; @@ -549,6 +549,7 @@ static void sd_start(struct gspca_dev *gspca_dev) PDEBUG(D_STREAM, "webcam started"); spca506_GetNormeInput(gspca_dev, &norme, &channel); spca506_SetNormeInput(gspca_dev, norme, channel); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 281ce02103a..63ec902c895 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1528,7 +1528,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { int mode; @@ -1546,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; } reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 4d8e2c0018b..29089d9526b 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -699,7 +699,7 @@ static void setautogain(struct gspca_dev *gspca_dev) sd->ag_cnt = -1; } -static void sd_start_12a(struct gspca_dev *gspca_dev) +static int sd_start_12a(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ @@ -725,8 +725,9 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) setwhite(gspca_dev); setautogain(gspca_dev); setexposure(gspca_dev); + return 0; } -static void sd_start_72a(struct gspca_dev *gspca_dev) +static int sd_start_72a(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int Clck; @@ -750,6 +751,7 @@ static void sd_start_72a(struct gspca_dev *gspca_dev) reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ reg_w_val(dev, 0x8112, 0x10 | 0x20); setautogain(gspca_dev); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 2f2de429e27..d9d64911f22 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -324,7 +324,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { int ret, value; @@ -374,9 +374,10 @@ static void sd_start(struct gspca_dev *gspca_dev) set_par(gspca_dev, 0x01000000); set_par(gspca_dev, 0x01000000); PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); - return; + return 0; out: PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); + return ret; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 1cfcc6c4955..bd9288665a8 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -961,7 +961,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; @@ -1042,6 +1042,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; } sp5xx_initContBrigHueRegisters(gspca_dev); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index f034c748fc7..78c67429759 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -849,7 +849,7 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { int mode; @@ -898,6 +898,7 @@ static void sd_start(struct gspca_dev *gspca_dev) setbrightness(gspca_dev); setcontrast(gspca_dev); setcolors(gspca_dev); + return 0; } static void sd_pkt_scan(struct gspca_dev *gspca_dev, diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 084af05302a..968a5911704 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -390,7 +390,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) } /* -- start the camera -- */ -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); @@ -443,6 +443,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /************************************************/ tv_8532_PollReg(gspca_dev); reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 0c68f433bb9..be46d923254 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1501,7 +1501,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; const __u8 *GammaT = NULL; @@ -1585,7 +1585,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; default: PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); - return; + return -EMEDIUMTYPE; } if (GammaT && MatrixT) { put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); @@ -1621,6 +1621,7 @@ static void sd_start(struct gspca_dev *gspca_dev) setautogain(gspca_dev); setlightfreq(gspca_dev); } + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d61ef727e0c..d0a4451dc46 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7178,7 +7178,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void sd_start(struct gspca_dev *gspca_dev) +static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; @@ -7331,6 +7331,7 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(dev, 0x02, 0x0008); break; } + return 0; } static void sd_stop0(struct gspca_dev *gspca_dev) -- GitLab From 9f4c0617edcc676a5281c04bf48a305b80dd5397 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 22 Sep 2008 02:57:56 -0300 Subject: [PATCH 4181/5416] V4L/DVB (9081): gspca: Bad webcam name of 046d:092f in documentation. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 308ce4ee23d..a845667ac43 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -82,7 +82,7 @@ spca561 046d:092b Labtec Webcam Plus spca561 046d:092c Logitech QC chat Elch2 spca561 046d:092d Logitech QC Elch2 spca561 046d:092e Logitech QC Elch2 -spca561 046d:092f Logitech QC Elch2 +spca561 046d:092f Logitech QuickCam Express Plus sunplus 046d:0960 Logitech ClickSmart 420 sunplus 0471:0322 Philips DMVC1300K zc3xx 0471:0325 Philips SPC 200 NC -- GitLab From 40e6ec129100041121aea2fb98590eaea4bb6ba2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 22 Sep 2008 03:14:25 -0300 Subject: [PATCH 4182/5416] V4L/DVB (9082): gspca: Vertical flip the image by default in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 9c6a874be99..03fe77d38cc 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -144,7 +144,7 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define VFLIP_DEF 0 +#define VFLIP_DEF 1 .default_value = VFLIP_DEF, }, .set = sd_setvflip, -- GitLab From 3b11fa3a0651984af60cb8ff8faf0338552ece1f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 26 Sep 2008 05:52:52 -0300 Subject: [PATCH 4183/5416] V4L/DVB (9083): gspca: URB_NO_TRANSFER_DMA_MAP is not useful for isoc transfers. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index a286b91965f..f130bb77f70 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -540,8 +540,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, if (npkt != 0) { /* ISOC */ urb->pipe = usb_rcvisocpipe(gspca_dev->dev, ep->desc.bEndpointAddress); - urb->transfer_flags = URB_ISO_ASAP - | URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = URB_ISO_ASAP; urb->interval = ep->desc.bInterval; urb->complete = isoc_irq; urb->number_of_packets = npkt; -- GitLab From 219423c147f6d4bc91ec904debfbc556887bd8fe Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Fri, 26 Sep 2008 07:43:54 -0300 Subject: [PATCH 4184/5416] V4L/DVB (9084): gspca: Fixed a few typos in comments. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index f130bb77f70..06e50159814 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -278,7 +278,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, } gspca_dev->last_packet_type = packet_type; - /* if last packet, wake the application and advance in the queue */ + /* if last packet, wake up the application and advance in the queue */ if (packet_type == LAST_PACKET) { frame->v4l2_buf.bytesused = frame->data_end - frame->data; frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; @@ -420,7 +420,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) } /* - * search an input transfer endpoint in an alternate setting + * look for an input transfer endpoint in an alternate setting */ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, __u8 epaddr, @@ -444,7 +444,7 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, } /* - * search an input (isoc or bulk) endpoint + * look for an input (isoc or bulk) endpoint * * The endpoint is defined by the subdriver. * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). @@ -591,7 +591,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; atomic_set(&gspca_dev->nevent, 0); - /* start the bulk transfer is done by the subdriver */ + /* bulk transfers are started by the subdriver */ if (gspca_dev->bulk) break; @@ -626,7 +626,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) return ret; } -/* Note both the queue and the usb lock should be hold when calling this */ +/* Note: both the queue and the usb locks should be held when calling this */ static void gspca_stream_off(struct gspca_dev *gspca_dev) { gspca_dev->streaming = 0; @@ -1685,7 +1685,7 @@ static ssize_t dev_read(struct file *file, char __user *data, } /* if the process slept for more than 1 second, - * get anewer frame */ + * get a newer frame */ frame = &gspca_dev->frame[v4l2_buf.index]; if (--n < 0) break; /* avoid infinite loop */ -- GitLab From 6c49da7f169c25eb39b80ff168f5bdbacf8457e1 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 28 Sep 2008 07:43:00 -0300 Subject: [PATCH 4185/5416] V4L/DVB (9085): gspca: URB_NO_TRANSFER_DMA_MAP is required for isoc and bulk transfers. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 06e50159814..3f0fd44f19a 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -540,7 +540,8 @@ static int create_urbs(struct gspca_dev *gspca_dev, if (npkt != 0) { /* ISOC */ urb->pipe = usb_rcvisocpipe(gspca_dev->dev, ep->desc.bEndpointAddress); - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP + | URB_NO_TRANSFER_DMA_MAP; urb->interval = ep->desc.bInterval; urb->complete = isoc_irq; urb->number_of_packets = npkt; @@ -551,6 +552,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, } else { /* bulk */ urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, ep->desc.bEndpointAddress), + urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->complete = bulk_irq; } } -- GitLab From 6b060ffea0722cfe4f5156a73a6424130d3d804a Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 28 Sep 2008 08:12:22 -0300 Subject: [PATCH 4186/5416] V4L/DVB (9086): gspca: Use a kref to avoid potentialy blocking forever in disconnect. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 39 +++++++++++++++++++++---------- drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 3f0fd44f19a..342a0f39e5d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -834,6 +835,16 @@ out: return ret; } +static void gspca_delete(struct kref *kref) +{ + struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref); + + PDEBUG(D_STREAM, "device deleted"); + + kfree(gspca_dev->usb_buf); + kfree(gspca_dev); +} + static int dev_open(struct inode *inode, struct file *file) { struct gspca_dev *gspca_dev; @@ -853,6 +864,10 @@ static int dev_open(struct inode *inode, struct file *file) goto out; } gspca_dev->users++; + + /* one more user */ + kref_get(&gspca_dev->kref); + file->private_data = gspca_dev; #ifdef GSPCA_DEBUG /* activate the v4l2 debug */ @@ -895,7 +910,11 @@ static int dev_close(struct inode *inode, struct file *file) } file->private_data = NULL; mutex_unlock(&gspca_dev->queue_lock); + PDEBUG(D_STREAM, "close done"); + + kref_put(&gspca_dev->kref, gspca_delete); + return 0; } @@ -1809,6 +1828,7 @@ int gspca_dev_probe(struct usb_interface *intf, err("couldn't kzalloc gspca struct"); return -EIO; } + kref_init(&gspca_dev->kref); gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); if (!gspca_dev->usb_buf) { err("out of memory"); @@ -1858,8 +1878,7 @@ int gspca_dev_probe(struct usb_interface *intf, PDEBUG(D_PROBE, "probe ok"); return 0; out: - kfree(gspca_dev->usb_buf); - kfree(gspca_dev); + kref_put(&gspca_dev->kref, gspca_delete); return ret; } EXPORT_SYMBOL(gspca_dev_probe); @@ -1874,8 +1893,8 @@ void gspca_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - if (!gspca_dev) - return; + usb_set_intfdata(intf, NULL); + gspca_dev->present = 0; mutex_lock(&gspca_dev->queue_lock); mutex_lock(&gspca_dev->usb_lock); @@ -1883,16 +1902,12 @@ void gspca_disconnect(struct usb_interface *intf) destroy_urbs(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); mutex_unlock(&gspca_dev->queue_lock); - while (gspca_dev->users != 0) { /* wait until fully closed */ - atomic_inc(&gspca_dev->nevent); - wake_up_interruptible(&gspca_dev->wq); /* wake processes */ - schedule(); - } + /* We don't want people trying to open up the device */ video_unregister_device(&gspca_dev->vdev); -/* Free the memory */ - kfree(gspca_dev->usb_buf); - kfree(gspca_dev); + + kref_put(&gspca_dev->kref, gspca_delete); + PDEBUG(D_PROBE, "disconnect complete"); } EXPORT_SYMBOL(gspca_disconnect); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index b0bdae194bb..192dffdcd9c 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -121,6 +121,7 @@ struct gspca_dev { struct video_device vdev; /* !! must be the first item */ struct file_operations fops; struct usb_device *dev; + struct kref kref; struct file *capt_file; /* file doing video capture */ struct cam cam; /* device information */ -- GitLab From 95d9142c8b250b2ce0e0a283fdf54d899dcc4f3e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Sep 2008 05:57:32 -0300 Subject: [PATCH 4187/5416] V4L/DVB (9087): gspca: Image transfer by bulk uses altsetting 0 with any buffer size. - gspca_dev field 'bulk_size' added. - when only one altsetting usable, do image transfer by bulk. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 42 ++++++++++++++++++++----------- drivers/media/video/gspca/gspca.h | 2 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 342a0f39e5d..02824fc101d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -461,25 +461,34 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); ep = NULL; i = gspca_dev->alt; /* previous alt setting */ + + /* try isoc */ while (--i > 0) { /* alt 0 is unusable */ ep = alt_xfer(&intf->altsetting[i], gspca_dev->cam.epaddr, - gspca_dev->bulk - ? USB_ENDPOINT_XFER_BULK - : USB_ENDPOINT_XFER_ISOC); + USB_ENDPOINT_XFER_ISOC); if (ep) break; } + + /* if no isoc, try bulk */ if (ep == NULL) { - err("no transfer endpoint found"); - return NULL; + ep = alt_xfer(&intf->altsetting[0], + gspca_dev->cam.epaddr, + USB_ENDPOINT_XFER_BULK); + if (ep == NULL) { + err("no transfer endpoint found"); + return NULL; + } } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); - if (ret < 0) { - err("set interface err %d", ret); - return NULL; + if (i > 0) { + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); + if (ret < 0) { + err("set interface err %d", ret); + return NULL; + } } gspca_dev->alt = i; /* memorize the current alt setting */ return ep; @@ -497,9 +506,10 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* calculate the packet size and the number of packets */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); - /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - if (!gspca_dev->bulk) { + if (gspca_dev->alt != 0) { /* isoc */ + + /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ + psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); npkt = ISO_MAX_SIZE / psize; if (npkt > ISO_MAX_PKT) npkt = ISO_MAX_PKT; @@ -508,9 +518,11 @@ static int create_urbs(struct gspca_dev *gspca_dev, "isoc %d pkts size %d = bsize:%d", npkt, psize, bsize); nurbs = DEF_NURBS; - } else { + } else { /* bulk */ npkt = 0; - bsize = psize; + bsize = gspca_dev->cam. bulk_size; + if (bsize == 0) + bsize = psize; PDEBUG(D_STREAM, "bulk bsize:%d", bsize); nurbs = 1; } @@ -595,7 +607,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) atomic_set(&gspca_dev->nevent, 0); /* bulk transfers are started by the subdriver */ - if (gspca_dev->bulk) + if (gspca_dev->alt == 0) break; /* submit the URBs */ diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 192dffdcd9c..f9006542c58 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -56,6 +56,7 @@ extern int gspca_debug; /* device information - set at probe time */ struct cam { + int bulk_size; /* buffer size when image transfer by bulk */ struct v4l2_pix_format *cam_mode; /* size nmodes */ char nmodes; __u8 epaddr; @@ -144,7 +145,6 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ - __u8 bulk; /* image transfer by isoc (0) or bulk (1) */ __u8 curr_mode; /* current camera mode */ __u32 pixfmt; /* current mode parameters */ __u16 width; -- GitLab From 97076859590ada76dc4bee46b6ccad86d89e82cf Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Mon, 29 Sep 2008 06:59:36 -0300 Subject: [PATCH 4188/5416] V4L/DVB (9088): gspca: New subdriver 'finepix' added. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 23 ++ drivers/media/video/gspca/Makefile | 3 +- drivers/media/video/gspca/finepix.c | 465 ++++++++++++++++++++++++++++ 3 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 drivers/media/video/gspca/finepix.c diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index a845667ac43..04c612eb897 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -97,6 +97,29 @@ sunplus 04a5:3003 Benq DC 1300 sunplus 04a5:3008 Benq DC 1500 sunplus 04a5:300a Benq DC 3410 spca500 04a5:300c Benq DC 1016 +finepix 04cb:0104 Fujifilm FinePix 4800 +finepix 04cb:0109 Fujifilm FinePix A202 +finepix 04cb:010b Fujifilm FinePix A203 +finepix 04cb:010f Fujifilm FinePix A204 +finepix 04cb:0111 Fujifilm FinePix A205 +finepix 04cb:0113 Fujifilm FinePix A210 +finepix 04cb:0115 Fujifilm FinePix A303 +finepix 04cb:0117 Fujifilm FinePix A310 +finepix 04cb:0119 Fujifilm FinePix F401 +finepix 04cb:011b Fujifilm FinePix F402 +finepix 04cb:011d Fujifilm FinePix F410 +finepix 04cb:0121 Fujifilm FinePix F601 +finepix 04cb:0123 Fujifilm FinePix F700 +finepix 04cb:0125 Fujifilm FinePix M603 +finepix 04cb:0127 Fujifilm FinePix S300 +finepix 04cb:0129 Fujifilm FinePix S304 +finepix 04cb:012b Fujifilm FinePix S500 +finepix 04cb:012d Fujifilm FinePix S602 +finepix 04cb:012f Fujifilm FinePix S700 +finepix 04cb:0131 Fujifilm FinePix unknown model +finepix 04cb:013b Fujifilm FinePix unknown model +finepix 04cb:013d Fujifilm FinePix unknown model +finepix 04cb:013f Fujifilm FinePix F420 sunplus 04f1:1001 JVC GC A50 spca561 04fc:0561 Flexcam 100 sunplus 04fc:500c Sunplus CA500C diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index e68a8965297..78bad045913 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o \ - gspca_conex.o gspca_etoms.o gspca_mars.o \ + gspca_conex.o gspca_etoms.o gspca_finepix.o gspca_mars.o \ gspca_ov519.o gspca_pac207.o gspca_pac7311.o \ gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \ gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \ @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o \ gspca_main-objs := gspca.o gspca_conex-objs := conex.o gspca_etoms-objs := etoms.o +gspca_finepix-objs := finepix.o gspca_mars-objs := mars.o gspca_ov519-objs := ov519.o gspca_pac207-objs := pac207.o diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c new file mode 100644 index 00000000000..f75db9585f0 --- /dev/null +++ b/drivers/media/video/gspca/finepix.c @@ -0,0 +1,465 @@ +/* + * Fujifilm Finepix subdriver + * + * Copyright (C) 2008 Frank Zago + * + * 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 + * 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 + */ + +#define MODULE_NAME "finepix" + +#include "gspca.h" + +MODULE_AUTHOR("Frank Zago "); +MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); +MODULE_LICENSE("GPL"); + +/* Default timeout, in ms */ +#define FPIX_TIMEOUT (HZ / 10) + +/* Maximum transfer size to use. The windows driver reads by chunks of + * 0x2000 bytes, so do the same. Note: reading more seems to work + * too. */ +#define FPIX_MAX_TRANSFER 0x2000 + +/* Structure to hold all of our device specific stuff */ +struct usb_fpix { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + /* + * USB stuff + */ + struct usb_ctrlrequest ctrlreq; + struct urb *control_urb; + struct timer_list bulk_timer; + + enum { + FPIX_NOP, /* inactive, else streaming */ + FPIX_RESET, /* must reset */ + FPIX_REQ_FRAME, /* requesting a frame */ + FPIX_READ_FRAME, /* reading frame */ + } state; + + /* + * Driver stuff + */ + struct delayed_work wqe; + struct completion can_close; + int streaming; +}; + +/* Delay after which claim the next frame. If the delay is too small, + * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms + * will fail every 4 or 5 frames, but 30ms is perfect. */ +#define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000) + +#define dev_new_state(new_state) { \ + PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \ + dev->state, new_state, __func__, __LINE__); \ + dev->state = new_state; \ +} + +/* These cameras only support 320x200. */ +static struct v4l2_pix_format fpix_mode[1] = { + { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0} +}; + +/* Reads part of a frame */ +static void read_frame_part(struct usb_fpix *dev) +{ + int ret; + + PDEBUG(D_STREAM, "read_frame_part"); + + /* Reads part of a frame */ + ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC); + if (ret) { + dev_new_state(FPIX_RESET); + schedule_delayed_work(&dev->wqe, 1); + PDEBUG(D_STREAM, "usb_submit_urb failed with %d", + ret); + } else { + /* Sometimes we never get a callback, so use a timer. + * Is this masking a bug somewhere else? */ + dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150); + add_timer(&dev->bulk_timer); + } +} + +/* Callback for URBs. */ +static void urb_callback(struct urb *urb) +{ + struct gspca_dev *gspca_dev = urb->context; + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + + PDEBUG(D_PACK, + "enter urb_callback - status=%d, length=%d", + urb->status, urb->actual_length); + + if (dev->state == FPIX_READ_FRAME) + del_timer(&dev->bulk_timer); + + if (urb->status != 0) { + /* We kill a stuck urb every 50 frames on average, so don't + * display a log message for that. */ + if (urb->status != -ECONNRESET) + PDEBUG(D_STREAM, "bad URB status %d", urb->status); + dev_new_state(FPIX_RESET); + schedule_delayed_work(&dev->wqe, 1); + } + + switch (dev->state) { + case FPIX_REQ_FRAME: + dev_new_state(FPIX_READ_FRAME); + read_frame_part(dev); + break; + + case FPIX_READ_FRAME: { + unsigned char *data = urb->transfer_buffer; + struct gspca_frame *frame; + + frame = gspca_get_i_frame(&dev->gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + break; + } + if (urb->actual_length < FPIX_MAX_TRANSFER || + (data[urb->actual_length-2] == 0xff && + data[urb->actual_length-1] == 0xd9)) { + + /* If the result is less than what was asked + * for, then it's the end of the + * frame. Sometime the jpeg is not complete, + * but there's nothing we can do. We also end + * here if the the jpeg ends right at the end + * of the frame. */ + gspca_frame_add(gspca_dev, LAST_PACKET, + frame, + data, urb->actual_length); + dev_new_state(FPIX_REQ_FRAME); + schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); + } else { + + /* got a partial image */ + gspca_frame_add(gspca_dev, + gspca_dev->last_packet_type == LAST_PACKET + ? FIRST_PACKET : INTER_PACKET, + frame, + data, urb->actual_length); + read_frame_part(dev); + } + break; + } + + case FPIX_NOP: + case FPIX_RESET: + PDEBUG(D_STREAM, "invalid state %d", dev->state); + break; + } +} + +/* Request a new frame */ +static void request_frame(struct usb_fpix *dev) +{ + int ret; + struct gspca_dev *gspca_dev = &dev->gspca_dev; + + /* Setup command packet */ + memset(gspca_dev->usb_buf, 0, 12); + gspca_dev->usb_buf[0] = 0xd3; + gspca_dev->usb_buf[7] = 0x01; + + /* Request a frame */ + dev->ctrlreq.bRequestType = + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + dev->ctrlreq.bRequest = USB_REQ_GET_STATUS; + dev->ctrlreq.wValue = 0; + dev->ctrlreq.wIndex = 0; + dev->ctrlreq.wLength = cpu_to_le16(12); + + usb_fill_control_urb(dev->control_urb, + gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + (unsigned char *) &dev->ctrlreq, + gspca_dev->usb_buf, + 12, urb_callback, gspca_dev); + + ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC); + if (ret) { + dev_new_state(FPIX_RESET); + schedule_delayed_work(&dev->wqe, 1); + PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret); + } +} + +/*--------------------------------------------------------------------------*/ + +/* State machine. */ +static void fpix_sm(struct work_struct *work) +{ + struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work); + + PDEBUG(D_STREAM, "fpix_sm state %d", dev->state); + + /* verify that the device wasn't unplugged */ + if (!dev->gspca_dev.present) { + PDEBUG(D_STREAM, "device is gone"); + dev_new_state(FPIX_NOP); + complete(&dev->can_close); + return; + } + + if (!dev->streaming) { + PDEBUG(D_STREAM, "stopping state machine"); + dev_new_state(FPIX_NOP); + complete(&dev->can_close); + return; + } + + switch (dev->state) { + case FPIX_RESET: + dev_new_state(FPIX_REQ_FRAME); + schedule_delayed_work(&dev->wqe, HZ / 10); + break; + + case FPIX_REQ_FRAME: + /* get an image */ + request_frame(dev); + break; + + case FPIX_NOP: + case FPIX_READ_FRAME: + PDEBUG(D_STREAM, "invalid state %d", dev->state); + break; + } +} + +/* this function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + + cam->cam_mode = fpix_mode; + cam->nmodes = 1; + cam->epaddr = 0x01; /* todo: correct for all cams? */ + cam->bulk_size = FPIX_MAX_TRANSFER; + +/* gspca_dev->nbalt = 1; * use bulk transfer */ + return 0; +} + +/* Stop streaming and free the ressources allocated by sd_start. */ +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + + dev->streaming = 0; + + /* Stop the state machine */ + if (dev->state != FPIX_NOP) + wait_for_completion(&dev->can_close); + + usb_free_urb(dev->control_urb); + dev->control_urb = NULL; +} + +/* Kill an URB that hasn't completed. */ +static void timeout_kill(unsigned long data) +{ + struct urb *urb = (struct urb *) data; + + usb_unlink_urb(urb); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + + INIT_DELAYED_WORK(&dev->wqe, fpix_sm); + + init_timer(&dev->bulk_timer); + dev->bulk_timer.function = timeout_kill; + + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + int ret; + int size_ret; + + /* Reset bulk in endpoint */ + usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); + + /* Init the device */ + memset(gspca_dev->usb_buf, 0, 12); + gspca_dev->usb_buf[0] = 0xc6; + gspca_dev->usb_buf[8] = 0x20; + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_GET_STATUS, + USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, + 12, FPIX_TIMEOUT); + + if (ret != 12) { + PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); + ret = -EIO; + goto error; + } + + /* Read the result of the command. Ignore the result, for it + * varies with the device. */ + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, + gspca_dev->cam.epaddr), + gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, + FPIX_TIMEOUT); + if (ret != 0) { + PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret); + ret = -EIO; + goto error; + } + + /* Request a frame, but don't read it */ + memset(gspca_dev->usb_buf, 0, 12); + gspca_dev->usb_buf[0] = 0xd3; + gspca_dev->usb_buf[7] = 0x01; + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_GET_STATUS, + USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, + 12, FPIX_TIMEOUT); + if (ret != 12) { + PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); + ret = -EIO; + goto error; + } + + /* Again, reset bulk in endpoint */ + usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); + + /* Allocate a control URB */ + dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->control_urb) { + PDEBUG(D_STREAM, "No free urbs available"); + ret = -EIO; + goto error; + } + + /* Various initializations. */ + init_completion(&dev->can_close); + dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0]; + dev->gspca_dev.urb[0]->complete = urb_callback; + dev->streaming = 1; + + /* Schedule a frame request. */ + dev_new_state(FPIX_REQ_FRAME); + schedule_delayed_work(&dev->wqe, 1); + + return 0; + +error: + /* Free the ressources */ + sd_stopN(gspca_dev); + return ret; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x04cb, 0x0104)}, + {USB_DEVICE(0x04cb, 0x0109)}, + {USB_DEVICE(0x04cb, 0x010b)}, + {USB_DEVICE(0x04cb, 0x010f)}, + {USB_DEVICE(0x04cb, 0x0111)}, + {USB_DEVICE(0x04cb, 0x0113)}, + {USB_DEVICE(0x04cb, 0x0115)}, + {USB_DEVICE(0x04cb, 0x0117)}, + {USB_DEVICE(0x04cb, 0x0119)}, + {USB_DEVICE(0x04cb, 0x011b)}, + {USB_DEVICE(0x04cb, 0x011d)}, + {USB_DEVICE(0x04cb, 0x0121)}, + {USB_DEVICE(0x04cb, 0x0123)}, + {USB_DEVICE(0x04cb, 0x0125)}, + {USB_DEVICE(0x04cb, 0x0127)}, + {USB_DEVICE(0x04cb, 0x0129)}, + {USB_DEVICE(0x04cb, 0x012b)}, + {USB_DEVICE(0x04cb, 0x012d)}, + {USB_DEVICE(0x04cb, 0x012f)}, + {USB_DEVICE(0x04cb, 0x0131)}, + {USB_DEVICE(0x04cb, 0x013b)}, + {USB_DEVICE(0x04cb, 0x013d)}, + {USB_DEVICE(0x04cb, 0x013f)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct usb_fpix), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + if (usb_register(&sd_driver) < 0) + return -1; + PDEBUG(D_PROBE, "registered"); + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- GitLab From b1043e562ec9e5fe60af85b3a7eea43e77a35994 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Sep 2008 07:03:06 -0300 Subject: [PATCH 4189/5416] V4L/DVB (9089): gspca: Remove the duplicated EOF (ff d9) in t613. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 78c67429759..7e435a36b05 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -916,7 +916,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, return; } - if (data[len - 1] == 0xff && data[len] == 0xd9) { + if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { /* Just in case, i have seen packets with the marker, * other's do not include it... */ data += 2; -- GitLab From a3a58467db3c90a1e289970ef319c7abb90be617 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Tue, 30 Sep 2008 03:55:33 -0300 Subject: [PATCH 4190/5416] V4L/DVB (9090): gspca: Restart the state machine when no frame buffer in finepix. Signed-off-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/finepix.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index f75db9585f0..65d3cbfe6b2 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -135,10 +135,8 @@ static void urb_callback(struct urb *urb) struct gspca_frame *frame; frame = gspca_get_i_frame(&dev->gspca_dev); - if (frame == NULL) { + if (frame == NULL) gspca_dev->last_packet_type = DISCARD_PACKET; - break; - } if (urb->actual_length < FPIX_MAX_TRANSFER || (data[urb->actual_length-2] == 0xff && data[urb->actual_length-1] == 0xd9)) { @@ -149,18 +147,21 @@ static void urb_callback(struct urb *urb) * but there's nothing we can do. We also end * here if the the jpeg ends right at the end * of the frame. */ - gspca_frame_add(gspca_dev, LAST_PACKET, - frame, - data, urb->actual_length); + if (frame) + gspca_frame_add(gspca_dev, LAST_PACKET, + frame, + data, urb->actual_length); dev_new_state(FPIX_REQ_FRAME); schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); } else { /* got a partial image */ - gspca_frame_add(gspca_dev, - gspca_dev->last_packet_type == LAST_PACKET - ? FIRST_PACKET : INTER_PACKET, - frame, + if (frame) + gspca_frame_add(gspca_dev, + gspca_dev->last_packet_type + == LAST_PACKET + ? FIRST_PACKET : INTER_PACKET, + frame, data, urb->actual_length); read_frame_part(dev); } -- GitLab From c109f8168f259ea1f1ab7009c6b99dbe8ea0e2b2 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 1 Oct 2008 04:51:53 -0300 Subject: [PATCH 4191/5416] V4L/DVB (9091): gspca: Subdriver m5602 (ALi) added. This patch adds support for the ALi m5602 usb bridge and is based on the gspca framework. It contains code for communicating with 5 different sensors: OmniVision OV9650, Pixel Plus PO1030, Samsung S5K83A, S5K4AA and finally Micron MT9M111. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine [mchehab@redhat.com: fix m5602/Makefile] [mchehab@redhat.com: extern debug caused conflicts. Renamed to m5602_debug] Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + Documentation/video4linux/m5602.txt | 12 + drivers/media/video/gspca/Kconfig | 3 + drivers/media/video/gspca/Makefile | 3 + drivers/media/video/gspca/m5602/Kconfig | 11 + drivers/media/video/gspca/m5602/Makefile | 11 + .../media/video/gspca/m5602/m5602_bridge.h | 180 +++ drivers/media/video/gspca/m5602/m5602_core.c | 321 ++++++ .../media/video/gspca/m5602/m5602_mt9m111.c | 343 ++++++ .../media/video/gspca/m5602/m5602_mt9m111.h | 1020 +++++++++++++++++ .../media/video/gspca/m5602/m5602_ov9650.c | 544 +++++++++ .../media/video/gspca/m5602/m5602_ov9650.h | 501 ++++++++ .../media/video/gspca/m5602/m5602_po1030.c | 334 ++++++ .../media/video/gspca/m5602/m5602_po1030.h | 478 ++++++++ .../media/video/gspca/m5602/m5602_s5k4aa.c | 460 ++++++++ .../media/video/gspca/m5602/m5602_s5k4aa.h | 368 ++++++ .../media/video/gspca/m5602/m5602_s5k83a.c | 331 ++++++ .../media/video/gspca/m5602/m5602_s5k83a.h | 444 +++++++ .../media/video/gspca/m5602/m5602_sensor.h | 76 ++ 19 files changed, 5441 insertions(+) create mode 100644 Documentation/video4linux/m5602.txt create mode 100644 drivers/media/video/gspca/m5602/Kconfig create mode 100644 drivers/media/video/gspca/m5602/Makefile create mode 100644 drivers/media/video/gspca/m5602/m5602_bridge.h create mode 100644 drivers/media/video/gspca/m5602/m5602_core.c create mode 100644 drivers/media/video/gspca/m5602/m5602_mt9m111.c create mode 100644 drivers/media/video/gspca/m5602/m5602_mt9m111.h create mode 100644 drivers/media/video/gspca/m5602/m5602_ov9650.c create mode 100644 drivers/media/video/gspca/m5602/m5602_ov9650.h create mode 100644 drivers/media/video/gspca/m5602/m5602_po1030.c create mode 100644 drivers/media/video/gspca/m5602/m5602_po1030.h create mode 100644 drivers/media/video/gspca/m5602/m5602_s5k4aa.c create mode 100644 drivers/media/video/gspca/m5602/m5602_s5k4aa.h create mode 100644 drivers/media/video/gspca/m5602/m5602_s5k83a.c create mode 100644 drivers/media/video/gspca/m5602/m5602_s5k83a.h create mode 100644 drivers/media/video/gspca/m5602/m5602_sensor.h diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 04c612eb897..004818fab04 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -7,6 +7,7 @@ The modules are: xxxx vend:prod ---- spca501 0000:0000 MystFromOri Unknow Camera +m5602 0402:5602 ALi Video Camera Controller spca501 040a:0002 Kodak DVC-325 spca500 040a:0300 Kodak EZ200 zc3xx 041e:041e Creative WebCam Live! diff --git a/Documentation/video4linux/m5602.txt b/Documentation/video4linux/m5602.txt new file mode 100644 index 00000000000..4450ab13f37 --- /dev/null +++ b/Documentation/video4linux/m5602.txt @@ -0,0 +1,12 @@ +This document describes the ALi m5602 bridge connected +to the following supported sensors: +OmniVision OV9650, +Samsung s5k83a, +Samsung s5k4aa, +Micron mt9m111, +Pixel plus PO1030 + +This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution. +In a perfect world we should be able to reprogram the m5602 and the connected sensor in hardware instead, supporting a range of resolutions and pixelformats + +Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 42b90742b40..fd31099e36a 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -11,3 +11,6 @@ config USB_GSPCA To compile this driver as modules, choose M here: the modules will be called gspca_xxxx. + +source "drivers/media/video/gspca/m5602/Kconfig" + diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 78bad045913..488ed97c58a 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -28,3 +28,6 @@ gspca_t613-objs := t613.o gspca_tv8532-objs := tv8532.o gspca_vc032x-objs := vc032x.o gspca_zc3xx-objs := zc3xx.o + +obj-$(CONFIG_USB_M5602) += m5602/ + diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig new file mode 100644 index 00000000000..7de33e22117 --- /dev/null +++ b/drivers/media/video/gspca/m5602/Kconfig @@ -0,0 +1,11 @@ +config USB_M5602 + tristate "USB ALi m5602 Webcam support" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the + ALi m5602 connected to various image sensors. + + See for more info. + + To compile this driver as a module, choose M here: the + module will be called gspca-m5602. diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile new file mode 100644 index 00000000000..226ab4fc9d6 --- /dev/null +++ b/drivers/media/video/gspca/m5602/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_USB_M5602) += gspca_m5602.o + +gspca_m5602-objs := m5602_core.o \ + m5602_ov9650.o \ + m5602_mt9m111.o \ + m5602_po1030.o \ + m5602_s5k83a.o \ + m5602_s5k4aa.o + +EXTRA_CFLAGS += -Idrivers/media/video/gspca + diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h new file mode 100644 index 00000000000..fcbc37bfea5 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -0,0 +1,180 @@ +/* + * USB Driver for ALi m5602 based webcams + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_BRIDGE_H_ +#define M5602_BRIDGE_H_ + +#include "gspca.h" + +#define MODULE_NAME "ALi m5602" + +/*****************************************************************************/ + +#undef PDEBUG +#undef info +#undef err + +#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ + format "\n" , ## arg) + +/* Debug parameters */ +#define DBG_INIT 0x1 +#define DBG_PROBE 0x2 +#define DBG_V4L2 0x4 +#define DBG_TRACE 0x8 +#define DBG_DATA 0x10 +#define DBG_V4L2_CID 0x20 +#define DBG_GSPCA 0x40 + +#define PDEBUG(level, fmt, args...) \ + do { \ + if (m5602_debug & level) \ + info("[%s:%d] " fmt, __func__, __LINE__ , \ + ## args); \ + } while (0) + +/*****************************************************************************/ + +#define M5602_XB_SENSOR_TYPE 0x00 +#define M5602_XB_SENSOR_CTRL 0x01 +#define M5602_XB_LINE_OF_FRAME_H 0x02 +#define M5602_XB_LINE_OF_FRAME_L 0x03 +#define M5602_XB_PIX_OF_LINE_H 0x04 +#define M5602_XB_PIX_OF_LINE_L 0x05 +#define M5602_XB_VSYNC_PARA 0x06 +#define M5602_XB_HSYNC_PARA 0x07 +#define M5602_XB_TEST_MODE_1 0x08 +#define M5602_XB_TEST_MODE_2 0x09 +#define M5602_XB_SIG_INI 0x0a +#define M5602_XB_DS_PARA 0x0e +#define M5602_XB_TRIG_PARA 0x0f +#define M5602_XB_CLK_PD 0x10 +#define M5602_XB_MCU_CLK_CTRL 0x12 +#define M5602_XB_MCU_CLK_DIV 0x13 +#define M5602_XB_SEN_CLK_CTRL 0x14 +#define M5602_XB_SEN_CLK_DIV 0x15 +#define M5602_XB_AUD_CLK_CTRL 0x16 +#define M5602_XB_AUD_CLK_DIV 0x17 +#define M5602_XB_DEVCTR1 0x41 +#define M5602_XB_EPSETR0 0x42 +#define M5602_XB_EPAFCTR 0x47 +#define M5602_XB_EPBFCTR 0x49 +#define M5602_XB_EPEFCTR 0x4f +#define M5602_XB_TEST_REG 0x53 +#define M5602_XB_ALT2SIZE 0x54 +#define M5602_XB_ALT3SIZE 0x55 +#define M5602_XB_OBSFRAME 0x56 +#define M5602_XB_PWR_CTL 0x59 +#define M5602_XB_ADC_CTRL 0x60 +#define M5602_XB_ADC_DATA 0x61 +#define M5602_XB_MISC_CTRL 0x62 +#define M5602_XB_SNAPSHOT 0x63 +#define M5602_XB_SCRATCH_1 0x64 +#define M5602_XB_SCRATCH_2 0x65 +#define M5602_XB_SCRATCH_3 0x66 +#define M5602_XB_SCRATCH_4 0x67 +#define M5602_XB_I2C_CTRL 0x68 +#define M5602_XB_I2C_CLK_DIV 0x69 +#define M5602_XB_I2C_DEV_ADDR 0x6a +#define M5602_XB_I2C_REG_ADDR 0x6b +#define M5602_XB_I2C_DATA 0x6c +#define M5602_XB_I2C_STATUS 0x6d +#define M5602_XB_GPIO_DAT_H 0x70 +#define M5602_XB_GPIO_DAT_L 0x71 +#define M5602_XB_GPIO_DIR_H 0x72 +#define M5602_XB_GPIO_DIR_L 0x73 +#define M5602_XB_GPIO_EN_H 0x74 +#define M5602_XB_GPIO_EN_L 0x75 +#define M5602_XB_GPIO_DAT 0x76 +#define M5602_XB_GPIO_DIR 0x77 +#define M5602_XB_MISC_CTL 0x70 + +#define I2C_BUSY 0x80 + +/*****************************************************************************/ + +/* Driver info */ +#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project" +#define DRIVER_DESC "ALi m5602 webcam driver" + +#define M5602_ISOC_ENDPOINT_ADDR 0x81 +#define M5602_INTR_ENDPOINT_ADDR 0x82 + +#define M5602_MAX_FRAMES 32 +#define M5602_URBS 2 +#define M5602_ISOC_PACKETS 14 + +#define M5602_URB_TIMEOUT msecs_to_jiffies(2 * M5602_ISOC_PACKETS) +#define M5602_URB_MSG_TIMEOUT 5000 +#define M5602_FRAME_TIMEOUT 2 + +/*****************************************************************************/ + +/* A skeleton used for sending messages to the m5602 bridge */ +static const unsigned char bridge_urb_skeleton[] = { + 0x13, 0x00, 0x81, 0x00 +}; + +/* A skeleton used for sending messages to the sensor */ +static const unsigned char sensor_urb_skeleton[] = { + 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06, + 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80, + 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00, + 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00, + 0x13, M5602_XB_I2C_DATA, 0x81, 0x00, + 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11 +}; + +/* m5602 device descriptor, currently it just wraps the m5602_camera struct */ +struct sd { + struct gspca_dev gspca_dev; + + /* The name of the m5602 camera */ + char *name; + + /* A pointer to the currently connected sensor */ + struct m5602_sensor *sensor; + + /* The current frame's id, used to detect frame boundaries */ + u8 frame_id; + + /* The current frame count */ + u32 frame_count; +}; + +int m5602_read_bridge( + struct sd *sd, u8 address, u8 *i2c_data); + +int m5602_write_bridge( + struct sd *sd, u8 address, u8 i2c_data); + +int m5602_configure(struct gspca_dev *gspca_dev, + const struct usb_device_id *id); + +int m5602_init(struct gspca_dev *gspca_dev); + +void m5602_start_transfer(struct gspca_dev *gspca_dev); + +void m5602_stop_transfer(struct gspca_dev *gspca_dev); + +void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, + __u8 *data, int len); + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c new file mode 100644 index 00000000000..559495e2d11 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -0,0 +1,321 @@ +/* + * USB Driver for ALi m5602 based webcams + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_ov9650.h" +#include "m5602_mt9m111.h" +#include "m5602_po1030.h" +#include "m5602_s5k83a.h" +#include "m5602_s5k4aa.h" + +/* Kernel module parameters */ +int force_sensor; +int dump_bridge; +int dump_sensor; +unsigned int m5602_debug; + +static const __devinitdata struct usb_device_id m5602_table[] = { + {USB_DEVICE(0x0402, 0x5602)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, m5602_table); + +/* sub-driver description, the ctrl and nctrl is filled at probe time */ +static struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = m5602_configure, + .init = m5602_init, + .start = m5602_start_transfer, + .stopN = m5602_stop_transfer, + .pkt_scan = m5602_urb_complete +}; + +/* Reads a byte from the m5602 */ +int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) +{ + int err; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x04, 0xc0, 0x14, + 0x8100 + address, buf, + 1, M5602_URB_MSG_TIMEOUT); + *i2c_data = buf[0]; + + PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x", + address, *i2c_data); + + /* usb_control_msg(...) returns the number of bytes sent upon success, + mask that and return zero upon success instead*/ + return (err < 0) ? err : 0; +} + +/* Writes a byte to to the m5602 */ +int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) +{ + int err; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x", + address, i2c_data); + + memcpy(buf, bridge_urb_skeleton, + sizeof(bridge_urb_skeleton)); + buf[1] = address; + buf[3] = i2c_data; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 4, M5602_URB_MSG_TIMEOUT); + + /* usb_control_msg(...) returns the number of bytes sent upon success, + mask that and return zero upon success instead */ + return (err < 0) ? err : 0; +} + +/* Dump all the registers of the m5602 bridge, + unfortunately this breaks the camera until it's power cycled */ +static void m5602_dump_bridge(struct sd *sd) +{ + int i; + for (i = 0; i < 0x80; i++) { + unsigned char val = 0; + m5602_read_bridge(sd, i, &val); + info("ALi m5602 address 0x%x contains 0x%x", i, val); + } + info("Warning: The camera probably won't work until it's power cycled"); +} + +int m5602_probe_sensor(struct sd *sd) +{ + /* Try the po1030 */ + sd->sensor = &po1030; + if (!sd->sensor->probe(sd)) { + sd_desc.ctrls = po1030.ctrls; + sd_desc.nctrls = po1030.nctrls; + return 0; + } + + /* Try the mt9m111 sensor */ + sd->sensor = &mt9m111; + if (!sd->sensor->probe(sd)) { + sd_desc.ctrls = mt9m111.ctrls; + sd_desc.nctrls = mt9m111.nctrls; + return 0; + } + + /* Try the s5k4aa */ + sd->sensor = &s5k4aa; + if (!sd->sensor->probe(sd)) { + sd_desc.ctrls = s5k4aa.ctrls; + sd_desc.nctrls = s5k4aa.nctrls; + return 0; + } + + /* Try the ov9650 */ + sd->sensor = &ov9650; + if (!sd->sensor->probe(sd)) { + sd_desc.ctrls = ov9650.ctrls; + sd_desc.nctrls = ov9650.nctrls; + return 0; + } + + /* Try the s5k83a */ + sd->sensor = &s5k83a; + if (!sd->sensor->probe(sd)) { + sd_desc.ctrls = s5k83a.ctrls; + sd_desc.nctrls = s5k83a.nctrls; + return 0; + } + + + /* More sensor probe function goes here */ + info("Failed to find a sensor"); + sd->sensor = NULL; + return -ENODEV; +} + +int m5602_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err; + + PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam"); + /* Run the init sequence */ + err = sd->sensor->init(sd); + + return err; +} + +void m5602_start_transfer(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* Send start command to the camera */ + const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; + memcpy(buf, buffer, sizeof(buffer)); + usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), + 0x04, 0x40, 0x19, 0x0000, buf, + 4, M5602_URB_MSG_TIMEOUT); + + PDEBUG(DBG_V4L2, "Transfer started"); +} + +void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, + __u8 *data, int len) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (len < 6) { + PDEBUG(DBG_DATA, "Packet is less than 6 bytes"); + return; + } + + /* Frame delimiter: ff xx xx xx ff ff */ + if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff && + data[2] != sd->frame_id) { + PDEBUG(DBG_DATA, "Frame delimiter detected"); + sd->frame_id = data[2]; + + /* Remove the extra fluff appended on each header */ + data += 6; + len -= 6; + + /* Complete the last frame (if any) */ + frame = gspca_frame_add(gspca_dev, LAST_PACKET, + frame, data, 0); + + /* Create a new frame */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + + PDEBUG(DBG_V4L2, "Starting new frame. First urb contained %d", + len); + + } else { + int cur_frame_len = frame->data_end - frame->data; + + /* Remove urb header */ + data += 4; + len -= 4; + + if (cur_frame_len + len <= frame->v4l2_buf.length) { + PDEBUG(DBG_DATA, "Continuing frame copying %d bytes", + len); + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, len); + } else if (frame->v4l2_buf.length - cur_frame_len > 0) { + /* Add the remaining data up to frame size */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, + frame->v4l2_buf.length - cur_frame_len); + } + } +} + +void m5602_stop_transfer(struct gspca_dev *gspca_dev) +{ + /* Is there are a command to stop a data transfer? */ +} + +/* this function is called at probe time */ +int m5602_configure(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam; + int err; + + PDEBUG(DBG_GSPCA, "m5602_configure start"); + cam = &gspca_dev->cam; + cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; + + if (dump_bridge) + m5602_dump_bridge(sd); + + /* Probe sensor */ + err = m5602_probe_sensor(sd); + if (err) + goto fail; + + PDEBUG(DBG_GSPCA, "m5602_configure end"); + return 0; + +fail: + PDEBUG(DBG_GSPCA, "m5602_configure failed"); + cam->cam_mode = NULL; + cam->nmodes = 0; + + return err; +} + +static int m5602_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = m5602_table, + .probe = m5602_probe, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif + .disconnect = gspca_disconnect +}; + +/* -- module insert / remove -- */ +static int __init mod_m5602_init(void) +{ + if (usb_register(&sd_driver) < 0) + return -1; + PDEBUG(D_PROBE, "m5602 module registered"); + return 0; +} +static void __exit mod_m5602_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "m5602 module deregistered"); +} + +module_init(mod_m5602_init); +module_exit(mod_m5602_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "toggles debug on/off"); + +module_param(force_sensor, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(force_sensor, + "force detection of sensor, " + "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); + +module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); + +module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers " + "at startup providing a sensor is found"); diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c new file mode 100644 index 00000000000..17f04dd5e1d --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -0,0 +1,343 @@ +/* + * Driver for the mt9m111 sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_mt9m111.h" + +int mt9m111_probe(struct sd *sd) +{ + u8 data[2] = {0x00, 0x00}; + int i; + + if (force_sensor) { + if (force_sensor == MT9M111_SENSOR) { + info("Forcing a %s sensor", mt9m111.name); + goto sensor_found; + } + /* If we want to force another sensor, don't try to probe this + * one */ + return -ENODEV; + } + + info("Probing for a mt9m111 sensor"); + + /* Do the preinit */ + for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { + if (preinit_mt9m111[i][0] == BRIDGE) { + m5602_write_bridge(sd, + preinit_mt9m111[i][1], + preinit_mt9m111[i][2]); + } else { + data[0] = preinit_mt9m111[i][2]; + data[1] = preinit_mt9m111[i][3]; + mt9m111_write_sensor(sd, + preinit_mt9m111[i][1], data, 2); + } + } + + if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) + return -ENODEV; + + if ((data[0] == 0x14) && (data[1] == 0x3a)) { + info("Detected a mt9m111 sensor"); + goto sensor_found; + } + + return -ENODEV; + +sensor_found: + sd->gspca_dev.cam.cam_mode = mt9m111.modes; + sd->gspca_dev.cam.nmodes = mt9m111.nmodes; + return 0; +} + +int mt9m111_init(struct sd *sd) +{ + int i, err; + + /* Init the sensor */ + for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) { + u8 data[2]; + + if (init_mt9m111[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + init_mt9m111[i][1], + init_mt9m111[i][2]); + } else { + data[0] = init_mt9m111[i][2]; + data[1] = init_mt9m111[i][3]; + err = mt9m111_write_sensor(sd, + init_mt9m111[i][1], data, 2); + } + } + + if (dump_sensor) + mt9m111_dump_registers(sd); + + return (err < 0) ? err : 0; +} + +int mt9m111_power_down(struct sd *sd) +{ + return 0; +} + +int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + data, 2); + *val = data[0] & MT9M111_RMB_MIRROR_ROWS; + PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + + return (err < 0) ? err : 0; +} + +int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + + /* Set the correct page map */ + err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + if (err < 0) + goto out; + + err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + if (err < 0) + goto out; + + data[0] = (data[0] & 0xfe) | val; + err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + data, 2); +out: + return (err < 0) ? err : 0; +} + +int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + data, 2); + *val = data[0] & MT9M111_RMB_MIRROR_COLS; + PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); + + return (err < 0) ? err : 0; +} + +int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); + + /* Set the correct page map */ + err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + if (err < 0) + goto out; + + err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + if (err < 0) + goto out; + + data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); + err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + data, 2); +out: + return (err < 0) ? err : 0; +} + +int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err, tmp; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); + tmp = ((data[1] << 8) | data[0]); + + *val = ((tmp & (1 << 10)) * 2) | + ((tmp & (1 << 9)) * 2) | + ((tmp & (1 << 8)) * 2) | + (tmp & 0x7f); + + PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + + return (err < 0) ? err : 0; +} + +int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err, tmp; + u8 data[2] = {0x00, 0x00}; + struct sd *sd = (struct sd *) gspca_dev; + + /* Set the correct page map */ + err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + if (err < 0) + goto out; + + if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) + return -EINVAL; + + if ((val >= INITIAL_MAX_GAIN * 2 * 2) && + (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) + tmp = (1 << 10) | (val << 9) | + (val << 8) | (val / 8); + else if ((val >= INITIAL_MAX_GAIN * 2) && + (val < INITIAL_MAX_GAIN * 2 * 2)) + tmp = (1 << 9) | (1 << 8) | (val / 4); + else if ((val >= INITIAL_MAX_GAIN) && + (val < INITIAL_MAX_GAIN * 2)) + tmp = (1 << 8) | (val / 2); + else + tmp = val; + + data[1] = (tmp & 0xff00) >> 8; + data[0] = (tmp & 0xff); + PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp, + data[1], data[0]); + + err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, + data, 2); +out: + return (err < 0) ? err : 0; +} + +int mt9m111_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) { + int err, i; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a); + if (err < 0) + goto out; + + for (i = 0; i < len && !err; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(DBG_TRACE, "Reading sensor register " + "0x%x contains 0x%x ", address, *i2c_data); + } +out: + return (err < 0) ? err : 0; +} + +int mt9m111_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* No sensor with a data width larger + than 16 bits has yet been seen, nor with 0 :p*/ + if (len > 2 || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, + sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the tailer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + +void mt9m111_dump_registers(struct sd *sd) +{ + u8 address, value[2] = {0x00, 0x00}; + + info("Dumping the mt9m111 register state"); + + info("Dumping the mt9m111 sensor core registers"); + value[1] = MT9M111_SENSOR_CORE; + mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + for (address = 0; address < 0xff; address++) { + mt9m111_read_sensor(sd, address, value, 2); + info("register 0x%x contains 0x%x%x", + address, value[0], value[1]); + } + + info("Dumping the mt9m111 color pipeline registers"); + value[1] = MT9M111_COLORPIPE; + mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + for (address = 0; address < 0xff; address++) { + mt9m111_read_sensor(sd, address, value, 2); + info("register 0x%x contains 0x%x%x", + address, value[0], value[1]); + } + + info("Dumping the mt9m111 camera control registers"); + value[1] = MT9M111_CAMERA_CONTROL; + mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + for (address = 0; address < 0xff; address++) { + mt9m111_read_sensor(sd, address, value, 2); + info("register 0x%x contains 0x%x%x", + address, value[0], value[1]); + } + + info("mt9m111 register state dump complete"); +} diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h new file mode 100644 index 00000000000..79a5d887819 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -0,0 +1,1020 @@ +/* + * Driver for the mt9m111 sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * Some defines taken from the mt9m111 sensor driver + * Copyright (C) 2008, Robert Jarzmik + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_MT9M111_H_ +#define M5602_MT9M111_H_ + +#include "m5602_sensor.h" + +/*****************************************************************************/ + +#define MT9M111_SC_CHIPVER 0x00 +#define MT9M111_SC_ROWSTART 0x01 +#define MT9M111_SC_COLSTART 0x02 +#define MT9M111_SC_WINDOW_HEIGHT 0x03 +#define MT9M111_SC_WINDOW_WIDTH 0x04 +#define MT9M111_SC_HBLANK_CONTEXT_B 0x05 +#define MT9M111_SC_VBLANK_CONTEXT_B 0x06 +#define MT9M111_SC_HBLANK_CONTEXT_A 0x07 +#define MT9M111_SC_VBLANK_CONTEXT_A 0x08 +#define MT9M111_SC_SHUTTER_WIDTH 0x09 +#define MT9M111_SC_ROW_SPEED 0x0a + +#define MT9M111_SC_EXTRA_DELAY 0x0b +#define MT9M111_SC_SHUTTER_DELAY 0x0c +#define MT9M111_SC_RESET 0x0d +#define MT9M111_SC_R_MODE_CONTEXT_B 0x20 +#define MT9M111_SC_R_MODE_CONTEXT_A 0x21 +#define MT9M111_SC_FLASH_CONTROL 0x23 +#define MT9M111_SC_GREEN_1_GAIN 0x2b +#define MT9M111_SC_BLUE_GAIN 0x2c +#define MT9M111_SC_RED_GAIN 0x2d +#define MT9M111_SC_GREEN_2_GAIN 0x2e +#define MT9M111_SC_GLOBAL_GAIN 0x2f + +#define MT9M111_RMB_MIRROR_ROWS (1 << 0) +#define MT9M111_RMB_MIRROR_COLS (1 << 1) + +#define MT9M111_CONTEXT_CONTROL 0xc8 +#define MT9M111_PAGE_MAP 0xf0 +#define MT9M111_BYTEWISE_ADDRESS 0xf1 + +#define MT9M111_CP_OPERATING_MODE_CTL 0x06 +#define MT9M111_CP_LUMA_OFFSET 0x34 +#define MT9M111_CP_LUMA_CLIP 0x35 +#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a +#define MT9M111_CP_LENS_CORRECTION_1 0x3b +#define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c +#define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d +#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b +#define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3 + +#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65 +#define MT9M111_CC_AWB_PARAMETER_7 0x28 + +#define MT9M111_SENSOR_CORE 0x00 +#define MT9M111_COLORPIPE 0x01 +#define MT9M111_CAMERA_CONTROL 0x02 + +#define INITIAL_MAX_GAIN 64 +#define DEFAULT_GAIN 283 + +/*****************************************************************************/ + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; +extern unsigned int m5602_debug; + +int mt9m111_probe(struct sd *sd); +int mt9m111_init(struct sd *sd); +int mt9m111_power_down(struct sd *sd); + +int mt9m111_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +int mt9m111_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +void mt9m111_dump_registers(struct sd *sd); + +int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); + +static struct m5602_sensor mt9m111 = { + .name = "MT9M111", + + .i2c_slave_id = 0xba, + + .probe = mt9m111_probe, + .init = mt9m111_init, + .power_down = mt9m111_power_down, + + .read_sensor = mt9m111_read_sensor, + .write_sensor = mt9m111_write_sensor, + + .nctrls = 3, + .ctrls = { + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = mt9m111_set_vflip, + .get = mt9m111_get_vflip + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = mt9m111_set_hflip, + .get = mt9m111_get_hflip + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0, + .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, + .step = 1, + .default_value = DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = mt9m111_set_hflip, + .get = mt9m111_get_hflip + } + }, + + .nmodes = 1, + .modes = { + { + M5602_DEFAULT_FRAME_WIDTH, + M5602_DEFAULT_FRAME_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, + .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +static const unsigned char preinit_mt9m111[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00} +}; + +static const unsigned char init_mt9m111[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xde}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, + {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, + + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, + {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, + + {SENSOR, 0xcd, 0x00, 0x0e}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, + {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, + {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {SENSOR, 0x33, 0x03, 0x49}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + + {SENSOR, 0x33, 0x03, 0x49}, + {SENSOR, 0x34, 0xc0, 0x19}, + {SENSOR, 0x3f, 0x20, 0x20}, + {SENSOR, 0x40, 0x20, 0x20}, + {SENSOR, 0x5a, 0xc0, 0x0a}, + {SENSOR, 0x70, 0x7b, 0x0a}, + {SENSOR, 0x71, 0xff, 0x00}, + {SENSOR, 0x72, 0x19, 0x0e}, + {SENSOR, 0x73, 0x18, 0x0f}, + {SENSOR, 0x74, 0x57, 0x32}, + {SENSOR, 0x75, 0x56, 0x34}, + {SENSOR, 0x76, 0x73, 0x35}, + {SENSOR, 0x77, 0x30, 0x12}, + {SENSOR, 0x78, 0x79, 0x02}, + {SENSOR, 0x79, 0x75, 0x06}, + {SENSOR, 0x7a, 0x77, 0x0a}, + {SENSOR, 0x7b, 0x78, 0x09}, + {SENSOR, 0x7c, 0x7d, 0x06}, + {SENSOR, 0x7d, 0x31, 0x10}, + {SENSOR, 0x7e, 0x00, 0x7e}, + {SENSOR, 0x80, 0x59, 0x04}, + {SENSOR, 0x81, 0x59, 0x04}, + {SENSOR, 0x82, 0x57, 0x0a}, + {SENSOR, 0x83, 0x58, 0x0b}, + {SENSOR, 0x84, 0x47, 0x0c}, + {SENSOR, 0x85, 0x48, 0x0e}, + {SENSOR, 0x86, 0x5b, 0x02}, + {SENSOR, 0x87, 0x00, 0x5c}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, 0x60, 0x00, 0x80}, + {SENSOR, 0x61, 0x00, 0x00}, + {SENSOR, 0x62, 0x00, 0x00}, + {SENSOR, 0x63, 0x00, 0x00}, + {SENSOR, 0x64, 0x00, 0x00}, + + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, + {SENSOR, 0x30, 0x04, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, + {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, + {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, + + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, + {SENSOR, 0xcd, 0x00, 0x0e}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, + {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, + {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {SENSOR, 0x33, 0x03, 0x49}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + + {SENSOR, 0x33, 0x03, 0x49}, + {SENSOR, 0x34, 0xc0, 0x19}, + {SENSOR, 0x3f, 0x20, 0x20}, + {SENSOR, 0x40, 0x20, 0x20}, + {SENSOR, 0x5a, 0xc0, 0x0a}, + {SENSOR, 0x70, 0x7b, 0x0a}, + {SENSOR, 0x71, 0xff, 0x00}, + {SENSOR, 0x72, 0x19, 0x0e}, + {SENSOR, 0x73, 0x18, 0x0f}, + {SENSOR, 0x74, 0x57, 0x32}, + {SENSOR, 0x75, 0x56, 0x34}, + {SENSOR, 0x76, 0x73, 0x35}, + {SENSOR, 0x77, 0x30, 0x12}, + {SENSOR, 0x78, 0x79, 0x02}, + {SENSOR, 0x79, 0x75, 0x06}, + {SENSOR, 0x7a, 0x77, 0x0a}, + {SENSOR, 0x7b, 0x78, 0x09}, + {SENSOR, 0x7c, 0x7d, 0x06}, + {SENSOR, 0x7d, 0x31, 0x10}, + {SENSOR, 0x7e, 0x00, 0x7e}, + {SENSOR, 0x80, 0x59, 0x04}, + {SENSOR, 0x81, 0x59, 0x04}, + {SENSOR, 0x82, 0x57, 0x0a}, + {SENSOR, 0x83, 0x58, 0x0b}, + {SENSOR, 0x84, 0x47, 0x0c}, + {SENSOR, 0x85, 0x48, 0x0e}, + {SENSOR, 0x86, 0x5b, 0x02}, + {SENSOR, 0x87, 0x00, 0x5c}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, 0x60, 0x00, 0x80}, + {SENSOR, 0x61, 0x00, 0x00}, + {SENSOR, 0x62, 0x00, 0x00}, + {SENSOR, 0x63, 0x00, 0x00}, + {SENSOR, 0x64, 0x00, 0x00}, + + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, + {SENSOR, 0x30, 0x04, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, + {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, + {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, + + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, + {SENSOR, 0xcd, 0x00, 0x0e}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, + {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, + {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {SENSOR, 0x33, 0x03, 0x49}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + + {SENSOR, 0x33, 0x03, 0x49}, + {SENSOR, 0x34, 0xc0, 0x19}, + {SENSOR, 0x3f, 0x20, 0x20}, + {SENSOR, 0x40, 0x20, 0x20}, + {SENSOR, 0x5a, 0xc0, 0x0a}, + {SENSOR, 0x70, 0x7b, 0x0a}, + {SENSOR, 0x71, 0xff, 0x00}, + {SENSOR, 0x72, 0x19, 0x0e}, + {SENSOR, 0x73, 0x18, 0x0f}, + {SENSOR, 0x74, 0x57, 0x32}, + {SENSOR, 0x75, 0x56, 0x34}, + {SENSOR, 0x76, 0x73, 0x35}, + {SENSOR, 0x77, 0x30, 0x12}, + {SENSOR, 0x78, 0x79, 0x02}, + {SENSOR, 0x79, 0x75, 0x06}, + {SENSOR, 0x7a, 0x77, 0x0a}, + {SENSOR, 0x7b, 0x78, 0x09}, + {SENSOR, 0x7c, 0x7d, 0x06}, + {SENSOR, 0x7d, 0x31, 0x10}, + {SENSOR, 0x7e, 0x00, 0x7e}, + {SENSOR, 0x80, 0x59, 0x04}, + {SENSOR, 0x81, 0x59, 0x04}, + {SENSOR, 0x82, 0x57, 0x0a}, + {SENSOR, 0x83, 0x58, 0x0b}, + {SENSOR, 0x84, 0x47, 0x0c}, + {SENSOR, 0x85, 0x48, 0x0e}, + {SENSOR, 0x86, 0x5b, 0x02}, + {SENSOR, 0x87, 0x00, 0x5c}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, 0x60, 0x00, 0x80}, + {SENSOR, 0x61, 0x00, 0x00}, + {SENSOR, 0x62, 0x00, 0x00}, + {SENSOR, 0x63, 0x00, 0x00}, + {SENSOR, 0x64, 0x00, 0x00}, + + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, + {SENSOR, 0x30, 0x04, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, + {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, + {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, + + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0xcd, 0x00, 0x0e}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, + {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0x33, 0x03, 0x49}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + + {SENSOR, 0x33, 0x03, 0x49}, + {SENSOR, 0x34, 0xc0, 0x19}, + {SENSOR, 0x3f, 0x20, 0x20}, + {SENSOR, 0x40, 0x20, 0x20}, + {SENSOR, 0x5a, 0xc0, 0x0a}, + {SENSOR, 0x70, 0x7b, 0x0a}, + {SENSOR, 0x71, 0xff, 0x00}, + {SENSOR, 0x72, 0x19, 0x0e}, + {SENSOR, 0x73, 0x18, 0x0f}, + {SENSOR, 0x74, 0x57, 0x32}, + {SENSOR, 0x75, 0x56, 0x34}, + {SENSOR, 0x76, 0x73, 0x35}, + {SENSOR, 0x77, 0x30, 0x12}, + {SENSOR, 0x78, 0x79, 0x02}, + {SENSOR, 0x79, 0x75, 0x06}, + {SENSOR, 0x7a, 0x77, 0x0a}, + {SENSOR, 0x7b, 0x78, 0x09}, + {SENSOR, 0x7c, 0x7d, 0x06}, + {SENSOR, 0x7d, 0x31, 0x10}, + {SENSOR, 0x7e, 0x00, 0x7e}, + {SENSOR, 0x80, 0x59, 0x04}, + {SENSOR, 0x81, 0x59, 0x04}, + {SENSOR, 0x82, 0x57, 0x0a}, + {SENSOR, 0x83, 0x58, 0x0b}, + {SENSOR, 0x84, 0x47, 0x0c}, + {SENSOR, 0x85, 0x48, 0x0e}, + {SENSOR, 0x86, 0x5b, 0x02}, + {SENSOR, 0x87, 0x00, 0x5c}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, 0x60, 0x00, 0x80}, + {SENSOR, 0x61, 0x00, 0x00}, + {SENSOR, 0x62, 0x00, 0x00}, + {SENSOR, 0x63, 0x00, 0x00}, + {SENSOR, 0x64, 0x00, 0x00}, + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, + {SENSOR, 0x30, 0x04, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, + {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, + {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, + {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, + + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0xcd, 0x00, 0x0e}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, + {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, 0x33, 0x03, 0x49}, + {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, + {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, + {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + + {SENSOR, 0x33, 0x03, 0x49}, + {SENSOR, 0x34, 0xc0, 0x19}, + {SENSOR, 0x3f, 0x20, 0x20}, + {SENSOR, 0x40, 0x20, 0x20}, + {SENSOR, 0x5a, 0xc0, 0x0a}, + {SENSOR, 0x70, 0x7b, 0x0a}, + {SENSOR, 0x71, 0xff, 0x00}, + {SENSOR, 0x72, 0x19, 0x0e}, + {SENSOR, 0x73, 0x18, 0x0f}, + {SENSOR, 0x74, 0x57, 0x32}, + {SENSOR, 0x75, 0x56, 0x34}, + {SENSOR, 0x76, 0x73, 0x35}, + {SENSOR, 0x77, 0x30, 0x12}, + {SENSOR, 0x78, 0x79, 0x02}, + {SENSOR, 0x79, 0x75, 0x06}, + {SENSOR, 0x7a, 0x77, 0x0a}, + {SENSOR, 0x7b, 0x78, 0x09}, + {SENSOR, 0x7c, 0x7d, 0x06}, + {SENSOR, 0x7d, 0x31, 0x10}, + {SENSOR, 0x7e, 0x00, 0x7e}, + {SENSOR, 0x80, 0x59, 0x04}, + {SENSOR, 0x81, 0x59, 0x04}, + {SENSOR, 0x82, 0x57, 0x0a}, + {SENSOR, 0x83, 0x58, 0x0b}, + {SENSOR, 0x84, 0x47, 0x0c}, + {SENSOR, 0x85, 0x48, 0x0e}, + {SENSOR, 0x86, 0x5b, 0x02}, + {SENSOR, 0x87, 0x00, 0x5c}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, 0x60, 0x00, 0x80}, + {SENSOR, 0x61, 0x00, 0x00}, + {SENSOR, 0x62, 0x00, 0x00}, + {SENSOR, 0x63, 0x00, 0x00}, + {SENSOR, 0x64, 0x00, 0x00}, + + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, + {SENSOR, 0x30, 0x04, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + /* Set number of blank rows chosen to 400 */ + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, + /* Set the global gain to 283 (of 512) */ + {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63} +}; + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c new file mode 100644 index 00000000000..74c3ffec0ca --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -0,0 +1,544 @@ +/* + * Driver for the ov9650 sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_ov9650.h" + +int ov9650_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + + /* The ov9650 registers have a max depth of one byte */ + if (len > 1 || !len) + return -EINVAL; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + + m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + ov9650.i2c_slave_id); + m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); + m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + + for (i = 0; i < len; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(DBG_TRACE, "Reading sensor register " + "0x%x containing 0x%x ", address, *i2c_data); + } + return (err < 0) ? err : 0; +} + +int ov9650_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* The ov9650 only supports one byte writes */ + if (len > 1 || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, + sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + /* Special case larger sensor writes */ + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the tailer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + +int ov9650_probe(struct sd *sd) +{ + u8 prod_id = 0, ver_id = 0, i; + + if (force_sensor) { + if (force_sensor == OV9650_SENSOR) { + info("Forcing an %s sensor", ov9650.name); + goto sensor_found; + } + /* If we want to force another sensor, + don't try to probe this one */ + return -ENODEV; + } + + info("Probing for an ov9650 sensor"); + + /* Run the pre-init to actually probe the unit */ + for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { + u8 data = preinit_ov9650[i][2]; + if (preinit_ov9650[i][0] == SENSOR) + ov9650_write_sensor(sd, + preinit_ov9650[i][1], &data, 1); + else + m5602_write_bridge(sd, preinit_ov9650[i][1], data); + } + + if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1)) + return -ENODEV; + + if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1)) + return -ENODEV; + + if ((prod_id == 0x96) && (ver_id == 0x52)) { + info("Detected an ov9650 sensor"); + goto sensor_found; + } + + return -ENODEV; + +sensor_found: + sd->gspca_dev.cam.cam_mode = ov9650.modes; + sd->gspca_dev.cam.nmodes = ov9650.nmodes; + return 0; +} + +int ov9650_init(struct sd *sd) +{ + int i, err = 0; + u8 data; + + if (dump_sensor) + ov9650_dump_registers(sd); + + for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) { + data = init_ov9650[i][2]; + if (init_ov9650[i][0] == SENSOR) + err = ov9650_write_sensor(sd, init_ov9650[i][1], + &data, 1); + else + err = m5602_write_bridge(sd, init_ov9650[i][1], data); + } + + if (!err && dmi_check_system(ov9650_flip_dmi_table)) { + info("vflip quirk active"); + data = 0x30; + err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1); + } + + return (err < 0) ? err : 0; +} + +int ov9650_power_down(struct sd *sd) +{ + int i; + for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) { + u8 data = power_down_ov9650[i][2]; + if (power_down_ov9650[i][0] == SENSOR) + ov9650_write_sensor(sd, + power_down_ov9650[i][1], &data, 1); + else + m5602_write_bridge(sd, power_down_ov9650[i][1], data); + } + + return 0; +} + +int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1); + if (err < 0) + goto out; + *val = i2c_data & 0x03; + + err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1); + if (err < 0) + goto out; + *val |= (i2c_data << 2); + + err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); + if (err < 0) + goto out; + *val |= (i2c_data & 0x3f) << 10; + + PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); +out: + return (err < 0) ? err : 0; +} + +int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + PDEBUG(DBG_V4L2_CID, "Set exposure to %d", + val & 0xffff); + + /* The 6 MSBs */ + i2c_data = (val >> 10) & 0x3f; + err = ov9650_write_sensor(sd, OV9650_AECHM, + &i2c_data, 1); + if (err < 0) + goto out; + + /* The 8 middle bits */ + i2c_data = (val >> 2) & 0xff; + err = ov9650_write_sensor(sd, OV9650_AECH, + &i2c_data, 1); + if (err < 0) + goto out; + + /* The 2 LSBs */ + i2c_data = val & 0x03; + err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1); + +out: + return (err < 0) ? err : 0; +} + +int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + *val = (i2c_data & 0x03) << 8; + + err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); + *val |= i2c_data; + PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + return (err < 0) ? err : 0; +} + +int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + /* The 2 MSB */ + /* Read the OV9650_VREF register first to avoid + corrupting the VREF high and low bits */ + ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + /* Mask away all uninteresting bits */ + i2c_data = ((val & 0x0300) >> 2) | + (i2c_data & 0x3F); + err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); + + /* The 8 LSBs */ + i2c_data = val & 0xff; + err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); + return (err < 0) ? err : 0; +} + +int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1); + *val = i2c_data; + + PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set red gain to %d", + val & 0xff); + + i2c_data = val & 0xff; + err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1); + + return (err < 0) ? err : 0; +} + +int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); + *val = i2c_data; + + PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set blue gain to %d", + val & 0xff); + + i2c_data = val & 0xff; + err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); + + return (err < 0) ? err : 0; +} + +int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + if (dmi_check_system(ov9650_flip_dmi_table)) + *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; + else + *val = (i2c_data & OV9650_HFLIP) >> 5; + PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); + err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + if (err < 0) + goto out; + + if (dmi_check_system(ov9650_flip_dmi_table)) + i2c_data = ((i2c_data & 0xdf) | + (((val ? 0 : 1) & 0x01) << 5)); + else + i2c_data = ((i2c_data & 0xdf) | + ((val & 0x01) << 5)); + + err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); +out: + return (err < 0) ? err : 0; +} + +int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + if (dmi_check_system(ov9650_flip_dmi_table)) + *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; + else + *val = (i2c_data & 0x10) >> 4; + PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + if (err < 0) + goto out; + + if (dmi_check_system(ov9650_flip_dmi_table)) + i2c_data = ((i2c_data & 0xef) | + (((val ? 0 : 1) & 0x01) << 4)); + else + i2c_data = ((i2c_data & 0xef) | + ((val & 0x01) << 4)); + + err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); +out: + return (err < 0) ? err : 0; +} + +int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + goto out; + *val = (i2c_data & 0x03) << 8; + + err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); + *val |= i2c_data; + PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); +out: + return (err < 0) ? err : 0; +} + +int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff); + + /* Read the OV9650_VREF register first to avoid + corrupting the VREF high and low bits */ + err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + goto out; + + /* Mask away all uninteresting bits */ + i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); + err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + goto out; + + /* The 8 LSBs */ + i2c_data = val & 0xff; + err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); + +out: + return (err < 0) ? err : 0; +} + +int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + *val = (i2c_data & OV9650_AWB_EN) >> 1; + PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val); + err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + if (err < 0) + goto out; + + i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); + err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); +out: + return (err < 0) ? err : 0; +} + +int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + *val = (i2c_data & OV9650_AGC_EN) >> 2; + PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val); + + return (err < 0) ? err : 0; +} + +int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val); + err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + if (err < 0) + goto out; + + i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); + err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); +out: + return (err < 0) ? err : 0; +} + +void ov9650_dump_registers(struct sd *sd) +{ + int address; + info("Dumping the ov9650 register state"); + for (address = 0; address < 0xa9; address++) { + u8 value; + ov9650_read_sensor(sd, address, &value, 1); + info("register 0x%x contains 0x%x", + address, value); + } + + info("ov9650 register state dump complete"); + + info("Probing for which registers that are read/write"); + for (address = 0; address < 0xff; address++) { + u8 old_value, ctrl_value; + u8 test_value[2] = {0xff, 0xff}; + + ov9650_read_sensor(sd, address, &old_value, 1); + ov9650_write_sensor(sd, address, test_value, 1); + ov9650_read_sensor(sd, address, &ctrl_value, 1); + + if (ctrl_value == test_value[0]) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original value */ + ov9650_write_sensor(sd, address, &old_value, 1); + } +} diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h new file mode 100644 index 00000000000..486ea337a8b --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -0,0 +1,501 @@ +/* + * Driver for the ov9650 sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_OV9650_H_ +#define M5602_OV9650_H_ + +#include + +#include "m5602_sensor.h" + +/*****************************************************************************/ + +#define OV9650_GAIN 0x00 +#define OV9650_BLUE 0x01 +#define OV9650_RED 0x02 +#define OV9650_VREF 0x03 +#define OV9650_COM1 0x04 +#define OV9650_BAVE 0x05 +#define OV9650_GEAVE 0x06 +#define OV9650_RSVD7 0x07 +#define OV9650_PID 0x0a +#define OV9650_VER 0x0b +#define OV9650_COM3 0x0c +#define OV9650_COM5 0x0e +#define OV9650_COM6 0x0f +#define OV9650_AECH 0x10 +#define OV9650_CLKRC 0x11 +#define OV9650_COM7 0x12 +#define OV9650_COM8 0x13 +#define OV9650_COM9 0x14 +#define OV9650_COM10 0x15 +#define OV9650_RSVD16 0x16 +#define OV9650_HSTART 0x17 +#define OV9650_HSTOP 0x18 +#define OV9650_VSTRT 0x19 +#define OV9650_VSTOP 0x1a +#define OV9650_PSHFT 0x1b +#define OV9650_MVFP 0x1e +#define OV9650_AEW 0x24 +#define OV9650_AEB 0x25 +#define OV9650_VPT 0x26 +#define OV9650_BBIAS 0x27 +#define OV9650_GbBIAS 0x28 +#define OV9650_Gr_COM 0x29 +#define OV9650_RBIAS 0x2c +#define OV9650_HREF 0x32 +#define OV9650_CHLF 0x33 +#define OV9650_ARBLM 0x34 +#define OV9650_RSVD35 0x35 +#define OV9650_RSVD36 0x36 +#define OV9650_ADC 0x37 +#define OV9650_ACOM38 0x38 +#define OV9650_OFON 0x39 +#define OV9650_TSLB 0x3a +#define OV9650_COM12 0x3c +#define OV9650_COM13 0x3d +#define OV9650_COM15 0x40 +#define OV9650_COM16 0x41 +#define OV9650_LCC1 0x62 +#define OV9650_LCC2 0x63 +#define OV9650_LCC3 0x64 +#define OV9650_LCC4 0x65 +#define OV9650_LCC5 0x66 +#define OV9650_HV 0x69 +#define OV9650_DBLV 0x6b +#define OV9650_COM21 0x8b +#define OV9650_COM22 0x8c +#define OV9650_COM24 0x8e +#define OV9650_DBLC1 0x8f +#define OV9650_RSVD94 0x94 +#define OV9650_RSVD95 0x95 +#define OV9650_RSVD96 0x96 +#define OV9650_LCCFB 0x9d +#define OV9650_LCCFR 0x9e +#define OV9650_AECHM 0xa1 +#define OV9650_COM26 0xa5 +#define OV9650_ACOMA8 0xa8 +#define OV9650_ACOMA9 0xa9 + +#define OV9650_REGISTER_RESET (1 << 7) +#define OV9650_VGA_SELECT (1 << 6) +#define OV9650_RGB_SELECT (1 << 2) +#define OV9650_RAW_RGB_SELECT (1 << 0) + +#define OV9650_FAST_AGC_AEC (1 << 7) +#define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6) +#define OV9650_BANDING (1 << 5) +#define OV9650_AGC_EN (1 << 2) +#define OV9650_AWB_EN (1 << 1) +#define OV9650_AEC_EN (1 << 0) + +#define OV9650_VARIOPIXEL (1 << 2) +#define OV9650_SYSTEM_CLK_SEL (1 << 7) +#define OV9650_SLAM_MODE (1 << 4) + +#define OV9650_VFLIP (1 << 4) +#define OV9650_HFLIP (1 << 5) + +#define GAIN_DEFAULT 0x14 +#define RED_GAIN_DEFAULT 0x70 +#define BLUE_GAIN_DEFAULT 0x20 +#define EXPOSURE_DEFAULT 0x5003 + +/*****************************************************************************/ + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; +extern unsigned int m5602_debug; + +int ov9650_probe(struct sd *sd); +int ov9650_init(struct sd *sd); +int ov9650_power_down(struct sd *sd); + +int ov9650_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); +int ov9650_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +void ov9650_dump_registers(struct sd *sd); + +int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); +int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); +int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); + +static struct m5602_sensor ov9650 = { + .name = "OV9650", + .i2c_slave_id = 0x60, + .probe = ov9650_probe, + .init = ov9650_init, + .power_down = ov9650_power_down, + .read_sensor = ov9650_read_sensor, + .write_sensor = ov9650_write_sensor, + + .nctrls = 8, + .ctrls = { + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0xffff, + .step = 0x1, + .default_value = EXPOSURE_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_exposure, + .get = ov9650_get_exposure + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0x3ff, + .step = 0x1, + .default_value = GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_gain, + .get = ov9650_get_gain + }, { + { + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = RED_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_red_balance, + .get = ov9650_get_red_balance + }, { + { + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = BLUE_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_blue_balance, + .get = ov9650_get_blue_balance + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_hflip, + .get = ov9650_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_vflip, + .get = ov9650_get_vflip + }, { + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto white balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_auto_white_balance, + .get = ov9650_get_auto_white_balance + }, { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto gain control", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_auto_gain, + .get = ov9650_get_auto_gain + } + }, + + .nmodes = 1, + .modes = { + { + M5602_DEFAULT_FRAME_WIDTH, + M5602_DEFAULT_FRAME_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, + .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +static const unsigned char preinit_ov9650[][3] = +{ + /* [INITCAM] */ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, + /* Reset chip */ + {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, + /* Enable double clock */ + {SENSOR, OV9650_CLKRC, 0x80}, + /* Do something out of spec with the power */ + {SENSOR, OV9650_OFON, 0x40} +}; + +static const unsigned char init_ov9650[][3] = +{ + /* [INITCAM] */ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, + /* Reset chip */ + {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, + /* Enable double clock */ + {SENSOR, OV9650_CLKRC, 0x80}, + /* Do something out of spec with the power */ + {SENSOR, OV9650_OFON, 0x40}, + + /* Set QQVGA */ + {SENSOR, OV9650_COM1, 0x20}, + /* Set fast AGC/AEC algorithm with unlimited step size */ + {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | + OV9650_AEC_UNLIM_STEP_SIZE | + OV9650_AWB_EN | OV9650_AGC_EN}, + + {SENSOR, OV9650_CHLF, 0x10}, + {SENSOR, OV9650_ARBLM, 0xbf}, + {SENSOR, OV9650_ACOM38, 0x81}, + /* Turn off color matrix coefficient double option */ + {SENSOR, OV9650_COM16, 0x00}, + /* Enable color matrix for RGB/YUV, Delay Y channel, + set output Y/UV delay to 1 */ + {SENSOR, OV9650_COM13, 0x19}, + /* Enable digital BLC, Set output mode to U Y V Y */ + {SENSOR, OV9650_TSLB, 0x0c}, + /* Limit the AGC/AEC stable upper region */ + {SENSOR, OV9650_COM24, 0x00}, + /* Enable HREF and some out of spec things */ + {SENSOR, OV9650_COM12, 0x73}, + /* Set all DBLC offset signs to positive and + do some out of spec stuff */ + {SENSOR, OV9650_DBLC1, 0xdf}, + {SENSOR, OV9650_COM21, 0x06}, + {SENSOR, OV9650_RSVD35, 0x91}, + /* Necessary, no camera stream without it */ + {SENSOR, OV9650_RSVD16, 0x06}, + {SENSOR, OV9650_RSVD94, 0x99}, + {SENSOR, OV9650_RSVD95, 0x99}, + {SENSOR, OV9650_RSVD96, 0x04}, + /* Enable full range output */ + {SENSOR, OV9650_COM15, 0x0}, + /* Enable HREF at optical black, enable ADBLC bias, + enable ADBLC, reset timings at format change */ + {SENSOR, OV9650_COM6, 0x4b}, + /* Subtract 32 from the B channel bias */ + {SENSOR, OV9650_BBIAS, 0xa0}, + /* Subtract 32 from the Gb channel bias */ + {SENSOR, OV9650_GbBIAS, 0xa0}, + /* Do not bypass the analog BLC and to some out of spec stuff */ + {SENSOR, OV9650_Gr_COM, 0x00}, + /* Subtract 32 from the R channel bias */ + {SENSOR, OV9650_RBIAS, 0xa0}, + /* Subtract 32 from the R channel bias */ + {SENSOR, OV9650_RBIAS, 0x0}, + {SENSOR, OV9650_COM26, 0x80}, + {SENSOR, OV9650_ACOMA9, 0x98}, + /* Set the AGC/AEC stable region upper limit */ + {SENSOR, OV9650_AEW, 0x68}, + /* Set the AGC/AEC stable region lower limit */ + {SENSOR, OV9650_AEB, 0x5c}, + /* Set the high and low limit nibbles to 3 */ + {SENSOR, OV9650_VPT, 0xc3}, + /* Set the Automatic Gain Ceiling (AGC) to 128x, + drop VSYNC at frame drop, + limit exposure timing, + drop frame when the AEC step is larger than the exposure gap */ + {SENSOR, OV9650_COM9, 0x6e}, + /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync) + and set PWDN to SLVS (slave mode vertical sync) */ + {SENSOR, OV9650_COM10, 0x42}, + /* Set horizontal column start high to default value */ + {SENSOR, OV9650_HSTART, 0x1a}, + /* Set horizontal column end */ + {SENSOR, OV9650_HSTOP, 0xbf}, + /* Complementing register to the two writes above */ + {SENSOR, OV9650_HREF, 0xb2}, + /* Set vertical row start high bits */ + {SENSOR, OV9650_VSTRT, 0x02}, + /* Set vertical row end low bits */ + {SENSOR, OV9650_VSTOP, 0x7e}, + /* Set complementing vertical frame control */ + {SENSOR, OV9650_VREF, 0x10}, + /* Set raw RGB output format with VGA resolution */ + {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, + {SENSOR, OV9650_ADC, 0x04}, + {SENSOR, OV9650_HV, 0x40}, + /* Enable denoise, and white-pixel erase */ + {SENSOR, OV9650_COM22, 0x23}, + + /* Set the high bits of the exposure value */ + {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)}, + + /* Set the low bits of the exposure value */ + {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)}, + {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, + {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, + {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, + + {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, + {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL}, + + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0xde} +}; + +static const unsigned char power_down_ov9650[][3] = +{ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {SENSOR, OV9650_COM7, 0x80}, + {SENSOR, OV9650_OFON, 0xf4}, + {SENSOR, OV9650_MVFP, 0x80}, + {SENSOR, OV9650_DBLV, 0x3f}, + {SENSOR, OV9650_RSVD36, 0x49}, + {SENSOR, OV9650_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} +}; + +/* Vertically and horizontally flips the image if matched, needed for machines + where the sensor is mounted upside down */ +static const struct dmi_system_id ov9650_flip_dmi_table[] = { + { + .ident = "ASUS A6VC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") + } + }, + { + .ident = "ASUS A6VM", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") + } + }, + { + .ident = "ASUS A6JC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") + } + }, + { + .ident = "ASUS A6Kt", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") + } + }, + { } +}; + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c new file mode 100644 index 00000000000..14a8f929dd1 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -0,0 +1,334 @@ +/* + * Driver for the po1030 sensor + * + * Copyright (c) 2008 Erik Andren + * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (c) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_po1030.h" + +int po1030_probe(struct sd *sd) +{ + u8 prod_id = 0, ver_id = 0, i; + + if (force_sensor) { + if (force_sensor == PO1030_SENSOR) { + info("Forcing a %s sensor", po1030.name); + goto sensor_found; + } + /* If we want to force another sensor, don't try to probe this + * one */ + return -ENODEV; + } + + info("Probing for a po1030 sensor"); + + /* Run the pre-init to actually probe the unit */ + for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { + u8 data = preinit_po1030[i][2]; + if (preinit_po1030[i][0] == SENSOR) + po1030_write_sensor(sd, + preinit_po1030[i][1], &data, 1); + else + m5602_write_bridge(sd, preinit_po1030[i][1], data); + } + + if (po1030_read_sensor(sd, 0x3, &prod_id, 1)) + return -ENODEV; + + if (po1030_read_sensor(sd, 0x4, &ver_id, 1)) + return -ENODEV; + + if ((prod_id == 0x02) && (ver_id == 0xef)) { + info("Detected a po1030 sensor"); + goto sensor_found; + } + return -ENODEV; + +sensor_found: + sd->gspca_dev.cam.cam_mode = po1030.modes; + sd->gspca_dev.cam.nmodes = po1030.nmodes; + return 0; +} + +int po1030_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + + m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); + m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + + for (i = 0; i < len; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(DBG_TRACE, "Reading sensor register " + "0x%x containing 0x%x ", address, *i2c_data); + } + return (err < 0) ? err : 0; +} + +int po1030_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* The po1030 only supports one byte writes */ + if (len > 1 || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the footer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + +int po1030_init(struct sd *sd) +{ + int i, err = 0; + + /* Init the sensor */ + for (i = 0; i < ARRAY_SIZE(init_po1030); i++) { + u8 data[2] = {0x00, 0x00}; + + switch (init_po1030[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + init_po1030[i][1], + init_po1030[i][2]); + break; + + case SENSOR: + data[0] = init_po1030[i][2]; + err = po1030_write_sensor(sd, + init_po1030[i][1], data, 1); + break; + + case SENSOR_LONG: + data[0] = init_po1030[i][2]; + data[1] = init_po1030[i][3]; + err = po1030_write_sensor(sd, + init_po1030[i][1], data, 2); + break; + default: + info("Invalid stream command, exiting init"); + return -EINVAL; + } + } + + if (dump_sensor) + po1030_dump_registers(sd); + + return (err < 0) ? err : 0; +} + +int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H, + &i2c_data, 1); + if (err < 0) + goto out; + *val = (i2c_data << 8); + + err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M, + &i2c_data, 1); + *val |= i2c_data; + + PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val); +out: + return (err < 0) ? err : 0; +} + +int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff); + + i2c_data = ((val & 0xff00) >> 8); + PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x", + i2c_data); + + err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H, + &i2c_data, 1); + if (err < 0) + goto out; + + i2c_data = (val & 0xff); + PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x", + i2c_data); + err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M, + &i2c_data, 1); + +out: + return (err < 0) ? err : 0; +} + +int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, + &i2c_data, 1); + *val = i2c_data; + PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val); + + return (err < 0) ? err : 0; +} + +int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + i2c_data = val & 0xff; + PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data); + err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, + &i2c_data, 1); + return (err < 0) ? err : 0; +} + +int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN, + &i2c_data, 1); + *val = i2c_data; + PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); + return (err < 0) ? err : 0; +} + +int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + i2c_data = val & 0xff; + PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data); + err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, + &i2c_data, 1); + return (err < 0) ? err : 0; +} + +int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN, + &i2c_data, 1); + *val = i2c_data; + PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); + + return (err < 0) ? err : 0; +} + +int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + i2c_data = val & 0xff; + PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data); + err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, + &i2c_data, 1); + + return (err < 0) ? err : 0; +} + +int po1030_power_down(struct sd *sd) +{ + return 0; +} + +void po1030_dump_registers(struct sd *sd) +{ + int address; + u8 value = 0; + + info("Dumping the po1030 sensor core registers"); + for (address = 0; address < 0x7f; address++) { + po1030_read_sensor(sd, address, &value, 1); + info("register 0x%x contains 0x%x", + address, value); + } + + info("po1030 register state dump complete"); + + info("Probing for which registers that are read/write"); + for (address = 0; address < 0xff; address++) { + u8 old_value, ctrl_value; + u8 test_value[2] = {0xff, 0xff}; + + po1030_read_sensor(sd, address, &old_value, 1); + po1030_write_sensor(sd, address, test_value, 1); + po1030_read_sensor(sd, address, &ctrl_value, 1); + + if (ctrl_value == test_value[0]) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original value */ + po1030_write_sensor(sd, address, &old_value, 1); + } +} diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h new file mode 100644 index 00000000000..68f34c97bf4 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -0,0 +1,478 @@ +/* + * Driver for the po1030 sensor. + * This is probably a pixel plus sensor but we haven't identified it yet + * + * Copyright (c) 2008 Erik Andren + * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (c) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * Register defines taken from Pascal Stangs Proxycon Armlib + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_PO1030_H_ +#define M5602_PO1030_H_ + +#include "m5602_sensor.h" + +/*****************************************************************************/ + +#define PO1030_REG_DEVID_H 0x00 +#define PO1030_REG_DEVID_L 0x01 +#define PO1030_REG_FRAMEWIDTH_H 0x04 +#define PO1030_REG_FRAMEWIDTH_L 0x05 +#define PO1030_REG_FRAMEHEIGHT_H 0x06 +#define PO1030_REG_FRAMEHEIGHT_L 0x07 +#define PO1030_REG_WINDOWX_H 0x08 +#define PO1030_REG_WINDOWX_L 0x09 +#define PO1030_REG_WINDOWY_H 0x0a +#define PO1030_REG_WINDOWY_L 0x0b +#define PO1030_REG_WINDOWWIDTH_H 0x0c +#define PO1030_REG_WINDOWWIDTH_L 0x0d +#define PO1030_REG_WINDOWHEIGHT_H 0x0e +#define PO1030_REG_WINDOWHEIGHT_L 0x0f + +#define PO1030_REG_GLOBALIBIAS 0x12 +#define PO1030_REG_PIXELIBIAS 0x13 + +#define PO1030_REG_GLOBALGAIN 0x15 +#define PO1030_REG_RED_GAIN 0x16 +#define PO1030_REG_GREEN_1_GAIN 0x17 +#define PO1030_REG_BLUE_GAIN 0x18 +#define PO1030_REG_GREEN_2_GAIN 0x19 + +#define PO1030_REG_INTEGLINES_H 0x1a +#define PO1030_REG_INTEGLINES_M 0x1b +#define PO1030_REG_INTEGLINES_L 0x1c + +#define PO1030_REG_CONTROL1 0x1d +#define PO1030_REG_CONTROL2 0x1e +#define PO1030_REG_CONTROL3 0x1f +#define PO1030_REG_CONTROL4 0x20 + +#define PO1030_REG_PERIOD50_H 0x23 +#define PO1030_REG_PERIOD50_L 0x24 +#define PO1030_REG_PERIOD60_H 0x25 +#define PO1030_REG_PERIOD60_L 0x26 +#define PO1030_REG_REGCLK167 0x27 +#define PO1030_REG_DELTA50 0x28 +#define PO1030_REG_DELTA60 0x29 + +#define PO1030_REG_ADCOFFSET 0x2c + +/* Gamma Correction Coeffs */ +#define PO1030_REG_GC0 0x2d +#define PO1030_REG_GC1 0x2e +#define PO1030_REG_GC2 0x2f +#define PO1030_REG_GC3 0x30 +#define PO1030_REG_GC4 0x31 +#define PO1030_REG_GC5 0x32 +#define PO1030_REG_GC6 0x33 +#define PO1030_REG_GC7 0x34 + +/* Color Transform Matrix */ +#define PO1030_REG_CT0 0x35 +#define PO1030_REG_CT1 0x36 +#define PO1030_REG_CT2 0x37 +#define PO1030_REG_CT3 0x38 +#define PO1030_REG_CT4 0x39 +#define PO1030_REG_CT5 0x3a +#define PO1030_REG_CT6 0x3b +#define PO1030_REG_CT7 0x3c +#define PO1030_REG_CT8 0x3d + +#define PO1030_REG_AUTOCTRL1 0x3e +#define PO1030_REG_AUTOCTRL2 0x3f + +#define PO1030_REG_YTARGET 0x40 +#define PO1030_REG_GLOBALGAINMIN 0x41 +#define PO1030_REG_GLOBALGAINMAX 0x42 + +/* Output format control */ +#define PO1030_REG_OUTFORMCTRL1 0x5a +#define PO1030_REG_OUTFORMCTRL2 0x5b +#define PO1030_REG_OUTFORMCTRL3 0x5c +#define PO1030_REG_OUTFORMCTRL4 0x5d +#define PO1030_REG_OUTFORMCTRL5 0x5e + +/* Imaging coefficients */ +#define PO1030_REG_YBRIGHT 0x73 +#define PO1030_REG_YCONTRAST 0x74 +#define PO1030_REG_YSATURATION 0x75 + +/*****************************************************************************/ + +#define PO1030_GLOBAL_GAIN_DEFAULT 0x12 +#define PO1030_EXPOSURE_DEFAULT 0xf0ff +#define PO1030_BLUE_GAIN_DEFAULT 0x40 +#define PO1030_RED_GAIN_DEFAULT 0x40 + +/*****************************************************************************/ + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; +extern unsigned int m5602_debug; + +int po1030_probe(struct sd *sd); +int po1030_init(struct sd *sd); +int po1030_power_down(struct sd *sd); + +void po1030_dump_registers(struct sd *sd); + +int po1030_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); +int po1030_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); + +static struct m5602_sensor po1030 = { + .name = "PO1030", + + .i2c_slave_id = 0xdc, + + .probe = po1030_probe, + .init = po1030_init, + .power_down = po1030_power_down, + + .nctrls = 4, + .ctrls = { + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_GLOBAL_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_gain, + .get = po1030_get_gain + }, { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0xffff, + .step = 0x1, + .default_value = PO1030_EXPOSURE_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_exposure, + .get = po1030_get_exposure + }, { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_RED_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_red_balance, + .get = po1030_get_red_balance + }, { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_BLUE_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_blue_balance, + .get = po1030_get_blue_balance + } + }, + .nmodes = 1, + .modes = { + { + M5602_DEFAULT_FRAME_WIDTH, + M5602_DEFAULT_FRAME_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, + .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +static const unsigned char preinit_po1030[][3] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + + {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + + {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00} +}; + +static const unsigned char init_po1030[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + /*sequence 1*/ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + /*end of sequence 1*/ + + /*sequence 2 (same as stop sequence)*/ + {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + /*end of sequence 2*/ + + /*sequence 5*/ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + /*end of sequence 5*/ + + /*sequence 2 stop */ + {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + /*end of sequence 2 stop */ + +/* --------------------------------- + * end of init - begin of start + * --------------------------------- */ + + /*sequence 3*/ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + /*end of sequence 3*/ + /*sequence 4*/ + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {SENSOR, PO1030_REG_AUTOCTRL2, 0x04}, + + /* Set the width to 751 */ + {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, + {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}, + + /* Set the height to 540 */ + {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02}, + {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c}, + + /* Set the x window to 1 */ + {SENSOR, PO1030_REG_WINDOWX_H, 0x00}, + {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, + + /* Set the y window to 1 */ + {SENSOR, PO1030_REG_WINDOWY_H, 0x00}, + {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, + + {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02}, + {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87}, + {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01}, + {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3}, + + {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, + {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, + {SENSOR, PO1030_REG_AUTOCTRL1, 0x08}, + {SENSOR, PO1030_REG_CONTROL2, 0x03}, + {SENSOR, 0x21, 0x90}, + {SENSOR, PO1030_REG_YTARGET, 0x60}, + {SENSOR, 0x59, 0x13}, + {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40}, + {SENSOR, 0x5f, 0x00}, + {SENSOR, 0x60, 0x80}, + {SENSOR, 0x78, 0x14}, + {SENSOR, 0x6f, 0x01}, + {SENSOR, PO1030_REG_CONTROL1, 0x18}, + {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14}, + {SENSOR, 0x63, 0x38}, + {SENSOR, 0x64, 0x38}, + {SENSOR, PO1030_REG_CONTROL1, 0x58}, + {SENSOR, PO1030_REG_RED_GAIN, 0x30}, + {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30}, + {SENSOR, PO1030_REG_BLUE_GAIN, 0x30}, + {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30}, + {SENSOR, PO1030_REG_GC0, 0x10}, + {SENSOR, PO1030_REG_GC1, 0x20}, + {SENSOR, PO1030_REG_GC2, 0x40}, + {SENSOR, PO1030_REG_GC3, 0x60}, + {SENSOR, PO1030_REG_GC4, 0x80}, + {SENSOR, PO1030_REG_GC5, 0xa0}, + {SENSOR, PO1030_REG_GC6, 0xc0}, + {SENSOR, PO1030_REG_GC7, 0xff}, + /*end of sequence 4*/ + /*sequence 5*/ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + /*end of sequence 5*/ + + /*sequence 6*/ + /* Changing 40 in f0 the image becomes green in bayer mode and red in + * rgb mode */ + {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, + /* in changing 40 in f0 the image becomes green in bayer mode and red in + * rgb mode */ + {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, + + /* with a very low lighted environment increase the exposure but + * decrease the FPS (Frame Per Second) */ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in + * low lighted environment (f0 is more than ff ?)*/ + {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) + & 0xff)}, + + /* Controls middle exposure, use only in high lighted environment */ + {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, + + /* Controls clarity (not sure) */ + {SENSOR, PO1030_REG_INTEGLINES_L, 0x00}, + /* Controls gain (the image is more lighted) */ + {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, + + /* Sets the width */ + {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, + {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef} + /*end of sequence 6*/ +}; + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c new file mode 100644 index 00000000000..3a2ae7a2e26 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -0,0 +1,460 @@ +/* + * Driver for the s5k4aa sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_s5k4aa.h" + +int s5k4aa_probe(struct sd *sd) +{ + u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; + int i, err = 0; + + if (force_sensor) { + if (force_sensor == S5K4AA_SENSOR) { + info("Forcing a %s sensor", s5k4aa.name); + goto sensor_found; + } + /* If we want to force another sensor, don't try to probe this + * one */ + return -ENODEV; + } + + info("Probing for a s5k4aa sensor"); + + /* Preinit the sensor */ + for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { + u8 data[2] = {0x00, 0x00}; + + switch (preinit_s5k4aa[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + preinit_s5k4aa[i][1], + preinit_s5k4aa[i][2]); + break; + + case SENSOR: + data[0] = preinit_s5k4aa[i][2]; + err = s5k4aa_write_sensor(sd, + preinit_s5k4aa[i][1], + data, 1); + break; + + case SENSOR_LONG: + data[0] = preinit_s5k4aa[i][2]; + data[1] = preinit_s5k4aa[i][3]; + err = s5k4aa_write_sensor(sd, + preinit_s5k4aa[i][1], + data, 2); + break; + default: + info("Invalid stream command, exiting init"); + return -EINVAL; + } + } + + /* Test some registers, but we don't know their exact meaning yet */ + if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + return -ENODEV; + + if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) + return -ENODEV; + else + info("Detected a s5k4aa sensor"); +sensor_found: + sd->gspca_dev.cam.cam_mode = s5k4aa.modes; + sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; + return 0; +} + +int s5k4aa_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); + if (err < 0) + goto out; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + if (err < 0) + goto out; + + for (i = 0; (i < len) & !err; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(DBG_TRACE, "Reading sensor register " + "0x%x containing 0x%x ", address, *i2c_data); + } +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* No sensor with a data width larger than 16 bits has yet been seen */ + if (len > 2 || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, + sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + /* Special case larger sensor writes */ + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the tailer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + +int s5k4aa_init(struct sd *sd) +{ + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { + u8 data[2] = {0x00, 0x00}; + + switch (init_s5k4aa[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + init_s5k4aa[i][1], + init_s5k4aa[i][2]); + break; + + case SENSOR: + data[0] = init_s5k4aa[i][2]; + err = s5k4aa_write_sensor(sd, + init_s5k4aa[i][1], data, 1); + break; + + case SENSOR_LONG: + data[0] = init_s5k4aa[i][2]; + data[1] = init_s5k4aa[i][3]; + err = s5k4aa_write_sensor(sd, + init_s5k4aa[i][1], data, 2); + break; + default: + info("Invalid stream command, exiting init"); + return -EINVAL; + } + } + + if (dump_sensor) + s5k4aa_dump_registers(sd); + + if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) { + u8 data = 0x02; + info("vertical flip quirk active"); + s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); + data |= S5K4AA_RM_V_FLIP; + data &= ~S5K4AA_RM_H_FLIP; + s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + + /* Decrement COLSTART to preserve color order (BGGR) */ + s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + data--; + s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + + /* Increment ROWSTART to preserve color order (BGGR) */ + s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + data++; + s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + } + + return (err < 0) ? err : 0; +} + +int s5k4aa_power_down(struct sd *sd) +{ + return 0; +} + +int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + + err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); + if (err < 0) + goto out; + + *val = data << 8; + err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); + *val |= data; + PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val); + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + data = (val >> 8) & 0xff; + err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); + if (err < 0) + goto out; + data = val & 0xff; + err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + + err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + *val = (data & S5K4AA_RM_V_FLIP) >> 7; + PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + goto out; + data = ((data & ~S5K4AA_RM_V_FLIP) + | ((val & 0x01) << 7)); + err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + goto out; + + if (val) { + err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + if (err < 0) + goto out; + + data++; + err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + } else { + err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + if (err < 0) + goto out; + + data--; + err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + } +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + + err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + *val = (data & S5K4AA_RM_H_FLIP) >> 6; + PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", + val); + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + goto out; + + data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); + err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + goto out; + + if (val) { + err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + if (err < 0) + goto out; + data++; + err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + if (err < 0) + goto out; + } else { + err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + if (err < 0) + goto out; + data--; + err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + } +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + + err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); + *val = data; + PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + +out: + return (err < 0) ? err : 0; +} + +int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + PDEBUG(DBG_V4L2_CID, "Set gain to %d", val); + err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + goto out; + + data = val & 0xff; + err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); + +out: + return (err < 0) ? err : 0; +} + +void s5k4aa_dump_registers(struct sd *sd) +{ + int address; + u8 page, old_page; + s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); + for (page = 0; page < 16; page++) { + s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); + info("Dumping the s5k4aa register state for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 value = 0; + s5k4aa_read_sensor(sd, address, &value, 1); + info("register 0x%x contains 0x%x", + address, value); + } + } + info("s5k4aa register state dump complete"); + + for (page = 0; page < 16; page++) { + s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); + info("Probing for which registers that are " + "read/write for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 old_value, ctrl_value, test_value = 0xff; + + s5k4aa_read_sensor(sd, address, &old_value, 1); + s5k4aa_write_sensor(sd, address, &test_value, 1); + s5k4aa_read_sensor(sd, address, &ctrl_value, 1); + + if (ctrl_value == test_value) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original value */ + s5k4aa_write_sensor(sd, address, &old_value, 1); + } + } + info("Read/write register probing complete"); + s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); +} diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h new file mode 100644 index 00000000000..1e4213a7321 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -0,0 +1,368 @@ +/* + * Driver for the s5k4aa sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_S5K4AA_H_ +#define M5602_S5K4AA_H_ + +#include + +#include "m5602_sensor.h" + +/*****************************************************************************/ + +#define S5K4AA_PAGE_MAP 0xec + +#define S5K4AA_PAGE_MAP_0 0x00 +#define S5K4AA_PAGE_MAP_1 0x01 +#define S5K4AA_PAGE_MAP_2 0x02 + +/* Sensor register definitions for page 0x02 */ +#define S5K4AA_READ_MODE 0x03 +#define S5K4AA_ROWSTART_HI 0x04 +#define S5K4AA_ROWSTART_LO 0x05 +#define S5K4AA_COLSTART_HI 0x06 +#define S5K4AA_COLSTART_LO 0x07 +#define S5K4AA_WINDOW_HEIGHT_HI 0x08 +#define S5K4AA_WINDOW_HEIGHT_LO 0x09 +#define S5K4AA_WINDOW_WIDTH_HI 0x0a +#define S5K4AA_WINDOW_WIDTH_LO 0x0b +#define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */ +#define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost + if too low, reduces frame rate + if too high */ +#define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */ +#define S5K4AA_EXPOSURE_HI 0x17 +#define S5K4AA_EXPOSURE_LO 0x18 +#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ +#define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */ + +#define S5K4AA_RM_ROW_SKIP_4X 0x08 +#define S5K4AA_RM_ROW_SKIP_2X 0x04 +#define S5K4AA_RM_COL_SKIP_4X 0x02 +#define S5K4AA_RM_COL_SKIP_2X 0x01 +#define S5K4AA_RM_H_FLIP 0x40 +#define S5K4AA_RM_V_FLIP 0x80 + +/*****************************************************************************/ + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; +extern unsigned int m5602_debug; + +int s5k4aa_probe(struct sd *sd); +int s5k4aa_init(struct sd *sd); +int s5k4aa_power_down(struct sd *sd); + +void s5k4aa_dump_registers(struct sd *sd); + +int s5k4aa_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); +int s5k4aa_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); + +static struct m5602_sensor s5k4aa = { + .name = "S5K4AA", + .probe = s5k4aa_probe, + .init = s5k4aa_init, + .power_down = s5k4aa_power_down, + .read_sensor = s5k4aa_read_sensor, + .write_sensor = s5k4aa_write_sensor, + .i2c_slave_id = 0x5a, + .nctrls = 4, + .ctrls = { + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k4aa_set_vflip, + .get = s5k4aa_get_vflip + + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k4aa_set_hflip, + .get = s5k4aa_get_hflip + + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 0xa0, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k4aa_set_gain, + .get = s5k4aa_get_gain + }, { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 13, + .maximum = 0xfff, + .step = 1, + .default_value = 0x100, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k4aa_set_exposure, + .get = s5k4aa_get_exposure + } + }, + + .nmodes = 1, + .modes = { + { + M5602_DEFAULT_FRAME_WIDTH, + M5602_DEFAULT_FRAME_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, + .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +static const unsigned char preinit_s5k4aa[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, + + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, + + {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00} +}; + +static const unsigned char init_s5k4aa[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, + + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, + + {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00}, + {SENSOR, 0x36, 0x01, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}, + {SENSOR, 0x7b, 0xff, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, 0x0c, 0x05, 0x00}, + {SENSOR, 0x02, 0x0e, 0x00}, + {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00}, + {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00}, + {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00}, + {SENSOR, 0x11, 0x00, 0x00}, + {SENSOR, 0x12, 0x00, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, + {SENSOR, 0x37, 0x00, 0x00}, + {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, + {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00}, + {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00}, + {SENSOR, 0x11, 0x04, 0x00}, + {SENSOR, 0x12, 0xc3, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ + + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X + | S5K4AA_RM_COL_SKIP_2X, 0x00}, + /* 0x37 : Fix image stability when light is too bright and improves + * image quality in 640x480, but worsens it in 1280x1024 */ + {SENSOR, 0x37, 0x01, 0x00}, + /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ + {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, + {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, + /* window_height_hi, window_height_lo : 960 = 0x03c0 */ + {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, + /* window_width_hi, window_width_lo : 1280 = 0x0500 */ + {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ + {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, + {SENSOR, 0x11, 0x04, 0x00}, + {SENSOR, 0x12, 0xc3, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, 0x02, 0x0e, 0x00}, + {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, + {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, + {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} +}; + +static const struct dmi_system_id s5k4aa_vflip_dmi_table[] = { + { + .ident = "Fujitsu-Siemens Amilo Xa 2528", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") + } + }, + { + .ident = "Fujitsu-Siemens Amilo Xi 2550", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") + } + }, + { + .ident = "MSI GX700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), + DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") + } + }, + { } +}; + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c new file mode 100644 index 00000000000..a4d6a816312 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -0,0 +1,331 @@ +/* + * Driver for the s5k83a sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_s5k83a.h" + +int s5k83a_probe(struct sd *sd) +{ + u8 prod_id = 0, ver_id = 0; + int i, err = 0; + + if (force_sensor) { + if (force_sensor == S5K83A_SENSOR) { + info("Forcing a %s sensor", s5k83a.name); + goto sensor_found; + } + /* If we want to force another sensor, don't try to probe this + * one */ + return -ENODEV; + } + + info("Probing for a s5k83a sensor"); + + /* Preinit the sensor */ + for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { + u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]}; + if (preinit_s5k83a[i][0] == SENSOR) + err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1], + data, 2); + else + err = m5602_write_bridge(sd, preinit_s5k83a[i][1], + data[0]); + } + + /* We don't know what register (if any) that contain the product id + * Just pick the first addresses that seem to produce the same results + * on multiple machines */ + if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1)) + return -ENODEV; + + if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1)) + return -ENODEV; + + if ((prod_id == 0xff) || (ver_id == 0xff)) + return -ENODEV; + else + info("Detected a s5k83a sensor"); + +sensor_found: + sd->gspca_dev.cam.cam_mode = s5k83a.modes; + sd->gspca_dev.cam.nmodes = s5k83a.nmodes; + return 0; +} + +int s5k83a_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); + if (err < 0) + goto out; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + + if (err < 0) + goto out; + for (i = 0; i < len && !len; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(DBG_TRACE, "Reading sensor register " + "0x%x containing 0x%x ", address, *i2c_data); + } + +out: + return (err < 0) ? err : 0; +} + +int s5k83a_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* No sensor with a data width larger than 16 bits has yet been seen */ + if (len > 2 || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, + sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + /* Special case larger sensor writes */ + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the tailer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + +int s5k83a_init(struct sd *sd) +{ + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { + u8 data[2] = {0x00, 0x00}; + + switch (init_s5k83a[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + init_s5k83a[i][1], + init_s5k83a[i][2]); + break; + + case SENSOR: + data[0] = init_s5k83a[i][2]; + err = s5k83a_write_sensor(sd, + init_s5k83a[i][1], data, 1); + break; + + case SENSOR_LONG: + data[0] = init_s5k83a[i][2]; + data[1] = init_s5k83a[i][3]; + err = s5k83a_write_sensor(sd, + init_s5k83a[i][1], data, 2); + break; + default: + info("Invalid stream command, exiting init"); + return -EINVAL; + } + } + + if (dump_sensor) + s5k83a_dump_registers(sd); + + return (err < 0) ? err : 0; +} + +int s5k83a_power_down(struct sd *sd) +{ + return 0; +} + +void s5k83a_dump_registers(struct sd *sd) +{ + int address; + u8 page, old_page; + s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); + + for (page = 0; page < 16; page++) { + s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + info("Dumping the s5k83a register state for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 val = 0; + s5k83a_read_sensor(sd, address, &val, 1); + info("register 0x%x contains 0x%x", + address, val); + } + } + info("s5k83a register state dump complete"); + + for (page = 0; page < 16; page++) { + s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + info("Probing for which registers that are read/write " + "for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 old_val, ctrl_val, test_val = 0xff; + + s5k83a_read_sensor(sd, address, &old_val, 1); + s5k83a_write_sensor(sd, address, &test_val, 1); + s5k83a_read_sensor(sd, address, &ctrl_val, 1); + + if (ctrl_val == test_val) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original val */ + s5k83a_write_sensor(sd, address, &old_val, 1); + } + } + info("Read/write register probing complete"); + s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); +} + +int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + + err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + data[1] = data[1] << 1; + *val = data[1]; + + return (err < 0) ? err : 0; +} + +int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0x00; + data[1] = 0x20; + err = s5k83a_write_sensor(sd, 0x14, data, 2); + if (err < 0) + return err; + + data[0] = 0x01; + data[1] = 0x00; + err = s5k83a_write_sensor(sd, 0x0d, data, 2); + if (err < 0) + return err; + + /* FIXME: This is not sane, we need to figure out the composition + of these registers */ + data[0] = val >> 3; /* brightness, high 5 bits */ + data[1] = val >> 1; /* brightness, high 7 bits */ + err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + + return (err < 0) ? err : 0; +} + +int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data; + struct sd *sd = (struct sd *) gspca_dev; + + err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1); + + *val = data; + return (err < 0) ? err : 0; +} + +int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[1]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = val; + err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1); + + return (err < 0) ? err : 0; +} + +int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + + err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2); + + data[1] = data[1] & 0x3f; + if (data[1] > S5K83A_MAXIMUM_GAIN) + data[1] = S5K83A_MAXIMUM_GAIN; + + *val = data[1]; + + return (err < 0) ? err : 0; +} + +int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err = 0; + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0; + data[1] = val; + err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2); + + return (err < 0) ? err : 0; +} diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h new file mode 100644 index 00000000000..a57f623d80c --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -0,0 +1,444 @@ +/* + * Driver for the s5k83a sensor + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_S5K83A_H_ +#define M5602_S5K83A_H_ + +#include "m5602_sensor.h" + +#define S5K83A_PAGE_MAP 0xec +#define S5K83A_GAIN 0x18 +#define S5K83A_WHITENESS 0x0a +#define S5K83A_BRIGHTNESS 0x1b + +#define S5K83A_DEFAULT_BRIGHTNESS 0x71 +#define S5K83A_DEFAULT_WHITENESS 0x7e +#define S5K83A_DEFAULT_GAIN 0x00 +#define S5K83A_MAXIMUM_GAIN 0x3c + +/*****************************************************************************/ + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; +extern unsigned int m5602_debug; + + +int s5k83a_probe(struct sd *sd); +int s5k83a_init(struct sd *sd); +int s5k83a_power_down(struct sd *sd); + +void s5k83a_dump_registers(struct sd *sd); + +int s5k83a_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); +int s5k83a_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + +int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); + +static struct m5602_sensor s5k83a = { + .name = "S5K83A", + .probe = s5k83a_probe, + .init = s5k83a_init, + .power_down = s5k83a_power_down, + .read_sensor = s5k83a_read_sensor, + .write_sensor = s5k83a_write_sensor, + .i2c_slave_id = 0x5a, + .nctrls = 3, + .ctrls = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = S5K83A_DEFAULT_BRIGHTNESS, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_brightness, + .get = s5k83a_get_brightness + + }, { + { + .id = V4L2_CID_WHITENESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "whiteness", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = S5K83A_DEFAULT_WHITENESS, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_whiteness, + .get = s5k83a_get_whiteness, + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = S5K83A_MAXIMUM_GAIN, + .step = 0x01, + .default_value = S5K83A_DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_gain, + .get = s5k83a_get_gain + } + }, + .nmodes = 1, + .modes = { + { + M5602_DEFAULT_FRAME_WIDTH, + M5602_DEFAULT_FRAME_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, + .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + + } + } +}; + +static const unsigned char preinit_s5k83a[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, + + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00} +}; + +/* This could probably be considerably shortened. + I don't have the hardware to experiment with it, patches welcome +*/ +static const unsigned char init_s5k83a[][4] = +{ + {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, + {SENSOR, 0xaf, 0x01, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, + {SENSOR, 0x7b, 0xff, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x01, 0x50, 0x00}, + {SENSOR, 0x12, 0x20, 0x00}, + {SENSOR, 0x17, 0x40, 0x00}, + {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, 0x1c, 0x00, 0x00}, + {SENSOR, 0x02, 0x70, 0x00}, + {SENSOR, 0x03, 0x0b, 0x00}, + {SENSOR, 0x04, 0xf0, 0x00}, + {SENSOR, 0x05, 0x0b, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x06, 0x71, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x08, 0x02, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x14, 0x00, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x19, 0x00, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x0f, 0x02, 0x00}, + {SENSOR, 0x10, 0xe5, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR_LONG, 0x14, 0x00, 0x20}, + {SENSOR_LONG, 0x0d, 0x00, 0x7d}, + {SENSOR_LONG, 0x1b, 0x0d, 0x05}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, + + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, + {SENSOR, 0xaf, 0x01, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + /* ff ( init value )is very dark) || 71 and f0 better */ + {SENSOR, 0x7b, 0xff, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x01, 0x50, 0x00}, + {SENSOR, 0x12, 0x20, 0x00}, + {SENSOR, 0x17, 0x40, 0x00}, + {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, 0x1c, 0x00, 0x00}, + {SENSOR, 0x02, 0x70, 0x00}, + /* some values like 0x10 give a blue-purple image */ + {SENSOR, 0x03, 0x0b, 0x00}, + {SENSOR, 0x04, 0xf0, 0x00}, + {SENSOR, 0x05, 0x0b, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + /* under 80 don't work, highter depend on value */ + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, + + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x06, 0x71, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x08, 0x02, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x14, 0x00, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x19, 0x00, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x0f, 0x02, 0x00}, + {SENSOR, 0x10, 0xe5, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR_LONG, 0x14, 0x00, 0x20}, + {SENSOR_LONG, 0x0d, 0x00, 0x7d}, + {SENSOR_LONG, 0x1b, 0x0d, 0x05}, + + /* The following sequence is useless after a clean boot + but is necessary after resume from suspend */ + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, + {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, + {SENSOR, 0xaf, 0x01, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, + {SENSOR, 0x7b, 0xff, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x01, 0x50, 0x00}, + {SENSOR, 0x12, 0x20, 0x00}, + {SENSOR, 0x17, 0x40, 0x00}, + {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, 0x1c, 0x00, 0x00}, + {SENSOR, 0x02, 0x70, 0x00}, + {SENSOR, 0x03, 0x0b, 0x00}, + {SENSOR, 0x04, 0xf0, 0x00}, + {SENSOR, 0x05, 0x0b, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x06, 0x71, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x08, 0x02, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x14, 0x00, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x19, 0x00, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x0f, 0x02, 0x00}, + + {SENSOR, 0x10, 0xe5, 0x00}, + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR_LONG, 0x14, 0x00, 0x20}, + {SENSOR_LONG, 0x0d, 0x00, 0x7d}, + {SENSOR_LONG, 0x1b, 0x0d, 0x05}, + + /* normal colors + (this is value after boot, but after tries can be different) */ + {SENSOR, 0x00, 0x06, 0x00}, + + /* set default brightness */ + {SENSOR_LONG, 0x14, 0x00, 0x20}, + {SENSOR_LONG, 0x0d, 0x01, 0x00}, + {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3, + S5K83A_DEFAULT_BRIGHTNESS >> 1}, + + /* set default whiteness */ + {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00}, + + /* set default gain */ + {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN} +}; + +#endif diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h new file mode 100644 index 00000000000..930fcaab441 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -0,0 +1,76 @@ +/* + * USB Driver for ALi m5602 based webcams + * + * Copyright (C) 2008 Erik Andren + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_SENSOR_H_ +#define M5602_SENSOR_H_ + +#include "m5602_bridge.h" + +#define M5602_DEFAULT_FRAME_WIDTH 640 +#define M5602_DEFAULT_FRAME_HEIGHT 480 + +#define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) + +/* Enumerates all supported sensors */ +enum sensors { + OV9650_SENSOR = 1, + S5K83A_SENSOR = 2, + S5K4AA_SENSOR = 3, + MT9M111_SENSOR = 4, + PO1030_SENSOR = 5 +}; + +/* Enumerates all possible instruction types */ +enum instruction { + BRIDGE, + SENSOR, + SENSOR_LONG +}; + +struct m5602_sensor { + /* Defines the name of a sensor */ + char name[32]; + + /* What i2c address the sensor is connected to */ + u8 i2c_slave_id; + + /* Probes if the sensor is connected */ + int (*probe)(struct sd *sd); + + /* Performs a initialization sequence */ + int (*init)(struct sd *sd); + + /* Performs a power down sequence */ + int (*power_down)(struct sd *sd); + + /* Reads a sensor register */ + int (*read_sensor)(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + + /* Writes to a sensor register */ + int (*write_sensor)(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + + int nctrls; + struct ctrl ctrls[M5602_MAX_CTRLS]; + + char nmodes; + struct v4l2_pix_format modes[]; +}; + +#endif -- GitLab From e293e599524f74532b0add53ddf80f10ff854598 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Fri, 3 Oct 2008 08:46:50 -0300 Subject: [PATCH 4192/5416] V4L/DVB (9093): gspca: Cleanup code and small changes. - convert some #define to enum. - remove some comments. - return ENOMEM on memory allocation failure. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 12 ++++-------- drivers/media/video/gspca/gspca.h | 12 +++++++----- drivers/media/video/gspca/m5602/m5602_core.c | 1 - 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 02824fc101d..9db3d899aa6 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -237,7 +237,7 @@ static void bulk_irq(struct urb *urb * On LAST_PACKET, a new frame is returned. */ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, - int packet_type, + enum gspca_packet_type packet_type, struct gspca_frame *frame, const __u8 *data, int len) @@ -317,7 +317,6 @@ static void *rvmalloc(unsigned long size) void *mem; unsigned long adr; -/* size = PAGE_ALIGN(size); (already done) */ mem = vmalloc_32(size); if (mem != NULL) { adr = (unsigned long) mem; @@ -937,7 +936,6 @@ static int vidioc_querycap(struct file *file, void *priv, memset(cap, 0, sizeof *cap); strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); -/* strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */ if (gspca_dev->dev->product != NULL) { strncpy(cap->card, gspca_dev->dev->product, sizeof cap->card); @@ -1571,7 +1569,6 @@ static int vidioc_qbuf(struct file *file, void *priv, } frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; -/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; @@ -1836,22 +1833,21 @@ int gspca_dev_probe(struct usb_interface *intf, if (dev_size < sizeof *gspca_dev) dev_size = sizeof *gspca_dev; gspca_dev = kzalloc(dev_size, GFP_KERNEL); - if (gspca_dev == NULL) { + if (!gspca_dev) { err("couldn't kzalloc gspca struct"); - return -EIO; + return -ENOMEM; } kref_init(&gspca_dev->kref); gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); if (!gspca_dev->usb_buf) { err("out of memory"); - ret = -EIO; + ret = -ENOMEM; goto out; } gspca_dev->dev = dev; gspca_dev->iface = interface->bInterfaceNumber; gspca_dev->nbalt = intf->num_altsetting; gspca_dev->sd_desc = sd_desc; -/* gspca_dev->users = 0; (done by kzalloc) */ gspca_dev->nbufread = 2; /* configure the subdriver and initialize the USB device */ diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index f9006542c58..4779dd0b06d 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -106,10 +106,12 @@ struct sd_desc { }; /* packet types when moving from iso buf to frame buf */ -#define DISCARD_PACKET 0 -#define FIRST_PACKET 1 -#define INTER_PACKET 2 -#define LAST_PACKET 3 +enum gspca_packet_type { + DISCARD_PACKET, + FIRST_PACKET, + INTER_PACKET, + LAST_PACKET +}; struct gspca_frame { __u8 *data; /* frame buffer */ @@ -175,7 +177,7 @@ int gspca_dev_probe(struct usb_interface *intf, struct module *module); void gspca_disconnect(struct usb_interface *intf); struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, - int packet_type, + enum gspca_packet_type packet_type, struct gspca_frame *frame, const __u8 *data, int len); diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 559495e2d11..ac105ef4aa6 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -146,7 +146,6 @@ int m5602_probe_sensor(struct sd *sd) return 0; } - /* More sensor probe function goes here */ info("Failed to find a sensor"); sd->sensor = NULL; -- GitLab From 1b3345996c056a979cfabf96c0815b4843d9bbfc Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Fri, 3 Oct 2008 09:28:45 -0300 Subject: [PATCH 4193/5416] V4L/DVB (9094): gspca: Frame counter in ALi m5602. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index ac105ef4aa6..58ebffdcaae 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -146,6 +146,7 @@ int m5602_probe_sensor(struct sd *sd) return 0; } + /* More sensor probe function goes here */ info("Failed to find a sensor"); sd->sensor = NULL; @@ -202,12 +203,13 @@ void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* Complete the last frame (if any) */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); + sd->frame_count++; /* Create a new frame */ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); - PDEBUG(DBG_V4L2, "Starting new frame. First urb contained %d", - len); + PDEBUG(DBG_V4L2, "Starting new frame %d", + sd->frame_count); } else { int cur_frame_len = frame->data_end - frame->data; @@ -217,8 +219,8 @@ void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, len -= 4; if (cur_frame_len + len <= frame->v4l2_buf.length) { - PDEBUG(DBG_DATA, "Continuing frame copying %d bytes", - len); + PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes", + sd->frame_count, len); gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); -- GitLab From d2d7e9ae3138307284c815e1c37ea0b7b8834692 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Fri, 3 Oct 2008 15:29:02 -0300 Subject: [PATCH 4194/5416] V4L/DVB (9095): gspca: Moves some sensor initialization to each sensor in m5602. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/m5602/m5602_bridge.h | 2 ++ drivers/media/video/gspca/m5602/m5602_core.c | 28 +++++-------------- .../media/video/gspca/m5602/m5602_mt9m111.c | 2 ++ .../media/video/gspca/m5602/m5602_ov9650.c | 2 ++ .../media/video/gspca/m5602/m5602_po1030.c | 2 ++ .../media/video/gspca/m5602/m5602_s5k4aa.c | 3 ++ .../media/video/gspca/m5602/m5602_s5k83a.c | 2 ++ 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h index fcbc37bfea5..18ca19a9436 100644 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -152,6 +152,8 @@ struct sd { /* A pointer to the currently connected sensor */ struct m5602_sensor *sensor; + struct sd_desc *desc; + /* The current frame's id, used to detect frame boundaries */ u8 frame_id; diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 58ebffdcaae..47507350111 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -108,44 +108,28 @@ int m5602_probe_sensor(struct sd *sd) { /* Try the po1030 */ sd->sensor = &po1030; - if (!sd->sensor->probe(sd)) { - sd_desc.ctrls = po1030.ctrls; - sd_desc.nctrls = po1030.nctrls; + if (!sd->sensor->probe(sd)) return 0; - } /* Try the mt9m111 sensor */ sd->sensor = &mt9m111; - if (!sd->sensor->probe(sd)) { - sd_desc.ctrls = mt9m111.ctrls; - sd_desc.nctrls = mt9m111.nctrls; + if (!sd->sensor->probe(sd)) return 0; - } /* Try the s5k4aa */ sd->sensor = &s5k4aa; - if (!sd->sensor->probe(sd)) { - sd_desc.ctrls = s5k4aa.ctrls; - sd_desc.nctrls = s5k4aa.nctrls; + if (!sd->sensor->probe(sd)) return 0; - } /* Try the ov9650 */ sd->sensor = &ov9650; - if (!sd->sensor->probe(sd)) { - sd_desc.ctrls = ov9650.ctrls; - sd_desc.nctrls = ov9650.nctrls; + if (!sd->sensor->probe(sd)) return 0; - } /* Try the s5k83a */ sd->sensor = &s5k83a; - if (!sd->sensor->probe(sd)) { - sd_desc.ctrls = s5k83a.ctrls; - sd_desc.nctrls = s5k83a.nctrls; + if (!sd->sensor->probe(sd)) return 0; - } - /* More sensor probe function goes here */ info("Failed to find a sensor"); @@ -246,8 +230,10 @@ int m5602_configure(struct gspca_dev *gspca_dev, int err; PDEBUG(DBG_GSPCA, "m5602_configure start"); + cam = &gspca_dev->cam; cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; + sd->desc = &sd_desc; if (dump_bridge) m5602_dump_bridge(sd); diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 17f04dd5e1d..ea2250217b0 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -62,6 +62,8 @@ int mt9m111_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = mt9m111.modes; sd->gspca_dev.cam.nmodes = mt9m111.nmodes; + sd->desc->ctrls = mt9m111.ctrls; + sd->desc->nctrls = mt9m111.nctrls; return 0; } diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 74c3ffec0ca..31c5896250e 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -132,6 +132,8 @@ int ov9650_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = ov9650.modes; sd->gspca_dev.cam.nmodes = ov9650.nmodes; + sd->desc->ctrls = ov9650.ctrls; + sd->desc->nctrls = ov9650.nctrls; return 0; } diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c index 14a8f929dd1..08c015bde11 100644 --- a/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -59,6 +59,8 @@ int po1030_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = po1030.modes; sd->gspca_dev.cam.nmodes = po1030.nmodes; + sd->desc->ctrls = po1030.ctrls; + sd->desc->nctrls = po1030.nctrls; return 0; } diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 3a2ae7a2e26..68202565325 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -78,6 +78,9 @@ int s5k4aa_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = s5k4aa.modes; sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; + sd->desc->ctrls = s5k4aa.ctrls; + sd->desc->nctrls = s5k4aa.nctrls; + return 0; } diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c index a4d6a816312..c1ff967b1c3 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -63,6 +63,8 @@ int s5k83a_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = s5k83a.modes; sd->gspca_dev.cam.nmodes = s5k83a.nmodes; + sd->desc->ctrls = s5k83a.ctrls; + sd->desc->nctrls = s5k83a.nctrls; return 0; } -- GitLab From eeb00c604ad203a51a0b92e124bcc4f98ba7e2c0 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Fri, 3 Oct 2008 15:47:03 -0300 Subject: [PATCH 4195/5416] V4L/DVB (9096): gspca: Subdriver selection at config time. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 203 +++++++++++++++++++++++- drivers/media/video/gspca/Makefile | 73 +++++---- drivers/media/video/gspca/m5602/Kconfig | 4 +- 3 files changed, 240 insertions(+), 40 deletions(-) diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index fd31099e36a..aa7f3eb7ee7 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -1,16 +1,203 @@ -config USB_GSPCA - tristate "USB GSPCA driver" +menuconfig USB_GSPCA + tristate "GSPCA based webcams" depends on VIDEO_V4L2 + default m ---help--- - Say Y here if you want support for various USB webcams. + Say Y here if you want to enable selecting webcams based + on the GSPCA framework. - See for more info. + See for more info. - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. - To compile this driver as modules, choose M here: the - modules will be called gspca_xxxx. + To compile this driver as modules, choose M here: the + modules will be called gspca_main. + + +if USB_GSPCA && VIDEO_V4L2 source "drivers/media/video/gspca/m5602/Kconfig" +config USB_GSPCA_CONEX + tristate "Conexant Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the Conexant chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_conex. + +config USB_GSPCA_ETOMS + tristate "Etoms USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the Etoms chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_etoms. + +config USB_GSPCA_MARS + tristate "Mars USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the Mars chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_mars. + +config USB_GSPCA_OV519 + tristate "OV519 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the OV519 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_ov519. + +config USB_GSPCA_PAC207 + tristate "Pixart PAC207 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the PAC207 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_pac207. + +config USB_GSPCA_PAC7311 + tristate "Pixart PAC7311 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the PAC7311 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_pac7311. + +config USB_GSPCA_SONIXB + tristate "SN9C102 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SONIXB chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sonixb. + +config USB_GSPCA_SONIXJ + tristate "SONIX JPEG USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SONIXJ chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sonixj + +config USB_GSPCA_SPCA500 + tristate "SPCA500 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA500 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca500. + +config USB_GSPCA_SPCA501 + tristate "SPCA501 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA501 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca501. + +config USB_GSPCA_SPCA505 + tristate "SPCA505 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA505 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca505. + +config USB_GSPCA_SPCA506 + tristate "SPCA506 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA506 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca506. + +config USB_GSPCA_SPCA508 + tristate "SPCA508 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA508 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca508. + +config USB_GSPCA_SPCA561 + tristate "SPCA561 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SPCA561 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca561. + +config USB_GSPCA_STK014 + tristate "Syntek DV4000 (STK014) USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the STK014 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_stk014. + +config USB_GSPCA_SPCA5XX + tristate "SPCA5xx USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the Sunplus + SPCA504(abc) SPCA533 SPCA536 chips. + + To compile this driver as a module, choose M here: the + module will be called gspca_spca5xx. + +config USB_GSPCA_T613 + tristate "T613 (JPEG Compliance) USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the T613 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_t613. + +config USB_GSPCA_TV8531 + tristate "TV8532 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the TV8531 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_tv8532. + +config USB_GSPCA_VC032X + tristate "VC032X USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the VC032X chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_vc032x. + +config USB_GSPCA_ZC3XX + tristate "VC3xx USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the ZC3XX chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_zc3xx. + +endif diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 488ed97c58a..b510b06fd87 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -1,33 +1,46 @@ -obj-$(CONFIG_USB_GSPCA) += gspca_main.o \ - gspca_conex.o gspca_etoms.o gspca_finepix.o gspca_mars.o \ - gspca_ov519.o gspca_pac207.o gspca_pac7311.o \ - gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \ - gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \ - gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \ - gspca_vc032x.o gspca_zc3xx.o +obj-$(CONFIG_USB_GSPCA) += gspca_main.o +obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o +obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o +obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o +obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o +obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o +obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o +obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o +obj-$(CONFIG_USB_GSPCA_SONXIJ) += gspca_sonixj.o +obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o +obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o +obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o +obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o +obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o +obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o +obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o +obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o +obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o +obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o +obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o +obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o -gspca_main-objs := gspca.o -gspca_conex-objs := conex.o -gspca_etoms-objs := etoms.o -gspca_finepix-objs := finepix.o -gspca_mars-objs := mars.o -gspca_ov519-objs := ov519.o -gspca_pac207-objs := pac207.o -gspca_pac7311-objs := pac7311.o -gspca_sonixb-objs := sonixb.o -gspca_sonixj-objs := sonixj.o -gspca_spca500-objs := spca500.o -gspca_spca501-objs := spca501.o -gspca_spca505-objs := spca505.o -gspca_spca506-objs := spca506.o -gspca_spca508-objs := spca508.o -gspca_spca561-objs := spca561.o -gspca_stk014-objs := stk014.o -gspca_sunplus-objs := sunplus.o -gspca_t613-objs := t613.o -gspca_tv8532-objs := tv8532.o -gspca_vc032x-objs := vc032x.o -gspca_zc3xx-objs := zc3xx.o +gspca_main-objs := gspca.o +gspca_conex-objs := conex.o +gspca_etoms-objs := etoms.o +gspca_mars-objs := mars.o +gspca_ov519-objs := ov519.o +gspca_pac207-objs := pac207.o +gspca_pac7311-objs := pac7311.o +gspca_sonixb-objs := sonixb.o +gspca_sonixj-objs := sonixj.o +gspca_spca500-objs := spca500.o +gspca_spca501-objs := spca501.o +gspca_spca505-objs := spca505.o +gspca_spca506-objs := spca506.o +gspca_spca508-objs := spca508.o +gspca_spca561-objs := spca561.o +gspca_stk014-objs := stk014.o +gspca_sunplus-objs := sunplus.o +gspca_t613-objs := t613.o +gspca_tv8532-objs := tv8532.o +gspca_vc032x-objs := vc032x.o +gspca_zc3xx-objs := zc3xx.o -obj-$(CONFIG_USB_M5602) += m5602/ +obj-$(CONFIG_USB_M5602) += m5602/ diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig index 7de33e22117..5a69016ed75 100644 --- a/drivers/media/video/gspca/m5602/Kconfig +++ b/drivers/media/video/gspca/m5602/Kconfig @@ -1,5 +1,5 @@ config USB_M5602 - tristate "USB ALi m5602 Webcam support" + tristate "ALi USB m5602 Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help Say Y here if you want support for cameras based on the @@ -8,4 +8,4 @@ config USB_M5602 See for more info. To compile this driver as a module, choose M here: the - module will be called gspca-m5602. + module will be called gspca_m5602. -- GitLab From 803f9ccf50178af6cde7aec86db2d78db3d069e7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 4 Oct 2008 14:17:02 -0300 Subject: [PATCH 4196/5416] V4L/DVB (9097): gspca: Adjust control values and restore compilation of sonixj. - no compilation since last changeset - brightness is a signed value - better values of the color matrix [mchehab@redhat.com: fix a merge conflict] Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Makefile | 2 +- drivers/media/video/gspca/sonixj.c | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b510b06fd87..b87322f4a48 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o -obj-$(CONFIG_USB_GSPCA_SONXIJ) += gspca_sonixj.o +obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 03fe77d38cc..93b17340b7b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -267,10 +267,12 @@ static const __u8 gamma_def[] = { 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; +/* color matrix and offsets */ static const __u8 reg84[] = { - 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f, - 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f, - 0xf7, 0x0f, 0x00, 0x00, 0x00 + 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ + 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */ + 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ + 0x00, 0x00, 0x00 /* YUV offsets */ }; static const __u8 hv7131r_sensor_init[][8] = { {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, @@ -1102,20 +1104,17 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, static void setbrightcont(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - unsigned val; + int val; __u8 reg84_full[0x15]; - memset(reg84_full, 0, sizeof reg84_full); - val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */ - reg84_full[2] = val; - reg84_full[0] = (val + 1) / 2; - reg84_full[4] = (val + 1) / 5; - if (val > BRIGHTNESS_DEF) - val = (sd->brightness - BRIGHTNESS_DEF) * 0x20 + memcpy(reg84_full, reg84, sizeof reg84_full); + val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */ + reg84_full[0] = (val + 1) / 2; /* red */ + reg84_full[2] = val; /* green */ + reg84_full[4] = (val + 1) / 5; /* blue */ + val = (sd->brightness - BRIGHTNESS_DEF) * 0x10 / BRIGHTNESS_MAX; - else - val = 0; - reg84_full[0x12] = val; /* 00..1f */ + reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */ reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); } -- GitLab From 695ebd125ade17101861c9eb99f74e6cc9a516ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 4 Oct 2008 14:18:37 -0300 Subject: [PATCH 4197/5416] V4L/DVB (9098): Whitespace cleanups Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 29089d9526b..020a03c466c 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1066,7 +1066,7 @@ static struct ctrl sd_ctrls_12a[] = { { .id = V4L2_CID_DO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "White Balance", + .name = "White Balance", .minimum = WHITE_MIN, .maximum = WHITE_MAX, .step = 1, -- GitLab From 2aa72f3b63e4b524e9e4b1438f6c0d50a214d836 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 1 Oct 2008 09:40:59 -0300 Subject: [PATCH 4198/5416] V4L/DVB (9101): radio-mr800: Add driver for AverMedia MR 800 USB FM radio devices This patch creates a new usb-radio driver, radio-mr800.c, that supports the AverMedia MR 800 USB FM radio devices. This device plugs into both the USB and an analog audio input, so this thing only deals with initialization and frequency setting, the audio data has to be handled by a sound driver. Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/Kconfig | 12 + drivers/media/radio/Makefile | 1 + drivers/media/radio/radio-mr800.c | 628 ++++++++++++++++++++++++++++++ 3 files changed, 641 insertions(+) create mode 100644 drivers/media/radio/radio-mr800.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 1b41b3f77cf..e51d707e58d 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -361,4 +361,16 @@ config USB_SI470X To compile this driver as a module, choose M here: the module will be called radio-silabs. +config USB_MR800 + tristate "AverMedia MR 800 USB FM radio support" + depends on USB && VIDEO_V4L2 + ---help--- + Say Y here if you want to connect this type of radio to your + computer's USB port. Note that the audio is not digital, and + you must connect the line out connector to a sound card or a + set of speakers. + + To compile this driver as a module, choose M here: the + module will be called radio-mr800. + endif # RADIO_ADAPTERS diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 7ca71ab96b4..240ec63cdaf 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_SI470X) += radio-si470x.o +obj-$(CONFIG_USB_MR800) += radio-mr800.o EXTRA_CFLAGS += -Isound diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c new file mode 100644 index 00000000000..a33717c4800 --- /dev/null +++ b/drivers/media/radio/radio-mr800.c @@ -0,0 +1,628 @@ +/* + * A driver for the AverMedia MR 800 USB FM radio. This device plugs + * into both the USB and an analog audio input, so this thing + * only deals with initialization and frequency setting, the + * audio data has to be handled by a sound driver. + * + * Copyright (c) 2008 Alexey Klimov + * + * 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 + */ + +/* + * Big thanks to authors of dsbr100.c and radio-si470x.c + * + * When work was looked pretty good, i discover this: + * http://av-usbradio.sourceforge.net/index.php + * http://sourceforge.net/projects/av-usbradio/ + * Latest release of theirs project was in 2005. + * Probably, this driver could be improved trough using their + * achievements (specifications given). + * So, we have smth to begin with. + * + * History: + * Version 0.01: First working version. + * It's required to blacklist AverMedia USB Radio + * in usbhid/hid-quirks.c + * + * Many things to do: + * - Correct power managment of device (suspend & resume) + * - Make x86 independance (little-endian and big-endian stuff) + * - Add code for scanning and smooth tuning + * - Checked and add stereo&mono stuff + * - Add code for sensitivity value + * - Correct mistakes + * - In Japan another FREQ_MIN and FREQ_MAX + */ + +/* kernel includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for KERNEL_VERSION MACRO */ + +/* driver and module definitions */ +#define DRIVER_AUTHOR "Alexey Klimov " +#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" +#define DRIVER_VERSION "0.01" +#define RADIO_VERSION KERNEL_VERSION(0, 0, 1) + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +#define USB_AMRADIO_VENDOR 0x07ca +#define USB_AMRADIO_PRODUCT 0xb800 + +/* Probably USB_TIMEOUT should be modified in module parameter */ +#define BUFFER_LENGTH 8 +#define USB_TIMEOUT 500 + +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76 and 91. */ +#define FREQ_MIN 87.5 +#define FREQ_MAX 108.0 +#define FREQ_MUL 16000 + +/* module parameter */ +static int radio_nr = -1; +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, "Radio Nr"); + +static struct v4l2_queryctrl radio_qctrl[] = { + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, +/* HINT: the disabled controls are only here to satify kradio and such apps */ + { .id = V4L2_CID_AUDIO_VOLUME, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_BALANCE, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_BASS, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_TREBLE, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_LOUDNESS, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, +}; + +static int usb_amradio_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void usb_amradio_disconnect(struct usb_interface *intf); +static int usb_amradio_open(struct inode *inode, struct file *file); +static int usb_amradio_close(struct inode *inode, struct file *file); +static int usb_amradio_suspend(struct usb_interface *intf, + pm_message_t message); +static int usb_amradio_resume(struct usb_interface *intf); + +/* Data for one (physical) device */ +struct amradio_device { + /* reference to USB and video device */ + struct usb_device *usbdev; + struct video_device *videodev; + + unsigned char *buffer; + struct mutex lock; /* buffer locking */ + int curfreq; + int stereo; + int users; + int removed; + int muted; +}; + +/* USB Device ID List */ +static struct usb_device_id usb_amradio_device_table[] = { + {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT, + USB_CLASS_HID, 0, 0) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, usb_amradio_device_table); + +/* USB subsystem interface */ +static struct usb_driver usb_amradio_driver = { + .name = "radio-mr800", + .probe = usb_amradio_probe, + .disconnect = usb_amradio_disconnect, + .suspend = usb_amradio_suspend, + .resume = usb_amradio_resume, + .reset_resume = usb_amradio_resume, + .id_table = usb_amradio_device_table, + .supports_autosuspend = 1, +}; + +/* switch on radio. Send 8 bytes to device. */ +static int amradio_start(struct amradio_device *radio) +{ + int retval; + int size; + + mutex_lock(&radio->lock); + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x55; + radio->buffer[2] = 0xaa; + radio->buffer[3] = 0x00; + radio->buffer[4] = 0xab; + radio->buffer[5] = 0x00; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x00; + + retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), + (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval) { + mutex_unlock(&radio->lock); + return retval; + } + + mutex_unlock(&radio->lock); + + radio->muted = 0; + + return retval; +} + +/* switch off radio */ +static int amradio_stop(struct amradio_device *radio) +{ + int retval; + int size; + + mutex_lock(&radio->lock); + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x55; + radio->buffer[2] = 0xaa; + radio->buffer[3] = 0x00; + radio->buffer[4] = 0xab; + radio->buffer[5] = 0x01; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x00; + + retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), + (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval) { + mutex_unlock(&radio->lock); + return retval; + } + + mutex_unlock(&radio->lock); + + radio->muted = 1; + + return retval; +} + +/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ +static int amradio_setfreq(struct amradio_device *radio, int freq) +{ + int retval; + int size; + unsigned short freq_send = 0x13 + (freq >> 3) / 25; + + mutex_lock(&radio->lock); + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x55; + radio->buffer[2] = 0xaa; + radio->buffer[3] = 0x03; + radio->buffer[4] = 0xa4; + radio->buffer[5] = 0x00; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x08; + + retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), + (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval) { + mutex_unlock(&radio->lock); + return retval; + } + + /* frequency is calculated from freq_send and placed in first 2 bytes */ + radio->buffer[0] = (freq_send >> 8) & 0xff; + radio->buffer[1] = freq_send & 0xff; + radio->buffer[2] = 0x01; + radio->buffer[3] = 0x00; + radio->buffer[4] = 0x00; + /* 5 and 6 bytes of buffer already = 0x00 */ + radio->buffer[7] = 0x00; + + retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), + (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval) { + mutex_unlock(&radio->lock); + return retval; + } + + mutex_unlock(&radio->lock); + + radio->stereo = 0; + + return retval; +} + +/* USB subsystem interface begins here */ + +/* handle unplugging of the device, release data structures +if nothing keeps us from doing it. If something is still +keeping us busy, the release callback of v4l will take care +of releasing it. */ +static void usb_amradio_disconnect(struct usb_interface *intf) +{ + struct amradio_device *radio = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + + if (radio) { + video_unregister_device(radio->videodev); + radio->videodev = NULL; + if (radio->users) { + kfree(radio->buffer); + kfree(radio); + } else { + radio->removed = 1; + } + } +} + +/* vidioc_querycap - query device capabilities */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); + strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); + sprintf(v->bus_info, "USB"); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER; + return 0; +} + +/* vidioc_g_tuner - get tuner attributes */ +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + if (v->index > 0) + return -EINVAL; + +/* TODO: Add function which look is signal stereo or not + * amradio_getstat(radio); + */ + radio->stereo = -1; + strcpy(v->name, "FM"); + v->type = V4L2_TUNER_RADIO; + v->rangelow = FREQ_MIN * FREQ_MUL; + v->rangehigh = FREQ_MAX * FREQ_MUL; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (radio->stereo) + v->audmode = V4L2_TUNER_MODE_STEREO; + else + v->audmode = V4L2_TUNER_MODE_MONO; + v->signal = 0xffff; /* Can't get the signal strength, sad.. */ + v->afc = 0; /* Don't know what is this */ + return 0; +} + +/* vidioc_s_tuner - set tuner attributes */ +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; + return 0; +} + +/* vidioc_s_frequency - set tuner radio frequency */ +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + radio->curfreq = f->frequency; + if (amradio_setfreq(radio, radio->curfreq) < 0) + warn("Set frequency failed"); + return 0; +} + +/* vidioc_g_frequency - get tuner radio frequency */ +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + f->type = V4L2_TUNER_RADIO; + f->frequency = radio->curfreq; + return 0; +} + +/* vidioc_queryctrl - enumerate control items */ +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); + return 0; + } + } + return -EINVAL; +} + +/* vidioc_g_ctrl - get the value of a control */ +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = radio->muted; + return 0; + } + return -EINVAL; +} + +/* vidioc_s_ctrl - set the value of a control */ +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + if (amradio_stop(radio) < 0) { + warn("amradio_stop() failed"); + return -1; + } + } else { + if (amradio_start(radio) < 0) { + warn("amradio_start() failed"); + return -1; + } + } + return 0; + } + return -EINVAL; +} + +/* vidioc_g_audio - get audio attributes */ +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index > 1) + return -EINVAL; + + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +/* vidioc_s_audio - set audio attributes */ +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; +} + +/* vidioc_g_input - get input */ +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +/* vidioc_s_input - set input */ +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +/* open device - amradio_start() and amradio_setfreq() */ +static int usb_amradio_open(struct inode *inode, struct file *file) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + radio->users = 1; + radio->muted = 1; + + if (amradio_start(radio) < 0) { + warn("Radio did not start up properly"); + radio->users = 0; + return -EIO; + } + if (amradio_setfreq(radio, radio->curfreq) < 0) + warn("Set frequency failed"); + return 0; +} + +/*close device - free driver structures */ +static int usb_amradio_close(struct inode *inode, struct file *file) +{ + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + if (!radio) + return -ENODEV; + radio->users = 0; + if (radio->removed) { + kfree(radio->buffer); + kfree(radio); + } + return 0; +} + +/* Suspend device - stop device. Need to be checked and fixed */ +static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct amradio_device *radio = usb_get_intfdata(intf); + + if (amradio_stop(radio) < 0) + warn("amradio_stop() failed"); + + info("radio-mr800: Going into suspend.."); + + return 0; +} + +/* Resume device - start device. Need to be checked and fixed */ +static int usb_amradio_resume(struct usb_interface *intf) +{ + struct amradio_device *radio = usb_get_intfdata(intf); + + if (amradio_start(radio) < 0) + warn("amradio_start() failed"); + + info("radio-mr800: Coming out of suspend.."); + + return 0; +} + +/* File system interface */ +static const struct file_operations usb_amradio_fops = { + .owner = THIS_MODULE, + .open = usb_amradio_open, + .release = usb_amradio_close, + .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl = v4l_compat_ioctl32, +#endif + .llseek = no_llseek, +}; + +static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, +}; + +/* V4L2 interface */ +static struct video_device amradio_videodev_template = { + .name = "AverMedia MR 800 USB FM Radio", + .fops = &usb_amradio_fops, + .ioctl_ops = &usb_amradio_ioctl_ops, + .release = video_device_release, +}; + +/* check if the device is present and register with v4l and +usb if it is */ +static int usb_amradio_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct amradio_device *radio; + + radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); + + if (!(radio)) + return -ENOMEM; + + radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); + + if (!(radio->buffer)) { + kfree(radio); + return -ENOMEM; + } + + radio->videodev = video_device_alloc(); + + if (!(radio->videodev)) { + kfree(radio->buffer); + kfree(radio); + return -ENOMEM; + } + + memcpy(radio->videodev, &amradio_videodev_template, + sizeof(amradio_videodev_template)); + + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->curfreq = 95.16 * FREQ_MUL; + + mutex_init(&radio->lock); + + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio->buffer); + kfree(radio); + return -EIO; + } + + usb_set_intfdata(intf, radio); + return 0; +} + +static int __init amradio_init(void) +{ + int retval = usb_register(&usb_amradio_driver); + + info(DRIVER_VERSION " " DRIVER_DESC); + if (retval) + err("usb_register failed. Error number %d", retval); + return retval; +} + +static void __exit amradio_exit(void) +{ + usb_deregister(&usb_amradio_driver); +} + +module_init(amradio_init); +module_exit(amradio_exit); + -- GitLab From 07c6bb9e6e5c9b8d0f697493cdd3978fc193ca90 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 30 Sep 2008 13:57:42 -0300 Subject: [PATCH 4199/5416] V4L/DVB (9105): correct Makefile symbol for stv0288 frontend Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 491eb5c5585..aba79f4a63a 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -53,5 +53,5 @@ obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o obj-$(CONFIG_DVB_SI21XX) += si21xx.o -obj-$(CONFIG_DVB_STV0299) += stv0288.o +obj-$(CONFIG_DVB_STV0288) += stv0288.o obj-$(CONFIG_DVB_STB6000) += stb6000.o -- GitLab From 986bd1e58b18c09b753f797df19251804bfe3e84 Mon Sep 17 00:00:00 2001 From: Tomi Orava Date: Fri, 19 Sep 2008 00:48:31 -0300 Subject: [PATCH 4200/5416] V4L/DVB (9107): Alternative version of Terratec Cinergy T2 driver Alternative version of the Terratec Cinergy T2 driver that uses the dvb framework. Signed-off-by: Tomi Orava Signed-off-by: Thierry MERLE [mchehab@redhat.com: fix dvb Makefile] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 1 - drivers/media/dvb/Makefile | 2 +- drivers/media/dvb/cinergyT2/Kconfig | 85 -- drivers/media/dvb/cinergyT2/Makefile | 3 - drivers/media/dvb/cinergyT2/cinergyT2.c | 1105 -------------------- drivers/media/dvb/dvb-usb/Kconfig | 8 + drivers/media/dvb/dvb-usb/Makefile | 4 + drivers/media/dvb/dvb-usb/cinergyT2-core.c | 230 ++++ drivers/media/dvb/dvb-usb/cinergyT2-fe.c | 351 +++++++ drivers/media/dvb/dvb-usb/cinergyT2.h | 95 ++ 10 files changed, 689 insertions(+), 1195 deletions(-) delete mode 100644 drivers/media/dvb/cinergyT2/Kconfig delete mode 100644 drivers/media/dvb/cinergyT2/Makefile delete mode 100644 drivers/media/dvb/cinergyT2/cinergyT2.c create mode 100644 drivers/media/dvb/dvb-usb/cinergyT2-core.c create mode 100644 drivers/media/dvb/dvb-usb/cinergyT2-fe.c create mode 100644 drivers/media/dvb/dvb-usb/cinergyT2.h diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 14488f64479..0bcd852576d 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -20,7 +20,6 @@ comment "Supported USB Adapters" source "drivers/media/dvb/dvb-usb/Kconfig" source "drivers/media/dvb/ttusb-budget/Kconfig" source "drivers/media/dvb/ttusb-dec/Kconfig" -source "drivers/media/dvb/cinergyT2/Kconfig" source "drivers/media/dvb/siano/Kconfig" comment "Supported FlexCopII (B2C2) Adapters" diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index ea953a03e24..f91e9eb15e5 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ dm1105/ +obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig deleted file mode 100644 index c03513b2cca..00000000000 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ /dev/null @@ -1,85 +0,0 @@ -config DVB_CINERGYT2 - tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver" - depends on DVB_CORE && USB && INPUT - help - Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers - - Say Y if you own such a device and want to use it. - - -config DVB_CINERGYT2_TUNING - bool "sophisticated fine-tuning for CinergyT2 cards" - depends on DVB_CINERGYT2 - help - Here you can fine-tune some parameters of the CinergyT2 driver. - - Normally you don't need to touch this, but in exotic setups you - may fine-tune your setup and adjust e.g. DMA buffer sizes for - a particular application. - - -config DVB_CINERGYT2_STREAM_URB_COUNT - int "Number of queued USB Request Blocks for Highspeed Stream Transfers" - depends on DVB_CINERGYT2_TUNING - default "32" - help - USB Request Blocks for Highspeed Stream transfers are scheduled in - a queue for the Host Controller. - - Usually the default value is a safe choice. - - You may increase this number if you are using this device in a - Server Environment with many high-traffic USB Highspeed devices - sharing the same USB bus. - - -config DVB_CINERGYT2_STREAM_BUF_SIZE - int "Size of URB Stream Buffers for Highspeed Transfers" - depends on DVB_CINERGYT2_TUNING - default "512" - help - Should be a multiple of native buffer size of 512 bytes. - Default value is a safe choice. - - You may increase this number if you are using this device in a - Server Environment with many high-traffic USB Highspeed devices - sharing the same USB bus. - - -config DVB_CINERGYT2_QUERY_INTERVAL - int "Status update interval [milliseconds]" - depends on DVB_CINERGYT2_TUNING - default "250" - help - This is the interval for status readouts from the demodulator. - You may try lower values if you need more responsive signal quality - measurements. - - Please keep in mind that these updates cause traffic on the tuner - control bus and thus may or may not affect reception sensitivity. - - The default value should be a safe choice for common applications. - - -config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE - bool "Register the onboard IR Remote Control Receiver as Input Device" - depends on DVB_CINERGYT2_TUNING - default y - help - Enable this option if you want to use the onboard Infrared Remote - Control Receiver as Linux-Input device. - - Right now only the keycode table for the default Remote Control - delivered with the device is supported, please see the driver - source code to find out how to add support for other controls. - - -config DVB_CINERGYT2_RC_QUERY_INTERVAL - int "Infrared Remote Controller update interval [milliseconds]" - depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE - default "50" - help - If you have a very fast-repeating remote control you can try lower - values, for normal consumer receivers the default value should be - a safe choice. - diff --git a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile deleted file mode 100644 index d762d8cb0cf..00000000000 --- a/drivers/media/dvb/cinergyT2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o - -EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c deleted file mode 100644 index a824f3719f8..00000000000 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * TerraTec Cinergy T²/qanu USB2 DVB-T adapter. - * - * Copyright (C) 2004 Daniel Mack and - * Holger Waechtler - * - * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf - * - * 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 "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_net.h" - -#ifdef CONFIG_DVB_CINERGYT2_TUNING - #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) - #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) - #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) - #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE - #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) - #define ENABLE_RC (1) - #endif -#else - #define STREAM_URB_COUNT (32) - #define STREAM_BUF_SIZE (512) /* bytes */ - #define ENABLE_RC (1) - #define RC_QUERY_INTERVAL (50) /* milliseconds */ - #define QUERY_INTERVAL (333) /* milliseconds */ -#endif - -#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" - -static int debug; -module_param_named(debug, debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define dprintk(level, args...) \ -do { \ - if ((debug & level)) { \ - printk("%s: %s(): ", KBUILD_MODNAME, \ - __func__); \ - printk(args); } \ -} while (0) - -enum cinergyt2_ep1_cmd { - CINERGYT2_EP1_PID_TABLE_RESET = 0x01, - CINERGYT2_EP1_PID_SETUP = 0x02, - CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, - CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, - CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, - CINERGYT2_EP1_START_SCAN = 0x06, - CINERGYT2_EP1_CONTINUE_SCAN = 0x07, - CINERGYT2_EP1_GET_RC_EVENTS = 0x08, - CINERGYT2_EP1_SLEEP_MODE = 0x09 -}; - -struct dvbt_set_parameters_msg { - uint8_t cmd; - __le32 freq; - uint8_t bandwidth; - __le16 tps; - uint8_t flags; -} __attribute__((packed)); - -struct dvbt_get_status_msg { - __le32 freq; - uint8_t bandwidth; - __le16 tps; - uint8_t flags; - __le16 gain; - uint8_t snr; - __le32 viterbi_error_rate; - __le32 rs_error_rate; - __le32 uncorrected_block_count; - uint8_t lock_bits; - uint8_t prev_lock_bits; -} __attribute__((packed)); - -static struct dvb_frontend_info cinergyt2_fe_info = { - .name = DRIVER_NAME, - .type = FE_OFDM, - .frequency_min = 174000000, - .frequency_max = 862000000, - .frequency_stepsize = 166667, - .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS -}; - -struct cinergyt2 { - struct dvb_demux demux; - struct usb_device *udev; - struct mutex sem; - struct mutex wq_sem; - struct dvb_adapter adapter; - struct dvb_device *fedev; - struct dmxdev dmxdev; - struct dvb_net dvbnet; - - int streaming; - int sleeping; - - struct dvbt_set_parameters_msg param; - struct dvbt_get_status_msg status; - struct delayed_work query_work; - - wait_queue_head_t poll_wq; - int pending_fe_events; - int disconnect_pending; - unsigned int uncorrected_block_count; - atomic_t inuse; - - void *streambuf; - dma_addr_t streambuf_dmahandle; - struct urb *stream_urb [STREAM_URB_COUNT]; - -#ifdef ENABLE_RC - struct input_dev *rc_input_dev; - char phys[64]; - struct delayed_work rc_query_work; - int rc_input_event; - __le32 rc_last_code; - unsigned long last_event_jiffies; -#endif -}; - -enum { - CINERGYT2_RC_EVENT_TYPE_NONE = 0x00, - CINERGYT2_RC_EVENT_TYPE_NEC = 0x01, - CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02 -}; - -struct cinergyt2_rc_event { - char type; - __le32 value; -} __attribute__((packed)); - -static const uint32_t rc_keys[] = { - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP, - CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT -}; - -static int cinergyt2_command (struct cinergyt2 *cinergyt2, - char *send_buf, int send_buf_len, - char *recv_buf, int recv_buf_len) -{ - int actual_len; - char dummy; - int ret; - - ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), - send_buf, send_buf_len, &actual_len, 1000); - - if (ret) - dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); - - if (!recv_buf) - recv_buf = &dummy; - - ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), - recv_buf, recv_buf_len, &actual_len, 1000); - - if (ret) - dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); - - return ret ? ret : actual_len; -} - -static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) -{ - char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); -} - -static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) -{ - char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); - cinergyt2->sleeping = sleep; -} - -static void cinergyt2_stream_irq (struct urb *urb); - -static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) -{ - int err; - - usb_fill_bulk_urb(urb, - cinergyt2->udev, - usb_rcvbulkpipe(cinergyt2->udev, 0x2), - urb->transfer_buffer, - STREAM_BUF_SIZE, - cinergyt2_stream_irq, - cinergyt2); - - if ((err = usb_submit_urb(urb, GFP_ATOMIC))) - dprintk(1, "urb submission failed (err = %i)!\n", err); - - return err; -} - -static void cinergyt2_stream_irq (struct urb *urb) -{ - struct cinergyt2 *cinergyt2 = urb->context; - - if (urb->actual_length > 0) - dvb_dmx_swfilter(&cinergyt2->demux, - urb->transfer_buffer, urb->actual_length); - - if (cinergyt2->streaming) - cinergyt2_submit_stream_urb(cinergyt2, urb); -} - -static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) -{ - int i; - - for (i=0; istream_urb[i]); - - usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, - cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); -} - -static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) -{ - int i; - - cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, - GFP_KERNEL, &cinergyt2->streambuf_dmahandle); - if (!cinergyt2->streambuf) { - dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); - return -ENOMEM; - } - - memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE); - - for (i=0; itransfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE; - urb->transfer_buffer_length = STREAM_BUF_SIZE; - - cinergyt2->stream_urb[i] = urb; - } - - return 0; -} - -static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) -{ - int i; - - cinergyt2_control_stream_transfer(cinergyt2, 0); - - for (i=0; istream_urb[i]); -} - -static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) -{ - int i, err; - - for (i=0; istream_urb[i]))) { - cinergyt2_stop_stream_xfer(cinergyt2); - dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err); - return err; - } - } - - cinergyt2_control_stream_transfer(cinergyt2, 1); - return 0; -} - -static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct dvb_demux *demux = dvbdmxfeed->demux; - struct cinergyt2 *cinergyt2 = demux->priv; - - if (cinergyt2->disconnect_pending) - return -EAGAIN; - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; - - if (cinergyt2->streaming == 0) - cinergyt2_start_stream_xfer(cinergyt2); - - cinergyt2->streaming++; - mutex_unlock(&cinergyt2->sem); - return 0; -} - -static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct dvb_demux *demux = dvbdmxfeed->demux; - struct cinergyt2 *cinergyt2 = demux->priv; - - if (cinergyt2->disconnect_pending) - return -EAGAIN; - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; - - if (--cinergyt2->streaming == 0) - cinergyt2_stop_stream_xfer(cinergyt2); - - mutex_unlock(&cinergyt2->sem); - return 0; -} - -/** - * convert linux-dvb frontend parameter set into TPS. - * See ETSI ETS-300744, section 4.6.2, table 9 for details. - * - * This function is probably reusable and may better get placed in a support - * library. - * - * We replace errornous fields by default TPS fields (the ones with value 0). - */ -static uint16_t compute_tps (struct dvb_frontend_parameters *p) -{ - struct dvb_ofdm_parameters *op = &p->u.ofdm; - uint16_t tps = 0; - - switch (op->code_rate_HP) { - case FEC_2_3: - tps |= (1 << 7); - break; - case FEC_3_4: - tps |= (2 << 7); - break; - case FEC_5_6: - tps |= (3 << 7); - break; - case FEC_7_8: - tps |= (4 << 7); - break; - case FEC_1_2: - case FEC_AUTO: - default: - /* tps |= (0 << 7) */; - } - - switch (op->code_rate_LP) { - case FEC_2_3: - tps |= (1 << 4); - break; - case FEC_3_4: - tps |= (2 << 4); - break; - case FEC_5_6: - tps |= (3 << 4); - break; - case FEC_7_8: - tps |= (4 << 4); - break; - case FEC_1_2: - case FEC_AUTO: - default: - /* tps |= (0 << 4) */; - } - - switch (op->constellation) { - case QAM_16: - tps |= (1 << 13); - break; - case QAM_64: - tps |= (2 << 13); - break; - case QPSK: - default: - /* tps |= (0 << 13) */; - } - - switch (op->transmission_mode) { - case TRANSMISSION_MODE_8K: - tps |= (1 << 0); - break; - case TRANSMISSION_MODE_2K: - default: - /* tps |= (0 << 0) */; - } - - switch (op->guard_interval) { - case GUARD_INTERVAL_1_16: - tps |= (1 << 2); - break; - case GUARD_INTERVAL_1_8: - tps |= (2 << 2); - break; - case GUARD_INTERVAL_1_4: - tps |= (3 << 2); - break; - case GUARD_INTERVAL_1_32: - default: - /* tps |= (0 << 2) */; - } - - switch (op->hierarchy_information) { - case HIERARCHY_1: - tps |= (1 << 10); - break; - case HIERARCHY_2: - tps |= (2 << 10); - break; - case HIERARCHY_4: - tps |= (3 << 10); - break; - case HIERARCHY_NONE: - default: - /* tps |= (0 << 10) */; - } - - return tps; -} - -static int cinergyt2_open (struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct cinergyt2 *cinergyt2 = dvbdev->priv; - int err = -EAGAIN; - - if (cinergyt2->disconnect_pending) - goto out; - err = mutex_lock_interruptible(&cinergyt2->wq_sem); - if (err) - goto out; - - err = mutex_lock_interruptible(&cinergyt2->sem); - if (err) - goto out_unlock1; - - if ((err = dvb_generic_open(inode, file))) - goto out_unlock2; - - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - cinergyt2_sleep(cinergyt2, 0); - schedule_delayed_work(&cinergyt2->query_work, HZ/2); - } - - atomic_inc(&cinergyt2->inuse); - -out_unlock2: - mutex_unlock(&cinergyt2->sem); -out_unlock1: - mutex_unlock(&cinergyt2->wq_sem); -out: - return err; -} - -static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) -{ - dvb_net_release(&cinergyt2->dvbnet); - dvb_dmxdev_release(&cinergyt2->dmxdev); - dvb_dmx_release(&cinergyt2->demux); - dvb_unregister_device(cinergyt2->fedev); - dvb_unregister_adapter(&cinergyt2->adapter); - - cinergyt2_free_stream_urbs(cinergyt2); - kfree(cinergyt2); -} - -static int cinergyt2_release (struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct cinergyt2 *cinergyt2 = dvbdev->priv; - - mutex_lock(&cinergyt2->wq_sem); - - if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { - cancel_rearming_delayed_work(&cinergyt2->query_work); - - mutex_lock(&cinergyt2->sem); - cinergyt2_sleep(cinergyt2, 1); - mutex_unlock(&cinergyt2->sem); - } - - mutex_unlock(&cinergyt2->wq_sem); - - if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { - warn("delayed unregister in release"); - cinergyt2_unregister(cinergyt2); - } - - return dvb_generic_release(inode, file); -} - -static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) -{ - struct dvb_device *dvbdev = file->private_data; - struct cinergyt2 *cinergyt2 = dvbdev->priv; - unsigned int mask = 0; - - if (cinergyt2->disconnect_pending) - return -EAGAIN; - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; - - poll_wait(file, &cinergyt2->poll_wq, wait); - - if (cinergyt2->pending_fe_events != 0) - mask |= (POLLIN | POLLRDNORM | POLLPRI); - - mutex_unlock(&cinergyt2->sem); - - return mask; -} - - -static int cinergyt2_ioctl (struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct dvb_device *dvbdev = file->private_data; - struct cinergyt2 *cinergyt2 = dvbdev->priv; - struct dvbt_get_status_msg *stat = &cinergyt2->status; - fe_status_t status = 0; - - switch (cmd) { - case FE_GET_INFO: - return copy_to_user((void __user*) arg, &cinergyt2_fe_info, - sizeof(struct dvb_frontend_info)); - - case FE_READ_STATUS: - if (0xffff - le16_to_cpu(stat->gain) > 30) - status |= FE_HAS_SIGNAL; - if (stat->lock_bits & (1 << 6)) - status |= FE_HAS_LOCK; - if (stat->lock_bits & (1 << 5)) - status |= FE_HAS_SYNC; - if (stat->lock_bits & (1 << 4)) - status |= FE_HAS_CARRIER; - if (stat->lock_bits & (1 << 1)) - status |= FE_HAS_VITERBI; - - return copy_to_user((void __user*) arg, &status, sizeof(status)); - - case FE_READ_BER: - return put_user(le32_to_cpu(stat->viterbi_error_rate), - (__u32 __user *) arg); - - case FE_READ_SIGNAL_STRENGTH: - return put_user(0xffff - le16_to_cpu(stat->gain), - (__u16 __user *) arg); - - case FE_READ_SNR: - return put_user((stat->snr << 8) | stat->snr, - (__u16 __user *) arg); - - case FE_READ_UNCORRECTED_BLOCKS: - { - uint32_t unc_count; - - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; - unc_count = cinergyt2->uncorrected_block_count; - cinergyt2->uncorrected_block_count = 0; - mutex_unlock(&cinergyt2->sem); - - /* UNC are already converted to host byte order... */ - return put_user(unc_count,(__u32 __user *) arg); - } - case FE_SET_FRONTEND: - { - struct dvbt_set_parameters_msg *param = &cinergyt2->param; - struct dvb_frontend_parameters p; - int err; - - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return -EPERM; - - if (copy_from_user(&p, (void __user*) arg, sizeof(p))) - return -EFAULT; - - if (cinergyt2->disconnect_pending) - return -EAGAIN; - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; - - param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; - param->tps = cpu_to_le16(compute_tps(&p)); - param->freq = cpu_to_le32(p.frequency / 1000); - param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; - - stat->lock_bits = 0; - cinergyt2->pending_fe_events++; - wake_up_interruptible(&cinergyt2->poll_wq); - - err = cinergyt2_command(cinergyt2, - (char *) param, sizeof(*param), - NULL, 0); - - mutex_unlock(&cinergyt2->sem); - - return (err < 0) ? err : 0; - } - - case FE_GET_FRONTEND: - /** - * trivial to implement (see struct dvbt_get_status_msg). - * equivalent to FE_READ ioctls, but needs - * TPS -> linux-dvb parameter set conversion. Feel free - * to implement this and send us a patch if you need this - * functionality. - */ - break; - - case FE_GET_EVENT: - { - /** - * for now we only fill the status field. the parameters - * are trivial to fill as soon FE_GET_FRONTEND is done. - */ - struct dvb_frontend_event __user *e = (void __user *) arg; - if (cinergyt2->pending_fe_events == 0) { - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - wait_event_interruptible(cinergyt2->poll_wq, - cinergyt2->pending_fe_events > 0); - } - cinergyt2->pending_fe_events = 0; - return cinergyt2_ioctl(inode, file, FE_READ_STATUS, - (unsigned long) &e->status); - } - - default: - ; - } - - return -EINVAL; -} - -static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct dvb_device *dvbdev = file->private_data; - struct cinergyt2 *cinergyt2 = dvbdev->priv; - int ret = 0; - - lock_kernel(); - - if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { - ret = -EPERM; - goto bailout; - } - - if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { - ret = -EINVAL; - goto bailout; - } - - vma->vm_flags |= (VM_IO | VM_DONTCOPY); - vma->vm_file = file; - - ret = remap_pfn_range(vma, vma->vm_start, - virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot) ? -EAGAIN : 0; -bailout: - unlock_kernel(); - return ret; -} - -static struct file_operations cinergyt2_fops = { - .owner = THIS_MODULE, - .ioctl = cinergyt2_ioctl, - .poll = cinergyt2_poll, - .open = cinergyt2_open, - .release = cinergyt2_release, - .mmap = cinergyt2_mmap -}; - -static struct dvb_device cinergyt2_fe_template = { - .users = ~0, - .writers = 1, - .readers = (~0)-1, - .fops = &cinergyt2_fops -}; - -#ifdef ENABLE_RC - -static void cinergyt2_query_rc (struct work_struct *work) -{ - struct cinergyt2 *cinergyt2 = - container_of(work, struct cinergyt2, rc_query_work.work); - char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; - struct cinergyt2_rc_event rc_events[12]; - int n, len, i; - - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) - return; - - len = cinergyt2_command(cinergyt2, buf, sizeof(buf), - (char *) rc_events, sizeof(rc_events)); - if (len < 0) - goto out; - if (len == 0) { - if (time_after(jiffies, cinergyt2->last_event_jiffies + - msecs_to_jiffies(150))) { - /* stop key repeat */ - if (cinergyt2->rc_input_event != KEY_MAX) { - dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); - input_report_key(cinergyt2->rc_input_dev, - cinergyt2->rc_input_event, 0); - input_sync(cinergyt2->rc_input_dev); - cinergyt2->rc_input_event = KEY_MAX; - } - cinergyt2->rc_last_code = cpu_to_le32(~0); - } - goto out; - } - cinergyt2->last_event_jiffies = jiffies; - - for (n = 0; n < (len / sizeof(rc_events[0])); n++) { - dprintk(1, "rc_events[%d].value = %x, type=%x\n", - n, le32_to_cpu(rc_events[n].value), rc_events[n].type); - - if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && - rc_events[n].value == cpu_to_le32(~0)) { - /* keyrepeat bit -> just repeat last rc_input_event */ - } else { - cinergyt2->rc_input_event = KEY_MAX; - for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) { - if (rc_keys[i + 0] == rc_events[n].type && - rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { - cinergyt2->rc_input_event = rc_keys[i + 2]; - break; - } - } - } - - if (cinergyt2->rc_input_event != KEY_MAX) { - if (rc_events[n].value == cinergyt2->rc_last_code && - cinergyt2->rc_last_code != cpu_to_le32(~0)) { - /* emit a key-up so the double event is recognized */ - dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); - input_report_key(cinergyt2->rc_input_dev, - cinergyt2->rc_input_event, 0); - } - dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); - input_report_key(cinergyt2->rc_input_dev, - cinergyt2->rc_input_event, 1); - input_sync(cinergyt2->rc_input_dev); - cinergyt2->rc_last_code = rc_events[n].value; - } - } - -out: - schedule_delayed_work(&cinergyt2->rc_query_work, - msecs_to_jiffies(RC_QUERY_INTERVAL)); - - mutex_unlock(&cinergyt2->sem); -} - -static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) -{ - struct input_dev *input_dev; - int i; - int err; - - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); - strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); - cinergyt2->rc_input_event = KEY_MAX; - cinergyt2->rc_last_code = cpu_to_le32(~0); - INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); - - input_dev->name = DRIVER_NAME " remote control"; - input_dev->phys = cinergyt2->phys; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) - set_bit(rc_keys[i + 2], input_dev->keybit); - input_dev->keycodesize = 0; - input_dev->keycodemax = 0; - input_dev->id.bustype = BUS_USB; - input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct); - input_dev->id.version = 1; - input_dev->dev.parent = &cinergyt2->udev->dev; - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - cinergyt2->rc_input_dev = input_dev; - schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); - - return 0; -} - -static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) -{ - cancel_rearming_delayed_work(&cinergyt2->rc_query_work); - input_unregister_device(cinergyt2->rc_input_dev); -} - -static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) -{ - cancel_rearming_delayed_work(&cinergyt2->rc_query_work); -} - -static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) -{ - schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); -} - -#else - -static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; } -static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { } -static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { } -static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } - -#endif /* ENABLE_RC */ - -static void cinergyt2_query (struct work_struct *work) -{ - struct cinergyt2 *cinergyt2 = - container_of(work, struct cinergyt2, query_work.work); - char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; - struct dvbt_get_status_msg *s = &cinergyt2->status; - uint8_t lock_bits; - - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) - return; - - lock_bits = s->lock_bits; - - cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); - - cinergyt2->uncorrected_block_count += - le32_to_cpu(s->uncorrected_block_count); - - if (lock_bits != s->lock_bits) { - wake_up_interruptible(&cinergyt2->poll_wq); - cinergyt2->pending_fe_events++; - } - - schedule_delayed_work(&cinergyt2->query_work, - msecs_to_jiffies(QUERY_INTERVAL)); - - mutex_unlock(&cinergyt2->sem); -} - -static int cinergyt2_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct cinergyt2 *cinergyt2; - int err; - - if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { - dprintk(1, "out of memory?!?\n"); - return -ENOMEM; - } - - usb_set_intfdata (intf, (void *) cinergyt2); - - mutex_init(&cinergyt2->sem); - mutex_init(&cinergyt2->wq_sem); - init_waitqueue_head (&cinergyt2->poll_wq); - INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); - - cinergyt2->udev = interface_to_usbdev(intf); - cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; - - if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { - dprintk(1, "unable to allocate stream urbs\n"); - kfree(cinergyt2); - return -ENOMEM; - } - - err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, - THIS_MODULE, &cinergyt2->udev->dev, - adapter_nr); - if (err < 0) { - kfree(cinergyt2); - return err; - } - - cinergyt2->demux.priv = cinergyt2; - cinergyt2->demux.filternum = 256; - cinergyt2->demux.feednum = 256; - cinergyt2->demux.start_feed = cinergyt2_start_feed; - cinergyt2->demux.stop_feed = cinergyt2_stop_feed; - cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING | - DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - - if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) { - dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err); - goto bailout; - } - - cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum; - cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; - cinergyt2->dmxdev.capabilities = 0; - - if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { - dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); - goto bailout; - } - - if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) - dprintk(1, "dvb_net_init() failed!\n"); - - dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, - &cinergyt2_fe_template, cinergyt2, - DVB_DEVICE_FRONTEND); - - err = cinergyt2_register_rc(cinergyt2); - if (err) - goto bailout; - - return 0; - -bailout: - dvb_net_release(&cinergyt2->dvbnet); - dvb_dmxdev_release(&cinergyt2->dmxdev); - dvb_dmx_release(&cinergyt2->demux); - dvb_unregister_adapter(&cinergyt2->adapter); - cinergyt2_free_stream_urbs(cinergyt2); - kfree(cinergyt2); - return -ENOMEM; -} - -static void cinergyt2_disconnect (struct usb_interface *intf) -{ - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - - cinergyt2_unregister_rc(cinergyt2); - cancel_rearming_delayed_work(&cinergyt2->query_work); - wake_up_interruptible(&cinergyt2->poll_wq); - - cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); - cinergyt2->disconnect_pending = 1; - - if (!atomic_read(&cinergyt2->inuse)) - cinergyt2_unregister(cinergyt2); -} - -static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) -{ - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - - if (cinergyt2->disconnect_pending) - return -EAGAIN; - if (mutex_lock_interruptible(&cinergyt2->wq_sem)) - return -ERESTARTSYS; - - cinergyt2_suspend_rc(cinergyt2); - cancel_rearming_delayed_work(&cinergyt2->query_work); - - mutex_lock(&cinergyt2->sem); - if (cinergyt2->streaming) - cinergyt2_stop_stream_xfer(cinergyt2); - cinergyt2_sleep(cinergyt2, 1); - mutex_unlock(&cinergyt2->sem); - - mutex_unlock(&cinergyt2->wq_sem); - - return 0; -} - -static int cinergyt2_resume (struct usb_interface *intf) -{ - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - struct dvbt_set_parameters_msg *param = &cinergyt2->param; - int err = -EAGAIN; - - if (cinergyt2->disconnect_pending) - goto out; - err = mutex_lock_interruptible(&cinergyt2->wq_sem); - if (err) - goto out; - - err = mutex_lock_interruptible(&cinergyt2->sem); - if (err) - goto out_unlock1; - - if (!cinergyt2->sleeping) { - cinergyt2_sleep(cinergyt2, 0); - cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); - if (cinergyt2->streaming) - cinergyt2_start_stream_xfer(cinergyt2); - schedule_delayed_work(&cinergyt2->query_work, HZ/2); - } - - cinergyt2_resume_rc(cinergyt2); - - mutex_unlock(&cinergyt2->sem); -out_unlock1: - mutex_unlock(&cinergyt2->wq_sem); -out: - return err; -} - -static const struct usb_device_id cinergyt2_table [] __devinitdata = { - { USB_DEVICE(0x0ccd, 0x0038) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(usb, cinergyt2_table); - -static struct usb_driver cinergyt2_driver = { - .name = "cinergyT2", - .probe = cinergyt2_probe, - .disconnect = cinergyt2_disconnect, - .suspend = cinergyt2_suspend, - .resume = cinergyt2_resume, - .id_table = cinergyt2_table -}; - -static int __init cinergyt2_init (void) -{ - int err; - - if ((err = usb_register(&cinergyt2_driver)) < 0) - dprintk(1, "usb_register() failed! (err %i)\n", err); - - return err; -} - -static void __exit cinergyt2_exit (void) -{ - usb_deregister(&cinergyt2_driver); -} - -module_init (cinergyt2_init); -module_exit (cinergyt2_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 241c9ab54b1..57bb470bd06 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -259,6 +259,14 @@ config DVB_USB_DW2102 Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers and the TeVii S650. +config DVB_USB_CINERGY_T2 + tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" + depends on DVB_USB + help + Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers + + Say Y if you own such a device and want to use it. + config DVB_USB_ANYSEE tristate "Anysee DVB-T/C USB2.0 support" depends on DVB_USB diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index ece8c9dfed1..3122b7cc2c2 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -73,6 +73,10 @@ obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o dvb-usb-af9015-objs = af9015.o obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o +dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o +obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o + + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c new file mode 100644 index 00000000000..25863033c48 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c @@ -0,0 +1,230 @@ +/* + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. + * + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) + * + * Based on the dvb-usb-framework code and the + * original Terratec Cinergy T2 driver by: + * + * Copyright (C) 2004 Daniel Mack and + * Holger Waechtler + * + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf + * + * 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 "cinergyT2.h" + + +/* debug */ +int dvb_usb_cinergyt2_debug; +int disable_remote; + +module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " + "(or-able))."); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + +/* We are missing a release hook with usb_device data */ +struct dvb_usb_device *cinergyt2_usb_device; + +static struct dvb_usb_device_properties cinergyt2_properties; + +static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) +{ + char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; + char result[64]; + return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, + sizeof(result), 0); +} + +static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) +{ + char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; + char state[3]; + return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); +} + +static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) +{ + char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; + char state[3]; + int ret; + + adap->fe = cinergyt2_fe_attach(adap->dev); + + ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, + sizeof(state), 0); + if (ret < 0) { + deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " + "state info\n"); + } + + /* Copy this pointer as we are gonna need it in the release phase */ + cinergyt2_usb_device = adap->dev; + + return 0; +} + +static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { + { 0x04, 0x01, KEY_POWER }, + { 0x04, 0x02, KEY_1 }, + { 0x04, 0x03, KEY_2 }, + { 0x04, 0x04, KEY_3 }, + { 0x04, 0x05, KEY_4 }, + { 0x04, 0x06, KEY_5 }, + { 0x04, 0x07, KEY_6 }, + { 0x04, 0x08, KEY_7 }, + { 0x04, 0x09, KEY_8 }, + { 0x04, 0x0a, KEY_9 }, + { 0x04, 0x0c, KEY_0 }, + { 0x04, 0x0b, KEY_VIDEO }, + { 0x04, 0x0d, KEY_REFRESH }, + { 0x04, 0x0e, KEY_SELECT }, + { 0x04, 0x0f, KEY_EPG }, + { 0x04, 0x10, KEY_UP }, + { 0x04, 0x14, KEY_DOWN }, + { 0x04, 0x11, KEY_LEFT }, + { 0x04, 0x13, KEY_RIGHT }, + { 0x04, 0x12, KEY_OK }, + { 0x04, 0x15, KEY_TEXT }, + { 0x04, 0x16, KEY_INFO }, + { 0x04, 0x17, KEY_RED }, + { 0x04, 0x18, KEY_GREEN }, + { 0x04, 0x19, KEY_YELLOW }, + { 0x04, 0x1a, KEY_BLUE }, + { 0x04, 0x1c, KEY_VOLUMEUP }, + { 0x04, 0x1e, KEY_VOLUMEDOWN }, + { 0x04, 0x1d, KEY_MUTE }, + { 0x04, 0x1b, KEY_CHANNELUP }, + { 0x04, 0x1f, KEY_CHANNELDOWN }, + { 0x04, 0x40, KEY_PAUSE }, + { 0x04, 0x4c, KEY_PLAY }, + { 0x04, 0x58, KEY_RECORD }, + { 0x04, 0x54, KEY_PREVIOUS }, + { 0x04, 0x48, KEY_STOP }, + { 0x04, 0x5c, KEY_NEXT } +}; + +static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; + *state = REMOTE_NO_KEY_PRESSED; + + dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); + if (key[4] == 0xff) + return 0; + + /* hack to pass checksum on the custom field (is set to 0xeb) */ + key[2] = ~0x04; + dvb_usb_nec_rc_key_to_event(d, key, event, state); + if (key[0] != 0) + deb_info("key: %x %x %x %x %x\n", + key[0], key[1], key[2], key[3], key[4]); + + return 0; +} + +static int cinergyt2_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return dvb_usb_device_init(intf, &cinergyt2_properties, + THIS_MODULE, NULL, adapter_nr); +} + + +static struct usb_device_id cinergyt2_usb_table[] = { + { USB_DEVICE(USB_VID_TERRATEC, 0x0038) }, + { 0 } +}; + +MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); + +static struct dvb_usb_device_properties cinergyt2_properties = { + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = cinergyt2_streaming_ctrl, + .frontend_attach = cinergyt2_frontend_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + } + }, + + .power_ctrl = cinergyt2_power_ctrl, + + .rc_interval = 50, + .rc_key_map = cinergyt2_rc_keys, + .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys), + .rc_query = cinergyt2_rc_query, + + .generic_bulk_ctrl_endpoint = 1, + + .num_device_descs = 1, + .devices = { + { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver", + .cold_ids = {NULL}, + .warm_ids = { &cinergyt2_usb_table[0], NULL }, + }, + { NULL }, + } +}; + + +static struct usb_driver cinergyt2_driver = { + .name = "cinergyT2", + .probe = cinergyt2_usb_probe, + .disconnect = dvb_usb_device_exit, + .id_table = cinergyt2_usb_table +}; + +static int __init cinergyt2_usb_init(void) +{ + int err; + + err = usb_register(&cinergyt2_driver); + if (err) { + err("usb_register() failed! (err %i)\n", err); + return err; + } + return 0; +} + +static void __exit cinergyt2_usb_exit(void) +{ + usb_deregister(&cinergyt2_driver); +} + +module_init(cinergyt2_usb_init); +module_exit(cinergyt2_usb_exit); + +MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tomi Orava"); diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c new file mode 100644 index 00000000000..649f25cca49 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -0,0 +1,351 @@ +/* + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. + * + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) + * + * Based on the dvb-usb-framework code and the + * original Terratec Cinergy T2 driver by: + * + * Copyright (C) 2004 Daniel Mack and + * Holger Waechtler + * + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf + * + * 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 "cinergyT2.h" + + +/** + * convert linux-dvb frontend parameter set into TPS. + * See ETSI ETS-300744, section 4.6.2, table 9 for details. + * + * This function is probably reusable and may better get placed in a support + * library. + * + * We replace errornous fields by default TPS fields (the ones with value 0). + */ + +static uint16_t compute_tps(struct dvb_frontend_parameters *p) +{ + struct dvb_ofdm_parameters *op = &p->u.ofdm; + uint16_t tps = 0; + + switch (op->code_rate_HP) { + case FEC_2_3: + tps |= (1 << 7); + break; + case FEC_3_4: + tps |= (2 << 7); + break; + case FEC_5_6: + tps |= (3 << 7); + break; + case FEC_7_8: + tps |= (4 << 7); + break; + case FEC_1_2: + case FEC_AUTO: + default: + /* tps |= (0 << 7) */; + } + + switch (op->code_rate_LP) { + case FEC_2_3: + tps |= (1 << 4); + break; + case FEC_3_4: + tps |= (2 << 4); + break; + case FEC_5_6: + tps |= (3 << 4); + break; + case FEC_7_8: + tps |= (4 << 4); + break; + case FEC_1_2: + case FEC_AUTO: + default: + /* tps |= (0 << 4) */; + } + + switch (op->constellation) { + case QAM_16: + tps |= (1 << 13); + break; + case QAM_64: + tps |= (2 << 13); + break; + case QPSK: + default: + /* tps |= (0 << 13) */; + } + + switch (op->transmission_mode) { + case TRANSMISSION_MODE_8K: + tps |= (1 << 0); + break; + case TRANSMISSION_MODE_2K: + default: + /* tps |= (0 << 0) */; + } + + switch (op->guard_interval) { + case GUARD_INTERVAL_1_16: + tps |= (1 << 2); + break; + case GUARD_INTERVAL_1_8: + tps |= (2 << 2); + break; + case GUARD_INTERVAL_1_4: + tps |= (3 << 2); + break; + case GUARD_INTERVAL_1_32: + default: + /* tps |= (0 << 2) */; + } + + switch (op->hierarchy_information) { + case HIERARCHY_1: + tps |= (1 << 10); + break; + case HIERARCHY_2: + tps |= (2 << 10); + break; + case HIERARCHY_4: + tps |= (3 << 10); + break; + case HIERARCHY_NONE: + default: + /* tps |= (0 << 10) */; + } + + return tps; +} + +struct cinergyt2_fe_state { + struct dvb_frontend fe; + struct dvb_usb_device *d; +}; + +static int cinergyt2_fe_read_status(struct dvb_frontend *fe, + fe_status_t *status) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_get_status_msg result; + u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + int ret; + + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, + sizeof(result), 0); + if (ret < 0) + return ret; + + *status = 0; + + if (0xffff - le16_to_cpu(result.gain) > 30) + *status |= FE_HAS_SIGNAL; + if (result.lock_bits & (1 << 6)) + *status |= FE_HAS_LOCK; + if (result.lock_bits & (1 << 5)) + *status |= FE_HAS_SYNC; + if (result.lock_bits & (1 << 4)) + *status |= FE_HAS_CARRIER; + if (result.lock_bits & (1 << 1)) + *status |= FE_HAS_VITERBI; + + if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != + (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) + *status &= ~FE_HAS_LOCK; + + return 0; +} + +static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_get_status_msg status; + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + int ret; + + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, + sizeof(status), 0); + if (ret < 0) + return ret; + + *ber = le32_to_cpu(status.viterbi_error_rate); + return 0; +} + +static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_get_status_msg status; + u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + int ret; + + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, + sizeof(status), 0); + if (ret < 0) { + err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", + ret); + return ret; + } + *unc = le32_to_cpu(status.uncorrected_block_count); + return 0; +} + +static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_get_status_msg status; + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + int ret; + + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, + sizeof(status), 0); + if (ret < 0) { + err("cinergyt2_fe_read_signal_strength() Failed!" + " (Error=%d)\n", ret); + return ret; + } + *strength = (0xffff - le16_to_cpu(status.gain)); + return 0; +} + +static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_get_status_msg status; + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + int ret; + + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, + sizeof(status), 0); + if (ret < 0) { + err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); + return ret; + } + *snr = (status.snr << 8) | status.snr; + return 0; +} + +static int cinergyt2_fe_init(struct dvb_frontend *fe) +{ + return 0; +} + +static int cinergyt2_fe_sleep(struct dvb_frontend *fe) +{ + deb_info("cinergyt2_fe_sleep() Called\n"); + return 0; +} + +static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 800; + return 0; +} + +static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + struct dvbt_set_parameters_msg param; + char result[2]; + int err; + + param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; + param.tps = cpu_to_le16(compute_tps(fep)); + param.freq = cpu_to_le32(fep->frequency / 1000); + param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; + + err = dvb_usb_generic_rw(state->d, + (char *)¶m, sizeof(param), + result, sizeof(result), 0); + if (err < 0) + err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); + + return (err < 0) ? err : 0; +} + +static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + return 0; +} + +static void cinergyt2_fe_release(struct dvb_frontend *fe) +{ + struct cinergyt2_fe_state *state = fe->demodulator_priv; + if (state != NULL) + kfree(state); +} + +static struct dvb_frontend_ops cinergyt2_fe_ops; + +struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) +{ + struct cinergyt2_fe_state *s = kzalloc(sizeof( + struct cinergyt2_fe_state), GFP_KERNEL); + if (s == NULL) + return NULL; + + s->d = d; + memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); + s->fe.demodulator_priv = s; + return &s->fe; +} + + +static struct dvb_frontend_ops cinergyt2_fe_ops = { + .info = { + .name = DRIVER_NAME, + .type = FE_OFDM, + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 + | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 + | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 + | FE_CAN_FEC_AUTO | FE_CAN_QPSK + | FE_CAN_QAM_16 | FE_CAN_QAM_64 + | FE_CAN_QAM_AUTO + | FE_CAN_TRANSMISSION_MODE_AUTO + | FE_CAN_GUARD_INTERVAL_AUTO + | FE_CAN_HIERARCHY_AUTO + | FE_CAN_RECOVER + | FE_CAN_MUTE_TS + }, + + .release = cinergyt2_fe_release, + + .init = cinergyt2_fe_init, + .sleep = cinergyt2_fe_sleep, + + .set_frontend = cinergyt2_fe_set_frontend, + .get_frontend = cinergyt2_fe_get_frontend, + .get_tune_settings = cinergyt2_fe_get_tune_settings, + + .read_status = cinergyt2_fe_read_status, + .read_ber = cinergyt2_fe_read_ber, + .read_signal_strength = cinergyt2_fe_read_signal_strength, + .read_snr = cinergyt2_fe_read_snr, + .read_ucblocks = cinergyt2_fe_read_unc_blocks, +}; diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h new file mode 100644 index 00000000000..11d79eb384c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2.h @@ -0,0 +1,95 @@ +/* + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. + * + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) + * + * Based on the dvb-usb-framework code and the + * original Terratec Cinergy T2 driver by: + * + * Copyright (C) 2004 Daniel Mack and + * Holger Waechtler + * + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _DVB_USB_CINERGYT2_H_ +#define _DVB_USB_CINERGYT2_H_ + +#include + +#define DVB_USB_LOG_PREFIX "cinergyT2" +#include "dvb-usb.h" + +#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" + +extern int dvb_usb_cinergyt2_debug; + +#define deb_info(args...) dprintk(dvb_usb_cinergyt2_debug, 0x001, args) +#define deb_xfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x002, args) +#define deb_pll(args...) dprintk(dvb_usb_cinergyt2_debug, 0x004, args) +#define deb_ts(args...) dprintk(dvb_usb_cinergyt2_debug, 0x008, args) +#define deb_err(args...) dprintk(dvb_usb_cinergyt2_debug, 0x010, args) +#define deb_rc(args...) dprintk(dvb_usb_cinergyt2_debug, 0x020, args) +#define deb_fw(args...) dprintk(dvb_usb_cinergyt2_debug, 0x040, args) +#define deb_mem(args...) dprintk(dvb_usb_cinergyt2_debug, 0x080, args) +#define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x100, args) + + + +enum cinergyt2_ep1_cmd { + CINERGYT2_EP1_PID_TABLE_RESET = 0x01, + CINERGYT2_EP1_PID_SETUP = 0x02, + CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, + CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, + CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, + CINERGYT2_EP1_START_SCAN = 0x06, + CINERGYT2_EP1_CONTINUE_SCAN = 0x07, + CINERGYT2_EP1_GET_RC_EVENTS = 0x08, + CINERGYT2_EP1_SLEEP_MODE = 0x09, + CINERGYT2_EP1_GET_FIRMWARE_VERSION = 0x0A +}; + + +struct dvbt_get_status_msg { + uint32_t freq; + uint8_t bandwidth; + uint16_t tps; + uint8_t flags; + uint16_t gain; + uint8_t snr; + uint32_t viterbi_error_rate; + uint32_t rs_error_rate; + uint32_t uncorrected_block_count; + uint8_t lock_bits; + uint8_t prev_lock_bits; +} __attribute__((packed)); + + +struct dvbt_set_parameters_msg { + uint8_t cmd; + uint32_t freq; + uint8_t bandwidth; + uint16_t tps; + uint8_t flags; +} __attribute__((packed)); + + +extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d); + +#endif /* _DVB_USB_CINERGYT2_H_ */ + -- GitLab From 7f9876785276ac7f8606f8bf53a3dae4c10b8adb Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Fri, 19 Sep 2008 00:24:51 -0300 Subject: [PATCH 4201/5416] V4L/DVB (9108): cinergyT2: add remote key repeat feature Implement key repeat feature for the cinergyT2 remote controller. Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cinergyT2-core.c | 52 +++++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c index 25863033c48..3ac9f74e9fb 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c @@ -40,6 +40,9 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct cinergyt2_state { + u8 rc_counter; +}; /* We are missing a release hook with usb_device data */ struct dvb_usb_device *cinergyt2_usb_device; @@ -122,22 +125,57 @@ static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { { 0x04, 0x5c, KEY_NEXT } }; +/* Number of keypresses to ignore before detect repeating */ +#define RC_REPEAT_DELAY 3 + +static int repeatable_keys[] = { + KEY_UP, + KEY_DOWN, + KEY_LEFT, + KEY_RIGHT, + KEY_VOLUMEUP, + KEY_VOLUMEDOWN, + KEY_CHANNELUP, + KEY_CHANNELDOWN +}; + static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { + struct cinergyt2_state *st = d->priv; u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; + int i; + *state = REMOTE_NO_KEY_PRESSED; dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); - if (key[4] == 0xff) + if (key[4] == 0xff) { + /* key repeat */ + st->rc_counter++; + if (st->rc_counter > RC_REPEAT_DELAY) { + for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { + if (d->last_event == repeatable_keys[i]) { + *state = REMOTE_KEY_REPEAT; + *event = d->last_event; + deb_rc("repeat key, event %x\n", + *event); + return 0; + } + } + deb_rc("repeated key (non repeatable)\n"); + } return 0; + } - /* hack to pass checksum on the custom field (is set to 0xeb) */ - key[2] = ~0x04; + /* hack to pass checksum on the custom field */ + key[2] = ~key[1]; dvb_usb_nec_rc_key_to_event(d, key, event, state); - if (key[0] != 0) - deb_info("key: %x %x %x %x %x\n", - key[0], key[1], key[2], key[3], key[4]); + if (key[0] != 0) { + if (*event != d->last_event) + st->rc_counter = 0; + deb_rc("key: %x %x %x %x %x\n", + key[0], key[1], key[2], key[3], key[4]); + } return 0; } @@ -157,7 +195,7 @@ static struct usb_device_id cinergyt2_usb_table[] = { MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); static struct dvb_usb_device_properties cinergyt2_properties = { - + .size_of_priv = sizeof(struct cinergyt2_state), .num_adapters = 1, .adapter = { { -- GitLab From d267d85101c509020a12686b96cbd179deaf4ecd Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 28 Sep 2008 21:46:02 -0300 Subject: [PATCH 4202/5416] V4L/DVB (9110): cx18: Add default behavior of checking and retrying PCI MMIO accesses cx18: Add default behavior of checking and retrying PCI MMIO accesses. The concept of checking and retrying PCI MMIO accesses for better reliability in older motherboards was suggested by Steve Toth . This change implements MMIO retries and the retry_mmio module parameter that is enabled by default. Limited experiments have shown this is more reliable than the mmio_ndelay parameter. mmio_ndelay has insignificant effect with retries enabled. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 11 + drivers/media/video/cx18/cx18-av-core.h | 2 + drivers/media/video/cx18/cx18-av-firmware.c | 18 +- drivers/media/video/cx18/cx18-driver.c | 7 + drivers/media/video/cx18/cx18-driver.h | 11 + drivers/media/video/cx18/cx18-io.c | 135 +++++++++- drivers/media/video/cx18/cx18-io.h | 278 ++++++++++++++++++-- drivers/media/video/cx18/cx18-ioctl.c | 1 + 8 files changed, 427 insertions(+), 36 deletions(-) diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index d8626e35465..73f5141a42d 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -42,6 +42,12 @@ int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) return 0; } +int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value) +{ + cx18_write_reg_noretry(cx, value, 0xc40000 + addr); + return 0; +} + u8 cx18_av_read(struct cx18 *cx, u16 addr) { u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3)); @@ -55,6 +61,11 @@ u32 cx18_av_read4(struct cx18 *cx, u16 addr) return cx18_read_reg(cx, 0xc40000 + addr); } +u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr) +{ + return cx18_read_reg_noretry(cx, 0xc40000 + addr); +} + int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, u8 or_value) { diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index eb61fa1e096..b67d8df20cc 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -301,8 +301,10 @@ struct cx18_av_state { /* cx18_av-core.c */ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); +int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value); u8 cx18_av_read(struct cx18 *cx, u16 addr); u32 cx18_av_read4(struct cx18 *cx, u16 addr); +u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr); int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index 0488b629770..522a035b2e8 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -50,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx) cx18_av_write4(cx, 0x8100, 0x00010000); /* Put the 8051 in reset and enable firmware upload */ - cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); + cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000); ptr = fw->data; size = fw->size; @@ -59,22 +59,28 @@ int cx18_av_loadfw(struct cx18 *cx) u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); u32 value = 0; int retries2; + int unrec_err = 0; - for (retries2 = 0; retries2 < 5; retries2++) { - cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); + for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES; + retries2++) { + cx18_av_write4_noretry(cx, CXADEC_DL_CTL, + dl_control); udelay(10); - value = cx18_av_read4(cx, CXADEC_DL_CTL); + value = cx18_av_read4_noretry(cx, + CXADEC_DL_CTL); if (value == dl_control) break; /* Check if we can correct the byte by changing the address. We can only write the lower address byte of the address. */ if ((value & 0x3F00) != (dl_control & 0x3F00)) { - retries2 = 5; + unrec_err = 1; break; } } - if (retries2 >= 5) + cx18_log_write_retries(cx, retries2, + cx->reg_mem + 0xc40000 + CXADEC_DL_CTL); + if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES) break; } if (i == size) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 4de7b501f20..df5531709ae 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -96,6 +96,7 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; static int cx18_pci_latency = 1; +int cx18_retry_mmio = 1; int cx18_debug; module_param_array(tuner, int, &tuner_c, 0644); @@ -106,6 +107,7 @@ module_param_string(pal, pal, sizeof(pal), 0644); module_param_string(secam, secam, sizeof(secam), 0644); module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); module_param_named(debug, cx18_debug, int, 0644); +module_param_named(retry_mmio, cx18_retry_mmio, int, 0644); module_param(cx18_pci_latency, int, 0644); module_param(cx18_first_minor, int, 0644); @@ -147,6 +149,9 @@ MODULE_PARM_DESC(debug, MODULE_PARM_DESC(cx18_pci_latency, "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" "\t\t\tDefault: Yes"); +MODULE_PARM_DESC(retry_mmio, + "Check and retry memory mapped IO accesses\n" + "\t\t\tDefault: 1 [Yes]"); MODULE_PARM_DESC(mmio_ndelay, "Delay (ns) for each CX23418 memory mapped IO access.\n" "\t\t\tTry larger values that are close to a multiple of the\n" @@ -827,6 +832,7 @@ err: if (retval == 0) retval = -ENODEV; CX18_ERR("Error %d on initialization\n", retval); + cx18_log_statistics(cx); kfree(cx18_cards[cx18_cards_active]); cx18_cards[cx18_cards_active] = NULL; @@ -931,6 +937,7 @@ static void cx18_remove(struct pci_dev *pci_dev) pci_disable_device(cx->dev); + cx18_log_statistics(cx); CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 66cb748875c..80f5f563d4f 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -171,6 +171,7 @@ #define CX18_MAX_PGM_INDEX (400) +extern int cx18_retry_mmio; /* enable check & retry of mmio accesses */ extern int cx18_debug; @@ -344,6 +345,13 @@ struct cx18_i2c_algo_callback_data { int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ }; +#define CX18_MAX_MMIO_RETRIES 10 + +struct cx18_mmio_stats { + atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1]; + atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1]; +}; + /* Struct to hold info about cx18 cards */ struct cx18 { int num; /* board number, -1 during init! */ @@ -433,6 +441,9 @@ struct cx18 { u32 gpio_val; struct mutex gpio_lock; + /* Statistics */ + struct cx18_mmio_stats mmio_stats; + /* v4l2 and User settings */ /* codec settings */ diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 55d1df93292..700ab9439c1 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -24,6 +24,131 @@ #include "cx18-io.h" #include "cx18-irq.h" +void cx18_log_statistics(struct cx18 *cx) +{ + int i; + + if (!(cx18_debug & CX18_DBGFLG_INFO)) + return; + + for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) + CX18_DEBUG_INFO("retried_write[%d] = %d\n", i, + atomic_read(&cx->mmio_stats.retried_write[i])); + for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) + CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, + atomic_read(&cx->mmio_stats.retried_read[i])); + return; +} + +void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) +{ + int i; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_raw_writel_noretry(cx, val, addr); + if (val == cx18_raw_readl_noretry(cx, addr)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + +u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr) +{ + int i; + u32 val; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + val = cx18_raw_readl_noretry(cx, addr); + if (val != 0xffffffff) /* PCI bus read error */ + break; + } + cx18_log_read_retries(cx, i, addr); + return val; +} + +u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr) +{ + int i; + u16 val; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + val = cx18_raw_readw_noretry(cx, addr); + if (val != 0xffff) /* PCI bus read error */ + break; + } + cx18_log_read_retries(cx, i, addr); + return val; +} + +void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) +{ + int i; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_writel_noretry(cx, val, addr); + if (val == cx18_readl_noretry(cx, addr)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + +void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) +{ + int i; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_writew_noretry(cx, val, addr); + if (val == cx18_readw_noretry(cx, addr)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + +void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr) +{ + int i; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_writeb_noretry(cx, val, addr); + if (val == cx18_readb_noretry(cx, addr)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + +u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr) +{ + int i; + u32 val; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + val = cx18_readl_noretry(cx, addr); + if (val != 0xffffffff) /* PCI bus read error */ + break; + } + cx18_log_read_retries(cx, i, addr); + return val; +} + +u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr) +{ + int i; + u16 val; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + val = cx18_readw_noretry(cx, addr); + if (val != 0xffff) /* PCI bus read error */ + break; + } + cx18_log_read_retries(cx, i, addr); + return val; +} + +u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr) +{ + int i; + u8 val; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + val = cx18_readb_noretry(cx, addr); + if (val != 0xff) /* PCI bus read error */ + break; + } + cx18_log_read_retries(cx, i, addr); + return val; +} + void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len) { @@ -127,13 +252,3 @@ void cx18_setup_page(struct cx18 *cx, u32 addr) val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00); cx18_write_reg(cx, val, 0xD000F8); } - -/* Tries to recover from the CX23418 responding improperly on the PCI bus */ -int cx18_pci_try_recover(struct cx18 *cx) -{ - u16 status; - - pci_read_config_word(cx->dev, PCI_STATUS, &status); - pci_write_config_word(cx->dev, PCI_STATUS, status); - return 0; -} diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 7ab7be2531c..197d4fbd9f9 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h @@ -31,102 +31,343 @@ static inline void cx18_io_delay(struct cx18 *cx) ndelay(cx->options.mmio_ndelay); } +/* + * Readback and retry of MMIO access for reliability: + * The concept was suggested by Steve Toth . + * The implmentation is the fault of Andy Walls . + */ + +/* Statistics gathering */ +static inline +void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr) +{ + if (i > CX18_MAX_MMIO_RETRIES) + i = CX18_MAX_MMIO_RETRIES; + atomic_inc(&cx->mmio_stats.retried_write[i]); + return; +} + +static inline +void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr) +{ + if (i > CX18_MAX_MMIO_RETRIES) + i = CX18_MAX_MMIO_RETRIES; + atomic_inc(&cx->mmio_stats.retried_read[i]); + return; +} + +void cx18_log_statistics(struct cx18 *cx); + /* Non byteswapping memory mapped IO */ -static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) +static inline +void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) { __raw_writel(val, addr); cx18_io_delay(cx); } -static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) +void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); + +static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + if (cx18_retry_mmio) + cx18_raw_writel_retry(cx, val, addr); + else + cx18_raw_writel_noretry(cx, val, addr); +} + + +static inline +u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr) { u32 ret = __raw_readl(addr); cx18_io_delay(cx); return ret; } -static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) +u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr); + +static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) +{ + if (cx18_retry_mmio) + return cx18_raw_readl_retry(cx, addr); + + return cx18_raw_readl_noretry(cx, addr); +} + + +static inline +u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr) { u16 ret = __raw_readw(addr); cx18_io_delay(cx); return ret; } +u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr); + +static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) +{ + if (cx18_retry_mmio) + return cx18_raw_readw_retry(cx, addr); + + return cx18_raw_readw_noretry(cx, addr); +} + + /* Normal memory mapped IO */ -static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) +static inline +void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) { writel(val, addr); cx18_io_delay(cx); } -static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) +void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); + +static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) +{ + if (cx18_retry_mmio) + cx18_writel_retry(cx, val, addr); + else + cx18_writel_noretry(cx, val, addr); +} + + +static inline +void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) { writew(val, addr); cx18_io_delay(cx); } -static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) +void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr); + +static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) +{ + if (cx18_retry_mmio) + cx18_writew_retry(cx, val, addr); + else + cx18_writew_noretry(cx, val, addr); +} + + +static inline +void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr) { writeb(val, addr); cx18_io_delay(cx); } -static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) +void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr); + +static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) +{ + if (cx18_retry_mmio) + cx18_writeb_retry(cx, val, addr); + else + cx18_writeb_noretry(cx, val, addr); +} + + +static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr) { u32 ret = readl(addr); cx18_io_delay(cx); return ret; } -static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) +u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr); + +static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) +{ + if (cx18_retry_mmio) + return cx18_readl_retry(cx, addr); + + return cx18_readl_noretry(cx, addr); +} + + +static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr) +{ + u16 ret = readw(addr); + cx18_io_delay(cx); + return ret; +} + +u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr); + +static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr) +{ + if (cx18_retry_mmio) + return cx18_readw_retry(cx, addr); + + return cx18_readw_noretry(cx, addr); +} + + +static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr) { u8 ret = readb(addr); cx18_io_delay(cx); return ret; } +u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr); + +static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) +{ + if (cx18_retry_mmio) + return cx18_readb_retry(cx, addr); + + return cx18_readb_noretry(cx, addr); +} + + +static inline +u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr) +{ + cx18_writel_noretry(cx, val, addr); + return cx18_readl_noretry(cx, addr); +} + +static inline +u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr) +{ + cx18_writel_retry(cx, val, addr); + return cx18_readl_retry(cx, addr); +} + static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) { - cx18_writel(cx, val, addr); - return cx18_readl(cx, addr); + if (cx18_retry_mmio) + return cx18_write_sync_retry(cx, val, addr); + + return cx18_write_sync_noretry(cx, val, addr); } + void cx18_memcpy_fromio(struct cx18 *cx, void *to, const void __iomem *from, unsigned int len); void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); + /* Access "register" region of CX23418 memory mapped I/O */ +static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg) +{ + cx18_writel_noretry(cx, val, cx->reg_mem + reg); +} + +static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg) +{ + cx18_writel_retry(cx, val, cx->reg_mem + reg); +} + static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) { - cx18_writel(cx, val, cx->reg_mem + reg); + if (cx18_retry_mmio) + cx18_write_reg_retry(cx, val, reg); + else + cx18_write_reg_noretry(cx, val, reg); +} + + +static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) +{ + return cx18_readl_noretry(cx, cx->reg_mem + reg); +} + +static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg) +{ + return cx18_readl_retry(cx, cx->reg_mem + reg); } static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) { - return cx18_readl(cx, cx->reg_mem + reg); + if (cx18_retry_mmio) + return cx18_read_reg_retry(cx, reg); + + return cx18_read_reg_noretry(cx, reg); +} + + +static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg) +{ + return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg); +} + +static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg) +{ + return cx18_write_sync_retry(cx, val, cx->reg_mem + reg); } static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) { - return cx18_write_sync(cx, val, cx->reg_mem + reg); + if (cx18_retry_mmio) + return cx18_write_reg_sync_retry(cx, val, reg); + + return cx18_write_reg_sync_noretry(cx, val, reg); } + /* Access "encoder memory" region of CX23418 memory mapped I/O */ +static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr) +{ + cx18_writel_noretry(cx, val, cx->enc_mem + addr); +} + +static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr) +{ + cx18_writel_retry(cx, val, cx->enc_mem + addr); +} + static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) { - cx18_writel(cx, val, cx->enc_mem + addr); + if (cx18_retry_mmio) + cx18_write_enc_retry(cx, val, addr); + else + cx18_write_enc_noretry(cx, val, addr); +} + + +static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr) +{ + return cx18_readl_noretry(cx, cx->enc_mem + addr); +} + +static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr) +{ + return cx18_readl_retry(cx, cx->enc_mem + addr); } static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) { - return cx18_readl(cx, cx->enc_mem + addr); + if (cx18_retry_mmio) + return cx18_read_enc_retry(cx, addr); + + return cx18_read_enc_noretry(cx, addr); +} + +static inline +u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr) +{ + return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr); } -static inline u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) +static inline +u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr) { - return cx18_write_sync(cx, val, cx->enc_mem + addr); + return cx18_write_sync_retry(cx, val, cx->enc_mem + addr); } +static inline +u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) +{ + if (cx18_retry_mmio) + return cx18_write_enc_sync_retry(cx, val, addr); + + return cx18_write_enc_sync_noretry(cx, val, addr); +} void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); @@ -134,7 +375,4 @@ void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); void cx18_setup_page(struct cx18 *cx, u32 addr); -/* Tries to recover from the CX23418 responding improperly on the PCI bus */ -int cx18_pci_try_recover(struct cx18 *cx); - #endif /* CX18_IO_H */ diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 4a47f61d948..83aa9cb02e0 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -752,6 +752,7 @@ static int cx18_log_status(struct file *file, void *fh) CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)cx->mpg_data_received, (long long)cx->vbi_data_inserted); + cx18_log_statistics(cx); CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); return 0; } -- GitLab From 1e758265f4df731fcd20e559af3a8eb849db3b4d Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 3 Oct 2008 13:49:05 -0300 Subject: [PATCH 4203/5416] V4L/DVB (9111): cx18: Up the version to 1.0.1 cx18: Up the version to 1.0.1. This will make it easy to tell if retries of MMIO access are implemented or not in trouble reports. First course of action for I2C and other initialization problem reports will be to have user upgrade to v1.0.1 of driver. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index d5c7a6f968d..9f6be2d457f 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h @@ -25,7 +25,7 @@ #define CX18_DRIVER_NAME "cx18" #define CX18_DRIVER_VERSION_MAJOR 1 #define CX18_DRIVER_VERSION_MINOR 0 -#define CX18_DRIVER_VERSION_PATCHLEVEL 0 +#define CX18_DRIVER_VERSION_PATCHLEVEL 1 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ -- GitLab From 028165a336ab7d097d23e2af936dea373e3d3afc Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Sat, 4 Oct 2008 21:37:36 -0300 Subject: [PATCH 4204/5416] V4L/DVB (9113): saa7134: fixes for the Asus Tiger Revision 1.00 In opposite to the P7131 Dual this early OEM card has a male radio antenna connector and also no remote. We currently switch the DVB-T RF feed to the radio input, like on the P7131 with female radio connector used also for DVB-T and should improve this. Signed-off-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 3 +- drivers/media/video/saa7134/saa7134-cards.c | 45 ++++++++++++++++++--- drivers/media/video/saa7134/saa7134-dvb.c | 5 +++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 727b5f21477..dc67eef38ff 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -76,7 +76,7 @@ 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] - 78 -> ASUSTeK P7131 Dual [1043:4862,1043:4857] + 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] 81 -> Philips Tiger reference design [1131:2018] @@ -150,3 +150,4 @@ 149 -> Avermedia PCI pure analog (M135A) [1461:f11d] 150 -> Zogis Real Angel 220 151 -> ADS Tech Instant HDTV [1421:0380] +152 -> Asus Tiger Rev:1.00 [1043:4857] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a2653b82e06..c9392c4e92f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4527,7 +4527,7 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, .tv = 1, .gpio = 0x624000, - }, { + }, { .name = name_comp1, .vmux = 1, .amux = LINE1, @@ -4564,14 +4564,48 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }, { .name = name_comp, - .vmux = 4, - .amux = LINE1, + .vmux = 4, + .amux = LINE1, }, { .name = name_svideo, .vmux = 8, .amux = LINE1, } }, }, + [SAA7134_BOARD_ASUSTeK_TIGER] = { + .name = "Asus Tiger Rev:1.00", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5358,8 +5392,8 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1043, - .subdevice = 0x4857, - .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, + .subdevice = 0x4857, /* REV:1.00 */ + .driver_data = SAA7134_BOARD_ASUSTeK_TIGER, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -6177,6 +6211,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_PINNACLE_PCTV_310i: case SAA7134_BOARD_KWORLD_DVBT_210: case SAA7134_BOARD_TEVION_DVBT_220RF: + case SAA7134_BOARD_ASUSTeK_TIGER: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_MEDION_MD8800_QUADRO: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 2c5185778af..87c10983266 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1335,6 +1335,11 @@ static int dvb_init(struct saa7134_dev *dev) } } break; + case SAA7134_BOARD_ASUSTeK_TIGER: + if (configure_tda827x_fe(dev, &philips_tiger_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 0907c70dc48..491ab1f8fdd 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -274,6 +274,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M135A 149 #define SAA7134_BOARD_REAL_ANGEL_220 150 #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 +#define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- GitLab From da703d6262b5d168a4ceb427255cfcf3771b8f96 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 2 Sep 2008 19:00:21 -0300 Subject: [PATCH 4205/5416] V4L/DVB (8904): cx88: add missing unlock_kernel sparse found an unbalanced BKL usage. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 1b7e2e44b80..e7136975430 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1073,6 +1073,7 @@ static int mpeg_open(struct inode *inode, struct file *file) err = drv->request_acquire(drv); if(err != 0) { dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); + unlock_kernel(); return err; } } -- GitLab From 79025a9ed9132880d5197611dec6d8533c121ac7 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 6 Oct 2008 12:07:48 -0300 Subject: [PATCH 4206/5416] V4L/DVB (9114): dib0700: fix bad assignment of dib0700_xc5000_tuner_callback after return call Put callback definition before function return and cleanup callback: Fix a bug where the xc5000 callback was being set *after* the return call (essentially resulting in dead code). Also cleanup the callback function to detect unknown commands. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 9891ca0924a..0cfccc24b19 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1181,11 +1181,16 @@ static int dib0700_xc5000_tuner_callback(void *priv, int component, { struct dvb_usb_adapter *adap = priv; - /* Reset the tuner */ - dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); - msleep(330); /* from Windows USB trace */ - dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); - msleep(330); /* from Windows USB trace */ + if (command == XC5000_TUNER_RESET) { + /* Reset the tuner */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); + msleep(330); /* from Windows USB trace */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); + msleep(330); /* from Windows USB trace */ + } else { + err("xc5000: unknown tuner callback command: %d\n", command); + return -EINVAL; + } return 0; } @@ -1197,12 +1202,12 @@ static struct xc5000_config s5h1411_xc5000_tunerconfig = { static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) { + /* FIXME: generalize & move to common area */ + adap->fe->callback = dib0700_xc5000_tuner_callback; + return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, &s5h1411_xc5000_tunerconfig) == NULL ? -ENODEV : 0; - - /* FIXME: generalize & move to common area */ - adap->fe->callback = dib0700_xc5000_tuner_callback; } /* DVB-USB and USB stuff follows */ -- GitLab From a482f327ff56bc3cf53176a7eb736cea47291a1d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Oct 2008 05:08:23 -0300 Subject: [PATCH 4207/5416] V4L/DVB (9116): USB: remove info() macro from usb media drivers USB should not be having it's own printk macros, so remove info() and use the system-wide standard of dev_info() wherever possible. Cc: Douglas Landgraf Cc: Mike Isely Cc: Thierry Merle Cc: Antoine Jacquet Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/dsbr100.c | 3 +- drivers/media/video/dabusb.c | 3 +- drivers/media/video/ov511.c | 105 +++++------ drivers/media/video/ov511.h | 3 +- drivers/media/video/pvrusb2/pvrusb2-main.c | 8 +- drivers/media/video/se401.c | 37 ++-- drivers/media/video/stv680.c | 6 +- drivers/media/video/usbvideo/ibmcam.c | 78 +++++---- drivers/media/video/usbvideo/konicawc.c | 17 +- .../media/video/usbvideo/quickcam_messenger.c | 3 +- drivers/media/video/usbvideo/ultracam.c | 29 ++-- drivers/media/video/usbvideo/usbvideo.c | 163 ++++++++++++------ .../media/video/usbvision/usbvision-core.c | 3 +- drivers/media/video/usbvision/usbvision-i2c.c | 3 +- .../media/video/usbvision/usbvision-video.c | 3 +- drivers/media/video/zr364xx.c | 50 +++--- 16 files changed, 312 insertions(+), 202 deletions(-) diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 0f06e6ffb0e..b3a5cb1adf3 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -510,7 +510,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf, static int __init dsbr100_init(void) { int retval = usb_register(&usb_dsbr100_driver); - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 79faedf5852..3aa538afcc0 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -866,7 +866,8 @@ static int __init dabusb_init (void) dbg("dabusb_init: driver registered"); - info(DRIVER_VERSION ":" DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); out: return retval; diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index c6852402c5e..935d73de57b 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -974,14 +974,14 @@ dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) for (i = reg1; i <= regn; i++) { rc = i2c_r(ov, i); - info("Sensor[0x%02X] = 0x%02X", i, rc); + dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc); } } static void dump_i2c_regs(struct usb_ov511 *ov) { - info("I2C REGS"); + dev_info(&ov->dev->dev, "I2C REGS\n"); dump_i2c_range(ov, 0x00, 0x7C); } @@ -992,28 +992,28 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) for (i = reg1; i <= regn; i++) { rc = reg_r(ov, i); - info("OV511[0x%02X] = 0x%02X", i, rc); + dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc); } } static void ov511_dump_regs(struct usb_ov511 *ov) { - info("CAMERA INTERFACE REGS"); + dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n"); dump_reg_range(ov, 0x10, 0x1f); - info("DRAM INTERFACE REGS"); + dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n"); dump_reg_range(ov, 0x20, 0x23); - info("ISO FIFO REGS"); + dev_info(&ov->dev->dev, "ISO FIFO REGS\n"); dump_reg_range(ov, 0x30, 0x31); - info("PIO REGS"); + dev_info(&ov->dev->dev, "PIO REGS\n"); dump_reg_range(ov, 0x38, 0x39); dump_reg_range(ov, 0x3e, 0x3e); - info("I2C REGS"); + dev_info(&ov->dev->dev, "I2C REGS\n"); dump_reg_range(ov, 0x40, 0x49); - info("SYSTEM CONTROL REGS"); + dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n"); dump_reg_range(ov, 0x50, 0x55); dump_reg_range(ov, 0x5e, 0x5f); - info("OmniCE REGS"); + dev_info(&ov->dev->dev, "OmniCE REGS\n"); dump_reg_range(ov, 0x70, 0x79); /* NOTE: Quantization tables are not readable. You will get the value * in reg. 0x79 for every table register */ @@ -1025,25 +1025,25 @@ ov511_dump_regs(struct usb_ov511 *ov) static void ov518_dump_regs(struct usb_ov511 *ov) { - info("VIDEO MODE REGS"); + dev_info(&ov->dev->dev, "VIDEO MODE REGS\n"); dump_reg_range(ov, 0x20, 0x2f); - info("DATA PUMP AND SNAPSHOT REGS"); + dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n"); dump_reg_range(ov, 0x30, 0x3f); - info("I2C REGS"); + dev_info(&ov->dev->dev, "I2C REGS\n"); dump_reg_range(ov, 0x40, 0x4f); - info("SYSTEM CONTROL AND VENDOR REGS"); + dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n"); dump_reg_range(ov, 0x50, 0x5f); - info("60 - 6F"); + dev_info(&ov->dev->dev, "60 - 6F\n"); dump_reg_range(ov, 0x60, 0x6f); - info("70 - 7F"); + dev_info(&ov->dev->dev, "70 - 7F\n"); dump_reg_range(ov, 0x70, 0x7f); - info("Y QUANTIZATION TABLE"); + dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n"); dump_reg_range(ov, 0x80, 0x8f); - info("UV QUANTIZATION TABLE"); + dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n"); dump_reg_range(ov, 0x90, 0x9f); - info("A0 - BF"); + dev_info(&ov->dev->dev, "A0 - BF\n"); dump_reg_range(ov, 0xa0, 0xbf); - info("CBR"); + dev_info(&ov->dev->dev, "CBR\n"); dump_reg_range(ov, 0xc0, 0xcf); } #endif @@ -3205,9 +3205,10 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) */ if (printph) { - info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", - pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], - in[7], in[8], in[9], in[10], in[11]); + dev_info(&ov->dev->dev, + "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", + pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], + in[7], in[8], in[9], in[10], in[11]); } /* Check for SOF/EOF packet */ @@ -3366,8 +3367,10 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) * the definitive SOF/EOF format */ if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { if (printph) { - info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], - in[1], in[2], in[3], in[4], in[5], in[6], in[7]); + dev_info(&ov->dev->dev, + "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n", + in[0], in[1], in[2], in[3], in[4], in[5], + in[6], in[7]); } if (frame->scanstate == STATE_LINES) { @@ -3646,14 +3649,16 @@ ov51x_init_isoc(struct usb_ov511 *ov) if (packetsize == -1) { ov518_set_packet_size(ov, 640); } else { - info("Forcing packet size to %d", packetsize); + dev_info(&ov->dev->dev, "Forcing packet size to %d\n", + packetsize); ov518_set_packet_size(ov, packetsize); } } else { if (packetsize == -1) { ov511_set_packet_size(ov, size); } else { - info("Forcing packet size to %d", packetsize); + dev_info(&ov->dev->dev, "Forcing packet size to %d\n", + packetsize); ov511_set_packet_size(ov, packetsize); } } @@ -4121,7 +4126,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, return -EIO; if (force_palette && p->palette != force_palette) { - info("Palette rejected (%s)", + dev_info(&ov->dev->dev, "Palette rejected (%s)\n", symbolic(v4l1_plist, p->palette)); return -EINVAL; } @@ -4849,26 +4854,27 @@ ov7xx0_configure(struct usb_ov511 *ov) err("Error detecting sensor type"); return -1; } else if ((rc & 3) == 3) { - info("Sensor is an OV7610"); + dev_info(&ov->dev->dev, "Sensor is an OV7610\n"); ov->sensor = SEN_OV7610; } else if ((rc & 3) == 1) { /* I don't know what's different about the 76BE yet. */ if (i2c_r(ov, 0x15) & 1) - info("Sensor is an OV7620AE"); + dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n"); else - info("Sensor is an OV76BE"); + dev_info(&ov->dev->dev, "Sensor is an OV76BE\n"); /* OV511+ will return all zero isoc data unless we * configure the sensor as a 7620. Someone needs to * find the exact reg. setting that causes this. */ if (ov->bridge == BRG_OV511PLUS) { - info("Enabling 511+/7620AE workaround"); + dev_info(&ov->dev->dev, + "Enabling 511+/7620AE workaround\n"); ov->sensor = SEN_OV7620; } else { ov->sensor = SEN_OV76BE; } } else if ((rc & 3) == 0) { - info("Sensor is an OV7620"); + dev_info(&ov->dev->dev, "Sensor is an OV7620\n"); ov->sensor = SEN_OV7620; } else { err("Unknown image sensor version: %d", rc & 3); @@ -5024,16 +5030,16 @@ ov6xx0_configure(struct usb_ov511 *ov) if ((rc & 3) == 0) { ov->sensor = SEN_OV6630; - info("Sensor is an OV6630"); + dev_info(&ov->dev->dev, "Sensor is an OV6630\n"); } else if ((rc & 3) == 1) { ov->sensor = SEN_OV6620; - info("Sensor is an OV6620"); + dev_info(&ov->dev->dev, "Sensor is an OV6620\n"); } else if ((rc & 3) == 2) { ov->sensor = SEN_OV6630; - info("Sensor is an OV6630AE"); + dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n"); } else if ((rc & 3) == 3) { ov->sensor = SEN_OV6630; - info("Sensor is an OV6630AF"); + dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n"); } /* Set sensor-specific vars */ @@ -5088,10 +5094,10 @@ ks0127_configure(struct usb_ov511 *ov) err("Error detecting sensor type"); return -1; } else if ((rc & 0x0f) == 0) { - info("Sensor is a KS0127"); + dev_info(&ov->dev->dev, "Sensor is a KS0127\n"); ov->sensor = SEN_KS0127; } else if ((rc & 0x0f) == 9) { - info("Sensor is a KS0127B Rev. A"); + dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n"); ov->sensor = SEN_KS0127B; } } else { @@ -5200,7 +5206,8 @@ saa7111a_configure(struct usb_ov511 *ov) err("Error detecting sensor version"); return -1; } else { - info("Sensor is an SAA7111A (version 0x%x)", rc); + dev_info(&ov->dev->dev, + "Sensor is an SAA7111A (version 0x%x)\n", rc); ov->sensor = SEN_SAA7111A; } @@ -5262,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov) PDEBUG (1, "CustomID = %d", ov->customid); ov->desc = symbolic(camlist, ov->customid); - info("model: %s", ov->desc); + dev_info(&ov->dev->dev, "model: %s\n", ov->desc); if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { err("Camera type (%d) not recognized", ov->customid); @@ -5426,7 +5433,8 @@ ov518_configure(struct usb_ov511 *ov) PDEBUG(4, ""); /* First 5 bits of custom ID reg are a revision ID on OV518 */ - info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); + dev_info(&ov->dev->dev, "Device revision %d\n", + 0x1F & reg_r(ov, R511_SYS_CUST_ID)); /* Give it the default description */ ov->desc = symbolic(camlist, 0); @@ -5773,7 +5781,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - info("USB %s video device found", symbolic(brglist, ov->bridge)); + dev_info(&intf->dev, "USB %s video device found\n", + symbolic(brglist, ov->bridge)); init_waitqueue_head(&ov->wq); @@ -5854,8 +5863,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - info("Device at %s registered to minor %d", ov->usb_path, - ov->vdev->minor); + dev_info(&intf->dev, "Device at %s registered to minor %d\n", + ov->usb_path, ov->vdev->minor); usb_set_intfdata(intf, ov); if (ov_create_sysfs(ov->vdev)) { @@ -5958,7 +5967,8 @@ usb_ov511_init(void) if (retval) goto out; - info(DRIVER_VERSION " : " DRIVER_DESC); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); out: return retval; @@ -5968,8 +5978,7 @@ static void __exit usb_ov511_exit(void) { usb_deregister(&ov511_driver); - info("driver deregistered"); - + printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n"); } module_init(usb_ov511_init); diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index baded1262ca..70d99e52329 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h @@ -12,7 +12,8 @@ #ifdef OV511_DEBUG #define PDEBUG(level, fmt, args...) \ - if (debug >= (level)) info("[%s:%d] " fmt, \ + if (debug >= (level)) \ + printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \ __func__, __LINE__ , ## args) #else #define PDEBUG(level, fmt, args...) do {} while(0) diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index ad0d98c2ebb..9b3c874d96d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -137,9 +137,11 @@ static int __init pvr_init(void) ret = usb_register(&pvr_driver); if (ret == 0) - info(DRIVER_DESC " : " DRIVER_VERSION); - if (pvrusb2_debug) info("Debug mask is %d (0x%x)", - pvrusb2_debug,pvrusb2_debug); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + if (pvrusb2_debug) + printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n", + pvrusb2_debug,pvrusb2_debug); pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index b01f25d7292..ae3949180c4 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -288,7 +288,7 @@ static void se401_button_irq(struct urb *urb) int status; if (!se401->dev) { - info("ohoh: device vapourished"); + dev_info(&urb->dev->dev, "device vapourished\n"); return; } @@ -328,7 +328,7 @@ static void se401_video_irq(struct urb *urb) return; if (!se401->dev) { - info ("ohoh: device vapourished"); + dev_info(&urb->dev->dev, "device vapourished\n"); return; } @@ -375,7 +375,7 @@ static void se401_video_irq(struct urb *urb) urb->status=0; urb->dev=se401->dev; if(usb_submit_urb(urb, GFP_KERNEL)) - info("urb burned down"); + dev_info(&urb->dev->dev, "urb burned down\n"); return; } @@ -860,7 +860,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) ); if (se401->nullpackets > SE401_MAX_NULLPACKETS) { se401->nullpackets=0; - info("to many null length packets, restarting capture"); + dev_info(&se401->dev->dev, + "too many null length packets, restarting capture\n"); se401_stop_stream(se401); se401_start_stream(se401); } else { @@ -880,7 +881,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) se401->scratch_use=0; if (errors > SE401_MAX_ERRORS) { errors=0; - info("to much errors, restarting capture"); + dev_info(&se401->dev->dev, + "too many errors, restarting capture\n"); se401_stop_stream(se401); se401_start_stream(se401); } @@ -913,7 +915,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); } - info("%s disconnected", se401->camera_name); + dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); /* Free the memory */ kfree(se401->width); @@ -960,8 +962,8 @@ static int se401_close(struct inode *inode, struct file *file) rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); if (se401->removed) { + dev_info(&se401->dev->dev, "device unregistered\n"); usb_se401_remove_disconnected(se401); - info("device unregistered"); } else { for (i=0; iframe[i].grabstate=FRAME_UNUSED; @@ -1276,7 +1278,7 @@ static int se401_init(struct usb_se401 *se401, int button) for (i=0; isizes; i++) { sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); } - info("%s", temp); + dev_info(&se401->dev->dev, "%s\n", temp); se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); @@ -1310,7 +1312,8 @@ static int se401_init(struct usb_se401 *se401, int button) if (button) { se401->inturb=usb_alloc_urb(0, GFP_KERNEL); if (!se401->inturb) { - info("Allocation of inturb failed"); + dev_info(&se401->dev->dev, + "Allocation of inturb failed\n"); return 1; } usb_fill_int_urb(se401->inturb, se401->dev, @@ -1321,7 +1324,7 @@ static int se401_init(struct usb_se401 *se401, int button) 8 ); if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - info("int urb burned down"); + dev_info(&se401->dev->dev, "int urb burned down\n"); return 1; } } else @@ -1378,7 +1381,7 @@ static int se401_probe(struct usb_interface *intf, return -ENODEV; /* We found one */ - info("SE401 camera found: %s", camera_name); + dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { err("couldn't kmalloc se401 struct"); @@ -1389,7 +1392,8 @@ static int se401_probe(struct usb_interface *intf, se401->iface = interface->bInterfaceNumber; se401->camera_name = camera_name; - info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); + dev_info(&intf->dev, "firmware version: %02x\n", + le16_to_cpu(dev->descriptor.bcdDevice) & 255); if (se401_init(se401, button)) { kfree(se401); @@ -1407,7 +1411,8 @@ static int se401_probe(struct usb_interface *intf, err("video_register_device failed"); return -EIO; } - info("registered new video device: video%d", se401->vdev.minor); + dev_info(&intf->dev, "registered new video device: video%d\n", + se401->vdev.minor); usb_set_intfdata (intf, se401); return 0; @@ -1451,10 +1456,10 @@ static struct usb_driver se401_driver = { static int __init usb_se401_init(void) { - info("SE401 usb camera driver version %s registering", version); + printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); if (flickerless) if (flickerless!=50 && flickerless!=60) { - info("Invallid flickerless value, use 0, 50 or 60."); + printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); return -1; } return usb_register(&se401_driver); @@ -1463,7 +1468,7 @@ static int __init usb_se401_init(void) static void __exit usb_se401_exit(void) { usb_deregister(&se401_driver); - info("SE401 driver deregistered"); + printk(KERN_INFO "SE401 driver deregistered\frame"); } module_init(usb_se401_init); diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index b21a8d6827c..9c549d93599 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -84,7 +84,8 @@ static unsigned int debug; #define PDEBUG(level, fmt, args...) \ do { \ if (debug >= level) \ - info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt, \ + __func__, __LINE__ , ## args); \ } while (0) @@ -1552,7 +1553,8 @@ static int __init usb_stv680_init (void) } PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return 0; } diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index cc27efe121d..28421d386f1 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -258,7 +258,9 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) { #if 0 /* This code helps to detect new frame markers */ - info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3)); + dev_info(&uvd->dev->dev, + "Header sig: 00 FF 00 %02X\n", + RING_QUEUE_PEEK(&uvd->dp, 3)); #endif frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); if ((frame->header == HDRSIG_MODEL1_128x96) || @@ -266,7 +268,8 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h (frame->header == HDRSIG_MODEL1_352x288)) { #if 0 - info("Header found."); + dev_info(&uvd->dev->dev, + "Header found.\n"); #endif RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); icam->has_hdr = 1; @@ -295,7 +298,7 @@ case IBMCAM_MODEL_4: (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) { #if 0 - info("Header found."); + dev_info(&uvd->dev->dev, "Header found.\n"); #endif RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); icam->has_hdr = 1; @@ -338,7 +341,7 @@ case IBMCAM_MODEL_4: byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); frame->header = (byte3 << 8) | byte4; #if 0 - info("Header found."); + dev_info(&uvd->dev->dev, "Header found.\n"); #endif RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); icam->has_hdr = 1; @@ -354,7 +357,8 @@ case IBMCAM_MODEL_4: } if (!icam->has_hdr) { if (uvd->debug > 2) - info("Skipping frame, no header"); + dev_info(&uvd->dev->dev, + "Skipping frame, no header\n"); return scan_EndParse; } @@ -881,7 +885,9 @@ static enum ParseState ibmcam_model3_parse_lines( */ if ((frame->curline + 1) >= data_h) { if (uvd->debug >= 3) - info("Reached line %d. (frame is done)", frame->curline); + dev_info(&uvd->dev->dev, + "Reached line %d. (frame is done)\n", + frame->curline); return scan_NextFrame; } @@ -954,8 +960,9 @@ static enum ParseState ibmcam_model3_parse_lines( if (frame->curline >= VIDEOSIZE_Y(frame->request)) { if (uvd->debug >= 3) { - info("All requested lines (%ld.) done.", - VIDEOSIZE_Y(frame->request)); + dev_info(&uvd->dev->dev, + "All requested lines (%ld.) done.\n", + VIDEOSIZE_Y(frame->request)); } return scan_NextFrame; } else @@ -1000,7 +1007,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( */ if ((frame->curline + 1) >= data_h) { if (uvd->debug >= 3) - info("Reached line %d. (frame is done)", frame->curline); + dev_info(&uvd->dev->dev, + "Reached line %d. (frame is done)\n", + frame->curline); return scan_NextFrame; } @@ -1049,8 +1058,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( if (frame->curline >= VIDEOSIZE_Y(frame->request)) { if (uvd->debug >= 3) { - info("All requested lines (%ld.) done.", - VIDEOSIZE_Y(frame->request)); + dev_info(&uvd->dev->dev, + "All requested lines (%ld.) done.\n", + VIDEOSIZE_Y(frame->request)); } return scan_NextFrame; } else @@ -1171,10 +1181,11 @@ static int ibmcam_veio( sizeof(cp), 1000); #if 0 - info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); + dev_info(&uvd->dev->dev, + "USB => %02x%02x%02x%02x%02x%02x%02x%02x " + "(req=$%02x val=$%04x ind=$%04x)\n", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index); #endif } else { i = usb_control_msg( @@ -1449,10 +1460,9 @@ static void ibmcam_adjust_contrast(struct uvd *uvd) */ static void ibmcam_change_lighting_conditions(struct uvd *uvd) { - static const char proc[] = "ibmcam_change_lighting_conditions"; - if (debug > 0) - info("%s: Set lighting to %hu.", proc, lighting); + dev_info(&uvd->dev->dev, + "%s: Set lighting to %hu.\n", __func__, lighting); switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: @@ -1495,8 +1505,6 @@ static void ibmcam_change_lighting_conditions(struct uvd *uvd) */ static void ibmcam_set_sharpness(struct uvd *uvd) { - static const char proc[] = "ibmcam_set_sharpness"; - switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: { @@ -1505,7 +1513,8 @@ static void ibmcam_set_sharpness(struct uvd *uvd) RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); if (debug > 0) - info("%s: Set sharpness to %hu.", proc, sharpness); + dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n", + __func__, sharpness); sv = sa[sharpness - SHARPNESS_MIN]; for (i=0; i < 2; i++) { @@ -1564,11 +1573,11 @@ static void ibmcam_set_sharpness(struct uvd *uvd) */ static void ibmcam_set_brightness(struct uvd *uvd) { - static const char proc[] = "ibmcam_set_brightness"; static const unsigned short n = 1; if (debug > 0) - info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); + dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n", + __func__, uvd->vpic.brightness); switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: @@ -2115,7 +2124,8 @@ static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) break; } if (uvd->debug > 0) - info("Framerate (hardware): %hd.", hw_fps); + dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n", + hw_fps); RESTRICT_TO_RANGE(hw_fps, 0, 31); ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); } @@ -3487,7 +3497,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) /* 01.01.08 - Added for RCA video in support -LO */ if(init_model3_input) { if (debug > 0) - info("Setting input to RCA."); + dev_info(&uvd->dev->dev, "Setting input to RCA.\n"); for (i=0; i < ARRAY_SIZE(initData); i++) { ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); } @@ -3685,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * unsigned char video_ep = 0; if (debug >= 1) - info("ibmcam_probe(%p,%u.)", intf, ifnum); + dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) @@ -3736,14 +3746,16 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ break; } - info("%s USB camera found (model %d, rev. 0x%04x)", - brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); + dev_info(&uvd->dev->dev, + "%s USB camera found (model %d, rev. 0x%04x)\n", + brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); } while (0); /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (debug > 0) - info("Number of alternate settings=%d.", nas); + dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", + nas); if (nas < 2) { err("Too few alternate settings for this camera!"); return -ENODEV; @@ -3787,7 +3799,9 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) - info("Active setting=%d. maxPS=%d.", i, maxPS); + dev_info(&uvd->dev->dev, + "Active setting=%d. " + "maxPS=%d.\n", i, maxPS); } else err("More than one active alt. setting! Ignoring #%d.", i); } @@ -3826,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * RESTRICT_TO_RANGE(framerate, 0, 5); break; default: - info("IBM camera: using 320x240"); + dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); size = SIZE_320x240; /* No break here */ case SIZE_320x240: @@ -3855,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * canvasY = 120; break; default: - info("IBM NetCamera: using 176x144"); + dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); size = SIZE_176x144; /* No break here */ case SIZE_176x144: diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 1c180284ec6..e986c28b7bb 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -337,7 +337,8 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur } if((sts > 0x01) && (sts < 0x80)) { - info("unknown status %2.2x", sts); + dev_info(&uvd->dev->dev, "unknown status %2.2x\n", + sts); bad++; continue; } @@ -568,8 +569,12 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; fdrops--; if(fdrops) { - info("Dropped %d frames (%d -> %d)", fdrops, - cam->lastframe, curframe); + dev_info(&uvd->dev->dev, + "Dropped %d frames " + "(%d -> %d)\n", + fdrops, + cam->lastframe, + curframe); } } cam->lastframe = curframe; @@ -784,7 +789,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; - info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); + dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", + le16_to_cpu(dev->descriptor.bcdDevice)); RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); /* Validate found interface: must have one ISO endpoint */ @@ -925,7 +931,8 @@ static struct usb_device_id id_table[] = { static int __init konicawc_init(void) { struct usbvideo_cb cbTbl; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); memset(&cbTbl, 0, sizeof(cbTbl)); cbTbl.probe = konicawc_probe; cbTbl.setupOnOpen = konicawc_setup_on_open; diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 3d26a30abe1..05c61b52311 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -1080,7 +1080,8 @@ static struct usbvideo_cb qcm_driver = { static int __init qcm_init(void) { - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return usbvideo_register( &cams, diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 9544e644bf0..9714baab783 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c @@ -156,10 +156,11 @@ static int ultracam_veio( sizeof(cp), 1000); #if 1 - info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); + dev_info(&uvd->dev->dev, + "USB => %02x%02x%02x%02x%02x%02x%02x%02x " + "(req=$%02x val=$%04x ind=$%04x)\n", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index); #endif } else { i = usb_control_msg( @@ -517,19 +518,20 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id unsigned char video_ep = 0; if (debug >= 1) - info("ultracam_probe(%p)", intf); + dev_info(&intf->dev, "ultracam_probe\n"); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; - info("IBM Ultra camera found (rev. 0x%04x)", - le16_to_cpu(dev->descriptor.bcdDevice)); + dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", + le16_to_cpu(dev->descriptor.bcdDevice)); /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (debug > 0) - info("Number of alternate settings=%d.", nas); + dev_info(&intf->dev, "Number of alternate settings=%d.\n", + nas); if (nas < 8) { err("Too few alternate settings for this camera!"); return -ENODEV; @@ -576,7 +578,9 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) - info("Active setting=%d. maxPS=%d.", i, maxPS); + dev_info(&intf->dev, + "Active setting=%d. " + "maxPS=%d.\n", i, maxPS); } else { /* Got another active alt. setting */ if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { @@ -584,8 +588,11 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) { - info("Even better ctive setting=%d. maxPS=%d.", - i, maxPS); + dev_info(&intf->dev, + "Even better ctive " + "setting=%d. " + "maxPS=%d.\n", + i, maxPS); } } } diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 9569e8ced4b..07cd87d16f6 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -468,8 +468,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) percent = (100 * goodPackets) / allPackets; else percent = goodPackets / (allPackets / 100); - info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", - allPackets, badPackets, percent); + dev_info(&uvd->dev->dev, + "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", + allPackets, badPackets, percent); if (uvd->iso_packet_len > 0) { unsigned long allBytes, xferBytes; char multiplier = ' '; @@ -497,8 +498,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) } } } - info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", - xferBytes, multiplier, percent); + dev_info(&uvd->dev->dev, + "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", + xferBytes, multiplier, percent); } } } @@ -545,7 +547,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) { /* For debugging purposes only */ char tmp[20]; usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); - info("testpattern: frame=%s", tmp); + dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); } #endif /* Form every scan line */ @@ -854,7 +856,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) usbvideo_ClientIncModCount(uvd); if (uvd->debug > 0) - info("%s(%p.)", __func__, intf); + dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); mutex_lock(&uvd->lock); uvd->remove_pending = 1; /* Now all ISO data will be ignored */ @@ -870,14 +872,15 @@ static void usbvideo_Disconnect(struct usb_interface *intf) video_unregister_device(&uvd->vdev); if (uvd->debug > 0) - info("%s: Video unregistered.", __func__); + dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); if (uvd->user) - info("%s: In use, disconnect pending.", __func__); + dev_info(&intf->dev, "%s: In use, disconnect pending.\n", + __func__); else usbvideo_CameraRelease(uvd); mutex_unlock(&uvd->lock); - info("USB camera disconnected."); + dev_info(&intf->dev, "USB camera disconnected.\n"); usbvideo_ClientDecModCount(uvd); } @@ -1015,14 +1018,17 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) return -EINVAL; } if (uvd->video_endp == 0) { - info("%s: No video endpoint specified; data pump disabled.", __func__); + dev_info(&uvd->dev->dev, + "%s: No video endpoint specified; data pump disabled.\n", + __func__); } if (uvd->paletteBits == 0) { err("%s: No palettes specified!", __func__); return -EINVAL; } if (uvd->defaultPalette == 0) { - info("%s: No default palette!", __func__); + dev_info(&uvd->dev->dev, "%s: No default palette!\n", + __func__); } uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * @@ -1031,8 +1037,10 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); if (uvd->debug > 0) { - info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", - __func__, uvd->iface, uvd->video_endp, uvd->paletteBits); + dev_info(&uvd->dev->dev, + "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", + __func__, uvd->iface, uvd->video_endp, + uvd->paletteBits); } if (uvd->dev == NULL) { err("%s: uvd->dev == NULL", __func__); @@ -1045,12 +1053,13 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) return -EPIPE; } if (uvd->debug > 1) { - info("%s: video_register_device() successful", __func__); + dev_info(&uvd->dev->dev, + "%s: video_register_device() successful\n", __func__); } - info("%s on /dev/video%d: canvas=%s videosize=%s", - (uvd->handle != NULL) ? uvd->handle->drvName : "???", - uvd->vdev.minor, tmp2, tmp1); + dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", + (uvd->handle != NULL) ? uvd->handle->drvName : "???", + uvd->vdev.minor, tmp2, tmp1); usb_get_dev(uvd->dev); return 0; @@ -1112,7 +1121,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) int i, errCode = 0; if (uvd->debug > 1) - info("%s($%p)", __func__, dev); + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); if (0 < usbvideo_ClientIncModCount(uvd)) return -ENODEV; @@ -1179,19 +1188,25 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) if (errCode == 0) { if (VALID_CALLBACK(uvd, setupOnOpen)) { if (uvd->debug > 1) - info("%s: setupOnOpen callback", __func__); + dev_info(&uvd->dev->dev, + "%s: setupOnOpen callback\n", + __func__); errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); if (errCode < 0) { err("%s: setupOnOpen callback failed (%d.).", __func__, errCode); } else if (uvd->debug > 1) { - info("%s: setupOnOpen callback successful", __func__); + dev_info(&uvd->dev->dev, + "%s: setupOnOpen callback successful\n", + __func__); } } if (errCode == 0) { uvd->settingsAdjusted = 0; if (uvd->debug > 1) - info("%s: Open succeeded.", __func__); + dev_info(&uvd->dev->dev, + "%s: Open succeeded.\n", + __func__); uvd->user++; file->private_data = uvd; } @@ -1201,7 +1216,8 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) if (errCode != 0) usbvideo_ClientDecModCount(uvd); if (uvd->debug > 0) - info("%s: Returning %d.", __func__, errCode); + dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, + errCode); return errCode; } @@ -1224,7 +1240,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) int i; if (uvd->debug > 1) - info("%s($%p)", __func__, dev); + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); mutex_lock(&uvd->lock); GET_CALLBACK(uvd, stopDataPump)(uvd); @@ -1244,14 +1260,15 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) uvd->user--; if (uvd->remove_pending) { if (uvd->debug > 0) - info("usbvideo_v4l_close: Final disconnect."); + dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", + __func__); usbvideo_CameraRelease(uvd); } mutex_unlock(&uvd->lock); usbvideo_ClientDecModCount(uvd); if (uvd->debug > 1) - info("%s: Completed.", __func__); + dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); file->private_data = NULL; return 0; } @@ -1365,8 +1382,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, struct video_mmap *vm = arg; if (uvd->debug >= 1) { - info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", - vm->frame, vm->width, vm->height, vm->format); + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", + vm->frame, vm->width, vm->height, vm->format); } /* * Check if the requested size is supported. If the requestor @@ -1384,18 +1402,24 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || (vm->height > VIDEOSIZE_Y(uvd->canvas))) { if (uvd->debug > 0) { - info("VIDIOCMCAPTURE: Size=%dx%d too large; " - "allowed only up to %ldx%ld", vm->width, vm->height, - VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: Size=%dx%d " + "too large; allowed only up " + "to %ldx%ld\n", vm->width, + vm->height, + VIDEOSIZE_X(uvd->canvas), + VIDEOSIZE_Y(uvd->canvas)); } return -EINVAL; } /* Check if the palette is supported */ if (((1L << vm->format) & uvd->paletteBits) == 0) { if (uvd->debug > 0) { - info("VIDIOCMCAPTURE: format=%d. not supported" - " (paletteBits=$%08lx)", - vm->format, uvd->paletteBits); + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: format=%d. " + "not supported " + "(paletteBits=$%08lx)\n", + vm->format, uvd->paletteBits); } return -EINVAL; } @@ -1423,7 +1447,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (uvd->debug >= 1) - info("VIDIOCSYNC: syncing to frame %d.", *frameNum); + dev_info(&uvd->dev->dev, + "VIDIOCSYNC: syncing to frame %d.\n", + *frameNum); if (uvd->flags & FLAGS_NO_DECODING) ret = usbvideo_GetFrame(uvd, *frameNum); else if (VALID_CALLBACK(uvd, getFrame)) { @@ -1505,7 +1531,9 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, return -EFAULT; if (uvd->debug >= 1) - info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock); + dev_info(&uvd->dev->dev, + "%s: %Zd. bytes, noblock=%d.\n", + __func__, count, noblock); mutex_lock(&uvd->lock); @@ -1686,18 +1714,21 @@ static void usbvideo_IsocIrq(struct urb *urb) return; #if 0 if (urb->actual_length > 0) { - info("urb=$%p status=%d. errcount=%d. length=%d.", - urb, urb->status, urb->error_count, urb->actual_length); + dev_info(&uvd->dev->dev, + "urb=$%p status=%d. errcount=%d. length=%d.\n", + urb, urb->status, urb->error_count, + urb->actual_length); } else { static int c = 0; if (c++ % 100 == 0) - info("No Isoc data"); + dev_info(&uvd->dev->dev, "No Isoc data\n"); } #endif if (!uvd->streaming) { if (uvd->debug >= 1) - info("Not streaming, but interrupt!"); + dev_info(&uvd->dev->dev, + "Not streaming, but interrupt!\n"); return; } @@ -1742,7 +1773,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd) int i, errFlag; if (uvd->debug > 1) - info("%s($%p)", __func__, uvd); + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); if (!CAMERA_IS_OPERATIONAL(uvd)) { err("%s: Camera is not operational", __func__); @@ -1790,7 +1821,9 @@ static int usbvideo_StartDataPump(struct uvd *uvd) uvd->streaming = 1; if (uvd->debug > 1) - info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp); + dev_info(&uvd->dev->dev, + "%s: streaming=1 video_endp=$%02x\n", __func__, + uvd->video_endp); return 0; } @@ -1812,14 +1845,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd) return; if (uvd->debug > 1) - info("%s($%p)", __func__, uvd); + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); /* Unschedule all of the iso td's */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { usb_kill_urb(uvd->sbuf[i].urb); } if (uvd->debug > 1) - info("%s: streaming=0", __func__); + dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); uvd->streaming = 0; if (!uvd->remove_pending) { @@ -1851,7 +1884,8 @@ static int usbvideo_NewFrame(struct uvd *uvd, int framenum) int n; if (uvd->debug > 1) - info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); + dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, + framenum); /* If we're not grabbing a frame right now and the other frame is */ /* ready to be grabbed into, then use it instead */ @@ -1956,12 +1990,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) struct usbvideo_frame *frame = &uvd->frame[frameNum]; if (uvd->debug >= 2) - info("%s($%p,%d.)", __func__, uvd, frameNum); + dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, + frameNum); switch (frame->frameState) { case FrameState_Unused: if (uvd->debug >= 2) - info("%s: FrameState_Unused", __func__); + dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", + __func__); return -EINVAL; case FrameState_Ready: case FrameState_Grabbing: @@ -1971,7 +2007,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) redo: if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (1)", __func__); + dev_info(&uvd->dev->dev, + "%s: Camera is not operational (1)\n", + __func__); return -EIO; } ntries = 0; @@ -1980,24 +2018,33 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) signalPending = signal_pending(current); if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (2)", __func__); + dev_info(&uvd->dev->dev, + "%s: Camera is not " + "operational (2)\n", __func__); return -EIO; } assert(uvd->fbuf != NULL); if (signalPending) { if (uvd->debug >= 2) - info("%s: Signal=$%08x", __func__, signalPending); + dev_info(&uvd->dev->dev, + "%s: Signal=$%08x\n", __func__, + signalPending); if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { usbvideo_TestPattern(uvd, 1, 0); uvd->curframe = -1; uvd->stats.frame_num++; if (uvd->debug >= 2) - info("%s: Forced test pattern screen", __func__); + dev_info(&uvd->dev->dev, + "%s: Forced test " + "pattern screen\n", + __func__); return 0; } else { /* Standard answer: Interrupted! */ if (uvd->debug >= 2) - info("%s: Interrupted!", __func__); + dev_info(&uvd->dev->dev, + "%s: Interrupted!\n", + __func__); return -EINTR; } } else { @@ -2011,8 +2058,10 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) } } while (frame->frameState == FrameState_Grabbing); if (uvd->debug >= 2) { - info("%s: Grabbing done; state=%d. (%lu. bytes)", - __func__, frame->frameState, frame->seqRead_Length); + dev_info(&uvd->dev->dev, + "%s: Grabbing done; state=%d. (%lu. bytes)\n", + __func__, frame->frameState, + frame->seqRead_Length); } if (frame->frameState == FrameState_Error) { int ret = usbvideo_NewFrame(uvd, frameNum); @@ -2049,7 +2098,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) } frame->frameState = FrameState_Done_Hold; if (uvd->debug >= 2) - info("%s: Entered FrameState_Done_Hold state.", __func__); + dev_info(&uvd->dev->dev, + "%s: Entered FrameState_Done_Hold state.\n", + __func__); return 0; case FrameState_Done_Hold: @@ -2060,7 +2111,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) * it will be released back into the wild to roam freely. */ if (uvd->debug >= 2) - info("%s: FrameState_Done_Hold state.", __func__); + dev_info(&uvd->dev->dev, + "%s: FrameState_Done_Hold state.\n", + __func__); return 0; } diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index c317ed7a848..b26b563a0b0 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -84,7 +84,8 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); #ifdef USBVISION_DEBUG #define PDEBUG(level, fmt, args...) { \ if (core_debug & (level)) \ - info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ + __func__, __LINE__ , ## args); \ } #else #define PDEBUG(level, fmt, args...) do {} while(0) diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index a6d00858b07..92427fdc145 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -47,7 +47,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define PDEBUG(level, fmt, args...) { \ if (i2c_debug & (level)) \ - info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ + __func__, __LINE__ , ## args); \ } static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 782ee643601..e10b256aeba 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -98,7 +98,8 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) #ifdef USBVISION_DEBUG #define PDEBUG(level, fmt, args...) { \ if (video_debug & (level)) \ - info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ + __func__, __LINE__ , ## args); \ } #else #define PDEBUG(level, fmt, args...) do {} while(0) diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 93991cb9ca7..7cdac99deea 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -52,7 +52,7 @@ /* Debug macro */ -#define DBG(x...) if (debug) info(x) +#define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x) /* Init methods, need to find nicer names for these @@ -128,7 +128,7 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); if (!transfer_buffer) { - info("kmalloc(%d) failed", size); + dev_err(&udev->dev, "kmalloc(%d) failed\n", size); return -ENOMEM; } @@ -144,7 +144,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, kfree(transfer_buffer); if (status < 0) - info("Failed sending control message, error %d.", status); + dev_err(&udev->dev, + "Failed sending control message, error %d.\n", status); return status; } @@ -304,11 +305,11 @@ static int read_frame(struct zr364xx_camera *cam, int framenum) DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); DBG("bulk : n=%d size=%d", n, actual_length); if (n < 0) { - info("error reading bulk msg"); + dev_err(&cam->udev->dev, "error reading bulk msg\n"); return 0; } if (actual_length < 0 || actual_length > BUFFER_SIZE) { - info("wrong number of bytes"); + dev_err(&cam->udev->dev, "wrong number of bytes\n"); return 0; } @@ -652,7 +653,7 @@ static int zr364xx_open(struct inode *inode, struct file *file) if (!cam->framebuf) { cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); if (!cam->framebuf) { - info("vmalloc_32 failed!"); + dev_err(&cam->udev->dev, "vmalloc_32 failed!\n"); err = -ENOMEM; goto out; } @@ -664,7 +665,8 @@ static int zr364xx_open(struct inode *inode, struct file *file) 0, init[cam->method][i].bytes, init[cam->method][i].size); if (err < 0) { - info("error during open sequence: %d", i); + dev_err(&cam->udev->dev, + "error during open sequence: %d\n", i); goto out; } } @@ -712,7 +714,7 @@ static int zr364xx_release(struct inode *inode, struct file *file) 0, init[i][cam->method].bytes, init[cam->method][i].size); if (err < 0) { - info("error during release sequence"); + dev_err(&udev->dev, "error during release sequence\n"); goto out; } } @@ -808,13 +810,14 @@ static int zr364xx_probe(struct usb_interface *intf, DBG("probing..."); - info(DRIVER_DESC " compatible webcam plugged"); - info("model %04x:%04x detected", udev->descriptor.idVendor, - udev->descriptor.idProduct); + dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); + dev_info(&intf->dev, "model %04x:%04x detected\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); if (cam == NULL) { - info("cam: out of memory !"); + dev_err(&udev->dev, "cam: out of memory !\n"); return -ENOMEM; } /* save the init method used by this camera */ @@ -822,7 +825,7 @@ static int zr364xx_probe(struct usb_interface *intf, cam->vdev = video_device_alloc(); if (cam->vdev == NULL) { - info("cam->vdev: out of memory !"); + dev_err(&udev->dev, "cam->vdev: out of memory !\n"); kfree(cam); return -ENOMEM; } @@ -834,7 +837,7 @@ static int zr364xx_probe(struct usb_interface *intf, cam->udev = udev; if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { - info("cam->buffer: out of memory !"); + dev_info(&udev->dev, "cam->buffer: out of memory !\n"); video_device_release(cam->vdev); kfree(cam); return -ENODEV; @@ -842,17 +845,17 @@ static int zr364xx_probe(struct usb_interface *intf, switch (mode) { case 1: - info("160x120 mode selected"); + dev_info(&udev->dev, "160x120 mode selected\n"); cam->width = 160; cam->height = 120; break; case 2: - info("640x480 mode selected"); + dev_info(&udev->dev, "640x480 mode selected\n"); cam->width = 640; cam->height = 480; break; default: - info("320x240 mode selected"); + dev_info(&udev->dev, "320x240 mode selected\n"); cam->width = 320; cam->height = 240; break; @@ -872,7 +875,7 @@ static int zr364xx_probe(struct usb_interface *intf, err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); if (err) { - info("video_register_device failed"); + dev_err(&udev->dev, "video_register_device failed\n"); video_device_release(cam->vdev); kfree(cam->buffer); kfree(cam); @@ -881,7 +884,8 @@ static int zr364xx_probe(struct usb_interface *intf, usb_set_intfdata(intf, cam); - info(DRIVER_DESC " controlling video device %d", cam->vdev->minor); + dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", + cam->vdev->minor); return 0; } @@ -891,7 +895,7 @@ static void zr364xx_disconnect(struct usb_interface *intf) struct zr364xx_camera *cam = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); dev_set_drvdata(&intf->dev, NULL); - info(DRIVER_DESC " webcam unplugged"); + dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); if (cam->vdev) video_unregister_device(cam->vdev); cam->vdev = NULL; @@ -920,16 +924,16 @@ static int __init zr364xx_init(void) int retval; retval = usb_register(&zr364xx_driver); if (retval) - info("usb_register failed!"); + printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n"); else - info(DRIVER_DESC " module loaded"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return retval; } static void __exit zr364xx_exit(void) { - info(DRIVER_DESC " module unloaded"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n"); usb_deregister(&zr364xx_driver); } -- GitLab From 79a9098ae47119fad54a3443e358f08e30b7d3a5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Oct 2008 04:21:24 -0300 Subject: [PATCH 4208/5416] V4L/DVB (9118): gspca: Set the vertical flip at streamon time in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 93b17340b7b..53cb82d9e7c 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1350,6 +1350,9 @@ static int sd_start(struct gspca_dev *gspca_dev) setbrightness(gspca_dev); setcontrast(gspca_dev); break; + case SENSOR_OV7630: + setvflip(sd); + /* fall thru */ default: /* OV76xx */ setbrightcont(gspca_dev); break; @@ -1582,7 +1585,8 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->vflip = val; - setvflip(sd); + if (gspca_dev->streaming) + setvflip(sd); return 0; } -- GitLab From 3145b8c1bfb96b02abf63dcd83ec7517c22cb574 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Oct 2008 04:22:10 -0300 Subject: [PATCH 4209/5416] V4L/DVB (9119): gspca: Don't destroy the URBs on disconnect. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 9db3d899aa6..c21af312ee7 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1903,17 +1903,12 @@ void gspca_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); - gspca_dev->present = 0; - mutex_lock(&gspca_dev->queue_lock); - mutex_lock(&gspca_dev->usb_lock); - gspca_dev->streaming = 0; - destroy_urbs(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - mutex_unlock(&gspca_dev->queue_lock); - /* We don't want people trying to open up the device */ video_unregister_device(&gspca_dev->vdev); + gspca_dev->present = 0; + gspca_dev->streaming = 0; + kref_put(&gspca_dev->kref, gspca_delete); PDEBUG(D_PROBE, "disconnect complete"); -- GitLab From e66c6419231cd61a1be04ef84bc6264556289e7d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Oct 2008 04:46:11 -0300 Subject: [PATCH 4210/5416] V4L/DVB (9120): gspca: sd_desc->start returns a value and static functions in m5602. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/m5602/m5602_bridge.h | 12 ------ drivers/media/video/gspca/m5602/m5602_core.c | 37 +++++++++++-------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h index 18ca19a9436..c786d7d3d44 100644 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -167,16 +167,4 @@ int m5602_read_bridge( int m5602_write_bridge( struct sd *sd, u8 address, u8 i2c_data); -int m5602_configure(struct gspca_dev *gspca_dev, - const struct usb_device_id *id); - -int m5602_init(struct gspca_dev *gspca_dev); - -void m5602_start_transfer(struct gspca_dev *gspca_dev); - -void m5602_stop_transfer(struct gspca_dev *gspca_dev); - -void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, - __u8 *data, int len); - #endif diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 47507350111..19d5e351ccc 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -35,16 +35,6 @@ static const __devinitdata struct usb_device_id m5602_table[] = { MODULE_DEVICE_TABLE(usb, m5602_table); -/* sub-driver description, the ctrl and nctrl is filled at probe time */ -static struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = m5602_configure, - .init = m5602_init, - .start = m5602_start_transfer, - .stopN = m5602_stop_transfer, - .pkt_scan = m5602_urb_complete -}; - /* Reads a byte from the m5602 */ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) { @@ -104,7 +94,7 @@ static void m5602_dump_bridge(struct sd *sd) info("Warning: The camera probably won't work until it's power cycled"); } -int m5602_probe_sensor(struct sd *sd) +static int m5602_probe_sensor(struct sd *sd) { /* Try the po1030 */ sd->sensor = &po1030; @@ -137,7 +127,10 @@ int m5602_probe_sensor(struct sd *sd) return -ENODEV; } -int m5602_init(struct gspca_dev *gspca_dev) +static int m5602_configure(struct gspca_dev *gspca_dev, + const struct usb_device_id *id); + +static int m5602_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int err; @@ -149,7 +142,7 @@ int m5602_init(struct gspca_dev *gspca_dev) return err; } -void m5602_start_transfer(struct gspca_dev *gspca_dev) +static int m5602_start_transfer(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 *buf = sd->gspca_dev.usb_buf; @@ -162,9 +155,11 @@ void m5602_start_transfer(struct gspca_dev *gspca_dev) 4, M5602_URB_MSG_TIMEOUT); PDEBUG(DBG_V4L2, "Transfer started"); + return 0; } -void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, +static void m5602_urb_complete(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, __u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; @@ -216,13 +211,23 @@ void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, } } -void m5602_stop_transfer(struct gspca_dev *gspca_dev) +static void m5602_stop_transfer(struct gspca_dev *gspca_dev) { /* Is there are a command to stop a data transfer? */ } +/* sub-driver description, the ctrl and nctrl is filled at probe time */ +static struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = m5602_configure, + .init = m5602_init, + .start = m5602_start_transfer, + .stopN = m5602_stop_transfer, + .pkt_scan = m5602_urb_complete +}; + /* this function is called at probe time */ -int m5602_configure(struct gspca_dev *gspca_dev, +static int m5602_configure(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { struct sd *sd = (struct sd *) gspca_dev; -- GitLab From 491831260e94475d14d5465b424df955d1f20aac Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Oct 2008 04:55:24 -0300 Subject: [PATCH 4211/5416] V4L/DVB (9121): gspca: Add the subdriver finepix in Kconfig and Makefile. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 9 +++++++++ drivers/media/video/gspca/Makefile | 2 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index aa7f3eb7ee7..f130a218f98 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -37,6 +37,15 @@ config USB_GSPCA_ETOMS To compile this driver as a module, choose M here: the module will be called gspca_etoms. +config USB_GSPCA_FINEPIX + tristate "Fujifilm FinePix USB V4L2 driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the FinePix chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_finepix. + config USB_GSPCA_MARS tristate "Mars USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b87322f4a48..22734f5a6c3 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o +obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o @@ -23,6 +24,7 @@ obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o gspca_main-objs := gspca.o gspca_conex-objs := conex.o gspca_etoms-objs := etoms.o +gspca_finepix-objs := finepix.o gspca_mars-objs := mars.o gspca_ov519-objs := ov519.o gspca_pac207-objs := pac207.o -- GitLab From 1abe4746ec11cff514c94fb11b3f3ac639fd200d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 6 Oct 2008 03:16:08 -0300 Subject: [PATCH 4212/5416] V4L/DVB (9122): gspca: Bad name of the sunplus subdriver in Kconfig. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index f130a218f98..655301837a3 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -163,8 +163,8 @@ config USB_GSPCA_STK014 To compile this driver as a module, choose M here: the module will be called gspca_stk014. -config USB_GSPCA_SPCA5XX - tristate "SPCA5xx USB Camera Driver" +config USB_GSPCA_SUNPLUS + tristate "SUNPLUS USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help Say Y here if you want support for cameras based on the Sunplus -- GitLab From 18f8fae19840a05a3a567e1251cf852bec5928b4 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Tue, 7 Oct 2008 03:02:59 -0300 Subject: [PATCH 4213/5416] V4L/DVB (9123): gspca: Add some lost controls to the s5k83a sensor. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/m5602/m5602_s5k83a.c | 92 ++++++++++++++++++- .../media/video/gspca/m5602/m5602_s5k83a.h | 58 ++++++++++-- 2 files changed, 140 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c index c1ff967b1c3..b4b33c2d049 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -321,7 +321,7 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) { - int err = 0; + int err; u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; @@ -331,3 +331,93 @@ int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } + +int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[1]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0x05; + err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + if (err < 0) + return err; + + err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + *val = (data[0] | 0x40) ? 1 : 0; + + return (err < 0) ? err : 0; +} + +int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[1]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0x05; + err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + if (err < 0) + return err; + + err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + if (err < 0) + return err; + + /* set or zero six bit, seven is hflip */ + data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK + : (data[0] & 0x80) | S5K83A_FLIP_MASK; + err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); + if (err < 0) + return err; + + data[0] = (val) ? 0x0b : 0x0a; + err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); + + return (err < 0) ? err : 0; +} + +int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u8 data[1]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0x05; + err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + if (err < 0) + return err; + + err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + *val = (data[0] | 0x80) ? 1 : 0; + + return (err < 0) ? err : 0; +} + +int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[1]; + struct sd *sd = (struct sd *) gspca_dev; + + data[0] = 0x05; + err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + if (err < 0) + return err; + + err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + if (err < 0) + return err; + + /* set or zero seven bit, six is vflip */ + data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK + : (data[0] & 0x40) | S5K83A_FLIP_MASK; + err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); + if (err < 0) + return err; + + data[0] = (val) ? 0x0a : 0x0b; + err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); + + return (err < 0) ? err : 0; +} diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h index a57f623d80c..833708eb5a4 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -21,15 +21,20 @@ #include "m5602_sensor.h" -#define S5K83A_PAGE_MAP 0xec -#define S5K83A_GAIN 0x18 +#define S5K83A_FLIP 0x01 +#define S5K83A_HFLIP_TUNE 0x03 +#define S5K83A_VFLIP_TUNE 0x05 #define S5K83A_WHITENESS 0x0a -#define S5K83A_BRIGHTNESS 0x1b +#define S5K83A_GAIN 0x18 +#define S5K83A_BRIGHTNESS 0x1b +#define S5K83A_PAGE_MAP 0xec #define S5K83A_DEFAULT_BRIGHTNESS 0x71 #define S5K83A_DEFAULT_WHITENESS 0x7e -#define S5K83A_DEFAULT_GAIN 0x00 -#define S5K83A_MAXIMUM_GAIN 0x3c +#define S5K83A_DEFAULT_GAIN 0x00 +#define S5K83A_MAXIMUM_GAIN 0x3c +#define S5K83A_FLIP_MASK 0x10 + /*****************************************************************************/ @@ -56,6 +61,11 @@ int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); + static struct m5602_sensor s5k83a = { .name = "S5K83A", @@ -65,7 +75,7 @@ static struct m5602_sensor s5k83a = { .read_sensor = s5k83a_read_sensor, .write_sensor = s5k83a_write_sensor, .i2c_slave_id = 0x5a, - .nctrls = 3, + .nctrls = 5, .ctrls = { { { @@ -107,7 +117,31 @@ static struct m5602_sensor s5k83a = { }, .set = s5k83a_set_gain, .get = s5k83a_get_gain - } + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k83a_set_hflip, + .get = s5k83a_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k83a_set_vflip, + .get = s5k83a_get_vflip + } }, .nmodes = 1, .modes = { @@ -121,7 +155,6 @@ static struct m5602_sensor s5k83a = { .bytesperline = M5602_DEFAULT_FRAME_WIDTH, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1 - } } }; @@ -438,7 +471,14 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00}, /* set default gain */ - {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN} + {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}, + + /* set default flip */ + {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00}, + {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00}, + {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00} + }; #endif -- GitLab From a2d7807788ff3213f540ba772f6c5c39548ae09f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 7 Oct 2008 08:42:30 -0300 Subject: [PATCH 4214/5416] V4L/DVB (9124): gspca: Bad name of the tv8532 subdriver in Kconfig. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 655301837a3..4d0817471c9 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -182,7 +182,7 @@ config USB_GSPCA_T613 To compile this driver as a module, choose M here: the module will be called gspca_t613. -config USB_GSPCA_TV8531 +config USB_GSPCA_TV8532 tristate "TV8532 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help -- GitLab From fadc79935cdb74e744c72e25f739a4acc9efabf5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 8 Oct 2008 08:06:08 -0300 Subject: [PATCH 4215/5416] V4L/DVB (9125): gspca: Big rewrite of t613 driver - separate functions for bridge and sensor exchanges - delays added after some exchanges - other sensor type Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 592 +++++++++++++++++-------------- 1 file changed, 326 insertions(+), 266 deletions(-) diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 7e435a36b05..b561f7c4f06 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -28,8 +28,6 @@ #include "gspca.h" -#define MAX_GAMMA 0x10 /* 0 to 15 */ - #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) MODULE_AUTHOR("Leandro Costantino "); @@ -49,6 +47,10 @@ struct sd { unsigned char whitebalance; unsigned char mirror; unsigned char effect; + + __u8 sensor; +#define SENSOR_TAS5130A 0 +#define SENSOR_OTHER 1 }; /* V4L2 controls supported by the driver */ @@ -83,9 +85,9 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 0, - .maximum = 0x0f, + .maximum = 14, .step = 1, - .default_value = 0x09, + .default_value = 8, }, .set = sd_setbrightness, .get = sd_getbrightness, @@ -118,16 +120,17 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, -#define SD_GAMMA 3 +#define GAMMA_MAX 16 +#define GAMMA_DEF 10 { { .id = V4L2_CID_GAMMA, /* (gamma on win) */ .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma (Untested)", + .name = "Gamma", .minimum = 0, - .maximum = MAX_GAMMA, + .maximum = GAMMA_MAX - 1, .step = 1, - .default_value = 0x09, + .default_value = GAMMA_DEF, }, .set = sd_setgamma, .get = sd_getgamma, @@ -197,7 +200,7 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Sharpness", .minimum = 0, - .maximum = MAX_GAMMA, /* 0 to 16 */ + .maximum = 15, .step = 1, .default_value = 0x06, }, @@ -258,7 +261,6 @@ static struct v4l2_pix_format vga_mode_t16[] = { .priv = 0}, }; -#define T16_OFFSET_DATA 631 #define MAX_EFFECTS 7 /* easily done by soft, this table could be removed, * i keep it here just in case */ @@ -272,87 +274,87 @@ static const __u8 effects_table[MAX_EFFECTS][6] = { {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ }; -static const __u8 gamma_table[MAX_GAMMA][34] = { - {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, +static const __u8 gamma_table[GAMMA_MAX][34] = { + {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */ 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75, - 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD, - 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4, - 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7, + {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */ + 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad, + 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4, + 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B, - 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6, - 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0, - 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6, + {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */ + 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6, + 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0, + 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, - 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E, - 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB, - 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, + {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */ + 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e, + 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb, + 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55, + {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */ 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, - 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6, - 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4, + 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6, + 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48, + {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */ 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, - 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE, - 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3, + 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe, + 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, + {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */ 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, - 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70, - 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0, - 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0, + {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */ + 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70, + 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0, + 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, - 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79, - 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6, - 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0, + {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */ + 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79, + 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6, + 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, + {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */ 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44, - 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E, - 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4, - 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0, + {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */ + 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e, + 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4, + 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52, - 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B, - 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB, - 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, + {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */ + 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B, + 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb, + 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E, - 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8, - 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3, - 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6, - 0xA0, 0xFF}, - {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83, - 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7, - 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC, - 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9, + {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */ + 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8, + 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3, + 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A, - 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6, - 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3, - 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA, + {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */ + 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7, + 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc, + 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9, 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7, - 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8, - 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED, - 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC, - 0xA0, 0xFF} + {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */ + 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6, + 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3, + 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa, + 0xa0, 0xff}, + {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */ + 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8, + 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed, + 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc, + 0xa0, 0xff} }; static const __u8 tas5130a_sensor_init[][8] = { @@ -364,7 +366,7 @@ static const __u8 tas5130a_sensor_init[][8] = { }; /* read 1 byte */ -static int reg_r_1(struct gspca_dev *gspca_dev, +static int reg_r(struct gspca_dev *gspca_dev, __u16 index) { usb_control_msg(gspca_dev->dev, @@ -378,26 +380,26 @@ static int reg_r_1(struct gspca_dev *gspca_dev, } static void reg_w(struct gspca_dev *gspca_dev, - __u16 value, - __u16 index, - const __u8 *buffer, __u16 len) + __u16 index) +{ + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0, index, + NULL, 0, 500); +} + +static void i2c_w(struct gspca_dev *gspca_dev, + const __u8 *buffer, __u16 len) { - if (buffer == NULL) { - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, - NULL, 0, 500); - return; - } if (len <= USB_BUF_SZ) { memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, + 0x01, 0, gspca_dev->usb_buf, len, 500); } else { __u8 *tmpbuf; @@ -408,12 +410,56 @@ static void reg_w(struct gspca_dev *gspca_dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, + 0x01, 0, tmpbuf, len, 500); kfree(tmpbuf); } } +static void other_sensor_init(struct gspca_dev *gspca_dev) +{ + int i; + const __u8 *p; + __u8 byte; + __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; + static const __u8 sensor_init[] = { + 0xdf, 0x6d, + 0xdd, 0x18, + 0x5a, 0xe0, + 0x5c, 0x07, + 0x5d, 0xb0, + 0x5e, 0x1e, + 0x60, 0x71, + 0xef, 0x00, + 0xe9, 0x00, + 0xea, 0x00, + 0x90, 0x24, + 0x91, 0xb2, + 0x82, 0x32, + 0xfd, 0x00, + 0xfd, 0x01, + 0xfd, 0x41, + 0x00 /* table end */ + }; + + p = sensor_init; + while (*p != 0) { + val[1] = *p++; + val[3] = *p++; + if (*p == 0) + reg_w(gspca_dev, 0x3c80); + i2c_w(gspca_dev, val, sizeof val); + i = 4; + while (--i >= 0) { + msleep(15); + byte = reg_r(gspca_dev, 0x60); + if (!(byte & 0x01)) + break; + } + } + reg_w(gspca_dev, 0x3c80); +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -430,7 +476,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; - sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value; + sd->gamma = GAMMA_DEF; sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; @@ -439,27 +485,37 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -static int init_default_parameters(struct gspca_dev *gspca_dev) +static void setgamma(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(D_CONF, "Gamma: %d", sd->gamma); + i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { /* some of this registers are not really neded, because * they are overriden by setbrigthness, setcontrast, etc, * but wont hurt anyway, and can help someone with similar webcam * to see the initial parameters.*/ - int i = 0; - __u8 test_byte; + struct sd *sd = (struct sd *) gspca_dev; + int i; + __u8 byte, test_byte; static const __u8 read_indexs[] = { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; - static const __u8 n1[6] = + static const __u8 n1[] = {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; - static const __u8 n2[2] = + static const __u8 n2[] = {0x08, 0x00}; - static const __u8 nset[6] = - { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; - static const __u8 n3[6] = + static const __u8 nset[] = + { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; + static const __u8 n3[] = {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; - static const __u8 n4[0x46] = + static const __u8 n4[] = {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, @@ -469,33 +525,26 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; - static const __u8 nset4[18] = { + static const __u8 nset4[] = { 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, 0xe8, 0xe0 }; /* ojo puede ser 0xe6 en vez de 0xe9 */ - static const __u8 nset2[20] = { + static const __u8 nset2[] = { 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, 0xd8, 0xc8, 0xd9, 0xfc }; - static const __u8 missing[8] = + static const __u8 missing[] = { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 }; - static const __u8 nset3[18] = { + static const __u8 nset3[] = { 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, 0xcf, 0xe0 }; - static const __u8 nset5[4] = - { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ - static const __u8 nset6[34] = { - 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54, - 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, - 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca, - 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2, - 0xa0, 0xff - }; /* Gamma */ + static const __u8 nset5[] = + { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ static const __u8 nset7[4] = { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */ static const __u8 nset9[4] = @@ -505,57 +554,74 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) static const __u8 nset10[6] = { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 }; - reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06); - reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06); - reg_r_1(gspca_dev, 0x0063); - reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02); + byte = reg_r(gspca_dev, 0x06); + test_byte = reg_r(gspca_dev, 0x07); + if (byte == 0x08 && test_byte == 0x07) { + PDEBUG(D_CONF, "other sensor"); + sd->sensor = SENSOR_OTHER; + } else { + PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte); + sd->sensor = SENSOR_TAS5130A; + } + + i2c_w(gspca_dev, n1, sizeof n1); + test_byte = 0; + i = 5; + while (--i >= 0) { + i2c_w(gspca_dev, nset, sizeof nset); + msleep(5); + test_byte = reg_r(gspca_dev, 0x0063); + msleep(100); + if (test_byte == 0x17) + break; /* OK */ + } + if (i < 0) { + err("Bad sensor reset %02x", test_byte); +/* return -EIO; */ +/*fixme: test - continue */ + } + i2c_w(gspca_dev, n2, sizeof n2); + i = 0; while (read_indexs[i] != 0x00) { - test_byte = reg_r_1(gspca_dev, read_indexs[i]); - PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i], + test_byte = reg_r(gspca_dev, read_indexs[i]); + PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i], test_byte); i++; } - reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06); - reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46); - reg_r_1(gspca_dev, 0x0080); - reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0); - reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); - reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); - reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); - reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); - reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); - reg_w(gspca_dev, 0x00, 0x338e, NULL, 0); - reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04); - reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0); - reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22); - reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0); - reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); - - reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08); - - reg_w(gspca_dev, 0x00, 0x2087, NULL, 0); - reg_w(gspca_dev, 0x00, 0x2088, NULL, 0); - reg_w(gspca_dev, 0x00, 0x2089, NULL, 0); - - reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04); - reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06); - reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06); - reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04); - - reg_w(gspca_dev, 0x00, 0x2880, NULL, 0); - reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); - reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); - reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); - - return 0; -} + i2c_w(gspca_dev, n3, sizeof n3); + i2c_w(gspca_dev, n4, sizeof n4); + reg_r(gspca_dev, 0x0080); + reg_w(gspca_dev, 0x2c80); + i2c_w(gspca_dev, nset2, sizeof nset2); + i2c_w(gspca_dev, nset3, sizeof nset3); + i2c_w(gspca_dev, nset4, sizeof nset4); + reg_w(gspca_dev, 0x3880); + reg_w(gspca_dev, 0x3880); + reg_w(gspca_dev, 0x338e); + i2c_w(gspca_dev, nset5, sizeof nset5); + reg_w(gspca_dev, 0x00a9); + setgamma(gspca_dev); + reg_w(gspca_dev, 0x86bb); + reg_w(gspca_dev, 0x4aa6); + + i2c_w(gspca_dev, missing, sizeof missing); + + reg_w(gspca_dev, 0x2087); + reg_w(gspca_dev, 0x2088); + reg_w(gspca_dev, 0x2089); + + i2c_w(gspca_dev, nset7, sizeof nset7); + i2c_w(gspca_dev, nset10, sizeof nset10); + i2c_w(gspca_dev, nset8, sizeof nset8); + i2c_w(gspca_dev, nset9, sizeof nset9); + + reg_w(gspca_dev, 0x2880); + i2c_w(gspca_dev, nset2, sizeof nset2); + i2c_w(gspca_dev, nset3, sizeof nset3); + i2c_w(gspca_dev, nset4, sizeof nset4); -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - init_default_parameters(gspca_dev); return 0; } @@ -563,37 +629,36 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned int brightness; - __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 }; - brightness = sd->brightness; + __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 }; + brightness = sd->brightness; if (brightness < 7) { - set6[3] = 0x70 - (brightness * 0xa); + set6[3] = 0x70 - brightness * 0x10; } else { set6[1] = 0x24; - set6[3] = 0x00 + ((brightness - 7) * 0xa); + set6[3] = 0x00 + ((brightness - 7) * 0x10); } - reg_w(gspca_dev, 0x01, 0x0000, set6, 4); + i2c_w(gspca_dev, set6, sizeof set6); } static void setflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 flipcmd[8] = - { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 }; + {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; - if (sd->mirror == 1) + if (sd->mirror) flipcmd[3] = 0x01; - reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8); + i2c_w(gspca_dev, flipcmd, sizeof flipcmd); } static void seteffect(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06); + i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]); if (sd->effect == 1 || sd->effect == 5) { PDEBUG(D_CONF, "This effect have been disabled for webcam \"safety\""); @@ -601,9 +666,9 @@ static void seteffect(struct gspca_dev *gspca_dev) } if (sd->effect == 1 || sd->effect == 4) - reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); + reg_w(gspca_dev, 0x4aa6); else - reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0); + reg_w(gspca_dev, 0xfaa6); } static void setwhitebalance(struct gspca_dev *gspca_dev) @@ -616,7 +681,7 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) if (sd->whitebalance == 1) white_balance[7] = 0x3c; - reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8); + i2c_w(gspca_dev, white_balance, sizeof white_balance); } static void setlightfreq(struct gspca_dev *gspca_dev) @@ -627,21 +692,21 @@ static void setlightfreq(struct gspca_dev *gspca_dev) if (sd->freq == 2) /* 60hz */ freq[1] = 0x00; - reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4); + i2c_w(gspca_dev, freq, sizeof freq); } static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned int contrast = sd->contrast; - __u16 reg_to_write = 0x00; + __u16 reg_to_write; if (contrast < 7) reg_to_write = 0x8ea9 - (0x200 * contrast); else reg_to_write = (0x00a9 + ((contrast - 7) * 0x200)); - reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); + reg_w(gspca_dev, reg_to_write); } static void setcolors(struct gspca_dev *gspca_dev) @@ -650,11 +715,7 @@ static void setcolors(struct gspca_dev *gspca_dev) __u16 reg_to_write; reg_to_write = 0xc0bb + sd->colors * 0x100; - reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); -} - -static void setgamma(struct gspca_dev *gspca_dev) -{ + reg_w(gspca_dev, reg_to_write); } static void setsharpness(struct gspca_dev *gspca_dev) @@ -664,7 +725,99 @@ static void setsharpness(struct gspca_dev *gspca_dev) reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; - reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); + reg_w(gspca_dev, reg_to_write); +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, mode; + static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; + __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; + static const __u8 t3[] = + { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, + 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; + static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; + + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; + switch (mode) { + case 1: /* 352x288 */ + t2[1] = 0x40; + break; + case 2: /* 320x240 */ + t2[1] = 0x10; + break; + case 3: /* 176x144 */ + t2[1] = 0x50; + break; + case 4: /* 160x120 */ + t2[1] = 0x20; + break; + default: /* 640x480 (0x00) */ + break; + } + + if (sd->sensor == SENSOR_TAS5130A) { + i = 0; + while (tas5130a_sensor_init[i][0] != 0) { + i2c_w(gspca_dev, tas5130a_sensor_init[i], + sizeof tas5130a_sensor_init[0]); + i++; + } + reg_w(gspca_dev, 0x3c80); + /* just in case and to keep sync with logs (for mine) */ + i2c_w(gspca_dev, tas5130a_sensor_init[3], + sizeof tas5130a_sensor_init[0]); + reg_w(gspca_dev, 0x3c80); + } else { + other_sensor_init(gspca_dev); + } + /* just in case and to keep sync with logs (for mine) */ + i2c_w(gspca_dev, t1, sizeof t1); + i2c_w(gspca_dev, t2, sizeof t2); + reg_r(gspca_dev, 0x0012); + i2c_w(gspca_dev, t3, sizeof t3); + reg_w(gspca_dev, 0x0013); + i2c_w(gspca_dev, t4, sizeof t4); + /* restart on each start, just in case, sometimes regs goes wrong + * when using controls from app */ + setbrightness(gspca_dev); + setcontrast(gspca_dev); + setcolors(gspca_dev); + return 0; +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + static __u8 ffd9[] = { 0xff, 0xd9 }; + + if (data[0] == 0x5a) { + /* Control Packet, after this came the header again, + * but extra bytes came in the packet before this, + * sometimes an EOF arrives, sometimes not... */ + return; + } + data += 2; + len -= 2; + if (data[0] == 0xff && data[1] == 0xd8) { + /* extra bytes....., could be processed too but would be + * a waste of time, right now leave the application and + * libjpeg do it for ourserlves.. */ + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + ffd9, 2); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + return; + } + + if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { + /* Just in case, i have seen packets with the marker, + * other's do not include it... */ + len -= 2; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) @@ -788,6 +941,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; + *val = sd->gamma; return 0; } @@ -835,9 +989,9 @@ static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val) sd->autogain = val; if (val != 0) - reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0); + reg_w(gspca_dev, 0xf48e); else - reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0); + reg_w(gspca_dev, 0xb48e); return 0; } @@ -849,100 +1003,6 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_start(struct gspca_dev *gspca_dev) -{ - int mode; - - static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; - __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; - static const __u8 t3[] = - { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, - 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; - static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; - - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; - switch (mode) { - case 1: /* 352x288 */ - t2[1] = 0x40; - break; - case 2: /* 320x240 */ - t2[1] = 0x10; - break; - case 3: /* 176x144 */ - t2[1] = 0x50; - break; - case 4: /* 160x120 */ - t2[1] = 0x20; - break; - default: /* 640x480 (0x00) */ - break; - } - - reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8); - reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8); - reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8); - reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); - reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); - /* just in case and to keep sync with logs (for mine) */ - reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); - reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); - /* just in case and to keep sync with logs (for mine) */ - reg_w(gspca_dev, 0x01, 0x0000, t1, 4); - reg_w(gspca_dev, 0x01, 0x0000, t2, 6); - reg_r_1(gspca_dev, 0x0012); - reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10); - reg_w(gspca_dev, 0x00, 0x0013, NULL, 0); - reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4); - /* restart on each start, just in case, sometimes regs goes wrong - * when using controls from app */ - setbrightness(gspca_dev); - setcontrast(gspca_dev); - setcolors(gspca_dev); - return 0; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - int sof = 0; - static __u8 ffd9[] = { 0xff, 0xd9 }; - - if (data[0] == 0x5a) { - /* Control Packet, after this came the header again, - * but extra bytes came in the packet before this, - * sometimes an EOF arrives, sometimes not... */ - return; - } - - if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { - /* Just in case, i have seen packets with the marker, - * other's do not include it... */ - data += 2; - len -= 4; - } else if (data[2] == 0xff && data[3] == 0xd8) { - sof = 1; - data += 2; - len -= 2; - } else { - data += 2; - len -= 2; - } - - if (sof) { - /* extra bytes....., could be processed too but would be - * a waste of time, right now leave the application and - * libjpeg do it for ourserlves.. */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - ffd9, 2); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); - return; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); -} - static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { -- GitLab From f1918fa284afaa46201b9c20a7bbeacd8db0c977 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 9 Oct 2008 03:14:03 -0300 Subject: [PATCH 4216/5416] V4L/DVB (9126): gspca: Fix some compilation warnings in m5602. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_mt9m111.c | 2 +- drivers/media/video/gspca/m5602/m5602_ov9650.h | 4 +++- drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c index ea2250217b0..566d4925a0e 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -69,7 +69,7 @@ sensor_found: int mt9m111_init(struct sd *sd) { - int i, err; + int i, err = 0; /* Init the sensor */ for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) { diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h index 486ea337a8b..2f29cb056f3 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -466,7 +466,9 @@ static const unsigned char power_down_ov9650[][3] = /* Vertically and horizontally flips the image if matched, needed for machines where the sensor is mounted upside down */ -static const struct dmi_system_id ov9650_flip_dmi_table[] = { +static + const + struct dmi_system_id ov9650_flip_dmi_table[] = { { .ident = "ASUS A6VC", .matches = { diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 1e4213a7321..bb7f7e3e90a 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -339,7 +339,9 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} }; -static const struct dmi_system_id s5k4aa_vflip_dmi_table[] = { +static + const + struct dmi_system_id s5k4aa_vflip_dmi_table[] = { { .ident = "Fujitsu-Siemens Amilo Xa 2528", .matches = { -- GitLab From 9eee4fb69ecbe6a8a25378e801a3621ef0146fa3 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 4 Oct 2008 20:28:40 -0300 Subject: [PATCH 4217/5416] V4L/DVB (9131): cx18: Add entries for the Leadtek PVR2100 and Toshiba Qosmio DVB-T/Analog cx18: Add entries for the Leadtek PVR2100 and Toshiba Qosmio DVB-T/Analog capture cards. Both cards are hybrids cards, but no digital capture functionality has been added yet. These entries are a first guess at the card entries to get analog working, given the information available. Terry Wu provided a pointer to information for the PVR2100. Martin Juhl , an owner of the Toshiba DVB-T/Analog tuner card, provided the DDR timing information from his Windows inf file. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 99 ++++++++++++++++++++++++++ drivers/media/video/cx18/cx18-driver.c | 2 + drivers/media/video/cx18/cx18-driver.h | 6 +- 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 3cb9734ec07..5efe01ebe9d 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -292,12 +292,111 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = { /* ------------------------------------------------------------------------- */ +/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */ + +static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = { + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 }, + { 0, 0, 0 } +}; + +static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { + .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT, + .name = "Toshiba Qosmio DVB-T/Analog", + .comment = "Experimenters and photos needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_CX23418, + .hw_all = CX18_HW_TUNER, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + }, + .tuners = { + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, + }, + .ddr = { + .chip_config = 0x202, + .refresh = 0x3bb, + .timing1 = 0x33320a63, + .timing2 = 0x0a, + .tune_lane = 0, + .initial_emrs = 0x42, + }, + .xceive_pin = 15, + .pci_list = cx18_pci_toshiba_qosmio_dvbt, + .i2c = &cx18_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + +/* Leadtek WinFast PVR2100 */ + +static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = { + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, + { 0, 0, 0 } +}; + +static const struct cx18_card cx18_card_leadtek_pvr2100 = { + .type = CX18_CARD_LEADTEK_PVR2100, + .name = "Leadtek WinFast PVR2100", + .comment = "Experimenters and photos needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_CX23418, + .hw_muxer = CX18_HW_GPIO, + .hw_all = CX18_HW_TUNER | CX18_HW_GPIO, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + }, + .tuners = { + /* XC3028 tuner */ + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, + }, + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, + .ddr = { + /* + * Pointer to proper DDR config values provided by + * Terry Wu + */ + .chip_config = 0x303, + .refresh = 0x3bb, + .timing1 = 0x24220e83, + .timing2 = 0x1f, + .tune_lane = 0, + .initial_emrs = 0x2, + }, + .gpio_init.initial_value = 0x6, + .gpio_init.direction = 0x7, + .gpio_audio_input = { .mask = 0x7, + .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, + .xceive_pin = 15, + .pci_list = cx18_pci_leadtek_pvr2100, + .i2c = &cx18_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + static const struct cx18_card *cx18_card_list[] = { &cx18_card_hvr1600_esmt, &cx18_card_hvr1600_samsung, &cx18_card_h900, &cx18_card_mpc718, &cx18_card_cnxt_raptor_pal, + &cx18_card_toshiba_qosmio_dvbt, + &cx18_card_leadtek_pvr2100, }; const struct cx18_card *cx18_get_card(u16 index) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index df5531709ae..6bf9ac8c4e7 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -130,6 +130,8 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 3 = Compro VideoMate H900\n" "\t\t\t 4 = Yuan MPC718\n" "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" + "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" + "\t\t\t 7 = Leadtek WinFast PVR2100\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 80f5f563d4f..fa8be0731a3 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -79,7 +79,9 @@ #define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ -#define CX18_CARD_LAST 4 +#define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ +#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ +#define CX18_CARD_LAST 6 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 @@ -99,6 +101,8 @@ #define CX18_PCI_ID_COMPRO 0x185b #define CX18_PCI_ID_YUAN 0x12ab #define CX18_PCI_ID_CONEXANT 0x14f1 +#define CX18_PCI_ID_TOSHIBA 0x1179 +#define CX18_PCI_ID_LEADTEK 0x107D /* ======================================================================== */ /* ========================== START USER SETTABLE DMA VARIABLES =========== */ -- GitLab From e86a93dc3c870c412592c1f298c1425d80c58c6e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 4 Oct 2008 19:09:41 -0300 Subject: [PATCH 4218/5416] V4L/DVB (9132): cx18: Fix warning message for DMA done notification for inactive stream. cx18: Fix warning message for DMA done notification for inactive stream. The warning message would always gripe that the radio stream was to blame, which was misleading and wrong (/dev/radioN nodes never transfer data). Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 55a50a2b048..360330f5463 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -49,8 +49,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) break; } if (i == CX18_MAX_STREAMS) { - CX18_WARN("DMA done for unknown handle %d for stream %s\n", - handle, s->name); + CX18_WARN("Got DMA done notification for unknown/inactive" + " handle %d\n", handle); mb->error = CXERR_NOT_OPEN; mb->cmd = 0; cx18_mb_ack(cx, mb); -- GitLab From dd89601d47e2eeab7c17b25f2549444751bcffe4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 4 Oct 2008 08:36:54 -0300 Subject: [PATCH 4219/5416] V4L/DVB (9133): v4l: disconnect kernel number from minor The v4l core creates four different video devices (video, vbi, radio, vtx) and each has its own range of minor numbers. However, modern devices keep increasing the number of devices that they need so a maximum of 64 video devices will not be enough in the future. In addition this scheme makes it very hard to add new device types. This patch disconnects the kernel number allocation (e.g. video0, video1, etc.) from the actual minor number (just pick the first free minor). This allows for much more flexibility in the future. However, it does require the use of udev. For those who cannot use udev a new CONFIG option was created that changes the allocation scheme back to the old behavior. Thanks to Greg KH for suggesting this approach during the 2008 LPC. In addition, several bugs were fixed in the ivtv and cx18 drivers: these drivers try to allocate specific kernel numbers but that scheme contained a bug which caused what should have been e.g. video17 to appear as e.g. video2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 9 +++ drivers/media/video/cx18/cx18-driver.c | 4 +- drivers/media/video/cx18/cx18-streams.c | 41 +++++----- drivers/media/video/em28xx/em28xx-video.c | 8 +- drivers/media/video/ivtv/ivtv-driver.c | 6 +- drivers/media/video/ivtv/ivtv-streams.c | 40 +++++----- drivers/media/video/v4l2-dev.c | 96 +++++++++++++++-------- include/media/v4l2-dev.h | 12 +-- 8 files changed, 128 insertions(+), 88 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index e28e292fe20..2dce16f863b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -72,6 +72,15 @@ config VIDEO_ADV_DEBUG V4L devices. In doubt, say N. +config VIDEO_FIXED_MINOR_RANGES + bool "Enable old-style fixed minor ranges for video devices" + default n + ---help--- + Say Y here to enable the old-style fixed-range minor assignments. + Only useful if you rely on the old behavior and use mknod instead of udev. + + When in doubt, say N. + config VIDEO_HELPER_CHIPS_AUTO bool "Autoselect pertinent encoders/decoders and other helper chips" default y diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 6bf9ac8c4e7..085121c2b47 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -175,7 +175,7 @@ MODULE_PARM_DESC(enc_pcm_buffers, "Encoder PCM buffers (in MB)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); -MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card"); +MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); MODULE_AUTHOR("Hans Verkuil"); MODULE_DESCRIPTION("CX23418 driver"); @@ -959,7 +959,7 @@ static int module_start(void) /* Validate parameters */ if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { - printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n", + printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n", CX18_MAX_CARDS - 1); return -1; } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index c752a6a4dbd..0c8e7542cf6 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -57,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = { static struct { const char *name; int vfl_type; - int minor_offset; + int num_offset; int dma; enum v4l2_buf_type buf_type; struct file_operations *fops; @@ -144,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; u32 cap = cx->v4l2_cap; - int minor_offset = cx18_stream_info[type].minor_offset; - int minor; + int num_offset = cx18_stream_info[type].num_offset; + int num = cx->num + cx18_first_minor + num_offset; /* These four fields are always initialized. If v4l2dev == NULL, then this stream is not in use. In that case no other fields but these @@ -164,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type) !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) return 0; - /* card number + user defined offset + device offset */ - minor = cx->num + cx18_first_minor + minor_offset; - /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (cx18_stream_info[type].dma != PCI_DMA_NONE && @@ -177,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) cx18_stream_init(cx, type); - if (minor_offset == -1) + if (num_offset == -1) return 0; /* allocate and initialize the v4l2 video device structure */ @@ -191,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", cx->num); - s->v4l2dev->minor = minor; + s->v4l2dev->num = num; s->v4l2dev->parent = &cx->dev->dev; s->v4l2dev->fops = cx18_stream_info[type].fops; s->v4l2dev->release = video_device_release; @@ -227,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; int vfl_type = cx18_stream_info[type].vfl_type; - int minor; + int num; /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? * We need a VFL_TYPE_TS defined. @@ -245,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type) if (s->v4l2dev == NULL) return 0; - minor = s->v4l2dev->minor; + num = s->v4l2dev->num; + /* card number + user defined offset + device offset */ + if (type != CX18_ENC_STREAM_TYPE_MPG) { + struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; + + if (s_mpg->v4l2dev) + num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset; + } /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, minor) && - video_register_device(s->v4l2dev, vfl_type, -1)) { - CX18_ERR("Couldn't register v4l2 device for %s minor %d\n", - s->name, minor); + if (video_register_device(s->v4l2dev, vfl_type, num)) { + CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", + s->name, num); video_device_release(s->v4l2dev); s->v4l2dev = NULL; return -ENOMEM; } - minor = s->v4l2dev->minor; + num = s->v4l2dev->num; switch (vfl_type) { case VFL_TYPE_GRABBER: CX18_INFO("Registered device video%d for %s (%d MB)\n", - minor, s->name, cx->options.megabytes[type]); + num, s->name, cx->options.megabytes[type]); break; case VFL_TYPE_RADIO: CX18_INFO("Registered device radio%d for %s\n", - minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); + num, s->name); break; case VFL_TYPE_VBI: if (cx->options.megabytes[type]) CX18_INFO("Registered device vbi%d for %s (%d MB)\n", - minor - MINOR_VFL_TYPE_VBI_MIN, + num, s->name, cx->options.megabytes[type]); else CX18_INFO("Registered device vbi%d for %s\n", - minor - MINOR_VFL_TYPE_VBI_MIN, s->name); + num, s->name); break; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 50d2c7a9b3c..c53649e5315 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1600,8 +1600,7 @@ static void em28xx_release_resources(struct em28xx *dev) /*FIXME: I2C IR should be disconnected */ em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", - dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, - dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); + dev->vdev->num, dev->vbi_dev->num); list_del(&dev->devlist); if (dev->sbutton_input_dev) em28xx_deregister_snapshot_button(dev); @@ -2073,8 +2072,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_mux(dev, 0); em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, - dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); + dev->vdev->num, dev->vbi_dev->num); mutex_lock(&em28xx_extension_devlist_lock); if (!list_empty(&em28xx_extension_devlist)) { @@ -2274,7 +2272,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_warn ("device /dev/video%d is open! Deregistration and memory " "deallocation are deferred on close.\n", - dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); + dev->vdev->num); dev->state |= DEV_MISCONFIGURED; em28xx_uninit_isoc(dev); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 6b04930d127..7aa61b61749 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -61,14 +61,14 @@ #include "tuner-xc2028.h" /* var to keep track of the number of array elements in use */ -int ivtv_cards_active = 0; +int ivtv_cards_active; /* If you have already X v4l cards, then set this to X. This way the device numbers stay matched. Example: you have a WinTV card without radio and a PVR-350 with. Normally this would give a video1 device together with a radio0 device for the PVR. By setting this to 1 you ensure that radio0 is now also radio1. */ -int ivtv_first_minor = 0; +int ivtv_first_minor; /* Master variable for all ivtv info */ struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; @@ -251,7 +251,7 @@ MODULE_PARM_DESC(newi2c, "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" "\t\t\tDefault is autodetect"); -MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card"); +MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card"); MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); MODULE_DESCRIPTION("CX23415/CX23416 driver"); diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 730e85d86fc..24273fbea47 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = { static struct { const char *name; int vfl_type; - int minor_offset; + int num_offset; int dma, pio; enum v4l2_buf_type buf_type; const struct file_operations *fops; @@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type) static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; - int minor_offset = ivtv_stream_info[type].minor_offset; - int minor; + int num_offset = ivtv_stream_info[type].num_offset; + int num = itv->num + ivtv_first_minor + num_offset; /* These four fields are always initialized. If v4l2dev == NULL, then this stream is not in use. In that case no other fields but these @@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; - /* card number + user defined offset + device offset */ - minor = itv->num + ivtv_first_minor + minor_offset; - /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (ivtv_stream_info[type].dma != PCI_DMA_NONE && @@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", itv->num, s->name); - s->v4l2dev->minor = minor; + s->v4l2dev->num = num; s->v4l2dev->parent = &itv->dev->dev; s->v4l2dev->fops = ivtv_stream_info[type].fops; s->v4l2dev->release = video_device_release; @@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int vfl_type = ivtv_stream_info[type].vfl_type; - int minor; + int num; if (s->v4l2dev == NULL) return 0; - minor = s->v4l2dev->minor; + num = s->v4l2dev->num; + /* card number + user defined offset + device offset */ + if (type != IVTV_ENC_STREAM_TYPE_MPG) { + struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; + + if (s_mpg->v4l2dev) + num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; + } + /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, minor) && - video_register_device(s->v4l2dev, vfl_type, -1)) { - IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", - s->name, minor); + if (video_register_device(s->v4l2dev, vfl_type, num)) { + IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", + s->name, num); video_device_release(s->v4l2dev); s->v4l2dev = NULL; return -ENOMEM; } + num = s->v4l2dev->num; switch (vfl_type) { case VFL_TYPE_GRABBER: IVTV_INFO("Registered device video%d for %s (%d kB)\n", - s->v4l2dev->minor, s->name, itv->options.kilobytes[type]); + num, s->name, itv->options.kilobytes[type]); break; case VFL_TYPE_RADIO: IVTV_INFO("Registered device radio%d for %s\n", - s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); + num, s->name); break; case VFL_TYPE_VBI: if (itv->options.kilobytes[type]) IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", - s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, - s->name, itv->options.kilobytes[type]); + num, s->name, itv->options.kilobytes[type]); else IVTV_INFO("Registered device vbi%d for %s\n", - s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); + num, s->name); break; } return 0; diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 7addf2fd55d..ccd6566a515 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -65,6 +65,7 @@ static struct device_attribute video_device_attrs[] = { */ static struct video_device *video_device[VIDEO_NUM_DEVICES]; static DEFINE_MUTEX(videodev_lock); +static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); struct video_device *video_device_alloc(void) { @@ -99,6 +100,7 @@ static void v4l2_chardev_release(struct kobject *kobj) /* Free up this device for reuse */ video_device[vfd->minor] = NULL; + clear_bit(vfd->num, video_nums[vfd->vfl_type]); mutex_unlock(&videodev_lock); /* Release the character device */ @@ -217,10 +219,10 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int index) { int i = 0; - int base; - int end; int ret; - char *name_base; + int minor_offset = 0; + int minor_cnt = VIDEO_NUM_DEVICES; + const char *name_base; void *priv = video_get_drvdata(vfd); /* the release callback MUST be present */ @@ -231,23 +233,15 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, switch (type) { case VFL_TYPE_GRABBER: - base = MINOR_VFL_TYPE_GRABBER_MIN; - end = MINOR_VFL_TYPE_GRABBER_MAX+1; name_base = "video"; break; case VFL_TYPE_VTX: - base = MINOR_VFL_TYPE_VTX_MIN; - end = MINOR_VFL_TYPE_VTX_MAX+1; name_base = "vtx"; break; case VFL_TYPE_VBI: - base = MINOR_VFL_TYPE_VBI_MIN; - end = MINOR_VFL_TYPE_VBI_MAX+1; name_base = "vbi"; break; case VFL_TYPE_RADIO: - base = MINOR_VFL_TYPE_RADIO_MIN; - end = MINOR_VFL_TYPE_RADIO_MAX+1; name_base = "radio"; break; default: @@ -256,31 +250,70 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, return -EINVAL; } + vfd->vfl_type = type; + +#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES + /* Keep the ranges for the first four types for historical + * reasons. + * Newer devices (not yet in place) should use the range + * of 128-191 and just pick the first free minor there + * (new style). */ + switch (type) { + case VFL_TYPE_GRABBER: + minor_offset = 0; + minor_cnt = 64; + break; + case VFL_TYPE_RADIO: + minor_offset = 64; + minor_cnt = 64; + break; + case VFL_TYPE_VTX: + minor_offset = 192; + minor_cnt = 32; + break; + case VFL_TYPE_VBI: + minor_offset = 224; + minor_cnt = 32; + break; + default: + minor_offset = 128; + minor_cnt = 64; + break; + } +#endif + /* Initialize the character device */ cdev_init(&vfd->cdev, vfd->fops); vfd->cdev.owner = vfd->fops->owner; /* pick a minor number */ mutex_lock(&videodev_lock); - if (nr >= 0 && nr < end-base) { - /* use the one the driver asked for */ - i = base + nr; - if (NULL != video_device[i]) { - mutex_unlock(&videodev_lock); - return -ENFILE; - } - } else { - /* use first free */ - for (i = base; i < end; i++) - if (NULL == video_device[i]) - break; - if (i == end) { - mutex_unlock(&videodev_lock); - return -ENFILE; - } + nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); + if (nr == minor_cnt) + nr = find_first_zero_bit(video_nums[type], minor_cnt); + if (nr == minor_cnt) { + printk(KERN_ERR "could not get a free kernel number\n"); + mutex_unlock(&videodev_lock); + return -ENFILE; } - video_device[i] = vfd; - vfd->vfl_type = type; - vfd->minor = i; +#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES + /* 1-on-1 mapping of kernel number to minor number */ + i = nr; +#else + /* The kernel number and minor numbers are independent */ + for (i = 0; i < VIDEO_NUM_DEVICES; i++) + if (video_device[i] == NULL) + break; + if (i == VIDEO_NUM_DEVICES) { + mutex_unlock(&videodev_lock); + printk(KERN_ERR "could not get a free minor\n"); + return -ENFILE; + } +#endif + vfd->minor = i + minor_offset; + vfd->num = nr; + set_bit(nr, video_nums[type]); + BUG_ON(video_device[vfd->minor]); + video_device[vfd->minor] = vfd; ret = get_index(vfd, index); vfd->index = ret; @@ -306,7 +339,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); if (vfd->parent) vfd->dev.parent = vfd->parent; - sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base); + sprintf(vfd->dev.bus_id, "%s%d", name_base, nr); ret = device_register(&vfd->dev); if (ret < 0) { printk(KERN_ERR "%s: device_register failed\n", __func__); @@ -324,6 +357,7 @@ del_cdev: fail_minor: mutex_lock(&videodev_lock); video_device[vfd->minor] = NULL; + clear_bit(vfd->num, video_nums[type]); mutex_unlock(&videodev_lock); vfd->minor = -1; return ret; diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index d129b56e1a9..a0a6b41c5e0 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -18,20 +18,11 @@ #define VIDEO_MAJOR 81 -/* Minor device allocation */ -#define MINOR_VFL_TYPE_GRABBER_MIN 0 -#define MINOR_VFL_TYPE_GRABBER_MAX 63 -#define MINOR_VFL_TYPE_RADIO_MIN 64 -#define MINOR_VFL_TYPE_RADIO_MAX 127 -#define MINOR_VFL_TYPE_VTX_MIN 192 -#define MINOR_VFL_TYPE_VTX_MAX 223 -#define MINOR_VFL_TYPE_VBI_MIN 224 -#define MINOR_VFL_TYPE_VBI_MAX 255 - #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 #define VFL_TYPE_VTX 3 +#define VFL_TYPE_MAX 4 struct v4l2_ioctl_callbacks; @@ -56,6 +47,7 @@ struct video_device char name[32]; int vfl_type; int minor; + u16 num; /* attribute to differentiate multiple indices on one physical device */ int index; -- GitLab From 19c309e383610453604092473287f77233f31e90 Mon Sep 17 00:00:00 2001 From: Tim Farrington Date: Sat, 11 Oct 2008 12:44:38 -0300 Subject: [PATCH 4220/5416] V4L/DVB (9135): cx88 Dvico FusionHDTV Pro Well, one thing you encouraged me to do was re-test some of my cards which contained the xc3028-zarlink combo. Which led me to test a Dvico FusionHDTV Pro. Almost a year ago, Chris Pascoe did a patch for this which can be found at his ~pascoe/xc-test at Linuxtv. This worked very well, however that was using his version of firmware. Alas, someone attempted to use this and patch v4l-dvb, and messed it up. So I've fixed it. I enclose the patch against today's tree (containing your latest tuner-xc2028.c patch). The card now works very well, well with DVB-T anyway. Signed-off-by: Tim Farrington Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 369ba69cd0b..a9e52decb6f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1581,9 +1581,9 @@ static const struct cx88_board cx88_boards[] = { }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { .name = "DViCO FusionHDTV DVB-T PRO", - .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = { { .type = CX88_VMUX_COMPOSITE1, @@ -2671,7 +2671,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) core->i2c_algo.udelay = 16; break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - ctl->scode_table = XC3028_FE_ZARLINK456; + ctl->demod = XC3028_FE_ZARLINK456; break; case CX88_BOARD_KWORLD_ATSC_120: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: -- GitLab From 45d011031d745d2c9a21c21d289428cb7f88a2d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 9 Oct 2008 05:51:22 -0300 Subject: [PATCH 4221/5416] V4L/DVB (9129): zoran: move zoran sources into a zoran subdirectory Prevent the zoran driver sources from cluttering the video directory. This changeset only moves the drivers and it does not fix any of the checkpatch warnings/errors to keep the changeset clean. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 74 +------------------ drivers/media/video/Makefile | 6 +- drivers/media/video/zoran/Kconfig | 73 ++++++++++++++++++ drivers/media/video/zoran/Makefile | 6 ++ drivers/media/video/{ => zoran}/videocodec.c | 0 drivers/media/video/{ => zoran}/videocodec.h | 0 drivers/media/video/{ => zoran}/zoran.h | 0 drivers/media/video/{ => zoran}/zoran_card.c | 0 drivers/media/video/{ => zoran}/zoran_card.h | 0 .../media/video/{ => zoran}/zoran_device.c | 0 .../media/video/{ => zoran}/zoran_device.h | 0 .../media/video/{ => zoran}/zoran_driver.c | 0 .../media/video/{ => zoran}/zoran_procfs.c | 0 .../media/video/{ => zoran}/zoran_procfs.h | 0 drivers/media/video/{ => zoran}/zr36016.c | 0 drivers/media/video/{ => zoran}/zr36016.h | 0 drivers/media/video/{ => zoran}/zr36050.c | 0 drivers/media/video/{ => zoran}/zr36050.h | 0 drivers/media/video/{ => zoran}/zr36057.h | 0 drivers/media/video/{ => zoran}/zr36060.c | 0 drivers/media/video/{ => zoran}/zr36060.h | 0 21 files changed, 81 insertions(+), 78 deletions(-) create mode 100644 drivers/media/video/zoran/Kconfig create mode 100644 drivers/media/video/zoran/Makefile rename drivers/media/video/{ => zoran}/videocodec.c (100%) rename drivers/media/video/{ => zoran}/videocodec.h (100%) rename drivers/media/video/{ => zoran}/zoran.h (100%) rename drivers/media/video/{ => zoran}/zoran_card.c (100%) rename drivers/media/video/{ => zoran}/zoran_card.h (100%) rename drivers/media/video/{ => zoran}/zoran_device.c (100%) rename drivers/media/video/{ => zoran}/zoran_device.h (100%) rename drivers/media/video/{ => zoran}/zoran_driver.c (100%) rename drivers/media/video/{ => zoran}/zoran_procfs.c (100%) rename drivers/media/video/{ => zoran}/zoran_procfs.h (100%) rename drivers/media/video/{ => zoran}/zr36016.c (100%) rename drivers/media/video/{ => zoran}/zr36016.h (100%) rename drivers/media/video/{ => zoran}/zr36050.c (100%) rename drivers/media/video/{ => zoran}/zr36050.h (100%) rename drivers/media/video/{ => zoran}/zr36057.h (100%) rename drivers/media/video/{ => zoran}/zr36060.c (100%) rename drivers/media/video/{ => zoran}/zr36060.h (100%) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2dce16f863b..47102c2c825 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -605,79 +605,7 @@ config VIDEO_STRADIS driver for PCI. There is a product page at . -config VIDEO_ZORAN - tristate "Zoran ZR36057/36067 Video For Linux" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS - help - Say Y for support for MJPEG capture cards based on the Zoran - 36057/36067 PCI controller chipset. This includes the Iomega - Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is - a driver homepage at . For - more information, check . - - To compile this driver as a module, choose M here: the - module will be called zr36067. - -config VIDEO_ZORAN_DC30 - tristate "Pinnacle/Miro DC30(+) support" - depends on VIDEO_ZORAN - select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO - help - Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback - card. This also supports really old DC10 cards based on the - zr36050 MJPEG codec and zr36016 VFE. - -config VIDEO_ZORAN_ZR36060 - tristate "Zoran ZR36060" - depends on VIDEO_ZORAN - help - Say Y to support Zoran boards based on 36060 chips. - This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 - and 33 R10 and AverMedia 6 boards. - -config VIDEO_ZORAN_BUZ - tristate "Iomega Buz support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO - help - Support for the Iomega Buz MJPEG capture/playback card. - -config VIDEO_ZORAN_DC10 - tristate "Pinnacle/Miro DC10(+) support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO - help - Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback - card. - -config VIDEO_ZORAN_LML33 - tristate "Linux Media Labs LML33 support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO - help - Support for the Linux Media Labs LML33 MJPEG capture/playback - card. - -config VIDEO_ZORAN_LML33R10 - tristate "Linux Media Labs LML33R10 support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO - help - support for the Linux Media Labs LML33R10 MJPEG capture/playback - card. - -config VIDEO_ZORAN_AVS6EYES - tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" - depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 - select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO - help - Support for the AverMedia 6 Eyes video surveillance card. +source "drivers/media/video/zoran/Kconfig" config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 28e32572530..16962f3aa15 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -2,8 +2,6 @@ # Makefile for the video capture/playback device drivers. # -zr36067-objs := zoran_procfs.o zoran_device.o \ - zoran_driver.o zoran_card.o tuner-objs := tuner-core.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -54,9 +52,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o -obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o -obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o -obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o +obj-$(CONFIG_VIDEO_ZORAN) += zoran/ obj-$(CONFIG_VIDEO_PMS) += pms.o obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig new file mode 100644 index 00000000000..4ea5fa71de8 --- /dev/null +++ b/drivers/media/video/zoran/Kconfig @@ -0,0 +1,73 @@ +config VIDEO_ZORAN + tristate "Zoran ZR36057/36067 Video For Linux" + depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS + help + Say Y for support for MJPEG capture cards based on the Zoran + 36057/36067 PCI controller chipset. This includes the Iomega + Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is + a driver homepage at . For + more information, check . + + To compile this driver as a module, choose M here: the + module will be called zr36067. + +config VIDEO_ZORAN_DC30 + tristate "Pinnacle/Miro DC30(+) support" + depends on VIDEO_ZORAN + select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO + help + Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback + card. This also supports really old DC10 cards based on the + zr36050 MJPEG codec and zr36016 VFE. + +config VIDEO_ZORAN_ZR36060 + tristate "Zoran ZR36060" + depends on VIDEO_ZORAN + help + Say Y to support Zoran boards based on 36060 chips. + This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 + and 33 R10 and AverMedia 6 boards. + +config VIDEO_ZORAN_BUZ + tristate "Iomega Buz support" + depends on VIDEO_ZORAN_ZR36060 + select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO + help + Support for the Iomega Buz MJPEG capture/playback card. + +config VIDEO_ZORAN_DC10 + tristate "Pinnacle/Miro DC10(+) support" + depends on VIDEO_ZORAN_ZR36060 + select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO + help + Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback + card. + +config VIDEO_ZORAN_LML33 + tristate "Linux Media Labs LML33 support" + depends on VIDEO_ZORAN_ZR36060 + select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + help + Support for the Linux Media Labs LML33 MJPEG capture/playback + card. + +config VIDEO_ZORAN_LML33R10 + tristate "Linux Media Labs LML33R10 support" + depends on VIDEO_ZORAN_ZR36060 + select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO + help + support for the Linux Media Labs LML33R10 MJPEG capture/playback + card. + +config VIDEO_ZORAN_AVS6EYES + tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" + depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 + select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO + help + Support for the AverMedia 6 Eyes video surveillance card. diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile new file mode 100644 index 00000000000..44cc13352c8 --- /dev/null +++ b/drivers/media/video/zoran/Makefile @@ -0,0 +1,6 @@ +zr36067-objs := zoran_procfs.o zoran_device.o \ + zoran_driver.o zoran_card.o + +obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o +obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o +obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/zoran/videocodec.c similarity index 100% rename from drivers/media/video/videocodec.c rename to drivers/media/video/zoran/videocodec.c diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/zoran/videocodec.h similarity index 100% rename from drivers/media/video/videocodec.h rename to drivers/media/video/zoran/videocodec.h diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran/zoran.h similarity index 100% rename from drivers/media/video/zoran.h rename to drivers/media/video/zoran/zoran.h diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran/zoran_card.c similarity index 100% rename from drivers/media/video/zoran_card.c rename to drivers/media/video/zoran/zoran_card.c diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran/zoran_card.h similarity index 100% rename from drivers/media/video/zoran_card.h rename to drivers/media/video/zoran/zoran_card.h diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran/zoran_device.c similarity index 100% rename from drivers/media/video/zoran_device.c rename to drivers/media/video/zoran/zoran_device.c diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran/zoran_device.h similarity index 100% rename from drivers/media/video/zoran_device.h rename to drivers/media/video/zoran/zoran_device.h diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c similarity index 100% rename from drivers/media/video/zoran_driver.c rename to drivers/media/video/zoran/zoran_driver.c diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c similarity index 100% rename from drivers/media/video/zoran_procfs.c rename to drivers/media/video/zoran/zoran_procfs.c diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h similarity index 100% rename from drivers/media/video/zoran_procfs.h rename to drivers/media/video/zoran/zoran_procfs.h diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zoran/zr36016.c similarity index 100% rename from drivers/media/video/zr36016.c rename to drivers/media/video/zoran/zr36016.c diff --git a/drivers/media/video/zr36016.h b/drivers/media/video/zoran/zr36016.h similarity index 100% rename from drivers/media/video/zr36016.h rename to drivers/media/video/zoran/zr36016.h diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zoran/zr36050.c similarity index 100% rename from drivers/media/video/zr36050.c rename to drivers/media/video/zoran/zr36050.c diff --git a/drivers/media/video/zr36050.h b/drivers/media/video/zoran/zr36050.h similarity index 100% rename from drivers/media/video/zr36050.h rename to drivers/media/video/zoran/zr36050.h diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zoran/zr36057.h similarity index 100% rename from drivers/media/video/zr36057.h rename to drivers/media/video/zoran/zr36057.h diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zoran/zr36060.c similarity index 100% rename from drivers/media/video/zr36060.c rename to drivers/media/video/zoran/zr36060.c diff --git a/drivers/media/video/zr36060.h b/drivers/media/video/zoran/zr36060.h similarity index 100% rename from drivers/media/video/zr36060.h rename to drivers/media/video/zoran/zr36060.h -- GitLab From 46eaa6702016e3ac9a188172a2c309d6ca1be1cd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:06:29 +0200 Subject: [PATCH 4222/5416] x86: memory corruption check - cleanup Move the prototypes from the generic kernel.h header to the more appropriate include/asm-x86/bios_ebda.h header file. Also, remove the check from the power management code - this is a pure x86 matter for now. Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 1 + arch/x86/mm/init_64.c | 1 + drivers/base/power/main.c | 1 - include/asm-x86/bios_ebda.h | 17 +++++++++++++++++ include/linux/kernel.h | 17 ----------------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 7e05462ffb1..bbe044dbe01 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d84d3e91d34..3e10054c573 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bf6d3554e50..273a944d404 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -254,7 +254,6 @@ static char *pm_verb(int event) static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info) { - check_for_bios_corruption(); dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ? ", may wakeup" : ""); diff --git a/include/asm-x86/bios_ebda.h b/include/asm-x86/bios_ebda.h index ec42ed87459..79b4b88505d 100644 --- a/include/asm-x86/bios_ebda.h +++ b/include/asm-x86/bios_ebda.h @@ -16,4 +16,21 @@ static inline unsigned int get_bios_ebda(void) void reserve_ebda_region(void); +#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION +/* + * This is obviously not a great place for this, but we want to be + * able to scatter it around anywhere in the kernel. + */ +void check_for_bios_corruption(void); +void start_periodic_check_for_corruption(void); +#else +static inline void check_for_bios_corruption(void) +{ +} + +static inline void start_periodic_check_for_corruption(void) +{ +} +#endif + #endif /* ASM_X86__BIOS_EBDA_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 50873b21178..2651f805ba6 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -240,23 +240,6 @@ extern const char *print_tainted(void); extern void add_taint(unsigned); extern int root_mountflags; -#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION -/* - * This is obviously not a great place for this, but we want to be - * able to scatter it around anywhere in the kernel. - */ -void check_for_bios_corruption(void); -void start_periodic_check_for_corruption(void); -#else -static inline void check_for_bios_corruption(void) -{ -} - -static inline void start_periodic_check_for_corruption(void) -{ -} -#endif - /* Values used for system_state */ extern enum system_states { SYSTEM_BOOTING, -- GitLab From 9f482807a6bd7e2aa1ed0d8cfc48463ec4ca3568 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 18 Aug 2008 12:59:32 +0200 Subject: [PATCH 4223/5416] x86, fpu: check __clear_user() return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix warning: arch/x86/kernel/xsave.c: In function ‘save_i387_xstate’: arch/x86/kernel/xsave.c:98: warning: ignoring return value of ‘__clear_user’, declared with attribute warn_unused_result check the return value and act on it. We should not be ignoring faults at this point. Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 2f98323716d..9abac8a9d82 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -95,7 +95,9 @@ int save_i387_xstate(void __user *buf) * Start with clearing the user buffer. This will present a * clean context for the bytes not touched by the fxsave/xsave. */ - __clear_user(buf, sig_xstate_size); + err = __clear_user(buf, sig_xstate_size); + if (err) + return err; if (task_thread_info(tsk)->status & TS_XSAVE) err = xsave_user(buf); -- GitLab From 45e96f26f257bd873017c6244a6cafd27f6f5439 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 27 Aug 2008 10:37:14 +0200 Subject: [PATCH 4224/5416] warnings: fix arch/x86/kernel/early_printk.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix warning: arch/x86/kernel/early_printk.c:993: warning: ‘enable_debug_console’ defined but not used Eliminate dead code. Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 02fc5b40c14..34ad997d383 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -989,22 +989,4 @@ static int __init setup_early_printk(char *buf) return 0; } -static void __init enable_debug_console(char *buf) -{ -#ifdef DBGP_DEBUG - struct console *old_early_console = NULL; - - if (early_console_initialized && early_console) { - old_early_console = early_console; - unregister_console(early_console); - early_console_initialized = 0; - } - - setup_early_printk(buf); - - if (early_console == old_early_console && old_early_console) - register_console(old_early_console); -#endif -} - early_param("earlyprintk", setup_early_printk); -- GitLab From d562353a4533c4671af683499191707c9a77c406 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:22:22 +0200 Subject: [PATCH 4225/5416] warnings: fix arch/x86/kernel/io_apic_64.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: arch/x86/kernel/io_apic_64.c: In function ‘print_local_APIC’: arch/x86/kernel/io_apic_64.c:1284: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ arch/x86/kernel/io_apic_64.c:1285: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ We want to print the two halves of 'icr' at 32 bit width. Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index a1bec2969c6..02063ae042f 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1281,8 +1281,8 @@ __apicdebuginit(void) print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC ESR: %08x\n", v); icr = apic_icr_read(); - printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); + printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr); + printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32)); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); -- GitLab From 8a66712ba0969aea5580b9e312badfc2490fc614 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:24:53 +0200 Subject: [PATCH 4226/5416] x86, amd-iommu: propagate PCI device enabling error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit propagate an error in enabling the PCI device. Also eliminates this warning: arch/x86/kernel/amd_iommu_init.c: In function ‘init_iommu_one’: arch/x86/kernel/amd_iommu_init.c:726: warning: ignoring return value of ‘pci_enable_device’, declared with attribute warn_unused_result Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu_init.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 148fcfe22f1..4cd8083c58b 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -723,9 +723,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) init_iommu_from_acpi(iommu, h); init_iommu_devices(iommu); - pci_enable_device(iommu->dev); - - return 0; + return pci_enable_device(iommu->dev); } /* -- GitLab From 14835a3325c1f84c3ae6eaf81102a3917e84809e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sun, 12 Oct 2008 13:34:11 +0000 Subject: [PATCH 4227/5416] [CIFS] cifs: remove pointless lock and unlock of GlobalMid_Lock in header_assemble We lock GlobalMid_Lock in header_assemble and then immediately unlock it again without doing anything. Not sure what this was intended to do, but remove it. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/misc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 654d972a88f..88786ba02d2 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -311,8 +311,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; buffer->Pid = cpu_to_le16((__u16)current->tgid); buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); - spin_lock(&GlobalMid_Lock); - spin_unlock(&GlobalMid_Lock); if (treeCon) { buffer->Tid = treeCon->tid; if (treeCon->ses) { -- GitLab From b7b3a42533e1e41297fe517533375f9f8f7b92d0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:36:24 +0200 Subject: [PATCH 4228/5416] x86: extend processor type select help text extend the help text of the CONFIG_CPU_SUP_* config options to express what it does and what effects it has. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 63 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index f8843c3ae77..a2ea1488b37 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -430,48 +430,97 @@ config CPU_SUP_INTEL default y bool "Support Intel processors" if PROCESSOR_SELECT help - This enables extended support for Intel processors + This enables detection, tunings and quirks for Intel processors + + You need this enabled if you want your kernel to run on an + Intel CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on an Intel + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CYRIX_32 default y bool "Support Cyrix processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Cyrix processors + This enables detection, tunings and quirks for Cyrix processors + + You need this enabled if you want your kernel to run on a + Cyrix CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Cyrix + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_AMD default y bool "Support AMD processors" if PROCESSOR_SELECT help - This enables extended support for AMD processors + This enables detection, tunings and quirks for AMD processors + + You need this enabled if you want your kernel to run on an + AMD CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on an AMD + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CENTAUR_32 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Centaur processors + This enables detection, tunings and quirks for Centaur processors + + You need this enabled if you want your kernel to run on a + Centaur CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Centaur + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_CENTAUR_64 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on 64BIT help - This enables extended support for Centaur processors + This enables detection, tunings and quirks for Centaur processors + + You need this enabled if you want your kernel to run on a + Centaur CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Centaur + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_TRANSMETA_32 default y bool "Support Transmeta processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for Transmeta processors + This enables detection, tunings and quirks for Transmeta processors + + You need this enabled if you want your kernel to run on a + Transmeta CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a Transmeta + CPU might render the kernel unbootable. + + If unsure, say N. config CPU_SUP_UMC_32 default y bool "Support UMC processors" if PROCESSOR_SELECT depends on !64BIT help - This enables extended support for UMC processors + This enables detection, tunings and quirks for UMC processors + + You need this enabled if you want your kernel to run on a + UMC CPU. Disabling this option on other types of CPUs + makes the kernel a tiny bit smaller. Disabling it on a UMC + CPU might render the kernel unbootable. + + If unsure, say N. config X86_DS bool "Debug Store support" -- GitLab From 1db5fff9aeab18566eb380e354629fdbbe7792f0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 15:40:45 +0200 Subject: [PATCH 4229/5416] x86: make processor type select depend on CONFIG_EMBEDDED deselecting one of the CPU type CONFIG_CPU_SUP_* config options can render a kernel unbootable. Make sure this option is only available if CONFIG_EMBEDDED is enabled. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index a2ea1488b37..c5f10136052 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -420,7 +420,6 @@ config X86_DEBUGCTLMSR depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) menuconfig PROCESSOR_SELECT - default y bool "Supported processor vendors" if EMBEDDED help This lets you choose what x86 vendor support code your kernel -- GitLab From caf18f19eefc0cf5539b4e82b8aa8df6a78391a6 Mon Sep 17 00:00:00 2001 From: Julien May Date: Wed, 24 Sep 2008 10:30:47 +0200 Subject: [PATCH 4230/5416] avr32: Allow selecting multiple pins at once at32_select_periph() now takes an u32 bitmask rather than a single pin. This allows to set multiple pins at once. Signed-off-by: Alex Raimondi Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 2 +- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- arch/avr32/boards/atstk1000/atstk1003.c | 2 +- arch/avr32/boards/atstk1000/atstk1004.c | 2 +- arch/avr32/mach-at32ap/at32ap700x.c | 307 ++++++++++-------- arch/avr32/mach-at32ap/include/mach/portmux.h | 4 +- arch/avr32/mach-at32ap/pio.c | 41 ++- 7 files changed, 212 insertions(+), 148 deletions(-) diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 65db3d26696..6c54580a66d 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -194,7 +194,7 @@ static int __init atngw100_init(void) * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), * but it's not available off-board. */ - at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP); + at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); at32_select_gpio(i2c_gpio_data.sda_pin, AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); at32_select_gpio(i2c_gpio_data.scl_pin, diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 32aceec0ae7..2bcea80b274 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index acc61235b89..2bc300c3471 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -94,7 +94,7 @@ static void __init atstk1003_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 949c13ec51e..5d485597171 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -99,7 +99,7 @@ static void __init atstk1004_setup_extdac(void) goto err_set_clk; } - at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); at73c213_data.dac_clk = gclk; err_set_clk: diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 5d00bb8d3cc..813b6844cdf 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -82,8 +82,9 @@ static struct platform_device _name##_id##_device = { \ .num_resources = ARRAY_SIZE(_name##_id##_resource), \ } -#define select_peripheral(pin, periph, flags) \ - at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags) +#define select_peripheral(port, pin_mask, periph, flags) \ + at32_select_periph(GPIO_##port##_BASE, pin_mask, \ + GPIO_##periph, flags) #define DEV_CLK(_name, devname, bus, _index) \ static struct clk devname##_##_name = { \ @@ -871,6 +872,7 @@ static struct clk atmel_psif1_pclk = { struct platform_device *__init at32_add_device_psif(unsigned int id) { struct platform_device *pdev; + u32 pin_mask; if (!(id == 0 || id == 1)) return NULL; @@ -881,20 +883,22 @@ struct platform_device *__init at32_add_device_psif(unsigned int id) switch (id) { case 0: + pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */ + if (platform_device_add_resources(pdev, atmel_psif0_resource, ARRAY_SIZE(atmel_psif0_resource))) goto err_add_resources; atmel_psif0_pclk.dev = &pdev->dev; - select_peripheral(PA(8), PERIPH_A, 0); /* CLOCK */ - select_peripheral(PA(9), PERIPH_A, 0); /* DATA */ + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); break; case 1: + pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */ + if (platform_device_add_resources(pdev, atmel_psif1_resource, ARRAY_SIZE(atmel_psif1_resource))) goto err_add_resources; atmel_psif1_pclk.dev = &pdev->dev; - select_peripheral(PB(11), PERIPH_A, 0); /* CLOCK */ - select_peripheral(PB(12), PERIPH_A, 0); /* DATA */ + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); break; default: return NULL; @@ -958,26 +962,30 @@ DEV_CLK(usart, atmel_usart3, pba, 6); static inline void configure_usart0_pins(void) { - select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ - select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ + + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); } static inline void configure_usart1_pins(void) { - select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ - select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ + u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ + + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); } static inline void configure_usart2_pins(void) { - select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); } static inline void configure_usart3_pins(void) { - select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ + u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); } static struct platform_device *__initdata at32_usarts[4]; @@ -1057,59 +1065,69 @@ struct platform_device *__init at32_add_device_eth(unsigned int id, struct eth_platform_data *data) { struct platform_device *pdev; + u32 pin_mask; switch (id) { case 0: pdev = &macb0_device; - select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ - select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ - select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ - select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ - select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ - select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ - select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ - select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ - select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ - select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ + pin_mask = (1 << 3); /* TXD0 */ + pin_mask |= (1 << 4); /* TXD1 */ + pin_mask |= (1 << 7); /* TXEN */ + pin_mask |= (1 << 8); /* TXCK */ + pin_mask |= (1 << 9); /* RXD0 */ + pin_mask |= (1 << 10); /* RXD1 */ + pin_mask |= (1 << 13); /* RXER */ + pin_mask |= (1 << 15); /* RXDV */ + pin_mask |= (1 << 16); /* MDC */ + pin_mask |= (1 << 17); /* MDIO */ if (!data->is_rmii) { - select_peripheral(PC(0), PERIPH_A, 0); /* COL */ - select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ - select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ - select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ - select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ - select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ - select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ - select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ - select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ + pin_mask |= (1 << 0); /* COL */ + pin_mask |= (1 << 1); /* CRS */ + pin_mask |= (1 << 2); /* TXER */ + pin_mask |= (1 << 5); /* TXD2 */ + pin_mask |= (1 << 6); /* TXD3 */ + pin_mask |= (1 << 11); /* RXD2 */ + pin_mask |= (1 << 12); /* RXD3 */ + pin_mask |= (1 << 14); /* RXCK */ + pin_mask |= (1 << 18); /* SPD */ } + + select_peripheral(PIOC, pin_mask, PERIPH_A, 0); + break; case 1: pdev = &macb1_device; - select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */ - select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */ - select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */ - select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */ - select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */ - select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */ - select_peripheral(PD(5), PERIPH_B, 0); /* RXER */ - select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */ - select_peripheral(PD(3), PERIPH_B, 0); /* MDC */ - select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */ + pin_mask = (1 << 13); /* TXD0 */ + pin_mask |= (1 << 14); /* TXD1 */ + pin_mask |= (1 << 11); /* TXEN */ + pin_mask |= (1 << 12); /* TXCK */ + pin_mask |= (1 << 10); /* RXD0 */ + pin_mask |= (1 << 6); /* RXD1 */ + pin_mask |= (1 << 5); /* RXER */ + pin_mask |= (1 << 4); /* RXDV */ + pin_mask |= (1 << 3); /* MDC */ + pin_mask |= (1 << 2); /* MDIO */ + + if (!data->is_rmii) + pin_mask |= (1 << 15); /* SPD */ + + select_peripheral(PIOD, pin_mask, PERIPH_B, 0); if (!data->is_rmii) { - select_peripheral(PC(19), PERIPH_B, 0); /* COL */ - select_peripheral(PC(23), PERIPH_B, 0); /* CRS */ - select_peripheral(PC(26), PERIPH_B, 0); /* TXER */ - select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */ - select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */ - select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */ - select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */ - select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */ - select_peripheral(PD(15), PERIPH_B, 0); /* SPD */ + pin_mask = (1 << 19); /* COL */ + pin_mask |= (1 << 23); /* CRS */ + pin_mask |= (1 << 26); /* TXER */ + pin_mask |= (1 << 27); /* TXD2 */ + pin_mask |= (1 << 28); /* TXD3 */ + pin_mask |= (1 << 29); /* RXD2 */ + pin_mask |= (1 << 30); /* RXD3 */ + pin_mask |= (1 << 24); /* RXCK */ + + select_peripheral(PIOC, pin_mask, PERIPH_B, 0); } break; @@ -1177,23 +1195,28 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) { GPIO_PIN_PB(2), GPIO_PIN_PB(3), GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; struct platform_device *pdev; + u32 pin_mask; switch (id) { case 0: pdev = &atmel_spi0_device; + pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */ + /* pullup MISO so a level is always defined */ - select_peripheral(PA(0), PERIPH_A, AT32_GPIOF_PULLUP); - select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ - select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ + select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP); + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + at32_spi_setup_slaves(0, b, n, spi0_pins); break; case 1: pdev = &atmel_spi1_device; + pin_mask = (1 << 1) | (1 << 5); /* MOSI */ + /* pullup MISO so a level is always defined */ - select_peripheral(PB(0), PERIPH_B, AT32_GPIOF_PULLUP); - select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ - select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ + select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP); + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); + at32_spi_setup_slaves(1, b, n, spi1_pins); break; @@ -1226,6 +1249,7 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, unsigned int n) { struct platform_device *pdev; + u32 pin_mask; if (id != 0) return NULL; @@ -1238,8 +1262,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, ARRAY_SIZE(atmel_twi0_resource))) goto err_add_resources; - select_peripheral(PA(6), PERIPH_A, 0); /* SDA */ - select_peripheral(PA(7), PERIPH_A, 0); /* SDL */ + pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */ + + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); atmel_twi0_pclk.dev = &pdev->dev; @@ -1274,6 +1299,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; struct dw_dma_slave *dws; + u32 pioa_mask; + u32 piob_mask; if (id != 0 || !data) return NULL; @@ -1311,17 +1338,17 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) goto fail; /* CLK line is common to both slots */ - select_peripheral(PA(10), PERIPH_A, 0); + pioa_mask = 1 << 10; switch (data->slot[0].bus_width) { case 4: - select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ - select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ + pioa_mask |= 1 << 13; /* DATA1 */ + pioa_mask |= 1 << 14; /* DATA2 */ + pioa_mask |= 1 << 15; /* DATA3 */ /* fall through */ case 1: - select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ - select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ + pioa_mask |= 1 << 11; /* CMD */ + pioa_mask |= 1 << 12; /* DATA0 */ if (gpio_is_valid(data->slot[0].detect_pin)) at32_select_gpio(data->slot[0].detect_pin, 0); @@ -1335,15 +1362,19 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) goto fail; } + select_peripheral(PIOA, pioa_mask, PERIPH_A, 0); + piob_mask = 0; + switch (data->slot[1].bus_width) { case 4: - select_peripheral(PB(8), PERIPH_B, 0); /* DATA1 */ - select_peripheral(PB(9), PERIPH_B, 0); /* DATA2 */ - select_peripheral(PB(10), PERIPH_B, 0); /* DATA3 */ + piob_mask |= 1 << 8; /* DATA1 */ + piob_mask |= 1 << 9; /* DATA2 */ + piob_mask |= 1 << 10; /* DATA3 */ /* fall through */ case 1: - select_peripheral(PB(6), PERIPH_B, 0); /* CMD */ - select_peripheral(PB(7), PERIPH_B, 0); /* DATA0 */ + piob_mask |= 1 << 6; /* CMD */ + piob_mask |= 1 << 7; /* DATA0 */ + select_peripheral(PIOB, piob_mask, PERIPH_B, 0); if (gpio_is_valid(data->slot[1].detect_pin)) at32_select_gpio(data->slot[1].detect_pin, 0); @@ -1412,7 +1443,7 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, struct fb_monspecs *monspecs; struct fb_videomode *modedb; unsigned int modedb_size; - int i; + u32 portc_mask, portd_mask, porte_mask; /* * Do a deep copy of the fb data, monspecs and modedb. Make @@ -1439,25 +1470,16 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL; /* LCDC on port C */ - for (i = 19; i < 32; i++) { - if (pin_mask & (1ULL << i)) - at32_select_periph(GPIO_PIOC_BASE + i, - GPIO_PERIPH_A, 0); - } + portc_mask = (pin_mask & 0xfff80000) >> 19; + select_peripheral(PIOC, portc_mask, PERIPH_A, 0); /* LCDC on port D */ - for (i = 0; i < 18; i++) { - if (pin_mask & (1ULL << i)) - at32_select_periph(GPIO_PIOD_BASE + i, - GPIO_PERIPH_A, 0); - } + portd_mask = pin_mask & 0x0003ffff; + select_peripheral(PIOD, portd_mask, PERIPH_A, 0); /* LCDC on port E */ - for (i = 0; i < 19; i++) { - if (pin_mask & (1ULL << (i + 32))) - at32_select_periph(GPIO_PIOE_BASE + i, - GPIO_PERIPH_B, 0); - } + porte_mask = (pin_mask >> 32) & 0x0007ffff; + select_peripheral(PIOE, porte_mask, PERIPH_B, 0); clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); @@ -1506,6 +1528,7 @@ static struct clk atmel_pwm0_mck = { struct platform_device *__init at32_add_device_pwm(u32 mask) { struct platform_device *pdev; + u32 pin_mask; if (!mask) return NULL; @@ -1521,14 +1544,21 @@ struct platform_device *__init at32_add_device_pwm(u32 mask) if (platform_device_add_data(pdev, &mask, sizeof(mask))) goto out_free_pdev; + pin_mask = 0; if (mask & (1 << 0)) - select_peripheral(PA(28), PERIPH_A, 0); + pin_mask |= (1 << 28); if (mask & (1 << 1)) - select_peripheral(PA(29), PERIPH_A, 0); + pin_mask |= (1 << 29); + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + + pin_mask = 0; if (mask & (1 << 2)) - select_peripheral(PA(21), PERIPH_B, 0); + pin_mask |= (1 << 21); if (mask & (1 << 3)) - select_peripheral(PA(22), PERIPH_B, 0); + pin_mask |= (1 << 22); + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); atmel_pwm0_mck.dev = &pdev->dev; @@ -1569,52 +1599,65 @@ struct platform_device *__init at32_add_device_ssc(unsigned int id, unsigned int flags) { struct platform_device *pdev; + u32 pin_mask = 0; switch (id) { case 0: pdev = &ssc0_device; if (flags & ATMEL_SSC_RF) - select_peripheral(PA(21), PERIPH_A, 0); /* RF */ + pin_mask |= (1 << 21); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PA(22), PERIPH_A, 0); /* RK */ + pin_mask |= (1 << 22); /* RK */ if (flags & ATMEL_SSC_TK) - select_peripheral(PA(23), PERIPH_A, 0); /* TK */ + pin_mask |= (1 << 23); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PA(24), PERIPH_A, 0); /* TF */ + pin_mask |= (1 << 24); /* TF */ if (flags & ATMEL_SSC_TD) - select_peripheral(PA(25), PERIPH_A, 0); /* TD */ + pin_mask |= (1 << 25); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PA(26), PERIPH_A, 0); /* RD */ + pin_mask |= (1 << 26); /* RD */ + + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_A, 0); + break; case 1: pdev = &ssc1_device; if (flags & ATMEL_SSC_RF) - select_peripheral(PA(0), PERIPH_B, 0); /* RF */ + pin_mask |= (1 << 0); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PA(1), PERIPH_B, 0); /* RK */ + pin_mask |= (1 << 1); /* RK */ if (flags & ATMEL_SSC_TK) - select_peripheral(PA(2), PERIPH_B, 0); /* TK */ + pin_mask |= (1 << 2); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PA(3), PERIPH_B, 0); /* TF */ + pin_mask |= (1 << 3); /* TF */ if (flags & ATMEL_SSC_TD) - select_peripheral(PA(4), PERIPH_B, 0); /* TD */ + pin_mask |= (1 << 4); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PA(5), PERIPH_B, 0); /* RD */ + pin_mask |= (1 << 5); /* RD */ + + if (pin_mask > 0) + select_peripheral(PIOA, pin_mask, PERIPH_B, 0); + break; case 2: pdev = &ssc2_device; if (flags & ATMEL_SSC_TD) - select_peripheral(PB(13), PERIPH_A, 0); /* TD */ + pin_mask |= (1 << 13); /* TD */ if (flags & ATMEL_SSC_RD) - select_peripheral(PB(14), PERIPH_A, 0); /* RD */ + pin_mask |= (1 << 14); /* RD */ if (flags & ATMEL_SSC_TK) - select_peripheral(PB(15), PERIPH_A, 0); /* TK */ + pin_mask |= (1 << 15); /* TK */ if (flags & ATMEL_SSC_TF) - select_peripheral(PB(16), PERIPH_A, 0); /* TF */ + pin_mask |= (1 << 16); /* TF */ if (flags & ATMEL_SSC_RF) - select_peripheral(PB(17), PERIPH_A, 0); /* RF */ + pin_mask |= (1 << 17); /* RF */ if (flags & ATMEL_SSC_RK) - select_peripheral(PB(18), PERIPH_A, 0); /* RK */ + pin_mask |= (1 << 18); /* RK */ + + if (pin_mask > 0) + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); + break; default: return NULL; @@ -1752,14 +1795,15 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, unsigned int cs, unsigned int extint) { static unsigned int extint_pin_map[4] __initdata = { - GPIO_PIN_PB(25), - GPIO_PIN_PB(26), - GPIO_PIN_PB(27), - GPIO_PIN_PB(28), + (1 << 25), + (1 << 26), + (1 << 27), + (1 << 28), }; static bool common_pins_initialized __initdata = false; unsigned int extint_pin; int ret; + u32 pin_mask; if (extint >= ARRAY_SIZE(extint_pin_map)) return -EINVAL; @@ -1773,7 +1817,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, if (ret) return ret; - select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */ + /* NCS4 -> OE_N */ + select_peripheral(PIOE, (1 << 21), PERIPH_A, 0); hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE); break; case 5: @@ -1783,7 +1828,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, if (ret) return ret; - select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */ + /* NCS5 -> OE_N */ + select_peripheral(PIOE, (1 << 22), PERIPH_A, 0); hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE); break; default: @@ -1791,14 +1837,17 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, } if (!common_pins_initialized) { - select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */ - select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */ - select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */ - select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */ + pin_mask = (1 << 19); /* CFCE1 -> CS0_N */ + pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */ + pin_mask |= (1 << 23); /* CFRNW -> DIR */ + pin_mask |= (1 << 24); /* NWAIT <- IORDY */ + + select_peripheral(PIOE, pin_mask, PERIPH_A, 0); + common_pins_initialized = true; } - at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); + select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH); pdev->resource[1].start = EIM_IRQ_BASE + extint; pdev->resource[1].end = pdev->resource[1].start; @@ -1937,6 +1986,7 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) { struct platform_device *pdev; struct ac97c_platform_data _data; + u32 pin_mask; if (id != 0) return NULL; @@ -1963,10 +2013,10 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) sizeof(struct ac97c_platform_data))) goto fail; - select_peripheral(PB(20), PERIPH_B, 0); /* SDO */ - select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */ - select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */ - select_peripheral(PB(23), PERIPH_B, 0); /* SDI */ + pin_mask = (1 << 20) | (1 << 21); /* SDO & SYNC */ + pin_mask |= (1 << 22) | (1 << 23); /* SCLK & SDI */ + + select_peripheral(PIOB, pin_mask, PERIPH_B, 0); /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ if (data->reset_pin != GPIO_PIN_NONE) @@ -2008,6 +2058,7 @@ static struct clk abdac0_sample_clk = { struct platform_device *__init at32_add_device_abdac(unsigned int id) { struct platform_device *pdev; + u32 pin_mask; if (id != 0) return NULL; @@ -2020,10 +2071,10 @@ struct platform_device *__init at32_add_device_abdac(unsigned int id) ARRAY_SIZE(abdac0_resource))) goto err_add_resources; - select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */ - select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */ - select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */ + pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */ + pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */ + + select_peripheral(PIOB, pin_mask, PERIPH_A, 0); abdac0_pclk.dev = &pdev->dev; abdac0_sample_clk.dev = &pdev->dev; diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h index 4bbf99ec2c4..21c79373b53 100644 --- a/arch/avr32/mach-at32ap/include/mach/portmux.h +++ b/arch/avr32/mach-at32ap/include/mach/portmux.h @@ -21,8 +21,8 @@ #define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ #define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ -void at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags); +void at32_select_periph(unsigned int port, unsigned int pin, + unsigned int periph, unsigned long flags); void at32_select_gpio(unsigned int pin, unsigned long flags); void at32_deselect_pin(unsigned int pin); void at32_reserve_pin(unsigned int pin); diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index ef2561e1539..ed81a8bcb22 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio) } /* Pin multiplexing API */ +static DEFINE_SPINLOCK(pio_lock); -void __init at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags) +void __init at32_select_periph(unsigned int port, u32 pin_mask, + unsigned int periph, unsigned long flags) { struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - pio = gpio_to_pio(pin); + /* assign and verify pio */ + pio = gpio_to_pio(port); if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); + printk(KERN_WARNING "pio: invalid port %u\n", port); goto fail; } - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) - || gpiochip_is_requested(&pio->chip, pin_index))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); + /* Test if any of the requested pins is already muxed */ + spin_lock(&pio_lock); + if (unlikely(pio->pinmux_mask & pin_mask)) { + printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", + pio->name, pin_mask, pio->pinmux_mask & pin_mask); + spin_unlock(&pio_lock); goto fail; } - pio_writel(pio, PUER, mask); + pio->pinmux_mask |= pin_mask; + + /* enable pull ups */ + pio_writel(pio, PUER, pin_mask); + + /* select either peripheral A or B */ if (periph) - pio_writel(pio, BSR, mask); + pio_writel(pio, BSR, pin_mask); else - pio_writel(pio, ASR, mask); + pio_writel(pio, ASR, pin_mask); + + /* enable peripheral control */ + pio_writel(pio, PDR, pin_mask); - pio_writel(pio, PDR, mask); + /* Disable pull ups if not requested. */ if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); + pio_writel(pio, PUDR, pin_mask); + + spin_unlock(&pio_lock); return; -- GitLab From 6eb3ebe04da4c8f31d776217b0b76ca3d00f20b1 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Sun, 12 Oct 2008 16:02:46 +0200 Subject: [PATCH 4231/5416] avr32: Fix build failures in board code Fix a few instances of board code breakage introduced by the atmel-mci platform interface changes. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- arch/avr32/boards/atstk1000/atstk1003.c | 1 + arch/avr32/boards/atstk1000/atstk1004.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 2bcea80b274..29e5b51a7fd 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -330,7 +330,7 @@ static int __init atstk1002_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0, &mci0_pdata); + at32_add_device_mci(0, &mci0_data); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM set_hw_addr(at32_add_device_eth(1, ð_data[1])); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index 2bc300c3471..be089d7f37e 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 5d485597171..248ef237c16 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -21,6 +21,7 @@ #include